# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet v2.5.73 -> 1.1357 # arch/sparc/Kconfig 1.17 -> 1.18 # drivers/pci/hotplug/cpqphp_core.c 1.19 -> 1.20 # include/asm-ppc64/smp.h 1.8 -> 1.10 # arch/m68knommu/platform/68360/ints.c 1.3 -> 1.4 # arch/mips/dec/prom/memory.c 1.3 -> 1.4 # include/asm-mips/dma.h 1.1 -> 1.2 # fs/nfsd/nfs3xdr.c 1.34 -> 1.35 # include/asm-mips/asm.h 1.2 -> 1.3 # net/ipv4/netfilter/ip_conntrack_core.c 1.30 -> 1.33 # drivers/mtd/devices/doc2001plus.c 1.1 -> 1.2 # arch/mips64/math-emu/dp_div.c 1.2 -> (deleted) # net/rose/sysctl_net_rose.c 1.3 -> 1.4 # include/asm-mips/string.h 1.2 -> 1.3 # arch/mips/math-emu/sp_frexp.c 1.1 -> 1.2 # drivers/scsi/megaraid.c 1.49 -> 1.50 # arch/ppc64/kernel/pci.h 1.8 -> 1.9 # arch/mips64/mm/Makefile 1.6 -> 1.7 # include/asm-mips/pci_channel.h 1.1 -> 1.2 # arch/mips64/kernel/r4k_fpu.S 1.2 -> 1.3 # include/asm-mips64/sn/intr.h 1.1 -> 1.2 # include/asm-alpha/pci.h 1.15 -> 1.16 # arch/i386/kernel/cpu/cpufreq/speedstep-ich.c 1.18.1.2 -> 1.21 # drivers/mtd/devices/doc2000.c 1.6 -> 1.7 # fs/xfs/xfs_mount.h 1.15 -> 1.16 # arch/mips64/lib/ide-no.c 1.3 -> 1.4 # arch/mips/philips/nino/prom.c 1.1 -> (deleted) # include/asm-mips64/xtalk/xtalk.h 1.2 -> 1.3 # arch/mips/baget/time.c 1.3 -> 1.4 # include/asm-mips/atomic.h 1.4 -> 1.5 # arch/mips/lib/kbd-std.c 1.3 -> (deleted) # arch/mips/math-emu/sp_cmp.c 1.1 -> 1.2 # include/asm-ppc/hardirq.h 1.20 -> 1.21 # drivers/scsi/sym53c8xx_2/sym_hipd.c 1.7 -> 1.8 # include/asm-mips64/topology.h 1.3 -> 1.4 # arch/mips/mips-boards/malta/Makefile 1.4 -> 1.5 # arch/mips/mm/sb1.c 1.3 -> (deleted) # arch/mips/philips/nino/setup.c 1.1 -> (deleted) # include/asm-mips64/asm.h 1.2 -> 1.3 # fs/xfs/linux/xfs_sysctl.h 1.8 -> 1.9 # drivers/s390/block/dasd_eckd.c 1.19 -> 1.21 # drivers/media/dvb/ttpci/av7110_firm.h 1.1 -> 1.2 # drivers/media/common/saa7146_vbi.c 1.1 -> 1.3 # include/asm-mips/parport.h 1.1 -> 1.2 # drivers/scsi/ips.c 1.59 -> 1.60 # arch/s390/kernel/smp.c 1.25 -> 1.26 # arch/mips64/kernel/setup.c 1.6 -> 1.7 # arch/mips/math-emu/ieee754sp.h 1.1 -> 1.2 # drivers/scsi/scsi_error.c 1.56 -> 1.59 # include/asm-ia64/topology.h 1.8 -> 1.9 # include/asm-mips64/page.h 1.4 -> 1.5 # include/asm-mips64/semaphore-helper.h 1.2 -> 1.3 # drivers/media/dvb/ttpci/av7110.h 1.1 -> 1.2 # drivers/media/dvb/frontends/Makefile 1.4 -> 1.5 # arch/mips64/sgi-ip27/ip27-nmi.c 1.2 -> 1.3 arch/mips/sgi-ip27/ip27-nmi.c (moved) # include/asm-mips64/ide.h 1.9 -> 1.10 # include/asm-mips64/fcntl.h 1.2 -> 1.3 # arch/x86_64/kernel/traps.c 1.24 -> 1.25 # drivers/ide/ide-taskfile.c 1.20 -> 1.22 # drivers/mtd/mtd_blkdevs.c 1.1 -> 1.3 # drivers/media/dvb/ttpci/av7110_ipack.h 1.1 -> 1.2 # arch/mips/philips/nino/time.c 1.2 -> (deleted) # include/asm-mips/addrspace.h 1.2 -> 1.3 # include/asm-mips/stackframe.h 1.2 -> 1.3 # arch/ppc64/kernel/cputable.c 1.1 -> 1.2 # drivers/ieee1394/raw1394.c 1.25 -> 1.26 # arch/mips/baget/setup.c 1.3 -> 1.4 # include/asm-mips/dec/tc.h 1.1 -> 1.2 # kernel/ksyms.c 1.205 -> 1.206 # drivers/char/n_tty.c 1.14 -> 1.15 # drivers/sgi/char/Makefile 1.6 -> (deleted) # arch/mips/Makefile 1.13 -> 1.14 # arch/mips/kernel/irix5sys.h 1.1 -> 1.2 # fs/xfs/linux/xfs_vfs.h 1.11.1.1 -> 1.14 # include/net/sctp/user.h 1.11 -> 1.12 # include/asm-mips64/elf.h 1.6 -> 1.7 # arch/ppc64/kernel/entry.S 1.26 -> 1.27 # include/linux/cdrom.h 1.13 -> 1.14 # arch/mips/mm/rm7k.c 1.4 -> (deleted) # drivers/i2c/Makefile 1.11 -> 1.12 # arch/mips64/kernel/r4k_switch.S 1.3 -> 1.4 # include/asm-mips/unistd.h 1.6 -> 1.7 # arch/mips64/mm/r4xx0.c 1.7 -> (deleted) # include/asm-mips/floppy.h 1.2 -> 1.3 # include/asm-mips/au1000.h 1.1 -> 1.2 # drivers/mtd/nftlcore.c 1.44 -> 1.45 # include/media/saa7146.h 1.2 -> 1.3 # arch/mips/philips/nino/int-handler.S 1.2 -> (deleted) # include/asm-mips64/addrspace.h 1.2 -> 1.3 # include/asm-mips64/io.h 1.3 -> 1.4 # include/asm-mips/nile4.h 1.1 -> 1.2 # arch/mips64/sgi-ip22/Makefile 1.7 -> (deleted) # net/ipv6/anycast.c 1.2 -> 1.3 # net/xfrm/xfrm_input.c 1.11 -> 1.12 # arch/alpha/kernel/core_t2.c 1.7 -> 1.8 # drivers/net/irda/vlsi_ir.c 1.16 -> 1.17 # include/asm-mips/processor.h 1.10 -> 1.11 # include/asm-mips/uaccess.h 1.2 -> 1.3 # include/asm-mips/vga.h 1.1 -> 1.2 # drivers/pnp/pnpbios/core.c 1.32 -> 1.33 # include/scsi/scsi_device.h 1.1 -> 1.2 # arch/x86_64/ia32/ia32_binfmt.c 1.13 -> 1.14 # net/sctp/associola.c 1.49.1.1 -> 1.55 # arch/ia64/Makefile 1.53 -> 1.55 # drivers/usb/net/cdc-ether.c 1.30 -> (deleted) # fs/xfs/pagebuf/page_buf.c 1.53 -> 1.54 # arch/ia64/kernel/efi.c 1.20 -> 1.21 # arch/mips/math-emu/ieee754.c 1.2 -> 1.3 # arch/mips64/mm/andes.c 1.6 -> (deleted) # arch/mips64/arc/time.c 1.2 -> (deleted) # arch/x86_64/kernel/setup.c 1.17 -> 1.18 # net/ipv6/exthdrs.c 1.12 -> 1.13 # include/asm-mips/gfx.h 1.2 -> 1.3 # include/asm-mips64/sn/sn0/addrs.h 1.2 -> 1.3 # include/linux/nfsd/state.h 1.4 -> 1.7 # drivers/serial/8250.c 1.33 -> 1.34 # drivers/char/agp/sis-agp.c 1.23 -> 1.24 # drivers/net/arcnet/arc-rimi.c 1.5 -> 1.6 # arch/mips/kernel/syscalls.h 1.3 -> 1.4 # arch/mips/math-emu/kernel_linkage.c 1.1 -> 1.2 # arch/mips/mips-boards/generic/init.c 1.1 -> 1.2 # lib/Makefile 1.24 -> 1.25 # drivers/scsi/hosts.c 1.77 -> 1.80 # arch/mips/sgi/kernel/Makefile 1.7 -> (deleted) # arch/mips/sgi/kernel/indy_int.c 1.4 -> (deleted) # arch/mips64/sgi-ip22/system.c 1.2 -> (deleted) # arch/mips64/math-emu/dp_frexp.c 1.1 -> (deleted) # drivers/ieee1394/csr.h 1.4 -> 1.5 # include/asm-mips64/mmzone.h 1.6 -> 1.7 # arch/mips64/math-emu/dp_sqrt.c 1.1 -> (deleted) # net/ipv6/ip6_output.c 1.31 -> 1.36 # drivers/mtd/inftlmount.c 1.1 -> 1.2 # net/sunrpc/sysctl.c 1.4 -> 1.5 # arch/mips/dec/prom/locore.S 1.1 -> 1.2 # include/asm-mips64/shmbuf.h 1.1 -> 1.2 # drivers/usb/serial/io_edgeport.c 1.45 -> 1.46 # drivers/net/ioc3-eth.c 1.18 -> 1.20 # drivers/media/video/mxb.c 1.4 -> 1.5 # include/asm-mips/types.h 1.2 -> 1.3 # arch/mips64/math-emu/dp_modf.c 1.1 -> (deleted) # arch/alpha/lib/memset.S 1.1 -> 1.3 # include/asm-mips/r4kcache.h 1.1 -> 1.2 # net/sctp/sm_statefuns.c 1.53.1.1 -> 1.60 # arch/mips/philips/nino/irq.c 1.5 -> (deleted) # arch/mips64/mips-boards/atlas/atlas_rtc.c 1.1 -> (deleted) # arch/mips/baget/ld.script.balo 1.2 -> 1.3 # arch/mips64/math-emu/sp_fint.c 1.1 -> (deleted) # include/asm-mips64/mmu.h 1.1 -> 1.2 # arch/i386/pci/pcbios.c 1.13 -> 1.14 # include/asm-ppc64/processor.h 1.30 -> 1.31 # drivers/i2c/busses/Makefile 1.8 -> 1.9 # mm/readahead.c 1.30 -> 1.31 # arch/mips/math-emu/dp_div.c 1.2 -> 1.3 # arch/mips/au1000/common/reset.c 1.1 -> 1.2 # include/asm-mips64/sn/sn0/hubni.h 1.2 -> 1.3 # arch/mips/kernel/irixinv.c 1.1 -> 1.2 # include/asm-mips64/dma.h 1.1 -> 1.2 # include/media/saa7146_vv.h 1.1 -> 1.3 # include/asm-mips64/xtalk/xwidget.h 1.2 -> 1.3 # arch/mips/math-emu/dp_tint.c 1.1 -> 1.2 # Documentation/cpu-freq/user-guide.txt 1.6 -> 1.7 # arch/mips/lib/Makefile 1.7 -> 1.8 # net/ipv6/sysctl_net_ipv6.c 1.6 -> 1.7 # net/bridge/br_fdb.c 1.6 -> 1.7 # include/asm-mips/bitops.h 1.5 -> 1.6 # include/asm-sparc/unistd.h 1.20 -> 1.21 # include/asm-mips/checksum.h 1.5 -> 1.6 # arch/mips64/lib/memcpy.S 1.3 -> 1.4 # include/asm-mips64/sn/sn0/ip27.h 1.2 -> 1.3 # include/asm-mips64/pci.h 1.9 -> 1.10 # arch/ia64/defconfig 1.19 -> 1.20 # include/asm-mips64/mmu_context.h 1.3 -> 1.4 # drivers/net/pcmcia/nmclan_cs.c 1.14 -> 1.16 # net/sched/cls_rsvp.h 1.4 -> 1.5 # drivers/media/dvb/dvb-core/dvb_net.h 1.3 -> 1.4 # arch/mips64/sgi-ip22/ip22-int.c 1.7 -> (deleted) # arch/alpha/lib/ev6-memset.S 1.2 -> 1.3 # arch/mips64/mips-boards/atlas/atlas_setup.c 1.1 -> (deleted) # include/asm-mips/baget/vic.h 1.1 -> 1.2 # include/linux/netfilter_ipv4/lockhelp.h 1.1 -> 1.2 # drivers/scsi/lasi700.c 1.11 -> 1.12 # arch/mips64/mips-boards/generic/pci.c 1.6 -> (deleted) # arch/s390/kernel/syscalls.S 1.2 -> 1.3 # arch/mips/lib/r3k_dump_tlb.c 1.2 -> 1.3 # arch/mips/ddb5074/prom.c 1.2 -> (deleted) # kernel/fork.c 1.126 -> 1.127 # net/sunrpc/svcsock.c 1.53 -> 1.54 # drivers/mtd/inftlcore.c 1.1 -> 1.3 # arch/mips64/mm/umap.c 1.6 -> (deleted) # include/asm-mips/fp.h 1.1 -> (deleted) # drivers/net/Space.c 1.22 -> 1.23 # kernel/sys.c 1.47 -> 1.49 # drivers/scsi/ibmmca.c 1.20 -> 1.21 # fs/jffs2/os-linux.h 1.10 -> 1.11 # include/linux/dvb/net.h 1.2 -> 1.3 # arch/mips/ddb5074/Makefile 1.6 -> 1.7 arch/mips/ddb5xxx/ddb5074/Makefile (moved) # include/asm-mips64/a.out.h 1.2 -> 1.3 # include/asm-mips/current.h 1.2 -> 1.3 # drivers/net/wireless/airo.c 1.41 -> 1.42 # drivers/pcmcia/i82092aa.h 1.7 -> 1.8 # drivers/pci/hotplug/ibmphp.h 1.8 -> 1.9 # include/asm-mips64/sn/sn0/hubio.h 1.3 -> 1.4 # arch/mips64/sgi-ip22/time.c 1.2 -> (deleted) # include/asm-mips64/sn/sn0/sn0_fru.h 1.2 -> 1.3 # include/asm-mips/sgi/sgint23.h 1.2 -> (deleted) # arch/mips/math-emu/sp_sqrt.c 1.1 -> 1.2 # include/asm-m68knommu/bitops.h 1.2 -> 1.3 # arch/mips64/tools/Makefile 1.4 -> (deleted) # arch/mips64/mm/extable.c 1.3 -> 1.4 # arch/mips64/math-emu/dp_scalb.c 1.1 -> (deleted) # include/net/tcp.h 1.49 -> 1.50 # drivers/mtd/maps/pcmciamtd.c 1.5 -> 1.6 # include/asm-mips/irq.h 1.4 -> 1.5 # drivers/media/dvb/ttpci/budget-ci.c 1.1 -> 1.3 # drivers/media/dvb/frontends/alps_bsrv2.c 1.4 -> 1.6 # arch/mips64/kernel/scall_64.S 1.6 -> 1.7 # include/linux/netfilter_ipv4/listhelp.h 1.2 -> 1.3 # include/asm-mips64/atomic.h 1.3 -> 1.4 # drivers/s390/net/lcs.c 1.15 -> 1.16 # include/asm-x86_64/nmi.h 1.1 -> 1.2 # arch/mips/ddb5xxx/ddb5477/irq.c 1.1 -> 1.2 # include/asm-mips/mips-boards/malta.h 1.1 -> 1.2 # arch/mips/kernel/ioport.c 1.1 -> (deleted) # fs/smbfs/inode.c 1.41 -> 1.42 # net/sctp/endpointola.c 1.26 -> 1.27 # fs/dcache.c 1.58 -> 1.59 # drivers/ieee1394/sbp2.c 1.35 -> 1.36 # include/linux/dvb/video.h 1.2 -> 1.3 # arch/mips/math-emu/ieee754.h 1.1 -> 1.2 # fs/smbfs/proc.c 1.31 -> 1.32 # drivers/s390/block/dasd_erp.c 1.3 -> 1.4 # drivers/media/dvb/frontends/grundig_29504-401.c 1.3 -> 1.5 # include/asm-mips64/gfx.h 1.3 -> 1.4 # arch/mips/mips-boards/generic/memory.c 1.2 -> 1.3 # include/asm-mips64/cpu.h 1.2 -> 1.3 # fs/proc/proc_misc.c 1.79 -> 1.80 # arch/mips/kernel/irq.c 1.10 -> 1.11 # arch/m68knommu/platform/5307/config.c 1.3 -> 1.4 # drivers/scsi/lasi700.h 1.5 -> 1.6 # drivers/media/dvb/ttpci/budget-patch.c 1.1 -> 1.3 # include/asm-x86_64/io_apic.h 1.6 -> 1.7 # arch/mips64/math-emu/Makefile 1.4 -> (deleted) # arch/mips/defconfig 1.6 -> 1.7 # arch/mips64/kernel/entry.S 1.4 -> 1.5 # include/asm-mips/cpu.h 1.3 -> 1.4 # include/asm-mips64/bootinfo.h 1.3 -> 1.4 # include/asm-mips64/sn/sn0/hubpi.h 1.2 -> 1.3 # arch/mips/arc/file.c 1.1 -> 1.2 # net/sctp/sm_make_chunk.c 1.51 -> 1.55 # drivers/scsi/dc395x.c 1.7 -> 1.8 # arch/sparc/kernel/process.c 1.26 -> 1.27 # arch/ia64/sn/kernel/Makefile 1.13 -> 1.14 # arch/sparc/Makefile 1.23 -> 1.24 # include/asm-mips64/current.h 1.2 -> 1.3 # arch/mips/math-emu/dp_fsp.c 1.1 -> 1.2 # arch/mips/math-emu/ieee754xcpt.c 1.1 -> 1.2 # drivers/pnp/interface.c 1.16 -> 1.17 # drivers/net/sk98lin/skge.c 1.20 -> 1.21 # include/asm-h8300/processor.h 1.1 -> 1.2 # drivers/usb/host/uhci-debug.c 1.5 -> 1.6 # include/asm-mips/dec/ioasic_addrs.h 1.2 -> 1.3 # arch/i386/Kconfig 1.62 -> 1.64 # include/linux/nfsd/xdr4.h 1.11 -> 1.14 # net/ipv4/netfilter/ip_nat_core.c 1.27 -> 1.28 # drivers/ieee1394/video1394.c 1.35 -> 1.36 # drivers/media/dvb/frontends/Kconfig 1.4 -> 1.5 # include/asm-s390/dasd.h 1.8 -> 1.9 # arch/mips/kernel/i8259.c 1.2 -> 1.3 # drivers/scsi/53c700.c 1.35 -> 1.37 # drivers/pci/hotplug/ibmphp_ebda.c 1.10 -> 1.11 # drivers/mtd/nand/autcpu12.c 1.1 -> 1.2 # include/asm-s390/compat.h 1.3 -> 1.4 # include/linux/elf.h 1.23 -> 1.24 # include/asm-mips/smp.h 1.2 -> 1.3 # arch/mips/arc/env.c 1.1 -> 1.2 # drivers/atm/he.c 1.15 -> 1.16 # arch/x86_64/kernel/i8259.c 1.7 -> 1.8 # arch/x86_64/kernel/x8664_ksyms.c 1.15 -> 1.16 # include/asm-mips64/sgi/sgimc.h 1.2 -> (deleted) # arch/mips/kernel/ipc.c 1.1 -> 1.2 # drivers/ieee1394/ieee1394_core.h 1.14 -> 1.15 # drivers/media/dvb/dvb-core/dvb_demux.c 1.4 -> 1.6 # include/asm-sparc64/unistd.h 1.19 -> 1.20 # arch/mips/sgi/kernel/time.c 1.3 -> (deleted) # drivers/usb/net/cdc-ether.h 1.6 -> (deleted) # arch/mips/algor/README 1.1 -> (deleted) # drivers/sgi/char/graphics.h 1.1 -> (deleted) # arch/i386/kernel/traps.c 1.54 -> 1.55 # arch/mips/arc/misc.c 1.4 -> 1.5 # arch/mips/kernel/smp.c 1.11 -> 1.12 # fs/nfsd/nfsctl.c 1.36 -> 1.37 # arch/i386/kernel/Makefile 1.44 -> 1.45 # include/asm-mips/isadep.h 1.3 -> 1.4 # arch/mips/sgi/kernel/reset.c 1.3 -> (deleted) # include/asm-mips64/floppy.h 1.2 -> 1.3 # include/asm-mips64/poll.h 1.2 -> 1.3 # include/asm-mips/rrm.h 1.1 -> (deleted) # drivers/mtd/maps/tqm8xxl.c 1.3 -> 1.4 # arch/s390/kernel/entry64.S 1.2 -> 1.3 # arch/mips/kernel/setup.c 1.10 -> 1.11 # arch/s390/kernel/entry.S 1.29 -> 1.30 # arch/mips/kernel/entry.S 1.4 -> 1.5 # include/asm-mips64/hw_irq.h 1.1 -> 1.2 # drivers/pcmcia/sa11xx_core.c 1.8 -> 1.11 # arch/mips64/sgi-ip32/crime.c 1.1 -> 1.2 arch/mips/sgi-ip32/crime.c (moved) # drivers/mtd/maps/impa7.c 1.3 -> 1.4 # arch/s390/Makefile 1.25 -> 1.26 # drivers/media/dvb/dvb-core/dvb_net.c 1.3 -> 1.5 # include/asm-x86_64/mtrr.h 1.5 -> 1.6 # arch/mips/tools/Makefile 1.3 -> (deleted) # arch/mips/ddb5xxx/ddb5477/debug.c 1.1 -> 1.2 # include/asm-mips/ddb5xxx/ddb5477.h 1.1 -> 1.2 # fs/xfs/xfs_vfsops.c 1.33.1.1 -> 1.36 # drivers/scsi/scsi_sysfs.c 1.22 -> 1.24 # arch/mips64/mips-boards/generic/time.c 1.4 -> (deleted) # arch/mips64/sgi-ip27/ip27-irq-glue.S 1.2 -> 1.3 arch/mips/sgi-ip27/ip27-irq-glue.S (moved) # include/asm-mips/param.h 1.2 -> 1.3 # drivers/serial/sunsu.c 1.35 -> 1.36 # drivers/char/agp/nvidia-agp.c 1.10 -> 1.11 # drivers/net/wan/sdla_ppp.c 1.25 -> 1.26 # drivers/media/dvb/ttpci/av7110_ir.c 1.1 -> 1.3 # include/asm-mips/dec/tcmodule.h 1.2 -> 1.3 # include/asm-mips/cacheops.h 1.1 -> 1.2 # include/asm-mips/dec/tcinfo.h 1.1 -> 1.2 # arch/i386/pci/numa.c 1.13 -> 1.14 # arch/i386/kernel/cpu/cpufreq/Kconfig 1.7 -> 1.8 # net/sched/sch_teql.c 1.6 -> 1.7 # drivers/media/dvb/dvb-core/dvbdev.c 1.10 -> 1.12 # drivers/s390/cio/qdio.h 1.4 -> 1.6 # include/asm-mips/bootinfo.h 1.4 -> 1.5 # include/asm-mips64/r10kcacheops.h 1.2 -> (deleted) # drivers/pnp/support.c 1.5 -> 1.6 # net/ipv4/netfilter/ip_nat_amanda.c 1.2 -> 1.3 # drivers/media/dvb/frontends/alps_tdmb7.c 1.3 -> 1.5 # arch/mips/kernel/mips_ksyms.c 1.8 -> 1.9 # arch/mips/arc/identify.c 1.3 -> 1.4 # include/asm-mips/inventory.h 1.1 -> 1.2 # include/asm-mips64/stackframe.h 1.1 -> 1.2 # net/atm/atm_misc.c 1.6 -> 1.7 # arch/x86_64/kernel/acpi/boot.c 1.2 -> 1.3 # security/dummy.c 1.25 -> 1.26 # drivers/i2c/Kconfig 1.10 -> 1.11 # net/netrom/sysctl_net_netrom.c 1.3 -> 1.4 # arch/mips64/mips-boards/generic/Makefile 1.6 -> (deleted) # arch/mips/kernel/gdb-low.S 1.2 -> 1.3 # drivers/atm/eni.c 1.16 -> 1.17 # include/asm-ppc/thread_info.h 1.8 -> 1.9 # include/linux/xfrm.h 1.11 -> 1.15 # arch/x86_64/oprofile/Makefile 1.2 -> 1.3 # drivers/media/dvb/dvb-core/dvb_filter.h 1.3 -> 1.4 # include/asm-mips/time.h 1.2 -> 1.3 # include/asm-mips/dec/kn02xa.h 1.2 -> 1.3 # arch/i386/pci/direct.c 1.15 -> 1.17 # net/bridge/br_private.h 1.14 -> 1.15 # drivers/scsi/NCR53C9x.c 1.23 -> 1.25 # net/ipv4/netfilter/Makefile 1.19 -> 1.21 # net/ipv6/ip6_flowlabel.c 1.2 -> 1.4 # arch/mips/tools/offset.c 1.3 -> (deleted) # drivers/block/nbd.c 1.56 -> 1.57 # drivers/media/dvb/dvb-core/dvb_frontend.c 1.4 -> 1.6 # include/asm-mips64/sn/arch.h 1.2 -> 1.3 # drivers/ieee1394/ieee1394_core.c 1.32 -> 1.33 # drivers/net/pcmcia/3c574_cs.c 1.17 -> 1.18 # arch/mips/lib/watch.S 1.1 -> 1.2 # net/ipv4/netfilter/ip_tables.c 1.16 -> 1.17 # include/asm-mips/module.h 1.2 -> 1.3 # arch/ia64/kernel/smpboot.c 1.35 -> 1.36 # arch/mips/defconfig-ddb5477 1.3 -> 1.4 # arch/mips64/math-emu/ieee754.c 1.2 -> (deleted) # arch/mips64/lib/strncpy_user.S 1.2 -> 1.3 # arch/mips/math-emu/dp_frexp.c 1.1 -> 1.2 # net/key/af_key.c 1.43 -> 1.45 # drivers/scsi/aha1740.c 1.19 -> 1.22 # drivers/scsi/sr.c 1.82 -> 1.85 # drivers/s390/char/tape_core.c 1.5 -> 1.6 # drivers/media/dvb/frontends/alps_tdlb7.c 1.3 -> 1.5 # include/asm-mips/mmu.h 1.1 -> 1.2 # net/bridge/br_input.c 1.14 -> 1.15 # drivers/scsi/scsi.h 1.87 -> 1.88 # arch/mips64/kernel/signal.c 1.8 -> 1.9 # arch/sparc64/solaris/fs.c 1.14 -> 1.15 # arch/m68knommu/platform/5206e/MOTOROLA/crt0_ram.S 1.1 -> 1.2 # arch/mips/au1000/pb1000/init.c 1.1 -> 1.2 # arch/mips/ddb5xxx/ddb5477/irq_5477.c 1.1 -> 1.2 # arch/mips/kernel/proc.c 1.3 -> 1.4 # arch/mips/mips-boards/malta/malta_int.c 1.2 -> 1.3 # arch/mips/sgi/kernel/indy_rtc.c 1.2 -> (deleted) # arch/mips64/math-emu/dp_logb.c 1.1 -> (deleted) # drivers/usb/storage/usb.c 1.68 -> 1.73 # drivers/pcmcia/cs.c 1.45 -> 1.50 # arch/ia64/sn/kernel/setup.c 1.14 -> 1.15 # include/asm-mips64/posix_types.h 1.3 -> 1.4 # arch/mips64/Makefile 1.15 -> 1.16 # arch/mips/kernel/init_task.c 1.3 -> 1.4 # arch/mips64/arc/identify.c 1.2 -> (deleted) # include/asm-mips/tlb.h 1.1 -> 1.2 # drivers/acpi/pci_root.c 1.15 -> 1.16 # arch/s390/kernel/head.S 1.11 -> 1.12 # drivers/char/watchdog/mixcomwd.c 1.15 -> 1.16 # arch/mips/kernel/sysmips.c 1.5 -> 1.6 # arch/i386/mach-voyager/voyager_basic.c 1.2 -> 1.3 # arch/mips64/kernel/unaligned.c 1.3 -> 1.4 # arch/mips64/sgi-ip27/ip27-berr.c 1.2 -> 1.3 arch/mips/sgi-ip27/ip27-berr.c (moved) # include/asm-mips/pmc/ev64120int.h 1.1 -> (deleted) # drivers/sgi/char/sgiserial.c 1.19 -> (deleted) # arch/mips/arc/Makefile 1.5 -> 1.6 # drivers/pci/hotplug/ibmphp_hpc.c 1.11 -> 1.13 # include/asm-x86_64/floppy.h 1.3 -> 1.4 # arch/mips/mm/fault.c 1.5 -> 1.6 # arch/mips64/kernel/process.c 1.6 -> 1.7 # arch/mips64/sgi-ip27/ip27-memory.c 1.5 -> 1.6 arch/mips/sgi-ip27/ip27-memory.c (moved) # include/asm-mips/dec/kn01.h 1.1 -> 1.2 # include/net/sctp/sctp.h 1.44 -> 1.45 # drivers/mtd/chips/amd_flash.c 1.6 -> 1.7 # arch/mips/defconfig-malta 1.3 -> 1.4 # arch/ia64/sn/io/machvec/pci.c 1.7 -> 1.8 # include/asm-mips/hardirq.h 1.3 -> 1.4 # include/asm-mips64/sgialib.h 1.3 -> 1.4 # drivers/pci/pci.c 1.56 -> 1.57 # drivers/media/dvb/frontends/dvb_dummy_fe.c 1.1 -> 1.3 # include/asm-mips64/checksum.h 1.5 -> 1.6 # include/asm-mips64/asmmacro.h 1.2 -> 1.3 # drivers/net/Makefile 1.63 -> 1.65 # drivers/mtd/chips/cfi_cmdset_0001.c 1.8 -> 1.9 # arch/x86_64/ia32/ptrace32.c 1.7 -> 1.8 # include/asm-mips/pgtable.h 1.11 -> 1.12 # arch/mips64/Kconfig 1.15 -> 1.16 # net/atm/proc.c 1.19 -> 1.20 # drivers/ide/ide.c 1.74 -> 1.80 # arch/x86_64/ia32/Makefile 1.16 -> 1.17 # arch/ia64/sn/io/machvec/pci_dma.c 1.9 -> 1.11 # include/asm-x86_64/ptrace.h 1.7 -> 1.8 # drivers/ieee1394/ieee1394.h 1.7 -> 1.8 # drivers/mtd/devices/doc2001.c 1.5 -> 1.6 # drivers/scsi/ncr53c8xx.c 1.29 -> 1.31 # arch/mips/math-emu/dp_add.c 1.2 -> 1.3 # arch/mips/ddb5xxx/ddb5477/Makefile 1.5 -> 1.6 # arch/mips64/kernel/binfmt_elf32.c 1.4 -> (deleted) # include/asm-mips/shmiq.h 1.2 -> 1.3 # net/atm/pvc.c 1.12 -> 1.13 # arch/mips/kernel/r4k_misc.S 1.4 -> (deleted) # arch/mips/philips/nino/ramdisk/ld.script 1.1 -> (deleted) # include/asm-mips64/bugs.h 1.2 -> 1.3 # include/asm-mips64/smp.h 1.3 -> 1.4 # arch/mips/au1000/common/serial.c 1.22 -> (deleted) # drivers/usb/serial/visor.c 1.62 -> 1.63 # arch/mips/baget/prom/init.c 1.2 -> 1.3 # arch/mips64/arc/env.c 1.2 -> (deleted) # include/asm-mips/mman.h 1.1 -> 1.2 # net/ipv6/reassembly.c 1.18 -> 1.20 # drivers/media/dvb/dvb-core/dvbdev.h 1.4 -> 1.6 # arch/mips64/kernel/r4k_tlb_glue.S 1.2 -> (deleted) # arch/mips64/kernel/head.S 1.2 -> 1.3 # arch/mips/mips-boards/generic/mipsIRQ.S 1.1 -> 1.2 # drivers/scsi/hosts.h 1.73 -> 1.74 # arch/mips64/math-emu/sp_add.c 1.2 -> (deleted) # arch/mips/dec/Makefile 1.9 -> 1.10 # drivers/sgi/Makefile 1.5 -> (deleted) # include/asm-mips/cache.h 1.3 -> 1.4 # include/asm-mips64/scatterlist.h 1.3 -> 1.4 # arch/mips/dec/rtc-dec.c 1.2 -> 1.3 # include/asm-mips64/mips-boards/malta.h 1.1 -> 1.2 # include/asm-mips64/pci/bridge.h 1.3 -> 1.4 # arch/mips64/kernel/branch.c 1.2 -> 1.3 # net/sctp/outqueue.c 1.35 -> 1.36 # drivers/video/i810/i810_main.c 1.10 -> 1.11 # arch/mips64/math-emu/sp_mul.c 1.2 -> (deleted) # arch/mips/au1000/common/int-handler.S 1.1 -> 1.2 # drivers/ieee1394/ieee1394_transactions.c 1.12 -> 1.13 # arch/s390/kernel/head64.S 1.2 -> 1.3 # drivers/media/dvb/ttpci/budget-core.c 1.1 -> 1.3 # include/asm-mips/signal.h 1.3 -> 1.4 # drivers/net/au1000_eth.h 1.3 -> 1.4 # include/asm-mips/msgbuf.h 1.1 -> 1.2 # drivers/pcmcia/yenta_socket.h 1.4 -> 1.6 # arch/i386/kernel/io_apic.c 1.71 -> 1.74 # fs/xfs/linux/xfs_iops.c 1.23 -> 1.25 # drivers/usb/core/hcd.h 1.28 -> 1.29 # include/net/sctp/sla1.h 1.3 -> (deleted) # arch/mips64/kernel/init_task.c 1.3 -> 1.4 # arch/mips64/arc/file.c 1.2 -> (deleted) # arch/mips64/lib/strlen_user.S 1.2 -> 1.3 # include/asm-mips/branch.h 1.1 -> 1.2 # include/asm-mips/sembuf.h 1.1 -> 1.2 # include/asm-mips64/sn/io.h 1.1 -> 1.2 # arch/sparc64/defconfig 1.89 -> 1.91 # drivers/net/sunhme.c 1.34 -> 1.35 # arch/ia64/sn/io/drivers/ifconfig_net.c 1.6 -> (deleted) # include/net/sctp/constants.h 1.14 -> 1.15 # arch/mips/math-emu/ieee754sp.c 1.3 -> 1.4 # include/asm-mips64/uaccess.h 1.2 -> 1.3 # arch/mips64/math-emu/ieee754int.h 1.1 -> (deleted) # include/asm-mips/pmc/ev64120.h 1.1 -> (deleted) # arch/mips/vmlinux.lds.S 1.9 -> 1.10 # drivers/mtd/maps/arctic-mtd.c 1.1 -> 1.2 # drivers/media/dvb/dvb-core/demux.h 1.2 -> 1.4 # drivers/sgi/char/ds1286.c 1.7 -> (deleted) # net/ipv4/netfilter/ipt_ULOG.c 1.9 -> 1.10 # arch/s390/kernel/traps.c 1.19 -> 1.20 # include/asm-mips64/irq.h 1.3 -> 1.4 # arch/mips/lib/ide-no.c 1.2 -> 1.3 # arch/mips64/lib/strnlen_user.S 1.2 -> 1.3 # arch/mips/math-emu/sp_fint.c 1.1 -> 1.2 # arch/mips/lib/kbd-no.c 1.1 -> (deleted) # fs/xfs/xfs_mount.c 1.30 -> 1.31 # arch/mips/au1000/common/time.c 1.3 -> 1.4 # arch/mips/defconfig-pb1000 1.3 -> 1.4 # include/asm-mips/dec/interrupts.h 1.2 -> 1.3 # drivers/sgi/char/rrm.c 1.2 -> (deleted) # arch/mips64/math-emu/dp_cmp.c 1.1 -> (deleted) # drivers/scsi/ncr53c8xx.h 1.12 -> 1.13 # arch/mips/math-emu/sp_sub.c 1.2 -> 1.3 # include/asm-mips64/user.h 1.2 -> 1.3 # include/asm-mips64/sgi/sgihpc.h 1.2 -> (deleted) # include/asm-mips64/sn/intr_public.h 1.1 -> 1.2 # security/capability.c 1.17 -> 1.18 # drivers/pcmcia/ti113x.h 1.6 -> 1.8 # arch/m68knommu/platform/5307/ARNEWSH/crt0_ram.S 1.1 -> 1.2 # arch/mips/defconfig-atlas 1.3 -> 1.4 # include/asm-mips64/sn/gda.h 1.2 -> 1.3 # include/asm-mips/sgiarcs.h 1.1 -> 1.2 # arch/mips/ddb5476/pci.c 1.9 -> (deleted) # include/asm-mips/page.h 1.4 -> 1.5 # arch/mips/au1000/common/irq.c 1.1 -> 1.2 # arch/mips64/math-emu/sp_tint.c 1.1 -> (deleted) # include/asm-mips/sgi/sgihpc.h 1.1 -> (deleted) # include/asm-mips64/param.h 1.1 -> 1.2 # drivers/pci/hotplug/pci_hotplug.h 1.8 -> 1.9 # drivers/s390/net/ctcmain.c 1.22 -> 1.23 # arch/mips64/sgi-ip27/ip27-timer.c 1.5 -> 1.6 arch/mips/sgi-ip27/ip27-timer.c (moved) # arch/mips/philips/nino/Makefile 1.6 -> (deleted) # include/asm-mips/mips-boards/atlas.h 1.1 -> 1.2 # arch/mips64/kernel/softfp.S 1.1 -> (deleted) # net/sctp/proc.c 1.5 -> 1.6 # drivers/scsi/fd_mcs.c 1.15 -> 1.17 # arch/mips/dec/prom/Makefile 1.7 -> 1.8 # net/sctp/sysctl.c 1.9 -> 1.12 # drivers/media/dvb/dvb-core/dvb_demux.h 1.3 -> 1.5 # arch/mips64/sgi-ip27/ip27-setup.c 1.2 -> 1.3 arch/mips/sgi-ip27/ip27-setup.c (moved) # arch/mips/ddb5074/nile4.c 1.2 -> 1.3 arch/mips/ddb5xxx/ddb5074/nile4_pic.c (moved) # drivers/sgi/char/gconsole.h 1.1 -> (deleted) # include/linux/ide.h 1.58 -> 1.60 # drivers/scsi/nsp32.c 1.14 -> 1.15 # drivers/mtd/mtdblock.c 1.44 -> 1.45 # net/unix/sysctl_net_unix.c 1.5 -> 1.6 # arch/mips64/kernel/Makefile 1.9 -> 1.10 # arch/mips/dec/setup.c 1.2 -> 1.3 # include/asm-mips/baget/vac.h 1.1 -> 1.2 # include/asm-ppc64/pci.h 1.7 -> 1.8 # drivers/usb/storage/transport.c 1.78 -> 1.83 # drivers/serial/sunsab.c 1.29 -> 1.30 # fs/xfs/xfs_acl.c 1.6 -> 1.7 # arch/mips/mips-boards/generic/gdb_hook.c 1.2 -> 1.3 # arch/mips64/sgi-ip22/ip22-irq.S 1.2 -> (deleted) # include/asm-mips/io.h 1.3 -> 1.4 # include/asm-mips64/hardirq.h 1.2 -> 1.3 # include/asm-mips64/sgiarcs.h 1.3 -> 1.4 # arch/mips/sgi/kernel/indyIRQ.S 1.1 -> (deleted) # include/asm-mips/paccess.h 1.1 -> 1.2 # include/asm-mips/prctl.h 1.1 -> 1.2 # arch/mips/mips-boards/generic/pci.c 1.8 -> (deleted) # arch/s390/kernel/sys_s390.c 1.5 -> 1.6 # arch/mips64/kernel/mips64_ksyms.c 1.8 -> 1.9 # drivers/s390/net/Makefile 1.10 -> 1.11 # arch/mips64/mips-boards/generic/cmdline.c 1.1 -> (deleted) # arch/mips64/sgi-ip27/ip27-klnuma.c 1.2 -> 1.3 arch/mips/sgi-ip27/ip27-klnuma.c (moved) # arch/s390/Kconfig 1.12 -> 1.14 # net/ipv6/raw.c 1.32 -> 1.33 # arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c 1.1 -> 1.2 # arch/ia64/kernel/irq_ia64.c 1.12 -> 1.13 # mm/swap.c 1.50 -> 1.51 # arch/mips64/tools/offset.c 1.2 -> (deleted) # include/asm-mips/umap.h 1.2 -> (deleted) # include/asm-mips/semaphore.h 1.4 -> 1.5 # include/asm-mips/ddb5xxx/debug.h 1.1 -> (deleted) # arch/mips64/arc/cmdline.c 1.2 -> (deleted) # drivers/usb/storage/initializers.c 1.6 -> 1.7 # arch/mips/philips/nino/ramdisk/Makefile 1.3 -> (deleted) # drivers/sgi/Kconfig 1.1 -> (deleted) # arch/mips/mm/andes.c 1.4 -> (deleted) # include/asm-mips64/reg.h 1.1 -> 1.2 # ipc/util.c 1.11 -> 1.12 # fs/xfs/xfs_sb.h 1.4 -> 1.5 # include/linux/sunrpc/debug.h 1.3 -> 1.4 # arch/mips64/math-emu/dp_tint.c 1.1 -> (deleted) # arch/i386/pci/common.c 1.39 -> 1.40 # net/netsyms.c 1.83 -> 1.85 # drivers/ide/setup-pci.c 1.15 -> 1.16 # drivers/media/video/dpc7146.c 1.2 -> 1.3 # fs/xfs/xfs_cap.c 1.4 -> 1.5 # net/rxrpc/sysctl.c 1.2 -> 1.3 # arch/mips64/mips-boards/malta/Makefile 1.5 -> (deleted) # include/asm-mips/user.h 1.1 -> 1.2 # include/linux/pci_ids.h 1.105 -> 1.106 # drivers/pci/hotplug/Kconfig 1.8 -> 1.9 # drivers/media/video/saa7111.c 1.12 -> 1.13 # arch/mips/kernel/process.c 1.9 -> 1.10 # arch/mips64/math-emu/sp_sub.c 1.2 -> (deleted) # drivers/sgi/char/usema.c 1.4 -> (deleted) # arch/mips/math-emu/dp_tlong.c 1.1 -> 1.2 # drivers/media/dvb/ttpci/av7110_ipack.c 1.1 -> 1.3 # arch/m68knommu/kernel/traps.c 1.2 -> 1.3 # arch/mips/ddb5476/int-handler.S 1.2 -> 1.3 arch/mips/ddb5xxx/ddb5476/int-handler.S (moved) # arch/mips/sgi/kernel/indy_hpc.c 1.2 -> (deleted) # include/asm-mips64/mips-boards/gt64120.h 1.1 -> 1.2 # include/asm-x86_64/pci.h 1.9 -> 1.10 # include/asm-i386/pci.h 1.22 -> 1.23 # include/asm-ia64/tlb.h 1.14 -> 1.15 # arch/mips/kernel/Makefile 1.11 -> 1.12 # fs/hpfs/namei.c 1.17 -> 1.18 # include/asm-mips64/system.h 1.4 -> 1.5 # arch/mips/mm/r4xx0.c 1.6 -> (deleted) # arch/mips64/sgi-ip32/ip32-irq-glue.S 1.1 -> 1.2 arch/mips/sgi-ip32/ip32-irq-glue.S (moved) # arch/mips64/sgi-ip32/ip32-pci-dma.c 1.1 -> (deleted) # drivers/sgi/char/sgiserial.h 1.4 -> (deleted) # arch/mips/kernel/traps.c 1.7 -> 1.8 # include/asm-mips/ddb5xxx/pci.h 1.1 -> (deleted) # include/asm-mips64/sn/kldir.h 1.1 -> 1.2 # arch/x86_64/ia32/sys_ia32.c 1.33 -> 1.34 # arch/sparc64/kernel/systbls.S 1.39 -> 1.40 # include/asm-mips/elf.h 1.5 -> 1.6 # include/asm-mips/system.h 1.5 -> 1.6 # arch/mips64/math-emu/ieee754d.c 1.1 -> (deleted) # arch/x86_64/kernel/pci-gart.c 1.13 -> 1.14 # include/linux/usb.h 1.80 -> 1.81 # drivers/pci/hotplug/cpci_hotplug_core.c 1.6 -> 1.7 # include/linux/usb_gadget.h 1.2 -> 1.3 # arch/mips/kernel/time.c 1.8 -> 1.9 # arch/mips/math-emu/dp_mul.c 1.2 -> 1.3 # drivers/scsi/aacraid/aachba.c 1.17 -> 1.19 # fs/jffs2/fs.c 1.12 -> 1.13 # drivers/video/vgastate.c 1.3 -> 1.4 # arch/mips/mm/r2300.c 1.5 -> (deleted) # arch/mips/arc/init.c 1.2 -> 1.3 # arch/mips/kernel/vm86.c 1.1 -> (deleted) # arch/i386/kernel/cpu/cpufreq/Makefile 1.7 -> 1.8 # drivers/scsi/seagate.c 1.19 -> 1.20 # include/linux/eventpoll.h 1.9 -> 1.10 # arch/mips/ddb5xxx/common/pci_auto.c 1.1 -> (deleted) # arch/ia64/pci/pci.c 1.31 -> 1.34 # drivers/ide/ide-cd.c 1.50 -> 1.51 # arch/x86_64/ia32/ia32entry.S 1.21 -> 1.22 # arch/mips/arc/time.c 1.1 -> 1.2 # fs/binfmt_elf.c 1.47 -> 1.48 # include/net/sctp/sm.h 1.24 -> 1.25 # arch/mips/ddb5xxx/common/irq_cpu.c 1.1 -> (deleted) # arch/mips64/math-emu/sp_flong.c 1.1 -> (deleted) # arch/mips64/math-emu/sp_sqrt.c 1.1 -> (deleted) # include/asm-mips64/sn/mapped_kernel.h 1.2 -> 1.3 # drivers/net/irda/Makefile 1.15 -> 1.16 # include/asm-mips/dec/kn03.h 1.2 -> 1.3 # arch/v850/Kconfig 1.14 -> 1.15 # arch/x86_64/kernel/nmi.c 1.12 -> 1.14 # arch/mips64/vmlinux.lds.S 1.8 -> 1.9 # drivers/scsi/sg.c 1.58 -> 1.59 # drivers/usb/serial/pl2303.c 1.41 -> 1.42 # drivers/s390/block/dasd.c 1.62 -> 1.63 # fs/xfs/xfs_trans.c 1.8 -> 1.9 # fs/compat.c 1.11 -> 1.12 # drivers/usb/usb-skeleton.c 1.37 -> 1.38 # drivers/net/e1000/e1000_ethtool.c 1.26 -> 1.27 # arch/ia64/kernel/efivars.c 1.11 -> 1.12 # include/asm-mips/mmu_context.h 1.3 -> 1.4 # arch/mips64/sgi-ip27/ip27-rtc.c 1.7 -> (deleted) # include/asm-mips64/mips-boards/atlas.h 1.1 -> 1.2 # arch/mips64/math-emu/sp_modf.c 1.1 -> (deleted) # drivers/net/sgiseeq.h 1.1 -> 1.2 # drivers/ide/Kconfig 1.15 -> 1.16 # drivers/net/acenic.c 1.33 -> 1.34 # net/ipv4/utils.c 1.2 -> 1.3 # include/asm-i386/scatterlist.h 1.3 -> 1.4 # include/asm-mips64/mman.h 1.2 -> 1.3 # include/linux/pci.h 1.95 -> 1.97 # arch/ia64/kernel/mca.c 1.33 -> 1.34 # drivers/net/e100/e100_main.c 1.76 -> 1.78 # arch/ia64/kernel/iosapic.c 1.27 -> 1.28 # Documentation/pci.txt 1.9 -> 1.10 # fs/xfs/xfs_attr_leaf.c 1.7 -> 1.8 # net/sctp/sla1.c 1.4 -> (deleted) # arch/mips/arc/console.c 1.3 -> 1.4 # drivers/scsi/osst.c 1.46 -> 1.47 # include/linux/dvb/frontend.h 1.2 -> 1.3 # arch/mips64/math-emu/dp_sub.c 1.2 -> (deleted) # include/asm-ia64/hw_irq.h 1.6 -> 1.7 # arch/ppc64/xmon/ppc-opc.c 1.1 -> 1.2 # arch/mips64/arc/memory.c 1.3 -> (deleted) # arch/mips/Kconfig 1.13 -> 1.14 # drivers/atm/idt77252.c 1.16 -> 1.17 # arch/ppc/kernel/process.c 1.36 -> 1.37 # arch/mips/ddb5074/pci.c 1.10 -> (deleted) # drivers/usb/core/hcd-pci.c 1.14 -> 1.15 # include/linux/nfs4.h 1.7 -> 1.9 # arch/mips/math-emu/sp_fdp.c 1.2 -> 1.3 # include/asm-mips64/div64.h 1.2 -> 1.3 # include/asm-mips64/sn/sn0/arch.h 1.2 -> 1.3 # arch/mips64/math-emu/dp_fsp.c 1.1 -> (deleted) # net/ipv4/ipmr.c 1.20 -> 1.27 # drivers/mtd/mtdblock_ro.c 1.27 -> 1.28 # include/asm-mips/shmbuf.h 1.2 -> 1.3 # include/asm-mips64/sn/klkernvars.h 1.1 -> 1.2 # arch/ia64/kernel/acpi.c 1.42 -> 1.43 # arch/x86_64/kernel/suspend.c 1.6 -> 1.7 # drivers/mtd/maps/elan-104nc.c 1.6 -> 1.7 # fs/nfs/dir.c 1.55 -> 1.56 # arch/mips/mm/ioremap.c 1.2 -> 1.3 # include/asm-mips64/inst.h 1.2 -> 1.3 # include/asm-mips/namei.h 1.1 -> 1.2 # include/linux/spinlock.h 1.26 -> 1.27 # drivers/net/wan/sdla_chdlc.c 1.31 -> 1.32 # drivers/scsi/scsi_syms.c 1.40 -> 1.42 # Documentation/DocBook/gadget.tmpl 1.1 -> 1.2 # fs/xfs/support/kmem.c 1.3 -> (deleted) # arch/mips64/kernel/ioctl32.c 1.11 -> 1.12 # drivers/serial/8250_cs.c 1.11 -> 1.15 # arch/mips64/defconfig-ip27 1.7 -> 1.8 # arch/mips/ddb5074/time.c 1.2 -> 1.3 arch/mips/ddb5xxx/ddb5074/time.c (moved) # drivers/usb/storage/scsiglue.c 1.48 -> 1.49 # drivers/scsi/scsi_lib.c 1.95 -> 1.99 # arch/mips/ddb5xxx/ddb5477/pci.c 1.2 -> (deleted) # include/asm-mips64/processor.h 1.8 -> 1.9 # include/asm-mips/mipsregs.h 1.5 -> 1.6 # arch/mips/kernel/branch.c 1.3 -> 1.4 # include/asm-mips/fpu_emulator.h 1.1 -> 1.2 # include/linux/mroute.h 1.3 -> 1.4 # arch/mips/baget/print.c 1.1 -> 1.2 # include/asm-alpha/elf.h 1.5 -> 1.6 # arch/sparc/kernel/systbls.S 1.17 -> 1.18 # include/asm-mips64/semaphore.h 1.3 -> 1.4 # net/core/dev.c 1.87 -> 1.88 # drivers/ide/legacy/pdc4030.c 1.11 -> 1.12 # drivers/media/common/saa7146_fops.c 1.2 -> 1.4 # arch/x86_64/kernel/io_apic.c 1.9 -> 1.10 # drivers/ide/ide-dma.c 1.15 -> 1.17 # include/linux/netfilter.h 1.5 -> 1.6 # arch/mips64/sgi-ip22/ip22-timer.c 1.4 -> (deleted) # arch/mips64/sgi-ip32/ip32-irq.c 1.1 -> 1.2 arch/mips/sgi-ip32/ip32-irq.c (moved) # include/asm-mips/gdb-stub.h 1.1 -> 1.2 # drivers/usb/core/usb.c 1.126 -> 1.127 # drivers/scsi/scsi.c 1.118 -> 1.119 # drivers/usb/storage/initializers.h 1.5 -> 1.6 # drivers/media/dvb/frontends/ves1820.c 1.4 -> 1.6 # arch/mips64/sgi-ip27/ip27-irq.c 1.7 -> 1.8 arch/mips/sgi-ip27/ip27-irq.c (moved) # arch/mips64/kernel/signal32.c 1.9 -> 1.10 # arch/mips64/math-emu/sp_simple.c 1.1 -> (deleted) # include/asm-mips/baget/baget.h 1.1 -> 1.2 # arch/alpha/kernel/time.c 1.18 -> 1.19 # drivers/s390/cio/device_fsm.c 1.5 -> 1.6 # drivers/ieee1394/dma.c 1.3 -> 1.4 # include/asm-mips64/sn/nmi.h 1.2 -> 1.3 # arch/mips64/mips-boards/malta/malta_setup.c 1.1 -> (deleted) # arch/mips/ddb5476/dbg_io.c 1.1 -> 1.2 arch/mips/ddb5xxx/ddb5476/dbg_io.c (moved) # drivers/scsi/zalon.h 1.3 -> 1.4 # arch/mips/lib/tinycon.c 1.1 -> 1.2 # include/asm-ppc/ptrace.h 1.7 -> 1.8 # include/asm-mips/ddb5xxx/ddb5xxx.h 1.2 -> 1.3 # include/asm-ia64/agp.h 1.3 -> 1.4 # arch/mips64/sgi-ip22/ip22-berr.c 1.2 -> (deleted) # include/asm-ppc64/uaccess.h 1.9 -> 1.11 # arch/x86_64/ia32/ia32_ioctl.c 1.28 -> 1.29 # arch/mips/lib/dump_tlb.c 1.2 -> 1.3 # include/asm-mips/siginfo.h 1.4 -> 1.5 # arch/mips64/mips-boards/generic/mipsIRQ.S 1.1 -> (deleted) # include/linux/sunrpc/cache.h 1.12 -> 1.14 # include/asm-mips/pgalloc.h 1.5 -> 1.6 # arch/mips/kernel/old-irq.c 1.6 -> (deleted) # arch/mips64/math-emu/sp_cmp.c 1.1 -> (deleted) # arch/ia64/sn/kernel/machvec.c 1.6 -> 1.7 # arch/mips64/mm/loadmmu.c 1.3 -> 1.4 # include/asm-mips64/sigcontext.h 1.2 -> 1.3 # include/asm-mips64/mips-boards/generic.h 1.1 -> 1.2 # include/asm-mips64/sn/addrs.h 1.1 -> 1.2 # arch/arm/Kconfig 1.24 -> 1.25 # include/linux/mtd/doc2000.h 1.5 -> 1.6 # drivers/net/au1000_eth.c 1.13 -> 1.14 # arch/ia64/sn/io/hwgfs/hcl.c 1.2 -> 1.4 # arch/mips64/sgi-ip27/ip27-reset.c 1.1 -> 1.2 arch/mips/sgi-ip27/ip27-reset.c (moved) # drivers/usb/net/usbnet.c 1.56 -> 1.57 # fs/xfs/xfs_log_recover.c 1.23 -> 1.26 # include/asm-mips64/sn/klconfig.h 1.3 -> 1.4 # drivers/sgi/char/graphics.c 1.9 -> (deleted) # arch/mips/ddb5xxx/ddb5477/pci_ops.c 1.2 -> (deleted) # arch/mips/math-emu/sp_simple.c 1.1 -> 1.2 # arch/mips/arc/tree.c 1.1 -> 1.2 # include/linux/sunrpc/svc.h 1.23 -> 1.24 # arch/mips/mm/r5432.c 1.5 -> (deleted) # arch/mips/lib/ide-std.c 1.3 -> 1.4 # arch/mips/dec/prom/init.c 1.2 -> 1.3 # arch/mips64/arc/salone.c 1.2 -> (deleted) # arch/ppc64/Kconfig 1.22 -> 1.23 # drivers/pnp/isapnp/core.c 1.38 -> 1.39 # drivers/pci/hotplug/pcihp_skeleton.c 1.3 -> 1.4 # drivers/s390/cio/device_pgid.c 1.4 -> 1.5 # arch/mips/dec/boot/Makefile 1.6 -> 1.7 # include/asm-mips/semaphore-helper.h 1.3 -> 1.4 # drivers/scsi/sym53c8xx_comm.h 1.11 -> 1.12 # drivers/s390/cio/chsc.c 1.11 -> 1.12 # arch/mips64/lib/ide-std.c 1.3 -> 1.4 # arch/mips/sgi/kernel/setup.c 1.3 -> (deleted) # arch/mips/baget/balo_supp.S 1.1 -> 1.2 # include/asm-mips64/ipcbuf.h 1.1 -> 1.2 # drivers/s390/net/ctctty.c 1.18 -> 1.19 # drivers/s390/cio/ccwgroup.c 1.3 -> 1.4 # include/asm-mips/errno.h 1.3 -> 1.4 # include/asm-mips/mips-boards/atlasint.h 1.1 -> 1.2 # include/asm-mips64/shmiq.h 1.3 -> 1.4 # fs/nfsd/nfssvc.c 1.38 -> 1.39 # net/ipv4/raw.c 1.35 -> 1.36 # drivers/media/dvb/ttpci/budget.c 1.1 -> 1.3 # net/ipv6/tcp_ipv6.c 1.62 -> 1.63 # drivers/pcmcia/tcic.c 1.27 -> 1.30 # net/ipv6/af_inet6.c 1.51 -> 1.52 # arch/i386/pci/Makefile 1.15 -> 1.16 # arch/mips/math-emu/Makefile 1.4 -> 1.5 # arch/mips/mips-boards/atlas/atlas_setup.c 1.2 -> 1.3 # drivers/s390/net/netiucv.c 1.20 -> 1.21 # arch/mips64/sgi-ip32/Makefile 1.7 -> 1.8 arch/mips/sgi-ip32/Makefile (moved) # arch/mips/dec/irq.c 1.7 -> (deleted) # ipc/util.h 1.4 -> 1.5 # arch/mips64/mips-boards/generic/memory.c 1.1 -> (deleted) # arch/mips/mm/extable.c 1.2 -> 1.3 # net/sunrpc/cache.c 1.15 -> 1.19 # net/xfrm/xfrm_user.c 1.26 -> 1.30 # fs/xfs/xfs_ialloc.c 1.7 -> 1.8 # arch/mips64/mm/fault.c 1.8 -> 1.9 # include/asm-mips64/msgbuf.h 1.1 -> 1.2 # drivers/pnp/resource.c 1.16 -> 1.17 # drivers/block/loop.c 1.98 -> 1.100 # fs/buffer.c 1.202 -> 1.203 # drivers/s390/block/dasd_ioctl.c 1.16 -> 1.17 # include/asm-mips/riscos-syscall.h 1.1 -> 1.2 # arch/arm26/Kconfig 1.2 -> 1.3 # fs/nfsd/export.c 1.81 -> 1.86 # drivers/ide/ide-probe.c 1.50 -> 1.52 # drivers/usb/core/hcd.c 1.66 -> 1.67 # include/asm-arm26/processor.h 1.1 -> 1.2 # include/asm-mips/ds1286.h 1.2 -> 1.3 # arch/mips/dec/promcon.c 1.3 -> 1.4 # fs/ext3/namei.c 1.41 -> 1.42 # drivers/scsi/aha1740.h 1.7 -> 1.8 # include/asm-mips/dec/ioasic.h 1.1 -> 1.2 # include/linux/ext3_fs.h 1.27 -> 1.28 # drivers/net/declance.c 1.15 -> 1.16 # include/asm-mips/ptrace.h 1.3 -> 1.4 # arch/mips64/defconfig-ip22 1.7 -> 1.8 # arch/mips/kernel/unaligned.c 1.3 -> 1.4 # arch/m68k/Kconfig 1.16 -> 1.17 # drivers/net/tulip/tulip_core.c 1.43 -> 1.44 # arch/mips64/sgi-ip22/ip22-rtc.c 1.2 -> (deleted) # arch/mips/math-emu/ieee754int.h 1.1 -> 1.2 # arch/mips64/lib/floppy-std.c 1.1 -> 1.2 # include/asm-mips/byteorder.h 1.1 -> 1.2 # net/ipv6/ndisc.c 1.44 -> 1.49 # arch/mips/lib/memcpy.S 1.2 -> 1.3 # arch/mips/math-emu/ieee754dp.h 1.1 -> 1.2 # MAINTAINERS 1.149 -> 1.150 # arch/parisc/Kconfig 1.16 -> 1.17 # net/sctp/protocol.c 1.53 -> 1.54 # net/sctp/ipv6.c 1.43 -> 1.44 # drivers/ieee1394/amdtp.c 1.13 -> 1.14 # arch/mips64/math-emu/ieee754sp.c 1.3 -> (deleted) # drivers/pcmcia/yenta_socket.c 1.28 -> 1.32 # drivers/s390/cio/qdio.c 1.6 -> 1.7 # drivers/media/dvb/ttpci/budget.h 1.1 -> 1.2 # drivers/ide/pci/sc1200.c 1.6 -> 1.7 # arch/mips/math-emu/sp_mul.c 1.2 -> 1.3 # drivers/sgi/char/usema.h 1.1 -> (deleted) # drivers/block/rd.c 1.75 -> 1.76 # include/linux/if_ether.h 1.6 -> 1.7 # drivers/ieee1394/nodemgr.c 1.29 -> 1.31 # drivers/media/common/saa7146_hlp.c 1.1 -> 1.3 # arch/mips64/math-emu/ieee754xcpt.c 1.1 -> (deleted) # net/atm/lec.c 1.28 -> 1.29 # include/net/irda/vlsi_ir.h 1.8 -> 1.9 # drivers/ide/ide-pnp.c 1.6 -> 1.7 # arch/mips64/sgi-ip27/TODO 1.1 -> 1.2 arch/mips/sgi-ip27/TODO (moved) # drivers/pci/hotplug/acpiphp_core.c 1.4 -> 1.6 # drivers/ieee1394/eth1394.c 1.16 -> 1.19 # mm/mmap.c 1.85 -> 1.87 # arch/mips64/kernel/linux32.c 1.13 -> 1.14 # arch/mips/mm/Makefile 1.7 -> 1.8 # arch/mips64/kernel/r4k_genex.S 1.2 -> 1.3 # drivers/sgi/char/sgicons.c 1.2 -> (deleted) # arch/mips/math-emu/dp_modf.c 1.1 -> 1.2 # drivers/scsi/gdth.c 1.29 -> 1.30 # include/asm-sparc64/compat.h 1.14 -> 1.15 # fs/xfs/linux/xfs_globals.c 1.14 -> 1.15 # drivers/ieee1394/dv1394-private.h 1.9 -> 1.10 # arch/mips64/math-emu/cp1emu.c 1.4 -> (deleted) # include/asm-mips/gt64120.h 1.1 -> 1.2 # fs/lockd/svc.c 1.21 -> 1.22 # net/sunrpc/svcauth_unix.c 1.16 -> 1.20 # include/asm-mips/posix_types.h 1.2 -> 1.3 # arch/i386/pci/acpi.c 1.9 -> 1.10 # drivers/net/typhoon.c 1.1.1.4 -> 1.4 # drivers/net/pppoe.c 1.29 -> 1.32 # include/linux/mtd/blktrans.h 1.1 -> 1.2 # arch/mips/kernel/pci-dma.c 1.2 -> 1.3 # include/asm-mips/bugs.h 1.2 -> 1.3 # drivers/scsi/st.c 1.65 -> 1.66 # arch/mips/baget/vacserial.c 1.18 -> (deleted) # drivers/usb/storage/usb.h 1.30 -> 1.34 # drivers/media/common/saa7146_video.c 1.2 -> 1.4 # arch/mips64/kernel/traps.c 1.6 -> 1.7 # arch/mips/mips-boards/generic/time.c 1.5 -> 1.6 # include/asm-mips/statfs.h 1.1 -> 1.2 # drivers/atm/atmtcp.c 1.9 -> 1.10 # net/atm/svc.c 1.14 -> 1.15 # drivers/net/eepro100.c 1.62 -> 1.63 # arch/mips/ddb5xxx/common/nile4.c 1.2 -> 1.3 # arch/mips/ddb5476/setup.c 1.2 -> 1.3 arch/mips/ddb5xxx/ddb5476/setup.c (moved) # arch/mips64/mips-boards/generic/init.c 1.1 -> (deleted) # arch/mips64/sgi-ip32/ip32-berr.c 1.1 -> 1.2 arch/mips/sgi-ip32/ip32-berr.c (moved) # drivers/usb/host/ehci-hcd.c 1.52 -> 1.53 # drivers/media/dvb/dvb-core/dvb_ringbuffer.c 1.1 -> 1.3 # include/asm-mips64/compat.h 1.1 -> 1.2 # include/linux/smb_fs.h 1.13 -> 1.14 # net/sctp/sm_sideeffect.c 1.45 -> 1.46 # arch/m68knommu/kernel/time.c 1.4 -> 1.5 # drivers/s390/block/dasd_fba.c 1.13 -> 1.14 # drivers/media/dvb/ttpci/av7110.c 1.1 -> 1.3 # include/asm-mips/rmap.h 1.1 -> 1.2 # arch/mips/kernel/head.S 1.3 -> 1.4 # include/asm-mips64/branch.h 1.2 -> 1.3 # include/asm-mips64/mc146818rtc.h 1.2 -> 1.3 # Makefile 1.412 -> 1.413 # arch/s390/kernel/compat_ioctl.c 1.3 -> 1.4 # drivers/sgi/char/streamable.c 1.4 -> (deleted) # fs/ext3/inode.c 1.75 -> 1.76 # include/asm-i386/io_apic.h 1.11 -> 1.13 # arch/ia64/kernel/head.S 1.12 -> 1.13 # arch/mips/baget/irq.c 1.8 -> 1.9 # include/asm-mips64/unaligned.h 1.2 -> 1.3 # arch/mips/lib/strncpy_user.S 1.1 -> 1.2 # include/asm-mips/reg.h 1.1 -> 1.2 # drivers/net/pcmcia/fmvj18x_cs.c 1.21 -> 1.22 # net/ipv4/netfilter/ip_nat_ftp.c 1.8 -> 1.10 # drivers/scsi/zalon.c 1.3 -> 1.4 # arch/mips/ddb5xxx/ddb5477/int-handler.S 1.1 -> 1.2 # arch/mips64/mm/init.c 1.9 -> 1.10 # drivers/scsi/ibmmca.h 1.9 -> 1.10 # arch/mips64/arc/misc.c 1.3 -> (deleted) # arch/mips64/sgi-ip32/ip32-rtc.c 1.1 -> 1.2 arch/mips/sgi-ip32/ip32-rtc.c (moved) # arch/mips/arc/memory.c 1.3 -> 1.4 # mm/page-writeback.c 1.71 -> 1.72 # drivers/net/pcmcia/smc91c92_cs.c 1.18 -> 1.19 # include/asm-x86_64/unistd.h 1.14 -> 1.15 # arch/mips/baget/wbflush.c 1.2 -> (deleted) # arch/mips64/sgi-ip22/ip22-setup.c 1.2 -> (deleted) # arch/mips/math-emu/dp_flong.c 1.1 -> 1.2 # include/asm-mips/sgi/sgi.h 1.1 -> 1.2 # arch/x86_64/kernel/time.c 1.18 -> 1.19 # arch/x86_64/defconfig 1.21 -> 1.22 # net/ipv4/tcp_output.c 1.30 -> 1.31 # include/net/ip.h 1.22 -> 1.24 # arch/mips/math-emu/ieee754dp.c 1.3 -> 1.4 # arch/mips64/math-emu/ieee754m.c 1.1 -> (deleted) # drivers/mtd/maps/lubbock-flash.c 1.1 -> 1.2 # arch/x86_64/kernel/acpi/wakeup.S 1.2 -> 1.3 # fs/xfs/xfs_inode_item.c 1.8 -> 1.9 # arch/mips/kernel/irixioctl.c 1.3 -> 1.4 # arch/mips/mips-boards/atlas/atlas_int.c 1.5 -> 1.6 # arch/mips/defconfig-nino 1.3 -> (deleted) # arch/mips64/sgi-ip27/ip27-klconfig.c 1.2 -> 1.3 arch/mips/sgi-ip27/ip27-klconfig.c (moved) # include/asm-mips64/r4kcacheops.h 1.2 -> (deleted) # include/asm-mips/wbflush.h 1.2 -> 1.3 # drivers/s390/char/con3215.c 1.23 -> 1.24 # drivers/ide/legacy/ide-cs.c 1.10 -> 1.11 # include/net/sctp/tsnmap.h 1.7 -> 1.8 # include/asm-mips/ng1hw.h 1.2 -> 1.3 # arch/mips64/sgi-ip27/ip27-console.c 1.3 -> 1.4 arch/mips/sgi-ip27/ip27-console.c (moved) # include/asm-mips/scatterlist.h 1.3 -> 1.4 # arch/mips/dec/int-handler.S 1.2 -> 1.3 # include/asm-mips/dec/machtype.h 1.1 -> 1.2 # arch/m68knommu/Kconfig 1.15 -> 1.18 # include/asm-ppc64/cputable.h 1.1 -> 1.2 # drivers/net/wan/sdla_x25.c 1.24 -> 1.25 # drivers/pcmcia/sa11xx_core.h 1.3 -> 1.5 # include/asm-mips/pci.h 1.10 -> 1.11 # include/asm-mips64/statfs.h 1.2 -> 1.3 # drivers/pci/pci-driver.c 1.30 -> 1.31 # arch/ppc64/kernel/sys_ppc32.c 1.64 -> 1.65 # include/scsi/scsi_cmnd.h 1.1 -> 1.2 # arch/mips64/kernel/syscall.c 1.7 -> 1.8 # arch/mips/au1000/common/prom.c 1.1 -> 1.2 # arch/mips/philips/nino/power.c 1.1 -> (deleted) # include/asm-mips/div64.h 1.3 -> 1.4 # include/asm-mips/sgialib.h 1.2 -> 1.3 # arch/mips/ddb5476/nile4.c 1.1 -> 1.2 arch/mips/ddb5xxx/ddb5476/nile4_pic.c (moved) # arch/mips/mips-boards/generic/display.c 1.1 -> 1.2 # drivers/pci/probe.c 1.44 -> 1.46 # drivers/pci/hotplug/Makefile 1.15 -> 1.16 # drivers/net/wireless/strip.c 1.12 -> 1.13 # arch/mips/kernel/pci.c 1.7 -> (deleted) # arch/mips64/lib/memset.S 1.2 -> 1.3 # arch/mips/boot/addinitrd.c 1.1 -> 1.2 # arch/mips/lib/floppy-std.c 1.1 -> 1.2 # fs/nfsd/nfs4state.c 1.5 -> 1.10 # drivers/s390/cio/requestirq.c 1.7 -> 1.8 # arch/mips/kernel/old-time.c 1.4 -> (deleted) # drivers/media/common/saa7146_core.c 1.2 -> 1.4 # drivers/media/dvb/frontends/nxt6000.c 1.1 -> 1.2 # arch/mips64/kernel/smp.c 1.8 -> 1.9 # arch/mips/math-emu/dp_sub.c 1.3 -> 1.4 # include/asm-mips/ucontext.h 1.1 -> 1.2 # drivers/usb/net/kaweth.c 1.45 -> 1.49 # include/asm-mips/bug.h 1.2 -> 1.3 # arch/ppc64/kernel/prom.c 1.28 -> 1.29 # drivers/s390/block/dasd_int.h 1.17 -> 1.18 # arch/mips64/mips-boards/malta/malta_int.c 1.4 -> (deleted) # include/acpi/acpi_drivers.h 1.14 -> 1.15 # arch/mips64/math-emu/dp_fint.c 1.1 -> (deleted) # arch/mips/baget/baget.c 1.1 -> 1.2 # include/asm-x86_64/pgtable.h 1.21 -> 1.22 # net/xfrm/xfrm_state.c 1.29 -> 1.31 # include/linux/security.h 1.23 -> 1.24 # kernel/module.c 1.86 -> 1.87 # arch/mips64/sgi-ip27/ip27-pci-dma.c 1.3 -> (deleted) # arch/mips/mm/loadmmu.c 1.4 -> 1.5 # arch/mips/ddb5xxx/ddb5477/kgdb_io.c 1.1 -> 1.2 # include/asm-mips/mips-boards/generic.h 1.1 -> 1.2 # drivers/ieee1394/dv1394.c 1.32 -> 1.33 # fs/xfs/xfs_inode.h 1.15 -> 1.17 # include/asm-mips/ide.h 1.10 -> 1.11 # arch/mips/baget/balo.c 1.1 -> 1.2 # drivers/usb/host/hc_sl811.c 1.4 -> 1.5 # include/asm-mips/dec/kn02.h 1.2 -> 1.3 # include/asm-mips64/r4kcache.h 1.2 -> 1.3 # arch/mips64/math-emu/sp_logb.c 1.1 -> (deleted) # arch/mips64/math-emu/sp_tlong.c 1.1 -> (deleted) # net/atm/common.h 1.8 -> 1.9 # arch/ppc64/kernel/smp.c 1.38 -> 1.39 # drivers/ieee1394/ieee1394_types.h 1.17 -> 1.18 # arch/mips/ddb5476/Makefile 1.5 -> 1.6 arch/mips/ddb5xxx/ddb5476/Makefile (moved) # arch/mips/ddb5xxx/common/irq.c 1.1 -> 1.2 # drivers/mtd/mtdpart.c 1.5 -> 1.6 # arch/m68knommu/platform/5282/MOTOROLA/crt0_ram.S 1.1 -> 1.2 # arch/mips64/kernel/scall_o32.S 1.8 -> 1.9 # include/asm-mips64/signal.h 1.4 -> 1.5 # include/asm-s390/queue.h 1.4 -> (deleted) # drivers/s390/block/xpram.c 1.41 -> 1.42 # drivers/s390/cio/device.c 1.6 -> 1.8 # drivers/s390/cio/device_ops.c 1.4 -> 1.5 # drivers/net/irda/Kconfig 1.4 -> 1.5 # arch/mips64/sgi-ip27/ip27-pci.c 1.8 -> (deleted) # drivers/ieee1394/dv1394.h 1.3 -> 1.4 # net/ipv6/route.c 1.45 -> 1.48 # net/ipv4/tcp_input.c 1.39 -> 1.41 # include/linux/nfs.h 1.4 -> 1.5 # drivers/scsi/sym53c416.h 1.7 -> 1.8 # drivers/ieee1394/cmp.c 1.6 -> 1.7 # arch/mips64/defconfig 1.9 -> 1.10 # arch/mips/ddb5476/time.c 1.1 -> (deleted) # arch/mips/sgi/kernel/system.c 1.1 -> (deleted) # drivers/scsi/sd.c 1.123 -> 1.126 # drivers/media/dvb/dvb-core/dvb_i2c.c 1.4 -> 1.6 # include/asm-mips64/ioctls.h 1.5 -> 1.6 # arch/mips/philips/nino/kgdb.c 1.1 -> (deleted) # net/ipv4/tcp_minisocks.c 1.40 -> 1.41 # drivers/media/dvb/dvb-core/dmxdev.c 1.3 -> 1.5 # net/sunrpc/svcauth.c 1.11 -> 1.12 # arch/mips64/sgi-ip22/ip22-reset.c 1.2 -> (deleted) # arch/mips/ddb5074/setup.c 1.2 -> 1.3 arch/mips/ddb5xxx/ddb5074/setup.c (moved) # arch/mips/mips-boards/generic/printf.c 1.1 -> 1.2 # drivers/sgi/char/shmiq.c 1.10 -> (deleted) # fs/xfs/xfs_iocore.c 1.6 -> 1.7 # drivers/serial/8250_pci.c 1.22 -> 1.23 # arch/mips/ddb5074/int-handler.S 1.2 -> 1.3 arch/mips/ddb5xxx/ddb5074/int-handler.S (moved) # arch/alpha/Kconfig 1.19 -> 1.21 # drivers/net/gt96100eth.c 1.9 -> 1.10 # arch/mips/kernel/signal.c 1.11 -> 1.12 # arch/mips64/lib/dump_tlb.c 1.3 -> 1.4 # arch/mips/kernel/scall_o32.S 1.4 -> 1.5 # arch/mips64/mips-boards/generic/gdb_hook.c 1.1 -> (deleted) # include/asm-mips/mips32_cache.h 1.1 -> (deleted) # net/atm/signaling.c 1.12 -> 1.13 # drivers/usb/storage/unusual_devs.h 1.42 -> 1.47 # net/ipv4/netfilter/ip_conntrack_irc.c 1.10 -> 1.12 # Documentation/scsi/scsi_mid_low_api.txt 1.13 -> 1.14 # arch/mips/boot/Makefile 1.7 -> 1.8 # arch/mips64/math-emu/dp_flong.c 1.1 -> (deleted) # arch/mips/baget/bagetIRQ.S 1.1 -> 1.2 # arch/mips/dec/prom/prom.h 1.1 -> (deleted) # mm/slab.c 1.89 -> 1.90 # net/ipv4/netfilter/arp_tables.c 1.8 -> 1.9 # include/linux/module.h 1.65 -> 1.66 # net/ipv4/netfilter/ip_conntrack_ftp.c 1.13 -> 1.15 # include/asm-ppc64/bitops.h 1.5 -> 1.6 # drivers/scsi/sym53c8xx_defs.h 1.8 -> 1.9 # include/net/ndisc.h 1.4 -> 1.5 # arch/mips/mips-boards/generic/cmdline.c 1.2 -> 1.3 # fs/xfs/xfsidbg.c 1.27 -> 1.28 # include/net/addrconf.h 1.9 -> 1.10 # drivers/media/dvb/ttpci/budget-av.c 1.1 -> 1.3 # arch/mips/au1000/pb1000/Makefile 1.5 -> 1.6 # arch/mips64/kernel/ptrace.c 1.7 -> 1.8 # arch/mips/kernel/syscall.c 1.4 -> 1.5 # drivers/scsi/scsi_scan.c 1.94 -> 1.96 # arch/x86_64/Kconfig 1.24 -> 1.25 # include/linux/rtnetlink.h 1.17 -> 1.18 # drivers/s390/cio/device.h 1.3 -> 1.4 # arch/mips/dec/prom/cmdline.c 1.2 -> 1.3 # kernel/sched.c 1.195 -> 1.198 # net/bridge/br_stp_bpdu.c 1.5 -> 1.6 # fs/jffs2/dir.c 1.26 -> 1.27 # drivers/scsi/seagate.h 1.6 -> 1.7 # arch/s390/kernel/compat_linux.c 1.2 -> 1.4 # arch/mips/kernel/r2300_misc.S 1.2 -> (deleted) # arch/mips/dec/reset.c 1.2 -> 1.3 # drivers/sgi/char/newport.c 1.2 -> (deleted) # include/asm-mips64/sembuf.h 1.1 -> 1.2 # net/atm/resources.h 1.6 -> 1.7 # drivers/Makefile 1.35 -> 1.36 # arch/mips/math-emu/sp_div.c 1.2 -> 1.3 # arch/mips64/lib/csum_partial_copy.c 1.4 -> 1.5 # include/asm-mips/fcntl.h 1.2 -> 1.3 # include/asm-mips/shmparam.h 1.1 -> 1.2 # drivers/usb/host/ehci-dbg.c 1.20 -> 1.21 # drivers/net/tulip/de2104x.c 1.19 -> 1.20 # drivers/scsi/Makefile 1.43 -> 1.45 # arch/mips/math-emu/sp_add.c 1.2 -> 1.3 # arch/mips64/math-emu/ieee754sp.h 1.1 -> (deleted) # arch/mips/math-emu/dp_simple.c 1.1 -> 1.2 # drivers/acpi/osl.c 1.38 -> 1.40 # arch/mips/mips-boards/generic/Makefile 1.5 -> 1.6 # arch/mips/dec/wbflush.c 1.3 -> 1.4 # arch/mips/philips/nino/reset.c 1.1 -> (deleted) # arch/mips64/arc/tree.c 1.3 -> (deleted) # include/asm-mips/asmmacro.h 1.2 -> 1.3 # arch/ia64/kernel/gate.S 1.17 -> 1.18 # include/net/ipv6.h 1.19 -> 1.21 # drivers/ieee1394/iso.c 1.6 -> 1.7 # net/ipv4/netfilter/ip_nat_snmp_basic.c 1.8 -> 1.9 # arch/mips/dec/time.c 1.5 -> 1.6 # arch/m68knommu/platform/5272/NETtel/crt0_ram.S 1.1 -> 1.2 # include/asm-mips64/unistd.h 1.5 -> 1.6 # include/asm-mips64/rmap.h 1.1 -> 1.2 # net/atm/mpc.c 1.19 -> 1.20 # drivers/ide/ide-io.c 1.12 -> 1.13 # arch/m68knommu/platform/5282/pit.c 1.1 -> 1.2 # drivers/media/dvb/frontends/grundig_29504-491.c 1.3 -> 1.5 # net/sctp/hashdriver.c 1.4 -> (deleted) # arch/mips64/sgi-ip32/ip32-timer.c 1.1 -> 1.2 arch/mips/sgi-ip32/ip32-timer.c (moved) # net/ipv6/udp.c 1.42 -> 1.43 # include/linux/atmdev.h 1.17 -> 1.18 # drivers/pci/hotplug/pci_hotplug_core.c 1.39 -> 1.40 # drivers/mtd/ftl.c 1.47 -> 1.48 # arch/ia64/sn/io/drivers/Makefile 1.3 -> 1.4 # net/ipv4/netfilter/Kconfig 1.6 -> 1.9 # arch/mips/au1000/common/puts.c 1.1 -> 1.2 # arch/mips64/mips-boards/generic/printf.c 1.1 -> (deleted) # include/asm-mips64/tlb.h 1.1 -> 1.2 # kernel/timer.c 1.60 -> 1.61 # fs/nfsd/nfs4xdr.c 1.18 -> 1.20 # include/net/xfrm.h 1.44 -> 1.46 # drivers/mtd/maps/ebony.c 1.1 -> 1.2 # arch/mips64/math-emu/ieee754dp.c 1.3 -> (deleted) # include/asm-mips64/mipsregs.h 1.5 -> 1.6 # arch/mips64/arc/init.c 1.2 -> (deleted) # include/asm-mips64/pgalloc.h 1.6 -> 1.7 # drivers/net/Makefile.lib 1.6 -> 1.7 # drivers/cdrom/Kconfig 1.2 -> 1.3 # arch/mips/ddb5xxx/common/rtc_ds1386.c 1.2 -> 1.3 # arch/mips64/mips-boards/atlas/Makefile 1.5 -> (deleted) # arch/mips/ddb5476/irq.c 1.1 -> 1.2 arch/mips/ddb5xxx/ddb5476/irq.c (moved) # net/sctp/bind_addr.c 1.17 -> 1.19 # drivers/s390/block/dasd_3990_erp.c 1.13 -> 1.14 # arch/mips/kernel/r2300_switch.S 1.6 -> 1.7 # include/asm-mips64/siginfo.h 1.6 -> 1.7 # arch/mips64/lib/kbd-no.c 1.2 -> (deleted) # arch/mips/math-emu/dp_cmp.c 1.1 -> 1.2 # arch/mips/lib/strnlen_user.S 1.1 -> 1.2 # include/asm-mips/dec/ioasic_ints.h 1.1 -> 1.2 # include/asm-ia64/timex.h 1.7 -> 1.8 # arch/mips64/lib/Makefile 1.6 -> 1.7 # arch/mips/kernel/irixsig.c 1.7 -> 1.8 # drivers/ieee1394/dma.h 1.2 -> 1.3 # arch/mips64/ld.script.elf64 1.5 -> (deleted) # include/asm-m68knommu/dma.h 1.1 -> 1.2 # arch/mips64/lib/kbd-std.c 1.2 -> (deleted) # arch/mips64/math-emu/kernel_linkage.c 1.1 -> (deleted) # include/asm-mips/bcache.h 1.2 -> 1.3 # arch/mips/math-emu/sp_flong.c 1.1 -> 1.2 # arch/mips/sgi/kernel/indy_mc.c 1.1 -> (deleted) # drivers/ieee1394/ohci1394.c 1.39 -> 1.41 # arch/s390/defconfig 1.22 -> 1.25 # drivers/media/dvb/frontends/at76c651.c 1.1 -> 1.3 # include/asm-mips64/r10kcache.h 1.3 -> (deleted) # arch/mips/sgi/kernel/indy_sc.c 1.4 -> (deleted) # arch/ppc64/kernel/pci.c 1.33 -> 1.34 # drivers/net/Kconfig 1.29 -> 1.34 # drivers/pci/hotplug/ibmphp_res.c 1.7 -> 1.8 # drivers/i2c/busses/Kconfig 1.11 -> 1.12 # arch/ppc64/xmon/xmon.c 1.26 -> 1.27 # arch/mips/au1000/pb1000/setup.c 1.2 -> 1.3 # arch/mips/ddb5xxx/common/prom.c 1.1 -> 1.2 # net/ipv6/mcast.c 1.25 -> 1.28 # include/asm-s390/ccwdev.h 1.4 -> 1.5 # include/asm-mips64/bitops.h 1.4 -> 1.5 # drivers/usb/host/ohci-dbg.c 1.22 -> 1.23 # arch/mips/mm/init.c 1.8 -> 1.9 # include/asm-mips/ioctls.h 1.4 -> 1.5 # arch/mips64/math-emu/dp_tlong.c 1.1 -> (deleted) # arch/sparc64/Kconfig 1.24 -> 1.25 # arch/mips/ddb5xxx/ddb5477/setup.c 1.2 -> 1.3 # include/asm-mips64/timex.h 1.2 -> 1.3 # include/asm-mips64/rrm.h 1.1 -> (deleted) # arch/mips/math-emu/dp_sqrt.c 1.1 -> 1.2 # kernel/exit.c 1.103 -> 1.104 # arch/ia64/kernel/irq.c 1.25 -> 1.26 # arch/alpha/kernel/process.c 1.27 -> 1.28 # arch/mips64/sgi-ip32/ip32-setup.c 1.1 -> 1.2 arch/mips/sgi-ip32/ip32-setup.c (moved) # fs/jbd/commit.c 1.35 -> 1.36 # include/asm-x86_64/proto.h 1.12 -> 1.13 # include/asm-x86_64/apic.h 1.7 -> 1.8 # arch/ppc/kernel/entry.S 1.29 -> 1.31 # drivers/ieee1394/iso.h 1.3 -> 1.4 # drivers/net/ixgb/ixgb_ethtool.c 1.4 -> 1.5 # drivers/mtd/chips/gen_probe.c 1.2 -> 1.3 # drivers/usb/host/uhci-hcd.c 1.35 -> 1.36 # net/ipv6/netfilter/ip6_tables.c 1.18 -> 1.20 # arch/s390/kernel/module.c 1.8 -> 1.9 # fs/xfs/xfs_dir_leaf.c 1.8 -> 1.9 # include/linux/dvb/dmx.h 1.2 -> 1.3 # arch/mips/mm/umap.c 1.5 -> (deleted) # include/asm-mips64/serial.h 1.2 -> 1.3 # arch/mips/lib/floppy-no.c 1.1 -> 1.2 # drivers/pcmcia/i82365.c 1.37 -> 1.40 # drivers/s390/net/Kconfig 1.2 -> 1.3 # arch/mips64/math-emu/dp_simple.c 1.1 -> (deleted) # arch/x86_64/kernel/module.c 1.9 -> 1.10 # arch/mips/math-emu/ieee754d.c 1.1 -> 1.2 # fs/ext3/super.c 1.70 -> 1.71 # drivers/scsi/Kconfig 1.23 -> 1.25 # include/asm-s390/setup.h 1.9 -> 1.10 # include/asm-ppc64/eeh.h 1.4 -> 1.5 # arch/mips64/arc/arc_con.c 1.1 -> (deleted) # arch/mips64/arc/console.c 1.2 -> (deleted) # include/asm-s390/elf.h 1.6 -> 1.7 # drivers/pci/Makefile 1.30 -> 1.33 # arch/mips64/boot/Makefile 1.7 -> 1.8 # arch/mips/math-emu/cp1emu.c 1.4 -> 1.5 # include/asm-mips/hw_irq.h 1.2 -> 1.3 # include/asm-mips/unaligned.h 1.2 -> 1.3 # include/asm-mips/timex.h 1.1 -> 1.2 # include/asm-mips64/ipc.h 1.1 -> 1.2 # arch/cris/Kconfig 1.10 -> 1.12 # drivers/mtd/maps/iq80310.c 1.5 -> 1.6 # include/asm-m68knommu/mcfuart.h 1.2 -> 1.3 # net/ax25/sysctl_net_ax25.c 1.6 -> 1.7 # arch/mips64/kernel/r4k_tlb_debug.c 1.2 -> (deleted) # fs/xfs/linux/xfs_super.c 1.46.1.1 -> 1.48 # include/asm-ia64/pci.h 1.19 -> 1.20 # drivers/pci/hotplug.c 1.17 -> 1.18 # drivers/serial/Kconfig 1.10 -> 1.12 # drivers/mtd/afs.c 1.3 -> 1.4 # drivers/net/sgiseeq.c 1.14 -> 1.15 # drivers/net/sb1250-mac.c 1.4 -> 1.5 # arch/mips/kernel/sysirix.c 1.10 -> 1.11 # include/asm-mips64/stat.h 1.3 -> 1.4 # include/asm-mips64/ptrace.h 1.2 -> 1.3 # include/asm-x86_64/scatterlist.h 1.2 -> 1.3 # arch/mips64/math-emu/sp_scalb.c 1.1 -> (deleted) # net/sunrpc/svc.c 1.21 -> 1.22 # mm/rmap.c 1.28 -> 1.29 # include/net/dst.h 1.14 -> 1.15 # arch/mips/mips-boards/atlas/Makefile 1.5 -> 1.6 # arch/mips64/sgi-ip22/ip22-sc.c 1.4 -> (deleted) # include/asm-mips64/delay.h 1.3 -> 1.4 # arch/mips/ddb5476/prom.c 1.1 -> (deleted) # fs/jffs2/scan.c 1.10 -> 1.11 # arch/mips/dec/prom/identify.c 1.1 -> 1.2 # include/asm-mips/poll.h 1.1 -> 1.2 # arch/ia64/kernel/perfmon.c 1.50 -> 1.52 # net/ipv6/addrconf.c 1.52 -> 1.54 # drivers/pci/hotplug/cpqphp_pci.c 1.21 -> 1.22 # include/asm-mips64/sgi/sgint23.h 1.3 -> (deleted) # arch/mips64/math-emu/ieee754.h 1.1 -> (deleted) # fs/Kconfig.binfmt 1.1 -> 1.2 # net/ipv4/icmp.c 1.32 -> 1.34 # drivers/net/ppp_generic.c 1.33 -> 1.35 # arch/mips/ddb5xxx/common/Makefile 1.4 -> 1.5 # arch/mips64/sgi-ip27/Makefile 1.7 -> 1.8 arch/mips/sgi-ip27/Makefile (moved) # include/asm-mips64/sn/sn0/hubmd.h 1.2 -> 1.3 # arch/mips/lib/csum_partial.S 1.1 -> 1.2 # include/linux/netdevice.h 1.43 -> 1.44 # net/atm/resources.c 1.12 -> 1.13 # arch/mips64/math-emu/sp_fdp.c 1.2 -> (deleted) # include/asm-mips64/sn/launch.h 1.3 -> 1.4 # arch/mips64/sgi-ip22/ip22-mc.c 1.2 -> (deleted) # arch/mips/math-emu/sp_modf.c 1.1 -> 1.2 # include/asm-mips/ng1.h 1.1 -> 1.2 # arch/ia64/Kconfig 1.32 -> 1.35 # fs/compat_ioctl.c 1.2 -> 1.3 # drivers/net/pcmcia/3c589_cs.c 1.17 -> 1.18 # arch/mips/kernel/r4k_switch.S 1.5 -> 1.6 # arch/mips/mm/mips32.c 1.5 -> (deleted) # arch/mips/lib/strlen_user.S 1.1 -> 1.2 # include/pcmcia/ss.h 1.20 -> 1.22 # arch/ia64/lib/Makefile 1.20 -> 1.21 # drivers/media/dvb/dvb-core/dvb_frontend.h 1.3 -> 1.5 # arch/mips/au1000/common/dbg_io.c 1.1 -> 1.2 # include/asm-mips/delay.h 1.2 -> 1.3 # include/asm-mips64/riscos-syscall.h 1.1 -> 1.2 # arch/mips64/sgi-ip27/ip27-init.c 1.6 -> 1.7 arch/mips/sgi-ip27/ip27-init.c (moved) # arch/mips64/kernel/proc.c 1.3 -> 1.4 # arch/mips/arc/cmdline.c 1.3 -> 1.4 # drivers/pnp/manager.c 1.7 -> 1.9 # drivers/net/sungem.c 1.38 -> 1.39 # arch/mips64/defconfig-ip32 1.3 -> 1.4 # include/asm-mips/tx3912.h 1.2 -> 1.3 # arch/ia64/scripts/toolchain-flags 1.1 -> 1.2 # drivers/scsi/scsi_ioctl.c 1.18 -> 1.20 # drivers/media/common/saa7146_i2c.c 1.1 -> 1.3 # arch/mips/au1000/common/Makefile 1.8 -> 1.9 # arch/sparc64/mm/fault.c 1.15 -> 1.16 # include/asm-mips/spinlock.h 1.3 -> 1.4 # include/asm-mips64/mips-boards/atlasint.h 1.1 -> 1.2 # arch/s390/kernel/Makefile 1.18 -> 1.19 # arch/mips/kernel/pci_auto.c 1.1 -> (deleted) # arch/mips64/mips-boards/generic/reset.c 1.1 -> (deleted) # arch/mips/ddb5074/irq.c 1.2 -> 1.3 arch/mips/ddb5xxx/ddb5074/irq.c (moved) # include/asm-mips/ipcbuf.h 1.1 -> 1.2 # fs/xfs/xfs_inode.c 1.23 -> 1.28 # fs/xfs/xfs_iget.c 1.15 -> 1.16 # arch/mips/defconfig-ddb5476 1.9 -> 1.10 # include/asm-mips64/spinlock.h 1.2 -> 1.3 # drivers/net/wireless/netwave_cs.c 1.18 -> 1.19 # net/sctp/tsnmap.c 1.9 -> 1.11 # include/asm-mips64/bcache.h 1.2 -> 1.3 # include/linux/nfsd/nfsd.h 1.21 -> 1.22 # net/atm/clip.c 1.16 -> 1.17 # include/asm-mips64/bug.h 1.2 -> 1.3 # drivers/mtd/maps/Kconfig 1.6 -> 1.7 # arch/mips/boot/elf2ecoff.c 1.2 -> 1.3 # include/asm-mips/ipc.h 1.1 -> 1.2 # include/asm-x86_64/processor.h 1.17 -> 1.18 # kernel/kallsyms.c 1.10 -> 1.11 # include/asm-mips64/paccess.h 1.2 -> 1.3 # include/scsi/scsi_request.h 1.1 -> 1.3 # net/sctp/sm_statetable.c 1.17 -> 1.18 # drivers/media/dvb/dvb-core/dvb_ksyms.c 1.3 -> 1.5 # arch/mips64/mips-boards/atlas/atlas_int.c 1.4 -> (deleted) # include/asm-mips64/cache.h 1.3 -> 1.4 # arch/mips64/mips-boards/generic/display.c 1.1 -> (deleted) # net/ipv4/ip_output.c 1.38 -> 1.40 # arch/ppc/Kconfig 1.26 -> 1.28 # net/ipv4/igmp.c 1.26 -> 1.30 # include/linux/pnp.h 1.21 -> 1.22 # include/asm-s390/statfs.h 1.2 -> 1.3 # include/asm-mips64/pgtable.h 1.13 -> 1.14 # arch/sparc64/kernel/traps.c 1.25 -> 1.26 # include/asm-mips/topology.h 1.1 -> 1.2 # arch/mips64/math-emu/sp_frexp.c 1.1 -> (deleted) # kernel/workqueue.c 1.8 -> 1.9 # arch/mips64/arc/Makefile 1.6 -> (deleted) # drivers/net/wan/sdla_fr.c 1.27 -> 1.28 # arch/mips/kernel/gdb-stub.c 1.5 -> 1.6 # drivers/ieee1394/Makefile 1.18 -> 1.19 # arch/mips/ddb5xxx/common/pci.c 1.6 -> (deleted) # include/asm-mips64/types.h 1.3 -> 1.4 # include/asm-mips/sgi/sgimc.h 1.2 -> (deleted) # arch/sparc64/prom/init.c 1.1 -> 1.3 # arch/sh/Kconfig 1.14 -> 1.16 # net/bridge/br_if.c 1.17 -> 1.18 # drivers/serial/sunzilog.c 1.31 -> 1.32 # arch/ia64/kernel/init_task.c 1.9 -> 1.10 # include/asm-mips/stat.h 1.3 -> 1.4 # include/asm-mips64/errno.h 1.4 -> 1.5 # drivers/media/dvb/dvb-core/Makefile 1.4 -> 1.5 # arch/mips/defconfig-ip22 1.5 -> 1.6 # arch/mips/arc/salone.c 1.1 -> 1.2 # drivers/atm/fore200e.c 1.17 -> 1.18 # include/net/sctp/structs.h 1.66 -> 1.68 # drivers/mtd/maps/pb1xxx-flash.c 1.1 -> 1.2 # include/asm-ppc64/system.h 1.18 -> 1.19 # arch/i386/kernel/i386_ksyms.c 1.52 -> 1.53 # include/asm-mips64/module.h 1.2 -> 1.3 # arch/mips/math-emu/sp_tint.c 1.1 -> 1.2 # drivers/block/scsi_ioctl.c 1.29 -> 1.30 # drivers/ide/ide-tcq.c 1.5 -> 1.6 # arch/mips/arc/arc_con.c 1.2 -> 1.3 # arch/mips64/mips-boards/malta/malta_rtc.c 1.1 -> (deleted) # fs/nfsd/nfs4proc.c 1.13 -> 1.20 # kernel/printk.c 1.25 -> 1.26 # arch/ppc64/kernel/pci_dn.c 1.8 -> 1.10 # include/asm-ppc64/prom.h 1.7 -> 1.8 # include/asm-mips/watch.h 1.2 -> 1.3 # arch/mips/math-emu/sp_tlong.c 1.1 -> 1.2 # arch/mips64/sgi-ip32/ip32-pci.c 1.7 -> (deleted) # include/asm-s390/hardirq.h 1.9 -> 1.10 # net/ipv4/netfilter/ip_nat_irc.c 1.5 -> 1.6 # drivers/media/dvb/dvb-core/dvb_ringbuffer.h 1.1 -> 1.2 # include/asm-mips64/watch.h 1.2 -> 1.3 # arch/i386/kernel/apic.c 1.42 -> 1.43 # include/linux/loop.h 1.13 -> 1.15 # arch/ia64/sn/kernel/idle.c 1.1 -> 1.2 # drivers/media/dvb/frontends/stv0299.c 1.1 -> 1.3 # arch/mips64/kernel/r4k_tlb.S 1.2 -> (deleted) # net/ipv6/xfrm6_input.c 1.10 -> 1.11 # include/asm-ia64/thread_info.h 1.9 -> 1.10 # fs/xfs/xfs_log.c 1.16 -> 1.19 # drivers/media/dvb/dvb-core/dmxdev.h 1.3 -> 1.5 # arch/mips64/math-emu/dp_add.c 1.2 -> (deleted) # arch/mips64/math-emu/sp_div.c 1.2 -> (deleted) # drivers/ide/ide-cd.h 1.5 -> 1.6 # arch/mips/kernel/ptrace.c 1.9 -> 1.10 # drivers/pcmcia/i82092.c 1.22 -> 1.25 # include/asm-sparc/bug.h 1.3 -> 1.4 # arch/mips/philips/nino/rtc.c 1.1 -> (deleted) # include/asm-mips64/m48t35.h 1.2 -> 1.3 # arch/mips/lib/csum_partial_copy.c 1.3 -> 1.4 # include/asm-mips/serial.h 1.2 -> 1.3 # drivers/pci/hotplug/ibmphp_core.c 1.32 -> 1.33 # drivers/mtd/maps/edb7312.c 1.3 -> 1.4 # fs/xfs/xfs_vnodeops.c 1.28 -> 1.30 # drivers/media/dvb/dvb-core/dvb_filter.c 1.3 -> 1.5 # arch/mips/mips-boards/malta/malta_setup.c 1.2 -> 1.3 # arch/mips64/math-emu/ieee754dp.h 1.1 -> (deleted) # include/asm-mips/mc146818rtc.h 1.2 -> 1.3 # drivers/char/ip2main.c 1.38 -> 1.39 # arch/mips/defconfig-decstation 1.5 -> 1.6 # arch/mips64/sgi-ip22/ip22-hpc.c 1.2 -> (deleted) # arch/mips/lib/memset.S 1.2 -> 1.3 # include/asm-mips/sigcontext.h 1.1 -> 1.2 # arch/ppc64/kernel/pSeries_pci.c 1.24 -> 1.25 # drivers/mtd/nand/nand.c 1.3 -> 1.4 # fs/reiserfs/tail_conversion.c 1.24 -> 1.25 # arch/mips64/math-emu/dp_mul.c 1.2 -> (deleted) # arch/mips/baget/Makefile 1.7 -> 1.8 # net/sctp/socket.c 1.74.1.5 -> 1.83 # net/atm/common.c 1.31 -> 1.32 # drivers/scsi/sym53c8xx_2/sym_glue.c 1.23 -> 1.26 # arch/mips/kernel/irixelf.c 1.5 -> 1.6 # fs/xfs/linux/xfs_sysctl.c 1.10 -> 1.11 # drivers/s390/cio/css.h 1.2 -> 1.3 # (new) -> 1.1 arch/mips/lasat/ds1603.c # (new) -> 1.1 include/asm-mips/dec/kn05.h # (new) -> 1.1 arch/mips64/kernel/i8259.c # (new) -> 1.1 include/asm-mips64/thread_info.h # (new) -> 1.1 include/asm-mips64/traps.h # (new) -> 1.1 arch/mips/mm/cex-sb1.S # (new) -> 1.1 include/asm-mips/thread_info.h # (new) -> 1.1 include/asm-mips/mips-boards/bonito64.h # (new) -> 1.1 include/asm-mips64/kmap_types.h # (new) -> 1.1 include/asm-mips64/sibyte/trace_prof.h # (new) -> 1.1 arch/mips/pci/pci-auto.c # (new) -> 1.1 arch/mips/momentum/ocelot_g/int-handler.S # (new) -> 1.1 arch/mips/galileo-boards/ev96100/Makefile # (new) -> 1.1 arch/mips/pci/ops-ddb5074.c # (new) -> 1.1 arch/mips/mm/sc-rm7k.c # (new) -> 1.1 include/asm-mips64/sibyte/sb1250_mc.h # (new) -> 1.1 include/asm-mips/lasat/head.h # (new) -> 1.1 include/asm-mips64/dec/kn02ca.h # (new) -> 1.1 include/asm-mips64/sibyte/sb1250_syncser.h # (new) -> 1.1 include/asm-mips64/pgtable-bits.h # (new) -> 1.1 include/asm-mips/ddb5xxx/ddb5074.h # (new) -> 1.1 arch/mips/cobalt/reset.c # (new) -> 1.1 include/asm-mips/sibyte/sb1250_int.h # (new) -> 1.1 arch/mips/pci/Makefile # (new) -> 1.1 arch/mips64/mm/sc-ip22.c # (new) -> 1.1 drivers/scsi/NCR_Q720.h # (new) -> 1.1 arch/mips/lasat/setup.c # (new) -> 1.1 include/asm-mips/lasat/lasatint.h # (new) -> 1.1 arch/mips/defconfig-jmr3927 # (new) -> 1.1 drivers/s390/net/qeth.h # (new) -> 1.1 arch/mips/vr41xx/common/icu.c # (new) -> 1.1 include/asm-mips64/cacheflush.h # (new) -> 1.1 include/linux/dvb/version.h # (new) -> 1.1 arch/mips/kernel/module.c # (new) -> 1.1 arch/mips/cobalt/setup.c # (new) -> 1.3 arch/mips/Kconfig-shared # (new) -> 1.1 include/asm-mips/sibyte/sb1250_smbus.h # (new) -> 1.1 include/asm-mips64/sibyte/io.h # (new) -> 1.1 arch/mips/pci/pci-sni.c # (new) -> 1.2 drivers/media/dvb/frontends/cx24110.c # (new) -> 1.1 include/asm-mips/dec/rtc-dec.h # (new) -> 1.1 include/asm-mips/mips-boards/seadint.h # (new) -> 1.1 include/asm-mips/au1000_gpio.h # (new) -> 1.1 arch/mips/cobalt/via.c # (new) -> 1.1 include/asm-mips/vr41xx/tb0226.h # (new) -> 1.1 arch/mips/au1000/common/usbdev.c # (new) -> 1.1 arch/mips/au1000/pb1500/Makefile # (new) -> 1.1 include/asm-mips/sibyte/sb1250_dma.h # (new) -> 1.1 include/asm-mips/lasat/ds1603.h # (new) -> 1.1 arch/mips/pci/pci-mips.c # (new) -> 1.1 arch/mips64/mm/cache.c # (new) -> 1.1 include/linux/netfilter_arp/arpt_mangle.h # (new) -> 1.1 arch/mips/lasat/picvue_proc.c # (new) -> 1.1 arch/mips/mips-boards/sead/sead_setup.c # (new) -> 1.1 arch/mips/defconfig-cobalt # (new) -> 1.1 arch/mips/jmr3927/rbhma3100/int-handler.S # (new) -> 1.1 arch/mips/galileo-boards/ev64120/setup.c # (new) -> 1.1 arch/mips/sgi-ip22/ip22-hpc.c # (new) -> 1.1 arch/mips/ddb5xxx/ddb5477/lcd44780.h # (new) -> 1.1 arch/mips/momentum/ocelot_c/pci-irq.c # (new) -> 1.1 arch/mips/vr41xx/tanbac-tb0226/Makefile # (new) -> 1.1 arch/mips64/defconfig-sb1250-swarm # (new) -> 1.1 arch/mips/sgi-ip22/ip22-setup.c # (new) -> 1.1 arch/mips/galileo-boards/ev64120/README # (new) -> 1.1 include/asm-mips64/fpu_emulator.h # (new) -> 1.1 include/asm-mips64/mips-boards/bonito64.h # (new) -> 1.1 arch/mips/pci/ops-ddb5477.c # (new) -> 1.1 include/asm-mips64/sibyte/sb1250_mac.h # (new) -> 1.1 arch/mips/vr41xx/ibm-workpad/setup.c # (new) -> 1.1 include/asm-mips64/sibyte/sb1250_regs.h # (new) -> 1.1 include/asm-mips/sibyte/board.h # (new) -> 1.1 arch/mips/vr41xx/nec-eagle/ide-eagle.c # (new) -> 1.1 include/asm-mips/vr41xx/mpc30x.h # (new) -> 1.1 arch/mips/galileo-boards/ev64120/serialGT.c # (new) -> 1.1 arch/mips/vr41xx/common/giu.c # (new) -> 1.1 arch/mips/math-emu/dsemul.c # (new) -> 1.1 arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_pci_ops.c # (new) -> 1.1 arch/mips/sibyte/cfe/cfe_error.h # (new) -> 1.1 arch/mips/pci/fixup-ivr.c # (new) -> 1.1 arch/mips/momentum/ocelot_g/ocelot_pld.h # (new) -> 1.1 include/asm-mips/cobalt/cobalt.h # (new) -> 1.1 arch/mips/vr41xx/tanbac-tb0229/reboot.c # (new) -> 1.1 include/asm-mips/sibyte/swarm.h # (new) -> 1.1 arch/mips/pci/fixup-au1000.c # (new) -> 1.1 arch/mips/au1000/db1x00/init.c # (new) -> 1.1 include/asm-mips/pgtable-bits.h # (new) -> 1.1 arch/mips/lasat/image/Makefile # (new) -> 1.1 arch/mips/galileo-boards/ev96100/init.c # (new) -> 1.1 include/asm-mips/sgi/mc.h # (new) -> 1.2 net/ipv4/netfilter/ipt_recent.c # (new) -> 1.1 arch/mips/pci/pci-ddb5074.c # (new) -> 1.1 arch/mips/lasat/picvue.h # (new) -> 1.1 include/asm-mips/vr41xx/workpad.h # (new) -> 1.1 drivers/scsi/NCR_Q720.c # (new) -> 1.1 arch/mips/jmr3927/rbhma3100/init.c # (new) -> 1.1 arch/mips/dec/ecc-berr.c # (new) -> 1.1 arch/mips/sibyte/cfe/cfe_api.h # (new) -> 1.1 include/asm-mips64/sgi/ioc.h # (new) -> 1.1 arch/mips/momentum/ocelot_g/gt-irq.c # (new) -> 1.1 arch/mips/vr41xx/casio-e55/init.c # (new) -> 1.1 arch/mips/tx4927/common/tx4927_irq_handler.S # (new) -> 1.1 arch/mips/pci/ops-ddb5476.c # (new) -> 1.1 include/asm-mips64/dec/kn02xa.h # (new) -> 1.1 arch/mips64/defconfig-malta # (new) -> 1.1 arch/mips/galileo-boards/ev64120/Makefile # (new) -> 1.1 arch/mips/momentum/ocelot_c/int-handler.S # (new) -> 1.1 arch/mips/vr41xx/nec-eagle/setup.c # (new) -> 1.1 include/asm-mips64/dec/io.h # (new) -> 1.1 arch/mips64/kernel/pci-dma.c # (new) -> 1.1 include/asm-mips/i8259.h # (new) -> 1.1 arch/mips/lasat/image/romscript.normal # (new) -> 1.1 arch/mips/defconfig-pb1100 # (new) -> 1.1 include/asm-mips/vr41xx/e55.h # (new) -> 1.1 include/net/irda/au1000_ircc.h # (new) -> 1.1 arch/mips/sgi-ip22/Makefile # (new) -> 1.1 arch/mips/pci/pci-sb1250.c # (new) -> 1.1 arch/mips/sibyte/cfe/cfe_api_int.h # (new) -> 1.1 include/asm-mips/galileo-boards/ev96100.h # (new) -> 1.1 include/asm-mips64/irq_cpu.h # (new) -> 1.1 arch/mips/momentum/ocelot_c/setup.c # (new) -> 1.1 arch/mips/jmr3927/common/puts.c # (new) -> 1.1 include/asm-mips64/dec/tcinfo.h # (new) -> 1.1 arch/mips/sibyte/sb1250/setup.c # (new) -> 1.1 arch/mips/pci/ops-ev64120.c # (new) -> 1.1 arch/mips/pci/pci-ddb5476.c # (new) -> 1.1 include/asm-mips64/sgi/gio.h # (new) -> 1.1 include/asm-mips64/dec/kn02ba.h # (new) -> 1.1 arch/mips/sgi-ip22/ip22-time.c # (new) -> 1.1 arch/mips64/mm/cerr-sb1.c # (new) -> 1.1 include/asm-mips64/break.h # (new) -> 1.1 include/asm-mips64/dec/ecc.h # (new) -> 1.1 arch/mips/tx4927/common/Makefile # (new) -> 1.1 include/asm-mips64/sgi/ip22.h # (new) -> 1.1 arch/mips64/mm/tlb-andes.c # (new) -> 1.1 include/asm-mips64/tlbflush.h # (new) -> 1.1 arch/mips/vr41xx/tanbac-tb0226/init.c # (new) -> 1.1 arch/mips/momentum/ocelot_g/prom.c # (new) -> 1.1 arch/mips/sibyte/swarm/rtc_m41t81.c # (new) -> 1.1 arch/mips/defconfig-ev64120 # (new) -> 1.1 arch/mips/galileo-boards/ev64120/irq.c # (new) -> 1.1 include/asm-mips/rtc.h # (new) -> 1.1 include/asm-mips64/ip32/io.h # (new) -> 1.1 include/asm-mips64/dec/kn01.h # (new) -> 1.1 include/asm-mips/tx4927/tx4927_mips.h # (new) -> 1.1 include/asm-mips64/fpu.h # (new) -> 1.1 arch/mips64/mm/c-r4k.c # (new) -> 1.1 arch/i386/kernel/cpu/cpufreq/speedstep-lib.h # (new) -> 1.1 arch/mips/pci/fixup-eagle.c # (new) -> 1.1 include/asm-mips/db1x00.h # (new) -> 1.1 arch/mips/momentum/ocelot_g/Makefile # (new) -> 1.1 include/asm-mips64/sibyte/carmel.h # (new) -> 1.1 arch/mips/defconfig-eagle # (new) -> 1.1 include/asm-mips/vr41xx/vr41xx.h # (new) -> 1.1 arch/mips/sibyte/cfe/setup.c # (new) -> 1.1 arch/mips/sibyte/swarm/rtc_xicor1241.c # (new) -> 1.1 include/asm-mips/sibyte/sb1250_regs.h # (new) -> 1.1 arch/mips64/defconfig-atlas # (new) -> 1.1 arch/mips/galileo-boards/ev96100/puts.c # (new) -> 1.1 arch/mips/momentum/ocelot_g/dbg_io.c # (new) -> 1.1 arch/mips/vr41xx/tanbac-tb0226/setup.c # (new) -> 1.1 arch/mips/vr41xx/zao-capcella/setup.c # (new) -> 1.1 arch/mips64/mm/tlbex-r4k.S # (new) -> 1.1 arch/mips/mm/highmem.c # (new) -> 1.1 include/asm-mips64/dec/machtype.h # (new) -> 1.1 arch/mips/mm/tlb-r4k.c # (new) -> 1.1 include/asm-mips/jmr3927/txx927.h # (new) -> 1.1 include/asm-mips/vr41xx/tb0229.h # (new) -> 1.1 include/asm-mips/mips-boards/msc01_pci.h # (new) -> 1.1 arch/mips/sibyte/swarm/time.c # (new) -> 1.1 arch/mips/pci/ops-vrc4173.c # (new) -> 1.1 include/asm-mips64/sgi/hpc3.h # (new) -> 1.1 include/asm-mips64/exception.h # (new) -> 1.1 arch/mips/momentum/ocelot_c/reset.c # (new) -> 1.1 include/asm-mips64/dec/kn02.h # (new) -> 1.1 arch/mips/pci/ops-ev96100.c # (new) -> 1.1 arch/mips/momentum/ocelot_g/irq.c # (new) -> 1.1 arch/mips/momentum/ocelot_g/setup.c # (new) -> 1.1 drivers/pcmcia/au1000_pb1x00.c # (new) -> 1.1 include/asm-mips/ddb5xxx/ddb5476.h # (new) -> 1.1 arch/mips/tx4927/toshiba_rbtx4927/Makefile # (new) -> 1.1 arch/mips/defconfig-sead # (new) -> 1.1 arch/mips/lasat/lasatIRQ.S # (new) -> 1.1 drivers/net/meth.h # (new) -> 1.1 arch/mips/pci/ops-jmr3927.c # (new) -> 1.1 include/asm-mips/debug.h # (new) -> 1.1 include/asm-mips/dec/prom.h # (new) -> 1.1 arch/mips/sibyte/cfe/Makefile # (new) -> 1.1 arch/mips/au1000/pb1100/init.c # (new) -> 1.1 arch/mips/dec/prom/call_o32.S # (new) -> 1.1 arch/mips/vr41xx/casio-e55/setup.c # (new) -> 1.1 arch/mips/tx4927/common/tx4927_dbgio.c # (new) -> 1.1 include/asm-mips64/mips-boards/msc01_pci.h # (new) -> 1.1 arch/mips/galileo-boards/ev64120/reset.c # (new) -> 1.1 arch/mips/vr41xx/common/cmu.c # (new) -> 1.1 arch/mips/kernel/cpu-probe.c # (new) -> 1.1 include/asm-mips/fixmap.h # (new) -> 1.1 arch/mips/defconfig-tb0229 # (new) -> 1.1 arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c # (new) -> 1.1 arch/mips/sgi-ip22/ip22-irq.S # (new) -> 1.1 include/asm-mips64/smplock.h # (new) -> 1.1 drivers/i2c/i2c-prosavage.c # (new) -> 1.1 arch/mips/sgi-ip22/ip22-rtc.c # (new) -> 1.1 arch/mips/mm/pg-r4k.S # (new) -> 1.1 arch/mips64/kernel/binfmt_elfo32.c # (new) -> 1.1 arch/mips/lasat/sysctl.h # (new) -> 1.1 include/asm-mips64/dec/ioasic_ints.h # (new) -> 1.1 arch/mips64/mm/pgtable.c # (new) -> 1.1 include/asm-mips64/dec/prom.h # (new) -> 1.1 include/asm-mips64/sections.h # (new) -> 1.1 arch/mips/sibyte/swarm/cmdline.c # (new) -> 1.1 arch/mips/pci/fixups-ev96100.c # (new) -> 1.1 include/asm-mips/fpu.h # (new) -> 1.1 include/asm-mips/mv64340_dep.h # (new) -> 1.1 include/asm-mips/traps.h # (new) -> 1.1 arch/mips/pci/fixup-capcella.c # (new) -> 1.1 arch/mips/mm/pgtable.c # (new) -> 1.1 include/asm-mips/jmr3927/ds1742rtc.h # (new) -> 1.1 arch/mips/vr41xx/zao-capcella/ide-capcella.c # (new) -> 1.1 arch/mips/tx4927/common/tx4927_prom.c # (new) -> 1.1 arch/mips/sibyte/swarm/Makefile # (new) -> 1.1 arch/mips/mm/cache.c # (new) -> 1.1 arch/mips/vr41xx/common/serial.c # (new) -> 1.1 include/asm-mips64/dec/tc.h # (new) -> 1.1 arch/mips/tx4927/common/tx4927_setup.c # (new) -> 1.1 arch/mips/au1000/db1x00/setup.c # (new) -> 1.1 include/asm-mips/sgi/ioc.h # (new) -> 1.1 arch/mips/lasat/reset.c # (new) -> 1.1 arch/mips64/defconfig-decstation # (new) -> 1.1 arch/mips/pci/pci-vr41xx.c # (new) -> 1.1 arch/mips/sgi-ip22/ip22-eisa.c # (new) -> 1.1 include/asm-mips/sgi/hpc3.h # (new) -> 1.1 include/asm-mips/keyboard.h # (new) -> 1.1 include/asm-mips64/ip32/mace.h # (new) -> 1.1 arch/mips/sibyte/sb1250/bcm1250_tbprof.c # (new) -> 1.1 arch/mips/sgi-ip22/ip22-mc.c # (new) -> 1.1 include/asm-mips64/i8259.h # (new) -> 1.1 arch/mips/vr41xx/nec-eagle/init.c # (new) -> 1.1 include/asm-mips/au1000_pcmcia.h # (new) -> 1.1 arch/mips/defconfig-lasat200 # (new) -> 1.1 include/asm-mips64/dec/rtc-dec.h # (new) -> 1.1 arch/mips/jmr3927/rbhma3100/irq.c # (new) -> 1.1 arch/mips/defconfig-capcella # (new) -> 1.1 include/asm-mips64/dec/kn05.h # (new) -> 1.1 arch/mips/sibyte/swarm/dbg_io.c # (new) -> 1.1 include/asm-mips/irq_cpu.h # (new) -> 1.1 arch/mips/mips-boards/sead/sead_time.c # (new) -> 1.1 include/asm-mips/sibyte/64bit.h # (new) -> 1.1 include/asm-mips64/sibyte/sb1250_int.h # (new) -> 1.1 arch/mips/pci/pci-ddb5477.c # (new) -> 1.1 include/asm-mips64/tlbdebug.h # (new) -> 1.1 drivers/char/lcd.c # (new) -> 1.1 include/asm-mips/jmr3927/pci.h # (new) -> 1.1 arch/mips64/mm/pg-sb1.c # (new) -> 1.1 arch/mips64/mm/sc-rm7k.c # (new) -> 1.1 include/asm-mips64/suspend.h # (new) -> 1.1 arch/mips/vr41xx/nec-eagle/irq.c # (new) -> 1.1 arch/mips64/kernel/irq.c # (new) -> 1.1 arch/mips/au1000/common/rtc.c # (new) -> 1.1 arch/mips/mm/pg-r3k.c # (new) -> 1.1 arch/mips/sibyte/sb1250/bus_watcher.c # (new) -> 1.1 include/asm-mips64/dec/tcmodule.h # (new) -> 1.1 arch/mips/sibyte/sb1250/irq_handler.S # (new) -> 1.1 include/asm-mips64/sibyte/sb1250_scd.h # (new) -> 1.1 arch/mips64/mm/sc-r5k.c # (new) -> 1.1 include/asm-mips/smplock.h # (new) -> 1.1 drivers/s390/net/qeth_mpc.h # (new) -> 1.1 arch/mips/defconfig-e55 # (new) -> 1.1 include/asm-mips/pb1500.h # (new) -> 1.1 include/asm-mips/sgi/gio.h # (new) -> 1.1 arch/mips/mm/c-sb1.c # (new) -> 1.1 include/asm-mips/mips-boards/sead.h # (new) -> 1.1 arch/mips/defconfig-pb1500 # (new) -> 1.1 arch/mips/sibyte/sb1250/smp.c # (new) -> 1.1 arch/mips/sibyte/swarm/setup.c # (new) -> 1.1 include/asm-mips/sibyte/sb1250_l2c.h # (new) -> 1.1 arch/mips/sgi-ip22/ip22-int.c # (new) -> 1.1 include/asm-mips/percpu.h # (new) -> 1.1 arch/mips/pci/pci-ocelot-g.c # (new) -> 1.1 arch/mips/sgi-ip22/ip22-berr.c # (new) -> 1.1 arch/mips/lasat/lasat_models.h # (new) -> 1.1 arch/mips/vr41xx/casio-e55/ide-e55.c # (new) -> 1.1 arch/mips/galileo-boards/ev96100/time.c # (new) -> 1.1 arch/mips64/mm/cex-sb1.S # (new) -> 1.1 include/asm-mips64/cacheops.h # (new) -> 1.1 arch/mips/lasat/picvue.c # (new) -> 1.1 arch/mips/vr41xx/common/Makefile # (new) -> 1.1 arch/mips/sibyte/sb1250/Makefile # (new) -> 1.1 drivers/media/dvb/dvb-core/dvb_functions.h # (new) -> 1.1 arch/mips/momentum/ocelot_c/prom.c # (new) -> 1.1 arch/mips/galileo-boards/ev96100/int-handler.S # (new) -> 1.1 include/asm-mips/pb1000.h # (new) -> 1.1 include/asm-mips/jmr3927/jmr3927.h # (new) -> 1.1 include/asm-mips/dec/ecc.h # (new) -> 1.1 arch/mips/au1000/pb1100/Makefile # (new) -> 1.1 include/asm-mips/au1000_usbdev.h # (new) -> 1.1 arch/mips/defconfig-sb1250-swarm # (new) -> 1.1 arch/mips/kernel/irq_cpu.c # (new) -> 1.1 arch/mips/jmr3927/common/rtc_ds1742.c # (new) -> 1.1 include/linux/netfilter_ipv4/ipt_recent.h # (new) -> 1.1 arch/mips/au1000/common/clocks.c # (new) -> 1.1 arch/mips/vr41xx/tanbac-tb0229/init.c # (new) -> 1.1 include/asm-mips64/sibyte/sb1250_ldt.h # (new) -> 1.1 include/asm-mips64/reboot.h # (new) -> 1.1 include/asm-mips64/sibyte/sb1250_dma.h # (new) -> 1.1 arch/mips/mm/sc-r5k.c # (new) -> 1.1 arch/mips/momentum/ocelot_g/gt64240_dep.h # (new) -> 1.1 arch/mips/defconfig-workpad # (new) -> 1.1 arch/mips/galileo-boards/ev64120/promcon.c # (new) -> 1.1 include/asm-mips64/percpu.h # (new) -> 1.1 arch/mips/vr41xx/ibm-workpad/ide-workpad.c # (new) -> 1.1 arch/mips/sibyte/sb1250/time.c # (new) -> 1.1 arch/mips64/mm/tlb-dbg-r4k.c # (new) -> 1.1 arch/mips/pci/common.c # (new) -> 1.1 arch/mips64/kernel/time.c # (new) -> 1.1 arch/mips/lasat/Makefile # (new) -> 1.1 arch/mips/ddb5xxx/ddb5477/lcd44780.c # (new) -> 1.1 include/asm-mips/sibyte/sb1250_syncser.h # (new) -> 1.1 include/asm-mips64/wbflush.h # (new) -> 1.1 arch/mips/lib/promlib.c # (new) -> 1.1 arch/mips/lasat/prom.c # (new) -> 1.1 arch/mips/vr41xx/tanbac-tb0229/setup.c # (new) -> 1.1 arch/mips/pci/fixup-ite8172g.c # (new) -> 1.1 arch/mips64/mm/c-sb1.c # (new) -> 1.1 drivers/pcmcia/au1000_generic.c # (new) -> 1.1 arch/mips64/kernel/irq_cpu.c # (new) -> 1.1 arch/mips/cobalt/promcon.c # (new) -> 1.1 arch/mips/pci/fixup-ocelot.c # (new) -> 1.1 arch/mips64/kernel/binfmt_elfn32.c # (new) -> 1.1 arch/mips/jmr3927/common/prom.c # (new) -> 1.1 arch/mips/jmr3927/rbhma3100/Makefile # (new) -> 1.1 include/asm-mips64/dec/kn230.h # (new) -> 1.1 include/asm-mips/sibyte/carmel.h # (new) -> 1.1 drivers/s390/net/qeth_mpc.c # (new) -> 1.1 arch/mips/vr41xx/zao-capcella/Makefile # (new) -> 1.1 arch/mips/pci/pci.c # (new) -> 1.1 include/asm-mips64/rtc.h # (new) -> 1.1 arch/mips/lasat/interrupt.c # (new) -> 1.1 arch/mips/momentum/ocelot_g/reset.c # (new) -> 1.1 arch/mips/pci/pci-vr41xx.h # (new) -> 1.1 include/asm-mips64/dec/kn03.h # (new) -> 1.1 arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c # (new) -> 1.1 arch/mips/pci/fixup-tb0229.c # (new) -> 1.1 arch/mips/sgi-ip22/ip22-nvram.c # (new) -> 1.1 arch/mips/mm/sc-ip22.c # (new) -> 1.1 arch/mips/mm/tlbex-r3k.S # (new) -> 1.1 include/asm-mips/jmr3927/tx3927.h # (new) -> 1.1 arch/mips/au1000/pb1500/init.c # (new) -> 1.1 arch/mips/lasat/image/head.S # (new) -> 1.1 arch/mips/galileo-boards/ev96100/setup.c # (new) -> 1.1 arch/mips/cobalt/irq.c # (new) -> 1.1 arch/mips/math-emu/dsemul.h # (new) -> 1.1 drivers/pci/hotplug/fakephp.c # (new) -> 1.1 include/asm-mips64/sibyte/sb1250_smbus.h # (new) -> 1.1 arch/mips/momentum/ocelot_c/mv-irq.c # (new) -> 1.1 arch/mips/vr41xx/tanbac-tb0229/Makefile # (new) -> 1.1 include/asm-mips/sibyte/trace_prof.h # (new) -> 1.1 include/asm-mips64/vga.h # (new) -> 1.1 arch/mips/vr41xx/victor-mpc30x/ide-mpc30x.c # (new) -> 1.1 arch/mips/jmr3927/rbhma3100/kgdb_io.c # (new) -> 1.1 include/asm-mips/vr41xx/eagle.h # (new) -> 1.1 arch/mips64/kernel/module.c # (new) -> 1.1 arch/mips/ramdisk/Makefile # (new) -> 1.1 include/asm-mips64/war.h # (new) -> 1.1 arch/mips/sibyte/cfe/cfe_api.c # (new) -> 1.1 arch/mips/defconfig-ev96100 # (new) -> 1.1 include/asm-mips/galileo-boards/gt96100.h # (new) -> 1.1 arch/mips/vr41xx/common/vrc4173.c # (new) -> 1.1 include/asm-mips/suspend.h # (new) -> 1.1 include/asm-mips/jmr3927/irq.h # (new) -> 1.1 arch/mips/pci/pci-ocelot-c.c # (new) -> 1.1 include/asm-mips64/dec/ioasic.h # (new) -> 1.1 arch/mips/vr41xx/victor-mpc30x/setup.c # (new) -> 1.1 arch/mips/au1000/pb1500/setup.c # (new) -> 1.1 include/scsi/scsi_driver.h # (new) -> 1.1 net/ipv4/netfilter/arpt_mangle.c # (new) -> 1.1 arch/mips/galileo-boards/generic/Makefile # (new) -> 1.1 arch/mips/pci/fixup-tb0226.c # (new) -> 1.1 include/asm-mips/sibyte/sb1250_scd.h # (new) -> 1.1 include/asm-mips/galileo-boards/ev64120.h # (new) -> 1.1 arch/mips/pci/pci-lasat.c # (new) -> 1.1 include/asm-mips/highmem.h # (new) -> 1.1 arch/mips/momentum/ocelot_g/pci-irq.c # (new) -> 1.1 include/asm-mips/sibyte/sb1250_defs.h # (new) -> 1.1 arch/mips64/lib/promlib.c # (new) -> 1.1 arch/mips/jmr3927/rbhma3100/rtc.c # (new) -> 1.1 arch/mips/vr41xx/victor-mpc30x/Makefile # (new) -> 1.1 arch/mips64/kernel/reset.c # (new) -> 1.1 arch/mips/au1000/db1x00/Makefile # (new) -> 1.1 arch/mips/sibyte/cfe/console.c # (new) -> 1.1 include/asm-mips/break.h # (new) -> 1.1 arch/mips/sibyte/sb1250/prom.c # (new) -> 1.1 arch/mips64/kernel/cpu-probe.c # (new) -> 1.1 arch/mips/lasat/sysctl.c # (new) -> 1.1 include/asm-mips64/ip32/crime.h # (new) -> 1.1 include/asm-mips/sibyte/sentosa.h # (new) -> 1.1 include/asm-mips/pb1100.h # (new) -> 1.1 arch/mips/pci/pci-hplj.c # (new) -> 1.1 include/asm-mips/sibyte/sb1250.h # (new) -> 1.1 arch/mips/kernel/offset.c # (new) -> 1.1 arch/mips/mm/cerr-sb1.c # (new) -> 1.1 include/asm-mips/cacheflush.h # (new) -> 1.1 include/asm-mips/mv64340.h # (new) -> 1.1 arch/mips/jmr3927/common/Makefile # (new) -> 1.1 include/asm-mips64/sibyte/board.h # (new) -> 1.1 include/asm-mips64/sibyte/sb1250_l2c.h # (new) -> 1.1 arch/mips/mm/c-r3k.c # (new) -> 1.1 include/asm-mips/lasat/eeprom.h # (new) -> 1.1 arch/mips/momentum/ocelot_c/dbg_io.c # (new) -> 1.1 arch/mips/sibyte/swarm/rtc.c # (new) -> 1.1 include/asm-mips/sibyte/sb1250_mc.h # (new) -> 1.1 include/asm-mips64/keyboard.h # (new) -> 1.1 arch/mips/momentum/ocelot_c/ocelot_c_fpga.h # (new) -> 1.1 arch/mips/vr41xx/nec-eagle/Makefile # (new) -> 1.1 arch/mips64/kernel/offset.c # (new) -> 1.1 drivers/net/meth.c # (new) -> 1.1 include/asm-mips64/ip32/machine.h # (new) -> 1.1 arch/mips/momentum/ocelot_g/gt64240.h # (new) -> 1.1 arch/mips/vr41xx/ibm-workpad/Makefile # (new) -> 1.1 include/asm-mips/sibyte/sb1250_mac.h # (new) -> 1.1 arch/mips/sibyte/cfe/smp.c # (new) -> 1.1 arch/mips/pci/ops-it8172.c # (new) -> 1.1 include/asm-mips/lasat/lasat.h # (new) -> 1.1 include/asm-mips/tx4927/tx4927.h # (new) -> 1.2 drivers/media/dvb/dvb-core/dvb_functions.c # (new) -> 1.1 arch/mips/momentum/ocelot_c/irq.c # (new) -> 1.1 arch/mips/vr41xx/ibm-workpad/init.c # (new) -> 1.1 arch/mips/pci/pci-ip32.c # (new) -> 1.1 drivers/i2c/busses/i2c-ali1535.c # (new) -> 1.1 arch/mips/galileo-boards/ev64120/dma.c # (new) -> 1.1 arch/mips/pci/ops-ocelot.c # (new) -> 1.1 arch/mips/vr41xx/common/time.c # (new) -> 1.1 arch/mips/mips-boards/sead/sead_int.c # (new) -> 1.1 include/asm-mips/softirq.h # (new) -> 1.1 drivers/net/irda/au1k_ir.c # (new) -> 1.1 arch/mips/lasat/ds1603.h # (new) -> 1.1 arch/mips/sgi-ip32/ip32-reset.c # (new) -> 1.1 include/asm-mips/au1000_dma.h # (new) -> 1.1 include/asm-mips64/sibyte/64bit.h # (new) -> 1.1 arch/mips/sgi-ip22/ip22-ksyms.c # (new) -> 1.1 include/asm-mips/kmap_types.h # (new) -> 1.1 include/asm-mips64/ip32/ip32_ints.h # (new) -> 1.1 arch/mips/cobalt/Makefile # (new) -> 1.1 arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c # (new) -> 1.1 arch/mips/galileo-boards/ev64120/irq-handler.c # (new) -> 1.1 arch/mips/defconfig-mpc30x # (new) -> 1.1 arch/mips64/defconfig-sead # (new) -> 1.2 arch/i386/kernel/cpu/cpufreq/speedstep-lib.c # (new) -> 1.1 arch/mips/vr41xx/zao-capcella/init.c # (new) -> 1.1 include/asm-mips64/dec/interrupts.h # (new) -> 1.1 include/asm-mips/sibyte/sb1250_ldt.h # (new) -> 1.1 include/asm-mips64/mips-boards/seadint.h # (new) -> 1.1 include/asm-mips64/sibyte/sentosa.h # (new) -> 1.1 include/asm-mips64/softirq.h # (new) -> 1.1 arch/mips/vr41xx/common/bcu.c # (new) -> 1.1 arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_pci_fixup.c # (new) -> 1.1 include/asm-mips64/mv64340.h # (new) -> 1.1 arch/mips/galileo-boards/generic/reset.c # (new) -> 1.1 arch/mips64/mm/tlb-glue-r4k.S # (new) -> 1.1 arch/mips64/mm/tlb-r4k.c # (new) -> 1.1 include/asm-mips64/mv64340_dep.h # (new) -> 1.1 include/asm-mips/vr41xx/vrc4173.h # (new) -> 1.1 arch/mips/galileo-boards/ev96100/irq.c # (new) -> 1.1 arch/mips/jmr3927/rbhma3100/setup.c # (new) -> 1.1 include/asm-mips64/sibyte/sb1250.h # (new) -> 1.1 arch/mips/lasat/prom.h # (new) -> 1.1 arch/mips/dec/kn02-irq.c # (new) -> 1.1 include/asm-mips/tx4927/tx4927_pci.h # (new) -> 1.1 arch/mips/sgi-ip22/ip22-reset.c # (new) -> 1.1 arch/mips/sibyte/sb1250/irq.c # (new) -> 1.1 include/asm-mips/sibyte/sb1250_uart.h # (new) -> 1.1 include/asm-mips/galileo-boards/ev64120int.h # (new) -> 1.1 arch/mips/pci/pci-cobalt.c # (new) -> 1.1 arch/mips/mm/tlbex-r4k.S # (new) -> 1.1 include/asm-mips/tlbdebug.h # (new) -> 1.1 arch/mips/cobalt/int-handler.S # (new) -> 1.1 include/asm-mips/dec/kn02ca.h # (new) -> 1.1 arch/mips/momentum/ocelot_c/cpci-irq.c # (new) -> 1.1 include/asm-mips/tx4927/toshiba_rbtx4927.h # (new) -> 1.1 arch/mips/au1000/common/dma.c # (new) -> 1.1 include/asm-mips/galileo-boards/ev96100int.h # (new) -> 1.1 arch/mips/au1000/common/power.c # (new) -> 1.1 arch/mips/momentum/ocelot_c/Makefile # (new) -> 1.1 arch/mips/dec/ioasic-irq.c # (new) -> 1.1 include/asm-mips/dec/kn230.h # (new) -> 1.1 arch/mips/mips-boards/sead/Makefile # (new) -> 1.1 include/asm-mips/sibyte/sb1250_genbus.h # (new) -> 1.1 arch/mips/mm/c-r4k.c # (new) -> 1.1 arch/mips/lasat/at93c.h # (new) -> 1.1 arch/mips/lasat/lasat_board.c # (new) -> 1.1 include/asm-mips64/sibyte/sb1250_uart.h # (new) -> 1.1 include/asm-mips64/gdb-stub.h # (new) -> 1.1 include/asm-mips64/gt64120.h # (new) -> 1.1 arch/mips/pci/fixup-jmr3927.c # (new) -> 1.1 arch/mips/pci/ops-au1000.c # (new) -> 1.1 arch/mips/arc/promlib.c # (new) -> 1.1 arch/mips/defconfig-tb0226 # (new) -> 1.1 include/asm-mips64/dec/ioasic_addrs.h # (new) -> 1.1 arch/mips64/kernel/scall_n32.S # (new) -> 1.1 arch/mips/vr41xx/common/int-handler.S # (new) -> 1.1 arch/mips/tx4927/common/tx4927_irq.c # (new) -> 1.1 include/asm-mips64/sgi/mc.h # (new) -> 1.1 arch/mips/momentum/ocelot_c/uart-irq.c # (new) -> 1.1 include/asm-mips/vr41xx/capcella.h # (new) -> 1.1 arch/mips/mm/tlb-r3k.c # (new) -> 1.1 arch/mips/lasat/at93c.c # (new) -> 1.1 include/asm-mips64/sibyte/sb1250_genbus.h # (new) -> 1.1 arch/mips64/mm/tlb-glue-sb1.S # (new) -> 1.1 include/asm-mips/dec/kn02ba.h # (new) -> 1.1 include/asm-mips64/time.h # (new) -> 1.1 arch/mips/galileo-boards/ev64120/int-handler.S # (new) -> 1.1 include/asm-mips/lasat/serial.h # (new) -> 1.1 arch/mips/pci/pci-ip27.c # (new) -> 1.1 arch/mips/vr41xx/common/reset.c # (new) -> 1.1 include/asm-mips/war.h # (new) -> 1.1 arch/mips/au1000/pb1100/setup.c # (new) -> 1.1 include/asm-mips64/mips-boards/sead.h # (new) -> 1.1 arch/mips/mm/tlb-sb1.c # (new) -> 1.1 arch/mips/ramdisk/ld.script # (new) -> 1.1 include/asm-mips/lasat/picvue.h # (new) -> 1.1 arch/mips/vr41xx/casio-e55/Makefile # (new) -> 1.1 arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c # (new) -> 1.1 arch/mips/galileo-boards/ev64120/i2o.c # (new) -> 1.1 arch/mips/pci/fixup-victor-mpc30x.c # (new) -> 1.1 include/asm-mips/sgi/ip22.h # (new) -> 1.1 arch/mips/mm/c-tx39.c # (new) -> 1.1 include/asm-mips/sections.h # (new) -> 1.1 arch/mips64/mm/pg-r4k.c # (new) -> 1.1 arch/mips64/mm/tlb-sb1.c # (new) -> 1.1 drivers/s390/net/qeth.c # (new) -> 1.1 include/asm-mips64/sibyte/sb1250_defs.h # (new) -> 1.1 include/asm-mips/tlbflush.h # (new) -> 1.1 arch/mips/vr41xx/victor-mpc30x/init.c # (new) -> 1.1 include/asm-mips64/sibyte/swarm.h # (new) -> 1.1 arch/mips/mm/pg-sb1.c # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 03/06/22 torvalds@home.transmeta.com 1.1310.58.4 # Linux 2.5.73 # -------------------------------------------- # 03/06/23 paulus@samba.org 1.1310.58.5 # Merge samba.org:/stuff/paulus/kernel/linux-2.5 # into samba.org:/stuff/paulus/kernel/for-linus-ppc # -------------------------------------------- # 03/06/22 akpm@digeo.com 1.1310.59.1 # [PATCH] __devinitdata declarations should not be marked const. # # There are some bad compiler issues with section confusion ("const" stuff # likes going into the rodata section). # -------------------------------------------- # 03/06/22 Andries.Brouwer@cwi.nl 1.1310.59.2 # [PATCH] loop.c cleanups # # This does the following: # - remove trailing spaces # - make loop.h independent by including bio.h, blk.h, spinlock.h # - replace the lock/unlock functions by module_get/module_put; # in struct loop this is the change # - void (*lock)(struct loop_device *); # - void (*unlock)(struct loop_device *); # + struct module *owner; # - replace the integer lo_encrypt_type by the pointer lo_encryption; # there was a race with loop_unregister_transfer # - fixed an off-by-one in loop_register_transfer # # This is Step 1 of a series of half a dozen or so. # # Half of the above is from Jari. Anything that is wrong is mine. # -------------------------------------------- # 03/06/22 ldl@aros.net 1.1310.59.3 # [PATCH] fix nbd driver for 2.5 block layer # # This makes NBD work with the new linux 2.5 block layer design. # Specifically, it fixes memory corruption that results from module # removal and possible memory corruption from sending or receiving disk # data from the server. # # It essentially rolls together the changes from two of the last patchlets # that I emailed: the fix for module removal & the fix for incorrect # struct bio usage. I believe it's wisest to roll these both together # into this one patch since they both deal with making NBD work better # with the 2.5 linux block layer design and without either of which, it's # possible that NBD will corrupt memory. # # Other changes I'd like to see introduced (like in the earlier jumbo # patch) meanwhile are feature enhancements so they can wait. This patch # also should address all the very helpful concerns that have been raised # so far. Particularly: # # 1. that the very first submitted NBD patch was broken down [Andrew] # 2. that only 1 spinlock is used for all the NBD request_queue structures # used [Jens,Al] # 3. that kmap() is used in case of highmem pages [Jens] # 4. that the allocation of request_queue is dynamic and seperate from # other allocated objects [Al] # -------------------------------------------- # 03/06/22 davem@nuts.ninka.net 1.1310.60.1 # [SPARC64]: Update struct compat_statfs. # -------------------------------------------- # 03/06/22 davem@nuts.ninka.net 1.1310.60.2 # [SPARC64]: Update solaris compat layer for vfs_statfs() changes. # -------------------------------------------- # 03/06/22 davem@nuts.ninka.net 1.1310.60.3 # [SPARC]: Update for show_stack() changes. # -------------------------------------------- # 03/06/22 davem@nuts.ninka.net 1.1310.60.4 # [SPARC]: Add {f,}statfs64 syscall entries. # -------------------------------------------- # 03/06/22 davem@kernel.bkbits.net 1.1310.59.4 # Merge davem@nuts.ninka.net:/home/davem/src/BK/sparc-2.5 # into kernel.bkbits.net:/home/davem/sparc-2.5 # -------------------------------------------- # 03/06/22 rusty@rustcorp.com.au 1.1310.59.5 # [PATCH] Workqueue Exit Neatening # # Jeff Garzik points out the initializing the exit completion at # exit time is foolish: we should just initialize it at creation time # live everything else in that structure, and avoid the memory barrier. # -------------------------------------------- # 03/06/23 rmk@flint.arm.linux.org.uk 1.1310.43.26 # [PCMCIA] Fix ide-cs driver name (for PCMCIA binding) # # Problem noticed by Eivind Tagseth. # # We seem to have resurected the "ide_cs" driver name for the ide-cs module. # Restore the driver name to "ide-cs". # -------------------------------------------- # 03/06/23 dwmw2@infradead.org 1.1310.59.6 # MTD driver cleanups... # # - Fix AFS partitioning oops when no partitions are found # - Add missing spin_unlock, optimise buffer writes in Intel NOR driver # - Fix DiskOnChip Millennium Plus register OutputControl register definition # - Fix DiskOnChip drivers to indicate correct ECC type # - Fix map drivers to use ARRAY_SIZE instead of redefining it. # - Make uCLinux map driver depend on !MMU # - Fix NAND write verify problem on some chips # - Other trivia from Rusty. # -------------------------------------------- # 03/06/23 dwmw2@infradead.org 1.1310.59.7 # Replace mtd_blktrans ->ioctl() method with ->getgeo() and ->flush() # # ... and also fix the embarrassing bug where NFTL and INFTL will # barf and exit if the add_mtd_blktrans_dev() function _exists_, # rather than actually calling it and barfing if it returns non-zero :) # -------------------------------------------- # 03/06/23 dwmw2@infradead.org 1.1310.59.8 # Trivia: use JFFS2 PAD() macro instead of masking manually. # -------------------------------------------- # 03/06/23 dwmw2@infradead.org 1.1310.59.9 # Fix jffs2_statfs w.r.t. statfs64 # -------------------------------------------- # 03/06/23 dwmw2@infradead.org 1.1310.59.10 # Remove superfluous debugging in mtd_blkdevs.c # -------------------------------------------- # 03/06/23 jgrimm@touki.austin.ibm.com 1.1305.18.1 # Merge touki.austin.ibm.com:/home/jgrimm/bk/linux-2.5 # into touki.austin.ibm.com:/home/jgrimm/bk/lksctp-2.5.work # -------------------------------------------- # 03/06/24 anton@samba.org 1.1315.1.2 # Merge samba.org:/scratch/anton/linux-2.5 # into samba.org:/scratch/anton/tmp3 # -------------------------------------------- # 03/06/24 anton@samba.org 1.1318 # Merge bk://ppc.bkbits.net/for-linus-ppc64 # into samba.org:/scratch/anton/tmp3 # -------------------------------------------- # 03/06/23 greg@kroah.com 1.1310.61.1 # Merge kroah.com:/home/greg/linux/BK/bleed-2.5 # into kroah.com:/home/greg/linux/BK/gregkh-2.5 # -------------------------------------------- # 03/06/23 ink@jurassic.park.msu.ru 1.1310.62.1 # [PATCH] PCI: fix non-hotplug build # # Current BK won't build when CONFIG_HOTPLUG is not set due to # undefined references to pci_destroy_dev in hotplug.c. # I think it makes sense to not compile hotplug.c in this case at all. # Also, this allows to get rid of several function which are unused # in non-hotplug kernel. # # Tested on Alpha. # -------------------------------------------- # 03/06/23 ink@jurassic.park.msu.ru 1.1310.62.2 # [PATCH] PCI: fix alpha for reimplement pci proc name # # On Fri, Jun 20, 2003 at 02:24:13PM -0700, Greg KH wrote: # > Thanks, I've reverted your previous patch, and fixed the one typo in # > this patch and applied it all to my bk tree. Hopefully Linus will pull # > from it sometime soon :) # # Argh, where were my eyes... There was another typo which broke Alpha. # -------------------------------------------- # 03/06/23 jes@wildopensource.com 1.1310.24.20 # [PATCH] ia64: fix static initializers # # No need to explicitly zero out global variables. # -------------------------------------------- # 03/06/23 lord@sgi.com 1.1310.1.64 # [PATCH] Fix XFS proc interface initializers # # [XFS] the intializers for the /proc interface to xfs got out of order, # and we are syncing 1000 times faster than we are supposed to! # # SGI Modid: 2.5.x-xfs:slinx:151712a # -------------------------------------------- # 03/06/23 torvalds@home.transmeta.com 1.1310.1.65 # Merge home.transmeta.com:/home/torvalds/v2.5/xfs # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/06/23 ralf@linux-mips.org 1.1310.1.66 # [PATCH] MIPS merge, generic mips bits. # # This contains all the generic 32-bit MIPS code, so all arch/mips/ and # include/asm-mips/ stuff. # -------------------------------------------- # 03/06/23 ralf@linux-mips.org 1.1310.1.67 # [PATCH] MIPS merge, generic mips64 bits. # # This updates the generic mips64 code. # -------------------------------------------- # 03/06/23 ralf@linux-mips.org 1.1310.1.68 # [PATCH] SGI IP22 bits # # An update for the Indy aka IP22 support. Consolidates the 32-bit and # 64-bit copies of the support code into one directory, so in total this # patch deletes quite a bit of code. # -------------------------------------------- # 03/06/23 ralf@linux-mips.org 1.1310.1.69 # [PATCH] PCI code # # This is the entire MIPS PCI code which I'm consolidating in arch/mips/pci/. # Applying this patch will result in some code duplication; the remaining # patches I'm about to send will clean that. # -------------------------------------------- # 03/06/23 ralf@linux-mips.org 1.1310.1.70 # [PATCH] 2.7.73 SGI IP27 update # # An update of the SGI IP27 aka Origin 200/2000/Onyx 2 support. # -------------------------------------------- # 03/06/23 ralf@linux-mips.org 1.1310.1.71 # [PATCH] Code for Galileo boards # # The support code for two more Galileo evaluation boards. # # (Evil stuff, just to get your tree in sync again. I've got a cleanup in # my work tree). # -------------------------------------------- # 03/06/23 ralf@linux-mips.org 1.1310.1.72 # [PATCH] Sibyte updates # # Update the code for the BCM1250 and evaluation platforms. # -------------------------------------------- # 03/06/23 ralf@linux-mips.org 1.1310.1.73 # [PATCH] Alchemy update # # This is an update of the AMD Alchemy support for 2.5. # # (This is way behind what we have for 2.4 but forward porting is non-trivial # and work in progress.) # -------------------------------------------- # 03/06/23 ralf@linux-mips.org 1.1310.1.74 # [PATCH] Update for MIPS Inc's eval boards. # # This is an update for MIPS Inc's evaluation boards in all their ugly # versions ... # -------------------------------------------- # 03/06/23 ralf@linux-mips.org 1.1310.1.75 # [PATCH] TX49xx update # # This adds support for Toshiba's TX49xx SOCs and an evaluation board with # the nice nae RBTX4927. # -------------------------------------------- # 03/06/23 ralf@linux-mips.org 1.1310.1.76 # [PATCH] Baget update # # This is an update for the Russian Baget industrial controller. Suffers a # bit from bitrot, the authors have promised an update to me. # -------------------------------------------- # 03/06/23 ralf@linux-mips.org 1.1310.1.77 # [PATCH] DEC update # # An update of the code for the DECstations. This also adds 64-bit support # for the R4000 versions of DEC's good old workstations. # -------------------------------------------- # 03/06/23 ralf@linux-mips.org 1.1310.1.78 # [PATCH] NEC DDB update # # This updates the support for NEC's DDB series of evaluation boards. # -------------------------------------------- # 03/06/23 ralf@linux-mips.org 1.1310.1.79 # [PATCH] NEC VR41xx update # # This one adds support for a bunch of NEC VR41xx-based platforms such as # IBM's workpad and a bunch of eval boards. # -------------------------------------------- # 03/06/23 ralf@linux-mips.org 1.1310.1.80 # [PATCH] JMR3927 update # # This updates support for the JMR3927 eval board. # -------------------------------------------- # 03/06/23 ralf@linux-mips.org 1.1310.1.81 # [PATCH] Update Cobalt support # # This adds back support for the MIPS-based Cobalt Raq 1/2 and Qube 1/2 # systems. # -------------------------------------------- # 03/06/23 ralf@linux-mips.org 1.1310.1.82 # [PATCH] Add support for SGI IP32 # # This adds support for SGI's O2 workstation aka IP32. # -------------------------------------------- # 03/06/23 ralf@linux-mips.org 1.1310.1.83 # [PATCH] Momentum update # # This adds the board support code for Momentum's Ocelot series of boards. # -------------------------------------------- # 03/06/23 ralf@linux-mips.org 1.1310.1.84 # [PATCH] drivers/sgi update # # This updates drivers/sgi by removing it :-) With all the conceptually # wrong code which has was rewritten or should be rewritten or better # live elsewhere there just was no point in keeping this directory around # any longer. # -------------------------------------------- # 03/06/23 ralf@linux-mips.org 1.1310.1.85 # [PATCH] ARC update # # This updates the ARC firmware support code. Also removes the 64-bit # variant of the code; the 64-bit kernel now uses the 32-bit code also. # -------------------------------------------- # 03/06/23 ralf@linux-mips.org 1.1310.1.86 # [PATCH] Lasat support # # This patch adds support for the Lasat 100 and 200 systems. # -------------------------------------------- # 03/06/23 ralf@linux-mips.org 1.1310.1.87 # [PATCH] Remove Nino support # # This patch mostly removes the support for the Phillips Nino at the # request of the author. The only remaining bits are directly related # to the SOC the Nino is based on which is used by other ports. # -------------------------------------------- # 03/06/23 torvalds@home.transmeta.com 1.1310.1.88 # Remove SGI subdirectory from driver Makefile, since it is now # gone. # -------------------------------------------- # 03/06/23 yoshfuji@linux-ipv6.org 1.1310.59.11 # [IPV6]: Clean-up advmss calculation. # -------------------------------------------- # 03/06/23 chas@cmf.nrl.navy.mil 1.1310.59.12 # [ATM]: Move vccs to global sk-based linked list. # -------------------------------------------- # 03/06/23 shemminger@osdl.org 1.1310.59.13 # [NET]: PPPoE cleanup [TRIVIAL]. # This is a cleanup patch, no change in functionality. # - Get rid of debug macro's that aren't used anywhere in the code. # - Make functions and data structures static where possible # - C99 initializer for ppoe_chan_ops # - fix whitespace typo # -------------------------------------------- # 03/06/23 shemminger@osdl.org 1.1310.59.14 # [NET]: Fix oops on /proc/net/pppoe. # -------------------------------------------- # 03/06/23 shemminger@osdl.org 1.1310.59.15 # [NET]: Convert PPPoE to new style protocol. # -------------------------------------------- # 03/06/23 hunold@convergence.de 1.1310.1.89 # [PATCH] update the generic saa7146 driver # # - update the generic saa7146 driver # - remove some #if LINUX_VERSION_CODE constructions # - sync with the interrupt handler changes in 2.5.69 # - add a missing kfree() call which caused the kernel to leak 32kB of # kmalloc()ed memory. iieek! # - fixed the capture code to handle cards that have swapped field order # (odd and even fields) # - added and fixed some debug messages # - changed from kmalloc() to pci_consistent() # - many small changes necessary to fix warnings/problems for ppc64 # compilation # -------------------------------------------- # 03/06/23 hunold@convergence.de 1.1310.1.90 # [PATCH] update dvb subsystem core # # - update dvb subsystem core # - switched from user-land types like __u8 to u8 and uint16_t to u16 # this makes the patch rather large. # - updated the dvr (digital videorecording) facility # - renamed some structures, like "struct dmxdev_s" to "struct dmxdev" # - introduced dvb_functions.[ch], where some linux-kernel specific # functions are encapsulated. by this, the dvb subsystem stays quite # independent from deeper linux kernel functions. # - moved dvb_usercopy() to dvb_functions.c -- this is essentially # video_usercopy() which should be generic_usercopy() instead... # - Made the dvb-core in dvbdev.c work with devfs again. # - remove all typedefs from structs # - remove all typedefs from enums # -------------------------------------------- # 03/06/23 hunold@convergence.de 1.1310.1.91 # [PATCH] update the av7110 and budget drivers # # - update the av7110 and budget drivers # - replaced ddelay() wait function with generic dvb_delay() # implementation # - new DATA_MPEG_VIDEO_EVENT for direct mpeg2 video playback # - added support for DVB-C cards with MSP3400 mixer and analog tuner # - fixed up the av7110_ir handler and especially the write_proc() # function; this fixed the bug the Stanford Checker has found # -------------------------------------------- # 03/06/23 hunold@convergence.de 1.1310.1.92 # [PATCH] update dvb frontend drivers # # - update dvb frontend drivers # - C99 initializers # - fix up some includes # - various bugfixes # -------------------------------------------- # 03/06/23 hunold@convergence.de 1.1310.1.93 # [PATCH] add a new driver for the cx24110 frontend # # - add a new driver for the cx24110 frontend by Peter Hettkamp # # -------------------------------------------- # 03/06/23 hunold@convergence.de 1.1310.1.94 # [PATCH] add dvb subsystem as a crc32 lib user # # - add dvb subsystem as a crc32 lib user # -------------------------------------------- # 03/06/23 hunold@convergence.de 1.1310.1.95 # [PATCH] update analog saa7146 drivers mxb and dpc7146 # # - update analog saa7146 drivers mxb and dpc7146 # - add MODULE_DEVICE_TABLE entries, so that /sbin/hotplug can handle the # devices # - fixup due to the latest i2c changes # -------------------------------------------- # 03/06/23 hunold@convergence.de 1.1310.1.96 # [PATCH] correct the i2c address of saa7111 # # - this patch corrects the i2c address from "34>>1" to 0x24 and 0x25. # # Believe me -- or look at the data sheet, for example from # # http://www.gdv.uni-hannover.de/~hunold1/linux/saa7146/specs/saa7111a.pdf # # Page 41 says: "Slave address read = 49H or 4BH; note 2 write = 48H or # 4AH" They use 8-bit addresses here, but i2c addresses are 7-bit, ie. # 0x48>>1 == 0x24 and 0x4a>>1 = 0x25 # -------------------------------------------- # 03/06/23 hunold@convergence.de 1.1310.1.97 # [PATCH] clean up the parts according to the comments on kernel mailing list # # clean up the parts according to the comments on kernel mailing list # (mainly by Christoph Hellwig) # # - ugly WRITE_RPS0 define in saa7146_hlp.c has been replaced by a proper # inline (I hope) # - use not everywhere # - include headers after ones # - revert the indentation from "static xxx to "static xxx" # -------------------------------------------- # 03/06/23 hadi@shell.cyberus.ca 1.1310.59.16 # [NET]: Fix OOPSes with RSVP. # -------------------------------------------- # 03/06/23 herbert@gondor.apana.org.au 1.1310.59.17 # [IPSEC]: Add encap_oa member to struct xfrm_encap_tmpl. # -------------------------------------------- # 03/06/23 herbert@gondor.apana.org.au 1.1310.59.18 # [IPSEC]: Close SADB_ADD race and add XFRM_MSG_UPDSA (SADB_UPDATE equivalent). # -------------------------------------------- # 03/06/23 whydoubt@yahoo.com 1.1310.59.19 # [NET]: Trivial patch to netfilter Kconfig. # -------------------------------------------- # 03/06/23 solt@dns.toxicfilms.tv 1.1310.59.20 # [IPV4]: Be more verbose about invalid ICMPs sent to broadcast. # -------------------------------------------- # 03/06/23 shemminger@osdl.org 1.1310.59.21 # [NET]: Update teql scheduler to dynamic net device. # - dynamically allocate and free the network device. # previously, used static network device. # - support multiple equalizers (default one) via module parameter (max_equalizers) # previously, limited to one. # -------------------------------------------- # 03/06/24 paulus@samba.org 1.1310.58.6 # Merge samba.org:/stuff/paulus/kernel/linux-2.5 # into samba.org:/stuff/paulus/kernel/for-linus-ppc # -------------------------------------------- # 03/06/23 rmk@flint.arm.linux.org.uk 1.1310.63.1 # Merge flint.arm.linux.org.uk:/usr/src/linux-bk-2.5/linux-2.5 # into flint.arm.linux.org.uk:/usr/src/linux-bk-2.5/linux-2.5-serial # -------------------------------------------- # 03/06/23 willy@debian.org 1.1310.62.3 # [PATCH] PCI: unconfuse arch/i386/pci/Makefile # # I was looking in this Makefile for link order when my head began to hurt. # Apparently you can't have both NUMAQ and VISWS selected, so getting rid # of all the ifdefs/ifndefs like this should work. # -------------------------------------------- # 03/06/23 willy@debian.org 1.1310.62.4 # [PATCH] PCI: pci_raw_ops devfn # # Combine the dev and func arguments to pci_raw_ops into devfn which is # more natural all around. # -------------------------------------------- # 03/06/23 torvalds@home.transmeta.com 1.1310.1.98 # Merge bk://kernel.bkbits.net/davem/net-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/06/23 bunk@fs.tum.de 1.1310.62.5 # [PATCH] PCI Hotplug: fix buggy comparison in cpqphp_pci.c # # I don't understand the code good enough to be sure my patch is correct, # but the current code is definitely buggy: # # 0xFF is the maximum value for an u8, so tdevice < 0x100 is _always_ # true. # -------------------------------------------- # 03/06/23 henk@god.dyndns.org 1.1310.64.1 # [PATCH] I2C: add i2c-prosavage driver # # Using the MMIO method now, the driver should be able to handle multiple # video cards. # # The driver could potentialy also handle other s3 devices. You can try this # by adding more pci id's to the prosavage_pci_tbl. # -------------------------------------------- # 03/06/23 willy@org.rmk.(none) 1.1310.63.2 # [SERIAL] Missing Kconfig dependencies # # If one turns off SERIAL_8250, these items shouldn't be selectable. # Also gets the indentation right in `make oldconfig'. # -------------------------------------------- # 03/06/23 dlstevens@us.ibm.com 1.1310.59.22 # [IPV{4,6}]: Fix "slow multicast on 2.5.69" bug. # -------------------------------------------- # 03/06/23 rmk@flint.arm.linux.org.uk 1.1310.63.3 # [SERIAL] 8250_cs update - remove serial_info_t # -------------------------------------------- # 03/06/23 greg@kroah.com 1.1310.64.2 # I2C: add i2c-ali1535 bus driver # # Ported from the i2c cvs tree. # -------------------------------------------- # 03/06/23 rmk@flint.arm.linux.org.uk 1.1310.63.4 # [SERIAL] 8250_cs update - remove work queue # # Remove the work queue for serial_remove; events always happen # in process context now so the work queue gains us nothing. # -------------------------------------------- # 03/06/23 rmk@flint.arm.linux.org.uk 1.1310.63.5 # [SERIAL] 8250_cs update - incorporate pcmcia-cs 3.1.34 serial_cs fixes # # - add buggy_uart parameter # - use detected Vcc values, not CIS Vcc values # - handle OxSemi OXCF950 ports # -------------------------------------------- # 03/06/23 greg@kroah.com 1.1310.1.99 # Merge kroah.com:/home/greg/linux/BK/bleed-2.5 # into kroah.com:/home/greg/linux/BK/pci-2.5 # -------------------------------------------- # 03/06/23 greg@kroah.com 1.1310.65.1 # Merge kroah.com:/home/greg/linux/BK/bleed-2.5 # into kroah.com:/home/greg/linux/BK/i2c-2.5 # -------------------------------------------- # 03/06/23 rusty@rustcorp.com.au 1.1310.66.1 # [PATCH] {PATCH 2.5.72] Use mod_timer in drivers_net_wan_sdla_fr.c # # From: Vinay K Nallamothu # -------------------------------------------- # 03/06/23 rusty@rustcorp.com.au 1.1310.66.2 # [PATCH] [PATCH 2.5.72] Use mod_timer in drivers_net_wan_sdla_ppp.c # # From: Vinay K Nallamothu # -------------------------------------------- # 03/06/23 rusty@rustcorp.com.au 1.1310.66.3 # [PATCH] [PATCH 2.5.72] Use mod_timer in drivers_net_wan_sdla_x25.c # # From: Vinay K Nallamothu # -------------------------------------------- # 03/06/23 rusty@rustcorp.com.au 1.1310.66.4 # [PATCH] [PATCH 2.5.72] Use mod_timer in drivers_net_wan_sdla_chdlc.c # # From: Vinay K Nallamothu # -------------------------------------------- # 03/06/23 romieu@fr.zoreil.com 1.1310.66.5 # [netdrvr sk98lin] PCI API conversion, and some cleanups # # # - PCI API init style conversion for drivers/net/sk98lin/skge.c; # - new helpers: SkGeDev{Init/CleanUp}; # - sk_devs_lock moved around as it's needed early. # # Compiles without error. Untested. # -------------------------------------------- # 03/06/23 oliver@neukum.org 1.1310.61.2 # [PATCH] USB: highdma support for kaweth # # this tells the network layer that we can DMA from high memory # if the host controller supports it. # # - enable 64bit DMA on platforms that support it # -------------------------------------------- # 03/06/23 davidm@tiger.hpl.hp.com 1.1310.24.21 # ia64: Rename init_thread_union to init_task_mem to avoid conflicting # declration in . # -------------------------------------------- # 03/06/23 davidm@tiger.hpl.hp.com 1.1310.24.22 # Drop pcibios_update_resource() #warning. # -------------------------------------------- # 03/06/23 davidm@tiger.hpl.hp.com 1.1310.24.23 # ia64: Rename irq_desc() to irq_descp() to avoid conflict with variable # of same name declared in linux/irq.h. The expectation is that # this variable will be removed eventually and then irq_descp() # can be renamed to irq_desc() again. But for now, this makes it # easier to compile against Linus' source tree. # -------------------------------------------- # 03/06/23 davidm@tiger.hpl.hp.com 1.1310.24.24 # ia64: Update defconfig. Add missing include to . Fix # compiler warning in perfmon.c. # -------------------------------------------- # 03/06/23 davidm@tiger.hpl.hp.com 1.1310.67.1 # Merge tiger.hpl.hp.com:/data1/bk/vanilla/linux-2.5 # into tiger.hpl.hp.com:/data1/bk/lia64/to-linus-2.5 # -------------------------------------------- # 03/06/24 anton@samba.org 1.1319 # Merge samba.org:/scratch/anton/linux-2.5 # into samba.org:/scratch/anton/tmp3 # -------------------------------------------- # 03/06/24 jmorris@intercode.com.au 1.1310.68.1 # Merge bk://kernel.bkbits.net/davem/net-2.5 # into intercode.com.au:/home/jmorris/bk/net/net-2.5 # -------------------------------------------- # 03/06/24 anton@samba.org 1.1320 # ppc64: remove memset/memcpy function prototypes in eeh header file # -------------------------------------------- # 03/06/24 anton@samba.org 1.1321 # ppc64: memset destination if access_ok fails in copy_from_user # -------------------------------------------- # 03/06/24 anton@samba.org 1.1322 # ppc64: pci domain support # -------------------------------------------- # 03/06/23 davem@nuts.ninka.net 1.1310.69.1 # Merge nuts.ninka.net:/home/davem/src/BK/network-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/06/23 davem@nuts.ninka.net 1.1310.69.2 # [XFS]: Fix build error on big-endian. # -------------------------------------------- # 03/06/24 anton@samba.org 1.1323 # ppc64: fix some compile warnings # -------------------------------------------- # 03/06/24 jmorris@intercode.com.au 1.1310.68.2 # Merge bk://kernel.bkbits.net/davem/net-2.5 # into intercode.com.au:/home/jmorris/bk/net/net-2.5 # -------------------------------------------- # 03/06/24 paulus@samba.org 1.1310.58.7 # PPC32: Implement 2-argument show_stack(). # -------------------------------------------- # 03/06/24 anton@samba.org 1.1324 # ppc64: add dabr and iabr cpu features # -------------------------------------------- # 03/06/24 anton@samba.org 1.1325 # ppc64: merge Paul's interrupt-map parsing code # -------------------------------------------- # 03/06/24 yoshfuji@linux-ipv6.org 1.1310.68.3 # [IPV6] use macro for maximum payload length # -------------------------------------------- # 03/06/24 yoshfuji@linux-ipv6.org 1.1310.68.4 # [IPV6] Fix large packet length check # # There were two errors in length check in the output path. # We could not send large packet (65535bytes). # # This patch fixes the problem. # -------------------------------------------- # 03/06/24 rth@kanga.twiddle.net 1.1310.70.1 # [ALPHA] Don't print all interrupts in /proc/stat. # From Jeff Wiedemeier. # -------------------------------------------- # 03/06/24 jgrimm@touki.austin.ibm.com 1.1310.71.1 # Merge touki.austin.ibm.com:/home/jgrimm/bk/linux-2.5 # into touki.austin.ibm.com:/home/jgrimm/bk/lksctp-2.5.work # -------------------------------------------- # 03/06/18 jgrimm@touki.austin.ibm.com 1.1310.71.2 # [SCTP] Add ASSOCINFO and RTOINFO sockopts. (Ryan Layer and Anup Pemmaiah) # # Submitted by pemmaiah@cc.usu.edu and rmlayer@us.ibm.com. # -------------------------------------------- # 03/06/18 jgrimm@touki.austin.ibm.com 1.1310.71.3 # [SCTP] Fix wrong logic in hlist change. # # Otherwise, we leak bind_buckets. # -------------------------------------------- # 03/06/18 jgrimm@touki.austin.ibm.com 1.1310.71.4 # [SCTP] Remove some unused source modules. # # We use crypto api. Get rid of our own versions of hash code. # -------------------------------------------- # 03/06/19 jgrimm@touki.austin.ibm.com 1.1310.71.5 # [SCTP] Minor warning cleanups. # -------------------------------------------- # 03/06/19 jgrimm@touki.austin.ibm.com 1.1310.71.6 # [SCTP] More typedef removals. # # sctp_cookie_t -> sctp_cookie, sctp_signed_cookie_t ->sctp_signed_cookie_t. # -------------------------------------------- # 03/06/19 jgrimm@touki.austin.ibm.com 1.1310.71.7 # [SCTP] More typedef & name cleanup. # -------------------------------------------- # 03/06/20 jgrimm@touki.austin.ibm.com 1.1310.71.8 # [SCTP] Shorten SACK generation path. # # 1) Remove sctp_tsnmap_update_pending from the SACK path. The # pending_data variable is only used by a socket option, so just # calculate it when needed rather than the I/O path. # 2) Instead of walking the tsnmap twice, change the interface to # allow walking once. # 3) Only report a fixed number of gabs and reserve this room in the # association, saving us a kmalloc every sack generation. # TBD: Still need to kick out of tanmap walking early if we get to # max_tsn_seen. # -------------------------------------------- # 03/06/23 jgrimm@touki.austin.ibm.com 1.1310.71.9 # [SCTP] Don't search gap ack blocks past max_tsn_seen. # # There is no need to keep walking the tsnmap past the # max_tsn_seen, so don't. # -------------------------------------------- # 03/06/24 jgrimm@touki.austin.ibm.com 1.1310.72.1 # Merge touki.austin.ibm.com:/home/jgrimm/bk/linux-2.5 # into touki.austin.ibm.com:/home/jgrimm/bk/lksctp-2.5.work # -------------------------------------------- # 03/06/24 torvalds@home.transmeta.com 1.1310.73.1 # Merge bk://bk.arm.linux.org.uk/linux-2.5-pcmcia # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/06/24 torvalds@home.transmeta.com 1.1310.73.2 # Merge bk://bk.arm.linux.org.uk/linux-2.5-serial # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/06/24 torvalds@home.transmeta.com 1.1310.65.2 # Merge bk://kernel.bkbits.net/gregkh/linux/i2c-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/06/24 torvalds@home.transmeta.com 1.1310.1.100 # Merge bk://kernel.bkbits.net/gregkh/linux/pci-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/06/24 torvalds@home.transmeta.com 1.1310.1.101 # Merge bk://kernel.bkbits.net/jgarzik/irda-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/06/24 torvalds@home.transmeta.com 1.1310.1.102 # Merge bk://kernel.bkbits.net/jgarzik/net-drivers-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/06/24 torvalds@home.transmeta.com 1.1310.1.103 # Merge bk://ppc.bkbits.net/for-linus-ppc # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/06/24 neilb@cse.unsw.edu.au 1.1310.1.104 # [PATCH] Fix bug in rpc cache_clean introduced by previous patch # # Having a 'continue' at the end of this look it pointless... it should # be a break. # -------------------------------------------- # 03/06/24 neilb@cse.unsw.edu.au 1.1310.1.105 # [PATCH] Always flush rpc caches after an update # # ..as the update might have set an expiry date in the past # and we want it to be removed instantly. # -------------------------------------------- # 03/06/24 neilb@cse.unsw.edu.au 1.1310.1.106 # [PATCH] Include update mode in declaration of RPC information caches. # # The sunrpc/cache.c caches which store nfsd export information # can be updated either "inplace" or by replacing the entry. # # replacement is needed when an entry hold a reference to some # other object, so the reference counts work properly. # # "inplace" can be used when no such references are held, and should be # used when the object could be refered to by another cache (as otherwise # the other cache would have to be updated whenever this one is). # # Previously the type of update (inplace or replace) was specified # as an argument to the *_lookup operation. This too easily lead to # inconsistancies. # # With this patch, the update mode is specified when the cache is # declared. # -------------------------------------------- # 03/06/24 neilb@cse.unsw.edu.au 1.1310.1.107 # [PATCH] Add some tracing when showing the content of an RPC cache. # # The /proc/net/rpc/*/content files now will show # entries that are still in the cache, but are either # expired or negative, as comment. # # ip_map_show is enhance to work if called with a negative # or incomplete entry. # # Also if cache debugging is enabled, the expiry time and # refcount of each entry will be included in a comment. # -------------------------------------------- # 03/06/24 neilb@cse.unsw.edu.au 1.1310.1.108 # [PATCH] Define cache_show methods for export and filehandle cache in nfsd. # -------------------------------------------- # 03/06/24 neilb@cse.unsw.edu.au 1.1310.1.109 # [PATCH] Use schedule_work to regular cache cleaning # # Cleaning of the export caches is currently done by idle # nfsd threads which isn't very reliable. # # This patch makes use of work_queues to do it all inside # cache.c # -------------------------------------------- # 03/06/24 neilb@cse.unsw.edu.au 1.1310.1.110 # [PATCH] Fix byte counting for NFSv3 readdir replies # # The amount of free space is calculated wrongly so # nfsv3 readdir replies are shorted than they could be. # -------------------------------------------- # 03/06/24 neilb@cse.unsw.edu.au 1.1310.1.111 # [PATCH] Get buf size and page count right for RPC services. # # The old calculations BUGed on 64k PAGESIZE machines. # -------------------------------------------- # 03/06/24 torvalds@home.transmeta.com 1.1310.1.112 # Merge http://lia64.bkbits.net/to-linus-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/06/24 torvalds@home.transmeta.com 1.1310.1.113 # Merge bk://kernel.bkbits.net/davem/net-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/06/24 B.Zolnierkiewicz@elka.pw.edu.pl 1.1310.1.114 # [PATCH] do not take ide_setting_sem under ide_lock # # From -mm tree, fixes oops when removing ide drivers. # -------------------------------------------- # 03/06/24 B.Zolnierkiewicz@elka.pw.edu.pl 1.1310.1.115 # [PATCH] fix use-after-free in ide_unregister() # -------------------------------------------- # 03/06/24 B.Zolnierkiewicz@elka.pw.edu.pl 1.1310.1.116 # [PATCH] build fix for pdc4030 without taskfile IO # # Noticed by Arkadiusz Miskiewicz. # -------------------------------------------- # 03/06/24 B.Zolnierkiewicz@elka.pw.edu.pl 1.1310.1.117 # [PATCH] fix compilation of NS SC1x00 driver without procfs # # Noticed by Adrian Bunk. # -------------------------------------------- # 03/06/24 B.Zolnierkiewicz@elka.pw.edu.pl 1.1310.1.118 # [PATCH] call setup_driver_defaults() only once for each driver # -------------------------------------------- # 03/06/24 mikpe@csd.uu.se 1.1310.1.119 # [PATCH] enable local APIC on P4 # # The current local APIC code refuses to enable the local APIC # on a P4 if the BIOS booted us with the local APIC disabled. # This patch removes this unnecessary restriction. Please apply. # # Most P4 machines do boot with the local APIC enabled, but # Keith Owens reported that the P4 based Compaq Evo N800v # disables the local APIC, even though the machine actually # works if Linux enables it. # # It is possible that some P4 machines with broken BIOSen # were saved by our refusal to enable the local APIC. We # can handle them via the DMI blacklist rules instead. # -------------------------------------------- # 03/06/24 ambx1@neo.rr.com 1.1310.74.1 # [PNP] pnp_init_resource_table compile fix # # In the last release, this api was accidently changed and therefore # affected some drivers. This patch corrects the issue by renaming # the api back to pnp_init_resource_table. # -------------------------------------------- # 03/06/24 ambx1@neo.rr.com 1.1310.74.2 # [PNP] Locking Fixes # # The semaphore in pnp_init_resource_table is not needed and, in some # cases, can cause resource management lockups. This patch removes the # improperly placed semaphore. # -------------------------------------------- # 03/06/24 davem@nuts.ninka.net 1.1310.1.120 # [SEQ_FILE]: Export seq_path() to modules. # -------------------------------------------- # 03/06/24 greg@kroah.com 1.1310.61.3 # [PATCH] USB: add support for 50 baud to io_edgeport.c # -------------------------------------------- # 03/06/24 kpc-usbdev@gelato.uiuc.edu 1.1310.61.4 # [PATCH] USB: Desknote/ECS UCR-61S2B card reader (2.5.72 patched) # # This is for 2.5.72 with the US_PR_DEVICE / US_SC_DEVICE patch in place. # Tested and working. # -------------------------------------------- # 03/06/24 oliver@neukum.org 1.1310.61.5 # [PATCH] USB: make kaweth deal with ENOMEM # # this fixes the logic kaweth uses to deal with ENOMEM from # usb_submit_urb(). Using the interrupt endpoint's completion # handller is longer an option because automagic resubmission # has been removed. Thus we use workqueues which can be delayed # so that kswapd can do its job and can use GFP_NOIO which is much # likelier to succeed. # -------------------------------------------- # 03/06/24 davem@nuts.ninka.net 1.1310.75.1 # Merge bk://kernel.bkbits.net/jmorris/net-2.5 # into nuts.ninka.net:/home/davem/src/BK/jmorris-2.5 # -------------------------------------------- # 03/06/24 davem@nuts.ninka.net 1.1310.1.121 # Merge nuts.ninka.net:/home/davem/src/BK/jmorris-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/06/24 bernie@develer.com 1.1310.1.122 # [IPV4]: Trim the includes used in util.c # -------------------------------------------- # 03/06/24 ehabkost@conectiva.com.br 1.1310.76.1 # [PATCH] Fix compilation of ip2main # # The following patch fix compilation of drivers/char/ip2main.c. It was # broken by the removal of pci_present(). # # It just adds open and closing braces around the code that declares the # pci_dev_i variable. The rest of the patch just change the indentation. # -------------------------------------------- # 03/06/24 willy@debian.org 1.1310.76.2 # [PATCH] PCI: [PATCH] pcibios_scan_acpi() # # On Mon, Jun 23, 2003 at 02:39:05PM -0700, Greg KH wrote: # > > How about acpi_scan_pci_bus_root()? # > # > I agree, that sounds better. # # I think it's too long ... so unless anyone has a better idea, I'm going with # pci_acpi_scan_root(). Here's the patch, presented in patch -p1 format to # make greg's scripts happy ;-) # # ia64 needs to be passed the pci domain and the acpi handle corresponding # to each root bus. Rather than change pcibios_scan_root to take additional # arguments, this patch introduces pci_acpi_scan_root(). # -------------------------------------------- # 03/06/24 greg@kroah.com 1.1310.77.1 # Merge kroah.com:/home/greg/linux/BK/bleed-2.5 # into kroah.com:/home/greg/linux/BK/gregkh-2.5 # -------------------------------------------- # 03/06/24 laforge@netfilter.org 1.1310.1.123 # `cat msg` # -------------------------------------------- # 03/06/24 laforge@netfilter.org 1.1310.1.124 # [NETFILTER]: Forward port cosmetic fixes from 2.4.x # -------------------------------------------- # 03/06/24 laforge@netfilter.org 1.1310.1.125 # [NETFILTER]: Enhancement for ip{,6}_tables, add new /proc files. # -------------------------------------------- # 03/06/24 laforge@netfilter.org 1.1310.1.126 # [NETFILTER]: Fix conntrack master_ct refcounting. # -------------------------------------------- # 03/06/24 willy@debian.org 1.1310.76.3 # [PATCH] PCI documentation # # Update the PCI Documentation to reflect some of the functions which have # recently been added and removed. # # Index: Documentation/pci.txt # =================================================================== # RCS file: /var/cvs/linux-2.5/Documentation/pci.txt,v # retrieving revision 1.4 # -------------------------------------------- # 03/06/24 sfrost@snowman.net 1.1310.1.127 # [NETFILTER]: Add "recent" iptables facility. # -------------------------------------------- # 03/06/24 ink@jurassic.park.msu.ru 1.1310.1.128 # [NET]: Need sys_socket cond_syscall() entry. # -------------------------------------------- # 03/06/24 torvalds@home.transmeta.com 1.1310.1.129 # Merge bk://kernel.bkbits.net/gregkh/linux/linus-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/06/24 torvalds@home.transmeta.com 1.1310.1.130 # Merge bk://linux-pnp.bkbits.net/pnp-2.5 # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/06/24 Andries.Brouwer@cwi.nl 1.1310.1.131 # [PATCH] loop.c - part 2 of N # # This does the following: # # - IV value is current 512-byte sector relative to start of loop # container file. This is what all cryptoloop people have done, if I # am not mistaken. Andi or others - if you can demonstrate the need # for a more flexible setup an additional ioctl field may be needed. I # hope we can do without. # # - made some things static # # - made lo_offset a loff_t # # - added lo_sizelimit # # If one wanted a (crypto)loop somewhere inside a container file, the # old code allowed a starting offset, but no size, so that the # cryptoloop always extended to the end of the container file. This # field allows one to select an arbitrary interval. Note that this # changes struct loop_info64. # # - improve error handling of loop_init() # # - removed the unused typedef transfer_proc_t. # # - added a define for LO_CRYPT_CRYPTOAPI # -------------------------------------------- # 03/06/24 rddunlap@osdl.org 1.1310.1.132 # [PATCH] unexpected IO-APIC update # # Recently there has been a rash of Unexpected IO APIC reports on the # linux-smp mailing list. Most of the most recent ones are due to some # newer Intel chipsets (865, 875). # # The IO APIC Version register doesn't indicate the differences in these # IO APICs. # # I have an patch that addresses these chipsets. It has been tested by a # few people with good results and has been blessed by Maciej Rozycki. # # Other than conditionally decoding IO APIC registers 2 and 3, we could # alternately ignore them since Linux doesn't use the values for anything # other than printing them. # # This patch ignores IO APIC register 2 if it's the same value as IO APIC # register 1. It also reads IO APIC register 3 if the IO APIC version is # >= 0x20, but some chipsets don't support this register, so it is also # ignored if its value if the same as IO APIC register 1 or 2. # # Another possible(?) alternative is to read the PID/VID of the device to # determine which registers it supports. However, PCI devices have not # been scanned at this point in init, so it would require scanning PCI # config space directly and I don't yet see the point of doing that. # # Oh, and the UNEXPECTED_IO_APIC() function doesn't print anything in # 2.5.current and I didn't change that. # -------------------------------------------- # 03/06/24 daniel.ritz@gmx.ch 1.1310.1.133 # [PATCH] alloc_etherdev for 3c574_cs # # net_device is no longer allocated as part of the driver's private structure, # instead it's allocated via alloc_netdev. compile tested only since no hardware # against 2.5.73-bk # # # -daniel # # # ===== drivers/net/pcmcia/3c574_cs.c 1.17 vs edited ===== # -------------------------------------------- # 03/06/24 daniel.ritz@gmx.ch 1.1310.1.134 # [PATCH] alloc_etherdev for 3c589_cs # # net_device is no longer allocated as part of the driver's private structure, # instead it's allocated via alloc_netdev. compile tested only since no hardware # against 2.5.73-bk # # # -daniel # # ===== drivers/net/pcmcia/3c589_cs.c 1.17 vs edited ===== # -------------------------------------------- # 03/06/24 daniel.ritz@gmx.ch 1.1310.1.135 # [PATCH] alloc_etherdev for fmvj18x_cs # # net_device is no longer allocated as part of the driver's private structure, # instead it's allocated via alloc_netdev. compile tested only since no hardware # against 2.5.73-bk # # # -daniel # # ===== fmvj18x_cs.c 1.21 vs edited ===== # -------------------------------------------- # 03/06/24 daniel.ritz@gmx.ch 1.1310.1.136 # [PATCH] alloc_etherdev for nmclan_cs # # net_device is no longer allocated as part of the driver's private structure, # instead it's allocated via alloc_netdev. compile tested only since no hardware # against 2.5.73-bk # # # -daniel # # ===== nmclan_cs.c 1.14 vs edited ===== # -------------------------------------------- # 03/06/24 daniel.ritz@gmx.ch 1.1310.1.137 # [PATCH] alloc_etherdev for smc91c92_cs # # net_device is no longer allocated as part of the driver's private structure, # instead it's allocated via alloc_netdev. compile tested only since no hardware # against 2.5.73-bk # # # -daniel # # ===== smc91c92_cs.c 1.18 vs edited ===== # -------------------------------------------- # 03/06/24 scott.feldman@intel.com 1.1310.1.138 # [PATCH] Remove CAP_NET_ADMIN check for SIOCETHTOOL's # # dev_ioctl already checks capable(CAP_NET_ADMIN), so no need to do so in # drivers. # -------------------------------------------- # 03/06/24 shemminger@osdl.org 1.1310.1.139 # [PATCH] 2.5.70 - eepro100 - use alloc_etherdev # # Ignore earlier patch -- this one locks and free's as appropriate. # Tested on 2.5.72 with SMP. # # Of course, it begs the question why have two (now three) versions of drivers for # the same hardware... # -------------------------------------------- # 03/06/24 davem@nuts.ninka.net 1.1310.78.1 # [USB]: Use linux/dma-mapping.h not asm/dma-mapping.h in kaweth.c # -------------------------------------------- # 03/06/24 davem@nuts.ninka.net 1.1310.78.2 # [PCI]: Export pci_enable_device_bars to modules. # -------------------------------------------- # 03/06/24 davem@nuts.ninka.net 1.1310.78.3 # [SPARC64]: Update defconfig. # -------------------------------------------- # 03/06/24 davem@nuts.ninka.net 1.1310.78.4 # [SERIAL]: Sanitize sparc serial console configuration. # -------------------------------------------- # 03/06/24 davem@nuts.ninka.net 1.1310.78.5 # [SPARC64]: Update defconfig. # -------------------------------------------- # 03/06/25 anton@samba.org 1.1326 # Merge samba.org:/scratch/anton/linux-2.5 # into samba.org:/scratch/anton/tmp3 # -------------------------------------------- # 03/06/25 paulus@samba.org 1.1310.58.8 # PPC32: remove check for ERESTARTNOHAND in syscall return path. # # This error is handled in the signal delivery code and should never be # returned from a syscall unless a signal is pending. Grepping seems to # indicate that that is in fact the case (but not for ERESTARTSYS, but # that is another problem). # -------------------------------------------- # 03/06/25 jgrimm@touki.austin.ibm.com 1.1310.72.2 # [SCTP] Peeled off/accepted sockets not in the right bind_bucket. # # hlist changes caused the peeloff testcase to fail. Investigation shows # that the peeloff sockets is not bound into bind_bucket, so the # bucket has gone away (original socket closed). Fixing this, shows # a problem that inet->num wasn't set on peeled off sockets, so autobind # kicks in creating a new bind_bucket. Ugh. One bug had been # hiding the other one all this time. # # Fix 1) peeledoff/accepted sockets need to have their own socket woven # into the bind_bucket->owner list. 2) Set inet->num, so autobind # doesn't think it needs to kick in. # -------------------------------------------- # 03/06/25 torvalds@home.transmeta.com 1.1310.78.6 # Merge bk://ppc.bkbits.net/for-linus-ppc # into home.transmeta.com:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/06/26 shemminger@osdl.org 1.1310.79.1 # [NET] remove skb_linearize from igmp.c # -------------------------------------------- # 03/06/26 shemminger@osdl.org 1.1310.78.7 # Merge bk://kernel.bkbits.net/torvalds/linux-2.5 # into osdl.org:/home/jmorris/bk/net/work-2.5 # -------------------------------------------- # 03/06/25 rddunlap@osdl.org 1.1310.80.1 # [PATCH] Unionize IO-APIC registers # # [ Registers of the world, unite! ] # # This makes the IO-APIC data structures use unions, so that we can # cleanly access them both as flat "raw" values, and as the bitmap # sub-entries. # -------------------------------------------- # 03/06/25 jejb@raven.il.steeleye.com 1.1310.81.1 # SCSI: abstract mode_sense 6 and 10 out completely # # Move the mode_sense request routines to a central location and make # all block device consumers use it. Also abstract the header as # part of the return to hide the 6/10 differences. # -------------------------------------------- # 03/06/25 jejb@raven.il.steeleye.com 1.1310.81.2 # scsi_mid_low_api.txt update # # From Douglas Gilbert # -------------------------------------------- # 03/06/25 bunk@fs.tum.de 1.1310.81.3 # [PATCH] remove an unused variable from fd_mcs.c # # The patch belowremoves an unused variable from drivers/scsi/fd_mcs.c . # # I've tested the compilation with 2.5.72-mm2. # -------------------------------------------- # 03/06/25 bunk@fs.tum.de 1.1310.81.4 # [PATCH] remove an unused function declaration from sym53c416.h # # The patch below removes a declaration for a function that is no longer # present. # # I've tested the compilation with 2.5.72-mm2. # -------------------------------------------- # 03/06/25 bunk@fs.tum.de 1.1310.81.5 # [PATCH] ibmmca cleanup # # The patch below does the following: # - remove an unused static function # - removes the declaration of a function that is no longer present # - removes a variable declaration that shadows a function parameter # # I've tested the compilation with 2.5.72-mm2. # -------------------------------------------- # 03/06/25 bunk@fs.tum.de 1.1310.81.6 # [PATCH] remove an unused function from nsp32.c # # The patch below removes an unused function from nsp32.c . # # I've tested the compilation with 2.5.72-mm2. # -------------------------------------------- # 03/06/25 bunk@fs.tum.de 1.1310.81.7 # [PATCH] seagate cleanup # # The patch below does the following cleanups on # drivers/scsi/seagate.{c,h}: # - remove two unused functions # - remove a function declaration for a function that is no longer present # # I've tested the compilation with 2.5.72-mm2. # -------------------------------------------- # 03/06/25 rusty@rustcorp.com.au 1.1310.81.8 # [PATCH] Trivial patch for scsi_error.c # # From: Alan Stern # -------------------------------------------- # 03/06/25 hch@lst.de 1.1310.81.9 # [PATCH] check for can_queue != 0 in scsi_host_alloc # # This is to give a proper warning if someone tries to load an # unconverted old-style driver. # -------------------------------------------- # 03/06/25 dougg@torque.net 1.1310.81.10 # [PATCH] REQUEST SENSE 254->252 byte response # # SPC-3 (rev 13) says that 252 bytes in the maximum (and # recommended) length for a REQUEST SENSE reponse. # # Linux asks for 254 bytes in scsi_error.c . # # That number was not specified in SPC-2 (although the # allocation length field is 1 byte thus limiting it to # 255). Seems as though some numbers are being rounded # down to be multiples of 4. # -------------------------------------------- # 03/06/25 bunk@fs.tum.de 1.1310.81.11 # [PATCH] NCR53C9x compile fix # # From: Geert Uytterhoeven # -------------------------------------------- # 03/06/25 bunk@fs.tum.de 1.1310.81.12 # [PATCH] integer constants in sym53c8xx_2/sym_glue.c too big for int # # The patch below postfixes a constant in sym53c8xx_2/sym_glue.c with ULL, # on 32 bit archs this constant is too big for an int. # -------------------------------------------- # 03/06/25 bunk@fs.tum.de 1.1310.81.13 # [PATCH] postfix two constants in ips.c with ULL # # The patch below postfixes two constants in ips.c with ULL, on 32 bit # archs this constant is too big for an int. # # The cast doesn't do the right thing, 0xffffffffffffffff is in C an int # and the cast casts 0xffffffffffffffff interpreted as an int to an u64. # -------------------------------------------- # 03/06/25 patmans@us.ibm.com 1.1310.81.14 # [PATCH] fix return value of scsi_device rescan attribute # # When writing to the rescan attribute, return count as result, otherwise # some user apps might retry the write forever. # # And remove the read capability of the attribute. # -------------------------------------------- # 03/06/25 markh@osdl.org 1.1310.81.15 # [PATCH] clean up aacraid use of SCSI constants # -------------------------------------------- # 03/06/25 davidm@napali.hpl.hp.com 1.1310.81.16 # [PATCH] small patch for sym53c8xx_2 # # I thought we had an agreement for a long time already that the use of # dma64_addr_t in the sym53c8xx_2 driver was wrong, but it's still # there. # -------------------------------------------- # 03/06/25 stern@rowland.harvard.edu 1.1310.81.17 # [PATCH] Fix scsi host attributes # # The shost_attrs stuff looks fine, expect for two points. # # 1. The scsi_sysfs_modify_shost_attribute() and # scsi_sysfs_modify_sdev_attribute() functions appear to be written a bit # carelessly. Below is a patch that: permits modification of the first # attribute in the list, allocates a new list with entries having the # correct size, copies the correct number of entries from the old list, and # wraps excessively long source lines. # # 2. More importantly, the current organization of the code has a # serious problem. The SCSI core does not modify the host driver when the # reference count for either shost->class_dev or shost->host_gendev drops to # 0. Without knowing that, it is unsafe for the driver ever to deallocate a # private host data structure, since a user process may continue to hold a # reference to an open attribute file indefinitely, even after # scsi_unregister() has returned. # -------------------------------------------- # 03/06/25 hch@lst.de 1.1310.81.18 # [PATCH] add scsi_driver.h # # include/scsi/scsi_driver.h contains æverything related to upper # level drivers. Unlike the other header moves there's no compatiblity # this time as it's easy to fix up the few users. # -------------------------------------------- # 03/06/25 tonyb@cybernetics.com 1.1310.81.19 # [PATCH] make sym53c8xx_2 not reject autosense IWR # # This patch makes sym53c8xx_2 silently ignore the Ignore Wide Residue # message on autosense commands rather than rejecting it. This makes # the SCSI communications cleaner for targets that return an odd number # of sense bytes. # -------------------------------------------- # 03/06/25 jgarzik@redhat.com 1.1310.1.140 # [irda] add driver for mips Alchemy Au1000 SIR/FIR # # Submitted by Ralf Baechle # -------------------------------------------- # 03/06/25 ralf@linux-mips.org 1.1310.1.141 # [netdrvr] add driver "meth", for SGI O2 MACE fast eth # -------------------------------------------- # 03/06/25 ralf@linux-mips.org 1.1310.1.142 # [netdrvr] sgiseeq update # -------------------------------------------- # 03/06/25 ralf@linux-mips.org 1.1310.1.143 # [netdrvr] update ioc3_eth # -------------------------------------------- # 03/06/25 ralf@linux-mips.org 1.1310.1.144 # [netdrvr] update declance # -------------------------------------------- # 03/06/25 ralf@linux-mips.org 1.1310.1.145 # [netdrvr] au1000_eth update # -------------------------------------------- # 03/06/25 ralf@linux-mips.org 1.1310.1.146 # [netdrvr] update sb1250-mac # -------------------------------------------- # 03/06/25 ralf@linux-mips.org 1.1310.1.147 # [netdrvr tulip] add mips cobalt support # -------------------------------------------- # 03/06/25 ralf@linux-mips.org 1.1310.1.148 # [netdrvr] misc small mips updates # # Add missing CONFIG_TC35805 entry to Kconfig. # Update CONFIG_NET_SB1250_MAC Kconfig entry. # Minor cosmetic updates to gt96100eth. # -------------------------------------------- # 03/06/25 torvalds@home.osdl.org 1.1310.1.149 # Merge bk://kernel.bkbits.net/jgarzik/net-drivers-2.5 # into home.osdl.org:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/06/26 anton@samba.org 1.1327 # Merge samba.org:/scratch/anton/linux-2.5 # into samba.org:/scratch/anton/tmp3 # -------------------------------------------- # 03/06/26 davej@tetrachloride.(none) 1.1310.82.1 # Merge tetrachloride.(none):/mnt/raid/src/kernel/2.5/bk-linus # into tetrachloride.(none):/mnt/raid/src/kernel/2.5/cpufreq # -------------------------------------------- # 03/06/26 anton@samba.org 1.1328 # ppc64: remove ERESTARTNOHAND code in syscall exit, from ppc32 # -------------------------------------------- # 03/06/25 willy@debian.org 1.1310.76.4 # [PATCH] PCI: more PCI gubbins # # I noticed we have a couple of redundancies in drivers/pci/Makefile, # have a patch... # -------------------------------------------- # 03/06/25 willy@debian.org 1.1310.76.5 # [PATCH] PCI: fixes for pci/probe.c # # - Combine pci_alloc_primary_bus_parented into pci_scan_bus_parented. # - Move the EXPORT_SYMBOL for pci_root_buses up to its definition. # - Don't EXPORT_SYMBOL pci_scan_bus since it's a static inline. # - Add the pci_domain_nr() to the sysfs name for this bus. # -------------------------------------------- # 03/06/25 greg@kroah.com 1.1310.76.6 # [PATCH] PCI Hotplug: fix core problem with kobject lifespans. # # Added needed release function, now all pci hotplug drivers need to implement # it... # -------------------------------------------- # 03/06/25 greg@kroah.com 1.1310.76.7 # [PATCH] IBM PCI Hotplug: fixes found by sparse # -------------------------------------------- # 03/06/25 greg@kroah.com 1.1310.76.8 # PCI Hotplug: add fake PCI hotplug driver. # # Useful for testing hotplug issues with pci drivers. # -------------------------------------------- # 03/06/25 greg@kroah.com 1.1310.1.150 # Merge kroah.com:/home/greg/linux/BK/bleed-2.5 # into kroah.com:/home/greg/linux/BK/pci-2.5 # -------------------------------------------- # 03/06/26 davej@codemonkey.org.uk 1.1310.82.2 # [CPUFREQ] speedstep cleanups. # From Dominik Brodowski. # # - separate functions which might be useful for speedstep-piix4, # speedstep-via or speedstep-bios into a new speedstep-lib.c. # - clean up speedstep-ich as it will only be used for ICH-based chipsets # in future. # - remove now-obsolete speedstep_coppermine parameter # -------------------------------------------- # 03/06/26 davej@codemonkey.org.uk 1.1310.82.3 # [CPUFREQ] Speedstep support for P4M/533 # From Dominik Brodowski. # # Add support for newest "Mobile Pentium 4-M" and the new "Mobile Pentium 4 with # 533 MHz FSB" processors. # -------------------------------------------- # 03/06/26 davej@codemonkey.org.uk 1.1310.82.4 # [CPUFREQ] Silence debug output on centrino speedstep driver. # -------------------------------------------- # 03/06/26 anton@samba.org 1.1329 # Merge samba.org:/scratch/anton/linux-2.5 # into samba.org:/scratch/anton/tmp3 # -------------------------------------------- # 03/06/26 davej@codemonkey.org.uk 1.1310.83.1 # [AGPGART] Add missing pte masking in NVIDIA nForce driver. # Noticed by Marcelo Penna Guerra. # -------------------------------------------- # 03/06/26 shemminger@osdl.org 1.1310.78.8 # [NET][IPMR] ipmr fixes # # These patches fix ip multicast route (ipmr) on 2.5.73. # # 1 - Trivial C99 initialization # 2 - Change functions/variables to static # 3 - Drop and reacquire RTNL in error path # 4 - Use time_after() # 5 - Use alloc_netdev # 6 - Fix OOPS on dropped packets # 7 - Get rid of skb_linearize # # Tested on 8-way SMP by bringing up pimd. # # -------------------------------------------- # 03/06/26 davej@codemonkey.org.uk 1.1310.83.2 # [AGPGART] SiS 655 support. # Needs more testing, especially in x8 mode. # -------------------------------------------- # 03/06/25 akpm@digeo.com 1.1310.1.151 # [PATCH] GCC 2.95.4 needs the spinlock workaround # # From: Mikael Pettersson # # 2.5.73 removed the workaround needed to prevent gcc-2.95.x from # miscompiling spinlocks on UP. It turns out that some versions of # gcc-2.95 still do have problems with empty structs, so re-introduce # the workaround. # -------------------------------------------- # 03/06/25 akpm@digeo.com 1.1310.1.152 # [PATCH] show_stack fix # # sysrq-T currently displays the same stack trace for every process. # # Teach show_stack() to look in the passed task_struct first if the caller did # not pass in a stack address. # -------------------------------------------- # 03/06/25 akpm@digeo.com 1.1310.1.153 # [PATCH] setscheduler needs to force a reschedule # # From: Robert Love # # Basically, the problem is that setscheduler() does not set need_resched # when needed. There are two basic cases where this is needed: # # - the task is running, but now it is no longer the highest # priority task on the rq # - the task is not running, but now it is the highest # priority task on the rq # # In either case, we need to set need_resched to invoke the scheduler. # -------------------------------------------- # 03/06/25 akpm@digeo.com 1.1310.1.154 # [PATCH] misc fixes # # - unused var warning in pnp_add_irq_resource() # # - unused var in fd_mcs.c (Adrian Bunk) # # - remove dead code in i810_main.c (a u8 cannot exceed 255) (Adrian Bunk) # # - don't truncate dma_addr_t's in gdth.c (Jes Sorensen) # # - vgastate.c needs vmalloc.h (Geert Uytterhoeven ) # # - revert bogus test from rd_open() - it was a 2.4 forward-port, and 2.5 # doesn't need it. (The gendisks aren't registered, we cannot get there # anyway). # -------------------------------------------- # 03/06/25 akpm@digeo.com 1.1310.1.155 # [PATCH] AT_SECURE auxv entry # # From: Stephen Smalley # # This patch adds an AT_SECURE auxv entry to pass a boolean flag indicating # whether "secure mode" should be enabled (i.e. sanitize the environment, # initial descriptors, etc) and allows each security module to specify the # flag value via a new hook. # # New userland can then simply obey this flag when present rather than # applying other methods of deciding (sample patch for glibc-2.3.2 can be # found at http://www.cs.utah.edu/~sds/glibc-secureexec.patch). # # This change enables security modules like SELinux to request secure mode # upon changes to other security attributes (e.g. capabilities, # roles/domains, etc) in addition to uid/gid changes or even to completely # override the legacy logic. # # The legacy decision algorithm is preserved in the default hook functions # for the dummy and capability security modules. # # Credit for the idea of adding an AT_SECURE auxv entry goes to Roland # McGrath. # -------------------------------------------- # 03/06/25 akpm@digeo.com 1.1310.1.156 # [PATCH] common name for the kernel DSO # # From: David Mosberger # # Give the ia32 vsyscall DSO the same name as ia64's. # -------------------------------------------- # 03/06/25 akpm@digeo.com 1.1310.1.157 # [PATCH] get_unmapped_area() speedup # # From: Ingo Molnar # # Apparently our thread-creation performance has gone down the tubes again, # because the mm.free_area_cache search heuristic broke. # # The initial, more naive hole-cache patch helped the testcode in the # beginning. Then after some point glibc started creating a 'small hole' in # the vmas, which hole was _below_ the thread stacks, and which hole thus # prevented the intended operation of the cache. # # The new code solves the problem by relaxing the 'smallest address hole cache' # rule a bit, the cache is now not re-set at every get_unmapped_area() time, # it's only re-set during unmaps. It's also re-set if there are no allocatable # mappings at all - ie. correctness is not affected. # -------------------------------------------- # 03/06/25 akpm@digeo.com 1.1310.1.158 # [PATCH] dentry->d_count fixes: d_invalidate # # From: Maneesh Soni # # - d_invalidate() can incorrectly return success instead of returning -EBUSY # as we can have situations where lockless d_lookup has found a dentry # successfully before d_invalidate drops it # -------------------------------------------- # 03/06/25 akpm@digeo.com 1.1310.1.159 # [PATCH] dentry->d_count fixes: nfs_unlink # # From: Maneesh Soni # # - nfs_unlink() can race with lockless d_lookup() as d_lookup() can # successfully lookup a dentry for which nfs_unlink() can assume that no one # else is using and can go ahead and do nfs_safe_remove() on it. By using # per dentry lock, it is solved as we d_lookup() will fail the lookup for # unhashed dentries. # -------------------------------------------- # 03/06/25 akpm@digeo.com 1.1310.1.160 # [PATCH] dentry->d_count fixes: hpfs # # From: Maneesh Soni # # - hpfs_unlink() can race with lockless d_lookup(), as we can have situations # where d_lookup() has successfully looked-up a dentry and at the sametime # hpfs_unlink()--->d_drop() has dropped it. Taking the per dentry lock # before checking the d_count in hpfs_unlink() solves this race condition. # -------------------------------------------- # 03/06/26 yoshfuji@linux-ipv6.org 1.1310.78.9 # [IPV6] DAD has to be destined to solicited node mulitcast address. # # Check if DAD is destined for solicited node multicast address # as RFC2461 required. # -------------------------------------------- # 03/06/25 akpm@digeo.com 1.1310.1.161 # [PATCH] workaround for smb_proc_getattr oops # # From: Zwane Mwaikambo # # smbfs tends to oops over a null server->ops->getattr in smb_proc_getattr(). # # Urban says: # # In 2.5 the server->ops is initialized when smbfs gets a connection, to # match whatever the server is capable of or not. This happens after the # mount syscall so smbfs is then mounted but not usable. # # Not sure if smb_lookup is always called before any other operation that # uses server->ops. If it is then it would be enough to have a test there. # # Otherwise I will just change all users of server->ops to verify the # pointer first and return -EIO or something. # # Al Viro says (paraphrasing) # # ugh, we need mount2(). # # It doesn't look to me like we'll be getting mount2() in the 2.6 timeframe. # Zwane's patch implement's Urban's workaround. # -------------------------------------------- # 03/06/25 akpm@digeo.com 1.1310.1.162 # [PATCH] Column counting fix in n_tty.c # # From: Chris Heath # # Here's a column counting bug that was lurking in a corner of n_tty.c. # -------------------------------------------- # 03/06/25 akpm@digeo.com 1.1310.1.163 # [PATCH] normalise node load for NUMA # # From: Andrew Theurer # # This patch ensures that when node loads are compared, the load value is # normalised. Without this, load balance across nodes of dissimilar cpu # counts can cause unfairness and sometimes lower overall performance. # # For example, a 2 node system with 4 cpus in the first node and 2 cpus in # the second. A workload with 6 running tasks would have 3 tasks running on # one node and 3 on the other, leaving one cpu idle in the first node and two # tasks sharing a cpu in the second node. The patch would ensure that 4 # tasks run in the first node and 2 in the second. # # I ran some kernel compiles comparing this patch on a 2 node 4 cpu/2 cpu # system to show the benefits. Without the patch I got 140 second elapsed # time. With the patch I get 132 seconds (6% better). # # Although it is not very common to have nodes with dissimilar cpu counts, it # is already happening. PPC64 systems with partitioning have this happen, # and I expect it to be more common on ia32 as partitioning becomes more # common. # -------------------------------------------- # 03/06/25 akpm@digeo.com 1.1310.1.164 # [PATCH] compat_sys_old_getrlimit() depends on # # From: David Mosberger # # compat_sys_old_getrlimit() depends on sys_old_getrlimit() and the patch # below updates the guarding #ifdef accordingly. # -------------------------------------------- # 03/06/25 akpm@digeo.com 1.1310.1.165 # [PATCH] ext3: fix page lock vs journal_start ranking bug # # ext3_block_truncate_page() is calling grab_cache_page() inside a JBD # transaction. This is wrong, because transactions nest inside lock_page(). # # The deadlock is against shrink_list->ext3_journalled_writepage->journal_start. # # This was not noticed before because we never used to journal writepage() data # in journalled-data mode. And because the deadlock against # generic_file_write() is covered up by i_sem. # # Rework things so that we lock the page prior to starting a transaction. # -------------------------------------------- # 03/06/25 akpm@digeo.com 1.1310.1.166 # [PATCH] ext3: fix memory leak # # We need to unconditionally brelse() the buffer in there, because # journal_remove_journal_head() leaves a ref behind. # # release_buffer_page() does that. Call it all the time because we can usually # strip the buffers and free the page even if it was not marked buffer_freed(). # # Mainly affects data=journal mode # -------------------------------------------- # 03/06/25 akpm@digeo.com 1.1310.1.167 # [PATCH] correct mail addresses for visws support # # From: Andrey Panin # # this trivial patch changes mailing list address for visws subarch support # along with some occurences of my old email addresses. # -------------------------------------------- # 03/06/26 yoshfuji@linux-ipv6.org 1.1310.78.10 # [IPV6] DAD must not have source link-layer option # # Check if DAD does not have source link-layer address option; # RFC2461 7.1.1. # # -------------------------------------------- # 03/06/25 akpm@digeo.com 1.1310.1.168 # [PATCH] NCR53C9x compile fix # # From: Geert Uytterhoeven # # NCR53C9x SCSI: Fix compilation after breakage in 2.5.71 # -------------------------------------------- # 03/06/25 akpm@digeo.com 1.1310.1.169 # [PATCH] htree: set the dir index bit in the right place # # From: Alex Tomas # # Don't set the directory's index flag until we know that we're doing ahead # with the directory modification. # -------------------------------------------- # 03/06/25 akpm@digeo.com 1.1310.1.170 # [PATCH] export flush_tlb_all for drm modules # # From: Jan Dittmer # # This adds an export for flush_tlb_all to i386_ksyms.c. The drm modules # miss this, when compiling for SMP. # # I changed Jan's patch to use EXPORT_SYMBOL_GPL. # -------------------------------------------- # 03/06/25 akpm@digeo.com 1.1310.1.171 # [PATCH] Typo after 8250_cs update (SERIAL) # # From: Francois Romieu # # s/GetConfiguration/GetConfigurationInfo/ # -------------------------------------------- # 03/06/25 torvalds@home.osdl.org 1.1310.1.172 # Merge bk://linux-dj.bkbits.net/cpufreq # into home.osdl.org:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/06/25 torvalds@home.osdl.org 1.1310.1.173 # Merge bk://linux-dj.bkbits.net/agpgart # into home.osdl.org:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/06/25 sfr@canb.auug.org.au 1.1310.1.174 # [PATCH] fix type in compat_sys_fcntl64 # # [Pointed out by Bjorn Helgaas via Arun Sharma] # # This fixes an obvious cut and paste error in my original patch. # -------------------------------------------- # 03/06/25 jejb@raven.il.steeleye.com 1.1310.81.20 # SCSI 53c700: add module_exit routine otherwise module isn't removable # -------------------------------------------- # 03/06/25 jejb@raven.il.steeleye.com 1.1310.81.21 # Add remove method to lasi700.c # -------------------------------------------- # 03/06/25 davem@nuts.ninka.net 1.1310.1.175 # Merge bk://kernel.bkbits.net/jmorris/net-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/06/25 davem@nuts.ninka.net 1.1310.1.176 # [NET]: Define LL_RESERVED_SPACE in terms of HH_DATA_MOD. # -------------------------------------------- # 03/06/25 romieu@fr.zoreil.com 1.1310.1.177 # [NETFILTER]: Fix leaks in error paths of ip_recent_ctrl. # -------------------------------------------- # 03/06/25 yoshfuji@linux-ipv6.org 1.1310.1.178 # [IPV6]: Inappropriate static variable in net/ipv6/ndisc.c # -------------------------------------------- # 03/06/25 bdschuym@pandora.be 1.1310.1.179 # [NETFILTER]: Missing return in arp_packet_match(). # -------------------------------------------- # 03/06/25 bdschuym@pandora.be 1.1310.1.180 # [NETFILTER]: Add arptables mangle module. # -------------------------------------------- # 03/06/25 rob@osinvestor.com 1.1310.84.1 # [SPARC]: Fix LIBS_Y. # -------------------------------------------- # 03/06/25 rob@osinvestor.com 1.1310.84.2 # [SPARC]: Do not use __builtin_trap() on sparc until gcc is fixed. # -------------------------------------------- # 03/06/26 davem@nuts.ninka.net 1.1310.1.181 # [TCP]: Sanitize initcwnd calculation, add new metrics. # 1) Remove srtt etc. tests in tcp_init_cwnd, was buggy # anyways. # 2) Add RTAX_INITCWMD route metric, use this in tcp_init_cwnd() # if non-zero. # 3) Add RTAX_FEATURES (to enable/disable ECN/SACK/TIMESTAMPS # on a per-route basis), currently unused. # -------------------------------------------- # 03/06/26 yoshfuji@linux-ipv6.org 1.1310.1.182 # [IPV6]: Make several ndisc private stuff static. # -------------------------------------------- # 03/06/26 dwmw2@infradead.org 1.1310.85.1 # DiskOnChip Millennium Plus translation layer fixes: # # - Fix geometry reporting. # - Avoid endless loop when deleting a Virtual Unit Chain. # -------------------------------------------- # 03/06/26 dwmw2@infradead.org 1.1310.85.2 # Add missing prototype in drivers/mtd/chips/gen_probe.c # -------------------------------------------- # 03/06/26 torvalds@home.osdl.org 1.1310.86.1 # Merge bk://kernel.bkbits.net/davem/sparc-2.5 # into home.osdl.org:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/06/26 ak@suse.de 1.1310.86.2 # [PATCH] x86-64 merge for 2.5.73 # # Bring the x86-64 architecture code uptodate for 2.5.73. # # One problem is that CONFIG_IDE_TASKFILE corrupts file systems on AMD 8111. It # may be worth to disable it in the configuration. # # - Disable 32bit vsyscalls for now until all bugs can be fixed # - Fix warnings # - Fix NULL pointer reference in 32bit ptrace # - Timing fixes from John Stultz # - Sync show_stack prototype # - Sync nmi and floppy.h code (Mikael P.) # - Set proper defines for AGP # - Make Simics work again # - Scale unit in 32bit sysinfo (originally from ppc64) # -------------------------------------------- # 03/06/26 ak@suse.de 1.1310.86.3 # [PATCH] Fix ACPI compilation for 2.5.73 # # Without this patch ACPI won't compile on AMD64 because of mismatched prototypes. # # Andrew stated that this is the way he wants it to be fixed. # -------------------------------------------- # 03/06/26 ak@suse.de 1.1310.86.4 # [PATCH] Change 64bit epoll ABI for AMD64 # # As discussed earlier. The 64bit epoll ABI on AMD64 is changed to # match 32bit. This way we avoid emulation overhead. # # To catch old binaries I allocate new syscall slots. # -------------------------------------------- # 03/06/26 willy@debian.org 1.1310.86.5 # [PATCH] remove *_segments() dummy functions again # # Last November Linus applied a patch to remove the now-unused # *_segments() functions from all architectures ... but some of the newer # architectures escaped and still have them. # -------------------------------------------- # 03/06/26 torvalds@home.osdl.org 1.1310.86.6 # Merge master.kernel.org:/home/dwmw2/BK/mtd-forlinus-2.5 # into home.osdl.org:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/06/26 jejb@raven.il.steeleye.com 1.1310.81.22 # SCSI: Add missing scsi/scsi_driver.h file # -------------------------------------------- # 03/06/26 willy@debian.org 1.1310.86.7 # [PATCH] Make SCSI selfcontained # # Move all the SCSI Kconfig bits from arch/*/Kconfig into driver/scsi/Kconfig. # Also add notes about FireWire & USB. # -------------------------------------------- # 03/06/26 greg@kroah.com 1.1310.86.8 # [PATCH] PCI Hotplug: pcihp_skeleton: fix delete bug and add release() callback # -------------------------------------------- # 03/06/26 greg@kroah.com 1.1310.86.9 # [PATCH] PCI Hotplug: acpiphp: add release() callback # -------------------------------------------- # 03/06/26 greg@kroah.com 1.1310.86.10 # [PATCH] PCI Hotplug: cpci: fix delete bug and add release() callback # -------------------------------------------- # 03/06/26 greg@kroah.com 1.1310.86.11 # [PATCH] PCI Hotplug: cpqphp: add release() callback and other minor cleanups. # -------------------------------------------- # 03/06/26 greg@kroah.com 1.1310.86.12 # [PATCH] PCI Hotplug: ibmphp: add release() callback and other minor cleanups # -------------------------------------------- # 03/06/26 rth@kanga.twiddle.net 1.1310.87.1 # Merge kanga.twiddle.net:/home/rth/work/linux/linus-2.5 # into kanga.twiddle.net:/home/rth/work/linux/axp-2.5 # -------------------------------------------- # 03/06/26 mzyngier@freesurf.fr 1.1130.1.2 # [PATCH] aha1740 update # # The included patch updates the old aha1740 driver to some of the 2.5 # APIs : # # - Generic DMA API # - EISA probing API # - SCSI hotplug API # # It's been heavily tested on x86 (UP and SMP) as well as alpha (UP) for # the past two months. # -------------------------------------------- # 03/06/26 jejb@raven.il.steeleye.com 1.1310.81.23 # Fix up aha1740 merge problems # -------------------------------------------- # 03/06/26 willy@debian.org 1.1310.86.13 # [PATCH] PCI: i386/pci/direct.c fixes # # - Request resources before using them # - Don't allocate GFP_KERNEL memory with interrupts disabled # - Split pci_direct_init() into three functions to prevent it from # getting too long. # -------------------------------------------- # 03/06/26 willy@debian.org 1.1310.86.14 # [PATCH] PCI: create pci_name() # # This patch introduces pci_name() and converts slot_name into a pointer to # dev.bus_id. # -------------------------------------------- # 03/06/26 davem@nuts.ninka.net 1.1310.1.183 # Merge nuts.ninka.net:/home/davem/src/BK/network-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/06/26 gerg@snapgear.com 1.1310.88.1 # [PATCH] define KCORE_ELF in m68knommu/Kconfnig # # Define missing type for CONFIG_KCORE_ELF in m68knommu/Kconfig. # -------------------------------------------- # 03/06/26 gerg@snapgear.com 1.1310.88.2 # [PATCH] fix do_settimeofday() for 'struct timespec' argument # # Modify m68knommu do_settimeofday() routine to take "struct timespec" # argument, and adjust code to handle nsec size quantities. # -------------------------------------------- # 03/06/26 bcollins@debian.org 1.1310.88.3 # [PATCH] Update IEEE1394 (r972) # # IEEE1394 : Kbuildify oui2c. # ALL : C construct cleanups, macro namespace cleanups. # ETH1394 : Limited multicast support. Minor fixes for IPv4 interop. # ETH1394 : Add ethtool support. # -------------------------------------------- # 03/06/27 yoshfuji@linux-ipv6.org 1.1310.89.1 # [IPV6] Fixed fragment check in ip6_output.c:ip6_fragment() # # MTU / alignment check in ip6_fragment() was wrong; # first_len was not correct. # # -------------------------------------------- # 03/06/27 ahaas@airmail.net 1.1310.89.2 # [NET] Remove some 0 initializers. # # These small patches remove a number of '.maxlen = 0,' initializers. # # -------------------------------------------- # 03/06/27 herbert@gondor.apana.org.au 1.1310.89.3 # [XFRM] Set port/proto in acquire messages. # # Also append policy spec to acquire message. # -------------------------------------------- # 03/06/26 hch@lst.de 1.1310.81.24 # [PATCH] use generic dma direction bits in scsi # # Make the *_data_direction flags of type enum dma_data_direction from # the generic dma mapping API. The SCSI_DATA_* defines are kept for # compatiblity and map to the dma mapping API values now. # scsi_to_pci_dma_dir and scsi_to_sbus_dma_dir are kept as stubs - # we define them to nothing as both the PCI and SBUS constants have # the same values as the generic dma mapping ones. Unfortunately # we can't check anymore whether someone messes this up as the values # are enumes now and not cpp defines. # -------------------------------------------- # 03/06/26 jejb@raven.il.steeleye.com 1.1310.81.25 # Fix scsi drivers needing to include # # With the simplification of the DMA direction/SCSI data direction # linux/pci.h is no longer pulled in by scsi.h # -------------------------------------------- # 03/06/26 jejb@raven.il.steeleye.com 1.1310.81.26 # Remove linux/pci.h dependency in SCSI 53c700 # # The consolidation of the SCSI data direction flags eliminate the # need for it. # -------------------------------------------- # 03/06/26 jejb@raven.il.steeleye.com 1.1310.81.27 # Fix SCSI data direction issues in aha1740 merger # # and also remove no longer used .command entry # -------------------------------------------- # 03/06/26 jejb@raven.il.steeleye.com 1.1310.81.28 # Fix up data direction in SCSI abstracted mode sense # -------------------------------------------- # 03/06/26 typhoon.adm@hostme.bitkeeper.com 1.1310.90.1 # Merge bk://linux.bkbits.net/linux-2.5 # into hostme.bitkeeper.com:/repos/t/typhoon/typhoon-2.5 # -------------------------------------------- # 03/06/26 greg@kroah.com 1.1310.86.15 # PCI Hotplug: acpiphp: stupid typo fixes. # -------------------------------------------- # 03/06/26 jejb@raven.il.steeleye.com 1.1310.81.29 # SCSI: Move can_queue == 0 check # # Some HBA drivers don't set this until their ->detect routines, # so don't check for it until scsi_add_host # -------------------------------------------- # 03/06/27 dave@thedillows.org 1.1310.91.1 # Fix misreporting of card type and spurious "already scheduled" messages. # -------------------------------------------- # 03/06/26 torvalds@home.osdl.org 1.1310.86.16 # Merge bk://kernel.bkbits.net/gregkh/linux/pci-2.5 # into home.osdl.org:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/06/27 dave@thedillows.org 1.1310.92.1 # Merge thedillows.org:/home/il1/projects/kernel/pristine/linus-2.5 # into thedillows.org:/home/il1/projects/typhoon/bk/typhoon-2.5 # -------------------------------------------- # 03/06/26 davem@nuts.ninka.net 1.1310.1.184 # [NET]: Kill skb_linearize() and bogus feature flag settings in eth1394.c # -------------------------------------------- # 03/06/27 dave@thedillows.org 1.1310.90.2 # Merge ssh://typhoon@typhoon.bkbits.net/typhoon-2.5 # into thedillows.org:/home/il1/projects/typhoon/bk/typhoon-2.5 # -------------------------------------------- # 03/06/26 davem@nuts.ninka.net 1.1310.1.185 # Merge bk://kernel.bkbits.net/jmorris/net-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/06/26 davem@nuts.ninka.net 1.1310.1.186 # Merge http://linux-lksctp.bkbits.net/lksctp-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/06/27 davem@nuts.ninka.net 1.1310.1.187 # [TCP]: Handle lack of cached dst in tcp_init_cwnd(). # -------------------------------------------- # 03/06/27 davem@nuts.ninka.net 1.1310.1.188 # [TCP]: If we have a lot of time-wait sockets to kill, do it via workqueue. # -------------------------------------------- # 03/06/27 davem@nuts.ninka.net 1.1310.1.189 # Merge Ben's and my fixes. # -------------------------------------------- # 03/06/27 jmorris@kernel.bkbits.net 1.1310.86.17 # Merge kernel.bkbits.net:/home/torvalds/linux-2.5 # into kernel.bkbits.net:/home/jmorris/net-2.5 # -------------------------------------------- # 03/06/27 markh@osdl.org 1.1310.81.30 # [PATCH] Fix aacraid status returns # # aacraid was using the old and erroneously unshifted status return # codes. Switch it to use the new SAM_STAT_ codes that don't need # shifting. # -------------------------------------------- # 03/06/27 anton@samba.org 1.1310.81.31 # [PATCH] remove a bogus check in sym2 driver # # The sym2 driver has a check for a very broken bios where it seems # devices appear twice. This test is broken on a machine with PCI domains # since busnumber:devfn is not a unique identifier. # # When we move to the scsi hotplug interface all this code will go away # but in the short term we need the following fix. # -------------------------------------------- # 03/06/27 neilb@cse.unsw.edu.au 1.1310.93.1 # [PATCH] Use new svc_export_show to implement e_show for /proc/fs/nfs/exports # # Also remove the path_buf that was passed around for # /proc/fs/nfs/exports as the existance of seq_path removes the need # for this. # -------------------------------------------- # 03/06/27 neilb@cse.unsw.edu.au 1.1310.93.2 # [PATCH] Remove path buffer passed around by cache_show routines # # this was need for paths, but now we have seq_path... # -------------------------------------------- # 03/06/27 neilb@cse.unsw.edu.au 1.1310.93.3 # [PATCH] NFSv4 server OPEN_CONFIRM # # From: "William A.(Andy) Adamson" # # Add OPEN_CONFIRM functionality to the nfsv4 server, including a # preprocess_seqid_op function that will be used in subsequent patches. # -------------------------------------------- # 03/06/27 neilb@cse.unsw.edu.au 1.1310.93.4 # [PATCH] NFSv4 server Close state # # From: "William A.(Andy) Adamson" # # Add share state processing to nfsd4_close. it includes some more # debug counters. # -------------------------------------------- # 03/06/27 neilb@cse.unsw.edu.au 1.1310.93.5 # [PATCH] NFSv4 server - open-downgrade # # From: "William A.(Andy) Adamson" # # Add the opendowngrade call with share state processing. it includes # nfs4_preprocess_stateid_op() which will be used in read and write # state processing. # -------------------------------------------- # 03/06/27 neilb@cse.unsw.edu.au 1.1310.93.6 # [PATCH] NFSv4 server - Read "share" state # # From: "William A.(Andy) Adamson" # # this patch adds share state processing to nfsd4_read(). # -------------------------------------------- # 03/06/27 neilb@cse.unsw.edu.au 1.1310.93.7 # [PATCH] NFSv4 server - Write "share" state # # From: "William A.(Andy) Adamson" # # this patch adds share state processing to nfsd4_write(). # -------------------------------------------- # 03/06/27 neilb@cse.unsw.edu.au 1.1310.93.8 # [PATCH] NFSv4 server - setattr share state # # From: "William A.(Andy) Adamson" # # this patch adds share state processing to nfsd4_setattr(). # -------------------------------------------- # 03/06/27 neilb@cse.unsw.edu.au 1.1310.93.9 # [PATCH] NFSv4 server - missing locking # # From: "William A.(Andy) Adamson" # # sorry. i forgot to lock the nfsv4 state in nfsd4_read, nfsd4_write, and # nfsd4_setattr. # -------------------------------------------- # 03/06/27 neilb@cse.unsw.edu.au 1.1310.93.10 # [PATCH] NFSv4 server - Removed duplicate #define # # Already defined in state.h # -------------------------------------------- # 03/06/27 neilb@cse.unsw.edu.au 1.1310.93.11 # [PATCH] Provoide refrigerator support for nfsd # # Call refrigerator() in svc_recv, so it is there for nfsd and # no longer needed explicitly in lockd. # -------------------------------------------- # 03/06/27 randy.dunlap@verizon.net 1.1310.93.12 # [PATCH] remove IO APIC newline # # This patch is to 2.5.73-bk4 and is purely cosmetic. Please apply. # It removes the blank line after "testing the IO APIC....": # -------------------------------------------- # 03/06/27 david@gibson.dropbear.id.au 1.1310.93.13 # [PATCH] Fix compile with !CONFIG_VT # # Architectures using the generic 32/64-bit ioctl() compatibility shims # will get a link error if CONFIG_VT is not defined, since the # compatbility ioctl() code calls functions in drivers/char/vt.c which # is only included in the build if CONFIG_VT is set. # # This fixes the compile with a couple of #ifdefs: # -------------------------------------------- # 03/06/27 gerg@snapgear.com 1.1310.93.14 # [PATCH] fix arguments of show_stack() # # Fix the m68knommu version of show_stack(). It expects the task as an # argument. # -------------------------------------------- # 03/06/27 gerg@snapgear.com 1.1310.93.15 # [PATCH] conditional ROMfs copy for M5206eLITE board # # Make the ROMfs copy in the startup code for Motorola/M5206eLITE board # conditional on actually using a ROMfs setup. # -------------------------------------------- # 03/06/27 gerg@snapgear.com 1.1310.93.16 # [PATCH] conditional ROMfs copy for NETtel/5272 board # # Make the ROMfs copy in the startup code for NETtel/5272 board # conditional on actually using a ROMfs setup. # -------------------------------------------- # 03/06/27 rusty@rustcorp.com.au 1.1310.93.17 # [PATCH] Use Local Percpu Macros for Local Percpu Variables # # In general, it is more better to use get_cpu_var() and __get_cpu_var() # to access per-cpu variables on this CPU than to use smp_processor_id() # and per_cpu(). In the current default implemention they are equivalent, # but on IA64 the former is already faster, and other archs will follow. # -------------------------------------------- # 03/06/27 torvalds@home.osdl.org 1.1310.1.190 # Merge bk://kernel.bkbits.net/davem/net-2.5 # into home.osdl.org:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/06/27 schwidefsky@de.ibm.com 1.1310.1.191 # [PATCH] s390: base fixes # # - Remove unused variables from smp.c. # - Reserve system call number 110 for sys_lookup_dcache. # - Fix show_trace. # - Remove superfluous asm include file. # - Add statfs64 structure. # -------------------------------------------- # 03/06/27 schwidefsky@de.ibm.com 1.1310.1.192 # [PATCH] s390: 31 bit compat. # # - Add missing includes to compat_ioctl.c. # - Fix 32 bit emulation of sys_settimeofday. # -------------------------------------------- # 03/06/27 schwidefsky@de.ibm.com 1.1310.1.193 # [PATCH] s390: common i/o layer. # # - Make ccwgroup online attribute consistent with ccw online attribute. # - Add link incident record handling to channel subsystem code. # - Do path grouping only if the device driver explicitly requests it. # - Fix multicast or broadcast flood ping hand on HiperSockets. # -------------------------------------------- # 03/06/27 schwidefsky@de.ibm.com 1.1310.1.194 # [PATCH] s390: dasd driver. # # - Simplify long busy condition handling, add quiesce/resume ioctl. # - Add sense data area to reserve/release/steal_lock ccw-chains. # -------------------------------------------- # 03/06/27 schwidefsky@de.ibm.com 1.1310.1.195 # [PATCH] s390: set module owner. # # Pass correct argument to SET_MODULE_OWNER. # -------------------------------------------- # 03/06/27 schwidefsky@de.ibm.com 1.1310.1.196 # [PATCH] s390: typos. # # Fix typos. # -------------------------------------------- # 03/06/27 schwidefsky@de.ibm.com 1.1310.1.197 # [PATCH] s390: tty3215_init. # # Add return statement to tty init function of 3215 driver. # -------------------------------------------- # 03/06/27 willy@debian.org 1.1310.1.198 # [PATCH] [KCONFIG] Make cdrom Kconfig selfcontained # # This patch moves all the duplicated cdrom Kconfig bits from arch/*/Kconfig # to drivers/cdrom/Kconfig # -------------------------------------------- # 03/06/27 rth@kanga.twiddle.net 1.1310.87.2 # [ALPHA] Define memset via symbol copy for ev6 as well. # -------------------------------------------- # 03/06/27 rth@kanga.twiddle.net 1.1310.1.199 # Merge kanga.twiddle.net:/home/rth/work/linux/linus-2.5 # into kanga.twiddle.net:/home/rth/work/linux/axp-2.5 # -------------------------------------------- # 03/06/27 greg@kroah.com 1.1310.94.1 # Cset exclude: cweidema@indiana.edu|ChangeSet|20030621162021|08529 # -------------------------------------------- # 03/06/27 B.Zolnierkiewicz@elka.pw.edu.pl 1.1310.95.1 # [PATCH] ide: TCQ initialization fixes # # - do not enable TCQ in ide_init_drive(), its too early # - enable TCQ in __ide_dma_on() only if CONFIG_BLK_DEV_IDE_TCQ_DEFAULT=y # - try to enable TCQ only on disk drives # - correct check for two drives on one channel # -------------------------------------------- # 03/06/27 B.Zolnierkiewicz@elka.pw.edu.pl 1.1310.95.2 # [PATCH] ide: fix IRQ handler returns # # Make the IDE driver return the proper status return # for unhandled interrupts. # -------------------------------------------- # 03/06/27 B.Zolnierkiewicz@elka.pw.edu.pl 1.1310.95.3 # [PATCH] ide: fix drive->unmask handling for taskfile PIO # -------------------------------------------- # 03/06/27 B.Zolnierkiewicz@elka.pw.edu.pl 1.1310.95.4 # [PATCH] ide: proper allocation of hwif->io_ports resources # -------------------------------------------- # 03/06/27 B.Zolnierkiewicz@elka.pw.edu.pl 1.1310.95.5 # [PATCH] ide: tiny cleanup of "ideX=ata66" parameter handling in ide_setup() # # hwif->udma_four is always preset to 0 # -------------------------------------------- # 03/06/27 B.Zolnierkiewicz@elka.pw.edu.pl 1.1310.95.6 # [PATCH] ide: remove dead code from ide_raw_build_sglist() # -------------------------------------------- # 03/06/27 B.Zolnierkiewicz@elka.pw.edu.pl 1.1310.95.7 # [PATCH] ide: remove dead and broken ide_diag_taskfile() variant # -------------------------------------------- # 03/06/27 B.Zolnierkiewicz@elka.pw.edu.pl 1.1310.95.8 # [PATCH] ide: tiny cleanup of ide_init(), it is called only _once_ # -------------------------------------------- # 03/06/27 jgarzik@redhat.com 1.1310.95.9 # Merge redhat.com:/garz/repo/linus-2.5 # into redhat.com:/garz/repo/net-drivers-2.5 # -------------------------------------------- # 03/06/27 rth@kanga.twiddle.net 1.1310.1.200 # [ALPHA] No, really fix memset. Really. # -------------------------------------------- # 03/06/27 daniel.ritz@gmx.ch 1.1310.95.10 # [PATCH] module ref counting for airo.c # # clean up airo.c: remove MOD_(INC|DEC)_USE_COUNT, set the owner field instead. # compile tested only. against 2.5.73-bk # -------------------------------------------- # 03/06/27 daniel.ritz@gmx.ch 1.1310.95.11 # [PATCH] strip.c: don't allocate net_device as part of private struct # # hi jeff # # cleans up strip.c not to allocate struct net_device as part of the private # structure. use a separate kmalloc (and kfree). compile tested only. # against 2.5.73-bk # # -daniel # -------------------------------------------- # 03/06/27 daniel.ritz@gmx.ch 1.1310.95.12 # [PATCH] alloc_etherdev for netwave_cs.c # # erm...i didn't actually compile it... # sorry. corrected patch below. # # -daniel # # On Fri June 27 2003 00:45, Daniel Ritz wrote: # > cleans up netwave_cs.c to use alloc_etherdev instead of allocating the # > device out of the private data structure. compile tested only. # > against 2.5.73-bk # -------------------------------------------- # 03/06/27 gandalf@wlug.westbo.se 1.1310.95.13 # [PATCH] fix use-after-free in e100 # -------------------------------------------- # 03/06/27 davem@nuts.ninka.net 1.1310.96.1 # [NET]: Scale DST/ipv6 intervals like we did for ipv4. # -------------------------------------------- # 03/06/28 anton@samba.org 1.1330 # Merge samba.org:/scratch/anton/linux-2.5 # into samba.org:/scratch/anton/tmp3 # -------------------------------------------- # 03/06/28 shemminger@osdl.org 1.1310.96.2 # [NET]: Fix PPP async regression. # # Fix PPP over async regression that the PPPoE changes caused. # Basically, PPP puts a zero length skbuff in the receive queue # as an error token, and the last change caused that to get flushed # as bad data. # # Thanks to Diego Calleja Garcia, Matthew Harrell for validating this. # -------------------------------------------- # 03/06/28 hch@lst.de 1.1310.81.32 # [PATCH] fix an aha1740 merge error # # it should use scsi_host_alloc/scsi_host_put now. # -------------------------------------------- # 03/06/28 rth@kanga.twiddle.net 1.1310.1.201 # [ALPHA] Set wall_to_monotonic on timer_init and settimeofday. # -------------------------------------------- # 03/06/28 rth@kanga.twiddle.net 1.1310.1.202 # [ALPHA] Eliminate struct declared in prototype warnings in asm/elf.h. # -------------------------------------------- # 03/06/28 rth@are.twiddle.net 1.1310.1.203 # Merge ssh://kanga/work/linux/axp-2.5 # into are.twiddle.net:/home/rth/BK/axp-2.5 # -------------------------------------------- # 03/06/28 jejb@raven.il.steeleye.com 1.1310.81.33 # Eliminate really old ncr53c8xx driver # # - Remove direct configuration of this driver # - Only remaining use is in the parisc zalon driver # - Split the driver up to make it more use to 720 based drivers # - Update zalon to new module/SCSI methods # -------------------------------------------- # 03/06/28 torvalds@home.osdl.org 1.1310.1.204 # Merge bk://are.twiddle.net/axp-2.5 # into home.osdl.org:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/06/28 da-x@gmx.net 1.1310.1.205 # [PATCH] avoid Oops in net/core/dev.c # # This fixes the kernel crash in the case when we do an SIOCSIFNAME # ioctl on /proc/net/dev to rename a network interface, and # we supply a string such as "foo%sbar". # -------------------------------------------- # 03/06/28 akpm@digeo.com 1.1310.1.206 # [PATCH] check for presence of readpage() in the readahead code # # Make sure that the address_space is capable of performing the readahead # before going in and allocating the pages. # -------------------------------------------- # 03/06/28 akpm@digeo.com 1.1310.1.207 # [PATCH] Fix reiserfs BUG # # From: Oleg Drokin # # Fix BUG_ON(!buffer_mapped(bh)) in submit_bh() # # Reiserfs is submitting unmapped buffers into submit_bh(), which trips a # BUG. # -------------------------------------------- # 03/06/28 akpm@digeo.com 1.1310.1.208 # [PATCH] Fix syslog(2) EFAULT reporting # # From: Andi Kleen # # Add proper EFAULT reporting to sys_syslog. # # This fixes some silly LTP test in the 32bit emulation of an AMD64 kernel. # -------------------------------------------- # 03/06/28 akpm@digeo.com 1.1310.1.209 # [PATCH] Fix ide-cd rw mounts # # From: Kouichi ONO # # in 2.5.73, I can't read/write mount DVD-RAM via ide-scsi (only r/o mount). # Without ide-scsi, I can mount DVD-RAM read/write mode and works fine. # # (acked by Jens). # -------------------------------------------- # 03/06/28 akpm@digeo.com 1.1310.1.210 # [PATCH] Remove check_region and MOD_*_USE_COUNT from # # From: Bob Miller # # - Replace the call to MOD_INC_USE_COUNT with a __module_get() when # forcing the module to not be unloadable. # # - Remove the check_region() calls and restructured things to only use # request_region(). # -------------------------------------------- # 03/06/28 akpm@digeo.com 1.1310.1.211 # [PATCH] Remove racy check_mem_region() call from arc-rimi.c # # From: Bob Miller # # Removed the check_mem_region() call and replaced with request_mem_region(). # # Because of the way the driver is structured the first request_mem_region() # call gets the default memory area. After probing the complete memory area # that is needed to communicate with the device is known, so the first memory # area is released and the complete area is requested. # -------------------------------------------- # 03/06/28 akpm@digeo.com 1.1310.1.212 # [PATCH] kmem_cache_destroy() forgets to drain all objects # # From: Philippe Elie # # kmem_cache_destroy() can fail with the following error: slab error in # kmem_cache_destroy(): cache `xxx': Can't free all objects but the cache # user really free'd all objects # # This is because drain_array_locked() only frees 80% of thge objects. # # Fix it by adding a parameter to drain_array_locked() telling it to drain # 100% of the objects. # -------------------------------------------- # 03/06/28 akpm@digeo.com 1.1310.1.213 # [PATCH] ext3: remove the version number # # The ext3 version number hasn't been updated since ext3 was merged. # # We track ext3 via the kernel release ID. Remove the ext3 version # number. # -------------------------------------------- # 03/06/28 akpm@digeo.com 1.1310.1.214 # [PATCH] cdrom eject scribbles on the request flags # # From: Nick Piggin # # It converts writes to reads and we end up returning the request to the wrong # queue. # -------------------------------------------- # 03/06/28 akpm@digeo.com 1.1310.1.215 # [PATCH] nmclan_cs compile fix # # nmclan_cs doesn't compile with older compilers # -------------------------------------------- # 03/06/28 tcallawa@redhat.com 1.1310.97.1 # [SPARC64]: Fix OBP version parsing on newer systems. # -------------------------------------------- # 03/06/28 davem@nuts.ninka.net 1.1310.97.2 # [SPARC64]: Fix build error from OBP parsing patch. # -------------------------------------------- # 03/06/28 jejb@raven.il.steeleye.com 1.1310.81.34 # Add NCR Quad 720 SCSI driver # # This adds support for the Q720 MCA SCSI driver. It's only really # useful on the voyager platform. The driver is preliminary and # currently makes no use of the Q720 on-board memory for storing # scripts and ccbs. # -------------------------------------------- # 03/06/28 jejb@raven.il.steeleye.com 1.1310.81.35 # Fix logic reversal in scsi_host_alloc # -------------------------------------------- # 03/06/29 jmorris@kernel.bkbits.net 1.1310.1.216 # Merge kernel.bkbits.net:/home/torvalds/linux-2.5 # into kernel.bkbits.net:/home/jmorris/net-2.5 # -------------------------------------------- # 03/06/29 anton@samba.org 1.1331 # Merge samba.org:/scratch/anton/linux-2.5 # into samba.org:/scratch/anton/tmp3 # -------------------------------------------- # 03/06/29 yoshfuji@linux-ipv6.org 1.1310.98.1 # [IPV6] Don't set M flag in last fragment. # -------------------------------------------- # 03/06/29 yoshfuji@linux-ipv6.org 1.1310.98.2 # [IPV6] Use macro for M-Flag and clean-up. # # Use macro IP6_MF for the M-Flag. # Clean-up for readability (commented by ). # -------------------------------------------- # 03/06/29 yoshfuji@linux-ipv6.org 1.1310.98.3 # [IPV6] Convert /proc/net/ip6_flowlabel to seq_file. # -------------------------------------------- # 03/06/29 yoshfuji@linux-ipv6.org 1.1310.1.217 # Merge kernel.bkbits.net:/home/jmorris/net-2.5 # into linux-ipv6.org:/home/jmorris/bk/net/work-2.5 # -------------------------------------------- # 03/06/30 yoshfuji@linux-ipv6.org 1.1310.1.218 # [XFRM] Fix typo. # -------------------------------------------- # 03/06/30 herbert@gondor.apana.org.au 1.1310.1.219 # [XFRM] Set SA saddr correctly # # The source address of an SA is not necessarily equal to the source address # in the selector. This patch addresses this problem. # -------------------------------------------- # 03/06/30 herbert@gondor.apana.org.au 1.1310.99.1 # [IPSEC] split xfrm_state_replace + fixes # # Split xfrm_state_replace into xfrm_state_add and xfrm_state_replace. # # Fixes: # 1. Only update update lifetime and encap options if the state is valid. # 2. Disallow updates to states that do not exist. # 3. Bail if afinfo cannot be found. # # This brings SADB_UPDATE in line with what is required by RFC2367. # It is also needed by SFS NAT-T support as it needs to update valid # states when the encap ports move. # # I've tweaked the logic slightly so that SADB_UPDATE will fail on a # larval state that hasn't undergone SADB_GETSPI. This is what RFC2367 # calls for and it simplifies the code in that we don't have to call # find_acq for SADB_UPDATE. # # This doesn't affect any of the three KMs as they either don't use # SADB_UPDATE or call SADB_GETSPI before doing an update. # -------------------------------------------- # 03/06/29 bcollins@debian.org 1.1310.100.1 # [PATCH] Update IEEE1394 (r986) # # ETH1394 : - Minor cleanups. # - Fix incorrect error handling with no broadcast channel. # - Set max/default MTU to 1500. # - Fix broken spinlock handling on device open. # IEEE1394 : Make bus-nodeid printk's of a consistent format. # OHCI1394 : Change one printk to a verbose/debug only message. # -------------------------------------------- # 03/06/29 alan@lxorguk.ukuu.org.uk 1.1310.100.2 # [NET]: Add EDP2 ethernet protocol ID. # -------------------------------------------- # 03/06/30 jmorris@intercode.com.au 1.1310.1.220 # Merge intercode.com.au:/home/jmorris/bk/net/ipsec-2.5 # into intercode.com.au:/home/jmorris/bk/net/net-2.5 # -------------------------------------------- # 03/06/30 anton@samba.org 1.1332 # Merge samba.org:/scratch/anton/linux-2.5 # into samba.org:/scratch/anton/tmp3 # -------------------------------------------- # 03/06/29 jejb@jet.(none) 1.1310.81.36 # Fix scsi device starvation handling # # Doing some debugging after the SDET failure, I found that # if we reject a command at zero depth, we can get into the # infinite loop where we refuse a command to a LUN because it # is starved, but there's no returning command to run the SCSI # queues and fix the starvation. # # The solution is to accept the command and remove the LUN from # the starved list. # -------------------------------------------- # 03/06/29 Kai.Makisara@kolumbus.fi 1.1310.81.37 # [PATCH] scsi_ioctl_send_command fix # # The SCSI_IOCTL_SEND_COMMAND ioctl does not work in 2.5.73-bk7. The # following patch (possibly mangled by my mail client) does fix the problem # (introduced in 2.5.73): # -------------------------------------------- # 03/06/29 davem@nuts.ninka.net 1.1310.1.221 # Merge bk://kernel.bkbits.net/jmorris/net-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/06/29 jejb@jet.(none) 1.1310.101.1 # Merge jet.(none):/home1/jejb/BK/scsi-misc-2.5 # into jet.(none):/home1/jejb/BK/scsi-for-linus-2.5 # -------------------------------------------- # 03/06/30 jmorris@kernel.bkbits.net 1.1310.102.1 # Merge kernel.bkbits.net:/home/torvalds/linux-2.5 # into kernel.bkbits.net:/home/jmorris/net-2.5 # -------------------------------------------- # 03/07/01 yoshfuji@linux-ipv6.org 1.1310.102.2 # [IPV6] put ipv6_rcv_saddr_equal() common place # -------------------------------------------- # 03/07/01 yoshfuji@linux-ipv6.org 1.1310.102.3 # [NET] fixed /proc/net/raw{,6} seq_file support # -------------------------------------------- # 03/07/01 yoshfuji@linux-ipv6.org 1.1310.102.4 # [IPV6] Fix bug in /proc/net/ip6_flowlabel seq_file conversion # -------------------------------------------- # 03/06/30 ink@jurassic.park.msu.ru 1.1310.103.1 # [ALPHA] Set HAE-4 for SABLE/LYNX # # From Jay Estabrook: # > Here's a real short one that fixes a GENERIC build problem introduced # > in pre2, and finalizes the SABLE/LYNX support setting of HAE-4, making # > X servers finally work on those platforms. # -------------------------------------------- # 03/06/30 rmk@flint.arm.linux.org.uk 1.1310.104.1 # [PCMCIA] Move "owner" field to pcmcia_socket. # # Move ->owner field from socket operations to pcmcia_socket. (This # change is mainly for the SA11xx drivers, which use a core driver # for the chip, and a separate module for all the machine specific # bits.) # -------------------------------------------- # 03/07/01 anton@samba.org 1.1333 # ppc64: any_online_cpu returns NR_CPUS on fail # -------------------------------------------- # 03/06/30 mdharm-usb@one-eyed-alien.net 1.1310.94.2 # [PATCH] USB storage: unusual_devs.h cleanups # # This patch re-sorts unusual_devs.h and removes some duplicate entries. # -------------------------------------------- # 03/06/30 mdharm-usb@one-eyed-alien.net 1.1310.94.3 # [PATCH] USB storage: create associate_dev(), more US_*_DEVICE printout # # This patch creates an associate_dev(), which is the mirror to # disassociate_dev(). It also adds some more printout when identifiying # devices that qualify for US_*_DEVICE codes so we need less interaction with # the reporting user. # -------------------------------------------- # 03/06/30 mdharm-usb@one-eyed-alien.net 1.1310.94.4 # [PATCH] USB storage: avoid sending URBs when disconnecting # # This patch avoids sending URBs which are part of the reset system when the # device is being disconnected. It also makes the control thread avoid # starting anything for a device in that state. # -------------------------------------------- # 03/06/30 mdharm-usb@one-eyed-alien.net 1.1310.94.5 # [PATCH] USB storage: create private I/O buffer # # This patch creates a private I/O buffer for the 'core' subdrivers. This # allows us to fix all cases of DMAing to/from the stacks, statics, or other # bad places. # -------------------------------------------- # 03/06/30 mdharm-usb@one-eyed-alien.net 1.1310.94.6 # [PATCH] USB storage: Cosmetic cleanups # # This is some cosmetic cleanups. Things like changing dr to cr (they used # to stand for usb_devrequest, which is now usb_ctrlrequest), using strlcpy # instead of strncpy, and modifying some comments. # -------------------------------------------- # 03/06/30 mdharm-usb@one-eyed-alien.net 1.1310.94.7 # [PATCH] USB storage: General purpose I/O buffer allocation and management # # This patch makes our private I/O buffer allocated such that it's pre-mapped # for DMA. We then add some logic to make sure that we don't try to re-map # it. # # We also make the size of the buffer large enough for other sub-drivers, # which will be converted shortly. # -------------------------------------------- # 03/06/30 mdharm-usb@one-eyed-alien.net 1.1310.94.8 # [PATCH] USB storage: logic cleanup # # This patch cleans up the logic involved in setting URB flags a bit so it's # more evident that some flags are always set and other flags are only set # under certain conditons. # -------------------------------------------- # 03/06/30 grigouze@noos.fr 1.1310.94.9 # [PATCH] USB: zaurus SL-C700 # # This is a patch for usbnet for working with Zaurus SL-C700. # The productid is different from other Zaurus, so i add an entry for it :) # -------------------------------------------- # 03/06/30 greg@kroah.com 1.1310.105.1 # Merge kroah.com:/home/greg/linux/BK/bleed-2.5 # into kroah.com:/home/greg/linux/BK/gregkh-2.5 # -------------------------------------------- # 03/06/30 rmk@flint.arm.linux.org.uk 1.1310.104.2 # [PCMCIA] Ref-count the socket driver module on card insertion/removal. # # Get/Put module when we insert and remove a card. This avoids a # potential deadlock when socket drivers are unloaded, and we have # a cardbus card known to the system. # -------------------------------------------- # 03/06/30 rmk@flint.arm.linux.org.uk 1.1310.104.3 # [PCMCIA] Remove original module use accounting in register_callback. # -------------------------------------------- # 03/06/30 rmk@flint.arm.linux.org.uk 1.1310.104.4 # [PCMCIA] Add work-around for bouncy card detect signals. # # Add work-around for i82365-based socket drivers to the core PCMCIA # code. Since insert processing is not a time critical event, we can # afford to delay (by sleeping) these for everyone. # -------------------------------------------- # 03/06/30 rmk@flint.arm.linux.org.uk 1.1310.104.5 # [PCMCIA] Allow socket drivers call pcmcia_parse_events directly. # # Remove register_callback methods. Instead, allow socket drivers # pass their events directly into cs.c via pcmcia_parse_events(). # -------------------------------------------- # 03/06/30 rmk@flint.arm.linux.org.uk 1.1310.104.6 # [PCMCIA] Remove now obsolete work queues, spinlocks and variables. # # Since the cs.c pcmcia core has a per-socket thread, we don't need each # socket driver having a work queue and associated complexity. # # Therefore, remove this complexity and allow the socket drivers to call # pcmcia_parse_events directly from their interrupt or timer handlers. # -------------------------------------------- # 03/06/30 rth@kanga.twiddle.net 1.1310.106.1 # [ALPHA] Fix SETTLS -- read TLS value to install before clobbering it. # -------------------------------------------- # 03/06/30 rth@kanga.twiddle.net 1.1310.103.2 # Merge ssh://are/BK/axp-2.5 # into kanga.twiddle.net:/home/rth/work/linux/axp-2.5 # -------------------------------------------- # 03/06/30 torvalds@home.osdl.org 1.1310.107.1 # Merge bk://are.twiddle.net/axp-2.5/ # into home.osdl.org:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/06/30 greg@kroah.com 1.1310.105.2 # [PATCH] USB: turn down some debugging messages in uhci-hcd. # -------------------------------------------- # 03/06/30 torvalds@home.osdl.org 1.1310.104.7 # Merge bk://bk.arm.linux.org.uk/linux-2.5-pcmcia # into home.osdl.org:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/06/30 torvalds@home.osdl.org 1.1310.1.222 # Merge bk://kernel.bkbits.net/davem/net-2.5 # into home.osdl.org:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/06/30 torvalds@home.osdl.org 1.1310.1.223 # Merge bk://linux-scsi.bkbits.net/scsi-for-linus-2.5 # into home.osdl.org:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/06/30 James.Bottomley@SteelEye.com 1.1310.1.224 # [PATCH] move sg_dma_ macros out of asm-i386/pci.h # # These macros belong in asm-i386/scatterlist.h instead. # # As the headers are disentangled this has shown up as a problem with my # MCA SCSI drivers since they no-longer include asm/pci.h in any form but # need to traverse the scatterlist. # -------------------------------------------- # 03/06/30 James.Bottomley@SteelEye.com 1.1310.1.225 # [PATCH] update show_stack() in voyager for new prototype # # When show_stack() was changed to take two arguments, the use in the # voyager code was not converted. This patch makes the correct # conversion. # -------------------------------------------- # 03/06/30 spse@secret.org.uk 1.1310.1.226 # [PATCH] pcmciamtd update # # Resync with CVS. Minor update including better handling of device removal. # -------------------------------------------- # 03/06/30 gerg@snapgear.com 1.1310.1.227 # [PATCH] conditional ROMfs copy for Motorola M5282EVB board # # Make the ROMfs copy in the startup code for Motorola M5282EVB board # conditional on actually using a ROMfs setup. # -------------------------------------------- # 03/06/30 gerg@snapgear.com 1.1310.1.228 # [PATCH] fix compile warnings ColdFire PIT timer # # Include interrupt.h in the Motorola ColdFire PIT timer code. # Cleans up compiler warning. # -------------------------------------------- # 03/06/30 gerg@snapgear.com 1.1310.1.229 # [PATCH] selection of boot parameters at configure time for Motorola 5307 targets # # Allow selection of boot arguments at configure time for the Motorola # ColdFire 5307 targets. # -------------------------------------------- # 03/06/30 anton@samba.org 1.1310.1.230 # [PATCH] fix return value after hugetlb mmap failure # # At the moment no one uses is_aligned_hugepage_range or is_hugepage_only_range, # but it is reasonable to assume they return true or false. # # On error we want to return -EINVAL back to userspace. # -------------------------------------------- # 03/06/30 torvalds@home.osdl.org 1.1310.1.231 # Merge bk://kernel.bkbits.net/davem/sparc-2.5 # into home.osdl.org:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/07/01 latten@austin.ibm.com 1.1310.102.5 # [IPV6] Make ipsec tunnel work with ext hdrs # # I noticed that using extensions headers along with IPsecv6 tunnel mode did # not work in 2.5.73 + patch-2.5.73-bk3. The following patch # checks "nexthdr" instead of "iph->nexthdr" which could be an # extension header. I tested this with tunnel mode and transport mode # with and without extension headers and it worked ok. # -------------------------------------------- # 03/06/30 torvalds@home.osdl.org 1.1310.1.232 # Fix the code that checks for PCI IDE controller "native" vs "legacy" # modes. # # It used to think that IDE controllers that weren't marked as "IDE storage" # PCI class (eg CMD IDE RAID controllers mark themselves as "RAID storage") # were always using legacy mode interrupt routing, which is bogus. In fact, # the whole native vs legacy thing only makes sense for the IDE storage class, # so fix the test to match. # -------------------------------------------- # 03/07/01 anton@samba.org 1.1334 # Merge samba.org:/scratch/anton/linux-2.5 # into samba.org:/scratch/anton/tmp3 # -------------------------------------------- # 03/06/30 shemminger@osdl.org 1.1310.1.233 # [BRIDGE]: Ethernet bridge fixes. # # 1. STP protocol has no security, so malcontents can fuck with the # bridge's topology. The fixes are to ship with STP turned off # to protect the ignorant, and run STP packets through ebtables # netfilter for the smart. # # Got this one via a russian hacker "Oleg K. Artemjev" # before he published the paper. # Bridge netfilter still needs work to give a nice face on this # but this patch gives the hooks to filter. # # 2. STP input processing was lax in it's length checking so I bet # you could make up a bomb packet. # # My inspection while doing #1. # # 3. Forwarding table could be abused by sending forged packets with # bogus source address same as the local host. This came via # Lennart from Jerry Kreuscher who ran into # it by mistake. # -------------------------------------------- # 03/07/01 yoshfuji@linux-ipv6.org 1.1310.102.6 # [NET] convert /proc/net/igmp to seq_file # -------------------------------------------- # 03/07/01 yoshfuji@linux-ipv6.org 1.1310.102.7 # [NET] convert /proc/net/igmp6 to seq_file # -------------------------------------------- # 03/07/01 yoshfuji@linux-ipv6.org 1.1310.102.8 # [NET] convert /proc/net/mcfilter to seq_file # -------------------------------------------- # 03/07/01 yoshfuji@linux-ipv6.org 1.1310.102.9 # [NET] convert /proc/net/mfilter6 to seq_file # -------------------------------------------- # 03/07/01 yoshfuji@linux-ipv6.org 1.1310.102.10 # [NET] convert /proc/net/anycast6 to seq_file # -------------------------------------------- # 03/06/30 davem@nuts.ninka.net 1.1310.1.234 # Merge bk://kernel.bkbits.net/jmorris/net-2.5 # into nuts.ninka.net:/home/davem/src/BK/net-2.5 # -------------------------------------------- # 03/07/01 davem@nuts.ninka.net 1.1310.1.235 # [IPV6]: Fix two ipv6_addr_addr failure checks. # -------------------------------------------- # 03/07/01 yoshfuji@linux-ipv6.org 1.1310.1.236 # [IPV6]: One too many ipv6_addr_type() calls in ndisc_recv_ns(). # -------------------------------------------- # 03/07/01 gerg@snapgear.com 1.1335 # [PATCH] conditional ROMfs copy for Arnewsh 5307 board # # Make the ROMfs copy in the startup code for ARNEWSH 5307 board # conditional on actually using a ROMfs setup. # -------------------------------------------- # 03/07/01 gerg@snapgear.com 1.1336 # [PATCH] rework 68360 interrupt handling code # # Rework the interrupt handling code for the m68knommu 68360 sub-architecture. # This is inline with the interrupt changes to the other m68knommu CPU's. # Makes this code be the primary interrupt setup for a 68360 based kernel, # not just a set of support functions. # -------------------------------------------- # 03/07/01 gerg@snapgear.com 1.1337 # [PATCH] clean up m68knommu bitops.h # # Rework the bitops functions for the m68knommu arhcitecture. Change # all addr pointers to be "unsigned long", cleans up many compiler # warnings. # -------------------------------------------- # 03/07/01 gerg@snapgear.com 1.1338 # [PATCH] fix ColdFire 5249 dma support # # The m68knommu ColdFire 5249 CPU has the same DMA engine as the 5307 # and 5407 ColdFire CPU's. Modify m68knommu dma.h to reflect this. # -------------------------------------------- # 03/07/01 gerg@snapgear.com 1.1339 # [PATCH] fix broken MARK parity define for ColdFire UART # # Fix broken definition of MARK parity for ColdFire UART. # -------------------------------------------- # 03/07/01 rusty@rustcorp.com.au 1.1340 # [PATCH] Identify Code Section Of Modules for kallsyms # # Remember the size of the SHF_EXECINSTR sections, which are conveniently # at the start of the modules, and use that to more reliably implement # module_text_address(). # -------------------------------------------- # 03/07/01 rusty@rustcorp.com.au 1.1341 # [PATCH] Make runqueues a per-cpu variable # # Makes scheduler use per-cpu variables for the runqueues. # -------------------------------------------- # 03/07/01 axboe@suse.de 1.1342 # [PATCH] ide-cd: capability flag for MO drives # # From: Pascal Schmidt # # Add capability flag for MO drives. Since ATAPI MOs are now recognized # by the ide-cd driver, it is useful to have a capability flag to be able # to tell MO drives from other drives (needed for later write support). # -------------------------------------------- # 03/07/01 torvalds@home.osdl.org 1.1343 # Merge bk://kernel.bkbits.net/davem/net-2.5 # into home.osdl.org:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/07/01 ak@suse.de 1.1344 # [PATCH] x86-64 merge for 2.5.73-bk9 # # - Update defconfig # - Merge with i386 # - Make oprofile compile again # - Warning fixes # - Minor changes for 32bit SYSCALL path (still disabled) # - Remove obsolete FS/GS symbols in ptrace.h # -------------------------------------------- # 03/07/01 mzyngier@freesurf.fr 1.1310.95.14 # [netdrvr de2104x] quiet link timer # # (can be enabled by ethtool) # -------------------------------------------- # 03/07/01 greg@kroah.com 1.1310.105.3 # [PATCH] USB: make struct usb_bus a struct class_device # # This creates sys/class/usb_host/ which lists all usb hosts in the system. # -------------------------------------------- # 03/07/01 greg@kroah.com 1.1310.105.4 # [PATCH] USB: move ehci's sysfs files to the class device instead of the pci device. # -------------------------------------------- # 03/07/01 greg@kroah.com 1.1310.105.5 # [PATCH] USB: move ohci's sysfs files to the class device instead of the pci device. # -------------------------------------------- # 03/07/01 lkml001@vrfy.org 1.1310.105.6 # [PATCH] USB: usb-skeleton.c usb_buffer_free() not called # # dev->udev was set to NULL to indicate a device disconnect but we need # this value for usb_buffer_free() when device is still opened and cleanup is # delayed until skel_release(). # I've added a dev->present for preventing device read, write and ioctl. # Also URB_NO_DMA_MAP is changed to URB_NO_TRANSFER_DMA_MAP and a unused # var is removed. # -------------------------------------------- # 03/07/01 stern@rowland.harvard.edu 1.1310.105.7 # [PATCH] USB: Reconcile unusual_devs.h in 2.4 and 2.5 # # This patch for 2.5 copies into unusual_devs.h an entry that is present in # 2.4 but missing here. It also adds back the IGNORE_SER flag with a dummy # value, just for backward compatibility. # -------------------------------------------- # 03/07/01 greg@kroah.com 1.1310.108.1 # Merge kroah.com:/home/greg/linux/BK/bleed-2.5 # into kroah.com:/home/greg/linux/BK/gregkh-2.5 # -------------------------------------------- # 03/07/01 torvalds@home.osdl.org 1.1345 # Merge bk://kernel.bkbits.net/gregkh/linux/linus-2.5 # into home.osdl.org:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/07/01 torvalds@home.osdl.org 1.1346 # Merge bk://kernel.bkbits.net/jgarzik/net-drivers-2.5 # into home.osdl.org:/home/torvalds/v2.5/linux # -------------------------------------------- # 03/07/01 schwidefsky@de.ibm.com 1.1347 # [PATCH] s390: semtimedop. # # Fix SEMTIMEDOP operation in sys_ipc. Patch by Ernie Petrides. # -------------------------------------------- # 03/07/01 schwidefsky@de.ibm.com 1.1348 # [PATCH] s390: ptrace. # # Fix ptrace system call number replacement code. # -------------------------------------------- # 03/07/01 schwidefsky@de.ibm.com 1.1349 # [PATCH] s390: online attribute. # # Fix online attribute. "echo 1 > online" should enable a device and # "echo 0 > online" should disable a device, not the other way round. # -------------------------------------------- # 03/07/01 schwidefsky@de.ibm.com 1.1350 # [PATCH] s390: processor type. # # Add configuration option to select the different processor types. Add new # path group algorith and new relocation types introduces with z990. # -------------------------------------------- # 03/07/01 schwidefsky@de.ibm.com 1.1351 # [PATCH] s390: thin interrupts. # # Add thin interrupt support to qdio. # -------------------------------------------- # 03/07/01 schwidefsky@de.ibm.com 1.1352 # [PATCH] s390: qeth network driver. # # The qeth network device driver. Supports the OSA Express Gigabit cards, # HiperSockes and VM GuestLAN interfaces. # -------------------------------------------- # 03/07/01 bcollins@debian.org 1.1353 # [PATCH] Spelling fix # # Spelling fix # -------------------------------------------- # 03/07/01 bcollins@debian.org 1.1354 # [PATCH] Use KALLSYMS for scripts/kallsyms # # Since KALLSYMS is defined, might aswell use it somewhere. # -------------------------------------------- # 03/07/01 ak@suse.de 1.1355 # [PATCH] Fix IPC ABI for AMD64 # # AMD64 like IA64 needs to force IPC_64 in the IPC functions. This makes # 2.5 compatible with 2.4 again. # -------------------------------------------- # 03/07/01 ak@suse.de 1.1356 # [PATCH] Disable a.out for AMD64 # # AMD64 does not support a.out, so don't display it in the configuration. # -------------------------------------------- # 03/07/01 B.Zolnierkiewicz@elka.pw.edu.pl 1.1357 # [PATCH] Mark taskfile EXPERIMENTAL again # # Okay, since now corruption happens and there are some other issues to be # resolved ("bad: scheduling while atomic" and "/proc/ide/hdX/identify") # better set it by default to n for 2.5.74, also mark it EXPERIMENTAL. # -------------------------------------------- # diff -Nru a/Documentation/DocBook/gadget.tmpl b/Documentation/DocBook/gadget.tmpl --- a/Documentation/DocBook/gadget.tmpl Tue Jul 1 18:44:35 2003 +++ b/Documentation/DocBook/gadget.tmpl Tue Jul 1 18:44:35 2003 @@ -6,31 +6,32 @@ 02 June 2003 - Permission is granted to copy, distribute, and/or modify - this document under the terms of the GNU Free Documentation - License, version 1.2, or any later version published by the - Free Software Foundation; with the Invariant Sections being - the "GNU Free Documentation License", - no Front-Cover Texts, - and - no Back-Cover Texts. - - - This documentation is distributed in the hope that it will be - useful, but WITHOUT ANY WARRANTY; without even the implied - warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU Free Documentation License for more details. - - - Note that certain sections of this document are merged - into Linux kernel source code. - That content is the bulk of - and - , - where the "GNU Free Documentation License" is identified - as an alternate licence for its documentation. - - + + This documentation is free software; you can redistribute + it and/or modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later + version. + + + + This program is distributed in the hope that it will be + useful, but WITHOUT ANY WARRANTY; without even the implied + warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU General Public License for more details. + + + + You should have received a copy of the GNU General Public + License along with this program; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, + MA 02111-1307 USA + + + + For more details see the file COPYING in the source + distribution of Linux. + 2003 @@ -325,9 +326,10 @@ of one or more "packets", and packet boundaries are visible to drivers. Compared to RS-232 serial protocols, USB resembles synchronous protocols like HDLC -(N bytes per frame, multipoint addressing from the host) +(N bytes per frame, multipoint addressing, host as the primary +station and devices as secondary stations) more than asynchronous ones -(tty style, like 8 bytes, no parity, one stop bit). +(tty style: 8 data bits per frame, no parity, one stop bit). So for example the controller drivers won't buffer two single byte writes into a single two-byte USB IN packet, although gadget drivers may do so when they implement @@ -527,438 +529,6 @@ - - -GNU Free Documentation License -Version 1.2, November 2002 - - - -PREAMBLE - -The purpose of this License is to make a manual, textbook, or -other functional and useful document "free" in the sense of freedom: to -assure everyone the effective freedom to copy and redistribute it, with -or without modifying it, either commercially or noncommercially. -Secondarily, this License preserves for the author and publisher a way -to get credit for their work, while not being considered responsible for -modifications made by others. - -This License is a kind of "copyleft", which means that derivative -works of the document must themselves be free in the same sense. It -complements the GNU General Public License, which is a copyleft license -designed for free software. - -We have designed this License in order to use it for manuals for -free software, because free software needs free documentation: a free -program should come with manuals providing the same freedoms that the -software does. But this License is not limited to software manuals; it -can be used for any textual work, regardless of subject matter or -whether it is published as a printed book. We recommend this License -principally for works whose purpose is instruction or reference. - - -APPLICABILITY AND DEFINITIONS - -This License applies to any manual or other work, in -any medium, that contains a notice placed by the copyright holder saying -it can be distributed under the terms of this License. Such a notice -grants a world-wide, royalty-free license, unlimited in duration, to use -that work under the conditions stated herein. The "Document", below, -refers to any such manual or work. Any member of the public is a -licensee, and is addressed as "you". You accept the license if you -copy, modify or distribute the work in a way requiring permission under -copyright law. - -A "Modified Version" of the Document means any -work containing the Document or a portion of it, either copied verbatim, -or with modifications and/or translated into another language. - -A "Secondary Section" is a named appendix or -a front-matter section of the Document that deals exclusively with the -relationship of the publishers or authors of the Document to the -Document's overall subject (or to related matters) and contains nothing -that could fall directly within that overall subject. (Thus, if the -Document is in part a textbook of mathematics, a Secondary Section may -not explain any mathematics.) The relationship could be a matter of -historical connection with the subject or with related matters, or of -legal, commercial, philosophical, ethical or political position -regarding them. - -The "Invariant Sections" are certain Secondary -Sections whose titles are designated, as being those of Invariant -Sections, in the notice that says that the Document is released under -this License. If a section does not fit the above definition of -Secondary then it is not allowed to be designated as Invariant. The -Document may contain zero Invariant Sections. If the Document does not -identify any Invariant Sections then there are none. - -The "Cover Texts" are certain short passages of -text that are listed, as Front-Cover Texts or Back-Cover Texts, in the -notice that says that the Document is released under this License. A -Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at -most 25 words. - -A "Transparent" copy of the Document means a -machine-readable copy, represented in a format whose specification is -available to the general public, that is suitable for revising the -document straightforwardly with generic text editors or (for images -composed of pixels) generic paint programs or (for drawings) some widely -available drawing editor, and that is suitable for input to text -formatters or for automatic translation to a variety of formats suitable -for input to text formatters. A copy made in an otherwise Transparent -file format whose markup, or absence of markup, has been arranged to -thwart or discourage subsequent modification by readers is not -Transparent. An image format is not Transparent if used for any -substantial amount of text. A copy that is not "Transparent" is called -"Opaque". - -Examples of suitable formats for Transparent copies include plain -ASCII without markup, Texinfo input format, LaTeX input format, SGML or -XML using a publicly available DTD, and standard-conforming simple HTML, -PostScript or PDF designed for human modification. Examples of -transparent image formats include PNG, XCF and JPG. Opaque formats -include proprietary formats that can be read and edited only by -proprietary word processors, SGML or XML for which the DTD and/or -processing tools are not generally available, and the machine-generated -HTML, PostScript or PDF produced by some word processors for output -purposes only. - -The "Title Page" means, for a printed book, -the title page itself, plus such following pages as are needed to hold, -legibly, the material this License requires to appear in the title page. -For works in formats which do not have any title page as such, "Title -Page" means the text near the most prominent appearance of the work's -title, preceding the beginning of the body of the text. - -A section "Entitled XYZ" means a named subunit -of the Document whose title either is precisely XYZ or contains XYZ in -parentheses following text that translates XYZ in another language. -(Here XYZ stands for a specific section name mentioned below, such as -"Acknowledgements", "Dedications", "Endorsements", or "History".) To -"Preserve the Title" of such a section when you modify the Document -means that it remains a section "Entitled XYZ" according to this -definition. - -The Document may include Warranty Disclaimers next to the notice -which states that this License applies to the Document. These Warranty -Disclaimers are considered to be included by reference in this License, -but only as regards disclaiming warranties: any other implication that -these Warranty Disclaimers may have is void and has no effect on the -meaning of this License. - - -VERBATIM COPYING - -You may copy and distribute the Document in any medium, either -commercially or noncommercially, provided that this License, the -copyright notices, and the license notice saying this License applies to -the Document are reproduced in all copies, and that you add no other -conditions whatsoever to those of this License. You may not use -technical measures to obstruct or control the reading or further copying -of the copies you make or distribute. However, you may accept -compensation in exchange for copies. If you distribute a large enough -number of copies you must also follow the conditions in section 3. - - -You may also lend copies, under the same conditions stated above, -and you may publicly display copies. - - -COPYING IN QUANTITY - -If you publish printed copies (or copies in media that commonly -have printed covers) of the Document, numbering more than 100, and the -Document's license notice requires Cover Texts, you must enclose the -copies in covers that carry, clearly and legibly, all these Cover Texts: -Front-Cover Texts on the front cover, and Back-Cover Texts on the back -cover. Both covers must also clearly and legibly identify you as the -publisher of these copies. The front cover must present the full title -with all words of the title equally prominent and visible. You may add -other material on the covers in addition. Copying with changes limited -to the covers, as long as they preserve the title of the Document and -satisfy these conditions, can be treated as verbatim copying in other -respects. - -If the required texts for either cover are too voluminous to fit -legibly, you should put the first ones listed (as many as fit -reasonably) on the actual cover, and continue the rest onto adjacent -pages. - -If you publish or distribute Opaque copies of the Document -numbering more than 100, you must either include a machine-readable -Transparent copy along with each Opaque copy, or state in or with each -Opaque copy a computer-network location from which the general -network-using public has access to download using public-standard -network protocols a complete Transparent copy of the Document, free of -added material. If you use the latter option, you must take reasonably -prudent steps, when you begin distribution of Opaque copies in quantity, -to ensure that this Transparent copy will remain thus accessible at the -stated location until at least one year after the last time you -distribute an Opaque copy (directly or through your agents or retailers) -of that edition to the public. - -It is requested, but not required, that you contact the authors of -the Document well before redistributing any large number of copies, to -give them a chance to provide you with an updated version of the -Document. - - -MODIFICATIONS - -You may copy and distribute a Modified Version of the Document -under the conditions of sections 2 and 3 above, provided that you -release the Modified Version under precisely this License, with the -Modified Version filling the role of the Document, thus licensing -distribution and modification of the Modified Version to whoever -possesses a copy of it. In addition, you must do these things in the -Modified Version: - - -Use in the Title Page (and on the covers, if any) a - title distinct from that of the Document, and from those of previous - versions (which should, if there were any, be listed in the History - section of the Document). You may use the same title as a previous - version if the original publisher of that version gives permission. - -List on the Title Page, as authors, one or more - persons or entities responsible for authorship of the modifications in - the Modified Version, together with at least five of the principal - authors of the Document (all of its principal authors, if it has fewer - than five), unless they release you from this requirement. - -State on the Title page the name of the publisher of - the Modified Version, as the publisher. -Preserve all the copyright notices of the Document. - -Add an appropriate copyright notice for your - modifications adjacent to the other copyright notices. - -Include, immediately after the copyright notices, a - license notice giving the public permission to use the Modified - Version under the terms of this License, in the form shown in the - Addendum below. - -Preserve in that license notice the full lists of - Invariant Sections and required Cover Texts given in the Document's - license notice. -Include an unaltered copy of this License. - -Preserve the section Entitled "History", Preserve its - Title, and add to it an item stating at least the title, year, new - authors, and publisher of the Modified Version as given on the Title - Page. If there is no section Entitled "History" in the Document, - create one stating the title, year, authors, and publisher of the - Document as given on its Title Page, then add an item describing the - Modified Version as stated in the previous sentence. - -Preserve the network location, if any, given in the - Document for public access to a Transparent copy of the Document, and - likewise the network locations given in the Document for previous - versions it was based on. These may be placed in the "History" - section. You may omit a network location for a work that was - published at least four years before the Document itself, or if the - original publisher of the version it refers to gives permission. - -For any section Entitled "Acknowledgements" or - "Dedications", Preserve the Title of the section, and preserve in the - section all the substance and tone of each of the contributor - acknowledgements and/or dedications given therein. - -Preserve all the Invariant Sections of the Document, - unaltered in their text and in their titles. Section numbers or the - equivalent are not considered part of the section titles. - -Delete any section Entitled "Endorsements". - Such a section may not be included in the Modified Version. - -Do not retitle any existing section to be Entitled - "Endorsements" or to conflict in title with any Invariant Section. - -Preserve any Warranty Disclaimers. - - - -If the Modified Version includes new front-matter sections or -appendices that qualify as Secondary Sections and contain no material -copied from the Document, you may at your option designate some or all -of these sections as invariant. To do this, add their titles to the -list of Invariant Sections in the Modified Version's license notice. -These titles must be distinct from any other section titles. - -You may add a section Entitled "Endorsements", provided it -contains nothing but endorsements of your Modified Version by various -parties--for example, statements of peer review or that the text has -been approved by an organization as the authoritative definition of a -standard. - -You may add a passage of up to five words as a Front-Cover Text, -and a passage of up to 25 words as a Back-Cover Text, to the end of the -list of Cover Texts in the Modified Version. Only one passage of -Front-Cover Text and one of Back-Cover Text may be added by (or through -arrangements made by) any one entity. If the Document already includes -a cover text for the same cover, previously added by you or by -arrangement made by the same entity you are acting on behalf of, you may -not add another; but you may replace the old one, on explicit permission -from the previous publisher that added the old one. - -The author(s) and publisher(s) of the Document do not by this -License give permission to use their names for publicity for or to -assert or imply endorsement of any Modified Version. - - -COMBINING DOCUMENTS - -You may combine the Document with other documents released under -this License, under the terms defined in section -4 above for modified versions, provided that you include in the -combination all of the Invariant Sections of all of the original -documents, unmodified, and list them all as Invariant Sections of your -combined work in its license notice, and that you preserve all their -Warranty Disclaimers. - -The combined work need only contain one copy of this License, and -multiple identical Invariant Sections may be replaced with a single -copy. If there are multiple Invariant Sections with the same name but -different contents, make the title of each such section unique by adding -at the end of it, in parentheses, the name of the original author or -publisher of that section if known, or else a unique number. Make the -same adjustment to the section titles in the list of Invariant Sections -in the license notice of the combined work. - -In the combination, you must combine any sections Entitled -"History" in the various original documents, forming one section -Entitled "History"; likewise combine any sections Entitled -"Acknowledgements", and any sections Entitled "Dedications". You must -delete all sections Entitled "Endorsements". - - -COLLECTIONS OF DOCUMENTS - -You may make a collection consisting of the Document and other -documents released under this License, and replace the individual copies -of this License in the various documents with a single copy that is -included in the collection, provided that you follow the rules of this -License for verbatim copying of each of the documents in all other -respects. - -You may extract a single document from such a collection, and -distribute it individually under this License, provided you insert a -copy of this License into the extracted document, and follow this -License in all other respects regarding verbatim copying of that -document. - - -AGGREGATION WITH INDEPENDENT WORKS - -A compilation of the Document or its derivatives with other -separate and independent documents or works, in or on a volume of a -storage or distribution medium, is called an "aggregate" if the -copyright resulting from the compilation is not used to limit the legal -rights of the compilation's users beyond what the individual works -permit. When the Document is included an aggregate, this License does -not apply to the other works in the aggregate which are not themselves -derivative works of the Document. - -If the Cover Text requirement of section 3 is applicable to these -copies of the Document, then if the Document is less than one half of -the entire aggregate, the Document's Cover Texts may be placed on covers -that bracket the Document within the aggregate, or the electronic -equivalent of covers if the Document is in electronic form. Otherwise -they must appear on printed covers that bracket the whole -aggregate. - - -TRANSLATION - -Translation is considered a kind of modification, so you may -distribute translations of the Document under the terms of section 4. -Replacing Invariant Sections with translations requires special -permission from their copyright holders, but you may include -translations of some or all Invariant Sections in addition to the -original versions of these Invariant Sections. You may include a -translation of this License, and all the license notices in the -Document, and any Warranty Disclaimers, provided that you also include -the original English version of this License and the original versions -of those notices and disclaimers. In case of a disagreement between the -translation and the original version of this License or a notice or -disclaimer, the original version will prevail. - -If a section in the Document is Entitled "Acknowledgements", -"Dedications", or "History", the requirement (section 4) to Preserve its -Title (section 1) will typically require changing the actual -title. - - -TERMINATION - -You may not copy, modify, sublicense, or distribute the Document -except as expressly provided for under this License. Any other attempt -to copy, modify, sublicense or distribute the Document is void, and will -automatically terminate your rights under this License. However, -parties who have received copies, or rights, from you under this License -will not have their licenses terminated so long as such parties remain -in full compliance. - - -FUTURE REVISIONS OF THIS LICENSE - -The Free Software Foundation may publish new, revised versions of -the GNU Free Documentation License from time to time. Such new versions -will be similar in spirit to the present version, but may differ in -detail to address new problems or concerns. See -http://www.gnu.org/copyleft/. - -Each version of the License is given a distinguishing version -number. If the Document specifies that a particular numbered version of -this License "or any later version" applies to it, you have the option -of following the terms and conditions either of that specified version -or of any later version that has been published (not as a draft) by the -Free Software Foundation. If the Document does not specify a version -number of this License, you may choose any version ever published (not -as a draft) by the Free Software Foundation. - - -ADDENDUM: How to use this License for - your documents - -To use this License in a document you have written, include a copy -of the License in the document and put the following copyright and -license notices just after the title page: - - - -If you have Invariant Sections, Front-Cover Texts and Back-Cover -Texts, replace the "with...Texts." line with this: - -
- with the Invariant Sections being LIST THEIR TITLES, with the - Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. -
- -If you have Invariant Sections without Cover Texts, or some other -combination of the three, merge those two alternatives to suit the -situation. - -If your document contains nontrivial examples of program code, we -recommend releasing these examples in parallel under your choice of free -software license, such as the GNU General Public License, to permit -their use in free software. -
-
+===-------------------=========--------------------===------ +scsi_host_alloc() --> scsi_add_host() --------+ | - slave_alloc() + slave_alloc() slave_configure() --> scsi_adjust_queue_depth() - | - slave_alloc() + | + slave_alloc() slave_configure() - | - slave_alloc() ** - slave_destroy() ** + | + slave_alloc() *** + slave_destroy() *** +------------------------------------------------------------ If the LLD wants to adjust the default queue settings, it can invoke scsi_adjust_queue_depth() in its slave_configure() routine. -** For scsi devices that the mid level tries to scan but do not - respond, a slave_alloc(), slave_destroy() pair is called. +*** For scsi devices that the mid level tries to scan but do not + respond, a slave_alloc(), slave_destroy() pair is called. -Here is the corresponding sequence when a host (HBA) is being -removed: +When a HBA is being removed is could as part of an orderly shutdown +associated with the LLD module being unloaded (e.g. with the "rmmod" +command) or in response to a "hot unplug" indicated by sysfs()'s +remove() callback being invoked. In either case, the sequence is the +same: -[HBA REMOVE] + HBA REMOVE: assume 2 SCSI devices attached LLD mid level LLD ---- --------- --- +===----------------------=========-----------------===------ scsi_remove_host() ---------+ | slave_destroy() slave_destroy() - release() --> scsi_unregister() +scsi_host_put() +------------------------------------------------------------ + +It may be useful for a LLD to keep track of struct Scsi_Host instances +(a pointer is returned by scsi_host_alloc()). Such instances are "owned" +by the mid-level. struct Scsi_Host instances are freed from +scsi_host_put() when the reference count hits zero. + +Hot unplugging a HBA that controls a disk which is processing SCSI +commands on a mounted file system is an interesting situation. Reference +counting logic is being introduced into the mid level to cope with many +of the issues involved. See the section on reference counting below. + + +The hotplug concept may be extended to SCSI devices. Currently, when a +HBA is added, the scsi_add_host() function causes a scan for SCSI devices +attached to the HBA's SCSI transport. On newer SCSI transports the HBA +may become aware of a new SCSI device _after_ the scan has completed. +A LLD can use this sequence to make the mid level aware of a SCSI device: -It is practical for a LLD to keep track of struct Scsi_Host instances -(a pointer is returned by scsi_register() ) and struct scsi_device -instances (a pointer is passed as the parameter to slave_alloc() and -slave_configure() ). Both classes of instances are "owned" by the -mid-level. struct scsi_device instances are freed after slave_destroy(). -struct Scsi_Host instances are freed within scsi_unregister(). - -TODO: -Descriptions, are the following correct? -[DEVICE hotplug] + SCSI DEVICE hotplug LLD mid level LLD ---- --------- --- +===-------------------=========--------------------===------ scsi_add_device() ------+ | - slave_alloc() + slave_alloc() slave_configure() [--> scsi_adjust_queue_depth()] +------------------------------------------------------------ -[DEVICE unplug] +In a similar fashion, a LLD may become aware that a SCSI device has been +removed (unplugged) or the connection to it has been interrupted. Some +existing SCSI transports (e.g. SPI) may not become aware that a SCSI +device has been removed until a subsequent SCSI command fails which will +probably cause that device to be set offline by the mid level. A LLD that +detects the removal of a SCSI device can instigate its removal from +upper layers with this sequence: + + SCSI DEVICE hot unplug LLD mid level LLD ---- --------- --- +===----------------------=========-----------------===------ scsi_set_device_offline() scsi_remove_device() -------+ | slave_destroy() +------------------------------------------------------------ +It may be useful for a LLD to keep track of struct scsi_device instances +(a pointer is passed as the parameter to slave_alloc() and +slave_configure() callbacks). Such instances are "owned" by the mid-level. +struct scsi_device instances are freed after slave_destroy(). Passive initialization model ============================ -LLD initialization (both built-in and module) and shutdown are "wired -up" by passing function pointers to the module_init() and module_exit() -macros respectively. In this model the function identified by "module_init" -must call scsi_register_host() and the function identified by "module_exit" -must call scsi_unregister_host(). -Most LLDs inherited from the lk 2.4 series include a file called -"scsi_module.c" [yes the ".c" is a little surprising] in their -source code. For that file to work a declaration like this is needed before -it is included: - static struct SHT driver_template = DRIVER_TEMPLATE; +These older LLDs include a file called "scsi_module.c" [yes the ".c" is a +little surprising] in their source code. For that file to work an +instance of struct scsi_host_template with the name "driver_template" +needs to be defined. Here is a typical code sequence used in this model: + static struct scsi_host_template driver_template = { + ... + }; #include "scsi_module.c" -In this case "DRIVER_TEMPLATE" is defined to be a structure initializer -that is placed in the driver header file by convention. It contains -pointers to supported interface functions and other values. +The scsi_module.c file contains two functions: + - init_this_scsi_driver() which is executed when the LLD is + initialized (i.e. boot time or module load time) + - exit_this_scsi_driver() which is executed when the LLD is shut + down (i.e. module unload time) +Note: since these functions are tagged with __init and __exit qualifiers +a LLD should not call them explicitly (since the kernel does that). Here is an example of an initialization sequence when two hosts are detected (so detect() returns 2) and the SCSI bus scan on each host finds 1 SCSI device (and a second device does not respond). LLD mid level LLD ---- --------- --- -scsi_register_host() -------+ +===----------------------=========-----------------===------ +init_this_scsi_driver() ----+ | detect() -----------------+ | | | scsi_register() | scsi_register() | - slave_alloc() + slave_alloc() slave_configure() --> scsi_adjust_queue_depth() - slave_alloc() ** - slave_destroy() ** + slave_alloc() *** + slave_destroy() *** | - slave_alloc() + slave_alloc() slave_configure() - slave_alloc() ** - slave_destroy() ** + slave_alloc() *** + slave_destroy() *** +------------------------------------------------------------ The mid level invokes scsi_adjust_queue_depth() with tagged queuing off and "cmd_per_lun" for that host as the queue length. These settings can be overridden by a slave_configure() supplied by the LLD. -** For scsi devices that the mid level tries to scan but do not - respond, a slave_alloc(), slave_destroy() pair is called. +*** For scsi devices that the mid level tries to scan but do not + respond, a slave_alloc(), slave_destroy() pair is called. Here is a LLD shutdown sequence: LLD mid level LLD ---- --------- --- -scsi_unregister_host() -----+ +===----------------------=========-----------------===------ +exit_this_scsi_driver() ----+ | slave_destroy() release() --> scsi_unregister() | slave_destroy() release() --> scsi_unregister() +------------------------------------------------------------ -slave_destroy() is optional. +A LLD need not define slave_destroy() (i.e. it is optional). The shortcoming of the "passive initialization model" is that host registration and de-registration are (typically) tied to LLD initialization and shutdown. Once the LLD is initialized then a new host that appears (e.g. via hotplugging) cannot easily be added without a redundant -driver shutdown and re-initialization. +driver shutdown and re-initialization. It may be possible to write a LLD +that uses both initialization models. + + +Reference Counting +================== +The Scsi_Host structure has had reference counting infrastructure added. +This effectively spreads the ownership of struct Scsi_Host instances +across the various SCSI layers which use them. Previously such instances +were exclusively owned by the mid level. LLDs would not usually need to +directly manipulate these reference counts but there may be some cases +where they do. + +There are 3 reference counting functions of interest associated with +struct Scsi_Host: + - scsi_host_alloc(): returns a pointer to new instance of struct + Scsi_Host which has its reference count ^^ set to 1 + - scsi_host_get(): adds 1 to the reference count of the given instance + - scsi_host_put(): decrements 1 from the reference count of the given + instance. If the reference count reaches 0 then the given instance + is freed + +^^ struct Scsi_Host actually has 2 reference counts which are manipulated +in parallel by these functions. Conventions =========== -First, Linus's thoughts on C coding can be found in the file -Documentation/CodingStyle . +First, Linus Torvald's thoughts on C coding style can be found in the +Documentation/CodingStyle file. Next, there is a movement to "outlaw" typedefs introducing synonyms for -struct tags. Both can be still found in the SCSI subsystem, for example: -"typedef struct SHT { ...} Scsi_Host_Template;" in hosts.h . In this -case "struct SHT" is preferred to "Scsi_Host_Template". [The poor naming -example was chosen with malevolent intent.] +struct tags. Both can be still found in the SCSI subsystem, but +the typedefs have been moved to a single file, scsi_typedefs.h to +make their future removal easier, for example: +"typedef struct scsi_host_template Scsi_Host_Template;" Also, C99 enhancements are encouraged to the extent they are supported by the relevant gcc compilers. So "//" style comments are encouraged @@ -304,9 +358,11 @@ scsi_bios_ptable - return copy of block device's partition table scsi_block_requests - prevent further commands being queued to given host scsi_delete_timer - cancel timer on a SCSI command. + scsi_host_alloc - return a new scsi_host instance whose refcount==1 + scsi_host_get - increments Scsi_Host instance's refcount + scsi_host_put - decrements Scsi_Host instance's refcount (free if 0) scsi_partsize - parse partition table into cylinders, heads + sectors scsi_register - create and register a scsi host adapter instance. - scsi_register_host - register a low level host driver scsi_remove_device - detach and remove a SCSI device scsi_remove_host - detach and remove all SCSI devices owned by host scsi_report_bus_reset - report scsi _bus_ reset observed @@ -316,8 +372,8 @@ scsi_to_sbus_dma_dir - convert SCSI subsystem direction flag to SBUS scsi_track_queue_full - track successive QUEUE_FULL events scsi_unblock_requests - allow further commands to be queued to given host - scsi_unregister - unregister and free memory used by host instance - scsi_unregister_host - unregister a low level host adapter driver + scsi_unregister - [calls scsi_host_put()] + Details: @@ -329,17 +385,17 @@ * @lun: logical unit number * * Returns pointer to new struct scsi_device instance or - * ERR_PTR(-ENODEV) (or some other bent pointer) if something is - * wrong (e.g. no lu responds at given address) + * ERR_PTR(-ENODEV) (or some other bent pointer) if something is + * wrong (e.g. no lu responds at given address) * - * Notes: This call is usually performed internally during a scsi - * bus scan when a HBA is added (i.e. scsi_add_host()). So it - * should only be called if the HBA becomes aware of a new scsi - * device (lu) after scsi_add_host() has completed. If successful - * this call we lead to slave_alloc() and slave_configure() callbacks - * into the LLD. + * Notes: This call is usually performed internally during a scsi + * bus scan when a HBA is added (i.e. scsi_add_host()). So it + * should only be called if the HBA becomes aware of a new scsi + * device (lu) after scsi_add_host() has completed. If successful + * this call we lead to slave_alloc() and slave_configure() callbacks + * into the LLD. * - * Defined in: drivers/scsi/scsi_scan.c + * Defined in: drivers/scsi/scsi_scan.c **/ struct scsi_device * scsi_add_device(struct Scsi_Host *shost, unsigned int channel, @@ -353,10 +409,10 @@ * * Returns 0 on success, negative errno of failure (e.g. -ENOMEM) * - * Notes: Only required in "hotplug initialization model" after a - * successful call to scsi_register(). + * Notes: Only required in "hotplug initialization model" after a + * successful call to scsi_host_alloc(). * - * Defined in: drivers/scsi/hosts.c + * Defined in: drivers/scsi/hosts.c **/ int scsi_add_host(struct Scsi_Host *shost, struct device * dev) @@ -369,40 +425,40 @@ * * Returns nothing * - * Notes: Each scsi command has its own timer, and as it is added - * to the queue, we set up the timer. When the command completes, + * Notes: Each scsi command has its own timer, and as it is added + * to the queue, we set up the timer. When the command completes, * we cancel the timer. A LLD can use this function to change - * the existing timeout value. + * the existing timeout value. * - * Defined in: drivers/scsi/scsi_error.c + * Defined in: drivers/scsi/scsi_error.c **/ -void scsi_add_timer(Scsi_Cmnd *scmd, int timeout, void (*complete) - (Scsi_Cmnd *)) +void scsi_add_timer(struct scsi_cmnd *scmd, int timeout, + void (*complete)(struct scsi_cmnd *)) /** * scsi_adjust_queue_depth - change the queue depth on a SCSI device - * @SDpnt: pointer to SCSI device to change queue depth on - * @tagged: 0 - no tagged queuing - * MSG_SIMPLE_TAG - simple (unordered) tagged queuing - * MSG_ORDERED_TAG - ordered tagged queuing - * @tags Number of tags allowed if tagged queuing enabled, - * or number of commands the LLD can queue up - * in non-tagged mode (as per cmd_per_lun). - * - * Returns nothing - * - * Notes: Can be invoked any time on a SCSI device controlled by this - * LLD. [Specifically during and after slave_configure() and prior to - * slave_destroy().] Can safely be invoked from interrupt code. Actual - * queue depth change may be delayed until the next command is being - * processed. + * @SDpnt: pointer to SCSI device to change queue depth on + * @tagged: 0 - no tagged queuing + * MSG_SIMPLE_TAG - simple (unordered) tagged queuing + * MSG_ORDERED_TAG - ordered tagged queuing + * @tags Number of tags allowed if tagged queuing enabled, + * or number of commands the LLD can queue up + * in non-tagged mode (as per cmd_per_lun). * - * Defined in: drivers/scsi/scsi.c [see source code for more notes] + * Returns nothing + * + * Notes: Can be invoked any time on a SCSI device controlled by this + * LLD. [Specifically during and after slave_configure() and prior to + * slave_destroy().] Can safely be invoked from interrupt code. Actual + * queue depth change may be delayed until the next command is being + * processed. + * + * Defined in: drivers/scsi/scsi.c [see source code for more notes] * **/ void scsi_adjust_queue_depth(struct scsi_device * SDpnt, int tagged, - int num_tags) + int num_tags) /** @@ -419,13 +475,13 @@ /** * scsi_bios_ptable - return copy of block device's partition table - * @dev: pointer to block device + * @dev: pointer to block device * - * Returns pointer to partition table, or NULL for failure + * Returns pointer to partition table, or NULL for failure * - * Notes: Caller owns memory returned (free with kfree() ) + * Notes: Caller owns memory returned (free with kfree() ) * - * Defined in: drivers/scsi/scsicam.c + * Defined in: drivers/scsi/scsicam.c **/ unsigned char *scsi_bios_ptable(struct block_device *dev) @@ -435,12 +491,12 @@ * * @SHpnt: pointer to host to block commands on * - * Returns nothing + * Returns nothing * - * Notes: There is no timer nor any other means by which the requests - * get unblocked other than the LLD calling scsi_unblock_requests(). + * Notes: There is no timer nor any other means by which the requests + * get unblocked other than the LLD calling scsi_unblock_requests(). * - * Defined in: drivers/scsi/scsi_lib.c + * Defined in: drivers/scsi/scsi_lib.c **/ void scsi_block_requests(struct Scsi_Host * SHpnt) @@ -450,15 +506,64 @@ * @scmd: pointer to scsi command instance * * Returns 1 if able to cancel timer else 0 (i.e. too late or already - * cancelled). + * cancelled). + * + * Notes: All commands issued by upper levels already have a timeout + * associated with them. A LLD can use this function to cancel the + * timer. * - * Notes: All commands issued by upper levels already have a timeout - * associated with them. A LLD can use this function to cancel the - * timer. + * Defined in: drivers/scsi/scsi_error.c + **/ +int scsi_delete_timer(struct scsi_cmnd *scmd) + + +/** + * scsi_host_alloc - create and register a scsi host adapter instance. + * @shost_tp: pointer to scsi host template + * @xtr_bytes: extra bytes to allocate in hostdata array (which is the + * last member of the returned Scsi_Host instance) * - * Defined in: drivers/scsi/scsi_error.c + * Returns pointer to new Scsi_Host instance or NULL on failure + * + * Notes: When this call returns to the LLDD, the SCSI bus scan on + * this host has _not_ yet been done. + * The hostdata array (by default zero length) is a per host scratch + * area for the LLD. + * Both associated refcounting objects have there refcount set to 1. + * + * Defined in: drivers/scsi/hosts.c . **/ -int scsi_delete_timer(Scsi_Cmnd *scmd) +struct Scsi_Host * scsi_host_alloc(struct scsi_host_template *, int xtr_bytes) + + +/** + * scsi_host_get - increment Scsi_Host instance refcount + * @shost: pointer to struct Scsi_Host instance + * + * Returns nothing + * + * Notes: Actually increments the counts in two sub-objects + * + * Defined in: drivers/scsi/hosts.c + **/ +void scsi_host_get(struct Scsi_Host *shost) + + +/** + * scsi_host_put - decrement Scsi_Host instance refcount, free if 0 + * @shost: pointer to struct Scsi_Host instance + * + * Returns nothing + * + * Notes: Actually decrements the counts in two sub-objects. If the + * latter refcount reaches 0, the Scsi_Host instance is freed. + * The LLD need not worry exactly when the Scsi_Host instance is + * freed, it just shouldn't access the instance after it has balanced + * out its refcount usage. + * + * Defined in: drivers/scsi/hosts.c + **/ +void scsi_host_put(struct Scsi_Host *shost) /** @@ -469,11 +574,11 @@ * @hds: outputs number of heads calculated via this pointer * @secs: outputs number of sectors calculated via this pointer * - * Returns 0 on success, -1 on failure + * Returns 0 on success, -1 on failure * - * Notes: Caller owns memory returned (free with kfree() ) + * Notes: Caller owns memory returned (free with kfree() ) * - * Defined in: drivers/scsi/scsicam.c + * Defined in: drivers/scsi/scsicam.c **/ int scsi_partsize(unsigned char *buf, unsigned long capacity, unsigned int *cyls, unsigned int *hds, unsigned int *secs) @@ -483,51 +588,33 @@ * scsi_register - create and register a scsi host adapter instance. * @shost_tp: pointer to scsi host template * @xtr_bytes: extra bytes to allocate in hostdata array (which is the - * last member of the returned Scsi_Host instance) + * last member of the returned Scsi_Host instance) * * Returns pointer to new Scsi_Host instance or NULL on failure * - * Notes: When this call returns to the LLDD, the SCSI bus scan on - * this host has _not_ yet been done. - * The hostdata array (by default zero length) is a per host scratch - * area for the LLD. - * - * Defined in: drivers/scsi/hosts.c . - **/ -struct Scsi_Host * scsi_register(struct SHT *, int xtr_bytes) - - -/** - * scsi_register_host - register a low level host driver - * @shost_tp: pointer to a scsi host driver template - * - * Returns 0 on Success, 1 on failure - * - * Notes: Should only be invoked if the "passive initialization - * model" is being used. Notice this is a _driver_ rather than - * HBA registration function. Most older drivers call this - * function by including the scsi_module.c file. - * This function is deprecated, use the "hotplug initialization - * model" instead. + * Notes: When this call returns to the LLDD, the SCSI bus scan on + * this host has _not_ yet been done. + * The hostdata array (by default zero length) is a per host scratch + * area for the LLD. * - * Defined in: drivers/scsi/hosts.c . + * Defined in: drivers/scsi/hosts.c . **/ -int scsi_register_host(Scsi_Host_Template *shost_tp) +struct Scsi_Host * scsi_register(struct scsi_host_template *, int xtr_bytes) /** * scsi_remove_device - detach and remove a SCSI device * @sdev: a pointer to a scsi device instance * - * Returns value: 0 on success, -EINVAL if device not attached + * Returns value: 0 on success, -EINVAL if device not attached * * Notes: If a LLD becomes aware that a scsi device (lu) has - * been removed but its host is still present then it can request - * the removal of that scsi device. If successful this call will - * lead to the slave_destroy() callback being invoked. sdev is an - * invalid pointer after this call. + * been removed but its host is still present then it can request + * the removal of that scsi device. If successful this call will + * lead to the slave_destroy() callback being invoked. sdev is an + * invalid pointer after this call. * - * Defined in: drivers/scsi/scsi_scan.c . + * Defined in: drivers/scsi/scsi_scan.c . **/ int scsi_remove_device(struct scsi_device *sdev) @@ -536,13 +623,13 @@ * scsi_remove_host - detach and remove all SCSI devices owned by host * @shost: a pointer to a scsi host instance * - * Returns value: 0 on success, 1 on failure (e.g. LLD busy ??) + * Returns value: 0 on success, 1 on failure (e.g. LLD busy ??) * * Notes: Should only be invoked if the "hotplug initialization - * model" is being used. It should be called _prior_ to - * scsi_unregister(). + * model" is being used. It should be called _prior_ to + * scsi_unregister(). * - * Defined in: drivers/scsi/hosts.c . + * Defined in: drivers/scsi/hosts.c . **/ int scsi_remove_host(struct Scsi_Host *shost) @@ -552,15 +639,15 @@ * @shost: a pointer to a scsi host involved * @channel: channel (within) host on which scsi bus reset occurred * - * Returns nothing + * Returns nothing * * Notes: This only needs to be called if the reset is one which - * originates from an unknown location. Resets originated by the - * mid level itself don't need to call this, but there should be - * no harm. The main purpose of this is to make sure that a - * CHECK_CONDITION is properly treated. + * originates from an unknown location. Resets originated by the + * mid level itself don't need to call this, but there should be + * no harm. The main purpose of this is to make sure that a + * CHECK_CONDITION is properly treated. * - * Defined in: drivers/scsi/scsi_lib.c . + * Defined in: drivers/scsi/scsi_lib.c . **/ void scsi_report_bus_reset(struct Scsi_Host * shost, int channel) @@ -570,7 +657,7 @@ * @shost: a pointer to a scsi host instance * @pdev: pointer to device instance to assign * - * Returns nothing + * Returns nothing * * Defined in: drivers/scsi/hosts.h . **/ @@ -581,13 +668,13 @@ * scsi_set_device_offline - set device offline then flush its queue * @sdev: a pointer to a scsi device instance to be set offline * - * Returns nothing + * Returns nothing * * Notes: Commands that are currently active on the scsi device have - * their timers cancelled and are transferred to the host's - * "eh" list for cancellation. + * their timers cancelled and are transferred to the host's + * "eh" list for cancellation. - * Defined in: drivers/scsi/scsi.c . + * Defined in: drivers/scsi/scsi.c . **/ void scsi_set_device_offline(struct scsi_device * sdev) @@ -596,10 +683,10 @@ * scsi_to_pci_dma_dir - convert SCSI subsystem direction flag to PCI * @scsi_data_direction: SCSI subsystem direction flag * - * Returns PCI_DMA_TODEVICE given SCSI_DATA_WRITE, - * PCI_DMA_FROMDEVICE given SCSI_DATA_READ - * PCI_DMA_BIDIRECTIONAL given SCSI_DATA_UNKNOWN - * else returns PCI_DMA_NONE + * Returns PCI_DMA_TODEVICE given SCSI_DATA_WRITE, + * PCI_DMA_FROMDEVICE given SCSI_DATA_READ + * PCI_DMA_BIDIRECTIONAL given SCSI_DATA_UNKNOWN + * else returns PCI_DMA_NONE * * Defined in: drivers/scsi/scsi.h . **/ @@ -610,10 +697,10 @@ * scsi_to_sbus_dma_dir - convert SCSI subsystem direction flag to SBUS * @scsi_data_direction: SCSI subsystem direction flag * - * Returns SBUS_DMA_TODEVICE given SCSI_DATA_WRITE, - * SBUS_DMA_FROMDEVICE given SCSI_DATA_READ - * SBUS_DMA_BIDIRECTIONAL given SCSI_DATA_UNKNOWN - * else returns SBUS_DMA_NONE + * Returns SBUS_DMA_TODEVICE given SCSI_DATA_WRITE, + * SBUS_DMA_FROMDEVICE given SCSI_DATA_READ + * SBUS_DMA_BIDIRECTIONAL given SCSI_DATA_UNKNOWN + * else returns SBUS_DMA_NONE * * Defined in: drivers/scsi/scsi.h . **/ @@ -622,21 +709,21 @@ /** * scsi_track_queue_full - track successive QUEUE_FULL events on given - * device to determine if and when there is a need - * to adjust the queue depth on the device. + * device to determine if and when there is a need + * to adjust the queue depth on the device. * @SDptr: pointer to SCSI device instance * @depth: Current number of outstanding SCSI commands on this device, - * not counting the one returned as QUEUE_FULL. + * not counting the one returned as QUEUE_FULL. * * Returns 0 - no change needed - * >0 - adjust queue depth to this new depth - * -1 - drop back to untagged operation using host->cmd_per_lun - * as the untagged command depth + * >0 - adjust queue depth to this new depth + * -1 - drop back to untagged operation using host->cmd_per_lun + * as the untagged command depth * * Notes: LLDs may call this at any time and we will do "The Right - * Thing"; interrupt context safe. + * Thing"; interrupt context safe. * - * Defined in: drivers/scsi/scsi.c . + * Defined in: drivers/scsi/scsi.c . **/ int scsi_track_queue_full(Scsi_Device *SDptr, int depth) @@ -646,70 +733,48 @@ * * @SHpnt: pointer to host to unblock commands on * - * Returns nothing + * Returns nothing * - * Defined in: drivers/scsi/scsi_lib.c . + * Defined in: drivers/scsi/scsi_lib.c . **/ void scsi_unblock_requests(struct Scsi_Host * SHpnt) /** * scsi_unregister - unregister and free memory used by host instance - * @shp: pointer to scsi host instance to unregister. + * @shp: pointer to scsi host instance to unregister. * - * Returns nothing + * Returns nothing * * Notes: Should only be invoked if the "hotplug initialization - * model" is being used. It should be called _after_ - * scsi_remove_host(). The shp pointer is invalid after this call. + * model" is being used. It should be called _after_ + * scsi_remove_host(). The shp pointer is invalid after this call. * - * Defined in: drivers/scsi/hosts.c . + * Defined in: drivers/scsi/hosts.c . **/ void scsi_unregister(struct Scsi_Host * shp) -/** - * scsi_unregister_host - unregister a low level host adapter driver - * @shost_tp: scsi host template to unregister. - * - * Returns 0 on Success, 1 on Failure - * - * Notes: Should only be invoked if the "passive initialization - * model" is being used. Notice this is a _driver_ rather than - * HBA deregistration function. So if there are multiple HBAs - * associated with the given template, they are each removed. Most - * older drivers call this function by including the scsi_module.c - * file. This function is deprecated, use the "hotplug initialization - * model" instead. - * - * Defined in: drivers/scsi/hosts.c . - **/ -int scsi_unregister_host(Scsi_Host_Template *shost_tp) - Interface Functions =================== -Interface functions are supplied (defined) by LLDs and -their function pointers are placed in an instance of struct SHT which -is passed to scsi_register() [or scsi_register_host()]. Some -are mandatory. Interface functions should be declared static. The +Interface functions are supplied (defined) by LLDs and their function +pointers are placed in an instance of struct scsi_host_template which +is passed to scsi_host_alloc() [or scsi_register() / init_this_scsi_driver()]. +Some are mandatory. Interface functions should be declared static. The accepted convention is that driver "xyz" will declare its slave_configure() function as: static int xyz_slave_configure(struct scsi_device * sdev); A pointer to this function should be placed in the 'slave_configure' member -of a "struct SHT" instance. A pointer to such an instance should -passed to the mid level's scsi_register() [or scsi_register_host()]. +of a "struct scsi_host_template" instance. A pointer to such an instance +should passed to the mid level's scsi_host_alloc() [or scsi_register() / +init_this_scsi_driver()]. The interface functions are also described in the hosts.h file immediately -above their definition point in "struct SHT". In some cases more detail -is given in hosts.h than below. - -Those interface functions marked "Required: yes" must be implemented -by the LLD and a pointer to that function must be placed in the driver's -"struct SHT" instance. Interface functions marked "Required: no" need not -be implemented. +above their definition point in "struct scsi_host_template". In some cases +more detail is given in hosts.h than below. The interface functions are listed below in alphabetical order. @@ -731,13 +796,14 @@ slave_configure - driver fine tuning for given device after attach slave_destroy - given device is about to be shut down + Details: /** * bios_param - fetch head, sector, cylinder info for a disk * @sdev: pointer to scsi device context (defined in scsi.h) * @bdev: pointer to block device context (defined in fs.h) - * @capacity: device size (in 512 byte sectors) + * @capacity: device size (in 512 byte sectors) * @params: three element array to place output: * params[0] number of heads (max 255) * params[1] number of sectors (max 63) @@ -745,8 +811,6 @@ * * Return value is ignored * - * Required: no - * * Locks: none * * Notes: an arbitrary geometry (based on READ CAPACITY) is used @@ -754,10 +818,10 @@ * pre-initialized with made up values just in case this function * doesn't output anything. * - * Defined in: LLD + * Optionally defined in: LLD **/ int bios_param(struct scsi_device * sdev, struct block_device *bdev, - sector_t capacity, int params[3]); + sector_t capacity, int params[3]) /** @@ -768,18 +832,16 @@ * host_byte, driver_byte (status_byte is in the lsb). A value of * 0 is an unqualified success. * - * Required: if struct Scsi_Host::can_queue can ever by cleared (zero) - * then this function is required. - * * Locks: struct Scsi_Host::host_lock held on entry (with "irqsave") * and is expected to be held on return. * * Notes: Drivers tend to be dropping support for this function and * supporting queuecommand() instead. * - * Defined in: LLD + * Defined in: LLD (if struct Scsi_Host::can_queue can ever by cleared + * (zero) then this function is required) **/ - int command(struct scsi_cmnd * scp); + int command(struct scsi_cmnd * scp) /** @@ -789,9 +851,6 @@ * Returns number of hosts this driver wants to control. 0 means no * suitable hosts found. * - * Required: yes, if "passive initialization mode" is used - * [in "hotplug initialization mode" it is not invoked] - * * Locks: none held * * Notes: First function called from the SCSI mid level on this @@ -799,9 +858,10 @@ * For each host found, this method should call scsi_register() * [see hosts.c]. * - * Defined in: LLD + * Defined in: LLD (required if "passive initialization mode" is used, + * not invoked in "hotplug initialization mode") **/ - int detect(struct SHT * shtp); + int detect(struct scsi_host_template * shtp) /** @@ -810,17 +870,15 @@ * * Returns SUCCESS if command aborted else FAILED * - * Required: no - * * Locks: struct Scsi_Host::host_lock held (with irqsave) on entry - * and assumed to be held on return. + * and assumed to be held on return. * * Notes: Invoked from scsi_eh thread. No other commands will be * queued on current host during eh. * - * Defined in: LLD + * Optionally defined in: LLD **/ - int eh_abort_handler(struct scsi_cmnd * scp); + int eh_abort_handler(struct scsi_cmnd * scp) /** @@ -829,17 +887,15 @@ * * Returns SUCCESS if command aborted else FAILED * - * Required: no - * * Locks: struct Scsi_Host::host_lock held (with irqsave) on entry - * and assumed to be held on return. + * and assumed to be held on return. * * Notes: Invoked from scsi_eh thread. No other commands will be * queued on current host during eh. * - * Defined in: LLD + * Optionally defined in: LLD **/ - int eh_bus_reset_handler(struct scsi_cmnd * scp); + int eh_bus_reset_handler(struct scsi_cmnd * scp) /** @@ -848,17 +904,15 @@ * * Returns SUCCESS if command aborted else FAILED * - * Required: no - * * Locks: struct Scsi_Host::host_lock held (with irqsave) on entry - * and assumed to be held on return. + * and assumed to be held on return. * * Notes: Invoked from scsi_eh thread. No other commands will be * queued on current host during eh. * - * Defined in: LLD + * Optionally defined in: LLD **/ - int eh_device_reset_handler(struct scsi_cmnd * scp); + int eh_device_reset_handler(struct scsi_cmnd * scp) /** @@ -867,10 +921,8 @@ * * Returns SUCCESS if command aborted else FAILED * - * Required: no - * * Locks: struct Scsi_Host::host_lock held (with irqsave) on entry - * and assumed to be held on return. + * and assumed to be held on return. * * Notes: Invoked from scsi_eh thread. No other commands will be * queued on current host during eh. @@ -879,9 +931,9 @@ * defined (or they all return FAILED) then the device in question * will be set offline whenever eh is invoked. * - * Defined in: LLD + * Optionally defined in: LLD **/ - int eh_host_reset_handler(struct scsi_cmnd * scp); + int eh_host_reset_handler(struct scsi_cmnd * scp) /** @@ -890,16 +942,14 @@ * * Returns TRUE if host unjammed, else FALSE. * - * Required: no - * * Locks: none * - * Notes: Invoked from scsi_eh thread. Driver supplied alternate to + * Notes: Invoked from scsi_eh thread. LLD supplied alternate to * scsi_unjam_host() found in scsi_error.c * - * Defined in: LLD + * Optionally defined in: LLD **/ - int eh_strategy_handler(struct Scsi_Host * shp); + int eh_strategy_handler(struct Scsi_Host * shp) /** @@ -911,8 +961,6 @@ * manage the memory pointed to and maintain it, typically for the * lifetime of this host.] * - * Required: no - * * Locks: none * * Notes: Often supplies PCI or ISA information such as IO addresses @@ -921,15 +969,15 @@ * (i.e. does not included embedded newlines). * The SCSI_IOCTL_PROBE_HOST ioctl yields the string returned by this * function (or struct Scsi_Host::name if this function is not - * available). - * In a similar manner, scsi_register_host() outputs to the console + * available). + * In a similar manner, init_this_scsi_driver() outputs to the console * each host's "info" (or name) for the driver it is registering. * Also if proc_info() is not supplied, the output of this function * is used instead. * - * Defined in: LLD + * Optionally defined in: LLD **/ - const char * info(struct Scsi_Host * shp); + const char * info(struct Scsi_Host * shp) /** @@ -944,8 +992,6 @@ * Returns negative "errno" value when there is a problem. 0 or a * positive value indicates success and is returned to the user space. * - * Required: no - * * Locks: none * * Notes: The SCSI subsystem uses a "trickle down" ioctl model. @@ -958,11 +1004,11 @@ * However the mid level returns -EINVAL for unrecognized 'cmd' * numbers when this function is not supplied by the driver. * Unfortunately some applications expect -EINVAL and react badly - * when -ENOTTY is returned; stick with -EINVAL. + * when -ENOTTY is returned; stick with -EINVAL. * - * Defined in: LLD + * Optionally defined in: LLD **/ - int ioctl(struct scsi_device *sdp, int cmd, void *arg); + int ioctl(struct scsi_device *sdp, int cmd, void *arg) /** @@ -983,16 +1029,14 @@ * Returns length when 1==writeto1_read0. Otherwise number of chars * output to buffer past offset. * - * Required: no - * * Locks: none held * * Notes: Driven from scsi_proc.c which interfaces to proc_fs * - * Defined in: LLD + * Optionally defined in: LLD **/ -int proc_info(char * buffer, char ** start, off_t offset, - int length, int hostno, int writeto1_read0); + int proc_info(char * buffer, char ** start, off_t offset, + int length, int hostno, int writeto1_read0) /** @@ -1000,13 +1044,10 @@ * @scp: pointer to scsi command object * @done: function pointer to be invoked on completion * - * Returns 1 if the adapter (host) is busy, else returns 0. One - * reason for an adapter to be busy is that the number - * of outstanding queued commands is already equal to - * struct Scsi_Host::can_queue . - * - * Required: if struct Scsi_Host::can_queue is ever non-zero - * then this function is required. + * Returns 0 on success and 1 if the LLD or the HBA is busy (i.e. run + * out of resources to queue further commands). Other types of errors + * are flagged by setting struct scsi_cmnd:result to an appropriate + * value, invoking the 'done' callback, and then returning 0. * * Locks: struct Scsi_Host::host_lock held on entry (with "irqsave") * and is expected to be held on return. @@ -1024,14 +1065,15 @@ * this case, it should be placed in scp->result before this function * returns. * If a status of CHECK CONDITION is placed in "result" when the - * 'done' callback is invoked, then the LLD driver should - * perform autosense and fill in the struct scsi_cmnd::sense_buffer - * array. + * 'done' callback is invoked, then the LLD driver should + * perform autosense and fill in the struct scsi_cmnd::sense_buffer + * array. * - * Defined in: LLD + * Defined in: LLD (required if if struct Scsi_Host::can_queue is ever + * non-zero) **/ int queuecommand(struct scsi_cmnd * scp, - void (*done)(struct scsi_cmnd *)); + void (*done)(struct scsi_cmnd *)) /** @@ -1040,100 +1082,91 @@ * * Return value ignored (could soon be a function returning void). * - * Required: yes (see notes) - * * Locks: none held * - * Notes: Invoked from mid level's scsi_unregister_host(). + * Notes: Invoked from scsi_module.c's exit_this_scsi_driver(). * LLD's implementation of this function should call - * scsi_unregister(shp) prior to returning. - * If not supplied mid-level [in hosts.c] supplies its own - * implementation (see scsi_host_legacy_release()) which is for old - * ISA adapters so it is best not to use it. + * scsi_unregister(shp) prior to returning. + * Only needed for old-style host templates. * - * Defined in: LLD + * Defined in: LLD (required in "passive initialization model", + * should not be defined in hotplug model) **/ - int release(struct Scsi_Host * shp); + int release(struct Scsi_Host * shp) /** - * slave_alloc - prior to any commands being sent to a new device - * (i.e. just prior to scan) this call is made + * slave_alloc - prior to any commands being sent to a new device + * (i.e. just prior to scan) this call is made * @sdp: pointer to new device (about to be scanned) * * Returns 0 if ok. Any other return is assumed to be an error and - * the device is ignored. - * - * Required: no + * the device is ignored. * * Locks: none * * Notes: Allows the driver to allocate any resources for a device - * prior to its initial scan. The corresponding scsi device may not - * exist but the mid level is just about to scan for it (i.e. send - * and INQUIRY command plus ...). If a device is found then - * slave_configure() will be called while if a device is not found - * slave_destroy() is called. + * prior to its initial scan. The corresponding scsi device may not + * exist but the mid level is just about to scan for it (i.e. send + * and INQUIRY command plus ...). If a device is found then + * slave_configure() will be called while if a device is not found + * slave_destroy() is called. * For more details see the hosts.h file. * - * Defined in: LLD + * Optionally defined in: LLD **/ - int slave_alloc(struct scsi_device *sdp); + int slave_alloc(struct scsi_device *sdp) /** * slave_configure - driver fine tuning for given device just after it - * has been first scanned (i.e. it responded to an - * INQUIRY) + * has been first scanned (i.e. it responded to an + * INQUIRY) * @sdp: device that has just been attached * * Returns 0 if ok. Any other return is assumed to be an error and - * the device is taken offline. [offline devices will _not_ have - * slave_destroy() called on them so clean up resources.] - * - * Required: no + * the device is taken offline. [offline devices will _not_ have + * slave_destroy() called on them so clean up resources.] * * Locks: none * * Notes: Allows the driver to inspect the response to the initial - * INQUIRY done by the scanning code and take appropriate action. - * For more details see the hosts.h file. + * INQUIRY done by the scanning code and take appropriate action. + * For more details see the hosts.h file. * - * Defined in: LLD + * Optionally defined in: LLD **/ - int slave_configure(struct scsi_device *sdp); + int slave_configure(struct scsi_device *sdp) /** * slave_destroy - given device is about to be shut down. All - * activity has ceased on this device. + * activity has ceased on this device. * @sdp: device that is about to be shut down * * Returns nothing * - * Required: no - * * Locks: none * * Notes: Mid level structures for given device are still in place - * but are about to be torn down. Any per device resources allocated - * by this driver for given device should be freed now. No further - * commands will be sent for this sdp instance. [However the device - * could be re-attached in the future in which case a new instance - * of struct scsi_device would be supplied by future slave_alloc() - * and slave_configure() calls.] + * but are about to be torn down. Any per device resources allocated + * by this driver for given device should be freed now. No further + * commands will be sent for this sdp instance. [However the device + * could be re-attached in the future in which case a new instance + * of struct scsi_device would be supplied by future slave_alloc() + * and slave_configure() calls.] * - * Defined in: LLD + * Optionally defined in: LLD **/ - void slave_destroy(struct scsi_device *sdp); + void slave_destroy(struct scsi_device *sdp) Data Structures =============== -struct SHT ----------- -There is one "struct SHT" instance per LLD ***. It is +struct scsi_host_template +------------------------- +There is one "struct scsi_host_template" instance per LLD ***. It is typically initialized as a file scope static in a driver's header file. That way members that are not explicitly initialized will be set to 0 or NULL. Member of interest: @@ -1143,22 +1176,23 @@ by sysfs in one of its "drivers" directories. Hence "proc_name" should only contain characters acceptable to a Unix file name. - (*release)() - should be defined by all LLDs as the default (legacy) - implementation is only appropriate for ISA adapters). + (*queuecommand)() - primary callback that the mid level uses to inject + SCSI commands into a LLD. The structure is defined and commented in hosts.h *** In extreme situations a single driver may have several instances - if it controls several different classes of hardware (e.g. the - advansys driver handles both ISA and PCI cards and has a separate - instance of struct SHT for each). + if it controls several different classes of hardware (e.g. a LLD + that handles both ISA and PCI cards and has a separate instance of + struct scsi_host_template for each class). struct Scsi_Host ---------------- There is one struct Scsi_Host instance per host (HBA) that a LLD controls. The struct Scsi_Host structure has many members in common -with "struct SHT". When a new struct Scsi_Host instance is created (in -scsi_register() in hosts.c) those common members are initialized from -the driver's struct SHT instance. Members of interest: +with "struct scsi_host_template". When a new struct Scsi_Host instance +is created (in scsi_host_alloc() in hosts.c) those common members are +initialized from the driver's struct scsi_host_template instance. Members +of interest: host_no - system wide unique number that is used for identifying this host. Issued in ascending order from 0 (and the positioning can be influenced by the scsihosts @@ -1172,7 +1206,7 @@ in a single SCSI command. 0 implies no maximum. cmd_per_lun - maximum number of command that can be queued on devices controlled by the host. Overridden by LLD calls to - scsi_adjust_queue_depth(). + scsi_adjust_queue_depth(). unchecked_isa_dma - 1->only use bottom 16 MB of ram (ISA DMA addressing restriction), 0->can use full 32 bit (or better) DMA address space @@ -1180,22 +1214,22 @@ 0->disallow SCSI command merging highmem_io - 1->can DMA in to or out of high memory, 0->use bounce buffers if data is in high memory - hostt - pointer to driver's struct SHT from which this - struct Scsi_Host instance was spawned + hostt - pointer to driver's struct scsi_host_template from which + this struct Scsi_Host instance was spawned sh_list - a double linked list of pointers to all struct Scsi_Host instances (currently ordered by ascending host_no) my_devices - a double linked list of pointers to struct scsi_device - instances that belong to this host. + instances that belong to this host. hostdata[0] - area reserved for LLD at end of struct Scsi_Host. Size is set by the second argument (named 'xtr_bytes') to - scsi_register(). + scsi_host_alloc() or scsi_register(). The structure is defined in hosts.h struct scsi_device ------------------ Generally, there is one instance of this structure for each SCSI logical unit -on a host. Scsi devices are uniquely identified within a host by bus number, -cahnnel number, target id and logical unit number (lun). +on a host. Scsi devices connected to a host are uniquely identified by a +channel number, target id and logical unit number (lun). The structure is defined in scsi.h struct scsi_cmnd @@ -1211,7 +1245,7 @@ Locks ===== Each struct Scsi_Host instance has a spin_lock called struct -Scsi_Host::default_lock which is initialized in scsi_register() [found in +Scsi_Host::default_lock which is initialized in scsi_host_alloc() [found in hosts.c]. Within the same function the struct Scsi_Host::host_lock pointer is initialized to point at default_lock with the scsi_assign_lock() function. Thereafter lock and unlock operations performed by the mid level use the @@ -1236,11 +1270,12 @@ to perform an extra data in phase on such responses b) or, the LLD issuing a REQUEST SENSE command itself -Either way, the mid level decides whether the LLD has -performed autosense by checking struct scsi_cmnd::sense_buffer[0] . If this -byte has an upper nibble of 7 (or 0xf) then autosense is assumed to have -taken place. If it has another value (and this byte is initialized to 0 -before each command) then the mid level will issue a REQUEST SENSE command. +Either way, when a status of CHECK CONDITION is detected, the mid level +decides whether the LLD has performed autosense by checking struct +scsi_cmnd::sense_buffer[0] . If this byte has an upper nibble of 7 (or 0xf) +then autosense is assumed to have taken place. If it has another value (and +this byte is initialized to 0 before each command) then the mid level will +issue a REQUEST SENSE command. In the presence of queued commands the "nexus" that maintains sense buffer data from the command that failed until a following REQUEST SENSE @@ -1256,7 +1291,7 @@ The older error handling mechanism has been removed. This means the LLD interface functions abort() and reset() have been removed. -The struct SHT::use_new_eh_code flag has been removed. +The struct scsi_host_template::use_new_eh_code flag has been removed. In the 2.4 series the SCSI subsystem configuration descriptions were aggregated with the configuration descriptions from all other Linux @@ -1264,9 +1299,10 @@ the SCSI subsystem now has its own (much smaller) drivers/scsi/Config.help file. -Addition of slave_alloc(), slave_configure() and slave_destroy(). +struct SHT has been renamed to struct scsi_host_template. -Addition of the "hotplug initialization model". +Addition of the "hotplug initialization model" and many extra functions +to support it. Credits @@ -1275,11 +1311,11 @@ Mike Anderson James Bottomley Patrick Mansfield - Christoph Hellwig - Doug Ledford + Christoph Hellwig + Doug Ledford Andries Brouwer Douglas Gilbert dgilbert@interlog.com -29th April 2003 +18th June 2003 diff -Nru a/MAINTAINERS b/MAINTAINERS --- a/MAINTAINERS Tue Jul 1 18:44:35 2003 +++ b/MAINTAINERS Tue Jul 1 18:44:35 2003 @@ -1628,8 +1628,8 @@ SGI VISUAL WORKSTATION 320 AND 540 P: Andrey Panin -M: pazke@orbita1.ru -L: linux-visws@lists.sf.net +M: pazke@donpac.ru +L: linux-visws-devel@lists.sf.net W: http://linux-visws.sf.net S: Maintained for 2.5. diff -Nru a/Makefile b/Makefile --- a/Makefile Tue Jul 1 18:44:36 2003 +++ b/Makefile Tue Jul 1 18:44:36 2003 @@ -388,7 +388,7 @@ kallsyms.o := .tmp_kallsyms2.o quiet_cmd_kallsyms = KSYM $@ -cmd_kallsyms = $(NM) -n $< | scripts/kallsyms > $@ +cmd_kallsyms = $(NM) -n $< | $(KALLSYMS) > $@ .tmp_kallsyms1.o .tmp_kallsyms2.o: %.o: %.S scripts FORCE $(call if_changed_dep,as_o_S) diff -Nru a/arch/alpha/Kconfig b/arch/alpha/Kconfig --- a/arch/alpha/Kconfig Tue Jul 1 18:44:36 2003 +++ b/arch/alpha/Kconfig Tue Jul 1 18:44:36 2003 @@ -665,33 +665,8 @@ source "drivers/ide/Kconfig" - -menu "SCSI support" - -config SCSI - tristate "SCSI support" - ---help--- - If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or - any other SCSI device under Linux, say Y and make sure that you know - the name of your SCSI host adapter (the card inside your computer - that "speaks" the SCSI protocol, also called SCSI controller), - because you will be asked for it. - - You also need to say Y here if you want support for the parallel - port version of the 100 MB IOMEGA ZIP drive. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called scsi_mod. If you want to compile it as - a module, say M here and read and - . However, do not compile this as a - module if your root file system (the one containing the directory /) - is located on a SCSI device. - source "drivers/scsi/Kconfig" -endmenu - if PCI source "drivers/message/fusion/Kconfig" endif @@ -704,41 +679,7 @@ source "drivers/isdn/Kconfig" - -menu "Old CD-ROM drivers (not SCSI, not IDE)" - -config CD_NO_IDESCSI - bool "Support non-SCSI/IDE/ATAPI CDROM drives" - ---help--- - If you have a CD-ROM drive that is neither SCSI nor IDE/ATAPI, say Y - here, otherwise N. Read the CD-ROM-HOWTO, available from - . - - Note that the answer to this question doesn't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about these CD-ROM drives. If you are unsure what you - have, say Y and find out whether you have one of the following - drives. - - For each of these drivers, a file Documentation/cdrom/{driver_name} - exists. Especially in cases where you do not know exactly which kind - of drive you have you should read there. Most of these drivers use a - file drivers/cdrom/{driver_name}.h where you can define your - interface parameters and switch some internal goodies. - - All these CD-ROM drivers are also usable as a module ( = code which - can be inserted in and removed from the running kernel whenever you - want). If you want to compile them as module, say M instead of Y and - read . - - If you want to use any of these CD-ROM drivers, you also have to - answer Y or M to "ISO 9660 CD-ROM file system support" below (this - answer will get "defaulted" for you if you enable any of the Linux - CD-ROM drivers). - source "drivers/cdrom/Kconfig" - -endmenu source "drivers/input/Kconfig" diff -Nru a/arch/alpha/kernel/core_t2.c b/arch/alpha/kernel/core_t2.c --- a/arch/alpha/kernel/core_t2.c Tue Jul 1 18:44:31 2003 +++ b/arch/alpha/kernel/core_t2.c Tue Jul 1 18:44:31 2003 @@ -465,10 +465,17 @@ *(vulp)T2_HAE_1 = 0; mb(); /* Sparse MEM HAE */ *(vulp)T2_HAE_2 = 0; mb(); /* Sparse I/O HAE */ *(vulp)T2_HAE_3 = 0; mb(); /* Config Space HAE */ -#if 0 - /* !!! DO NOT EVER TOUCH THIS !!! */ - *(vulp)T2_HAE_4 = 0; mb(); /* Dense MEM HAE */ -#endif + + /* + * We also now zero out HAE_4, the dense memory HAE, so that + * we need not account for its "offset" when accessing dense + * memory resources which we allocated in our normal way. This + * HAE would need to stay untouched were we to keep the SRM + * resource settings. + * + * Thus we can now run standard X servers on SABLE/LYNX. :-) + */ + *(vulp)T2_HAE_4 = 0; mb(); } void diff -Nru a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c --- a/arch/alpha/kernel/process.c Tue Jul 1 18:44:37 2003 +++ b/arch/alpha/kernel/process.c Tue Jul 1 18:44:37 2003 @@ -270,7 +270,7 @@ struct thread_info *childti = p->thread_info; struct pt_regs * childregs; struct switch_stack * childstack, *stack; - unsigned long stack_offset; + unsigned long stack_offset, settls; stack_offset = PAGE_SIZE - sizeof(struct pt_regs); if (!(regs->ps & 8)) @@ -279,6 +279,7 @@ (stack_offset + PAGE_SIZE + (long) childti); *childregs = *regs; + settls = regs->r20; childregs->r0 = 0; childregs->r19 = 0; childregs->r20 = 1; /* OSF/1 has some strange fork() semantics. */ @@ -292,14 +293,16 @@ childti->pcb.flags = 1; /* set FEN, clear everything else */ /* Set a new TLS for the child thread? Peek back into the - syscall arguments that we saved on syscall entry. */ + syscall arguments that we saved on syscall entry. Oops, + except we'd have clobbered it with the parent/child set + of r20. Read the saved copy. */ /* Note: if CLONE_SETTLS is not set, then we must inherit the value from the parent, which will have been set by the block copy in dup_task_struct. This is non-intuitive, but is required for proper operation in the case of a threaded application calling fork. */ if (clone_flags & CLONE_SETTLS) - childti->pcb.unique = regs->r20; + childti->pcb.unique = settls; return 0; } diff -Nru a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c --- a/arch/alpha/kernel/time.c Tue Jul 1 18:44:35 2003 +++ b/arch/alpha/kernel/time.c Tue Jul 1 18:44:35 2003 @@ -371,6 +371,9 @@ xtime.tv_sec = mktime(year, mon, day, hour, min, sec); xtime.tv_nsec = 0; + wall_to_monotonic.tv_sec -= xtime.tv_sec; + wall_to_monotonic.tv_nsec = 0; + if (HZ > (1<<16)) { extern void __you_loose (void); __you_loose(); @@ -485,6 +488,16 @@ time_status |= STA_UNSYNC; time_maxerror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT; + + wall_to_monotonic.tv_sec += xtime.tv_sec - tv->tv_sec; + wall_to_monotonic.tv_nsec += xtime.tv_nsec - tv->tv_nsec; + if (wall_to_monotonic.tv_nsec > NSEC_PER_SEC) { + wall_to_monotonic.tv_nsec -= NSEC_PER_SEC; + wall_to_monotonic.tv_sec++; + } else if (wall_to_monotonic.tv_nsec < 0) { + wall_to_monotonic.tv_nsec += NSEC_PER_SEC; + wall_to_monotonic.tv_sec--; + } write_sequnlock_irq(&xtime_lock); return 0; diff -Nru a/arch/alpha/lib/ev6-memset.S b/arch/alpha/lib/ev6-memset.S --- a/arch/alpha/lib/ev6-memset.S Tue Jul 1 18:44:32 2003 +++ b/arch/alpha/lib/ev6-memset.S Tue Jul 1 18:44:32 2003 @@ -38,7 +38,6 @@ .ent __memset .align 5 __memset: -memset: .frame $30,0,$26,0 .prologue 0 @@ -594,3 +593,5 @@ ret $31,($26),1 # L0 : .end __memsetw + +memset = __memset diff -Nru a/arch/alpha/lib/memset.S b/arch/alpha/lib/memset.S --- a/arch/alpha/lib/memset.S Tue Jul 1 18:44:31 2003 +++ b/arch/alpha/lib/memset.S Tue Jul 1 18:44:31 2003 @@ -17,6 +17,7 @@ .set noat .set noreorder .text + .globl memset .globl __memset .globl __memsetw .globl __constant_c_memset @@ -120,8 +121,4 @@ .end __memsetw -#ifdef __ELF__ - .weak memset; memset = __memset -#else - .weakext memset, __memset -#endif +memset = __memset diff -Nru a/arch/arm/Kconfig b/arch/arm/Kconfig --- a/arch/arm/Kconfig Tue Jul 1 18:44:35 2003 +++ b/arch/arm/Kconfig Tue Jul 1 18:44:35 2003 @@ -898,32 +898,7 @@ source "drivers/ide/Kconfig" - -menu "SCSI support" - -config SCSI - tristate "SCSI support" - ---help--- - If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or - any other SCSI device under Linux, say Y and make sure that you know - the name of your SCSI host adapter (the card inside your computer - that "speaks" the SCSI protocol, also called SCSI controller), - because you will be asked for it. - - You also need to say Y here if you want support for the parallel - port version of the 100 MB IOMEGA ZIP drive. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called scsi_mod. If you want to compile it as - a module, say M here and read and - . However, do not compile this as a - module if your root file system (the one containing the directory /) - is located on a SCSI device. - source "drivers/scsi/Kconfig" - -endmenu source "drivers/ieee1394/Kconfig" diff -Nru a/arch/arm26/Kconfig b/arch/arm26/Kconfig --- a/arch/arm26/Kconfig Tue Jul 1 18:44:35 2003 +++ b/arch/arm26/Kconfig Tue Jul 1 18:44:35 2003 @@ -364,31 +364,7 @@ endmenu -menu "SCSI support" - -config SCSI - tristate "SCSI support" - ---help--- - If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or - any other SCSI device under Linux, say Y and make sure that you know - the name of your SCSI host adapter (the card inside your computer - that "speaks" the SCSI protocol, also called SCSI controller), - because you will be asked for it. - - You also need to say Y here if you want support for the parallel - port version of the 100 MB IOMEGA ZIP drive. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called scsi_mod. If you want to compile it as - a module, say M here and read and - . However, do not compile this as a - module if your root file system (the one containing the directory /) - is located on a SCSI device. - source "drivers/scsi/Kconfig" - -endmenu source "drivers/isdn/Kconfig" diff -Nru a/arch/cris/Kconfig b/arch/cris/Kconfig --- a/arch/cris/Kconfig Tue Jul 1 18:44:37 2003 +++ b/arch/cris/Kconfig Tue Jul 1 18:44:38 2003 @@ -533,33 +533,8 @@ source "drivers/ide/Kconfig" - -menu "SCSI support" - -config SCSI - tristate "SCSI support" - ---help--- - If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or - any other SCSI device under Linux, say Y and make sure that you know - the name of your SCSI host adapter (the card inside your computer - that "speaks" the SCSI protocol, also called SCSI controller), - because you will be asked for it. - - You also need to say Y here if you want support for the parallel - port version of the 100 MB IOMEGA ZIP drive. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called scsi_mod. If you want to compile it as - a module, say M here and read and - . However, do not compile this as a - module if your root file system (the one containing the directory /) - is located on a SCSI device. - source "drivers/scsi/Kconfig" -endmenu - source "drivers/ieee1394/Kconfig" source "drivers/message/i2o/Kconfig" @@ -574,41 +549,7 @@ source "drivers/telephony/Kconfig" - -menu "Old CD-ROM drivers (not SCSI, not IDE)" - -config CD_NO_IDESCSI - bool "Support non-SCSI/IDE/ATAPI CDROM drives" - ---help--- - If you have a CD-ROM drive that is neither SCSI nor IDE/ATAPI, say Y - here, otherwise N. Read the CD-ROM-HOWTO, available from - . - - Note that the answer to this question doesn't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about these CD-ROM drives. If you are unsure what you - have, say Y and find out whether you have one of the following - drives. - - For each of these drivers, a file Documentation/cdrom/{driver_name} - exists. Especially in cases where you do not know exactly which kind - of drive you have you should read there. Most of these drivers use a - file drivers/cdrom/{driver_name}.h where you can define your - interface parameters and switch some internal goodies. - - All these CD-ROM drivers are also usable as a module ( = code which - can be inserted in and removed from the running kernel whenever you - want). If you want to compile them as module, say M instead of Y and - read . - - If you want to use any of these CD-ROM drivers, you also have to - answer Y or M to "ISO 9660 CD-ROM file system support" below (this - answer will get "defaulted" for you if you enable any of the Linux - CD-ROM drivers). - source "drivers/cdrom/Kconfig" - -endmenu # # input before char - char/joystick depends on it. As does USB. diff -Nru a/arch/i386/Kconfig b/arch/i386/Kconfig --- a/arch/i386/Kconfig Tue Jul 1 18:44:32 2003 +++ b/arch/i386/Kconfig Tue Jul 1 18:44:32 2003 @@ -1206,69 +1206,9 @@ source "drivers/ide/Kconfig" - -menu "SCSI device support" - -config SCSI - tristate "SCSI device support" - ---help--- - If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or - any other SCSI device under Linux, say Y and make sure that you know - the name of your SCSI host adapter (the card inside your computer - that "speaks" the SCSI protocol, also called SCSI controller), - because you will be asked for it. - - You also need to say Y here if you want support for the parallel - port version of the 100 MB IOMEGA ZIP drive. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called scsi_mod. If you want to compile it as - a module, say M here and read and - . However, do not compile this as a - module if your root file system (the one containing the directory /) - is located on a SCSI device. - source "drivers/scsi/Kconfig" -endmenu - - -menu "Old CD-ROM drivers (not SCSI, not IDE)" - depends on ISA - -config CD_NO_IDESCSI - bool "Support non-SCSI/IDE/ATAPI CDROM drives" - ---help--- - If you have a CD-ROM drive that is neither SCSI nor IDE/ATAPI, say Y - here, otherwise N. Read the CD-ROM-HOWTO, available from - . - - Note that the answer to this question doesn't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about these CD-ROM drives. If you are unsure what you - have, say Y and find out whether you have one of the following - drives. - - For each of these drivers, a file Documentation/cdrom/{driver_name} - exists. Especially in cases where you do not know exactly which kind - of drive you have you should read there. Most of these drivers use a - file drivers/cdrom/{driver_name}.h where you can define your - interface parameters and switch some internal goodies. - - All these CD-ROM drivers are also usable as a module ( = code which - can be inserted in and removed from the running kernel whenever you - want). If you want to compile them as module, say M instead of Y and - read . - - If you want to use any of these CD-ROM drivers, you also have to - answer Y or M to "ISO 9660 CD-ROM file system support" below (this - answer will get "defaulted" for you if you enable any of the Linux - CD-ROM drivers). - source "drivers/cdrom/Kconfig" - -endmenu source "drivers/md/Kconfig" diff -Nru a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile --- a/arch/i386/kernel/Makefile Tue Jul 1 18:44:32 2003 +++ b/arch/i386/kernel/Makefile Tue Jul 1 18:44:32 2003 @@ -47,7 +47,7 @@ cmd_syscall = $(CC) -nostdlib $(SYSCFLAGS_$(@F)) \ -Wl,-T,$(filter-out FORCE,$^) -o $@ -vsyscall-flags = -shared -s -Wl,-soname=linux-vsyscall.so.1 +vsyscall-flags = -shared -s -Wl,-soname=linux-gate.so.1 SYSCFLAGS_vsyscall-sysenter.so = $(vsyscall-flags) SYSCFLAGS_vsyscall-int80.so = $(vsyscall-flags) diff -Nru a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c --- a/arch/i386/kernel/apic.c Tue Jul 1 18:44:39 2003 +++ b/arch/i386/kernel/apic.c Tue Jul 1 18:44:39 2003 @@ -616,7 +616,7 @@ goto no_apic; case X86_VENDOR_INTEL: if (boot_cpu_data.x86 == 6 || - (boot_cpu_data.x86 == 15 && cpu_has_apic) || + boot_cpu_data.x86 == 15 || (boot_cpu_data.x86 == 5 && cpu_has_apic)) break; goto no_apic; diff -Nru a/arch/i386/kernel/cpu/cpufreq/Kconfig b/arch/i386/kernel/cpu/cpufreq/Kconfig --- a/arch/i386/kernel/cpu/cpufreq/Kconfig Tue Jul 1 18:44:33 2003 +++ b/arch/i386/kernel/cpu/cpufreq/Kconfig Tue Jul 1 18:44:33 2003 @@ -123,6 +123,11 @@ If in doubt, say N. +config X86_SPEEDSTEP_LIB + tristate + depends on X86_SPEEDSTEP_ICH + default X86_SPEEDSTEP_ICH + config X86_P4_CLOCKMOD tristate "Intel Pentium 4 clock modulation" depends on CPU_FREQ_TABLE diff -Nru a/arch/i386/kernel/cpu/cpufreq/Makefile b/arch/i386/kernel/cpu/cpufreq/Makefile --- a/arch/i386/kernel/cpu/cpufreq/Makefile Tue Jul 1 18:44:34 2003 +++ b/arch/i386/kernel/cpu/cpufreq/Makefile Tue Jul 1 18:44:34 2003 @@ -8,6 +8,7 @@ obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi.o obj-$(CONFIG_X86_SPEEDSTEP_ICH) += speedstep-ich.o obj-$(CONFIG_X86_SPEEDSTEP_CENTRINO) += speedstep-centrino.o +obj-$(CONFIG_X86_SPEEDSTEP_LIB) += speedstep-lib.o ifdef CONFIG_X86_ACPI_CPUFREQ ifdef CONFIG_ACPI_DEBUG diff -Nru a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c --- a/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c Tue Jul 1 18:44:34 2003 +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-centrino.c Tue Jul 1 18:44:34 2003 @@ -29,7 +29,7 @@ #define PFX "speedstep-centrino: " #define MAINTAINER "Jeremy Fitzhardinge " -#define CENTRINO_DEBUG +/*#define CENTRINO_DEBUG*/ #ifdef CENTRINO_DEBUG #define dprintk(msg...) printk(msg) diff -Nru a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c --- a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c Tue Jul 1 18:44:31 2003 +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c Tue Jul 1 18:44:31 2003 @@ -1,6 +1,4 @@ /* - * $Id: speedstep.c,v 1.70 2003/02/22 10:23:46 db Exp $ - * * (C) 2001 Dave Jones, Arjan van de ven. * (C) 2002 - 2003 Dominik Brodowski * @@ -27,46 +25,32 @@ #include #include -#include +#include "speedstep-lib.h" + /* speedstep_chipset: * It is necessary to know which chipset is used. As accesses to * this device occur at various places in this module, we need a * static struct pci_dev * pointing to that device. */ -static unsigned int speedstep_chipset; -static struct pci_dev *speedstep_chipset_dev; +static struct pci_dev *speedstep_chipset_dev; -#define SPEEDSTEP_CHIPSET_ICH2M 0x00000002 -#define SPEEDSTEP_CHIPSET_ICH3M 0x00000003 -#define SPEEDSTEP_CHIPSET_ICH4M 0x00000004 /* speedstep_processor */ -static unsigned int speedstep_processor = 0; -static int speedstep_coppermine = 0; - -#define SPEEDSTEP_PROCESSOR_PIII_C 0x00000001 /* Coppermine core */ -#define SPEEDSTEP_PROCESSOR_PIII_T 0x00000002 /* Tualatin core */ -#define SPEEDSTEP_PROCESSOR_P4M 0x00000003 /* P4-M with 100 MHz FSB */ +static unsigned int speedstep_processor = 0; -/* speedstep_[low,high]_freq +/* * There are only two frequency states for each processor. Values * are in kHz for the time being. */ -#define SPEEDSTEP_HIGH 0x00000000 -#define SPEEDSTEP_LOW 0x00000001 - static struct cpufreq_frequency_table speedstep_freqs[] = { {SPEEDSTEP_HIGH, 0}, {SPEEDSTEP_LOW, 0}, {0, CPUFREQ_TABLE_END}, }; -#define speedstep_low_freq speedstep_freqs[SPEEDSTEP_LOW].frequency -#define speedstep_high_freq speedstep_freqs[SPEEDSTEP_HIGH].frequency - /* DEBUG * Define it if you want verbose debug output, e.g. for bug reporting @@ -80,149 +64,82 @@ #endif - -/********************************************************************* - * LOW LEVEL CHIPSET INTERFACE * - *********************************************************************/ - -/** - * speedstep_get_state - read the current SpeedStep state - * @state: Speedstep state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH) - * - * Tries to read the SpeedStep state. Returns -EIO when there has been - * trouble to read the status or write to the control register, -EINVAL - * on an unsupported chipset, and zero on success. - */ -static int speedstep_get_state (unsigned int *state) -{ - unsigned long flags; - u32 pmbase; - u8 value; - - if (!speedstep_chipset_dev || !state) - return -EINVAL; - - switch (speedstep_chipset) { - case SPEEDSTEP_CHIPSET_ICH2M: - case SPEEDSTEP_CHIPSET_ICH3M: - case SPEEDSTEP_CHIPSET_ICH4M: - /* get PMBASE */ - pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase); - if (!(pmbase & 0x01)) - return -EIO; - - pmbase &= 0xFFFFFFFE; - if (!pmbase) - return -EIO; - - /* read state */ - local_irq_save(flags); - value = inb(pmbase + 0x50); - local_irq_restore(flags); - - dprintk(KERN_DEBUG "cpufreq: read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value); - - *state = value & 0x01; - return 0; - - } - - printk (KERN_ERR "cpufreq: setting CPU frequency on this chipset unsupported.\n"); - return -EINVAL; -} - - /** * speedstep_set_state - set the SpeedStep state * @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH) * * Tries to change the SpeedStep state. */ -static void speedstep_set_state (unsigned int state, int notify) +static void speedstep_set_state (unsigned int state, unsigned int notify) { - u32 pmbase; - u8 pm2_blk; - u8 value; - unsigned long flags; - unsigned int oldstate; - struct cpufreq_freqs freqs; + u32 pmbase; + u8 pm2_blk; + u8 value; + unsigned long flags; + struct cpufreq_freqs freqs; if (!speedstep_chipset_dev || (state > 0x1)) return; - if (speedstep_get_state(&oldstate)) - return; - - if (oldstate == state) - return; - - freqs.old = (oldstate == SPEEDSTEP_HIGH) ? speedstep_high_freq : speedstep_low_freq; - freqs.new = (state == SPEEDSTEP_HIGH) ? speedstep_high_freq : speedstep_low_freq; + freqs.old = speedstep_get_processor_frequency(speedstep_processor); + freqs.new = speedstep_freqs[SPEEDSTEP_LOW].frequency; freqs.cpu = 0; /* speedstep.c is UP only driver */ if (notify) cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - switch (speedstep_chipset) { - case SPEEDSTEP_CHIPSET_ICH2M: - case SPEEDSTEP_CHIPSET_ICH3M: - case SPEEDSTEP_CHIPSET_ICH4M: - /* get PMBASE */ - pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase); - if (!(pmbase & 0x01)) - { - printk(KERN_ERR "cpufreq: could not find speedstep register\n"); - return; - } + /* get PMBASE */ + pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase); + if (!(pmbase & 0x01)) + { + printk(KERN_ERR "cpufreq: could not find speedstep register\n"); + return; + } - pmbase &= 0xFFFFFFFE; - if (!pmbase) { - printk(KERN_ERR "cpufreq: could not find speedstep register\n"); - return; - } + pmbase &= 0xFFFFFFFE; + if (!pmbase) { + printk(KERN_ERR "cpufreq: could not find speedstep register\n"); + return; + } - /* Disable IRQs */ - local_irq_save(flags); + /* Disable IRQs */ + local_irq_save(flags); - /* read state */ - value = inb(pmbase + 0x50); + /* read state */ + value = inb(pmbase + 0x50); - dprintk(KERN_DEBUG "cpufreq: read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value); + dprintk(KERN_DEBUG "cpufreq: read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value); - /* write new state */ - value &= 0xFE; - value |= state; + /* write new state */ + value &= 0xFE; + value |= state; - dprintk(KERN_DEBUG "cpufreq: writing 0x%x to pmbase 0x%x + 0x50\n", value, pmbase); + dprintk(KERN_DEBUG "cpufreq: writing 0x%x to pmbase 0x%x + 0x50\n", value, pmbase); - /* Disable bus master arbitration */ - pm2_blk = inb(pmbase + 0x20); - pm2_blk |= 0x01; - outb(pm2_blk, (pmbase + 0x20)); + /* Disable bus master arbitration */ + pm2_blk = inb(pmbase + 0x20); + pm2_blk |= 0x01; + outb(pm2_blk, (pmbase + 0x20)); - /* Actual transition */ - outb(value, (pmbase + 0x50)); + /* Actual transition */ + outb(value, (pmbase + 0x50)); - /* Restore bus master arbitration */ - pm2_blk &= 0xfe; - outb(pm2_blk, (pmbase + 0x20)); + /* Restore bus master arbitration */ + pm2_blk &= 0xfe; + outb(pm2_blk, (pmbase + 0x20)); - /* check if transition was successful */ - value = inb(pmbase + 0x50); + /* check if transition was successful */ + value = inb(pmbase + 0x50); - /* Enable IRQs */ - local_irq_restore(flags); + /* Enable IRQs */ + local_irq_restore(flags); - dprintk(KERN_DEBUG "cpufreq: read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value); + dprintk(KERN_DEBUG "cpufreq: read at pmbase 0x%x + 0x50 returned 0x%x\n", pmbase, value); - if (state == (value & 0x1)) { - dprintk (KERN_INFO "cpufreq: change to %u MHz succeeded\n", (freqs.new / 1000)); - } else { - printk (KERN_ERR "cpufreq: change failed - I/O error\n"); - } - break; - default: - printk (KERN_ERR "cpufreq: setting CPU frequency on this chipset unsupported.\n"); + if (state == (value & 0x1)) { + dprintk (KERN_INFO "cpufreq: change to %u MHz succeeded\n", (freqs.new / 1000)); + } else { + printk (KERN_ERR "cpufreq: change failed - I/O error\n"); } if (notify) @@ -240,31 +157,21 @@ */ static int speedstep_activate (void) { + u16 value = 0; + if (!speedstep_chipset_dev) return -EINVAL; - switch (speedstep_chipset) { - case SPEEDSTEP_CHIPSET_ICH2M: - case SPEEDSTEP_CHIPSET_ICH3M: - case SPEEDSTEP_CHIPSET_ICH4M: - { - u16 value = 0; - - pci_read_config_word(speedstep_chipset_dev, - 0x00A0, &value); - if (!(value & 0x08)) { - value |= 0x08; - dprintk(KERN_DEBUG "cpufreq: activating SpeedStep (TM) registers\n"); - pci_write_config_word(speedstep_chipset_dev, - 0x00A0, value); - } - - return 0; - } + pci_read_config_word(speedstep_chipset_dev, + 0x00A0, &value); + if (!(value & 0x08)) { + value |= 0x08; + dprintk(KERN_DEBUG "cpufreq: activating SpeedStep (TM) registers\n"); + pci_write_config_word(speedstep_chipset_dev, + 0x00A0, value); } - - printk (KERN_ERR "cpufreq: SpeedStep (TM) on this chipset unsupported.\n"); - return -EINVAL; + + return 0; } @@ -284,7 +191,7 @@ PCI_ANY_ID, NULL); if (speedstep_chipset_dev) - return SPEEDSTEP_CHIPSET_ICH4M; + return 4; /* 4-M */ speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, @@ -292,7 +199,7 @@ PCI_ANY_ID, NULL); if (speedstep_chipset_dev) - return SPEEDSTEP_CHIPSET_ICH3M; + return 3; /* 3-M */ speedstep_chipset_dev = pci_find_subsys(PCI_VENDOR_ID_INTEL, @@ -305,7 +212,7 @@ * 8100 which use a pretty old revision of the 82815 * host brige. Abort on these systems. */ - static struct pci_dev *hostbridge; + static struct pci_dev *hostbridge; u8 rev = 0; hostbridge = pci_find_subsys(PCI_VENDOR_ID_INTEL, @@ -315,7 +222,7 @@ NULL); if (!hostbridge) - return SPEEDSTEP_CHIPSET_ICH2M; + return 2; /* 2-M */ pci_read_config_byte(hostbridge, PCI_REVISION_ID, &rev); if (rev < 5) { @@ -324,266 +231,9 @@ return 0; } - return SPEEDSTEP_CHIPSET_ICH2M; - } - - return 0; -} - - - -/********************************************************************* - * LOW LEVEL PROCESSOR INTERFACE * - *********************************************************************/ - - -/** - * pentium3_get_frequency - get the core frequencies for PIIIs - * - * Returns the core frequency of a Pentium III processor (in kHz) - */ -static unsigned int pentium3_get_frequency (void) -{ - /* See table 14 of p3_ds.pdf and table 22 of 29834003.pdf */ - struct { - unsigned int ratio; /* Frequency Multiplier (x10) */ - u8 bitmap; /* power on configuration bits - [27, 25:22] (in MSR 0x2a) */ - } msr_decode_mult [] = { - { 30, 0x01 }, - { 35, 0x05 }, - { 40, 0x02 }, - { 45, 0x06 }, - { 50, 0x00 }, - { 55, 0x04 }, - { 60, 0x0b }, - { 65, 0x0f }, - { 70, 0x09 }, - { 75, 0x0d }, - { 80, 0x0a }, - { 85, 0x26 }, - { 90, 0x20 }, - { 100, 0x2b }, - { 0, 0xff } /* error or unknown value */ - }; - /* PIII(-M) FSB settings: see table b1-b of 24547206.pdf */ - struct { - unsigned int value; /* Front Side Bus speed in MHz */ - u8 bitmap; /* power on configuration bits [18: 19] - (in MSR 0x2a) */ - } msr_decode_fsb [] = { - { 66, 0x0 }, - { 100, 0x2 }, - { 133, 0x1 }, - { 0, 0xff} - }; - u32 msr_lo, msr_tmp; - int i = 0, j = 0; - struct cpuinfo_x86 *c = cpu_data; - - /* read MSR 0x2a - we only need the low 32 bits */ - rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_tmp); - dprintk(KERN_DEBUG "cpufreq: P3 - MSR_IA32_EBL_CR_POWERON: 0x%x 0x%x\n", msr_lo, msr_tmp); - msr_tmp = msr_lo; - - /* decode the FSB */ - msr_tmp &= 0x00c0000; - msr_tmp >>= 18; - while (msr_tmp != msr_decode_fsb[i].bitmap) { - if (msr_decode_fsb[i].bitmap == 0xff) - return -EINVAL; - i++; - } - - /* decode the multiplier */ - if ((c->x86_model == 0x08) && (c->x86_mask == 0x01)) - /* different on early Coppermine PIII */ - msr_lo &= 0x03c00000; - else - msr_lo &= 0x0bc00000; - msr_lo >>= 22; - while (msr_lo != msr_decode_mult[j].bitmap) { - if (msr_decode_mult[j].bitmap == 0xff) - return -EINVAL; - j++; - } - - return (msr_decode_mult[j].ratio * msr_decode_fsb[i].value * 100); -} - - -/** - * pentium4_get_frequency - get the core frequency for P4-Ms - * - * Should return the core frequency (in kHz) for P4-Ms. - */ -static unsigned int pentium4_get_frequency(void) -{ - u32 msr_lo, msr_hi; - - rdmsr(0x2c, msr_lo, msr_hi); - - dprintk(KERN_DEBUG "cpufreq: P4 - MSR_EBC_FREQUENCY_ID: 0x%x 0x%x\n", msr_lo, msr_hi); - - /* First 12 bits seem to change a lot (0x511, 0x410 and 0x30f seen - * yet). Next 12 bits always seem to be 0x300. If this is not true - * on this CPU, complain. Last 8 bits are frequency (in 100MHz). - */ - if (msr_hi || ((msr_lo & 0x00FFF000) != 0x300000)) { - printk(KERN_DEBUG "cpufreq: P4 - MSR_EBC_FREQUENCY_ID: 0x%x 0x%x\n", msr_lo, msr_hi); - printk(KERN_INFO "cpufreq: problem in initialization. Please contact Dominik Brodowski\n"); - printk(KERN_INFO "cpufreq: and attach this dmesg. Thanks in advance\n"); - return 0; - } - - msr_lo >>= 24; - return (msr_lo * 100000); -} - - -/** - * speedstep_detect_processor - detect Intel SpeedStep-capable processors. - * - * Returns the SPEEDSTEP_PROCESSOR_-number for the detected processor, - * or zero on failure. - */ -static unsigned int speedstep_detect_processor (void) -{ - struct cpuinfo_x86 *c = cpu_data; - u32 ebx; - - if ((c->x86_vendor != X86_VENDOR_INTEL) || - ((c->x86 != 6) && (c->x86 != 0xF))) - return 0; - - if (c->x86 == 0xF) { - /* Intel Pentium 4 Mobile P4-M */ - if (c->x86_model != 2) - return 0; - - if ((c->x86_mask != 4) && (c->x86_mask != 7)) - return 0; - - ebx = cpuid_ebx(0x00000001); - ebx &= 0x000000FF; - if ((ebx != 0x0e) && (ebx != 0x0f)) - return 0; - - return SPEEDSTEP_PROCESSOR_P4M; - } - - switch (c->x86_model) { - case 0x0B: /* Intel PIII [Tualatin] */ - /* cpuid_ebx(1) is 0x04 for desktop PIII, - 0x06 for mobile PIII-M */ - ebx = cpuid_ebx(0x00000001); - - ebx &= 0x000000FF; - if (ebx != 0x06) - return 0; - - /* So far all PIII-M processors support SpeedStep. See - * Intel's 24540633.pdf of August 2002 - */ - - return SPEEDSTEP_PROCESSOR_PIII_T; - - case 0x08: /* Intel PIII [Coppermine] */ - { - u32 msr_lo, msr_hi; - - /* all mobile PIII Coppermines have FSB 100 MHz - * ==> sort out a few desktop PIIIs. */ - rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_hi); - dprintk(KERN_DEBUG "cpufreq: Coppermine: MSR_IA32_EBL_Cr_POWERON is 0x%x, 0x%x\n", msr_lo, msr_hi); - msr_lo &= 0x00c0000; - if (msr_lo != 0x0080000) - return 0; - - if (speedstep_coppermine) - return SPEEDSTEP_PROCESSOR_PIII_C; - - /* - * If the processor is a mobile version, - * platform ID has bit 50 set - * it has SpeedStep technology if either - * bit 56 or 57 is set - */ - rdmsr(MSR_IA32_PLATFORM_ID, msr_lo, msr_hi); - dprintk(KERN_DEBUG "cpufreq: Coppermine: MSR_IA32_PLATFORM ID is 0x%x, 0x%x\n", msr_lo, msr_hi); - if ((msr_hi & (1<<18)) && (msr_hi & (3<<24))) - return SPEEDSTEP_PROCESSOR_PIII_C; - - printk(KERN_INFO "cpufreq: in case this is a SpeedStep-capable Intel Pentium III Coppermine\n"); - printk(KERN_INFO "cpufreq: processor, please pass the boot option or module parameter\n"); - printk(KERN_INFO "cpufreq: `speedstep_coppermine=1` to the kernel. Thanks!\n"); - return 0; - } - - default: - return 0; - } -} - - - -/********************************************************************* - * HIGH LEVEL FUNCTIONS * - *********************************************************************/ - -/** - * speedstep_detect_speeds - detects low and high CPU frequencies. - * - * Detects the low and high CPU frequencies in kHz. Returns 0 on - * success or -EINVAL / -EIO on problems. - */ -static int speedstep_detect_speeds (void) -{ - unsigned long flags; - unsigned int state; - int i, result; - - /* Disable irqs for entire detection process */ - local_irq_save(flags); - - for (i=0; i<2; i++) { - /* read the current state */ - result = speedstep_get_state(&state); - if (result) { - local_irq_restore(flags); - return result; - } - - /* save the correct value, and switch to other */ - if (state == SPEEDSTEP_LOW) { - switch (speedstep_processor) { - case SPEEDSTEP_PROCESSOR_PIII_C: - case SPEEDSTEP_PROCESSOR_PIII_T: - speedstep_low_freq = pentium3_get_frequency(); - break; - case SPEEDSTEP_PROCESSOR_P4M: - speedstep_low_freq = pentium4_get_frequency(); - } - speedstep_set_state(SPEEDSTEP_HIGH, 0); - } else { - switch (speedstep_processor) { - case SPEEDSTEP_PROCESSOR_PIII_C: - case SPEEDSTEP_PROCESSOR_PIII_T: - speedstep_high_freq = pentium3_get_frequency(); - break; - case SPEEDSTEP_PROCESSOR_P4M: - speedstep_high_freq = pentium4_get_frequency(); - } - speedstep_set_state(SPEEDSTEP_LOW, 0); - } + return 2; /* 2-M */ } - local_irq_restore(flags); - - if (!speedstep_low_freq || !speedstep_high_freq || - (speedstep_low_freq == speedstep_high_freq)) - return -EIO; - return 0; } @@ -598,7 +248,7 @@ unsigned int target_freq, unsigned int relation) { - unsigned int newstate = 0; + unsigned int newstate = 0; if (cpufreq_frequency_table_target(policy, &speedstep_freqs[0], target_freq, relation, &newstate)) return -EINVAL; @@ -632,22 +282,24 @@ return -ENODEV; /* detect low and high frequency */ - result = speedstep_detect_speeds(); + result = speedstep_get_freqs(speedstep_processor, + &speedstep_freqs[SPEEDSTEP_LOW].frequency, + &speedstep_freqs[SPEEDSTEP_HIGH].frequency, + &speedstep_set_state); if (result) return result; /* get current speed setting */ - result = speedstep_get_state(&speed); - if (result) - return result; + speed = speedstep_get_processor_frequency(speedstep_processor); + if (!speed) + return -EIO; - speed = (speed == SPEEDSTEP_LOW) ? speedstep_low_freq : speedstep_high_freq; dprintk(KERN_INFO "cpufreq: currently at %s speed setting - %i MHz\n", (speed == speedstep_low_freq) ? "low" : "high", (speed / 1000)); /* cpuinfo and default policy values */ - policy->policy = (speed == speedstep_low_freq) ? + policy->policy = (speed == speedstep_freqs[SPEEDSTEP_LOW].frequency) ? CPUFREQ_POLICY_POWERSAVE : CPUFREQ_POLICY_PERFORMANCE; policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; policy->cur = speed; @@ -656,26 +308,6 @@ } -#ifndef MODULE -/** - * speedstep_setup speedstep command line parameter parsing - * - * speedstep command line parameter. Use: - * speedstep_coppermine=1 - * if the CPU in your notebook is a SpeedStep-capable Intel - * Pentium III Coppermine. These processors cannot be detected - * automatically, as Intel continues to consider the detection - * algorithm as proprietary material. - */ -static int __init speedstep_setup(char *str) -{ - speedstep_coppermine = simple_strtoul(str, &str, 0); - return 1; -} -__setup("speedstep_coppermine=", speedstep_setup); -#endif - - static struct cpufreq_driver speedstep_driver = { .name = "speedstep", .verify = speedstep_verify, @@ -694,20 +326,17 @@ */ static int __init speedstep_init(void) { - /* detect chipset */ - speedstep_chipset = speedstep_detect_chipset(); + /* detect processor */ + speedstep_processor = speedstep_detect_processor(); + if (!speedstep_processor) + return -ENODEV; /* detect chipset */ - if (speedstep_chipset) - speedstep_processor = speedstep_detect_processor(); - - if ((!speedstep_chipset) || (!speedstep_processor)) { - printk(KERN_INFO "cpufreq: Intel(R) SpeedStep(TM) for this %s not (yet) available.\n", speedstep_chipset ? "processor" : "chipset"); + if (!speedstep_detect_chipset()) { + printk(KERN_INFO "cpufreq: Intel(R) SpeedStep(TM) for this chipset not (yet) available.\n"); return -ENODEV; } - dprintk(KERN_INFO "cpufreq: Intel(R) SpeedStep(TM) support $Revision: 1.70 $\n"); - /* activate speedstep support */ if (speedstep_activate()) return -EINVAL; @@ -727,10 +356,8 @@ } -MODULE_PARM (speedstep_coppermine, "i"); - MODULE_AUTHOR ("Dave Jones , Dominik Brodowski "); -MODULE_DESCRIPTION ("Speedstep driver for Intel mobile processors."); +MODULE_DESCRIPTION ("Speedstep driver for Intel mobile processors on chipsets with ICH-M southbridges."); MODULE_LICENSE ("GPL"); module_init(speedstep_init); diff -Nru a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,275 @@ +/* + * (C) 2002 - 2003 Dominik Brodowski + * + * Licensed under the terms of the GNU GPL License version 2. + * + * Library for common functions for Intel SpeedStep v.1 and v.2 support + * + * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous* + */ + +#include +#include +#include +#include +#include +#include + +#include +#include "speedstep-lib.h" + + +/* DEBUG + * Define it if you want verbose debug output, e.g. for bug reporting + */ +//#define SPEEDSTEP_DEBUG + +#ifdef SPEEDSTEP_DEBUG +#define dprintk(msg...) printk(msg) +#else +#define dprintk(msg...) do { } while(0) +#endif + +/********************************************************************* + * GET PROCESSOR CORE SPEED IN KHZ * + *********************************************************************/ + +static unsigned int pentium3_get_frequency (unsigned int processor) +{ + /* See table 14 of p3_ds.pdf and table 22 of 29834003.pdf */ + struct { + unsigned int ratio; /* Frequency Multiplier (x10) */ + u8 bitmap; /* power on configuration bits + [27, 25:22] (in MSR 0x2a) */ + } msr_decode_mult [] = { + { 30, 0x01 }, + { 35, 0x05 }, + { 40, 0x02 }, + { 45, 0x06 }, + { 50, 0x00 }, + { 55, 0x04 }, + { 60, 0x0b }, + { 65, 0x0f }, + { 70, 0x09 }, + { 75, 0x0d }, + { 80, 0x0a }, + { 85, 0x26 }, + { 90, 0x20 }, + { 100, 0x2b }, + { 0, 0xff } /* error or unknown value */ + }; + + /* PIII(-M) FSB settings: see table b1-b of 24547206.pdf */ + struct { + unsigned int value; /* Front Side Bus speed in MHz */ + u8 bitmap; /* power on configuration bits [18: 19] + (in MSR 0x2a) */ + } msr_decode_fsb [] = { + { 66, 0x0 }, + { 100, 0x2 }, + { 133, 0x1 }, + { 0, 0xff} + }; + + u32 msr_lo, msr_tmp; + int i = 0, j = 0; + + /* read MSR 0x2a - we only need the low 32 bits */ + rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_tmp); + dprintk(KERN_DEBUG "speedstep-lib: P3 - MSR_IA32_EBL_CR_POWERON: 0x%x 0x%x\n", msr_lo, msr_tmp); + msr_tmp = msr_lo; + + /* decode the FSB */ + msr_tmp &= 0x00c0000; + msr_tmp >>= 18; + while (msr_tmp != msr_decode_fsb[i].bitmap) { + if (msr_decode_fsb[i].bitmap == 0xff) + return 0; + i++; + } + + /* decode the multiplier */ + if (processor == SPEEDSTEP_PROCESSOR_PIII_C_EARLY) + msr_lo &= 0x03c00000; + else + msr_lo &= 0x0bc00000; + msr_lo >>= 22; + while (msr_lo != msr_decode_mult[j].bitmap) { + if (msr_decode_mult[j].bitmap == 0xff) + return 0; + j++; + } + + return (msr_decode_mult[j].ratio * msr_decode_fsb[i].value * 100); +} + + +static unsigned int pentium4_get_frequency(void) +{ + u32 msr_lo, msr_hi; + + rdmsr(0x2c, msr_lo, msr_hi); + + dprintk(KERN_DEBUG "speedstep-lib: P4 - MSR_EBC_FREQUENCY_ID: 0x%x 0x%x\n", msr_lo, msr_hi); + + msr_lo >>= 24; + return (msr_lo * 100000); +} + + +unsigned int speedstep_get_processor_frequency(unsigned int processor) +{ + switch (processor) { + case SPEEDSTEP_PROCESSOR_P4M: + return pentium4_get_frequency(); + case SPEEDSTEP_PROCESSOR_PIII_T: + case SPEEDSTEP_PROCESSOR_PIII_C: + case SPEEDSTEP_PROCESSOR_PIII_C_EARLY: + return pentium3_get_frequency(processor); + default: + return 0; + }; + return 0; +} +EXPORT_SYMBOL_GPL(speedstep_get_processor_frequency); + + +/********************************************************************* + * DETECT SPEEDSTEP-CAPABLE PROCESSOR * + *********************************************************************/ + +unsigned int speedstep_detect_processor (void) +{ + struct cpuinfo_x86 *c = cpu_data; + u32 ebx, msr_lo, msr_hi; + + if ((c->x86_vendor != X86_VENDOR_INTEL) || + ((c->x86 != 6) && (c->x86 != 0xF))) + return 0; + + if (c->x86 == 0xF) { + /* Intel Mobile Pentium 4-M + * or Intel Mobile Pentium 4 with 533 MHz FSB */ + if (c->x86_model != 2) + return 0; + + if ((c->x86_mask != 4) && /* B-stepping [M-P4-M] */ + (c->x86_mask != 7) && /* C-stepping [M-P4-M] */ + (c->x86_mask != 9)) /* D-stepping [M-P4-M or M-P4/533] */ + return 0; + + ebx = cpuid_ebx(0x00000001); + ebx &= 0x000000FF; + if ((ebx != 0x0e) && (ebx != 0x0f)) + return 0; + + return SPEEDSTEP_PROCESSOR_P4M; + } + + switch (c->x86_model) { + case 0x0B: /* Intel PIII [Tualatin] */ + /* cpuid_ebx(1) is 0x04 for desktop PIII, + 0x06 for mobile PIII-M */ + ebx = cpuid_ebx(0x00000001); + + ebx &= 0x000000FF; + if (ebx != 0x06) + return 0; + + /* So far all PIII-M processors support SpeedStep. See + * Intel's 24540640.pdf of June 2003 + */ + + return SPEEDSTEP_PROCESSOR_PIII_T; + + case 0x08: /* Intel PIII [Coppermine] */ + + /* all mobile PIII Coppermines have FSB 100 MHz + * ==> sort out a few desktop PIIIs. */ + rdmsr(MSR_IA32_EBL_CR_POWERON, msr_lo, msr_hi); + dprintk(KERN_DEBUG "cpufreq: Coppermine: MSR_IA32_EBL_CR_POWERON is 0x%x, 0x%x\n", msr_lo, msr_hi); + msr_lo &= 0x00c0000; + if (msr_lo != 0x0080000) + return 0; + + /* + * If the processor is a mobile version, + * platform ID has bit 50 set + * it has SpeedStep technology if either + * bit 56 or 57 is set + */ + rdmsr(MSR_IA32_PLATFORM_ID, msr_lo, msr_hi); + dprintk(KERN_DEBUG "cpufreq: Coppermine: MSR_IA32_PLATFORM ID is 0x%x, 0x%x\n", msr_lo, msr_hi); + if ((msr_hi & (1<<18)) && (msr_hi & (3<<24))) { + if (c->x86_mask == 0x01) + return SPEEDSTEP_PROCESSOR_PIII_C_EARLY; + else + return SPEEDSTEP_PROCESSOR_PIII_C; + } + + default: + return 0; + } +} +EXPORT_SYMBOL_GPL(speedstep_detect_processor); + + +/********************************************************************* + * DETECT SPEEDSTEP SPEEDS * + *********************************************************************/ + +unsigned int speedstep_get_freqs(unsigned int processor, + unsigned int *low_speed, + unsigned int *high_speed, + void (*set_state) (unsigned int state, + unsigned int notify) + ) +{ + unsigned int prev_speed; + unsigned int ret = 0; + unsigned long flags; + + if ((!processor) || (!low_speed) || (!high_speed) || (!set_state)) + return EINVAL; + + /* get current speed */ + prev_speed = speedstep_get_processor_frequency(processor); + if (!prev_speed) + return EIO; + + local_irq_save(flags); + + /* switch to low state */ + set_state(SPEEDSTEP_LOW, 0); + *low_speed = speedstep_get_processor_frequency(processor); + if (!*low_speed) { + ret = EIO; + goto out; + } + + /* switch to high state */ + set_state(SPEEDSTEP_HIGH, 0); + *high_speed = speedstep_get_processor_frequency(processor); + if (!*high_speed) { + ret = EIO; + goto out; + } + + if (*low_speed == *high_speed) { + ret = ENODEV; + goto out; + } + + /* switch to previous state, if necessary */ + if (*high_speed != prev_speed) + set_state(SPEEDSTEP_LOW, 0); + + out: + local_irq_restore(flags); + return (ret); +} +EXPORT_SYMBOL_GPL(speedstep_get_freqs); + +MODULE_AUTHOR ("Dominik Brodowski "); +MODULE_DESCRIPTION ("Library for Intel SpeedStep 1 or 2 cpufreq drivers."); +MODULE_LICENSE ("GPL"); diff -Nru a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h Tue Jul 1 18:44:40 2003 @@ -0,0 +1,41 @@ +/* + * (C) 2002 - 2003 Dominik Brodowski + * + * Licensed under the terms of the GNU GPL License version 2. + * + * Library for common functions for Intel SpeedStep v.1 and v.2 support + * + * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous* + */ + + + +/* processors */ + +#define SPEEDSTEP_PROCESSOR_PIII_C_EARLY 0x00000001 /* Coppermine core */ +#define SPEEDSTEP_PROCESSOR_PIII_C 0x00000002 /* Coppermine core */ +#define SPEEDSTEP_PROCESSOR_PIII_T 0x00000003 /* Tualatin core */ +#define SPEEDSTEP_PROCESSOR_P4M 0x00000004 /* P4-M with 100 MHz FSB */ + +/* speedstep states -- only two of them */ + +#define SPEEDSTEP_HIGH 0x00000000 +#define SPEEDSTEP_LOW 0x00000001 + + +/* detect a speedstep-capable processor */ +extern unsigned int speedstep_detect_processor (void); + +/* detect the current speed (in khz) of the processor */ +extern unsigned int speedstep_get_processor_frequency(unsigned int processor); + + +/* detect the low and high speeds of the processor. The callback + * set_state"'s first argument is either SPEEDSTEP_HIGH or + * SPEEDSTEP_LOW; the second argument is zero so that no + * cpufreq_notify_transition calls are initiated. + */ +extern unsigned int speedstep_get_freqs(unsigned int processor, + unsigned int *low_speed, + unsigned int *high_speed, + void (*set_state) (unsigned int state, unsigned int notify)); diff -Nru a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c --- a/arch/i386/kernel/i386_ksyms.c Tue Jul 1 18:44:39 2003 +++ b/arch/i386/kernel/i386_ksyms.c Tue Jul 1 18:44:39 2003 @@ -159,6 +159,7 @@ /* TLB flushing */ EXPORT_SYMBOL(flush_tlb_page); +EXPORT_SYMBOL_GPL(flush_tlb_all); #endif #ifdef CONFIG_X86_IO_APIC diff -Nru a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c --- a/arch/i386/kernel/io_apic.c Tue Jul 1 18:44:34 2003 +++ b/arch/i386/kernel/io_apic.c Tue Jul 1 18:44:34 2003 @@ -1272,9 +1272,10 @@ void __init print_IO_APIC(void) { int apic, i; - struct IO_APIC_reg_00 reg_00; - struct IO_APIC_reg_01 reg_01; - struct IO_APIC_reg_02 reg_02; + union IO_APIC_reg_00 reg_00; + union IO_APIC_reg_01 reg_01; + union IO_APIC_reg_02 reg_02; + union IO_APIC_reg_03 reg_03; unsigned long flags; printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries); @@ -1291,51 +1292,70 @@ for (apic = 0; apic < nr_ioapics; apic++) { spin_lock_irqsave(&ioapic_lock, flags); - *(int *)®_00 = io_apic_read(apic, 0); - *(int *)®_01 = io_apic_read(apic, 1); - if (reg_01.version >= 0x10) - *(int *)®_02 = io_apic_read(apic, 2); + reg_00.raw = io_apic_read(apic, 0); + reg_01.raw = io_apic_read(apic, 1); + if (reg_01.bits.version >= 0x10) + reg_02.raw = io_apic_read(apic, 2); + if (reg_01.bits.version >= 0x20) + reg_03.raw = io_apic_read(apic, 3); spin_unlock_irqrestore(&ioapic_lock, flags); - printk("\n"); printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mpc_apicid); - printk(KERN_DEBUG ".... register #00: %08X\n", *(int *)®_00); - printk(KERN_DEBUG "....... : physical APIC id: %02X\n", reg_00.ID); - printk(KERN_DEBUG "....... : Delivery Type: %X\n", reg_00.delivery_type); - printk(KERN_DEBUG "....... : LTS : %X\n", reg_00.LTS); - if (reg_00.ID >= APIC_BROADCAST_ID) + printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw); + printk(KERN_DEBUG "....... : physical APIC id: %02X\n", reg_00.bits.ID); + printk(KERN_DEBUG "....... : Delivery Type: %X\n", reg_00.bits.delivery_type); + printk(KERN_DEBUG "....... : LTS : %X\n", reg_00.bits.LTS); + if (reg_00.bits.ID >= APIC_BROADCAST_ID) UNEXPECTED_IO_APIC(); - if (reg_00.__reserved_1 || reg_00.__reserved_2) + if (reg_00.bits.__reserved_1 || reg_00.bits.__reserved_2) UNEXPECTED_IO_APIC(); - printk(KERN_DEBUG ".... register #01: %08X\n", *(int *)®_01); - printk(KERN_DEBUG "....... : max redirection entries: %04X\n", reg_01.entries); - if ( (reg_01.entries != 0x0f) && /* older (Neptune) boards */ - (reg_01.entries != 0x17) && /* typical ISA+PCI boards */ - (reg_01.entries != 0x1b) && /* Compaq Proliant boards */ - (reg_01.entries != 0x1f) && /* dual Xeon boards */ - (reg_01.entries != 0x22) && /* bigger Xeon boards */ - (reg_01.entries != 0x2E) && - (reg_01.entries != 0x3F) + printk(KERN_DEBUG ".... register #01: %08X\n", reg_01.raw); + printk(KERN_DEBUG "....... : max redirection entries: %04X\n", reg_01.bits.entries); + if ( (reg_01.bits.entries != 0x0f) && /* older (Neptune) boards */ + (reg_01.bits.entries != 0x17) && /* typical ISA+PCI boards */ + (reg_01.bits.entries != 0x1b) && /* Compaq Proliant boards */ + (reg_01.bits.entries != 0x1f) && /* dual Xeon boards */ + (reg_01.bits.entries != 0x22) && /* bigger Xeon boards */ + (reg_01.bits.entries != 0x2E) && + (reg_01.bits.entries != 0x3F) ) UNEXPECTED_IO_APIC(); - printk(KERN_DEBUG "....... : PRQ implemented: %X\n", reg_01.PRQ); - printk(KERN_DEBUG "....... : IO APIC version: %04X\n", reg_01.version); - if ( (reg_01.version != 0x01) && /* 82489DX IO-APICs */ - (reg_01.version != 0x10) && /* oldest IO-APICs */ - (reg_01.version != 0x11) && /* Pentium/Pro IO-APICs */ - (reg_01.version != 0x13) && /* Xeon IO-APICs */ - (reg_01.version != 0x20) /* Intel P64H (82806 AA) */ + printk(KERN_DEBUG "....... : PRQ implemented: %X\n", reg_01.bits.PRQ); + printk(KERN_DEBUG "....... : IO APIC version: %04X\n", reg_01.bits.version); + if ( (reg_01.bits.version != 0x01) && /* 82489DX IO-APICs */ + (reg_01.bits.version != 0x10) && /* oldest IO-APICs */ + (reg_01.bits.version != 0x11) && /* Pentium/Pro IO-APICs */ + (reg_01.bits.version != 0x13) && /* Xeon IO-APICs */ + (reg_01.bits.version != 0x20) /* Intel P64H (82806 AA) */ ) UNEXPECTED_IO_APIC(); - if (reg_01.__reserved_1 || reg_01.__reserved_2) + if (reg_01.bits.__reserved_1 || reg_01.bits.__reserved_2) UNEXPECTED_IO_APIC(); - if (reg_01.version >= 0x10) { - printk(KERN_DEBUG ".... register #02: %08X\n", *(int *)®_02); - printk(KERN_DEBUG "....... : arbitration: %02X\n", reg_02.arbitration); - if (reg_02.__reserved_1 || reg_02.__reserved_2) + /* + * Some Intel chipsets with IO APIC VERSION of 0x1? don't have reg_02, + * but the value of reg_02 is read as the previous read register + * value, so ignore it if reg_02 == reg_01. + */ + if (reg_01.bits.version >= 0x10 && reg_02.raw != reg_01.raw) { + printk(KERN_DEBUG ".... register #02: %08X\n", reg_02.raw); + printk(KERN_DEBUG "....... : arbitration: %02X\n", reg_02.bits.arbitration); + if (reg_02.bits.__reserved_1 || reg_02.bits.__reserved_2) + UNEXPECTED_IO_APIC(); + } + + /* + * Some Intel chipsets with IO APIC VERSION of 0x2? don't have reg_02 + * or reg_03, but the value of reg_0[23] is read as the previous read + * register value, so ignore it if reg_03 == reg_0[12]. + */ + if (reg_01.bits.version >= 0x20 && reg_03.raw != reg_02.raw && + reg_03.raw != reg_01.raw) { + printk(KERN_DEBUG ".... register #03: %08X\n", reg_03.raw); + printk(KERN_DEBUG "....... : Boot DT : %X\n", reg_03.bits.boot_DT); + if (reg_03.bits.__reserved_1) UNEXPECTED_IO_APIC(); } @@ -1344,7 +1364,7 @@ printk(KERN_DEBUG " NR Log Phy Mask Trig IRR Pol" " Stat Dest Deli Vect: \n"); - for (i = 0; i <= reg_01.entries; i++) { + for (i = 0; i <= reg_01.bits.entries; i++) { struct IO_APIC_route_entry entry; spin_lock_irqsave(&ioapic_lock, flags); @@ -1525,7 +1545,7 @@ static void __init enable_IO_APIC(void) { - struct IO_APIC_reg_01 reg_01; + union IO_APIC_reg_01 reg_01; int i; unsigned long flags; @@ -1542,9 +1562,9 @@ */ for (i = 0; i < nr_ioapics; i++) { spin_lock_irqsave(&ioapic_lock, flags); - *(int *)®_01 = io_apic_read(i, 1); + reg_01.raw = io_apic_read(i, 1); spin_unlock_irqrestore(&ioapic_lock, flags); - nr_ioapic_registers[i] = reg_01.entries+1; + nr_ioapic_registers[i] = reg_01.bits.entries+1; } /* @@ -1576,7 +1596,7 @@ #ifndef CONFIG_X86_NUMAQ static void __init setup_ioapic_ids_from_mpc(void) { - struct IO_APIC_reg_00 reg_00; + union IO_APIC_reg_00 reg_00; unsigned long phys_id_present_map; int apic; int i; @@ -1596,7 +1616,7 @@ /* Read the register 0 value */ spin_lock_irqsave(&ioapic_lock, flags); - *(int *)®_00 = io_apic_read(apic, 0); + reg_00.raw = io_apic_read(apic, 0); spin_unlock_irqrestore(&ioapic_lock, flags); old_id = mp_ioapics[apic].mpc_apicid; @@ -1605,8 +1625,8 @@ printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n", apic, mp_ioapics[apic].mpc_apicid); printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n", - reg_00.ID); - mp_ioapics[apic].mpc_apicid = reg_00.ID; + reg_00.bits.ID); + mp_ioapics[apic].mpc_apicid = reg_00.bits.ID; } /* @@ -1650,18 +1670,18 @@ printk(KERN_INFO "...changing IO-APIC physical APIC ID to %d ...", mp_ioapics[apic].mpc_apicid); - reg_00.ID = mp_ioapics[apic].mpc_apicid; + reg_00.bits.ID = mp_ioapics[apic].mpc_apicid; spin_lock_irqsave(&ioapic_lock, flags); - io_apic_write(apic, 0, *(int *)®_00); + io_apic_write(apic, 0, reg_00.raw); spin_unlock_irqrestore(&ioapic_lock, flags); /* * Sanity check */ spin_lock_irqsave(&ioapic_lock, flags); - *(int *)®_00 = io_apic_read(apic, 0); + reg_00.raw = io_apic_read(apic, 0); spin_unlock_irqrestore(&ioapic_lock, flags); - if (reg_00.ID != mp_ioapics[apic].mpc_apicid) + if (reg_00.bits.ID != mp_ioapics[apic].mpc_apicid) panic("could not set ID!\n"); else printk(" ok.\n"); @@ -2199,7 +2219,7 @@ int __init io_apic_get_unique_id (int ioapic, int apic_id) { - struct IO_APIC_reg_00 reg_00; + union IO_APIC_reg_00 reg_00; static unsigned long apic_id_map = 0; unsigned long flags; int i = 0; @@ -2217,13 +2237,13 @@ apic_id_map = phys_cpu_present_map; spin_lock_irqsave(&ioapic_lock, flags); - *(int *)®_00 = io_apic_read(ioapic, 0); + reg_00.raw = io_apic_read(ioapic, 0); spin_unlock_irqrestore(&ioapic_lock, flags); if (apic_id >= IO_APIC_MAX_ID) { printk(KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying " - "%d\n", ioapic, apic_id, reg_00.ID); - apic_id = reg_00.ID; + "%d\n", ioapic, apic_id, reg_00.bits.ID); + apic_id = reg_00.bits.ID; } /* @@ -2248,16 +2268,16 @@ apic_id_map |= apicid_to_cpu_present(apic_id); - if (reg_00.ID != apic_id) { - reg_00.ID = apic_id; + if (reg_00.bits.ID != apic_id) { + reg_00.bits.ID = apic_id; spin_lock_irqsave(&ioapic_lock, flags); - io_apic_write(ioapic, 0, *(int *)®_00); - *(int *)®_00 = io_apic_read(ioapic, 0); + io_apic_write(ioapic, 0, reg_00.raw); + reg_00.raw = io_apic_read(ioapic, 0); spin_unlock_irqrestore(&ioapic_lock, flags); /* Sanity check */ - if (reg_00.ID != apic_id) + if (reg_00.bits.ID != apic_id) panic("IOAPIC[%d]: Unable change apic_id!\n", ioapic); } @@ -2269,27 +2289,27 @@ int __init io_apic_get_version (int ioapic) { - struct IO_APIC_reg_01 reg_01; + union IO_APIC_reg_01 reg_01; unsigned long flags; spin_lock_irqsave(&ioapic_lock, flags); - *(int *)®_01 = io_apic_read(ioapic, 1); + reg_01.raw = io_apic_read(ioapic, 1); spin_unlock_irqrestore(&ioapic_lock, flags); - return reg_01.version; + return reg_01.bits.version; } int __init io_apic_get_redir_entries (int ioapic) { - struct IO_APIC_reg_01 reg_01; + union IO_APIC_reg_01 reg_01; unsigned long flags; spin_lock_irqsave(&ioapic_lock, flags); - *(int *)®_01 = io_apic_read(ioapic, 1); + reg_01.raw = io_apic_read(ioapic, 1); spin_unlock_irqrestore(&ioapic_lock, flags); - return reg_01.entries; + return reg_01.bits.entries; } diff -Nru a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c --- a/arch/i386/kernel/traps.c Tue Jul 1 18:44:32 2003 +++ b/arch/i386/kernel/traps.c Tue Jul 1 18:44:32 2003 @@ -123,19 +123,20 @@ show_trace(tsk, (unsigned long *)esp); } -void show_stack(struct task_struct *task, unsigned long * esp) +void show_stack(struct task_struct *task, unsigned long *esp) { unsigned long *stack; int i; - // debugging aid: "show_stack(NULL);" prints the - // back trace for this cpu. - - if(esp==NULL) - esp=(unsigned long*)&esp; + if (esp == NULL) { + if (task) + esp = (unsigned long*)task->thread.esp; + else + esp = (unsigned long *)&esp; + } stack = esp; - for(i=0; i < kstack_depth_to_print; i++) { + for(i = 0; i < kstack_depth_to_print; i++) { if (((long) stack & (THREAD_SIZE-1)) == 0) break; if (i && ((i % 8) == 0)) diff -Nru a/arch/i386/mach-voyager/voyager_basic.c b/arch/i386/mach-voyager/voyager_basic.c --- a/arch/i386/mach-voyager/voyager_basic.c Tue Jul 1 18:44:33 2003 +++ b/arch/i386/mach-voyager/voyager_basic.c Tue Jul 1 18:44:33 2003 @@ -284,7 +284,6 @@ { __u8 dumpval __attribute__((unused)) = inb(0xf823); __u8 swnmi __attribute__((unused)) = inb(0xf813); - extern void show_stack(unsigned long *); /* FIXME: assume dump switch pressed */ /* check to see if the dump switch was pressed */ @@ -302,7 +301,7 @@ } } printk(KERN_ERR "VOYAGER: Dump switch pressed, printing CPU%d tracebacks\n", smp_processor_id()); - show_stack(NULL); + show_stack(NULL, NULL); show_state(); } diff -Nru a/arch/i386/pci/Makefile b/arch/i386/pci/Makefile --- a/arch/i386/pci/Makefile Tue Jul 1 18:44:35 2003 +++ b/arch/i386/pci/Makefile Tue Jul 1 18:44:35 2003 @@ -1,27 +1,13 @@ -obj-y := i386.o +obj-y := i386.o obj-$(CONFIG_PCI_BIOS) += pcbios.o obj-$(CONFIG_PCI_DIRECT) += direct.o -obj-$(CONFIG_X86_VISWS) += visws.o +pci-y := fixup.o +pci-$(CONFIG_ACPI_PCI) += acpi.o +pci-y += legacy.o irq.o -ifdef CONFIG_X86_NUMAQ -obj-y += numa.o -else -obj-y += fixup.o +pci-$(CONFIG_X86_VISWS) := visws.o fixup.o +pci-$(CONFIG_X86_NUMAQ) := numa.o irq.o -ifdef CONFIG_ACPI_PCI -obj-y += acpi.o -endif - -ifndef CONFIG_X86_VISWS -obj-y += legacy.o -endif - -endif # CONFIG_X86_NUMAQ - -ifndef CONFIG_X86_VISWS -obj-y += irq.o -endif - -obj-y += common.o +obj-y += $(pci-y) common.o diff -Nru a/arch/i386/pci/acpi.c b/arch/i386/pci/acpi.c --- a/arch/i386/pci/acpi.c Tue Jul 1 18:44:36 2003 +++ b/arch/i386/pci/acpi.c Tue Jul 1 18:44:36 2003 @@ -3,6 +3,16 @@ #include #include "pci.h" +struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int domain, int busnum) +{ + if (domain != 0) { + printk(KERN_WARNING "PCI: Multiple domains not supported\n"); + return NULL; + } + + return pcibios_scan_root(busnum); +} + static int __init pci_acpi_init(void) { if (pcibios_scanned) diff -Nru a/arch/i386/pci/common.c b/arch/i386/pci/common.c --- a/arch/i386/pci/common.c Tue Jul 1 18:44:34 2003 +++ b/arch/i386/pci/common.c Tue Jul 1 18:44:34 2003 @@ -27,14 +27,12 @@ static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) { - return raw_pci_ops->read(0, bus->number, PCI_SLOT(devfn), - PCI_FUNC(devfn), where, size, value); + return raw_pci_ops->read(0, bus->number, devfn, where, size, value); } static int pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) { - return raw_pci_ops->write(0, bus->number, PCI_SLOT(devfn), - PCI_FUNC(devfn), where, size, value); + return raw_pci_ops->write(0, bus->number, devfn, where, size, value); } struct pci_ops pci_root_ops = { diff -Nru a/arch/i386/pci/direct.c b/arch/i386/pci/direct.c --- a/arch/i386/pci/direct.c Tue Jul 1 18:44:33 2003 +++ b/arch/i386/pci/direct.c Tue Jul 1 18:44:33 2003 @@ -10,19 +10,19 @@ * Functions for accessing PCI configuration space with type 1 accesses */ -#define PCI_CONF1_ADDRESS(bus, dev, fn, reg) \ - (0x80000000 | (bus << 16) | (dev << 11) | (fn << 8) | (reg & ~3)) +#define PCI_CONF1_ADDRESS(bus, devfn, reg) \ + (0x80000000 | (bus << 16) | (devfn << 8) | (reg & ~3)) -static int pci_conf1_read (int seg, int bus, int dev, int fn, int reg, int len, u32 *value) +static int pci_conf1_read (int seg, int bus, int devfn, int reg, int len, u32 *value) { unsigned long flags; - if (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) + if (!value || (bus > 255) || (devfn > 255) || (reg > 255)) return -EINVAL; spin_lock_irqsave(&pci_config_lock, flags); - outl(PCI_CONF1_ADDRESS(bus, dev, fn, reg), 0xCF8); + outl(PCI_CONF1_ADDRESS(bus, devfn, reg), 0xCF8); switch (len) { case 1: @@ -41,16 +41,16 @@ return 0; } -static int pci_conf1_write (int seg, int bus, int dev, int fn, int reg, int len, u32 value) +static int pci_conf1_write (int seg, int bus, int devfn, int reg, int len, u32 value) { unsigned long flags; - if ((bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) + if ((bus > 255) || (devfn > 255) || (reg > 255)) return -EINVAL; spin_lock_irqsave(&pci_config_lock, flags); - outl(PCI_CONF1_ADDRESS(bus, dev, fn, reg), 0xCF8); + outl(PCI_CONF1_ADDRESS(bus, devfn, reg), 0xCF8); switch (len) { case 1: @@ -83,13 +83,17 @@ #define PCI_CONF2_ADDRESS(dev, reg) (u16)(0xC000 | (dev << 8) | reg) -static int pci_conf2_read (int seg, int bus, int dev, int fn, int reg, int len, u32 *value) +static int pci_conf2_read(int seg, int bus, int devfn, int reg, int len, u32 *value) { unsigned long flags; + int dev, fn; - if (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) + if (!value || (bus > 255) || (devfn > 255) || (reg > 255)) return -EINVAL; + dev = PCI_SLOT(devfn); + fn = PCI_FUNC(devfn); + if (dev & 0x10) return PCIBIOS_DEVICE_NOT_FOUND; @@ -110,20 +114,24 @@ break; } - outb (0, 0xCF8); + outb(0, 0xCF8); spin_unlock_irqrestore(&pci_config_lock, flags); return 0; } -static int pci_conf2_write (int seg, int bus, int dev, int fn, int reg, int len, u32 value) +static int pci_conf2_write (int seg, int bus, int devfn, int reg, int len, u32 value) { unsigned long flags; + int dev, fn; - if ((bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) + if ((bus > 255) || (devfn > 255) || (reg > 255)) return -EINVAL; + dev = PCI_SLOT(devfn); + fn = PCI_FUNC(devfn); + if (dev & 0x10) return PCIBIOS_DEVICE_NOT_FOUND; @@ -134,17 +142,17 @@ switch (len) { case 1: - outb ((u8)value, PCI_CONF2_ADDRESS(dev, reg)); + outb((u8)value, PCI_CONF2_ADDRESS(dev, reg)); break; case 2: - outw ((u16)value, PCI_CONF2_ADDRESS(dev, reg)); + outw((u16)value, PCI_CONF2_ADDRESS(dev, reg)); break; case 4: - outl ((u32)value, PCI_CONF2_ADDRESS(dev, reg)); + outl((u32)value, PCI_CONF2_ADDRESS(dev, reg)); break; } - outb (0, 0xCF8); + outb(0, 0xCF8); spin_unlock_irqrestore(&pci_config_lock, flags); @@ -178,14 +186,12 @@ return 1; for (devfn = 0; devfn < 0x100; devfn++) { - if (o->read(0, 0, PCI_SLOT(devfn), PCI_FUNC(devfn), - PCI_CLASS_DEVICE, 2, &x)) + if (o->read(0, 0, devfn, PCI_CLASS_DEVICE, 2, &x)) continue; if (x == PCI_CLASS_BRIDGE_HOST || x == PCI_CLASS_DISPLAY_VGA) return 1; - if (o->read(0, 0, PCI_SLOT(devfn), PCI_FUNC(devfn), - PCI_VENDOR_ID, 2, &x)) + if (o->read(0, 0, devfn, PCI_VENDOR_ID, 2, &x)) continue; if (x == PCI_VENDOR_ID_INTEL || x == PCI_VENDOR_ID_COMPAQ) return 1; @@ -195,54 +201,84 @@ return 0; } -static int __init pci_direct_init(void) +static int __init pci_check_type1(void) { + unsigned long flags; unsigned int tmp; + int works = 0; + + local_irq_save(flags); + + outb(0x01, 0xCFB); + tmp = inl(0xCF8); + outl(0x80000000, 0xCF8); + if (inl(0xCF8) == 0x80000000 && pci_sanity_check(&pci_direct_conf1)) { + works = 1; + } + outl(tmp, 0xCF8); + local_irq_restore(flags); + + return works; +} + +static int __init pci_check_type2(void) +{ unsigned long flags; + int works = 0; local_irq_save(flags); - /* - * Check if configuration type 1 works. - */ - if (pci_probe & PCI_PROBE_CONF1) { - outb (0x01, 0xCFB); - tmp = inl (0xCF8); - outl (0x80000000, 0xCF8); - if (inl (0xCF8) == 0x80000000 && - pci_sanity_check(&pci_direct_conf1)) { - outl (tmp, 0xCF8); - local_irq_restore(flags); - printk(KERN_INFO "PCI: Using configuration type 1\n"); - if (!request_region(0xCF8, 8, "PCI conf1")) - raw_pci_ops = NULL; - else - raw_pci_ops = &pci_direct_conf1; - return 0; - } - outl (tmp, 0xCF8); - } - - /* - * Check if configuration type 2 works. - */ - if (pci_probe & PCI_PROBE_CONF2) { - outb (0x00, 0xCFB); - outb (0x00, 0xCF8); - outb (0x00, 0xCFA); - if (inb (0xCF8) == 0x00 && inb (0xCFA) == 0x00 && - pci_sanity_check(&pci_direct_conf2)) { - local_irq_restore(flags); - printk(KERN_INFO "PCI: Using configuration type 2\n"); - if (!request_region(0xCF8, 4, "PCI conf2")) - raw_pci_ops = NULL; - else - raw_pci_ops = &pci_direct_conf2; - return 0; - } + outb(0x00, 0xCFB); + outb(0x00, 0xCF8); + outb(0x00, 0xCFA); + if (inb(0xCF8) == 0x00 && inb(0xCFA) == 0x00 && + pci_sanity_check(&pci_direct_conf2)) { + works = 1; } local_irq_restore(flags); + + return works; +} + +static int __init pci_direct_init(void) +{ + struct resource *region, *region2; + + if ((pci_probe & PCI_PROBE_CONF1) == 0) + goto type2; + region = request_region(0xCF8, 8, "PCI conf1"); + if (!region) + goto type2; + + if (pci_check_type1()) { + printk(KERN_INFO "PCI: Using configuration type 1\n"); + raw_pci_ops = &pci_direct_conf1; + return 0; + } + release_resource(region); + + type2: + if ((!pci_probe & PCI_PROBE_CONF2) == 0) + goto out; + region = request_region(0xCF8, 4, "PCI conf2"); + if (!region) + goto out; + region2 = request_region(0xC000, 0x1000, "PCI conf2"); + if (!region2) + goto fail2; + + if (pci_check_type2()) { + printk(KERN_INFO "PCI: Using configuration type 2\n"); + raw_pci_ops = &pci_direct_conf2; + return 0; + } + + release_resource(region2); + fail2: + release_resource(region); + + out: return 0; } diff -Nru a/arch/i386/pci/numa.c b/arch/i386/pci/numa.c --- a/arch/i386/pci/numa.c Tue Jul 1 18:44:33 2003 +++ b/arch/i386/pci/numa.c Tue Jul 1 18:44:33 2003 @@ -10,19 +10,19 @@ #define BUS2LOCAL(global) (mp_bus_id_to_local[global]) #define QUADLOCAL2BUS(quad,local) (quad_local_to_mp_bus_id[quad][local]) -#define PCI_CONF1_MQ_ADDRESS(bus, dev, fn, reg) \ - (0x80000000 | (BUS2LOCAL(bus) << 16) | (dev << 11) | (fn << 8) | (reg & ~3)) +#define PCI_CONF1_MQ_ADDRESS(bus, devfn, reg) \ + (0x80000000 | (BUS2LOCAL(bus) << 16) | (devfn << 8) | (reg & ~3)) -static int pci_conf1_mq_read (int seg, int bus, int dev, int fn, int reg, int len, u32 *value) +static int pci_conf1_mq_read (int seg, int bus, int devfn, int reg, int len, u32 *value) { unsigned long flags; - if (!value || (bus > MAX_MP_BUSSES) || (dev > 31) || (fn > 7) || (reg > 255)) + if (!value || (bus > MAX_MP_BUSSES) || (devfn > 255) || (reg > 255)) return -EINVAL; spin_lock_irqsave(&pci_config_lock, flags); - outl_quad(PCI_CONF1_MQ_ADDRESS(bus, dev, fn, reg), 0xCF8, BUS2QUAD(bus)); + outl_quad(PCI_CONF1_MQ_ADDRESS(bus, devfn, reg), 0xCF8, BUS2QUAD(bus)); switch (len) { case 1: @@ -41,16 +41,16 @@ return 0; } -static int pci_conf1_mq_write (int seg, int bus, int dev, int fn, int reg, int len, u32 value) +static int pci_conf1_mq_write (int seg, int bus, int devfn, int reg, int len, u32 value) { unsigned long flags; - if ((bus > MAX_MP_BUSSES) || (dev > 31) || (fn > 7) || (reg > 255)) + if ((bus > MAX_MP_BUSSES) || (devfn > 255) || (reg > 255)) return -EINVAL; spin_lock_irqsave(&pci_config_lock, flags); - outl_quad(PCI_CONF1_MQ_ADDRESS(bus, dev, fn, reg), 0xCF8, BUS2QUAD(bus)); + outl_quad(PCI_CONF1_MQ_ADDRESS(bus, devfn, reg), 0xCF8, BUS2QUAD(bus)); switch (len) { case 1: diff -Nru a/arch/i386/pci/pcbios.c b/arch/i386/pci/pcbios.c --- a/arch/i386/pci/pcbios.c Tue Jul 1 18:44:31 2003 +++ b/arch/i386/pci/pcbios.c Tue Jul 1 18:44:31 2003 @@ -172,13 +172,13 @@ return (int) (ret & 0xff00) >> 8; } -static int pci_bios_read (int seg, int bus, int dev, int fn, int reg, int len, u32 *value) +static int pci_bios_read (int seg, int bus, int devfn, int reg, int len, u32 *value) { unsigned long result = 0; unsigned long flags; - unsigned long bx = ((bus << 8) | (dev << 3) | fn); + unsigned long bx = (bus << 8) | devfn; - if (!value || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) + if (!value || (bus > 255) || (devfn > 255) || (reg > 255)) return -EINVAL; spin_lock_irqsave(&pci_config_lock, flags); @@ -227,13 +227,13 @@ return (int)((result & 0xff00) >> 8); } -static int pci_bios_write (int seg, int bus, int dev, int fn, int reg, int len, u32 value) +static int pci_bios_write (int seg, int bus, int devfn, int reg, int len, u32 value) { unsigned long result = 0; unsigned long flags; - unsigned long bx = ((bus << 8) | (dev << 3) | fn); + unsigned long bx = (bus << 8) | devfn; - if ((bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) + if ((bus > 255) || (devfn > 255) || (reg > 255)) return -EINVAL; spin_lock_irqsave(&pci_config_lock, flags); diff -Nru a/arch/ia64/Kconfig b/arch/ia64/Kconfig --- a/arch/ia64/Kconfig Tue Jul 1 18:44:38 2003 +++ b/arch/ia64/Kconfig Tue Jul 1 18:44:38 2003 @@ -544,6 +544,8 @@ source "drivers/block/Kconfig" +source "drivers/ide/Kconfig" + source "drivers/ieee1394/Kconfig" source "drivers/message/i2o/Kconfig" @@ -555,32 +557,8 @@ endif -menu "SCSI support" - -config SCSI - tristate "SCSI support" - ---help--- - If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or - any other SCSI device under Linux, say Y and make sure that you know - the name of your SCSI host adapter (the card inside your computer - that "speaks" the SCSI protocol, also called SCSI controller), - because you will be asked for it. - - You also need to say Y here if you want support for the parallel - port version of the 100 MB IOMEGA ZIP drive. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called scsi_mod. If you want to compile it as - a module, say M here and read and - . However, do not compile this as a - module if your root file system (the one containing the directory /) - is located on a SCSI device. - source "drivers/scsi/Kconfig" -endmenu - source "net/Kconfig" @@ -590,42 +568,8 @@ source "drivers/isdn/Kconfig" - -menu "CD-ROM drivers (not for SCSI or IDE/ATAPI drives)" - -config CD_NO_IDESCSI - bool "Support non-SCSI/IDE/ATAPI CDROM drives" - ---help--- - If you have a CD-ROM drive that is neither SCSI nor IDE/ATAPI, say Y - here, otherwise N. Read the CD-ROM-HOWTO, available from - . - - Note that the answer to this question doesn't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about these CD-ROM drives. If you are unsure what you - have, say Y and find out whether you have one of the following - drives. - - For each of these drivers, a file Documentation/cdrom/{driver_name} - exists. Especially in cases where you do not know exactly which kind - of drive you have you should read there. Most of these drivers use a - file drivers/cdrom/{driver_name}.h where you can define your - interface parameters and switch some internal goodies. - - All these CD-ROM drivers are also usable as a module ( = code which - can be inserted in and removed from the running kernel whenever you - want). If you want to compile them as module, say M instead of Y and - read . - - If you want to use any of these CD-ROM drivers, you also have to - answer Y or M to "ISO 9660 CD-ROM file system support" below (this - answer will get "defaulted" for you if you enable any of the Linux - CD-ROM drivers). - source "drivers/cdrom/Kconfig" -endmenu - # # input before char - char/joystick depends on it. As does USB. # @@ -786,6 +730,10 @@ config IA64_EARLY_PRINTK_VGA bool "Early printk on VGA" depends on IA64_EARLY_PRINTK + +config IA64_EARLY_PRINTK_SGI_SN + bool "Early printk on SGI SN serial console" + depends on IA64_EARLY_PRINTK && (IA64_GENERIC || IA64_SGI_SN2) config DEBUG_SLAB bool "Debug memory allocations" diff -Nru a/arch/ia64/Makefile b/arch/ia64/Makefile --- a/arch/ia64/Makefile Tue Jul 1 18:44:31 2003 +++ b/arch/ia64/Makefile Tue Jul 1 18:44:31 2003 @@ -27,7 +27,7 @@ GAS_STATUS=$(shell arch/ia64/scripts/check-gas $(CC) $(OBJDUMP)) -arch-cppflags := $(shell arch/ia64/scripts/toolchain-flags $(CC) $(LD) $(OBJDUMP)) +arch-cppflags := $(shell arch/ia64/scripts/toolchain-flags $(CC) $(OBJDUMP)) cflags-y += $(arch-cppflags) AFLAGS += $(arch-cppflags) @@ -66,7 +66,8 @@ drivers-$(CONFIG_PCI) += arch/ia64/pci/ drivers-$(CONFIG_IA64_HP_SIM) += arch/ia64/hp/sim/ drivers-$(CONFIG_IA64_HP_ZX1) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ -drivers-$(CONFIG_IA64_GENERIC) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ arch/ia64/hp/sim/ +drivers-$(CONFIG_IA64_GENERIC) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ arch/ia64/hp/sim/ \ + arch/ia64/sn/ boot := arch/ia64/boot diff -Nru a/arch/ia64/defconfig b/arch/ia64/defconfig --- a/arch/ia64/defconfig Tue Jul 1 18:44:31 2003 +++ b/arch/ia64/defconfig Tue Jul 1 18:44:32 2003 @@ -10,30 +10,38 @@ # # General setup # -CONFIG_NET=y +CONFIG_SWAP=y CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_BSD_PROCESS_ACCT=y CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=16 +# CONFIG_EMBEDDED is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y # # Loadable module support # CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_OBSOLETE_MODPARM=y CONFIG_MODVERSIONS=y -# CONFIG_KMOD is not set +CONFIG_KMOD=y # # Processor type and features # CONFIG_IA64=y -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_ITANIUM=y -# CONFIG_MCKINLEY is not set +CONFIG_MMU=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_TIME_INTERPOLATION=y +# CONFIG_ITANIUM is not set +CONFIG_MCKINLEY=y # CONFIG_IA64_GENERIC is not set -CONFIG_IA64_DIG=y +# CONFIG_IA64_DIG is not set # CONFIG_IA64_HP_SIM is not set -# CONFIG_IA64_HP_ZX1 is not set -# CONFIG_IA64_SGI_SN1 is not set +CONFIG_IA64_HP_ZX1=y # CONFIG_IA64_SGI_SN2 is not set # CONFIG_IA64_PAGE_SIZE_4KB is not set # CONFIG_IA64_PAGE_SIZE_8KB is not set @@ -43,41 +51,64 @@ CONFIG_ACPI_EFI=y CONFIG_ACPI_INTERPRETER=y CONFIG_ACPI_KERNEL_CONFIG=y -CONFIG_IA64_BRL_EMU=y -# CONFIG_ITANIUM_BSTEP_SPECIFIC is not set -CONFIG_IA64_L1_CACHE_SHIFT=6 +CONFIG_IA64_L1_CACHE_SHIFT=7 +# CONFIG_MCKINLEY_ASTEP_SPECIFIC is not set # CONFIG_NUMA is not set +CONFIG_VIRTUAL_MEM_MAP=y CONFIG_IA64_MCA=y CONFIG_PM=y CONFIG_IOSAPIC=y CONFIG_KCORE_ELF=y CONFIG_FORCE_MAX_ZONEORDER=18 -# CONFIG_HUGETLB_PAGE is not set +CONFIG_HUGETLB_PAGE=y +# CONFIG_HUGETLB_PAGE_SIZE_4GB is not set +# CONFIG_HUGETLB_PAGE_SIZE_1GB is not set +# CONFIG_HUGETLB_PAGE_SIZE_256MB is not set +CONFIG_HUGETLB_PAGE_SIZE_64MB=y +# CONFIG_HUGETLB_PAGE_SIZE_16MB is not set +# CONFIG_HUGETLB_PAGE_SIZE_4MB is not set +# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set +# CONFIG_HUGETLB_PAGE_SIZE_256KB is not set +CONFIG_IA64_PAL_IDLE=y CONFIG_SMP=y +# CONFIG_PREEMPT is not set CONFIG_IA32_SUPPORT=y +CONFIG_COMPAT=y CONFIG_PERFMON=y CONFIG_IA64_PALINFO=y CONFIG_EFI_VARS=y CONFIG_NR_CPUS=16 CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set +CONFIG_BINFMT_MISC=y # # ACPI Support # CONFIG_ACPI_BOOT=y CONFIG_ACPI_BUTTON=y -CONFIG_ACPI_FAN=m -CONFIG_ACPI_PROCESSOR=m -CONFIG_ACPI_THERMAL=m +CONFIG_ACPI_FAN=y +CONFIG_ACPI_PROCESSOR=y +CONFIG_ACPI_THERMAL=y # CONFIG_ACPI_DEBUG is not set CONFIG_ACPI_BUS=y CONFIG_ACPI_POWER=y CONFIG_ACPI_PCI=y CONFIG_ACPI_SYSTEM=y CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_LEGACY_PROC=y CONFIG_PCI_NAMES=y -# CONFIG_HOTPLUG is not set +CONFIG_HOTPLUG=y + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set + +# +# PCMCIA/CardBus support +# +# CONFIG_PCMCIA is not set # # Parallel port support @@ -85,12 +116,17 @@ # CONFIG_PARPORT is not set # +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# # Memory Technology Devices (MTD) # # CONFIG_MTD is not set # -# Plug and Play configuration +# Plug and Play support # # CONFIG_PNP is not set @@ -104,7 +140,9 @@ # CONFIG_BLK_DEV_UMEM is not set CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_RAM is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y # # IEEE 1394 (FireWire) support (EXPERIMENTAL) @@ -124,64 +162,11 @@ # # Fusion MPT device support # -# CONFIG_FUSION is not set - -# -# ATA/ATAPI/MFM/RLL support -# -CONFIG_IDE=y - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=y -CONFIG_IDEDISK_MULTI_MODE=y -# CONFIG_IDEDISK_STROKE is not set -CONFIG_BLK_DEV_IDECD=y -CONFIG_BLK_DEV_IDEFLOPPY=y -CONFIG_BLK_DEV_IDESCSI=y -# CONFIG_IDE_TASK_IOCTL is not set - -# -# IDE chipset support/bugfixes -# -CONFIG_BLK_DEV_IDEPCI=y -# CONFIG_BLK_DEV_GENERIC is not set -CONFIG_IDEPCI_SHARE_IRQ=y -CONFIG_BLK_DEV_IDEDMA_PCI=y -# CONFIG_BLK_DEV_IDE_TCQ is not set -# CONFIG_BLK_DEV_OFFBOARD is not set -# CONFIG_BLK_DEV_IDEDMA_FORCED is not set -# CONFIG_IDEDMA_PCI_AUTO is not set -CONFIG_BLK_DEV_IDEDMA=y -# CONFIG_IDEDMA_PCI_WIP is not set -CONFIG_BLK_DEV_ADMA=y -# CONFIG_BLK_DEV_AEC62XX is not set -# CONFIG_BLK_DEV_ALI15X3 is not set -# CONFIG_BLK_DEV_AMD74XX is not set -# CONFIG_BLK_DEV_CMD64X is not set -# CONFIG_BLK_DEV_CY82C693 is not set -# CONFIG_BLK_DEV_CS5530 is not set -# CONFIG_BLK_DEV_HPT34X is not set -# CONFIG_BLK_DEV_HPT366 is not set -# CONFIG_BLK_DEV_PIIX is not set -# CONFIG_BLK_DEV_NFORCE is not set -# CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_OPTI621 is not set -# CONFIG_BLK_DEV_PDC202XX_OLD is not set -# CONFIG_BLK_DEV_PDC202XX_NEW is not set -# CONFIG_BLK_DEV_SVWKS is not set -# CONFIG_BLK_DEV_SIIMAGE is not set -# CONFIG_BLK_DEV_SLC90E66 is not set -# CONFIG_BLK_DEV_TRM290 is not set -# CONFIG_BLK_DEV_VIA82CXXX is not set -# CONFIG_IDEDMA_IVB is not set +CONFIG_FUSION=y +CONFIG_FUSION_BOOT=y +CONFIG_FUSION_MAX_SGE=40 +# CONFIG_FUSION_ISENSE is not set +# CONFIG_FUSION_CTL is not set # # SCSI support @@ -192,16 +177,17 @@ # SCSI support type (disk, tape, CD-ROM) # CONFIG_BLK_DEV_SD=y -# CONFIG_CHR_DEV_ST is not set -# CONFIG_CHR_DEV_OSST is not set -# CONFIG_BLK_DEV_SR is not set -# CONFIG_CHR_DEV_SG is not set +CONFIG_CHR_DEV_ST=y +CONFIG_CHR_DEV_OSST=y +CONFIG_BLK_DEV_SR=y +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=y # # Some SCSI devices (e.g. CD jukebox) support multiple LUNs # -# CONFIG_SCSI_MULTI_LUN is not set -# CONFIG_SCSI_REPORT_LUNS is not set +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_REPORT_LUNS=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y @@ -212,57 +198,76 @@ # CONFIG_SCSI_ACARD is not set # CONFIG_SCSI_AACRAID is not set # CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC7XXX_OLD is not set +CONFIG_SCSI_AIC7XXX_OLD=y +# CONFIG_SCSI_AIC79XX is not set # CONFIG_SCSI_DPT_I2O is not set # CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_AM53C974 is not set -# CONFIG_SCSI_MEGARAID is not set +CONFIG_SCSI_MEGARAID=y # CONFIG_SCSI_BUSLOGIC is not set # CONFIG_SCSI_CPQFCTS is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_DMA is not set # CONFIG_SCSI_EATA_PIO is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_GDTH is not set -# CONFIG_SCSI_GENERIC_NCR5380 is not set -# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set # CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_NCR53C7xx is not set -# CONFIG_SCSI_SYM53C8XX_2 is not set -# CONFIG_SCSI_NCR53C8XX is not set -# CONFIG_SCSI_SYM53C8XX is not set +CONFIG_SCSI_SYM53C8XX_2=y +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set # CONFIG_SCSI_PCI2000 is not set # CONFIG_SCSI_PCI2220I is not set # CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_QLOGIC_FC is not set CONFIG_SCSI_QLOGIC_1280=y +# CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_U14_34F is not set # CONFIG_SCSI_NSP32 is not set # CONFIG_SCSI_DEBUG is not set # +# Networking support +# +CONFIG_NET=y + +# # Networking options # CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y +# CONFIG_PACKET_MMAP is not set # CONFIG_NETLINK_DEV is not set -# CONFIG_NETFILTER is not set -CONFIG_FILTER=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set CONFIG_UNIX=y +# CONFIG_NET_KEY is not set CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set +CONFIG_IP_MULTICAST=y # CONFIG_IP_ADVANCED_ROUTER is not set # CONFIG_IP_PNP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set # CONFIG_ARPD is not set # CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_IP_NF_CONNTRACK is not set +# CONFIG_IP_NF_QUEUE is not set +# CONFIG_IP_NF_IPTABLES is not set +CONFIG_IP_NF_ARPTABLES=y +# CONFIG_IP_NF_ARPFILTER is not set +# CONFIG_IP_NF_COMPAT_IPCHAINS is not set +# CONFIG_IP_NF_COMPAT_IPFWADM is not set # CONFIG_IPV6 is not set +# CONFIG_XFRM_USER is not set # # SCTP Configuration (EXPERIMENTAL) @@ -288,8 +293,9 @@ # CONFIG_NET_SCHED is not set # -# Network device support +# Network testing # +# CONFIG_NET_PKTGEN is not set CONFIG_NETDEVICES=y # @@ -297,7 +303,7 @@ # # CONFIG_ARCNET is not set CONFIG_DUMMY=y -# CONFIG_BONDING is not set +CONFIG_BONDING=y # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set # CONFIG_ETHERTAP is not set @@ -306,11 +312,10 @@ # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y +CONFIG_MII=y # CONFIG_HAPPYMEAL is not set # CONFIG_SUNGEM is not set # CONFIG_NET_VENDOR_3COM is not set -# CONFIG_NET_VENDOR_SMC is not set -# CONFIG_NET_VENDOR_RACAL is not set # # Tulip family network device support @@ -319,9 +324,12 @@ # CONFIG_HP100 is not set CONFIG_NET_PCI=y # CONFIG_PCNET32 is not set +# CONFIG_AMD8111_ETH is not set # CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_B44 is not set # CONFIG_DGRS is not set CONFIG_EEPRO100=y +# CONFIG_EEPRO100_PIO is not set # CONFIG_E100 is not set # CONFIG_FEALNX is not set # CONFIG_NATSEMI is not set @@ -333,19 +341,25 @@ # CONFIG_SUNDANCE is not set # CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set -# CONFIG_NET_POCKET is not set # # Ethernet (1000 Mbit) # # CONFIG_ACENIC is not set # CONFIG_DL2K is not set -# CONFIG_E1000 is not set +CONFIG_E1000=y +# CONFIG_E1000_NAPI is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set # CONFIG_SK98LIN is not set -# CONFIG_TIGON3 is not set +CONFIG_TIGON3=m + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set # CONFIG_PPP is not set @@ -357,9 +371,8 @@ # CONFIG_NET_RADIO is not set # -# Token Ring devices +# Token Ring devices (depends on LLC=y) # -# CONFIG_TR is not set # CONFIG_NET_FC is not set # CONFIG_RCPCI is not set # CONFIG_SHAPER is not set @@ -393,10 +406,10 @@ # Userland interfaces # CONFIG_INPUT_MOUSEDEV=y -CONFIG_INPUT_MOUSEDEV_PSAUX=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -# CONFIG_INPUT_JOYDEV is not set +CONFIG_INPUT_JOYDEV=y # CONFIG_INPUT_TSDEV is not set CONFIG_INPUT_EVDEV=y # CONFIG_INPUT_EVBUG is not set @@ -407,26 +420,19 @@ # CONFIG_GAMEPORT is not set CONFIG_SOUND_GAMEPORT=y CONFIG_SERIO=y -CONFIG_SERIO_I8042=y -CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_I8042 is not set +# CONFIG_SERIO_SERPORT is not set # CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set # # Input Device Drivers # -CONFIG_INPUT_KEYBOARD=y -CONFIG_KEYBOARD_ATKBD=y -# CONFIG_KEYBOARD_SUNKBD is not set -# CONFIG_KEYBOARD_XTKBD is not set -# CONFIG_KEYBOARD_NEWTON is not set -CONFIG_INPUT_MOUSE=y -CONFIG_MOUSE_PS2=y -# CONFIG_MOUSE_SERIAL is not set +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set # CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_TOUCHSCREEN is not set -CONFIG_INPUT_MISC=y -# CONFIG_INPUT_PCSPKR is not set -# CONFIG_INPUT_UINPUT is not set +# CONFIG_INPUT_MISC is not set # # Character devices @@ -441,12 +447,9 @@ # CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_SERIAL_8250_EXTENDED=y -# CONFIG_SERIAL_8250_MANY_PORTS is not set -CONFIG_SERIAL_8250_SHARE_IRQ=y -# CONFIG_SERIAL_8250_DETECT_IRQ is not set -# CONFIG_SERIAL_8250_MULTIPORT is not set -# CONFIG_SERIAL_8250_RSA is not set +CONFIG_SERIAL_8250_ACPI=y +CONFIG_SERIAL_8250_HCDP=y +# CONFIG_SERIAL_8250_EXTENDED is not set # # Non-8250 serial port support @@ -459,14 +462,16 @@ # # I2C support # -CONFIG_I2C=y -CONFIG_I2C_ALGOBIT=y -# CONFIG_I2C_ELV is not set -# CONFIG_I2C_VELLEMAN is not set -# CONFIG_SCx200_ACB is not set -# CONFIG_I2C_ALGOPCF is not set -CONFIG_I2C_CHARDEV=y -CONFIG_I2C_PROC=y +# CONFIG_I2C is not set + +# +# I2C Hardware Sensors Mainboard support +# + +# +# I2C Hardware Sensors Chip support +# +# CONFIG_I2C_SENSOR is not set # # Mice @@ -475,12 +480,16 @@ # CONFIG_QIC02_TAPE is not set # +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# # Watchdog Cards # # CONFIG_WATCHDOG is not set -# CONFIG_INTEL_RNG is not set +# CONFIG_HW_RANDOM is not set # CONFIG_NVRAM is not set -# CONFIG_RTC is not set # CONFIG_GEN_RTC is not set CONFIG_EFI_RTC=y # CONFIG_DTLK is not set @@ -491,25 +500,17 @@ # Ftape, the floppy tape device driver # # CONFIG_FTAPE is not set -CONFIG_AGP=y -CONFIG_AGP_INTEL=y -CONFIG_AGP_I810=y -CONFIG_AGP_VIA=y -CONFIG_AGP_AMD=y -CONFIG_AGP_SIS=y -CONFIG_AGP_ALI=y -CONFIG_AGP_SWORKS=y -# CONFIG_AGP_AMD_8151 is not set -CONFIG_AGP_I460=y -CONFIG_AGP_HP_ZX1=y +CONFIG_AGP=m +CONFIG_AGP_I460=m +CONFIG_AGP_HP_ZX1=m CONFIG_DRM=y -CONFIG_DRM_TDFX=y -CONFIG_DRM_R128=y -CONFIG_DRM_RADEON=y -CONFIG_DRM_I810=y -CONFIG_DRM_I830=y -CONFIG_DRM_MGA=y +# CONFIG_DRM_TDFX is not set +# CONFIG_DRM_GAMMA is not set +# CONFIG_DRM_R128 is not set +CONFIG_DRM_RADEON=m +# CONFIG_DRM_MGA is not set # CONFIG_RAW_DRIVER is not set +# CONFIG_HANGCHECK_TIMER is not set # # Multimedia devices @@ -517,51 +518,79 @@ # CONFIG_VIDEO_DEV is not set # +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# # File systems # +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +# CONFIG_EXT2_FS_POSIX_ACL is not set +# CONFIG_EXT2_FS_SECURITY is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set CONFIG_AUTOFS_FS=y # CONFIG_AUTOFS4_FS is not set -# CONFIG_REISERFS_FS is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +# CONFIG_ZISOFS is not set +CONFIG_UDF_FS=y + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +# CONFIG_DEVPTS_FS_XATTR is not set +CONFIG_TMPFS=y +CONFIG_HUGETLBFS=y +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set -CONFIG_EXT3_FS=y -CONFIG_JBD=y -# CONFIG_JBD_DEBUG is not set -CONFIG_FAT_FS=y -CONFIG_MSDOS_FS=y -CONFIG_VFAT_FS=y # CONFIG_EFS_FS is not set # CONFIG_CRAMFS is not set -# CONFIG_TMPFS is not set -CONFIG_RAMFS=y -CONFIG_ISO9660_FS=y -# CONFIG_JOLIET is not set -# CONFIG_ZISOFS is not set -# CONFIG_JFS_FS is not set -# CONFIG_MINIX_FS is not set # CONFIG_VXFS_FS is not set -# CONFIG_NTFS_FS is not set # CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set # CONFIG_UFS_FS is not set -# CONFIG_XFS_FS is not set # # Network File Systems # -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=y CONFIG_NFS_V3=y CONFIG_NFS_V4=y @@ -569,13 +598,16 @@ CONFIG_NFSD_V3=y # CONFIG_NFSD_V4 is not set # CONFIG_NFSD_TCP is not set -CONFIG_SUNRPC=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y CONFIG_EXPORTFS=y -# CONFIG_CIFS is not set +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y # CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set # CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set # CONFIG_AFS_FS is not set # @@ -593,6 +625,7 @@ # CONFIG_SOLARIS_X86_PARTITION is not set # CONFIG_UNIXWARE_DISKLABEL is not set # CONFIG_LDM_PARTITION is not set +# CONFIG_NEC98_PARTITION is not set # CONFIG_SGI_PARTITION is not set # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set @@ -603,53 +636,84 @@ # Native Language Support # CONFIG_NLS_DEFAULT="iso8859-1" -# CONFIG_NLS_CODEPAGE_437 is not set -# CONFIG_NLS_CODEPAGE_737 is not set -# CONFIG_NLS_CODEPAGE_775 is not set -# CONFIG_NLS_CODEPAGE_850 is not set -# CONFIG_NLS_CODEPAGE_852 is not set -# CONFIG_NLS_CODEPAGE_855 is not set -# CONFIG_NLS_CODEPAGE_857 is not set -# CONFIG_NLS_CODEPAGE_860 is not set -# CONFIG_NLS_CODEPAGE_861 is not set -# CONFIG_NLS_CODEPAGE_862 is not set -# CONFIG_NLS_CODEPAGE_863 is not set -# CONFIG_NLS_CODEPAGE_864 is not set -# CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set -# CONFIG_NLS_CODEPAGE_869 is not set -# CONFIG_NLS_CODEPAGE_936 is not set -# CONFIG_NLS_CODEPAGE_950 is not set -# CONFIG_NLS_CODEPAGE_932 is not set -# CONFIG_NLS_CODEPAGE_949 is not set -# CONFIG_NLS_CODEPAGE_874 is not set -# CONFIG_NLS_ISO8859_8 is not set +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=y +CONFIG_NLS_CODEPAGE_775=y +CONFIG_NLS_CODEPAGE_850=y +CONFIG_NLS_CODEPAGE_852=y +CONFIG_NLS_CODEPAGE_855=y +CONFIG_NLS_CODEPAGE_857=y +CONFIG_NLS_CODEPAGE_860=y +CONFIG_NLS_CODEPAGE_861=y +CONFIG_NLS_CODEPAGE_862=y +CONFIG_NLS_CODEPAGE_863=y +CONFIG_NLS_CODEPAGE_864=y +CONFIG_NLS_CODEPAGE_865=y +CONFIG_NLS_CODEPAGE_866=y +CONFIG_NLS_CODEPAGE_869=y +CONFIG_NLS_CODEPAGE_936=y +CONFIG_NLS_CODEPAGE_950=y +CONFIG_NLS_CODEPAGE_932=y +CONFIG_NLS_CODEPAGE_949=y +CONFIG_NLS_CODEPAGE_874=y +CONFIG_NLS_ISO8859_8=y # CONFIG_NLS_CODEPAGE_1250 is not set -# CONFIG_NLS_CODEPAGE_1251 is not set -# CONFIG_NLS_ISO8859_1 is not set -# CONFIG_NLS_ISO8859_2 is not set -# CONFIG_NLS_ISO8859_3 is not set -# CONFIG_NLS_ISO8859_4 is not set -# CONFIG_NLS_ISO8859_5 is not set -# CONFIG_NLS_ISO8859_6 is not set -# CONFIG_NLS_ISO8859_7 is not set -# CONFIG_NLS_ISO8859_9 is not set -# CONFIG_NLS_ISO8859_13 is not set -# CONFIG_NLS_ISO8859_14 is not set -# CONFIG_NLS_ISO8859_15 is not set -# CONFIG_NLS_KOI8_R is not set -# CONFIG_NLS_KOI8_U is not set -# CONFIG_NLS_UTF8 is not set +CONFIG_NLS_CODEPAGE_1251=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_ISO8859_2=y +CONFIG_NLS_ISO8859_3=y +CONFIG_NLS_ISO8859_4=y +CONFIG_NLS_ISO8859_5=y +CONFIG_NLS_ISO8859_6=y +CONFIG_NLS_ISO8859_7=y +CONFIG_NLS_ISO8859_9=y +CONFIG_NLS_ISO8859_13=y +CONFIG_NLS_ISO8859_14=y +CONFIG_NLS_ISO8859_15=y +CONFIG_NLS_KOI8_R=y +CONFIG_NLS_KOI8_U=y +CONFIG_NLS_UTF8=y + +# +# Graphics support +# +CONFIG_FB=y +# CONFIG_FB_CIRRUS is not set +# CONFIG_FB_PM2 is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_IMSTT is not set +CONFIG_FB_RIVA=m +# CONFIG_FB_MATROX is not set +CONFIG_FB_RADEON=y +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_PM3 is not set +# CONFIG_FB_VIRTUAL is not set # -# Console drivers +# Console display driver support # CONFIG_VGA_CONSOLE=y +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_PCI_CONSOLE=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y # -# Frame-buffer support -# -# CONFIG_FB is not set +# Logo configuration +# +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_LOGO_LINUX_CLUT224=y # # Sound @@ -659,31 +723,62 @@ # # Advanced Linux Sound Architecture # -# CONFIG_SND is not set +CONFIG_SND=m +CONFIG_SND_SEQUENCER=m +# CONFIG_SND_SEQ_DUMMY is not set +# CONFIG_SND_OSSEMUL is not set +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set + +# +# Generic devices +# +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_VIRMIDI is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set + +# +# PCI devices +# +# CONFIG_SND_ALI5451 is not set +# CONFIG_SND_AZT3328 is not set +# CONFIG_SND_CS46XX is not set +# CONFIG_SND_CS4281 is not set +# CONFIG_SND_EMU10K1 is not set +# CONFIG_SND_KORG1212 is not set +# CONFIG_SND_NM256 is not set +# CONFIG_SND_RME32 is not set +# CONFIG_SND_RME96 is not set +# CONFIG_SND_RME9652 is not set +# CONFIG_SND_HDSP is not set +# CONFIG_SND_TRIDENT is not set +# CONFIG_SND_YMFPCI is not set +# CONFIG_SND_ALS4000 is not set +# CONFIG_SND_CMIPCI is not set +# CONFIG_SND_ENS1370 is not set +# CONFIG_SND_ENS1371 is not set +# CONFIG_SND_ES1938 is not set +# CONFIG_SND_ES1968 is not set +# CONFIG_SND_MAESTRO3 is not set +CONFIG_SND_FM801=m +# CONFIG_SND_ICE1712 is not set +# CONFIG_SND_ICE1724 is not set +# CONFIG_SND_INTEL8X0 is not set +# CONFIG_SND_SONICVIBES is not set +# CONFIG_SND_VIA82XX is not set +# CONFIG_SND_VX222 is not set + +# +# ALSA USB devices +# +# CONFIG_SND_USB_AUDIO is not set # # Open Sound System # -CONFIG_SOUND_PRIME=y -# CONFIG_SOUND_BT878 is not set -# CONFIG_SOUND_CMPCI is not set -# CONFIG_SOUND_EMU10K1 is not set -# CONFIG_SOUND_FUSION is not set -CONFIG_SOUND_CS4281=y -# CONFIG_SOUND_ES1370 is not set -# CONFIG_SOUND_ES1371 is not set -# CONFIG_SOUND_ESSSOLO1 is not set -# CONFIG_SOUND_MAESTRO is not set -# CONFIG_SOUND_MAESTRO3 is not set -# CONFIG_SOUND_ICH is not set -# CONFIG_SOUND_RME96XX is not set -# CONFIG_SOUND_SONICVIBES is not set -# CONFIG_SOUND_TRIDENT is not set -# CONFIG_SOUND_MSNDCLAS is not set -# CONFIG_SOUND_MSNDPIN is not set -# CONFIG_SOUND_VIA82CXXX is not set -# CONFIG_SOUND_OSS is not set -# CONFIG_SOUND_TVMIXER is not set +# CONFIG_SOUND_PRIME is not set # # USB support @@ -694,17 +789,16 @@ # # Miscellaneous USB options # -CONFIG_USB_DEVICEFS=y -# CONFIG_USB_LONG_TIMEOUT is not set -# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DEVICEFS is not set +CONFIG_USB_BANDWIDTH=y # CONFIG_USB_DYNAMIC_MINORS is not set # # USB Host Controller Drivers # -# CONFIG_USB_EHCI_HCD is not set -# CONFIG_USB_OHCI_HCD is not set -CONFIG_USB_UHCI_HCD_ALT=y +CONFIG_USB_EHCI_HCD=m +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_UHCI_HCD=m # # USB Device Class drivers @@ -725,6 +819,7 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_AIPTEK is not set # CONFIG_USB_WACOM is not set +# CONFIG_USB_KBTAB is not set # CONFIG_USB_POWERMATE is not set # CONFIG_USB_XPAD is not set @@ -748,8 +843,8 @@ # # USB Network adaptors # +# CONFIG_USB_AX8817X is not set # CONFIG_USB_CATC is not set -# CONFIG_USB_CDCETHER is not set # CONFIG_USB_KAWETH is not set # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set @@ -772,17 +867,17 @@ # CONFIG_USB_RIO500 is not set # CONFIG_USB_BRLVGER is not set # CONFIG_USB_LCD is not set -# CONFIG_USB_TEST is not set +# CONFIG_USB_GADGET is not set # -# Library routines +# Bluetooth support # -# CONFIG_CRC32 is not set +# CONFIG_BT is not set # -# Bluetooth support +# Library routines # -# CONFIG_BT is not set +CONFIG_CRC32=y # # Kernel hacking @@ -794,18 +889,17 @@ CONFIG_IA64_PRINT_HAZARDS=y # CONFIG_DISABLE_VHPT is not set CONFIG_MAGIC_SYSRQ=y -CONFIG_IA64_EARLY_PRINTK=y -# CONFIG_IA64_EARLY_PRINTK_UART is not set -CONFIG_IA64_EARLY_PRINTK_VGA=y +# CONFIG_IA64_EARLY_PRINTK is not set # CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_IA64_DEBUG_CMPXCHG is not set # CONFIG_IA64_DEBUG_IRQ is not set # # Security options # -CONFIG_SECURITY_CAPABILITIES=y +# CONFIG_SECURITY is not set # # Cryptographic options diff -Nru a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c --- a/arch/ia64/kernel/acpi.c Tue Jul 1 18:44:35 2003 +++ b/arch/ia64/kernel/acpi.c Tue Jul 1 18:44:35 2003 @@ -575,59 +575,6 @@ } -#ifdef CONFIG_SERIAL_8250_ACPI - -#include - -static int __init -acpi_parse_spcr (unsigned long phys_addr, unsigned long size) -{ - acpi_ser_t *spcr; - unsigned int gsi; - - if (!phys_addr || !size) - return -EINVAL; - - if (!iosapic_register_intr) - return -ENODEV; - - /* - * ACPI is able to describe serial ports that live at non-standard - * memory addresses and use non-standard interrupts, either via - * direct SAPIC mappings or via PCI interrupts. We handle interrupt - * routing for SAPIC-based (non-PCI) devices here. Interrupt routing - * for PCI devices will be handled when processing the PCI Interrupt - * Routing Table (PRT). - */ - - spcr = (acpi_ser_t *) __va(phys_addr); - - setup_serial_acpi(spcr); - - if (spcr->length < sizeof(acpi_ser_t)) - /* Table not long enough for full info, thus no interrupt */ - return -ENODEV; - - if ((spcr->base_addr.space_id != ACPI_SERIAL_PCICONF_SPACE) && - (spcr->int_type == ACPI_SERIAL_INT_SAPIC)) - { - int vector; - - /* We have a UART in memory space with an SAPIC interrupt */ - - gsi = ( (spcr->global_int[3] << 24) | - (spcr->global_int[2] << 16) | - (spcr->global_int[1] << 8) | - (spcr->global_int[0]) ); - - vector = iosapic_register_intr(gsi, IOSAPIC_POL_HIGH, IOSAPIC_EDGE); - } - return 0; -} - -#endif /* CONFIG_SERIAL_8250_ACPI */ - - int __init acpi_boot_init (void) { @@ -681,16 +628,6 @@ */ if (acpi_table_parse(ACPI_FADT, acpi_parse_fadt) < 1) printk(KERN_ERR PREFIX "Can't find FADT\n"); - -#ifdef CONFIG_SERIAL_8250_ACPI - /* - * TBD: Need phased approach to table parsing (only do those absolutely - * required during boot-up). Recommend expanding concept of fix- - * feature devices (LDM) to include table-based devices such as - * serial ports, EC, SMBus, etc. - */ - acpi_table_parse(ACPI_SPCR, acpi_parse_spcr); -#endif #ifdef CONFIG_SMP smp_boot_data.cpu_count = available_cpus; diff -Nru a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c --- a/arch/ia64/kernel/efi.c Tue Jul 1 18:44:31 2003 +++ b/arch/ia64/kernel/efi.c Tue Jul 1 18:44:31 2003 @@ -46,7 +46,7 @@ * prior to creating their own entries under /proc/efi. */ #ifdef CONFIG_PROC_FS -struct proc_dir_entry *efi_dir = NULL; +struct proc_dir_entry *efi_dir; #endif static unsigned long mem_limit = ~0UL; diff -Nru a/arch/ia64/kernel/efivars.c b/arch/ia64/kernel/efivars.c --- a/arch/ia64/kernel/efivars.c Tue Jul 1 18:44:34 2003 +++ b/arch/ia64/kernel/efivars.c Tue Jul 1 18:44:34 2003 @@ -119,7 +119,7 @@ */ static spinlock_t efivars_lock = SPIN_LOCK_UNLOCKED; static LIST_HEAD(efivar_list); -static struct proc_dir_entry *efi_vars_dir = NULL; +static struct proc_dir_entry *efi_vars_dir; #define efivar_entry(n) list_entry(n, efivar_entry_t, list) diff -Nru a/arch/ia64/kernel/gate.S b/arch/ia64/kernel/gate.S --- a/arch/ia64/kernel/gate.S Tue Jul 1 18:44:37 2003 +++ b/arch/ia64/kernel/gate.S Tue Jul 1 18:44:37 2003 @@ -199,7 +199,7 @@ cmp.ne p8,p0=r15,r0 // do we need to switch the rbs? mov.m r9=ar.bsp // fetch ar.bsp .spillsp.p p8, ar.rnat, RNAT_OFF+SIGCONTEXT_OFF -(p8) br.cond.spnt setup_rbs // yup -> (clobbers r14, r15, and r16) +(p8) br.cond.spnt setup_rbs // yup -> (clobbers p8, r14-r16, and r18-r20) back_from_setup_rbs: alloc r8=ar.pfs,0,0,3,0 ld8 out0=[base0],16 // load arg0 (signum) @@ -268,26 +268,30 @@ setup_rbs: mov ar.rsc=0 // put RSE into enforced lazy mode ;; - .save ar.rnat, r16 - mov r16=ar.rnat // save RNaT before switching backing store area + .save ar.rnat, r19 + mov r19=ar.rnat // save RNaT before switching backing store area adds r14=(RNAT_OFF+SIGCONTEXT_OFF),sp + mov r18=ar.bspstore mov ar.bspstore=r15 // switch over to new register backing store area ;; + .spillsp ar.rnat, RNAT_OFF+SIGCONTEXT_OFF - st8 [r14]=r16 // save sc_ar_rnat + st8 [r14]=r19 // save sc_ar_rnat .body - adds r14=(LOADRS_OFF+SIGCONTEXT_OFF),sp - mov.m r16=ar.bsp // sc_loadrs <- (new bsp - new bspstore) << 16 + adds r14=(LOADRS_OFF+SIGCONTEXT_OFF),sp ;; invala sub r15=r16,r15 + extr.u r20=r18,3,6 ;; + mov ar.rsc=0xf // set RSE into eager mode, pl 3 + cmp.eq p8,p0=63,r20 shl r15=r15,16 ;; st8 [r14]=r15 // save sc_loadrs - mov ar.rsc=0xf // set RSE into eager mode, pl 3 +(p8) st8 [r18]=r19 // if bspstore points at RNaT slot, store RNaT there now .restore sp // pop .prologue br.cond.sptk back_from_setup_rbs diff -Nru a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S --- a/arch/ia64/kernel/head.S Tue Jul 1 18:44:36 2003 +++ b/arch/ia64/kernel/head.S Tue Jul 1 18:44:36 2003 @@ -144,13 +144,13 @@ movl r3=task_for_booting_cpu ;; ld8 r3=[r3] - movl r2=init_thread_union + movl r2=init_task ;; cmp.eq isBP,isAP=r3,r0 ;; (isAP) mov r2=r3 #else - movl r2=init_thread_union + movl r2=init_task cmp.eq isBP,isAP=r0,r0 #endif ;; diff -Nru a/arch/ia64/kernel/init_task.c b/arch/ia64/kernel/init_task.c --- a/arch/ia64/kernel/init_task.c Tue Jul 1 18:44:39 2003 +++ b/arch/ia64/kernel/init_task.c Tue Jul 1 18:44:39 2003 @@ -26,17 +26,17 @@ * We need to make sure that this is properly aligned due to the way process stacks are * handled. This is done by having a special ".data.init_task" section... */ -#define init_thread_info init_thread_union.s.thread_info +#define init_thread_info init_task_mem.s.thread_info -union init_thread { +static union { struct { struct task_struct task; struct thread_info thread_info; } s; unsigned long stack[KERNEL_STACK_SIZE/sizeof (unsigned long)]; -} init_thread_union __attribute__((section(".data.init_task"))) = {{ - .task = INIT_TASK(init_thread_union.s.task), - .thread_info = INIT_THREAD_INFO(init_thread_union.s.task) +} init_task_mem __attribute__((section(".data.init_task"))) = {{ + .task = INIT_TASK(init_task_mem.s.task), + .thread_info = INIT_THREAD_INFO(init_task_mem.s.task) }}; -asm (".global init_task; init_task = init_thread_union"); +asm (".global init_task; init_task = init_task_mem"); diff -Nru a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c --- a/arch/ia64/kernel/iosapic.c Tue Jul 1 18:44:35 2003 +++ b/arch/ia64/kernel/iosapic.c Tue Jul 1 18:44:35 2003 @@ -382,7 +382,7 @@ static void iosapic_ack_edge_irq (unsigned int irq) { - irq_desc_t *idesc = irq_desc(irq); + irq_desc_t *idesc = irq_descp(irq); /* * Once we have recorded IRQ_PENDING already, we can mask the * interrupt for real. This prevents IRQ storms from unhandled @@ -478,7 +478,7 @@ else irq_type = &irq_type_iosapic_level; - idesc = irq_desc(vector); + idesc = irq_descp(vector); if (idesc->handler != irq_type) { if (idesc->handler != &no_irq_type) printk(KERN_WARNING "%s: changing vector %d from %s to %s\n", @@ -724,7 +724,7 @@ * If vector was previously initialized to a different * handler, re-initialize. */ - idesc = irq_desc(vector); + idesc = irq_descp(vector); if (idesc->handler != irq_type) register_intr(gsi, vector, IOSAPIC_LOWEST_PRIORITY, IOSAPIC_POL_LOW, IOSAPIC_LEVEL); diff -Nru a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c --- a/arch/ia64/kernel/irq.c Tue Jul 1 18:44:37 2003 +++ b/arch/ia64/kernel/irq.c Tue Jul 1 18:44:37 2003 @@ -74,7 +74,7 @@ }; #ifdef CONFIG_IA64_GENERIC -struct irq_desc * __ia64_irq_desc (unsigned int irq) +irq_desc_t * __ia64_irq_desc (unsigned int irq) { return _irq_desc + irq; } @@ -171,7 +171,7 @@ seq_putc(p, '\n'); for (i = 0 ; i < NR_IRQS ; i++) { - idesc = irq_desc(i); + idesc = irq_descp(i); spin_lock_irqsave(&idesc->lock, flags); action = idesc->action; if (!action) @@ -218,7 +218,7 @@ #ifdef CONFIG_SMP inline void synchronize_irq(unsigned int irq) { - while (irq_desc(irq)->status & IRQ_INPROGRESS) + while (irq_descp(irq)->status & IRQ_INPROGRESS) cpu_relax(); } #endif @@ -352,7 +352,7 @@ inline void disable_irq_nosync(unsigned int irq) { - irq_desc_t *desc = irq_desc(irq); + irq_desc_t *desc = irq_descp(irq); unsigned long flags; spin_lock_irqsave(&desc->lock, flags); @@ -395,7 +395,7 @@ void enable_irq(unsigned int irq) { - irq_desc_t *desc = irq_desc(irq); + irq_desc_t *desc = irq_descp(irq); unsigned long flags; spin_lock_irqsave(&desc->lock, flags); @@ -437,7 +437,7 @@ * 0 return value means that this irq is already being * handled by some other CPU. (or is disabled) */ - irq_desc_t *desc = irq_desc(irq); + irq_desc_t *desc = irq_descp(irq); struct irqaction * action; irqreturn_t action_ret; unsigned int status; @@ -620,7 +620,7 @@ if (irq >= NR_IRQS) return; - desc = irq_desc(irq); + desc = irq_descp(irq); spin_lock_irqsave(&desc->lock,flags); p = &desc->action; for (;;) { @@ -682,7 +682,7 @@ * flush such a longstanding irq before considering it as spurious. */ for (i = NR_IRQS-1; i > 0; i--) { - desc = irq_desc(i); + desc = irq_descp(i); spin_lock_irq(&desc->lock); if (!desc->action) @@ -700,7 +700,7 @@ * happened in the previous stage, it may have masked itself) */ for (i = NR_IRQS-1; i > 0; i--) { - desc = irq_desc(i); + desc = irq_descp(i); spin_lock_irq(&desc->lock); if (!desc->action) { @@ -722,7 +722,7 @@ */ val = 0; for (i = 0; i < NR_IRQS; i++) { - irq_desc_t *desc = irq_desc(i); + irq_desc_t *desc = irq_descp(i); unsigned int status; spin_lock_irq(&desc->lock); @@ -762,7 +762,7 @@ mask = 0; for (i = 0; i < 16; i++) { - irq_desc_t *desc = irq_desc(i); + irq_desc_t *desc = irq_descp(i); unsigned int status; spin_lock_irq(&desc->lock); @@ -807,7 +807,7 @@ nr_irqs = 0; irq_found = 0; for (i = 0; i < NR_IRQS; i++) { - irq_desc_t *desc = irq_desc(i); + irq_desc_t *desc = irq_descp(i); unsigned int status; spin_lock_irq(&desc->lock); @@ -836,7 +836,7 @@ int shared = 0; unsigned long flags; struct irqaction *old, **p; - irq_desc_t *desc = irq_desc(irq); + irq_desc_t *desc = irq_descp(irq); if (desc->handler == &no_irq_type) return -ENOSYS; @@ -963,15 +963,16 @@ } static int irq_affinity_write_proc (struct file *file, const char *buffer, - unsigned long count, void *data) + unsigned long count, void *data) { unsigned int irq = (unsigned long) data; int full_count = count, err; unsigned long new_value; const char *buf = buffer; + irq_desc_t *desc = irq_descp(irq); int redir; - if (!irq_desc(irq)->handler->set_affinity) + if (!desc->handler->set_affinity) return -EIO; if (buf[0] == 'r' || buf[0] == 'R') { @@ -993,8 +994,7 @@ if (!(new_value & cpu_online_map)) return -EINVAL; - irq_desc(irq)->handler->set_affinity(irq | (redir? IA64_IRQ_REDIRECTED : 0), new_value); - + desc->handler->set_affinity(irq | (redir? IA64_IRQ_REDIRECTED : 0), new_value); return full_count; } @@ -1030,7 +1030,7 @@ { char name [MAX_NAMELEN]; - if (!root_irq_dir || (irq_desc(irq)->handler == &no_irq_type) || irq_dir[irq]) + if (!root_irq_dir || (irq_descp(irq)->handler == &no_irq_type) || irq_dir[irq]) return; memset(name, 0, MAX_NAMELEN); @@ -1083,7 +1083,7 @@ * Create entries for all existing IRQs. */ for (i = 0; i < NR_IRQS; i++) { - if (irq_desc(i)->handler == &no_irq_type) + if (irq_descp(i)->handler == &no_irq_type) continue; register_irq_proc(i); } diff -Nru a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c --- a/arch/ia64/kernel/irq_ia64.c Tue Jul 1 18:44:34 2003 +++ b/arch/ia64/kernel/irq_ia64.c Tue Jul 1 18:44:34 2003 @@ -162,7 +162,7 @@ for (irq = 0; irq < NR_IRQS; ++irq) if (irq_to_vector(irq) == vec) { - desc = irq_desc(irq); + desc = irq_descp(irq); desc->status |= IRQ_PER_CPU; desc->handler = &irq_type_ia64_lsapic; if (action) diff -Nru a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c --- a/arch/ia64/kernel/mca.c Tue Jul 1 18:44:35 2003 +++ b/arch/ia64/kernel/mca.c Tue Jul 1 18:44:35 2003 @@ -734,7 +734,7 @@ if (cpev >= 0) { for (irq = 0; irq < NR_IRQS; ++irq) if (irq_to_vector(irq) == cpev) { - desc = irq_desc(irq); + desc = irq_descp(irq); desc->status |= IRQ_PER_CPU; desc->handler = &irq_type_iosapic_level; setup_irq(irq, &mca_cpe_irqaction); diff -Nru a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c --- a/arch/ia64/kernel/perfmon.c Tue Jul 1 18:44:38 2003 +++ b/arch/ia64/kernel/perfmon.c Tue Jul 1 18:44:38 2003 @@ -115,6 +115,8 @@ #define PMD_IS_COUNTING(i) ((pmu_conf.pmd_desc[i].type & PFM_REG_COUNTING) == PFM_REG_COUNTING) #define PMC_IS_COUNTING(i) ((pmu_conf.pmc_desc[i].type & PFM_REG_COUNTING) == PFM_REG_COUNTING) #define PMC_IS_MONITOR(i) ((pmu_conf.pmc_desc[i].type & PFM_REG_MONITOR) == PFM_REG_MONITOR) +#define PMC_IS_CONTROL(i) ((pmu_conf.pmc_desc[i].type & PFM_REG_CONTROL) == PFM_REG_CONTROL) + #define PMC_DFL_VAL(i) pmu_conf.pmc_desc[i].default_value #define PMC_RSVD_MASK(i) pmu_conf.pmc_desc[i].reserved_mask #define PMD_PMD_DEP(i) pmu_conf.pmd_desc[i].dep_pmd[0] @@ -232,6 +234,8 @@ */ #define PMC0_HAS_OVFL(cmp0) (cmp0 & ~0x1UL) +#define PFMFS_MAGIC 0xa0b4d889 + /* * debugging */ @@ -328,7 +332,7 @@ pfm_counter_t ctx_pmds[IA64_NUM_PMD_REGS]; /* software state for PMDS */ - u64 ctx_saved_psr; /* copy of psr used for ctxsw */ + u64 ctx_saved_psr_up; /* only contains psr.up value */ unsigned long ctx_last_activation; /* context last activation number for last_cpu */ unsigned int ctx_last_cpu; /* CPU id of current or last CPU used (SMP only) */ @@ -560,100 +564,6 @@ close: pfm_vm_close }; -/* - * Linux 2.5 vs. 2.4 helper macros and definitions - * - * if not at least 2.5.69, then assume 2.4.x. - */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,69) - -#define PFM_COMPILED_FOR_2_4 1 - -#include - -#define pfm_get_cpu_var(v) local_cpu_data->v -#define pfm_get_cpu_data(a,b) cpu_data((b))->a -typedef void pfm_irq_handler_t; -#define PFM_IRQ_HANDLER_RET(v) - -#define DEFINE_PER_CPU(a,b) - -static inline int -pfm_wait_task_inactive(struct task_struct *task) -{ -#ifdef CONFIG_SMP - /* Make sure the child gets off its CPU.. */ - for (;;) { - task_lock(task); - if (!task_has_cpu(task)) break; - task_unlock(task); - do { - if (task->state != TASK_STOPPED) - return -ESRCH; - barrier(); - cpu_relax(); - } while (task_has_cpu(task)); - } - task_unlock(task); -#endif - return 0; -} - -static inline void -pfm_put_task(struct task_struct *task) -{ - if (task != current) free_task_struct(task); -} - -static inline void -pfm_set_task_notify(struct task_struct *task) -{ -} - -static inline void -pfm_clear_task_notify(void) -{ -} - -static inline void -pfm_reserve_page(unsigned long a) -{ - unsigned long page; - - page = ia64_tpa(a); - mem_map_reserve(virt_to_page(__va(page))); -} - -static inline void -pfm_unreserve_page(unsigned long a) -{ - unsigned long page; - - page = ia64_tpa(a); - mem_map_unreserve(virt_to_page(__va(page))); -} - -static inline int -pfm_remap_page_range(struct vm_area_struct *vma, unsigned long from, unsigned long phys_addr, unsigned long size, pgprot_t prot) -{ - return remap_page_range(from, phys_addr, size, prot); -} - -static inline unsigned long -pfm_protect_ctx_ctxsw(pfm_context_t *x) -{ - unsigned long f; - spin_lock(&(x)->ctx_lock); - return f; -} - -static inline unsigned long -pfm_unprotect_ctx_ctxsw(pfm_context_t *x, unsigned long f) -{ - spin_unlock(&(x)->ctx_lock); -} - -#else /* 2.5.69 or higher */ #define pfm_wait_task_inactive(t) wait_task_inactive(t) #define pfm_get_cpu_var(v) __get_cpu_var(v) @@ -705,7 +615,7 @@ static inline unsigned long pfm_protect_ctx_ctxsw(pfm_context_t *x) { - spin_lock_irq(&(x)->ctx_lock); + spin_lock(&(x)->ctx_lock); return 0UL; } @@ -715,7 +625,30 @@ spin_unlock(&(x)->ctx_lock); } -#endif /* 2.5 vs. 2.4 */ +static inline unsigned int +pfm_do_munmap(struct mm_struct *mm, unsigned long addr, size_t len, int acct) +{ + return do_munmap(mm, addr, len); +} + +static inline unsigned long +pfm_get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags, unsigned long exec) +{ + return get_unmapped_area(file, addr, len, pgoff, flags); +} + + +static struct super_block * +pfmfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) +{ + return get_sb_pseudo(fs_type, "pfm:", NULL, PFMFS_MAGIC); +} + +static struct file_system_type pfm_fs_type = { + .name = "pfmfs", + .get_sb = pfmfs_get_sb, + .kill_sb = kill_anon_super, +}; DEFINE_PER_CPU(unsigned long, pfm_syst_info); DEFINE_PER_CPU(struct task_struct *, pmu_owner); @@ -758,13 +691,13 @@ static inline void pfm_clear_psr_up(void) { - __asm__ __volatile__ ("rum psr.up;; srlz.i;;"::: "memory"); + __asm__ __volatile__ ("rsm psr.up;; srlz.i;;"::: "memory"); } static inline void pfm_set_psr_up(void) { - __asm__ __volatile__ ("sum psr.up;; srlz.i;;"::: "memory"); + __asm__ __volatile__ ("ssm psr.up;; srlz.i;;"::: "memory"); } static inline unsigned long @@ -1502,7 +1435,7 @@ DPRINT(("down_write done smpl_vaddr=%p size=%lu\n", vaddr, size)); - r = do_munmap(task->mm, (unsigned long)vaddr, size); + r = pfm_do_munmap(task->mm, (unsigned long)vaddr, size, 0); up_write(&task->mm->mmap_sem); if (r !=0) { @@ -1569,68 +1502,6 @@ * d_name - pfm: will go nicely and kill the special-casing in procfs. */ static struct vfsmount *pfmfs_mnt; -#define PFMFS_MAGIC 0xa0b4d889 - -#ifdef PFM_COMPILED_FOR_2_4 - -static int -pfmfs_statfs(struct super_block *sb, struct statfs *buf) -{ - buf->f_type = PFMFS_MAGIC; - buf->f_bsize = 1024; - buf->f_namelen = 255; - return 0; -} - -static struct super_operations pfmfs_ops = { - statfs: pfmfs_statfs, -}; - -static struct super_block * -pfmfs_read_super(struct super_block *sb, void *data, int silent) -{ - struct inode *root = new_inode(sb); - if (!root) - return NULL; - root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR; - root->i_uid = root->i_gid = 0; - root->i_atime = root->i_mtime = root->i_ctime = CURRENT_TIME; - sb->s_blocksize = 1024; - sb->s_blocksize_bits = 10; - sb->s_magic = PFMFS_MAGIC; - sb->s_op = &pfmfs_ops; - sb->s_root = d_alloc(NULL, &(const struct qstr) { "pfm:", 4, 0 }); - if (!sb->s_root) { - iput(root); - return NULL; - } - sb->s_root->d_sb = sb; - sb->s_root->d_parent = sb->s_root; - d_instantiate(sb->s_root, root); - return sb; -} - -//static DECLARE_FSTYPE(pfm_fs_type, "pfmfs", pfmfs_read_super, FS_NOMOUNT); -static struct file_system_type pfm_fs_type = { - name: "pfmfs", - read_super: pfmfs_read_super, - fs_flags: FS_NOMOUNT, -}; - -#else /* ! COMPILED_FOR_2_4 */ - -static struct super_block * -pfmfs_get_sb(struct file_system_type *fs_type, int flags, char *dev_name, void *data) -{ - return get_sb_pseudo(fs_type, "pfm:", NULL, PFMFS_MAGIC); -} - -static struct file_system_type pfm_fs_type = { - .name = "pfmfs", - .get_sb = pfmfs_get_sb, - .kill_sb = kill_anon_super, -}; -#endif /* COMPILED_FOR_2_4 */ static int __init init_pfm_fs(void) @@ -2453,7 +2324,7 @@ down_write(&task->mm->mmap_sem); /* find some free area in address space, must have mmap sem held */ - vma->vm_start = get_unmapped_area(NULL, 0, size, 0, MAP_PRIVATE|MAP_ANONYMOUS); + vma->vm_start = pfm_get_unmapped_area(NULL, 0, size, 0, MAP_PRIVATE|MAP_ANONYMOUS, 0); if (vma->vm_start == 0UL) { DPRINT(("Cannot find unmapped area for size %ld\n", size)); up_write(&task->mm->mmap_sem); @@ -3020,7 +2891,7 @@ * as attempts to modify PMC[0-3] which are used * as status registers by the PMU */ - if (!PMC_IS_IMPL(cnum) || cnum < 4) { + if (PMC_IS_IMPL(cnum) == 0 || PMC_IS_CONTROL(cnum)) { DPRINT(("pmc%u is unimplemented or invalid\n", cnum)); goto error; } @@ -4124,7 +3995,7 @@ /* * monitoring disabled in kernel at next reschedule */ - ctx->ctx_saved_psr &= ~IA64_PSR_UP; + ctx->ctx_saved_psr_up = 0; printk("pfm_stop: current [%d] task=[%d]\n", current->pid, ctx->ctx_task->pid); } return 0; @@ -4198,7 +4069,7 @@ * start monitoring at the kernel level the next * time the task is scheduled */ - ctx->ctx_saved_psr |= IA64_PSR_UP; + ctx->ctx_saved_psr_up = IA64_PSR_UP; /* * activate monitoring at user level @@ -4429,7 +4300,7 @@ SET_LAST_CPU(ctx, -1); /* initial saved psr (stopped) */ - ctx->ctx_saved_psr = pfm_get_psr() & ~(IA64_PSR_PP|IA64_PSR_UP); + ctx->ctx_saved_psr_up = 0UL; ia64_psr(regs)->up = ia64_psr(regs)->pp = 0; if (ctx->ctx_fl_unsecure) { @@ -5640,6 +5511,7 @@ unsigned long flags; u64 psr; + ctx = PFM_GET_CTX(task); if (ctx == NULL) goto save_error; t = &task->thread; @@ -5672,9 +5544,9 @@ * sanity check */ if (ctx->ctx_last_activation != GET_ACTIVATION()) { - DPRINT(("ctx_activation=%lu activation=%lu state=%d: no save\n", + printk("ctx_activation=%lu activation=%lu state=%d: no save\n", ctx->ctx_last_activation, - GET_ACTIVATION(), ctx->ctx_state)); + GET_ACTIVATION(), ctx->ctx_state); pfm_unprotect_ctx_ctxsw(ctx, flags); @@ -5684,8 +5556,11 @@ /* * save current PSR: needed because we modify it */ + ia64_srlz_d(); psr = pfm_get_psr(); + BUG_ON(psr & (IA64_PSR_I)); + /* * stop monitoring: * This is the last instruction which may generate an overflow @@ -5696,9 +5571,13 @@ pfm_clear_psr_up(); /* - * keep a copy of the saved psr (for reload) + * keep a copy of psr.up (for reload) */ - ctx->ctx_saved_psr = psr; + ctx->ctx_saved_psr_up = psr & IA64_PSR_UP; + + { u64 foo = pfm_get_psr(); + BUG_ON(foo & ((IA64_PSR_UP|IA64_PSR_PP))); + } /* * release ownership of this PMU. @@ -5772,18 +5651,16 @@ pfm_clear_psr_up(); /* - * keep a copy of the saved psr (for reload) + * keep a copy of psr.up (for reload) */ - ctx->ctx_saved_psr = psr; + ctx->ctx_saved_psr_up = psr & IA64_PSR_UP; - psr = pfm_get_psr(); - if (psr & IA64_PSR_UP) { - printk(KERN_ERR " perfmon: pfm_save_regs: psr.up set current [%d] owner [%d] psr=0x%lx\n", current->pid, GET_PMU_OWNER()->pid, psr); - } - if (psr & IA64_PSR_I) { - printk(KERN_ERR " perfmon: pfm_save_regs: psr.i set current [%d] owner [%d] psr=0x%lx\n", current->pid, GET_PMU_OWNER()->pid, psr); +#if 1 + { u64 foo = pfm_get_psr(); + BUG_ON(foo & (IA64_PSR_I)); + BUG_ON(foo & ((IA64_PSR_UP|IA64_PSR_PP))); } - +#endif return; save_error: printk(KERN_ERR "perfmon: pfm_save_regs CPU%d [%d] NULL context PM_VALID=%ld\n", @@ -5797,13 +5674,10 @@ pfm_context_t *ctx; struct thread_struct *t; unsigned long flags; - unsigned long psr; #if 1 - psr = pfm_get_psr(); - if (psr & IA64_PSR_UP) { - printk(KERN_ERR " perfmon: pfm_lazy_save_regs: psr.up set current [%d] owner [%d] psr=0x%lx\n", current->pid, task->pid, psr); - pfm_clear_psr_up(); + { u64 foo = pfm_get_psr(); + BUG_ON(foo & IA64_PSR_UP); } #endif @@ -5864,10 +5738,9 @@ { pfm_context_t *ctx; struct thread_struct *t; - struct task_struct *owner; unsigned long pmc_mask = 0UL, pmd_mask = 0UL; unsigned long flags; - u64 psr; + u64 psr, psr_up; ctx = PFM_GET_CTX(task); if (unlikely(ctx == NULL)) { @@ -5875,22 +5748,21 @@ return; } - owner = GET_PMU_OWNER(); + BUG_ON(GET_PMU_OWNER()); + t = &task->thread; + psr = pfm_get_psr(); #if 1 - psr = pfm_get_psr(); - BUG_ON(psr & IA64_PSR_UP); - psr = pfm_get_psr(); + BUG_ON(psr & (IA64_PSR_UP|IA64_PSR_PP)); BUG_ON(psr & IA64_PSR_I); #endif - /* * possible on unload */ if (unlikely((t->flags & IA64_THREAD_PM_VALID) == 0)) { - DPRINT(("[%d] PM_VALID=0, nothing to do\n", task->pid)); + printk("[%d] PM_VALID=0, nothing to do\n", task->pid); return; } @@ -5923,19 +5795,15 @@ /* * we restore ALL the debug registers to avoid picking up * stale state. - * - * This must be done even when the task is still the owner - * as the registers may have been modified via ptrace() - * (not perfmon) by the previous task. */ if (ctx->ctx_fl_using_dbreg) { pfm_restore_ibrs(ctx->ctx_ibrs, pmu_conf.num_ibrs); pfm_restore_dbrs(ctx->ctx_dbrs, pmu_conf.num_dbrs); } /* - * retrieve saved psr + * retrieve saved psr.up */ - psr = ctx->ctx_saved_psr; + psr_up = ctx->ctx_saved_psr_up; /* * if we were the last user of the PMU on that CPU, @@ -5968,8 +5836,8 @@ */ pmc_mask = ctx->ctx_all_pmcs[0]; - DPRINT(("full reload for [%d] owner=%d activation=%lu last_activation=%lu last_cpu=%d pmd_mask=0x%lx pmc_mask=0x%lx\n", - task->pid, owner ? owner->pid : -1, + DPRINT(("full reload for [%d] activation=%lu last_activation=%lu last_cpu=%d pmd_mask=0x%lx pmc_mask=0x%lx\n", + task->pid, GET_ACTIVATION(), ctx->ctx_last_activation, GET_LAST_CPU(ctx), pmd_mask, pmc_mask)); @@ -6026,9 +5894,9 @@ SET_PMU_OWNER(task, ctx); /* - * restore the psr we changed + * restore the psr.up bit */ - pfm_set_psr_l(psr); + if (likely(psr_up)) pfm_set_psr_up(); /* * allow concurrent access to context @@ -6047,21 +5915,16 @@ pfm_context_t *ctx; struct task_struct *owner; unsigned long pmd_mask, pmc_mask; - u64 psr; + u64 psr, psr_up; - owner = GET_PMU_OWNER(); - ctx = PFM_GET_CTX(task); - t = &task->thread; + owner = GET_PMU_OWNER(); + ctx = PFM_GET_CTX(task); + t = &task->thread; + psr = pfm_get_psr(); #if 1 - psr = pfm_get_psr(); - if (psr & IA64_PSR_UP) { - printk(KERN_ERR " perfmon: pfm_load_regs: psr.up set current [%d] owner [%d] psr=0x%lx\n", current->pid, owner->pid, psr); - } - psr = pfm_get_psr(); - if (psr & IA64_PSR_I) { - printk(KERN_ERR " perfmon: pfm_load_regs: psr.i set current [%d] owner [%d] psr=0x%lx\n", current->pid, owner->pid, psr); - } + BUG_ON(psr & (IA64_PSR_UP|IA64_PSR_PP)); + BUG_ON(psr & IA64_PSR_I); #endif /* @@ -6078,9 +5941,9 @@ } /* - * retrieved save psr + * retrieved saved psr.up */ - psr = ctx->ctx_saved_psr; + psr_up = ctx->ctx_saved_psr_up; /* * short path, our state is still there, just @@ -6091,7 +5954,7 @@ * concurrency even without interrupt masking. */ if (likely(owner == task)) { - pfm_set_psr_l(psr); + if (likely(psr_up)) pfm_set_psr_up(); return; } @@ -6163,8 +6026,7 @@ * restore the psr. This is the point at which * new overflow interrupts can be generated again. */ - pfm_set_psr_l(psr); - + if (likely(psr_up)) pfm_set_psr_up(); } #endif /* CONFIG_SMP */ @@ -6469,13 +6331,13 @@ printk("pmd[%d]=0x%lx tpmd=0x%lx\n", i, ia64_get_pmd(i), t->pmds[i]); } if (ctx) { - printk("ctx_state=%d vaddr=%p addr=%p fd=%d ctx_task=[%d] saved_psr=0x%lx\n", + printk("ctx_state=%d vaddr=%p addr=%p fd=%d ctx_task=[%d] saved_psr_up=0x%lx\n", ctx->ctx_state, ctx->ctx_smpl_vaddr, ctx->ctx_smpl_hdr, ctx->ctx_msgq_head, ctx->ctx_msgq_tail, - ctx->ctx_saved_psr); + ctx->ctx_saved_psr_up); } } diff -Nru a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c --- a/arch/ia64/kernel/smpboot.c Tue Jul 1 18:44:33 2003 +++ b/arch/ia64/kernel/smpboot.c Tue Jul 1 18:44:33 2003 @@ -452,7 +452,7 @@ sapicid = smp_boot_data.cpu_phys_id[i]; if (sapicid == boot_cpu_id) continue; - phys_cpu_present_map |= (1 << cpu); + phys_cpu_present_map |= (1UL << cpu); ia64_cpu_to_sapicid[cpu] = sapicid; cpu++; } diff -Nru a/arch/ia64/lib/Makefile b/arch/ia64/lib/Makefile --- a/arch/ia64/lib/Makefile Tue Jul 1 18:44:38 2003 +++ b/arch/ia64/lib/Makefile Tue Jul 1 18:44:38 2003 @@ -12,12 +12,7 @@ lib-$(CONFIG_ITANIUM) += copy_page.o copy_user.o memcpy.o lib-$(CONFIG_MCKINLEY) += copy_page_mck.o memcpy_mck.o lib-$(CONFIG_PERFMON) += carta_random.o - -ifeq ($(CONFIG_MD_RAID5),m) - lib-y += xor.o -else - lib-$(CONFIG_MD_RAID5) += xor.o -endif +lib-$(CONFIG_MD_RAID5) += xor.o IGNORE_FLAGS_OBJS = __divsi3.o __udivsi3.o __modsi3.o __umodsi3.o \ __divdi3.o __udivdi3.o __moddi3.o __umoddi3.o diff -Nru a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c --- a/arch/ia64/pci/pci.c Tue Jul 1 18:44:34 2003 +++ b/arch/ia64/pci/pci.c Tue Jul 1 18:44:34 2003 @@ -53,21 +53,21 @@ * synchronization mechanism here. */ -#define PCI_SAL_ADDRESS(seg, bus, dev, fn, reg) \ +#define PCI_SAL_ADDRESS(seg, bus, devfn, reg) \ ((u64)(seg << 24) | (u64)(bus << 16) | \ - (u64)(dev << 11) | (u64)(fn << 8) | (u64)(reg)) + (u64)(devfn << 8) | (u64)(reg)) static int -pci_sal_read (int seg, int bus, int dev, int fn, int reg, int len, u32 *value) +pci_sal_read (int seg, int bus, int devfn, int reg, int len, u32 *value) { int result = 0; u64 data = 0; - if (!value || (seg > 255) || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) + if (!value || (seg > 255) || (bus > 255) || (devfn > 255) || (reg > 255)) return -EINVAL; - result = ia64_sal_pci_config_read(PCI_SAL_ADDRESS(seg, bus, dev, fn, reg), len, &data); + result = ia64_sal_pci_config_read(PCI_SAL_ADDRESS(seg, bus, devfn, reg), len, &data); *value = (u32) data; @@ -75,12 +75,12 @@ } static int -pci_sal_write (int seg, int bus, int dev, int fn, int reg, int len, u32 value) +pci_sal_write (int seg, int bus, int devfn, int reg, int len, u32 value) { - if ((seg > 255) || (bus > 255) || (dev > 31) || (fn > 7) || (reg > 255)) + if ((seg > 255) || (bus > 255) || (devfn > 255) || (reg > 255)) return -EINVAL; - return ia64_sal_pci_config_write(PCI_SAL_ADDRESS(seg, bus, dev, fn, reg), len, value); + return ia64_sal_pci_config_write(PCI_SAL_ADDRESS(seg, bus, devfn, reg), len, value); } struct pci_raw_ops pci_sal_ops = { @@ -95,14 +95,14 @@ pci_read (struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) { return raw_pci_ops->read(pci_domain_nr(bus), bus->number, - PCI_SLOT(devfn), PCI_FUNC(devfn), where, size, value); + devfn, where, size, value); } static int pci_write (struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) { return raw_pci_ops->write(pci_domain_nr(bus), bus->number, - PCI_SLOT(devfn), PCI_FUNC(devfn), where, size, value); + devfn, where, size, value); } static struct pci_ops pci_root_ops = { @@ -284,21 +284,21 @@ } struct pci_bus * -pcibios_scan_root (void *handle, int seg, int bus) +pci_acpi_scan_root (struct acpi_device *device, int domain, int bus) { struct pci_root_info info; struct pci_controller *controller; unsigned int windows = 0; char *name; - printk("PCI: Probing PCI hardware on bus (%02x:%02x)\n", seg, bus); - controller = alloc_pci_controller(seg); + printk("PCI: Probing PCI hardware on bus (%04x:%02x)\n", domain, bus); + controller = alloc_pci_controller(domain); if (!controller) goto out1; - controller->acpi_handle = handle; + controller->acpi_handle = device->handle; - acpi_walk_resources(handle, METHOD_NAME__CRS, count_window, &windows); + acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window, &windows); controller->window = kmalloc(sizeof(*controller->window) * windows, GFP_KERNEL); if (!controller->window) goto out2; @@ -307,10 +307,10 @@ if (!name) goto out3; - sprintf(name, "PCI Bus %02x:%02x", seg, bus); + sprintf(name, "PCI Bus %04x:%02x", domain, bus); info.controller = controller; info.name = name; - acpi_walk_resources(handle, METHOD_NAME__CRS, add_window, &info); + acpi_walk_resources(device->handle, METHOD_NAME__CRS, add_window, &info); return scan_root_bus(bus, &pci_root_ops, controller); @@ -363,8 +363,6 @@ return; } - -#warning pcibios_update_resource() is now a generic implementation - please check void __devinit pcibios_update_irq (struct pci_dev *dev, int irq) diff -Nru a/arch/ia64/scripts/toolchain-flags b/arch/ia64/scripts/toolchain-flags --- a/arch/ia64/scripts/toolchain-flags Tue Jul 1 18:44:38 2003 +++ b/arch/ia64/scripts/toolchain-flags Tue Jul 1 18:44:38 2003 @@ -3,15 +3,13 @@ # Check whether linker can handle cross-segment @segrel(): # CC=$1 -LD=$2 -OBJDUMP=$3 +OBJDUMP=$2 dir=$(dirname $0) tmp=${TMPDIR:-/tmp} out=$tmp/out$$ -$CC -c $dir/check-segrel.S -o $out.o -$LD -static -T$dir/check-segrel.lds $out.o -o $out +$CC -nostdlib -static -Wl,-T$dir/check-segrel.lds $dir/check-segrel.S -o $out res=$($OBJDUMP --full --section .rodata $out | fgrep 000 | cut -f3 -d' ') -rm -f $out $out.o +rm -f $out if [ $res != 00000a00 ]; then echo " -DHAVE_BUGGY_SEGREL" cat >&2 < -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define SGI_IFCONFIG_NET "SGI-PERSISTENT NETWORK DEVICE NAME DRIVER" -#define SGI_IFCONFIG_NET_VERSION "1.0" - -/* - * Some Global definitions. - */ -static devfs_handle_t ifconfig_net_handle; -static unsigned long ifconfig_net_debug; - -/* - * ifconfig_net_open - Opens the special device node "/devhw/.ifconfig_net". - */ -static int ifconfig_net_open(struct inode * inode, struct file * filp) -{ - if (ifconfig_net_debug) { - printk("ifconfig_net_open called.\n"); - } - - return(0); - -} - -/* - * ifconfig_net_close - Closes the special device node "/devhw/.ifconfig_net". - */ -static int ifconfig_net_close(struct inode * inode, struct file * filp) -{ - - if (ifconfig_net_debug) { - printk("ifconfig_net_close called.\n"); - } - - return(0); -} - -/* - * assign_ifname - Assign the next available interface name from the persistent list. - */ -void -assign_ifname(struct net_device *dev, - struct ifname_num *ifname_num) - -{ - - /* - * Handle eth devices. - */ - if ( (memcmp(dev->name, "eth", 3) == 0) ) { - if (ifname_num->next_eth != -1) { - /* - * Assign it the next available eth interface number. - */ - memset(dev->name, 0, strlen(dev->name)); - sprintf(dev->name, "eth%d", (int)ifname_num->next_eth); - ifname_num->next_eth++; - } - - return; - } - - /* - * Handle fddi devices. - */ - if ( (memcmp(dev->name, "fddi", 4) == 0) ) { - if (ifname_num->next_fddi != -1) { - /* - * Assign it the next available fddi interface number. - */ - memset(dev->name, 0, strlen(dev->name)); - sprintf(dev->name, "fddi%d", (int)ifname_num->next_fddi); - ifname_num->next_fddi++; - } - - return; - } - - /* - * Handle hip devices. - */ - if ( (memcmp(dev->name, "hip", 3) == 0) ) { - if (ifname_num->next_hip != -1) { - /* - * Assign it the next available hip interface number. - */ - memset(dev->name, 0, strlen(dev->name)); - sprintf(dev->name, "hip%d", (int)ifname_num->next_hip); - ifname_num->next_hip++; - } - - return; - } - - /* - * Handle tr devices. - */ - if ( (memcmp(dev->name, "tr", 2) == 0) ) { - if (ifname_num->next_tr != -1) { - /* - * Assign it the next available tr interface number. - */ - memset(dev->name, 0, strlen(dev->name)); - sprintf(dev->name, "tr%d", (int)ifname_num->next_tr); - ifname_num->next_tr++; - } - - return; - } - - /* - * Handle fc devices. - */ - if ( (memcmp(dev->name, "fc", 2) == 0) ) { - if (ifname_num->next_fc != -1) { - /* - * Assign it the next available fc interface number. - */ - memset(dev->name, 0, strlen(dev->name)); - sprintf(dev->name, "fc%d", (int)ifname_num->next_fc); - ifname_num->next_fc++; - } - - return; - } -} - -/* - * find_persistent_ifname: Returns the entry that was seen in previous boot. - */ -struct ifname_MAC * -find_persistent_ifname(struct net_device *dev, - struct ifname_MAC *ifname_MAC) - -{ - - while (ifname_MAC->addr_len) { - if (memcmp(dev->dev_addr, ifname_MAC->dev_addr, dev->addr_len) == 0) - return(ifname_MAC); - - ifname_MAC++; - } - - return(NULL); -} - -/* - * ifconfig_net_ioctl: ifconfig_net driver ioctl interface. - */ -static int ifconfig_net_ioctl(struct inode * inode, struct file * file, - unsigned int cmd, unsigned long arg) -{ - - extern struct net_device *__dev_get_by_name(const char *); -#ifdef CONFIG_NET - struct net_device *dev; - struct ifname_MAC *found; - char temp[64]; -#endif - struct ifname_MAC *ifname_MAC; - struct ifname_MAC *new_devices, *temp_new_devices; - struct ifname_num *ifname_num; - unsigned long size; - - - if (ifconfig_net_debug) { - printk("HCL: hcl_ioctl called.\n"); - } - - /* - * Read in the header and see how big of a buffer we really need to - * allocate. - */ - ifname_num = (struct ifname_num *) kmalloc(sizeof(struct ifname_num), - GFP_KERNEL); - copy_from_user( ifname_num, (char *) arg, sizeof(struct ifname_num)); - size = ifname_num->size; - kfree(ifname_num); - ifname_num = (struct ifname_num *) kmalloc(size, GFP_KERNEL); - ifname_MAC = (struct ifname_MAC *) ((char *)ifname_num + (sizeof(struct ifname_num)) ); - - copy_from_user( ifname_num, (char *) arg, size); - new_devices = kmalloc(size - sizeof(struct ifname_num), GFP_KERNEL); - temp_new_devices = new_devices; - - memset(new_devices, 0, size - sizeof(struct ifname_num)); - -#ifdef CONFIG_NET - /* - * Go through the net device entries and make them persistent! - */ - for (dev = dev_base; dev != NULL; dev = dev->next) { - /* - * Skip NULL entries or "lo" - */ - if ( (dev->addr_len == 0) || ( !strncmp(dev->name, "lo", strlen(dev->name))) ){ - continue; - } - - /* - * See if we have a persistent interface name for this device. - */ - found = NULL; - found = find_persistent_ifname(dev, ifname_MAC); - if (found) { - strcpy(dev->name, found->name); - } else { - /* Never seen this before .. */ - assign_ifname(dev, ifname_num); - - /* - * Save the information for the next boot. - */ - sprintf(temp,"%s %02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, - dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], - dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); - strcpy(temp_new_devices->name, dev->name); - temp_new_devices->addr_len = dev->addr_len; - memcpy(temp_new_devices->dev_addr, dev->dev_addr, dev->addr_len); - temp_new_devices++; - } - - } -#endif - - /* - * Copy back to the User Buffer area any new devices encountered. - */ - copy_to_user((char *)arg + (sizeof(struct ifname_num)), new_devices, - size - sizeof(struct ifname_num)); - - return(0); - -} - -struct file_operations ifconfig_net_fops = { - ioctl:ifconfig_net_ioctl, /* ioctl */ - open:ifconfig_net_open, /* open */ - release:ifconfig_net_close /* release */ -}; - - -/* - * init_ifconfig_net() - Boot time initialization. Ensure that it is called - * after devfs has been initialized. - * - */ -#ifdef MODULE -int init_module (void) -#else -int __init init_ifconfig_net(void) -#endif -{ - ifconfig_net_handle = NULL; - ifconfig_net_handle = hwgraph_register(hwgraph_root, ".ifconfig_net", - 0, 0, - 0, 0, - S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0, - &ifconfig_net_fops, NULL); - - if (ifconfig_net_handle == NULL) { - panic("Unable to create SGI PERSISTENT NETWORK DEVICE Name Driver.\n"); - } - - return(0); - -} diff -Nru a/arch/ia64/sn/io/hwgfs/hcl.c b/arch/ia64/sn/io/hwgfs/hcl.c --- a/arch/ia64/sn/io/hwgfs/hcl.c Tue Jul 1 18:44:35 2003 +++ b/arch/ia64/sn/io/hwgfs/hcl.c Tue Jul 1 18:44:35 2003 @@ -113,22 +113,10 @@ } struct file_operations hcl_fops = { - (struct module *)0, - NULL, /* lseek - default */ - NULL, /* read - general block-dev read */ - NULL, /* write - general block-dev write */ - NULL, /* readdir - bad */ - NULL, /* poll */ - hcl_ioctl, /* ioctl */ - NULL, /* mmap */ - hcl_open, /* open */ - NULL, /* flush */ - hcl_close, /* release */ - NULL, /* fsync */ - NULL, /* fasync */ - NULL, /* lock */ - NULL, /* readv */ - NULL, /* writev */ + .owner = (struct module *)0, + .ioctl = hcl_ioctl, + .open = hcl_open, + .release = hcl_close, }; @@ -140,7 +128,6 @@ { extern void string_table_init(struct string_table *); extern struct string_table label_string_table; - extern int init_ifconfig_net(void); extern int init_ioconfig_bus(void); extern int init_hwgfs_fs(void); int rv = 0; @@ -195,7 +182,6 @@ * Initialize the ifconfgi_net driver that does network devices * Persistent Naming. */ - init_ifconfig_net(); init_ioconfig_bus(); return(0); @@ -258,6 +244,7 @@ if (!de) { printk(KERN_WARNING "HCL: hwgraph_fastinfo_get handle given is NULL.\n"); + dump_stack(); return(-1); } @@ -568,7 +555,7 @@ * In this case the vertex was previous created with a REAL pathname. */ rv = hwgfs_mk_symlink (from, (const char *)name, - DEVFS_FL_DEFAULT, link, + 0, link, &handle, NULL); kfree(path); kfree(link); diff -Nru a/arch/ia64/sn/io/machvec/pci.c b/arch/ia64/sn/io/machvec/pci.c --- a/arch/ia64/sn/io/machvec/pci.c Tue Jul 1 18:44:33 2003 +++ b/arch/ia64/sn/io/machvec/pci.c Tue Jul 1 18:44:33 2003 @@ -49,6 +49,8 @@ vertex_hdl_t device_vertex; device_vertex = devfn_to_vertex(bus->number, devfn); + if (!device_vertex) + return PCIBIOS_DEVICE_NOT_FOUND; res = pciio_config_get(device_vertex, (unsigned) where, size); *val = (unsigned int) res; return PCIBIOS_SUCCESSFUL; @@ -59,6 +61,8 @@ vertex_hdl_t device_vertex; device_vertex = devfn_to_vertex(bus->number, devfn); + if (!device_vertex) + return PCIBIOS_DEVICE_NOT_FOUND; pciio_config_set( device_vertex, (unsigned)where, size, (uint64_t) val); return PCIBIOS_SUCCESSFUL; } diff -Nru a/arch/ia64/sn/io/machvec/pci_dma.c b/arch/ia64/sn/io/machvec/pci_dma.c --- a/arch/ia64/sn/io/machvec/pci_dma.c Tue Jul 1 18:44:34 2003 +++ b/arch/ia64/sn/io/machvec/pci_dma.c Tue Jul 1 18:44:34 2003 @@ -280,7 +280,7 @@ */ for (i = 0; i < nents; i++, sg++) { phys_addr = __pa(sg->dma_address ? sg->dma_address : - page_address(sg->page) + sg->offset); + (unsigned long)page_address(sg->page) + sg->offset); /* * Handle the most common case: 64 bit cards. This @@ -578,7 +578,7 @@ { BUG_ON(dev->bus != &pci_bus_type); - return pci_dma_supported(to_pci_dev(dev), mask); + return sn_pci_dma_supported(to_pci_dev(dev), mask); } EXPORT_SYMBOL(sn_dma_supported); @@ -587,7 +587,11 @@ { BUG_ON(dev->bus != &pci_bus_type); - return pci_set_dma_mask(to_pci_dev(dev), dma_mask); + if (!sn_dma_supported(dev, dma_mask)) + return 0; + + dev->dma_mask = dma_mask; + return 1; } EXPORT_SYMBOL(sn_dma_set_mask); @@ -597,7 +601,7 @@ { BUG_ON(dev->bus != &pci_bus_type); - return pci_alloc_consistent(to_pci_dev(dev), size, dma_handle); + return sn_pci_alloc_consistent(to_pci_dev(dev), size, dma_handle); } EXPORT_SYMBOL(sn_dma_alloc_coherent); @@ -607,7 +611,7 @@ { BUG_ON(dev->bus != &pci_bus_type); - pci_free_consistent(to_pci_dev(dev), size, cpu_addr, dma_handle); + sn_pci_free_consistent(to_pci_dev(dev), size, cpu_addr, dma_handle); } EXPORT_SYMBOL(sn_dma_free_coherent); @@ -617,7 +621,7 @@ { BUG_ON(dev->bus != &pci_bus_type); - return pci_map_single(to_pci_dev(dev), cpu_addr, size, (int)direction); + return sn_pci_map_single(to_pci_dev(dev), cpu_addr, size, (int)direction); } EXPORT_SYMBOL(sn_dma_map_single); @@ -627,7 +631,7 @@ { BUG_ON(dev->bus != &pci_bus_type); - pci_unmap_single(to_pci_dev(dev), dma_addr, size, (int)direction); + sn_pci_unmap_single(to_pci_dev(dev), dma_addr, size, (int)direction); } EXPORT_SYMBOL(sn_dma_unmap_single); @@ -658,7 +662,7 @@ { BUG_ON(dev->bus != &pci_bus_type); - return pci_map_sg(to_pci_dev(dev), sg, nents, (int)direction); + return sn_pci_map_sg(to_pci_dev(dev), sg, nents, (int)direction); } EXPORT_SYMBOL(sn_dma_map_sg); @@ -668,7 +672,7 @@ { BUG_ON(dev->bus != &pci_bus_type); - pci_unmap_sg(to_pci_dev(dev), sg, nhwentries, (int)direction); + sn_pci_unmap_sg(to_pci_dev(dev), sg, nhwentries, (int)direction); } EXPORT_SYMBOL(sn_dma_unmap_sg); @@ -678,7 +682,7 @@ { BUG_ON(dev->bus != &pci_bus_type); - pci_dma_sync_single(to_pci_dev(dev), dma_handle, size, (int)direction); + sn_pci_dma_sync_single(to_pci_dev(dev), dma_handle, size, (int)direction); } EXPORT_SYMBOL(sn_dma_sync_single); @@ -688,7 +692,7 @@ { BUG_ON(dev->bus != &pci_bus_type); - pci_dma_sync_sg(to_pci_dev(dev), sg, nelems, (int)direction); + sn_pci_dma_sync_sg(to_pci_dev(dev), sg, nelems, (int)direction); } EXPORT_SYMBOL(sn_dma_sync_sg); diff -Nru a/arch/ia64/sn/kernel/Makefile b/arch/ia64/sn/kernel/Makefile --- a/arch/ia64/sn/kernel/Makefile Tue Jul 1 18:44:32 2003 +++ b/arch/ia64/sn/kernel/Makefile Tue Jul 1 18:44:32 2003 @@ -9,7 +9,8 @@ EXTRA_CFLAGS := -DLITTLE_ENDIAN -obj-y := probe.o setup.o sv.o bte.o irq.o mca.o sn2/ +obj-y := probe.o setup.o sv.o bte.o irq.o mca.o \ + idle.o sn2/ obj-$(CONFIG_IA64_GENERIC) += machvec.o obj-$(CONFIG_MODULES) += sn_ksyms.o diff -Nru a/arch/ia64/sn/kernel/idle.c b/arch/ia64/sn/kernel/idle.c --- a/arch/ia64/sn/kernel/idle.c Tue Jul 1 18:44:39 2003 +++ b/arch/ia64/sn/kernel/idle.c Tue Jul 1 18:44:39 2003 @@ -12,7 +12,7 @@ void snidle(int state) { if (state) { - if (pda.idle_flag == 0) { + if (pda->idle_flag == 0) { /* * Turn the activity LED off. */ @@ -24,13 +24,13 @@ SIMULATOR_SLEEP(); #endif - pda.idle_flag = 1; + pda->idle_flag = 1; } else { /* * Turn the activity LED on. */ set_led_bits(LED_CPU_ACTIVITY, LED_CPU_ACTIVITY); - pda.idle_flag = 0; + pda->idle_flag = 0; } } diff -Nru a/arch/ia64/sn/kernel/machvec.c b/arch/ia64/sn/kernel/machvec.c --- a/arch/ia64/sn/kernel/machvec.c Tue Jul 1 18:44:35 2003 +++ b/arch/ia64/sn/kernel/machvec.c Tue Jul 1 18:44:35 2003 @@ -31,4 +31,5 @@ */ #define MACHVEC_PLATFORM_NAME sn2 +#define MACHVEC_PLATFORM_HEADER #include diff -Nru a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c --- a/arch/ia64/sn/kernel/setup.c Tue Jul 1 18:44:33 2003 +++ b/arch/ia64/sn/kernel/setup.c Tue Jul 1 18:44:33 2003 @@ -75,11 +75,13 @@ #define pxm_to_nasid(pxm) ((pxm)<<1) +#define MAX_PHYS_MEMORY (1UL << 49) /* 1 TB */ + extern void bte_init_node (nodepda_t *, cnodeid_t); extern void bte_init_cpu (void); -extern void sn_timer_init (void); +extern void sn_timer_init(void); extern void (*ia64_mark_idle)(int); -void snidle(int); +extern void snidle(int); unsigned long sn_rtc_cycles_per_second; @@ -296,21 +298,20 @@ */ sn_check_for_wars(); + ia64_mark_idle = &snidle; + /* * For the bootcpu, we do this here. All other cpus will make the * call as part of cpu_init in slave cpu initialization. */ sn_cpu_init(); - #ifdef CONFIG_SMP init_smp_config(); #endif screen_info = sn_screen_info; sn_timer_init(); - - ia64_mark_idle = &snidle; } /** @@ -437,20 +438,4 @@ } bte_init_cpu(); -} - -void snidle(int idleness) -{ - if (!idleness) { - if (pda->idle_flag == 0) { - set_led_bits(0, LED_CPU_ACTIVITY); - } - - pda->idle_flag = 1; - } - else { - set_led_bits(LED_CPU_ACTIVITY, LED_CPU_ACTIVITY); - - pda->idle_flag = 0; - } } diff -Nru a/arch/m68k/Kconfig b/arch/m68k/Kconfig --- a/arch/m68k/Kconfig Tue Jul 1 18:44:35 2003 +++ b/arch/m68k/Kconfig Tue Jul 1 18:44:35 2003 @@ -585,32 +585,7 @@ source "drivers/ide/Kconfig" - -menu "SCSI device support" - -config SCSI - tristate "SCSI device support" - ---help--- - If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or - any other SCSI device under Linux, say Y and make sure that you know - the name of your SCSI host adapter (the card inside your computer - that "speaks" the SCSI protocol, also called SCSI controller), - because you will be asked for it. - - You also need to say Y here if you want support for the parallel - port version of the 100 MB IOMEGA ZIP drive. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called scsi_mod. If you want to compile it as - a module, say M here and read and - . However, do not compile this as a - module if your root file system (the one containing the directory /) - is located on a SCSI device. - source "drivers/scsi/Kconfig" - -endmenu source "net/Kconfig" diff -Nru a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig --- a/arch/m68knommu/Kconfig Tue Jul 1 18:44:36 2003 +++ b/arch/m68knommu/Kconfig Tue Jul 1 18:44:36 2003 @@ -499,6 +499,7 @@ default y config KCORE_ELF + bool default y source "fs/Kconfig.binfmt" @@ -527,59 +528,9 @@ source "drivers/ide/Kconfig" - -menu "SCSI device support" - -config SCSI - tristate "SCSI device support" - help - If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or - any other SCSI device under Linux, say Y and make sure that you know - the name of your SCSI host adapter (the card inside your computer - that "speaks" the SCSI protocol, also called SCSI controller), - because you will be asked for it. - source "drivers/scsi/Kconfig" -endmenu - - -menu "Old CD-ROM drivers (not SCSI, not IDE)" - depends on ISA - -config CD_NO_IDESCSI - bool "Support non-SCSI/IDE/ATAPI CDROM drives" - ---help--- - If you have a CD-ROM drive that is neither SCSI nor IDE/ATAPI, say Y - here, otherwise N. Read the CD-ROM-HOWTO, available from - . - - Note that the answer to this question doesn't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about these CD-ROM drives. If you are unsure what you - have, say Y and find out whether you have one of the following - drives. - - For each of these drivers, a file Documentation/cdrom/{driver_name} - exists. Especially in cases where you do not know exactly which kind - of drive you have you should read there. Most of these drivers use a - file drivers/cdrom/{driver_name}.h where you can define your - interface parameters and switch some internal goodies. - - All these CD-ROM drivers are also usable as a module ( = code which - can be inserted in and removed from the running kernel whenever you - want). If you want to compile them as module, say M instead of Y and - read . - - If you want to use any of these CD-ROM drivers, you also have to - answer Y or M to "ISO 9660 CD-ROM file system support" below (this - answer will get "defaulted" for you if you enable any of the Linux - CD-ROM drivers). - source "drivers/cdrom/Kconfig" - -endmenu - source "drivers/md/Kconfig" diff -Nru a/arch/m68knommu/kernel/time.c b/arch/m68knommu/kernel/time.c --- a/arch/m68knommu/kernel/time.c Tue Jul 1 18:44:36 2003 +++ b/arch/m68knommu/kernel/time.c Tue Jul 1 18:44:36 2003 @@ -162,28 +162,33 @@ tv->tv_usec = usec; } -void do_settimeofday(struct timeval *tv) +int do_settimeofday(struct timespec *tv) { + if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) + return -EINVAL; + write_seqlock_irq(&xtime_lock); - /* This is revolting. We need to set the xtime.tv_usec + /* + * This is revolting. We need to set the xtime.tv_usec * correctly. However, the value in this location is * is value at the last tick. * Discover what correction gettimeofday * would have done, and then undo it! */ if (mach_gettimeoffset) - tv->tv_usec -= mach_gettimeoffset(); + tv->tv_nsec -= (mach_gettimeoffset() * 1000); - while (tv->tv_usec < 0) { - tv->tv_usec += 1000000; + while (tv->tv_nsec < 0) { + tv->tv_nsec += NSEC_PER_SEC; tv->tv_sec--; } xtime.tv_sec = tv->tv_sec; - xtime.tv_nsec = (tv->tv_usec * 1000); + xtime.tv_nsec = tv->tv_nsec; time_adjust = 0; /* stop active adjtime() */ time_status |= STA_UNSYNC; time_maxerror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT; write_sequnlock_irq(&xtime_lock); + return 0; } diff -Nru a/arch/m68knommu/kernel/traps.c b/arch/m68knommu/kernel/traps.c --- a/arch/m68knommu/kernel/traps.c Tue Jul 1 18:44:34 2003 +++ b/arch/m68knommu/kernel/traps.c Tue Jul 1 18:44:34 2003 @@ -82,7 +82,7 @@ printk("Process %s (pid: %d, stackpage=%08lx)\n", current->comm, current->pid, PAGE_SIZE+(unsigned long)current); - show_stack((unsigned long *)fp); + show_stack(NULL, (unsigned long *)fp); do_exit(SIGSEGV); } @@ -106,7 +106,7 @@ int kstack_depth_to_print = 48; -void show_stack(unsigned long *esp) +void show_stack(struct task_struct *task, unsigned long *esp) { unsigned long *stack, *endstack, addr; extern char _start, _etext; diff -Nru a/arch/m68knommu/platform/5206e/MOTOROLA/crt0_ram.S b/arch/m68knommu/platform/5206e/MOTOROLA/crt0_ram.S --- a/arch/m68knommu/platform/5206e/MOTOROLA/crt0_ram.S Tue Jul 1 18:44:33 2003 +++ b/arch/m68knommu/platform/5206e/MOTOROLA/crt0_ram.S Tue Jul 1 18:44:33 2003 @@ -96,6 +96,7 @@ movec %d0, %CACR /* Enable cache */ +#ifdef CONFIG_ROMFS_FS /* * Move ROM filesystem above bss :-) */ @@ -116,6 +117,12 @@ move.l %d0, -(%a1) cmp.l %a0, %a2 /* Check if at end */ bne _copy_romfs + +#else /* CONFIG_ROMFS_FS */ + lea.l _ebss, %a1 + move.l %a1, _ramstart +#endif /* CONFIG_ROMFS_FS */ + /* * Zero out the bss region. diff -Nru a/arch/m68knommu/platform/5272/NETtel/crt0_ram.S b/arch/m68knommu/platform/5272/NETtel/crt0_ram.S --- a/arch/m68knommu/platform/5272/NETtel/crt0_ram.S Tue Jul 1 18:44:37 2003 +++ b/arch/m68knommu/platform/5272/NETtel/crt0_ram.S Tue Jul 1 18:44:37 2003 @@ -116,6 +116,8 @@ movec %d0, %CACR /* Enable cache */ nop + +#ifdef CONFIG_ROMFS_FS #ifdef CONFIG_ROMFS_FROM_ROM /* * check for an in RAM romfs @@ -159,6 +161,12 @@ move.l %a1, _ramstart /* Set start of ram */ done_romfs: #endif + +#else /* CONFIG_ROMFS_FS */ + lea.l _ebss, %a1 + move.l %a1, _ramstart +#endif /* CONFIG_ROMFS_FS */ + /* * Zero out the bss region. diff -Nru a/arch/m68knommu/platform/5282/MOTOROLA/crt0_ram.S b/arch/m68knommu/platform/5282/MOTOROLA/crt0_ram.S --- a/arch/m68knommu/platform/5282/MOTOROLA/crt0_ram.S Tue Jul 1 18:44:36 2003 +++ b/arch/m68knommu/platform/5282/MOTOROLA/crt0_ram.S Tue Jul 1 18:44:36 2003 @@ -115,6 +115,8 @@ nop #endif + +#ifdef CONFIG_ROMFS_FS /* * Move ROM filesystem above bss :-) */ @@ -135,6 +137,11 @@ move.l %d0, -(%a1) cmp.l %a0, %a2 /* Check if at end */ bne _copy_romfs +#else /* CONFIG_ROMFS_FS */ + lea.l _ebss, %a1 + move.l %a1, _ramstart +#endif /* CONFIG_ROMFS_FS */ + /* * Zero out the bss region. diff -Nru a/arch/m68knommu/platform/5282/pit.c b/arch/m68knommu/platform/5282/pit.c --- a/arch/m68knommu/platform/5282/pit.c Tue Jul 1 18:44:37 2003 +++ b/arch/m68knommu/platform/5282/pit.c Tue Jul 1 18:44:37 2003 @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include diff -Nru a/arch/m68knommu/platform/5307/ARNEWSH/crt0_ram.S b/arch/m68knommu/platform/5307/ARNEWSH/crt0_ram.S --- a/arch/m68knommu/platform/5307/ARNEWSH/crt0_ram.S Tue Jul 1 18:44:34 2003 +++ b/arch/m68knommu/platform/5307/ARNEWSH/crt0_ram.S Tue Jul 1 18:44:34 2003 @@ -110,6 +110,8 @@ movc %d0,%CACR nop + +#ifdef CONFIG_ROMFS_FS /* * Move ROM filesystem above bss :-) */ @@ -130,6 +132,12 @@ move.l %d0, -(%a1) cmp.l %a0, %a2 /* Check if at end */ bne _copy_romfs + +#else /* CONFIG_ROMFS_FS */ + lea.l _ebss, %a1 + move.l %a1, _ramstart +#endif /* CONFIG_ROMFS_FS */ + /* * Zero out the bss region. diff -Nru a/arch/m68knommu/platform/5307/config.c b/arch/m68knommu/platform/5307/config.c --- a/arch/m68knommu/platform/5307/config.c Tue Jul 1 18:44:32 2003 +++ b/arch/m68knommu/platform/5307/config.c Tue Jul 1 18:44:32 2003 @@ -102,9 +102,12 @@ { mcf_setimr(MCFSIM_IMR_MASKALL); -#if defined(CONFIG_NETtel) || defined(CONFIG_eLIA) || \ - defined(CONFIG_DISKtel) || defined(CONFIG_SECUREEDGEMP3) || \ - defined(CONFIG_CLEOPATRA) +#if defined(CONFIG_BOOTPARAM) + strncpy(commandp, CONFIG_BOOTPARAM_STRING, size); + commandp[size-1] = 0; +#elif defined(CONFIG_NETtel) || defined(CONFIG_eLIA) || \ + defined(CONFIG_DISKtel) || defined(CONFIG_SECUREEDGEMP3) || \ + defined(CONFIG_CLEOPATRA) /* Copy command line from FLASH to local buffer... */ memcpy(commandp, (char *) 0xf0004000, size); commandp[size-1] = 0; diff -Nru a/arch/m68knommu/platform/68360/ints.c b/arch/m68knommu/platform/68360/ints.c --- a/arch/m68knommu/platform/68360/ints.c Tue Jul 1 18:44:31 2003 +++ b/arch/m68knommu/platform/68360/ints.c Tue Jul 1 18:44:31 2003 @@ -40,23 +40,21 @@ extern void *_ramvec[]; +/* The number of spurious interrupts */ +volatile unsigned int num_spurious; +unsigned int local_irq_count[NR_CPUS]; + /* irq node variables for the 32 (potential) on chip sources */ -static irq_node_t *int_irq_list[INTERNAL_IRQS]; +static irq_node_t int_irq_list[INTERNAL_IRQS]; -static int int_irq_count[INTERNAL_IRQS]; static short int_irq_ablecount[INTERNAL_IRQS]; -static void int_badint(int irq, void *dev_id, struct pt_regs *fp) -{ - num_spurious += 1; -} - /* * This function should be called during kernel startup to initialize * IRQ handling routines. */ -void M68360_init_IRQ(void) +void init_IRQ(void) { int i; int vba = (CPM_VECTOR_BASE<<4); @@ -128,13 +126,14 @@ /* initialize handlers */ for (i = 0; i < INTERNAL_IRQS; i++) { - int_irq_list[i] = NULL; - - int_irq_ablecount[i] = 0; - int_irq_count[i] = 0; + int_irq_list[i].handler = NULL; + int_irq_list[i].flags = IRQ_FLG_STD; + int_irq_list[i].dev_id = NULL; + int_irq_list[i].devname = NULL; } } +#if 0 void M68360_insert_irq(irq_node_t **list, irq_node_t *node) { unsigned long flags; @@ -178,9 +177,10 @@ local_irq_restore(flags); printk ("%s: tried to remove invalid irq\n", __FUNCTION__); } +#endif -int M68360_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), - unsigned long flags, const char *devname, void *dev_id) +int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), + unsigned long flags, const char *devname, void *dev_id) { int mask = (1<flags = IRQ_FLG_STD; - } - - if (!(int_irq_list[irq]->flags & IRQ_FLG_STD)) { - if (int_irq_list[irq]->flags & IRQ_FLG_LOCK) { + if (!(int_irq_list[irq].flags & IRQ_FLG_STD)) { + if (int_irq_list[irq].flags & IRQ_FLG_LOCK) { printk("%s: IRQ %d from %s is not replaceable\n", - __FUNCTION__, irq, int_irq_list[irq]->devname); + __FUNCTION__, irq, int_irq_list[irq].devname); return -EBUSY; } if (flags & IRQ_FLG_REPLACE) { printk("%s: %s can't replace IRQ %d from %s\n", - __FUNCTION__, devname, irq, int_irq_list[irq]->devname); + __FUNCTION__, devname, irq, int_irq_list[irq].devname); return -EBUSY; } } - int_irq_list[irq]->handler = handler; - int_irq_list[irq]->flags = flags; - int_irq_list[irq]->dev_id = dev_id; - int_irq_list[irq]->devname = devname; + int_irq_list[irq].handler = handler; + int_irq_list[irq].flags = flags; + int_irq_list[irq].dev_id = dev_id; + int_irq_list[irq].devname = devname; /* enable in the CIMR */ if (!int_irq_ablecount[irq]) @@ -221,24 +216,25 @@ return 0; } -void M68360_free_irq(unsigned int irq, void *dev_id) +void free_irq(unsigned int irq, void *dev_id) { if (irq >= INTERNAL_IRQS) { printk ("%s: Unknown IRQ %d\n", __FUNCTION__, irq); return; } - if (int_irq_list[irq]->dev_id != dev_id) + if (int_irq_list[irq].dev_id != dev_id) printk("%s: removing probably wrong IRQ %d from %s\n", - __FUNCTION__, irq, int_irq_list[irq]->devname); - int_irq_list[irq]->handler = int_badint; - int_irq_list[irq]->flags = IRQ_FLG_STD; - int_irq_list[irq]->dev_id = NULL; - int_irq_list[irq]->devname = NULL; + __FUNCTION__, irq, int_irq_list[irq].devname); + int_irq_list[irq].handler = NULL; + int_irq_list[irq].flags = IRQ_FLG_STD; + int_irq_list[irq].dev_id = NULL; + int_irq_list[irq].devname = NULL; *(volatile unsigned long *)0xfffff304 |= 1<handler) { - int_irq_list[irq]->handler(irq , int_irq_list[irq]->dev_id, fp); - int_irq_count[irq]++; + if (int_irq_list[irq].handler) { + int_irq_list[irq].handler(irq , int_irq_list[irq].dev_id, fp); + kstat_cpu(0).irqs[irq]++; pquicc->intr_cisr = (1 << vec); /* indicate that irq has been serviced */ } else { printk("unregistered interrupt %d!\nTurning it off in the CIMR...\n", irq); /* *(volatile unsigned long *)0xfffff304 |= mask; */ pquicc->intr_cimr &= ~(1 << vec); + num_spurious += 1; } } - -void config_M68360_irq(void) -{ - mach_default_handler = NULL; - mach_init_IRQ = M68360_init_IRQ; - mach_request_irq = M68360_request_irq; - mach_free_irq = M68360_free_irq; - mach_enable_irq = M68360_enable_irq; - mach_disable_irq = M68360_disable_irq; - mach_process_int = M68360_do_irq; -} - diff -Nru a/arch/mips/Kconfig b/arch/mips/Kconfig --- a/arch/mips/Kconfig Tue Jul 1 18:44:35 2003 +++ b/arch/mips/Kconfig Tue Jul 1 18:44:35 2003 @@ -6,1113 +6,12 @@ bool default y -config MMU +config MIPS32 bool default y -config SMP +config MIPS64 bool - ---help--- - This enables support for systems with more than one CPU. If you have - a system with only one CPU, like most personal computers, say N. If - you have a system with more than one CPU, say Y. - - If you say N here, the kernel will run on single and multiprocessor - machines, but will use only one CPU of a multiprocessor machine. If - you say Y here, the kernel will run on many, but not all, - singleprocessor machines. On a singleprocessor machine, the kernel - will run faster if you say N here. - - Note that if you say Y here and choose architecture "586" or - "Pentium" under "Processor family", the kernel will not work on 486 - architectures. Similarly, multiprocessor kernels for the "PPro" - architecture may not work on all Pentium based boards. - - People using multiprocessor machines who say Y here should also say - Y to "Enhanced Real Time Clock Support", below. The "Advanced Power - Management" code will be disabled if you say Y here. - - See also the , - , , - and the SMP-HOWTO available at - . - - If you don't know what to do here, say N. - -config GENERIC_ISA_DMA - bool - default y - - -mainmenu "Linux Kernel Configuration" - -source "init/Kconfig" - - -menu "Machine selection" - -config ACER_PICA_61 - bool "Support for Acer PICA 1 chipset (EXPERIMENTAL)" - depends on EXPERIMENTAL - help - This is a machine with a R4400 133/150 MHz CPU. To compile a Linux - kernel that runs on these, say Y here. For details about Linux on - the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at - . - -config ALGOR_P4032 - bool "Support for Algorithmics P4032 (EXPERIMENTAL)" - depends on EXPERIMENTAL - help - This is an evaluation board of the British company Algorithmics. - The board uses the R4300 and a R5230 CPUs. For more information - about this board see . - -config BAGET_MIPS - bool "Support for BAGET MIPS series (EXPERIMENTAL)" - depends on EXPERIMENTAL - help - This enables support for the Baget, a Russian embedded system. For - more details about the Baget see the Linux/MIPS FAQ on - . - -config DECSTATION - bool "Support for DECstations (EXPERIMENTAL)" - depends on EXPERIMENTAL - ---help--- - This enables support for DEC's MIPS based workstations. For details - see the Linux/MIPS FAQ on and the - DECstation porting pages on . - - If you have one of the following DECstation Models you definitely - want to choose R4xx0 for the CPU Type: - - DECstation 5000/50 - DECstation 5000/150 - DECstation 5000/260 - DECsystem 5900/260 - - otherwise choose R3000. - -config DDB5074 - bool "Support for NEC DDB Vrc-5074 (EXPERIMENTAL)" - depends on EXPERIMENTAL - help - This enables support for the VR5000-based NEC DDB Vrc-5074 - evaluation board. - -config MIPS_EV96100 - bool "Support for Galileo EV96100 Evaluation board (EXPERIMENTAL)" - depends on EXPERIMENTAL - help - This is an evaluation board based on the Galielo GT-96100 LAN/WAN - communications controllers containing a MIPS R5000 compatible core - running at 83MHz. Their website is . Say Y - here if you wish to build a kernel for this platform. - -config MIPS_EV64120 - bool "Support for Galileo EV64120 Evaluation board (EXPERIMENTAL)" - depends on EXPERIMENTAL - help - This is an evaluation board based on the Galileo GT-64120 - single-chip system controller that contains a MIPS R5000 compatible - core running at 75/100MHz. Their website is located at - . Say Y here if you wish to build a - kernel for this platform. - -config EVB_PCI1 - bool "Enable Second PCI (PCI1)" - depends on MIPS_EV64120 - -choice - prompt "Galileo Chip Clock" - depends on MIPS_EV64120 - -config SYSCLK_75 - bool "75" - -config SYSCLK_83 - bool "83.3" - -config SYSCLK_100_1 - bool "100" - -endchoice - -config MIPS_ATLAS - bool "Support for MIPS Atlas board (EXPERIMENTAL)" - depends on EXPERIMENTAL - help - This enables support for the QED R5231-based MIPS Atlas evaluation - board. - -config MIPS_MALTA - bool "Support for MIPS Malta board (EXPERIMENTAL)" - depends on EXPERIMENTAL - help - This enables support for the VR5000-based MIPS Malta evaluation - board. - -config NINO - bool "Support for Philips Nino (EXPERIMENTAL)" - depends on EXPERIMENTAL - help - Say Y here to select a kernel for the Philips Nino Palm PC. The - website at - will have more information. - -choice - prompt "Nino Model Number" - depends on NINO - -config NINO_4MB - bool "Model-300/301/302/319" - help - Say Y here to build a kernel specifically for Nino Palm PCs with - 4MB of memory. These include models 300/301/302/319. - -config NINO_8MB - bool "Model-200/210/312/320/325/350/390" - help - Say Y here to build a kernel specifically for Nino Palm PCs with - 8MB of memory. These include models 200/210/312/320/325/350/390. - -config NINO_16MB - bool "Model-500/510" - help - Say Y here to build a kernel specifically for Nino 500/501 color - Palm PCs from Philips (INCOMPLETE). - -endchoice - -config MIPS_MAGNUM_4000 - bool "Support for Mips Magnum 4000" - help - This is a machine with a R4000 100 MHz CPU. To compile a Linux - kernel that runs on these, say Y here. For details about Linux on - the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at - . - -config MOMENCO_OCELOT - bool "Support for Momentum Ocelot board" - help - The Ocelot is a MIPS-based Single Board Computer (SBC) made by - Momentum Computer . - -config DDB5476 - bool "Support for NEC DDB Vrc-5476" - help - This enables support for the R5432-based NEC DDB Vrc-5476 - evaluation board. - - Features : kernel debugging, serial terminal, NFS root fs, on-board - ether port (Need an additional patch at ), - USB, AC97, PCI, PCI VGA card & framebuffer console, IDE controller, - PS2 keyboard, PS2 mouse, etc. - -config DDB5477 - bool "Support for NEC DDB Vrc-5477" - help - This enables support for the R5432-based NEC DDB Vrc-5477 - evaluation board. - - Features : kernel debugging, serial terminal, NFS root fs, on-board - ether port (Need an additional patch at ), - USB, AC97, PCI, etc. - -config OLIVETTI_M700 - bool "Support for Olivetti M700-10" - help - This is a machine with a R4000 100 MHz CPU. To compile a Linux - kernel that runs on these, say Y here. For details about Linux on - the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at - . - -config SGI_IP22 - bool "Support for SGI IP22" - help - This are the SGI Indy, Challenge S and Indigo2, as well as certain - OEM variants like the Tandem CMN B006S. To compile a Linux kernel - that runs on these, say Y here. - -config SNI_RM200_PCI - bool "Support for SNI RM200 PCI" - help - The SNI RM200 PCI was a MIPS-based platform manufactured by Siemens - Nixdorf Informationssysteme (SNI), parent company of Pyramid - Technology and now in turn merged with Fujitsu. Say Y here to - support this machine type. - -config MIPS_ITE8172 - bool "Support for ITE 8172G board" - help - Ths is an evaluation board made by ITE - with ATX form factor that utilizes a MIPS R5000 to work with its - ITE8172G companion internet appliance chip. The MIPS core can be - either a NEC Vr5432 or QED RM5231. Say Y here if you wish to build - a kernel for this platform. - -config IT8172_REVC - bool "Support for older IT8172 (Rev C)" - depends on MIPS_ITE8172 - help - Say Y here to support the older, Revision C version of the Integrated - Technology Express, Inc. ITE8172 SBC. Vendor page at - ; picture of the - board at . - -config QTRONIX_KEYBOARD - bool "Enable Qtronix 990P Keyboard Support" - depends on MIPS_IVR || MIPS_ITE8172 - help - Images of Qtronix keyboards are at - . - -config IT8172_CIR - bool - depends on QTRONIX_KEYBOARD && (MIPS_IVR || MIPS_ITE8172) - default y - -config PC_KEYB - bool "Enable PS2 Keyboard Support" if MIPS_ITE8172 && !QTRONIX_KEYBOARD - default y if NINO || MIPS_ITE8172 || DDB5476 || DDB5074 || SNI_RM200_PCI || SGI_IP22 || ACER_PICA_61 || MIPS_MAGNUM_4000 || OLIVETTI_M700 - -config IT8172_SCR0 - bool "Enable Smart Card Reader 0 Support " - depends on MIPS_IVR || MIPS_ITE8172 - help - Say Y here to support smart-card reader 0 (SCR0) on the Integrated - Technology Express, Inc. ITE8172 SBC. Vendor page at - ; picture of the - board at . - -config IT8172_SCR1 - bool "Enable Smart Card Reader 1 Support " - depends on MIPS_ITE8172 - help - Say Y here to support smart-card reader 1 (SCR1) on the Integrated - Technology Express, Inc. ITE8172 SBC. Vendor page at - ; picture of the - board at . - -config MIPS_IVR - bool "Support for Globespan IVR board" - help - This is an evaluation board built by Globespan to showcase thir - iVR (Internet Video Recorder) design. It utilizes a QED RM5231 - R5000 MIPS core. More information can be found out their website - located at P. Say Y - here if you wish to build a kernel for this platform. - -config MIPS_PB1000 - bool "Support for Alchemy Semi PB1000 board" - help - This is an evaluation board built by Alchemy Semiconducttor to - showcase their Au1000 Internet Edge Processor. It is SOC design - containing a MIPS32 core running at 266/400/500MHz with many - integrated peripherals. Further information can be found at their - website, . Say Y here if you wish to - build a kernel for this platform. - -config RWSEM_GENERIC_SPINLOCK - bool - default y - -config RWSEM_XCHGADD_ALGORITHM - bool - -# -# Select some configuration options automatically for certain systems. -# -config ISA - bool - depends on DDB5476 || DDB5074 || SNI_RM200_PCI || ACER_PICA_61 || MIPS_MAGNUM_4000 || OLIVETTI_M700 - default y - help - Find out whether you have ISA slots on your motherboard. ISA is the - name of a bus system, i.e. the way the CPU talks to the other stuff - inside your box. Other bus systems are PCI, EISA, MicroChannel - (MCA) or VESA. ISA is an older system, now being displaced by PCI; - newer boards don't support it. If you have ISA, say Y, otherwise N. - -config EISA - bool - depends on ISA - default y - ---help--- - The Extended Industry Standard Architecture (EISA) bus was - developed as an open alternative to the IBM MicroChannel bus. - - The EISA bus provided some of the features of the IBM MicroChannel - bus while maintaining backward compatibility with cards made for - the older ISA bus. The EISA bus saw limited use between 1988 and - 1995 when it was made obsolete by the PCI bus. - - Say Y here if you are building a kernel for an EISA-based machine. - - Otherwise, say N. - -config PCI - bool - depends on MIPS_IVR || MIPS_ITE8172 || DDB5477 || DDB5476 || DDB5074 || SNI_RM200_PCI || MOMENCO_OCELOT || MIPS_MALTA || MIPS_ATLAS || ALGOR_P4032 || MIPS_EV64120 || MIPS_EV96100 - default y - help - Find out whether you have a PCI motherboard. PCI is the name of a - bus system, i.e. the way the CPU talks to the other stuff inside - your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or - VESA. If you have PCI, say Y, otherwise N. - - The PCI-HOWTO, available from - , contains valuable - information about which PCI hardware does work under Linux and which - doesn't. - -config MCA - bool - help - MicroChannel Architecture is found in some IBM PS/2 machines and - laptops. It is a bus system similar to PCI or ISA. See - (and especially the web page given - there) before attempting to build an MCA bus kernel. - -config SBUS - bool - -config I8259 - bool - depends on DDB5074 || SNI_RM200_PCI || MIPS_MALTA || ACER_PICA_61 || MIPS_MAGNUM_4000 || OLIVETTI_M700 - default y - -config MIPS_GT96100 - bool - depends on MIPS_EV96100 - default y - help - Say Y here to support the Galileo Technology GT96100 communications - controller card. There is a web page at . - -config SWAP_IO_SPACE - bool - depends on MOMENCO_OCELOT || MIPS_MALTA || MIPS_ATLAS || MIPS_EV96100 - default y - -config NEW_PCI - bool - depends on MIPS_ITE8172 || MIPS_EV96100 - default y - -config PCI_AUTO - bool - depends on MIPS_ITE8172 || MIPS_EV96100 - default y - -config MIPS_GT64120 - bool - depends on MIPS_EV64120 - default y - -config OLD_TIME_C - bool - depends on DDB5074 || SNI_RM200_PCI || SGI_IP22 || MOMENCO_OCELOT || ACER_PICA_61 || MIPS_MAGNUM_4000 || OLIVETTI_M700 || ALGOR_P4032 || MIPS_EV64120 - default y - -config ARC32 - bool - depends on SNI_RM200_PCI || SGI_IP22 || ACER_PICA_61 || MIPS_MAGNUM_4000 || OLIVETTI_M700 - default y - -config FB - bool - depends on MIPS_MAGNUM_4000 || OLIVETTI_M700 - default y - ---help--- - The frame buffer device provides an abstraction for the graphics - hardware. It represents the frame buffer of some video hardware and - allows application software to access the graphics hardware through - a well-defined interface, so the software doesn't need to know - anything about the low-level (hardware register) stuff. - - Frame buffer devices work identically across the different - architectures supported by Linux and make the implementation of - application programs easier and more portable; at this point, an X - server exists which uses the frame buffer device exclusively. - On several non-X86 architectures, the frame buffer device is the - only way to use the graphics hardware. - - The device is accessed through special device nodes, usually located - in the /dev directory, i.e. /dev/fb*. - - You need an utility program called fbset to make full use of frame - buffer devices. Please read - and the Framebuffer-HOWTO at - for more - information. - - Say Y here and to the driver for your graphics board below if you - are compiling a kernel for a non-x86 architecture. - - If you are compiling for the x86 architecture, you can say Y if you - want to play with it, but it is not essential. Please note that - running graphical applications that directly touch the hardware - (e.g. an accelerated X server) and that are not frame buffer - device-aware may cause unexpected results. If unsure, say N. - -config FB_G364 - bool - depends on MIPS_MAGNUM_4000 || OLIVETTI_M700 - default y - -config MIPS_JAZZ - bool - depends on ACER_PICA_61 || MIPS_MAGNUM_4000 || OLIVETTI_M700 - default y - -config ROTTEN_IRQ - bool - depends on DDB5476 || DDB5074 || SNI_RM200_PCI || ACER_PICA_61 - default y - -config HAVE_STD_PC_SERIAL_PORT - bool - depends on DDB5476 || DDB5074 || MIPS_MALTA - default y - -config NEW_IRQ - bool - depends on MIPS_PB1000 || DDB5477 || SGI_IP22 || MOMENCO_OCELOT || MIPS_MALTA - default y - -config SYSCLK_100_2 - bool - depends on MOMENCO_OCELOT - default y - -config BOARD_SCACHE - bool - depends on SGI_IP22 - default y - -config SGI - bool - depends on SGI_IP22 - default y - -config NEW_TIME_C - bool - depends on DDB5477 || DDB5476 - default y - -config CPU_LITTLE_ENDIAN - bool - depends on DDB5477 - default y - help - Some MIPS machines can be configured for either little or big endian - byte order. These modes require different kernels. Say Y if your - machine is little endian, N if it's a big endian machine. - -config IT8712 - bool - depends on MIPS_ITE8172 - default y - -config MIPS_AU1000 - bool - depends on MIPS_PB1000 - default y - -config SYSCLK_100 - bool - depends on SYSCLK_100_1 || SYSCLK_100_2 - default y - -endmenu - - -menu "CPU selection" - -choice - prompt "CPU type" - default CPU_R4X00 - -config CPU_R3000 - bool "R3000" - ---help--- - Please make sure to pick the right CPU type. Linux/MIPS is not - designed to be generic, i.e. Kernels compiled for R3000 CPUs will - *not* work on R4000 machines and vice versa. However, since most - of the supported machines have an R4000 (or similar) CPU, R4x00 - might be a safe bet. If the resulting kernel does not work, - try to recompile with R3000. - - R3000 MIPS Technologies R3000-series processors, - including the 3041, 3051, and 3081. - - R6000 MIPS Technologies R6000-series processors, - including the 64474, 64475, 64574 and 64575. - - R4300 MIPS Technologies R4300-series processors. - - R4x00 MIPS Technologies R4000-series processors other than 4300, - including the 4640, 4650, and 4700. - - R5000 MIPS Technologies R5000-series processors other than the - Nevada. - - R52xx MIPS Technologies R52xx-series ("Nevada") processors. - - R10000 MIPS Technologies R10000-series processors. - -config CPU_R6000 - bool "R6000" - help - MIPS Technologies R6000-series processors, including the 64474, - 64475, 64574 and 64575. - -config CPU_VR41XX - bool "R41xx" - help - The options selects support for the NEC VR41xx series of processors. - Only choose this option if you have one of these processors as a - kernel built with this option will not run on any other type of - processor or vice versa. - -config CPU_R4300 - bool "R4300" - help - MIPS Technologies R4300-series processors. - -config CPU_R4X00 - bool "R4x00" - help - MIPS Technologies R4000-series processors other than 4300, including - the 4640, 4650, and 4700. - -config CPU_R5000 - bool "R5000" - help - MIPS Technologies R5000-series processors other than the Nevada. - -config CPU_R5432 - bool "R5432" - -config CPU_RM7000 - bool "RM7000" - -config CPU_NEVADA - bool "R52xx" - help - MIPS Technologies R52x0-series ("Nevada") processors. - -config CPU_R10000 - bool "R10000" - help - MIPS Technologies R10000-series processors. - -config CPU_SB1 - bool "SB1" - -config CPU_MIPS32 - bool "MIPS32" - -config CPU_MIPS64 - bool "MIPS64" - -endchoice - -config CPU_ADVANCED - bool "Override CPU Options" - help - Saying yes here allows you to select support for various features - your CPU may or may not have. Most people should say N here. - -config CPU_HAS_LLSC - bool "ll/sc Instructions available" if CPU_ADVANCED - default y if !CPU_ADVANCED && !CPU_R3000 && !CPU_VR41XX - help - MIPS R4000 series and later provide the Load Linked (ll) - and Store Conditional (sc) instructions. More information is - available at . - - Say Y here if your CPU has the ll and sc instructions. Say Y here - for better performance, N if you don't know. You must say Y here - for multiprocessor machines. - -config CPU_HAS_LLDSCD - bool "lld/scd Instructions available" if CPU_ADVANCED - default y if !CPU_ADVANCED && !CPU_R3000 && !CPU_VR41XX && !CPU_MIPS32 - help - Say Y here if your CPU has the lld and scd instructions, the 64-bit - equivalents of ll and sc. Say Y here for better performance, N if - you don't know. You must say Y here for multiprocessor machines. - -config CPU_HAS_WB - bool "Writeback Buffer available" if CPU_ADVANCED - default y if !CPU_ADVANCED && (CPU_R3000 || CPU_VR41XX) && CONFIG_DECSTATION=y - help - Say N here for slightly better performance. You must say Y here for - machines which require flushing of write buffers in software. Saying - Y is the safe option; N may result in kernel malfunction and crashes. - -endmenu - - -menu "General setup" - -config CPU_LITTLE_ENDIAN - bool "Generate little endian code" if !DECSTATION && !DDB5074 && !DDB5476 && !NINO - default y if DECSTATION || DDB5074 || DDB5476 || NINO - -config KCORE_ELF - bool - depends on PROC_FS - default y - ---help--- - If you enabled support for /proc file system then the file - /proc/kcore will contain the kernel core image. This can be used - in gdb: - - $ cd /usr/src/linux ; gdb vmlinux /proc/kcore - - You have two choices here: ELF and A.OUT. Selecting ELF will make - /proc/kcore appear in ELF core format as defined by the Executable - and Linking Format specification. Selecting A.OUT will choose the - old "a.out" format which may be necessary for some old versions - of binutils or on some architectures. - - This is especially useful if you have compiled the kernel with the - "-g" option to preserve debugging information. It is mainly used - for examining kernel data structures on the live kernel so if you - don't understand what this means or are not a kernel hacker, just - leave it at its default value ELF. - -config ELF_KERNEL - bool - default y - -config BINFMT_IRIX - bool "Include IRIX binary compatibility" - depends on !CPU_LITTLE_ENDIAN - -config FORWARD_KEYBOARD - bool "Include forward keyboard" - depends on !CPU_LITTLE_ENDIAN - -config ARC_CONSOLE - bool "ARC console support" - depends on ARC32 - -source "fs/Kconfig.binfmt" - -source "drivers/pci/Kconfig" - -config HOTPLUG - bool "Support for hot-pluggable devices" - ---help--- - Say Y here if you want to plug devices into your computer while - the system is running, and be able to use them quickly. In many - cases, the devices can likewise be unplugged at any time too. - - One well known example of this is PCMCIA- or PC-cards, credit-card - size devices such as network cards, modems or hard drives which are - plugged into slots found on all modern laptop computers. Another - example, used on modern desktops as well as laptops, is USB. - - Enable HOTPLUG and KMOD, and build a modular kernel. Get agent - software (at ) and install it. - Then your kernel will automatically call out to a user mode "policy - agent" (/sbin/hotplug) to load modules and set up software needed - to use devices as you hotplug them. - -source "drivers/pcmcia/Kconfig" - -config TC - bool "TURBOchannel support" - depends on DECSTATION - help - TurboChannel is a DEC (now Compaq) bus for Alpha and MIPS processors. - Documentation on writing device drivers for TurboChannel is available at: - . - -# if [ "$CONFIG_TC" = "y" ]; then -# bool ' Access.Bus support' CONFIG_ACCESSBUS -# fi -endmenu - - -if ISA -source "drivers/pnp/Kconfig" -endif - -source "drivers/base/Kconfig" - -source "drivers/mtd/Kconfig" - -source "drivers/parport/Kconfig" - -source "drivers/block/Kconfig" - -source "drivers/md/Kconfig" - -if !SGI_IP22 && !DECSTATION -source "drivers/ide/Kconfig" -endif - - -menu "SCSI support" - -config SCSI - tristate "SCSI support" - ---help--- - If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or - any other SCSI device under Linux, say Y and make sure that you know - the name of your SCSI host adapter (the card inside your computer - that "speaks" the SCSI protocol, also called SCSI controller), - because you will be asked for it. - - You also need to say Y here if you want support for the parallel - port version of the 100 MB IOMEGA ZIP drive. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called scsi_mod. If you want to compile it as - a module, say M here and read and - . However, do not compile this as a - module if your root file system (the one containing the directory /) - is located on a SCSI device. - -source "drivers/scsi/Kconfig" - -endmenu - - -if !DECSTATION && !SGI_IP22 -source "drivers/message/i2o/Kconfig" -endif - -source "net/Kconfig" - -source "net/ax25/Kconfig" - -source "net/irda/Kconfig" - -source "drivers/isdn/Kconfig" - -source "drivers/telephony/Kconfig" - - -menu "Old CD-ROM drivers (not SCSI, not IDE)" - -config CD_NO_IDESCSI - bool "Support non-SCSI/IDE/ATAPI CDROM drives" - ---help--- - If you have a CD-ROM drive that is neither SCSI nor IDE/ATAPI, say Y - here, otherwise N. Read the CD-ROM-HOWTO, available from - . - - Note that the answer to this question doesn't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about these CD-ROM drives. If you are unsure what you - have, say Y and find out whether you have one of the following - drives. - - For each of these drivers, a file Documentation/cdrom/{driver_name} - exists. Especially in cases where you do not know exactly which kind - of drive you have you should read there. Most of these drivers use a - file drivers/cdrom/{driver_name}.h where you can define your - interface parameters and switch some internal goodies. - - All these CD-ROM drivers are also usable as a module ( = code which - can be inserted in and removed from the running kernel whenever you - want). If you want to compile them as module, say M instead of Y and - read . - - If you want to use any of these CD-ROM drivers, you also have to - answer Y or M to "ISO 9660 CD-ROM file system support" below (this - answer will get "defaulted" for you if you enable any of the Linux - CD-ROM drivers). - -source "drivers/cdrom/Kconfig" - -endmenu - -source "drivers/input/Kconfig" - -source "drivers/char/Kconfig" - -source "drivers/media/Kconfig" - - -menu "DECStation Character devices" - depends on DECSTATION - -config VT - bool "Virtual terminal" - -config VT_CONSOLE - bool "Support for console on virtual terminal" - depends on VT - -config SERIAL - tristate "Standard/generic (dumb) serial support" - ---help--- - This selects whether you want to include the driver for the standard - serial ports. The standard answer is Y. People who might say N - here are those that are setting up dedicated Ethernet WWW/FTP - servers, or users that have one of the various bus mice instead of a - serial mouse and don't intend to use their machine's standard serial - port for anything. (Note that the Cyclades and Stallion multi - serial port drivers do not need this driver built in for them to - work.) - - If you want to compile this driver as a module, say M here and read - . The module will be called - serial. - [WARNING: Do not compile this driver as a module if you are using - non-standard serial ports, since the configuration information will - be lost when the driver is unloaded. This limitation may be lifted - in the future.] - - BTW1: If you have a mouseman serial mouse which is not recognized by - the X window system, try running gpm first. - - BTW2: If you intend to use a software modem (also called Winmodem) - under Linux, forget it. These modems are crippled and require - proprietary drivers which are only available under Windows. - - Most people will say Y or M here, so that they can use serial mice, - modems and similar devices connecting to the standard serial ports. - -config DZ - bool "DZ11 Serial Support" - depends on SERIAL=y - help - DZ11-family serial controllers for VAXstations, including the - DC7085, M7814, and M7819. - -config ZS - bool "Z85C30 Serial Support" - depends on SERIAL=y && TC - help - Documentation on the Zilog 85C350 serial communications controller - is downloadable at . - -config SERIAL_CONSOLE - bool "Support for console on serial port" - depends on SERIAL=y - ---help--- - If you say Y here, it will be possible to use a serial port as the - system console (the system console is the device which receives all - kernel messages and warnings and which allows logins in single user - mode). This could be useful if some terminal or printer is connected - to that serial port. - - Even if you say Y here, the currently visible virtual console - (/dev/tty0) will still be used as the system console by default, but - you can alter that using a kernel command line option such as - "console=ttyS1". (Try "man bootparam" or see the documentation of - your boot loader (lilo or loadlin) about how to pass options to the - kernel at boot time.) - - If you don't have a VGA card installed and you say Y here, the - kernel will automatically use the first serial line, /dev/ttyS0, as - system console. - - If unsure, say N. - -config UNIX98_PTYS - bool "Unix98 PTY support" - -config UNIX98_PTY_COUNT - int "Maximum number of Unix98 PTYs in use (0-2048)" - depends on UNIX98_PTYS - default "256" - -# if [ "$CONFIG_ACCESSBUS" = "y" ]; then -# bool 'MAXINE Access.Bus mouse (VSXXX-BB/GB) support' CONFIG_DTOP_MOUSE -# fi -config RTC - tristate "Enhanced Real Time Clock Support" - -endmenu - - -menu "SGI Character devices" - depends on SGI_IP22 - -config VT - bool "Virtual terminal" - -config VT_CONSOLE - bool "Support for console on virtual terminal" - depends on VT - -config PSMOUSE - bool "PS/2 mouse support (aka \"auxiliary device\")" - ---help--- - The PS/2 mouse connects to a special mouse port that looks much like - the keyboard port (small circular connector with 6 pins). This way, - the mouse does not use any serial ports. This port can also be used - for other input devices like light pens, tablets, keypads. Compaq, - AST and IBM all use this as their mouse port on currently shipping - machines. The trackballs of some laptops are PS/2 mice also. In - particular, the C&T 82C710 mouse on TI Travelmates is a PS/2 mouse. - - Although PS/2 mice are not technically bus mice, they are explained - in detail in the Busmouse-HOWTO, available from - . - - When using a PS/2 mouse, you can get problems if you want to use the - mouse both on the Linux console and under X. Using the "-R" option - of the Linux mouse managing program gpm (available from - ) solves this problem, or you can get - the "mconv2" utility from . - -config MOUSE - bool - depends on PSMOUSE - default y - ---help--- - This is for machines with a mouse which is neither a serial nor a - bus mouse. Examples are PS/2 mice (such as the track balls on some - laptops) and some digitizer pads. Most people have a regular serial - MouseSystem or Microsoft mouse (made by Logitech) that plugs into a - COM port (rectangular with 9 or 25 pins). These people say N here. - If you have something else, read the Busmouse-HOWTO, available from - . This HOWTO contains - information about all non-serial mice, not just bus mice. - - If you have a laptop, you either have to check the documentation or - experiment a bit to find out whether the trackball is a serial mouse - or not; it's best to say Y here for you. - - Note that the answer to this question won't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about non-serial mice. If unsure, say Y. - -config UNIX98_PTYS - bool "Unix98 PTY support" - -config UNIX98_PTY_COUNT - int "Maximum number of Unix98 PTYs in use (0-2048)" - depends on UNIX98_PTYS - default "256" - -endmenu - -source "fs/Kconfig" - -source "drivers/video/Kconfig" - -menu "Sound" - depends on !DECSTATION - -config SOUND - tristate "Sound card support" - ---help--- - If you have a sound card in your computer, i.e. if it can say more - than an occasional beep, say Y. Be sure to have all the information - about your sound card and its configuration down (I/O port, - interrupt and DMA channel), because you will be asked for it. - - You want to read the Sound-HOWTO, available from - . General information about - the modular sound system is contained in the files - . The file - contains some slightly - outdated but still useful information as well. - - If you have a PnP sound card and you want to configure it at boot - time using the ISA PnP tools (read - ), then you need to - compile the sound card support as a module ( = code which can be - inserted in and removed from the running kernel whenever you want) - and load that module after the PnP configuration is finished. To do - this, say M here and read as well - as ; the module will be - called soundcore. - - I'm told that even without a sound card, you can make your computer - say more than an occasional beep, by programming the PC speaker. - Kernel patches and supporting utilities to do that are in the pcsp - package, available at . - -source "sound/Kconfig" - -endmenu - -source "drivers/sgi/Kconfig" - -source "drivers/usb/Kconfig" - - -menu "Kernel hacking" - -config CROSSCOMPILE - bool "Are you using a crosscompiler" - help - Say Y here if you are compiling the kernel on a different - architecture than the one it is intended to run on. - -config REMOTE_DEBUG - bool "Remote GDB kernel debugging" - depends on SERIAL=y || AU1000_UART - help - If you say Y here, it will be possible to remotely debug the MIPS - kernel using gdb. This enlarges your kernel image disk size by - several megabytes and requires a machine with more than 16 MB, - better 32 MB RAM to avoid excessive linking time. This is only - useful for kernel hackers. If unsure, say N. - -config GDB_CONSOLE - bool "Console output to GDB" - depends on REMOTE_DEBUG - help - If you are using GDB for remote debugging over a serial port and - would like kernel messages to be formatted into GDB $O packets so - that GDB prints them as program output, say 'Y'. - -config LL_DEBUG - bool "Low-level debugging" - depends on SERIAL=y - help - Enable low-level debugging assertion macros in the kernel code. - Currently used only by the time services code in the MIPS port. - Don't turn this on unless you know what you are doing. - -config MAGIC_SYSRQ - bool "Magic SysRq key" - help - If you say Y here, you will have some control over the system even - if the system crashes for example during kernel debugging (e.g., you - will be able to flush the buffer cache to disk, reboot the system - immediately or dump some status information). This is accomplished - by pressing various keys while holding SysRq (Alt+PrintScreen). It - also works on a serial console (on PC hardware at least), if you - send a BREAK and then within 5 seconds a command keypress. The - keys are documented in . Don't say Y - unless you really know what this hack does. - -config MIPS_UNCACHED - bool "Run uncached" - depends on !SMP - help - If you say Y here there kernel will disable all CPU caches. This will - reduce the system's performance dramatically but can help finding - otherwise hard to track bugs. It can also useful if you're doing - hardware debugging with a logic analyzer and need to see all traffic - on the bus. - -config NR_CPUS - int "Maximum number of CPUs (2-32)" - depends on SMP - default "32" - -endmenu - -source "security/Kconfig" - -source "crypto/Kconfig" - -source "lib/Kconfig" + default n +source "arch/mips/Kconfig-shared" diff -Nru a/arch/mips/Kconfig-shared b/arch/mips/Kconfig-shared --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/Kconfig-shared Tue Jul 1 18:44:39 2003 @@ -0,0 +1,1371 @@ +mainmenu "Linux/MIPS Kernel Configuration" + +source "init/Kconfig" + +menu "Machine selection" + +config ACER_PICA_61 + bool "Support for Acer PICA 1 chipset (EXPERIMENTAL)" + depends on EXPERIMENTAL + help + This is a machine with a R4400 133/150 MHz CPU. To compile a Linux + kernel that runs on these, say Y here. For details about Linux on + the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at + . + +config BAGET_MIPS + bool "Support for BAGET MIPS series (EXPERIMENTAL)" + depends on MIPS32 && EXPERIMENTAL + help + This enables support for the Baget, a Russian embedded system. For + more details about the Baget see the Linux/MIPS FAQ on + . + +config CASIO_E55 + bool "Support for CASIO CASSIOPEIA E-10/15/55/65" + +config MIPS_COBALT + bool "Support for Cobalt Server (EXPERIMENTAL)" + depends on EXPERIMENTAL + +config DECSTATION + bool "Support for DECstations" + depends on MIPS32 || EXPERIMENTAL + ---help--- + This enables support for DEC's MIPS based workstations. For details + see the Linux/MIPS FAQ on and the + DECstation porting pages on . + + If you have one of the following DECstation Models you definitely + want to choose R4xx0 for the CPU Type: + + DECstation 5000/50 + DECstation 5000/150 + DECstation 5000/260 + DECsystem 5900/260 + + otherwise choose R3000. + +config MIPS_EV64120 + bool "Support for Galileo EV64120 Evaluation board (EXPERIMENTAL)" + depends on EXPERIMENTAL + help + This is an evaluation board based on the Galileo GT-64120 + single-chip system controller that contains a MIPS R5000 compatible + core running at 75/100MHz. Their website is located at + . Say Y here if you wish to build a + kernel for this platform. + +config EVB_PCI1 + bool "Enable Second PCI (PCI1)" + depends on MIPS_EV64120 + +if MOMENCO_OCELOT_G || MOMENCO_OCELOT + +config SYSCLK_100 + bool + default y + +endif +if MIPS_EV64120 + +choice + prompt "Galileo Chip Clock" + default SYSCLK_83 + +config SYSCLK_75 + bool "75" + +config SYSCLK_83 + bool "83.3" + +config SYSCLK_100 + bool "100" if MIPS_EV64120 + +endchoice + +endif + +config MIPS_EV96100 + bool "Support for Galileo EV96100 Evaluation board (EXPERIMENTAL)" + depends on EXPERIMENTAL + help + This is an evaluation board based on the Galielo GT-96100 LAN/WAN + communications controllers containing a MIPS R5000 compatible core + running at 83MHz. Their website is . Say Y + here if you wish to build a kernel for this platform. + +config MIPS_IVR + bool "Support for Globespan IVR board" + help + This is an evaluation board built by Globespan to showcase thir + iVR (Internet Video Recorder) design. It utilizes a QED RM5231 + R5000 MIPS core. More information can be found out their website + located at P. Say Y + here if you wish to build a kernel for this platform. + +config LASAT + bool "Support for LASAT Networks platforms" + +config LASAT_100 + bool "Support for LASAT Networks 100 series" + depends on LASAT + +config LASAT_200 + bool "Support for LASAT Networks 200 series" + depends on LASAT + +config PICVUE + tristate "PICVUE LCD display driver" + depends on LASAT + +config PICVUE_PROC + tristate "PICVUE LCD display driver /proc interface" + depends on PICVUE + +config DS1603 + bool "DS1603 RTC driver" + depends on LASAT + +config LASAT_SYSCTL + bool "LASAT sysctl interface" + depends on LASAT + +config HP_LASERJET + bool "Support for Hewlett Packard LaserJet board" + +config IBM_WORKPAD + bool "Support for IBM WorkPad z50" + +config MIPS_ITE8172 + bool "Support for ITE 8172G board" + help + Ths is an evaluation board made by ITE + with ATX form factor that utilizes a MIPS R5000 to work with its + ITE8172G companion internet appliance chip. The MIPS core can be + either a NEC Vr5432 or QED RM5231. Say Y here if you wish to build + a kernel for this platform. + +config IT8172_REVC + bool "Support for older IT8172 (Rev C)" + depends on MIPS_ITE8172 + help + Say Y here to support the older, Revision C version of the Integrated + Technology Express, Inc. ITE8172 SBC. Vendor page at + ; picture of the + board at . + +config MIPS_ATLAS + bool "Support for MIPS Atlas board" + help + This enables support for the QED R5231-based MIPS Atlas evaluation + board. + +config MIPS_MAGNUM_4000 + bool "Support for MIPS Magnum 4000" + help + This is a machine with a R4000 100 MHz CPU. To compile a Linux + kernel that runs on these, say Y here. For details about Linux on + the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at + . + +config MIPS_MALTA + bool "Support for MIPS Malta board" + help + This enables support for the VR5000-based MIPS Malta evaluation + board. + +config MIPS_SEAD + bool "Support for MIPS SEAD board (EXPERIMENTAL)" + depends on EXPERIMENTAL + +config MOMENCO_OCELOT + bool "Support for Momentum Ocelot board" + help + The Ocelot is a MIPS-based Single Board Computer (SBC) made by + Momentum Computer . + +config MOMENCO_OCELOT_G + bool "Support for Momentum Ocelot-G board" + help + The Ocelot is a MIPS-based Single Board Computer (SBC) made by + Momentum Computer . + +config MOMENCO_OCELOT_C + bool "Support for Momentum Ocelot-C board" + help + The Ocelot is a MIPS-based Single Board Computer (SBC) made by + Momentum Computer . + +config DDB5074 + bool "Support for NEC DDB Vrc-5074 (EXPERIMENTAL)" + depends on EXPERIMENTAL + help + This enables support for the VR5000-based NEC DDB Vrc-5074 + evaluation board. + +config DDB5476 + bool "Support for NEC DDB Vrc-5476" + help + This enables support for the R5432-based NEC DDB Vrc-5476 + evaluation board. + + Features : kernel debugging, serial terminal, NFS root fs, on-board + ether port USB, AC97, PCI, PCI VGA card & framebuffer console, + IDE controller, PS2 keyboard, PS2 mouse, etc. + +config DDB5477 + bool "Support for NEC DDB Vrc-5477" + help + This enables support for the R5432-based NEC DDB Vrc-5477, + or Rockhopper/SolutionGear boards with R5432/R5500 CPUs. + + Features : kernel debugging, serial terminal, NFS root fs, on-board + ether port USB, AC97, PCI, etc. + +config DDB5477_BUS_FREQUENCY + int "bus frequency (in kHZ, 0 for auto-detect)" + depends on DDB5477 + default 0 + +config NEC_OSPREY + bool "Support for NEC Osprey board" + +config NEC_EAGLE + bool "Support for NEC Eagle/Hawk board" + +config OLIVETTI_M700 + bool "Support for Olivetti M700-10" + help + This is a machine with a R4000 100 MHz CPU. To compile a Linux + kernel that runs on these, say Y here. For details about Linux on + the MIPS architecture, check out the Linux/MIPS FAQ on the WWW at + . + +config SGI_IP22 + bool "Support for SGI IP22 (Indy/Indigo2)" + help + This are the SGI Indy, Challenge S and Indigo2, as well as certain + OEM variants like the Tandem CMN B006S. To compile a Linux kernel + that runs on these, say Y here. + +config SGI_IP27 + bool "Support for SGI IP27 (Origin200/2000)" + depends on MIPS64 + help + This are the SGI Origin 200, Origin 2000 and Onyx 2 Graphics + workstations. To compile a Linux kernel that runs on these, say Y + here. + +#config SGI_SN0_XXL +# bool "IP27 XXL" +# depends on SGI_IP27 +# This options adds support for userspace processes upto 16TB size. +# Normally the limit is just .5TB. + +config SGI_SN0_N_MODE + bool "IP27 N-Mode" + depends on SGI_IP27 + help + The nodes of Origin 200, Origin 2000 and Onyx 2 systems can be + configured in either N-Modes which allows for more nodes or M-Mode + which allows for more memory. Your system is most probably + running in M-Mode, so you should say N here. + +config DISCONTIGMEM + bool "Discontiguous Memory Support" + depends on SGI_IP27 + help + Say Y to upport efficient handling of discontiguous physical memory, + for architectures which are either NUMA (Non-Uniform Memory Access) + or have huge holes in the physical address space for other reasons. + See for more. + +config NUMA + bool "NUMA Support" + depends on SGI_IP27 + help + Say Y to compile the kernel to support NUMA (Non-Uniform Memory + Access). This option is for configuring high-end multiprocessor + server machines. If in doubt, say N. + +config MAPPED_KERNEL + bool "Mapped kernel support" + depends on SGI_IP27 + help + Change the way a Linux kernel is loaded unto memory on a MIPS64 + machine. This is required in order to support text replication and + NUMA. If you need to undersatand it, read the source code. + +config REPLICATE_KTEXT + bool "Kernel text replication support" + depends on SGI_IP27 + help + Say Y here to enable replicating the kernel text across multiple + nodes in a NUMA cluster. This trades memory for speed. + +config REPLICATE_EXHANDLERS + bool "Exception handler replication support" + depends on SGI_IP27 + help + Say Y here to enable replicating the kernel exception handlers + across multiple nodes in a NUMA cluster. This trades memory for + speed. + +config SGI_IP32 + bool "Support for SGI IP32 (O2) (EXPERIMENTAL)" + depends on EXPERIMENTAL + help + If you want this kernel to run on SGI O2 workstation, say Y here. + +config SOC_AU1X00 + depends on MIPS32 + bool "Support for AMD/Alchemy Au1X00 SOCs" + +choice + prompt "Au1X00 SOC Type" + depends on SOC_AU1X00 + help + Say Y here to enable support for one of three AMD/Alchemy + SOCs. For additional documentation see www.amd.com. + +config SOC_AU1000 + bool "SOC_AU1000" +config SOC_AU1100 + bool "SOC_AU1100" +config SOC_AU1500 + bool "SOC_AU1500" + +endchoice + +choice + prompt "AMD/Alchemy Pb1x and Db1x board support" + depends on SOC_AU1X00 + help + These are evaluation boards built by AMD/Alchemy to + showcase their Au1X00 Internet Edge Processors. The SOC design + is based on the MIPS32 architecture running at 266/400/500MHz + with many integrated peripherals. Further information can be + found at their website, . Say Y here if you + wish to build a kernel for this platform. + +config MIPS_PB1000 + bool "PB1000 board" + depends on SOC_AU1000 + +config MIPS_PB1100 + bool "PB1100 board" + depends on SOC_AU1100 + +config MIPS_PB1500 + bool "PB1500 board" + depends on SOC_AU1500 + +config MIPS_DB1000 + bool "DB1000 board" + depends on SOC_AU1000 + +config MIPS_DB1100 + bool "DB1100 board" + depends on SOC_AU1100 + +config MIPS_DB1500 + bool "DB1500 board" + depends on SOC_AU1500 + +endchoice + +config SIBYTE_SB1xxx_SOC + bool "Support for Broadcom BCM1xxx SOCs (EXPERIMENTAL)" + depends on EXPERIMENTAL + +choice + prompt "BCM1xxx SOC Type" + depends on SIBYTE_SB1xxx_SOC + default SIBYTE_SB1250 + +config SIBYTE_SB1250 + bool "BCM1250" + +endchoice + +config SIMULATION + bool "Running under simulation" + depends on SIBYTE_SB1xxx_SOC + +config SIBYTE_CFE + bool "Booting from CFE" + depends on SIBYTE_SB1xxx_SOC + +config SIBYTE_CFE_CONSOLE + bool "Use firmware console" + depends on SIBYTE_CFE + +config SIBYTE_STANDALONE + bool + depends on SIBYTE_SB1xxx_SOC && !SIBYTE_CFE + default y + +config SIBYTE_STANDALONE_RAM_SIZE + int "Memory size (in megabytes)" + depends on SIBYTE_SB1xxx_SOC && !SIBYTE_CFE + default "32" + +config SIBYTE_BUS_WATCHER + bool "Support for Bus Watcher statistics" + depends on SIBYTE_SB1xxx_SOC + +config SIBYTE_SB1250_PROF + bool "Support for SB1/SOC profiling - SB1/SCD perf counters" + depends on SIBYTE_SB1xxx_SOC + +config SIBYTE_TBPROF + bool "Support for ZBbus profiling" + depends on SIBYTE_SB1xxx_SOC + +config SIBYTE_SWARM + bool "Support for SWARM board" + depends on SIBYTE_SB1250 + +config SIBYTE_BOARD + bool + depends on SIBYTE_SWARM + default y + +config SNI_RM200_PCI + bool "Support for SNI RM200 PCI" + help + The SNI RM200 PCI was a MIPS-based platform manufactured by Siemens + Nixdorf Informationssysteme (SNI), parent company of Pyramid + Technology and now in turn merged with Fujitsu. Say Y here to + support this machine type. + +config TANBAC_TB0226 + bool "Support for TANBAC TB0226 (Mbase)" + help + The TANBAC TB0226 (Mbase) is a MIPS-based platform manufactured by TANBAC. + Please refer to about Mbase. + +config TANBAC_TB0229 + bool "Support for TANBAC TB0229 (VR4131DIMM)" + help + The TANBAC TB0229 (VR4131DIMM) is a MIPS-based platform manufactured by TANBAC. + Please refer to about VR4131DIMM. + +config TOSHIBA_JMR3927 + bool "Support for Toshiba JMR-TX3927 board" + depends on MIPS32 + +config TOSHIBA_RBTX4927 + bool "Support for Toshiba TBTX49[23]7 board" + depends on MIPS32 + +config VICTOR_MPC30X + bool "Support for Victor MP-C303/304" + +config ZAO_CAPCELLA + bool "Support for ZAO Networks Capcella" + +config RWSEM_GENERIC_SPINLOCK + bool + default y + +config RWSEM_XCHGADD_ALGORITHM + bool + +# +# Select some configuration options automatically based on user selections. +# +config ARC + bool + depends on SNI_RM200_PCI || SGI_IP32 || SGI_IP27 || SGI_IP22 || MIPS_MAGNUM_4000 || OLIVETTI_M700 || ACER_PICA_61 + default y + +config GENERIC_ISA_DMA + bool + depends on SNI_RM200_PCI || MIPS_MAGNUM_4000 || OLIVETTI_M700 || ACER_PICA_61 + default y + +config CONFIG_GT64120 + bool + depends on MIPS_EV64120 || MOMENCO_OCELOT + default y + +config I8259 + bool + depends on SNI_RM200_PCI || DDB5477 || DDB5476 || DDB5074 || MIPS_MALTA || MIPS_MAGNUM_4000 || OLIVETTI_M700 || MIPS_COBALT || ACER_PICA_61 + default y + +config MIPS_JAZZ + bool + depends on MIPS_MAGNUM_4000 || OLIVETTI_M700 || ACER_PICA_61 + default y + +config NONCOHERENT_IO + bool + depends on ZAO_CAPCELLA || VICTOR_MPC30X || TOSHIBA_JMR3927 || TOSHIBA_RBTX4927 || SNI_RM200_PCI || SGI_IP32 || SGI_IP22 || NEC_EAGLE || NEC_OSPREY || DDB5477 || DDB5476 || DDB5074 || MOMENCO_OCELOT || MOMENCO_OCELOT_C || MOMENCO_OCELOT_G || MIPS_SEAD || MIPS_MALTA || MIPS_MAGNUM_4000 || OLIVETTI_M700 || MIPS_ATLAS || LASAT || MIPS_ITE8172 || IBM_WORKPAD || HP_LASERJET || MIPS_IVR || MIPS_EV96100 || MIPS_EV64120 || DECSTATION || MIPS_COBALT || MIPS_PB1500 || MIPS_PB1100 || MIPS_PB1000 || CASIO_E55 || ACER_PICA_61 || TANBAC_TB0226 || TANBAC_TB0229 + default y if ZAO_CAPCELLA || VICTOR_MPC30X || TOSHIBA_JMR3927 || TOSHIBA_RBTX4927 || SNI_RM200_PCI || SGI_IP32 || SGI_IP22 || NEC_EAGLE || NEC_OSPREY || DDB5477 || DDB5476 || DDB5074 || MOMENCO_OCELOT_G || MOMENCO_OCELOT || MIPS_SEAD || MIPS_MALTA || MIPS_MAGNUM_4000 || OLIVETTI_M700 || MIPS_ATLAS || LASAT || MIPS_ITE8172 || IBM_WORKPAD || HP_LASERJET || MIPS_IVR || MIPS_EV96100 || MIPS_EV64120 || DECSTATION || MIPS_COBALT || MIPS_PB1500 || MIPS_PB1100 || MIPS_PB1000 || CASIO_E55 || ACER_PICA_61 || TANBAC_TB0226 || TANBAC_TB0229 + default n if (SIBYTE_SB1250 || SGI_IP27) + +config CPU_LITTLE_ENDIAN + bool "Generate little endian code" + default y if ACER_PICA_61 || CASIO_E55 || DDB5074 || DDB5476 || DDB5477 || DECSTATION || HP_LASERJET || IBM_WORKPAD || LASAT || MIPS_COBALT || MIPS_ITE8172 || MIPS_IVR || MIPS_PB1000 || MIPS_PB1100 || MIPS_PB1500 || NEC_OSPREY || NEC_EAGLE || OLIVETTI_M700 || SNI_RM200_PCI || VICTOR_MPC30X || ZAO_CAPCELLA + default n if BAGET_MIPS || MIPS_EV64120 || MIPS_EV96100 || MOMENCO_OCELOT || MOMENCO_OCELOT_G || SGI_IP22 || SGI_IP27 || SGI_IP32 || TOSHIBA_JMR3927 + help + Some MIPS machines can be configured for either little or big endian + byte order. These modes require different kernels. Say Y if your + machine is little endian, N if it's a big endian machine. + +config IRQ_CPU + bool + depends on ZAO_CAPCELLA || VICTOR_MPC30X || SGI_IP22 || NEC_EAGLE || NEC_OSPREY || DDB5477 || DDB5476 || DDB5074 || IBM_WORKPAD || HP_LASERJET || DECSTATION || CASIO_E55 || TANBAC_TB0226 || TANBAC_TB0229 + default y + +config VR41XX_TIME_C + bool + depends on ZAO_CAPCELLA || VICTOR_MPC30X || NEC_EAGLE || IBM_WORKPAD || CASIO_E55 || TANBAC_TB0226 || TANBAC_TB0229 + default y + +config DUMMY_KEYB + bool + depends on ZAO_CAPCELLA || VICTOR_MPC30X || SIBYTE_SB1250 || NEC_EAGLE || NEC_OSPREY || DDB5477 || IBM_WORKPAD || CASIO_E55 || TANBAC_TB0226 || TANBAC_TB0229 + default y + +config VR41XX_COMMON + bool + depends on NEC_EAGLE || ZAO_CAPCELLA || VICTOR_MPC30X || IBM_WORKPAD || CASIO_E55 || TANBAC_TB0226 || TANBAC_TB0229 + default y + +config VRC4173 + tristate "NEC VRC4173 Support" + depends on NEC_EAGLE || VICTOR_MPC30X + +config DDB5XXX_COMMON + bool + depends on DDB5074 || DDB5476 || DDB5477 + default y + +config MIPS_BOARDS_GEN + bool + depends on MIPS_ATLAS || MIPS_MALTA || MIPS_SEAD + default y + +config ITE_BOARD_GEN + bool + depends on MIPS_IVR || MIPS_ITE8172 + default y + +config NEW_PCI + bool + depends on ZAO_CAPCELLA || VICTOR_MPC30X || TOSHIBA_JMR3927 || TOSHIBA_RBTX4927 || NEC_EAGLE || DDB5477 || DDB5476 || DDB5074 || MIPS_ITE8172 || HP_LASERJET || MIPS_IVR || MIPS_EV96100 || MIPS_PB1500 || MIPS_PB1100 || MIPS_PB1000 || TANBAC_TB0226 || TANBAC_TB0229 + default y + +config SWAP_IO_SPACE + bool "Support for paging of anonymous memory" + depends on TOSHIBA_JMR3927 || TOSHIBA_RBTX4927 || SIBYTE_SB1250 || SGI_IP22 || MOMENCO_OCELOT_C || MOMENCO_OCELOT_G || MOMENCO_OCELOT || MIPS_MALTA || MIPS_ATLAS || MIPS_EV96100 || MIPS_PB1100 || MIPS_PB1000 + default y + help + This option allows you to choose whether you want to have support + for socalled swap devices or swap files in your kernel that are + used to provide more virtual memory than the actual RAM present + in your computer. If unusre say Y. + +config AU1000_USB_DEVICE + bool + depends on MIPS_PB1500 || MIPS_PB1100 || MIPS_PB1000 + default n + +config COBALT_LCD + bool + depends on MIPS_COBALT + default y + +config MIPS_GT64120 + bool + depends on MIPS_EV64120 + default y + +config MIPS_GT96100 + bool + depends on MIPS_EV96100 + default y + help + Say Y here to support the Galileo Technology GT96100 communications + controller card. There is a web page at . + +config IT8172_CIR + bool + depends on MIPS_ITE8172 || MIPS_IVR + default y + +config IT8712 + bool + depends on MIPS_ITE8172 + default y + +config BOOT_ELF32 + bool + depends on DECSTATION || MIPS_ATLAS || MIPS_MALTA || SIBYTE_SB1250 || SGI_IP32 || SGI_IP22 || SNI_RM200_PCI + default y + +config L1_CACHE_SHIFT + int + default "4" if DECSTATION + default "5" if SGI_IP32 || SGI_IP22 || MIPS_SEAD || MIPS_MALTA || MIPS_ATLAS + default "7" if SGI_IP27 + +config ARC32 + bool + depends on SNI_RM200_PCI || SGI_IP32 || SGI_IP22 || MIPS_MAGNUM_4000 || OLIVETTI_M700 + default y + +config FB + bool + depends on MIPS_MAGNUM_4000 || OLIVETTI_M700 + default y + ---help--- + The frame buffer device provides an abstraction for the graphics + hardware. It represents the frame buffer of some video hardware and + allows application software to access the graphics hardware through + a well-defined interface, so the software doesn't need to know + anything about the low-level (hardware register) stuff. + + Frame buffer devices work identically across the different + architectures supported by Linux and make the implementation of + application programs easier and more portable; at this point, an X + server exists which uses the frame buffer device exclusively. + On several non-X86 architectures, the frame buffer device is the + only way to use the graphics hardware. + + The device is accessed through special device nodes, usually located + in the /dev directory, i.e. /dev/fb*. + + You need an utility program called fbset to make full use of frame + buffer devices. Please read + and the Framebuffer-HOWTO at + for more + information. + + Say Y here and to the driver for your graphics board below if you + are compiling a kernel for a non-x86 architecture. + + If you are compiling for the x86 architecture, you can say Y if you + want to play with it, but it is not essential. Please note that + running graphical applications that directly touch the hardware + (e.g. an accelerated X server) and that are not frame buffer + device-aware may cause unexpected results. If unsure, say N. + +config FB_G364 + bool + depends on MIPS_MAGNUM_4000 || OLIVETTI_M700 + default y + +config HAVE_STD_PC_SERIAL_PORT + bool + depends on DDB5476 || DDB5074 || MIPS_MALTA + default y + +config VR4181 + bool + depends on NEC_OSPREY + default y + +config ARC_CONSOLE + bool "ARC console support" + depends on SGI_IP22 || SNI_RM200_PCI + +config ARC_MEMORY + bool + depends on SNI_RM200_PCI || SGI_IP32 + default y + +config ARC_PROMLIB + bool + depends on SNI_RM200_PCI || SGI_IP32 || SGI_IP22 + default y + +config BOARD_SCACHE + bool + depends on MIPS_EV96100 || MOMENCO_OCELOT || SGI_IP22 + default y + +config ARC64 + bool + depends on SGI_IP27 + default y + +config BOOT_ELF64 + bool + depends on SGI_IP27 + default y + +#config MAPPED_PCI_IO y +# bool +# depends on SGI_IP27 +# default y + +config QL_ISP_A64 + bool + depends on SGI_IP27 + default y + +config TOSHIBA_BOARDS + bool + depends on TOSHIBA_JMR3927 || TOSHIBA_RBTX4927 + default y + +config TANBAC_TB0219 + bool "Added TANBAC TB0219 Base board support" + depends on TANBAC_TB0229 + +endmenu + + +menu "CPU selection" + +choice + prompt "CPU type" + default CPU_R4X00 + +config CPU_MIPS32 + bool "MIPS32" + +config CPU_MIPS64 + bool "MIPS64" + +config CPU_R3000 + bool "R3000" + depends on MIPS32 + help + Please make sure to pick the right CPU type. Linux/MIPS is not + designed to be generic, i.e. Kernels compiled for R3000 CPUs will + *not* work on R4000 machines and vice versa. However, since most + of the supported machines have an R4000 (or similar) CPU, R4x00 + might be a safe bet. If the resulting kernel does not work, + try to recompile with R3000. + +config CPU_TX39XX + bool "R39XX" + depends on MIPS32 + +config CPU_VR41XX + bool "R41xx" + help + The options selects support for the NEC VR41xx series of processors. + Only choose this option if you have one of these processors as a + kernel built with this option will not run on any other type of + processor or vice versa. + +config CPU_R4300 + bool "R4300" + help + MIPS Technologies R4300-series processors. + +config CPU_R4X00 + bool "R4x00" + help + MIPS Technologies R4000-series processors other than 4300, including + the R4000, R4400, R4600, and 4700. + +config CPU_TX49XX + bool "R49XX" + +config CPU_R5000 + bool "R5000" + help + MIPS Technologies R5000-series processors other than the Nevada. + +config CPU_R5432 + bool "R5432" + +config CPU_R6000 + bool "R6000" + depends on MIPS32 && EXPERIMENTAL + help + MIPS Technologies R6000 and R6000A series processors. Note these + processors are extremly rare and the support for them is incomplete. + +config CPU_NEVADA + bool "R52xx" + help + MIPS Technologies R52x0-series ("Nevada") processors. + +config CPU_R8000 + bool "R8000" + depends on MIPS64 && EXPERIMENTAL + help + MIPS Technologies R8000 processors. Note these processors are + uncommon and the support for them is incomplete. + +config CPU_R10000 + bool "R10000" + help + MIPS Technologies R10000-series processors. + +config CPU_RM7000 + bool "RM7000" + +config CPU_SB1 + bool "SB1" + +endchoice + +config R5000_CPU_SCACHE + bool + depends on CPU_NEVADA || CPU_R5000 + default y if SGI_IP32 || LASAT + +config BOARD_SCACHE + bool + depends on CPU_NEVADA || CPU_R4X00 || CPU_R5000 + default y if SGI_IP22 || (SGI_IP32 && CPU_R5000) || R5000_CPU_SCACHE + +config CPU_HAS_PREFETCH + bool "Enable prefetches" if CPU_SB1 && !CPU_SB1_PASS_2 + default y if CPU_RM7000 || CPU_MIPS64 || CPU_MIPS32 + +config VTAG_ICACHE + bool "Support for Virtual Tagged I-cache" if CPU_MIPS64 || CPU_MIPS32 + default y if CPU_SB1 + +choice + prompt "SB1 Pass" + depends on CPU_SB1 + default CPU_SB1_PASS_1 + +config CPU_SB1_PASS_1 + bool "Pass1" + +config CPU_SB1_PASS_2 + bool "Pass2" + +config CPU_SB1_PASS_2_2 + bool "Pass2.2" + +endchoice + +config SB1_PASS_1_WORKAROUNDS + bool + depends on CPU_SB1_PASS_1 + default y + +config SB1_PASS_2_WORKAROUNDS + bool + depends on CPU_SB1 && (CPU_SB1_PASS_2_2 || CPU_SB1_PASS_2) + default y + +# Avoid prefetches on Pass 2 (before 2.2) +# XXXKW for now, let 2.2 use same WORKAROUNDS flag as pre-2.2 +config SB1_CACHE_ERROR + bool "Support for SB1 Cache Error handler" + depends on CPU_SB1 + +config SB1_CERR_IGNORE_RECOVERABLE + bool "Ignore recoverable cache errors" + depends on SB1_CACHE_ERROR + +config SB1_CERR_SPIN + bool "Spin instead of running handler" + depends on SB1_CACHE_ERROR + +config 64BIT_PHYS_ADDR + bool "Support for 64-bit physical address space" + depends on (CPU_R4X00 || CPU_R5000 || CPU_RM7000 || CPU_R10000 || CPU_SB1 || CPU_MIPS32 || CPU_MIPS64) && MIPS32 + +config CPU_ADVANCED + bool "Override CPU Options" + depends on MIPS32 + help + Saying yes here allows you to select support for various features + your CPU may or may not have. Most people should say N here. + +config CPU_HAS_LLSC + bool "ll/sc Instructions available" if CPU_ADVANCED + default y if !CPU_ADVANCED && !CPU_R3000 && !CPU_VR41XX && !CPU_TX39XX + help + MIPS R4000 series and later provide the Load Linked (ll) + and Store Conditional (sc) instructions. More information is + available at . + + Say Y here if your CPU has the ll and sc instructions. Say Y here + for better performance, N if you don't know. You must say Y here + for multiprocessor machines. + +config CPU_HAS_LLDSCD + bool "lld/scd Instructions available" if CPU_ADVANCED + default y if !CPU_ADVANCED && !CPU_R3000 && !CPU_VR41XX && !CPU_TX39XX && !CPU_MIPS32 + help + Say Y here if your CPU has the lld and scd instructions, the 64-bit + equivalents of ll and sc. Say Y here for better performance, N if + you don't know. You must say Y here for multiprocessor machines. + +config CPU_HAS_WB + bool "Writeback Buffer available" if CPU_ADVANCED + default y if !CPU_ADVANCED && (CPU_R3000 || CPU_VR41XX || CPU_TX39XX) && DECSTATION + help + Say N here for slightly better performance. You must say Y here for + machines which require flushing of write buffers in software. Saying + Y is the safe option; N may result in kernel malfunction and crashes. + +config CPU_HAS_SYNC + bool + depends on !CPU_R3000 + default y + +# +# - Highmem only makes sense for the 32-bit kernel. +# - The current highmem code will only work properly on physically indexed +# caches such as R3000, SB1, R7000 or those that look like they're virtually +# indexed such as R4000/R4400 SC and MC versions or R10000. So for the +# moment we protect the user and offer the highmem option only on machines +# where it's known to be safe. This will not offer highmem on a few systems +# such as MIPS32 and MIPS64 CPUs which may have virtual and physically +# indexed CPUs but we're playing safe. +# - We should not offer highmem for system of which we already know that they +# don't have memory configurations that could gain from highmem support in +# the kernel because they don't support configurations with RAM at physical +# addresses > 0x20000000. +# +config HIGHMEM + bool "High Memory Support" + depends on MIPS32 && (CPU_R3000 || CPU_SB1 || CPU_R7000 || CPU_R10000) && !(BAGET_MIPS || DECSTATION) + +config SMP + bool "Multi-Processing support" + depends on SIBYTE_SB1xxx_SOC && SIBYTE_SB1250 && !SIBYTE_STANDALONE || SGI_IP27 + ---help--- + This enables support for systems with more than one CPU. If you have + a system with only one CPU, like most personal computers, say N. If + you have a system with more than one CPU, say Y. + + If you say N here, the kernel will run on single and multiprocessor + machines, but will use only one CPU of a multiprocessor machine. If + you say Y here, the kernel will run on many, but not all, + singleprocessor machines. On a singleprocessor machine, the kernel + will run faster if you say N here. + + People using multiprocessor machines who say Y here should also say + Y to "Enhanced Real Time Clock Support", below. + + See also the , + and the SMP-HOWTO available at + . + + If you don't know what to do here, say N. + +config NR_CPUS + int "Maximum number of CPUs (2-32)" + depends on SMP + default "32" + help + This allows you to specify the maximum number of CPUs which this + kernel will support. The maximum supported value is 32 and the + minimum value which makes sense is 2. + + This is purely to save memory - each supported CPU adds + approximately eight kilobytes to the kernel image. + +config PREEMPT + bool "Preemptible Kernel" + help + This option reduces the latency of the kernel when reacting to + real-time or interactive events by allowing a low priority process to + be preempted even if it is in kernel mode executing a system call. + This allows applications to run more reliably even when the system is + under load. + +config KALLSYMS + bool "Load all symbols for debugging/kksymoops" + help + Say Y here to let the kernel print out symbolic crash information and + symbolic stack backtraces. This increases the size of the kernel + somewhat, as all symbols have to be loaded into the kernel image. + +config DEBUG_SPINLOCK_SLEEP + bool "Sleep-inside-spinlock checking" + help + If you say Y here, various routines which may sleep will become very + noisy if they are called with a spinlock held. + +config RTC_DS1742 + bool "DS1742 BRAM/RTC support" + depends on TOSHIBA_JMR3927 || TOSHIBA_RBTX4927 + +config MIPS_INSANE_LARGE + bool "Support for large 64-bit configurations" + depends on CPU_R10000 && MIPS64 + help + MIPS R10000 does support a 44 bit / 16TB address space as opposed to + previous 64-bit processors which only supported 40 bit / 1TB. If you + need processes of more than 1TB virtual address space, say Y here. + This will result in additional memory usage, so it is not + recommended for normal users. + +config RWSEM_GENERIC_SPINLOCK + bool + default y + +endmenu + +menu "Bus options (PCI, PCMCIA, EISA, ISA, TC)" + +config PCI + bool "Support for PCI controller" + depends on MIPS_DB1000 || DDB5074 || DDB5476 || DDB5477 || HP_LASERJET || LASAT || MIPS_IVR || MIPS_ATLAS || MIPS_COBALT || MIPS_EV64120 || MIPS_EV96100 || MIPS_ITE8172 || MIPS_MALTA || MOMENCO_OCELOT || MOMENCO_OCELOT_C || MOMENCO_OCELOT_G || MIPS_PB1000 || MIPS_PB1100 || MIPS_PB1500 || NEC_EAGLE || SGI_IP27 || SGI_IP32 || SIBYTE_SB1250 || SNI_RM200_PCI || TANBAC_TB0226 || TANBAC_TB0229 || TOSHIBA_JMR3927 || TOSHIBA_RBTX4927 || VICTOR_MPC30X || ZAO_CAPCELLA + help + Find out whether you have a PCI motherboard. PCI is the name of a + bus system, i.e. the way the CPU talks to the other stuff inside + your box. Other bus systems are ISA, EISA, or VESA. If you have PCI, + say Y, otherwise N. + + The PCI-HOWTO, available from + , contains valuable + information about which PCI hardware does work under Linux and which + doesn't. + +source "drivers/pci/Kconfig" + +config ISA + bool "ISA bus support" + depends on ACER_PICA_61 || SGI_IP22 || MIPS_MAGNUM_4000 || OLIVETTI_M700 || SNI_RM200_PCI + default y if TOSHIBA_RBTX4927 || DDB5476 || DDB5074 || IBM_WORKPAD || CASIO_E55 + help + Find out whether you have ISA slots on your motherboard. ISA is the + name of a bus system, i.e. the way the CPU talks to the other stuff + inside your box. Other bus systems are PCI, EISA, or VESA. ISA is + an older system, now being displaced by PCI; newer boards don't + support it. If you have ISA, say Y, otherwise N. + +# +# The SCSI bits are needed to get the SCSI code to link ... +# +config GENERIC_ISA_DMA + bool + default y if ACER_PICA_61 || MIPS_MAGNUM_4000 || OLIVETTI_M700 || SNI_RM200_PCI || SCSI + +config EISA + bool "EISA support" + depends on ISA && (SGI_IP22 || SNI_RM200_PCI) + ---help--- + The Extended Industry Standard Architecture (EISA) bus was + developed as an open alternative to the IBM MicroChannel bus. + + The EISA bus provided some of the features of the IBM MicroChannel + bus while maintaining backward compatibility with cards made for + the older ISA bus. The EISA bus saw limited use between 1988 and + 1995 when it was made obsolete by the PCI bus. + + Say Y here if you are building a kernel for an EISA-based machine. + + Otherwise, say N. + +source "drivers/eisa/Kconfig" + +config TC + bool "TURBOchannel support" + depends on DECSTATION + help + TurboChannel is a DEC (now Compaq (now HP)) bus for Alpha and MIPS + processors. Documentation on writing device drivers for TurboChannel + is available at: + . + +#config ACCESSBUS +# bool "Access.Bus support" +# depends on TC + +config MMU + bool + default y + +config MCA + bool + +config SBUS + bool + +config HOTPLUG + bool "Support for hot-pluggable devices" + ---help--- + Say Y here if you want to plug devices into your computer while + the system is running, and be able to use them quickly. In many + cases, the devices can likewise be unplugged at any time too. + + One well known example of this is PCMCIA- or PC-cards, credit-card + size devices such as network cards, modems or hard drives which are + plugged into slots found on all modern laptop computers. Another + example, used on modern desktops as well as laptops, is USB. + + Enable HOTPLUG and KMOD, and build a modular kernel. Get agent + software (at ) and install it. + Then your kernel will automatically call out to a user mode "policy + agent" (/sbin/hotplug) to load modules and set up software needed + to use devices as you hotplug them. + +source "drivers/pcmcia/Kconfig" + +source "drivers/pci/hotplug/Kconfig" + +endmenu + +menu "Executable file formats" + +config KCORE_ELF + bool + default y + ---help--- + If you enabled support for /proc file system then the file + /proc/kcore will contain the kernel core image. This can be used + in gdb: + + $ cd /usr/src/linux ; gdb vmlinux /proc/kcore + + You have two choices here: ELF and A.OUT. Selecting ELF will make + /proc/kcore appear in ELF core format as defined by the Executable + and Linking Format specification. Selecting A.OUT will choose the + old "a.out" format which may be necessary for some old versions + of binutils or on some architectures. + + This is especially useful if you have compiled the kernel with the + "-g" option to preserve debugging information. It is mainly used + for examining kernel data structures on the live kernel so if you + don't understand what this means or are not a kernel hacker, just + leave it at its default value ELF. + +config KCORE_AOUT + bool + +source "fs/Kconfig.binfmt" + +config BINFMT_IRIX + bool "Include IRIX binary compatibility" + depends on !CPU_LITTLE_ENDIAN && MIPS32 + +config MIPS32_COMPAT + bool "Kernel support for Linux/MIPS 32-bit binary compatibility" + depends on MIPS64 + help + Select this option if you want Linux/MIPS 32-bit binary + compatibility. Since all software available for Linux/MIPS is + currently 32-bit you should say Y here. + +config COMPAT + bool + depends on MIPS32_COMPAT + default y + +config MIPS32_O32 + bool "Kernel support for o32 binaries" + depends on MIPS32_COMPAT + help + Select this option if you want to run o32 binaries. These are pure + 32-bit binaries as used by the 32-bit Linux/MIPS port. Most of + existing binaries are in this format. + + If unsure, say Y. + +config MIPS32_N32 + bool "Kernel support for n32 binaries" + depends on MIPS32_COMPAT + help + Select this option if you want to run n32 binaries. These are + 64-bit binaries using 32-bit quantities for addressing and certain + data that would normally be 64-bit. They are used in special + cases. + + If unsure, say N. + +config BINFMT_ELF32 + bool + default y if MIPS32_O32 || MIPS32_N32 + +config PM + bool "Power Management support (EXPERIMENTAL)" + depends on EXPERIMENTAL && SOC_AU1X00 + +endmenu + +source "drivers/mtd/Kconfig" + +source "drivers/parport/Kconfig" + +source "drivers/pnp/Kconfig" + +source "drivers/base/Kconfig" + +source "drivers/block/Kconfig" + + +menu "MIPS initrd options" + depends on BLK_DEV_INITRD + +config EMBEDDED_RAMDISK + bool "Embed root filesystem ramdisk into the kernel" + +config EMBEDDED_RAMDISK_IMAGE + string "Filename of gziped ramdisk image" + depends on EMBEDDED_RAMDISK + default "ramdisk.gz" + help + This is the filename of the ramdisk image to be built into the + kernel. Relative pathnames are relative to arch/mips/ramdisk/. + The ramdisk image is not part of the kernel distribution; you must + provide one yourself. + +endmenu + +source "drivers/ide/Kconfig" + +source "drivers/scsi/Kconfig" + +source "drivers/cdrom/Kconfig" + +source "drivers/md/Kconfig" + +source "drivers/message/fusion/Kconfig" + +source "drivers/ieee1394/Kconfig" + +source "drivers/message/i2o/Kconfig" + +source "net/Kconfig" + +source "net/ax25/Kconfig" + +source "net/irda/Kconfig" + +source "drivers/isdn/Kconfig" + +source "drivers/telephony/Kconfig" + +# +# input before char - char/joystick depends on it. As does USB. +# +source "drivers/input/Kconfig" + +source "drivers/char/Kconfig" + +#source drivers/misc/Config.in + +source "drivers/media/Kconfig" + +source "fs/Kconfig" + +source "drivers/video/Kconfig" + + +menu "Sound" + +config SOUND + tristate "Sound card support" + ---help--- + If you have a sound card in your computer, i.e. if it can say more + than an occasional beep, say Y. Be sure to have all the information + about your sound card and its configuration down (I/O port, + interrupt and DMA channel), because you will be asked for it. + + You want to read the Sound-HOWTO, available from + . General information about + the modular sound system is contained in the files + . The file + contains some slightly + outdated but still useful information as well. + + If you have a PnP sound card and you want to configure it at boot + time using the ISA PnP tools (read + ), then you need to + compile the sound card support as a module ( = code which can be + inserted in and removed from the running kernel whenever you want) + and load that module after the PnP configuration is finished. To do + this, say M here and read as well + as ; the module will be + called soundcore. + + I'm told that even without a sound card, you can make your computer + say more than an occasional beep, by programming the PC speaker. + Kernel patches and supporting utilities to do that are in the pcsp + package, available at . + +source "sound/Kconfig" + +endmenu + +source "drivers/usb/Kconfig" + +source "net/bluetooth/Kconfig" + + +menu "Kernel hacking" + +config CROSSCOMPILE + bool "Are you using a crosscompiler" + help + Say Y here if you are compiling the kernel on a different + architecture than the one it is intended to run on. + +config DEBUG_KERNEL + bool "Kernel debugging" + +config KGDB + bool "Remote GDB kernel debugging" + depends on DEBUG_KERNEL + help + If you say Y here, it will be possible to remotely debug the MIPS + kernel using gdb. This enlarges your kernel image disk size by + several megabytes and requires a machine with more than 16 MB, + better 32 MB RAM to avoid excessive linking time. This is only + useful for kernel hackers. If unsure, say N. + +config GDB_CONSOLE + bool "Console output to GDB" + depends on KGDB + help + If you are using GDB for remote debugging over a serial port and + would like kernel messages to be formatted into GDB $O packets so + that GDB prints them as program output, say 'Y'. + +config RUNTIME_DEBUG + bool "Enable run-time debugging" + depends on DEBUG_KERNEL + help + If you say Y here, some debugging macros will do run-time checking. + If you say N here, those macros will mostly turn to no-ops. See + include/asm-mips/debug.h for debuging macros. + If unsure, say N. + + +config MAGIC_SYSRQ + bool "Magic SysRq key" + depends on DEBUG_KERNEL + help + If you say Y here, you will have some control over the system even + if the system crashes for example during kernel debugging (e.g., you + will be able to flush the buffer cache to disk, reboot the system + immediately or dump some status information). This is accomplished + by pressing various keys while holding SysRq (Alt+PrintScreen). It + also works on a serial console (on PC hardware at least), if you + send a BREAK and then within 5 seconds a command keypress. The + keys are documented in . Don't say Y + unless you really know what this hack does. + +config MIPS_UNCACHED + bool "Run uncached" + depends on DEBUG_KERNEL && !SMP && !SGI_IP27 + help + If you say Y here there kernel will disable all CPU caches. This will + reduce the system's performance dramatically but can help finding + otherwise hard to track bugs. It can also useful if you're doing + hardware debugging with a logic analyzer and need to see all traffic + on the bus. + +config DEBUG_HIGHMEM + bool "Highmem debugging" + depends on DEBUG_KERNEL && HIGHMEM + +endmenu + +source "security/Kconfig" + +source "crypto/Kconfig" + +source "lib/Kconfig" diff -Nru a/arch/mips/Makefile b/arch/mips/Makefile --- a/arch/mips/Makefile Tue Jul 1 18:44:31 2003 +++ b/arch/mips/Makefile Tue Jul 1 18:44:31 2003 @@ -5,11 +5,11 @@ # # Copyright (C) 1994, 1995, 1996 by Ralf Baechle # DECStation modifications by Paul M. Antoine, 1996 +# Copyright (C) 2002 Maciej W. Rozycki # # This file is included by the global makefile so that you can add your own # architecture-specific flags and dependencies. Remember to do have actions -# for "archclean" and "archdep" for cleaning up and making dependencies for -# this architecture +# for "archclean" cleaning up for this architecture. # # @@ -17,16 +17,20 @@ # ifdef CONFIG_CPU_LITTLE_ENDIAN tool-prefix = mipsel-linux- +JIFFIES32 = jiffies_64 +LDFLAGS_BLOB := --format binary --oformat elf32-tradlittlemips else tool-prefix = mips-linux- +JIFFIES32 = jiffies_64 + 4 +LDFLAGS_BLOB := --format binary --oformat elf32-tradbigmips endif ifdef CONFIG_CROSSCOMPILE -CROSS_COMPILE = $(tool-prefix) +CROSS_COMPILE := $(tool-prefix) endif # -# GCC uses -G0 -mabicalls -fpic as default. We don't want PIC in the kernel +# GCC uses -G 0 -mabicalls -fpic as default. We don't want PIC in the kernel # code since it only slows down the whole thing. At some point we might make # use of global pointer optimizations but their use of $28 conflicts with # the current pointer optimization. @@ -35,218 +39,314 @@ # machines may also. Since BFD is incredibly buggy with respect to # crossformat linking we rely on the elf2ecoff tool for format conversion. # -GCCFLAGS := -G 0 -mno-abicalls -fno-pic -LDFLAGS_vmlinux += -static -MODFLAGS += -mlong-calls -LDFLAGS := -G 0 +cflags-y := -I $(TOPDIR)/include/asm/gcc +cflags-y += -G 0 -mno-abicalls -fno-pic -pipe +LDFLAGS_vmalinux += -G 0 -static # -N +MODFLAGS += -mlong-calls -ifdef CONFIG_REMOTE_DEBUG -CFLAGS := $(CFLAGS) -g -endif +cflags-$(CONFIG_KGDB) += -g +cflags-$(CONFIG_SB1XXX_CORELIS) += -mno-sched-prolog -fno-omit-frame-pointer + +check_gcc = $(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi) # # CPU-dependent compiler/assembler options for optimization. # -ifdef CONFIG_CPU_R3000 -GCCFLAGS += -mcpu=r3000 -mips1 -endif -ifdef CONFIG_CPU_R6000 -GCCFLAGS += -mcpu=r6000 -mips2 -Wa,--trap -endif -ifdef CONFIG_CPU_R4300 -GCCFLAGS += -mcpu=r4300 -mips2 -Wa,--trap -endif -ifdef CONFIG_CPU_VR41XX -GCCFLAGS += -mcpu=r4600 -mips2 -Wa,--trap -endif -ifdef CONFIG_CPU_R4X00 -GCCFLAGS += -mcpu=r4600 -mips2 -Wa,--trap -endif -ifdef CONFIG_CPU_MIPS32 -GCCFLAGS += -mcpu=r4600 -mips2 -Wa,--trap -endif -ifdef CONFIG_CPU_MIPS64 -GCCFLAGS += -mcpu=r4600 -mips2 -Wa,--trap -endif -ifdef CONFIG_CPU_R5000 -GCCFLAGS += -mcpu=r5000 -mips2 -Wa,--trap -endif -ifdef CONFIG_CPU_R5432 -GCCFLAGS += -mcpu=r5000 -mips2 -Wa,--trap -endif -ifdef CONFIG_CPU_NEVADA +cflags-$(CONFIG_CPU_R3000) += -mcpu=r3000 -mips1 +cflags-$(CONFIG_CPU_TX39XX) += -mcpu=r3000 -mips1 +cflags-$(CONFIG_CPU_R6000) += -mcpu=r6000 -mips2 -Wa,--trap +cflags-$(CONFIG_CPU_R4300) += -mcpu=r4300 -mips2 -Wa,--trap +cflags-$(CONFIG_CPU_VR41XX) += -mcpu=r4600 -mips2 -Wa,--trap +cflags-$(CONFIG_CPU_R4X00) += -mcpu=r4600 -mips2 -Wa,--trap +cflags-$(CONFIG_CPU_TX49XX) += -mcpu=r4600 -mips2 -Wa,--trap +cflags-$(CONFIG_CPU_MIPS32) += -mcpu=r4600 -mips2 -Wa,--trap +cflags-$(CONFIG_CPU_MIPS64) += -mcpu=r4600 -mips2 -Wa,--trap +cflags-$(CONFIG_CPU_R5000) += -mcpu=r5000 -mips2 -Wa,--trap +cflags-$(CONFIG_CPU_R5432) += -mcpu=r5000 -mips2 -Wa,--trap # Cannot use -mmad with currently recommended tools -GCCFLAGS += -mcpu=r5000 -mips2 -Wa,--trap -endif -ifdef CONFIG_CPU_RM7000 -GCCFLAGS += -mcpu=r5000 -mips2 -Wa,--trap -endif +cflags-$(CONFIG_CPU_NEVADA) += -mcpu=r5000 -mips2 -Wa,--trap +cflags-$(CONFIG_CPU_RM7000) += -mcpu=r5000 -mips2 -Wa,--trap +cflags-$(CONFIG_CPU_RM7000) += $(call check_gcc, -mcpu=r7000, -mcpu=r5000) \ + -mips2 -Wa,--trap +cflags-$(CONFIG_CPU_SB1) += $(call check_gcc, -mcpu=sb1, -mcpu=r8000) \ + -mips2 -Wa,--trap ifdef CONFIG_CPU_SB1 -GCCFLAGS += -mcpu=sb1 -mips2 -Wa,--trap +ifdef CONFIG_SB1_PASS_1_WORKAROUNDS +MODFLAGS += -msb1-pass1-workarounds endif +endif + +AFLAGS += $(cflags-y) +CFLAGS += $(cflags-y) -GCCFLAGS += -pipe -CFLAGS := -I $(TOPDIR)/include/asm/gcc $(CFLAGS) $(GCCFLAGS) -AFLAGS += $(GCCFLAGS) -ASFLAGS += $(GCCFLAGS) +# +# ramdisk/initrd support +# You need a compressed ramdisk image, named ramdisk.gz in +# arch/mips/ramdisk +# +ifdef CONFIG_EMBEDDED_RAMDISK +CORE_FILES += arch/mips/ramdisk/ramdisk.o +SUBDIRS += arch/mips/ramdisk +endif # -# We unconditionally build the math emulator +# Firmware support # -core-y += arch/mips/math-emu/ +libs-$(CONFIG_ARC) += arch/mips/arc/ +libs-$(CONFIG_SIBYTE_CFE) += arch/mips/sibyte/cfe/ # # Board-dependent options and extra files # -ifdef CONFIG_ALGOR_P4032 -core-y += arch/mips/algor/ -LOADADDR += 0x80000000 -endif # -# DECstation family +# Acer PICA 61, Mips Magnum 4000 and Olivetti M700. # -ifdef CONFIG_DECSTATION -core-y += arch/mips/dec/ -libs-y += arch/mips/dec/prom/ -LOADADDR += 0x80040000 -endif +core-$(CONFIG_MIPS_JAZZ) += arch/mips/jazz/ +load-$(CONFIG_MIPS_JAZZ) += 0x80080000 -ifdef CONFIG_MIPS_ATLAS -core-y += arch/mips/mips-boards/atlas/ arch/mips/mips-boards/generic/ -LOADADDR += 0x80100000 -endif -ifdef CONFIG_MIPS_MALTA -core-y += arch/mips/mips-boards/malta/ arch/mips/mips-boards/generic/ -LOADADDR += 0x80100000 -endif +# +# Au1500 (Alchemy Semi PB1500) eval board +# +core-$(CONFIG_MIPS_PB1500) += arch/mips/au1000/common/ +libs-$(CONFIG_MIPS_PB1500) += arch/mips/au1000/pb1500/ +load-$(CONFIG_MIPS_PB1500) += 0x80100000 # -# Acer PICA 61, Mips Magnum 4000 and Olivetti M700. +# Baget/MIPS # -ifdef CONFIG_MIPS_JAZZ -core-y += arch/mips/jazz/ -libs-y += arch/mips/arc/ -LOADADDR += 0x80080000 -endif +libs-$(CONFIG_BAGET_MIPS) += arch/mips/baget/ arch/mips/baget/prom/ +load-$(CONFIG_BAGET_MIPS) += 0x80001000 -ifdef CONFIG_SNI_RM200_PCI -core-y += arch/mips/sni/ -libs-y += arch/mips/arc/ -LOADADDR += 0x80080000 -endif +# +# Cobalt Server +# +core-$(CONFIG_MIPS_COBALT) += arch/mips/cobalt/ +load-$(CONFIG_MIPS_COBALT) += 0x80080000 -ifdef CONFIG_SGI_IP22 -core-y += arch/mips/sgi/kernel/ -libs-y += arch/mips/arc/ -# -# Set LOADADDR to >= 0x88069000 if you want to leave space for symmon, -# 0x88002000 for production kernels. Note that the value must be -# 8kb aligned or the handling of the current variable will break. # -LOADADDR += 0x88002000 -endif +# DECstation family +# +core-$(CONFIG_DECSTATION) += arch/mips/dec/ +libs-$(CONFIG_DECSTATION) += arch/mips/dec/prom/ +load-$(CONFIG_DECSTATION) += 0x80040000 +CLEAN_FILES += drivers/tc/lk201-map.c # -# Baget/MIPS +# Galileo EV64120 Board # -ifdef CONFIG_BAGET_MIPS -core-y += arch/mips/baget/ -libs-y += arch/mips/baget/prom/ -LOADADDR += 0x80001000 -endif +core-$(CONFIG_MIPS_EV64120) += arch/mips/galileo-boards/ev64120/ +load-$(CONFIG_MIPS_EV64120) += 0x80100000 # -# NEC DDB Vrc-5074 +# Galileo EV96100 Board # -ifdef CONFIG_DDB5074 -core-y += arch/mips/ddb5074/ -LOADADDR += 0x80080000 -endif +core-$(CONFIG_MIPS_EV96100) += arch/mips/galileo-boards/generic/ \ + arch/mips/galileo-boards/ev96100/ +load-$(CONFIG_MIPS_EV96100) += 0x80100000 # +# Globespan IVR eval board with QED 5231 CPU # -# NEC DDB Vrc-5476 +core-$(CONFIG_ITE_BOARD_GEN) += arch/mips/ite-boards/generic/ +core-$(CONFIG_MIPS_IVR) += arch/mips/ite-boards/ivr/ +load-$(CONFIG_MIPS_IVR) += 0x80100000 + # -ifdef CONFIG_DDB5476 -core-y += arch/mips/ddb5476/ -LOADADDR += 0x80080000 -endif +# HP LaserJet +# +core-$(CONFIG_HP_LASERJET) += arch/mips/hp-lj/ +load-$(CONFIG_HP_LASERJET) += 0x80030000 # +# ITE 8172 eval board with QED 5231 CPU # -# NEC DDB Vrc-5477 +core-$(CONFIG_MIPS_ITE8172) += arch/mips/ite-boards/qed-4n-s01b/ +load-$(CONFIG_MIPS_ITE8172) += 0x80100000 + # -ifdef CONFIG_DDB5477 -core-y += arch/mips/ddb5xxx/common/ \ - arch/mips/ddb5xxx/ddb5477/ -LOADADDR += 0x80080000 -endif +# MIPS Atlas board +# +core-$(CONFIG_MIPS_BOARDS_GEN) += arch/mips/mips-boards/generic/ +core-$(CONFIG_MIPS_ATLAS) += arch/mips/mips-boards/atlas/ +load-$(CONFIG_MIPS_ATLAS) += 0x80100000 # -# Galileo EV64120 Board +# MIPS Malta board # -ifdef CONFIG_MIPS_EV64120 -core-y += arch/mips/galileo-boards/ev64120/ -LOADADDR += 0x80100000 -endif +core-$(CONFIG_MIPS_MALTA) += arch/mips/mips-boards/malta/ +load-$(CONFIG_MIPS_MALTA) := 0x80100000 # -# Galileo EV96100 Board +# MIPS SEAD board # -ifdef CONFIG_MIPS_EV96100 -core-y += arch/mips/galileo-boards/ev96100/ \ - arch/mips/galileo-boards/generic/ -LOADADDR += 0x80100000 -endif +core-$(CONFIG_MIPS_SEAD) += arch/mips/mips-boards/sead/ +load-$(CONFIG_MIPS_SEAD) += 0x80100000 # # Momentum Ocelot board # -ifdef CONFIG_MOMENCO_OCELOT # The Ocelot setup.o must be linked early - it does the ioremap() for the # mips_io_port_base. -core-y += arch/mips/gt64120/common/ \ - arch/mips/gt64120/momenco_ocelot/ -LOADADDR += 0x80100000 -endif +# +core-$(CONFIG_MOMENCO_OCELOT) += arch/mips/gt64120/common/ \ + arch/mips/gt64120/momenco_ocelot/ +load-$(CONFIG_MOMENCO_OCELOT) += 0x80100000 # -# Philips Nino +# Momentum Ocelot-G board # -ifdef CONFIG_NINO -core-y += arch/mips/philips/nino/ -LOADADDR += 0x80000000 -endif +# The Ocelot-G setup.o must be linked early - it does the ioremap() for the +# mips_io_port_base. +# +core-$(CONFIG_MOMENCO_OCELOT_G) += arch/mips/momentum/ocelot_g/ +load-$(CONFIG_MOMENCO_OCELOT_G) += 0x80100000 # -# ITE 8172 eval board with QED 5231 CPU +# Momentum Ocelot-C and -CS boards # -ifdef CONFIG_MIPS_ITE8172 -core-y += arch/mips/ite-boards/qed-4n-s01b/ \ - arch/mips/ite-boards/generic/ -LOADADDR += 0x80100000 -endif +# The Ocelot-C[S] setup.o must be linked early - it does the ioremap() for the +# mips_io_port_base. +core-$(CONFIG_MOMENCO_OCELOT_C) += arch/mips/momentum/ocelot_c/ +load-$(CONFIG_MOMENCO_OCELOT_C) += 0x80100000 # -# Globespan IVR eval board with QED 5231 CPU +# NEC DDB Vrc-5074 # -ifdef CONFIG_MIPS_IVR -core-y += arch/mips/ite-boards/ivr/ \ - arch/mips/ite-boards/generic/ -LOADADDR += 0x80100000 -endif +core-$(CONFIG_DDB5XXX_COMMON) += arch/mips/ddb5xxx/common/ +core-$(CONFIG_DDB5074) += arch/mips/ddb5xxx/ddb5074/ +load-$(CONFIG_DDB5074) += 0x80080000 # -# Au1000 eval board +# NEC DDB Vrc-5476 # -ifdef CONFIG_MIPS_PB1000 -core-y += arch/mips/au1000/pb1000/ \ - arch/mips/au1000/common/ -LOADADDR += 0x80100000 -endif +core-$(CONFIG_DDB5476) += arch/mips/ddb5xxx/ddb5476/ +load-$(CONFIG_DDB5476) += 0x80080000 + +# +# NEC DDB Vrc-5477 +# +core-$(CONFIG_DDB5477) += arch/mips/ddb5xxx/ddb5477/ +load-$(CONFIG_DDB5477) += 0x80100000 + +core-$(CONFIG_LASAT) += arch/mips/lasat/ +load-$(CONFIG_LASAT) += 0x80000000 + +# +# NEC Osprey (vr4181) board +# +core-$(CONFIG_NEC_OSPREY) += arch/mips/vr4181/common/ \ + arch/mips/vr4181/osprey/ +load-$(CONFIG_NEC_OSPREY) += 0x80002000 + +# +# NEC Eagle/Hawk (VR4122/VR4131) board +# +core-$(CONFIG_VR41XX_COMMON) += arch/mips/vr41xx/common/ +core-$(CONFIG_NEC_EAGLE) += arch/mips/vr41xx/nec-eagle/ +load-$(CONFIG_NEC_EAGLE) += 0x80000000 + +# +# ZAO Networks Capcella (VR4131) +# +core-$(CONFIG_ZAO_CAPCELLA) += arch/mips/vr41xx/zao-capcella/ +load-$(CONFIG_ZAO_CAPCELLA) += 0x80000000 + +# +# Victor MP-C303/304 (VR4122) +# +core-$(CONFIG_VICTOR_MPC30X) += arch/mips/vr41xx/victor-mpc30x/ +load-$(CONFIG_VICTOR_MPC30X) += 0x80001000 + +# +# IBM WorkPad z50 (VR4121) +# +core-$(CONFIG_IBM_WORKPAD) += arch/mips/vr41xx/ibm-workpad/ +load-$(CONFIG_IBM_WORKPAD) += 0x80004000 + +# +# CASIO CASSIPEIA E-55/65 (VR4111) +# +core-$(CONFIG_CASIO_E55) += arch/mips/vr41xx/casio-e55/ +load-$(CONFIG_CASIO_E55) += 0x80004000 + +# +# TANBAC TB0226 Mbase (VR4131) +# +core-$(CONFIG_TANBAC_TB0226) += arch/mips/vr41xx/tanbac-tb0226/ +load-$(CONFIG_TANBAC_TB0226) += 0x80000000 + +# +# TANBAC TB0229 VR4131DIMM (VR4131) +# +core-$(CONFIG_TANBAC_TB0229) += arch/mips/vr41xx/tanbac-tb0229/ +load-$(CONFIG_TANBAC_TB0229) += 0x80000000 + +# +# SGI IP22 (Indy/Indigo2) +# +# Set the load address to >= 0x88069000 if you want to leave space for symmon, +# 0x88002000 for production kernels. Note that the value must be 8kb aligned +# or the handling of the current variable will break. +# +core-$(CONFIG_SGI_IP22) += arch/mips/sgi-ip22/ +load-$(CONFIG_SGI_IP22) += 0x88002000 + +# +# Sibyte SB1250 SOC +# +# This is a LIB so that it links at the end, and initcalls are later +# the sequence; but it is built as an object so that modules don't get +# removed (as happens, even if they have __initcall/module_init) +# +core-$(CONFIG_SIBYTE_BCM112X) += arch/mips/sibyte/sb1250/ +core-$(CONFIG_SIBYTE_SB1250) += arch/mips/sibyte/sb1250/ + +# +# Sibyte BCM91120x (Carmel) board +# Sibyte BCM91120C (CRhine) board +# Sibyte BCM91125C (CRhone) board +# Sibyte BCM91125E (Rhone) board +# Sibyte SWARM board +# +libs-$(CONFIG_SIBYTE_CARMEL) += arch/mips/sibyte/swarm/ +load-$(CONFIG_SIBYTE_CARMEL) := 0x80100000 +libs-$(CONFIG_SIBYTE_CRHINE) += arch/mips/sibyte/swarm/ +load-$(CONFIG_SIBYTE_CRHINE) := 0x80100000 +libs-$(CONFIG_SIBYTE_CRHONE) += arch/mips/sibyte/swarm/ +load-$(CONFIG_SIBYTE_CRHONE) := 0x80100000 +libs-$(CONFIG_SIBYTE_RHONE) += arch/mips/sibyte/swarm/ +load-$(CONFIG_SIBYTE_RHONE) := 0x80100000 +libs-$(CONFIG_SIBYTE_SENTOSA) += arch/mips/sibyte/swarm/ +load-$(CONFIG_SIBYTE_SENTOSA) := 0x80100000 +libs-$(CONFIG_SIBYTE_SWARM) += arch/mips/sibyte/swarm/ +load-$(CONFIG_SIBYTE_SWARM) := 0x80100000 + +# +# SNI RM200 PCI +# +core-$(CONFIG_SNI_RM200_PCI) += arch/mips/sni/ +load-$(CONFIG_SNI_RM200_PCI) += 0x80080000 + +# +# Toshiba JMR-TX3927 board +# +core-$(CONFIG_TOSHIBA_JMR3927) += arch/mips/jmr3927/rbhma3100/ \ + arch/mips/jmr3927/common/ +load-$(CONFIG_TOSHIBA_JMR3927) += 0x80050000 + +# +# Toshiba RBTX4927 board or +# Toshiba RBTX4937 board +# +core-$(CONFIG_TOSHIBA_RBTX4927) += arch/mips/tx4927/toshiba_rbtx4927/ +core-$(CONFIG_TOSHIBA_RBTX4927) += arch/mips/tx4927/common/ +load-$(CONFIG_TOSHIBA_RBTX4927) := 0x80020000 + +drivers-$(CONFIG_PCI) += arch/mips/pci/ + # # Choosing incompatible machines durings configuration will result in @@ -254,42 +354,79 @@ # none has been choosen above. # -AFLAGS_vmlinux.lds.o := -DLOADADDR=$(LOADADDR) +AFLAGS_vmlinux.lds.o := -D"LOADADDR=$(load-y)" -D"JIFFIES32=$(JIFFIES32)" head-y := arch/mips/kernel/head.o arch/mips/kernel/init_task.o -SUBDIRS := arch/mips/tools - -core-y += arch/mips/kernel/ arch/mips/mm/ -libs-y += arch/mips/lib/lib.a +libs-y += arch/mips/lib/ +core-y += arch/mips/kernel/ arch/mips/mm/ arch/mips/math-emu/ ifdef CONFIG_BAGET_MIPS BAGETBOOT = $(MAKE) -C arch/$(ARCH)/baget -balo: vmlinux +balo: vmlinux $(BAGETBOOT) balo endif -ifdef CONFIG_MIPS_EV64120 -GALILEOBOOT = $(MAKE) -C arch/$(ARCH)/galileo-boards/ev64120 +ifdef CONFIG_LASAT +rom.bin rom.sw: vmlinux + $(call descend,arch/mips/lasat/image,$@) +endif + +makeboot =$(Q)$(MAKE) -f scripts/Makefile.build obj=arch/mips/boot $(1) -gboot: vmlinux - $(MAKE) -C arch/$(ARCH)/galileo-boards/ev64120/compressed +# +# SNI firmware is f*cked in interesting ways ... +# +ifdef CONFIG_SNI_RM200_PCI +all: vmlinux.rm200 endif -MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot +vmlinux.ecoff vmlinux.rm200: vmlinux + +@$(call makeboot,$@) -vmlinux.ecoff: vmlinux - @$(MAKEBOOT) $@ +CLEAN_FILES += vmlinux.ecoff \ + vmlinux.rm200.tmp \ + vmlinux.rm200 archclean: - @$(MAKEBOOT) clean - rm -f arch/$(ARCH)/ld.script - $(MAKE) -C arch/$(ARCH)/tools clean - $(MAKE) -C arch/mips/baget clean + @$(MAKE) -f scripts/Makefile.clean obj=arch/mips/boot + @$(MAKE) -f scripts/Makefile.clean obj=arch/mips/baget + @$(MAKE) -f scripts/Makefile.clean obj=arch/mips/lasat archmrproper: - @$(MAKEBOOT) mrproper - $(MAKE) -C arch/$(ARCH)/tools mrproper + +# Generate #include -#include #include #include #include - -extern char prom_getchar (void); -extern void prom_printf (char *, ...); +#include static void prom_console_write(struct console *co, const char *s, unsigned count) { - unsigned i; - - /* - * Now, do each character - */ - for (i = 0; i < count; i++) { - if (*s == 10) - prom_printf("%c", 13); - prom_printf("%c", *s++); + /* Do each character */ + while (count--) { + if (*s == '\n') + prom_putchar('\r'); + prom_putchar(*s++); } } -static int prom_console_wait_key(struct console *co) -{ - return prom_getchar(); -} - static int __init prom_console_setup(struct console *co, char *options) { - return 0; -} - -static kdev_t prom_console_device(struct console *c) -{ - return MKDEV(TTY_MAJOR, 64 + c->index); + return !(prom_flags & PROM_FLAG_USE_AS_CONSOLE); } static struct console arc_cons = { - "ttyS", - prom_console_write, - NULL, - prom_console_device, - prom_console_wait_key, - NULL, - prom_console_setup, - CON_PRINTBUFFER, - -1, - 0, - NULL + .name = "arc", + .write = prom_console_write, + .setup = prom_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, }; /* * Register console. */ -static void __init arc_console_init(void) +static int __init arc_console_init(void) { register_console(&arc_cons); + + return 0; } console_initcall(arc_console_init); diff -Nru a/arch/mips/arc/cmdline.c b/arch/mips/arc/cmdline.c --- a/arch/mips/arc/cmdline.c Tue Jul 1 18:44:38 2003 +++ b/arch/mips/arc/cmdline.c Tue Jul 1 18:44:38 2003 @@ -1,4 +1,8 @@ /* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * * cmdline.c: Kernel command line creation using ARCS argc/argv. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) @@ -12,11 +16,11 @@ #undef DEBUG_CMDLINE -char arcs_cmdline[COMMAND_LINE_SIZE]; +char arcs_cmdline[CL_SIZE]; char * __init prom_getcmdline(void) { - return &(arcs_cmdline[0]); + return arcs_cmdline; } static char *ignored[] = { @@ -28,7 +32,6 @@ "OSLoadFilename=", "OSLoadOptions=" }; -#define NENTS(foo) ((sizeof((foo)) / (sizeof((foo[0]))))) static char *used_arc[][2] = { { "OSLoadPartition=", "root=" }, @@ -43,16 +46,16 @@ actr = 1; /* Always ignore argv[0] */ while (actr < prom_argc) { - for(i = 0; i < NENTS(used_arc); i++) { + for(i = 0; i < ARRAY_SIZE(used_arc); i++) { int len = strlen(used_arc[i][0]); - if(!strncmp(prom_argv[actr], used_arc[i][0], len)) { + if (!strncmp(prom_argv(actr), used_arc[i][0], len)) { /* Ok, we want it. First append the replacement... */ strcat(cp, used_arc[i][1]); cp += strlen(used_arc[i][1]); /* ... and now the argument */ - s = strstr(prom_argv[actr], "="); - if(s) { + s = strstr(prom_argv(actr), "="); + if (s) { s++; strcpy(cp, s); cp += strlen(s); @@ -67,7 +70,6 @@ return cp; } - void __init prom_init_cmdline(void) { char *cp; @@ -75,33 +77,34 @@ actr = 1; /* Always ignore argv[0] */ - cp = &(arcs_cmdline[0]); - /* + cp = arcs_cmdline; + /* * Move ARC variables to the beginning to make sure they can be * overridden by later arguments. */ cp = move_firmware_args(cp); while (actr < prom_argc) { - for (i = 0; i < NENTS(ignored); i++) { + for (i = 0; i < ARRAY_SIZE(ignored); i++) { int len = strlen(ignored[i]); - if(!strncmp(prom_argv[actr], ignored[i], len)) + if (!strncmp(prom_argv(actr), ignored[i], len)) goto pic_cont; } /* Ok, we want it. */ - strcpy(cp, prom_argv[actr]); - cp += strlen(prom_argv[actr]); + strcpy(cp, prom_argv(actr)); + cp += strlen(prom_argv(actr)); *cp++ = ' '; pic_cont: actr++; } - if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */ + + if (cp != arcs_cmdline) /* get rid of trailing space */ --cp; *cp = '\0'; #ifdef DEBUG_CMDLINE - prom_printf("prom_init_cmdline: %s\n", &(arcs_cmdline[0])); + printk(KERN_DEBUG "prom cmdline: %s\n", arcs_cmdline); #endif } diff -Nru a/arch/mips/arc/console.c b/arch/mips/arc/console.c --- a/arch/mips/arc/console.c Tue Jul 1 18:44:35 2003 +++ b/arch/mips/arc/console.c Tue Jul 1 18:44:35 2003 @@ -6,14 +6,9 @@ * Copyright (C) 1996 David S. Miller (dm@sgi.com) * Compability with board caches, Ulf Carlsson */ -#include -#include #include #include #include -#include -#include -#include /* * IP22 boardcache is not compatible with board caches. Thus we disable it @@ -27,44 +22,42 @@ void prom_putchar(char c) { - long cnt; - char it = c; + ULONG cnt; + CHAR it = c; bc_disable(); - romvec->write(1, &it, 1, &cnt); + ArcWrite(1, &it, 1, &cnt); bc_enable(); } -char __init prom_getchar(void) +char prom_getchar(void) { - long cnt; - char c; + ULONG cnt; + CHAR c; bc_disable(); - romvec->read(0, &c, 1, &cnt); + ArcRead(0, &c, 1, &cnt); bc_enable(); return c; } -static char ppbuf[1024]; - void prom_printf(char *fmt, ...) { va_list args; - char ch, *bptr; - int i; + char ppbuf[1024]; + char *bptr; va_start(args, fmt); - i = vsprintf(ppbuf, fmt, args); + vsprintf(ppbuf, fmt, args); bptr = ppbuf; - while ((ch = *(bptr++)) != 0) { - if (ch == '\n') + while (*bptr != 0) { + if (*bptr == '\n') prom_putchar('\r'); - prom_putchar(ch); + prom_putchar(*bptr++); } va_end(args); } diff -Nru a/arch/mips/arc/env.c b/arch/mips/arc/env.c --- a/arch/mips/arc/env.c Tue Jul 1 18:44:32 2003 +++ b/arch/mips/arc/env.c Tue Jul 1 18:44:32 2003 @@ -1,24 +1,27 @@ /* + * 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. + * * env.c: ARCS environment variable routines. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * - * $Id: env.c,v 1.2 1999/10/09 00:00:57 ralf Exp $ */ #include #include #include +#include #include PCHAR __init ArcGetEnvironmentVariable(CHAR *name) { - return romvec->get_evar(name); + return (CHAR *) ARC_CALL1(get_evar, name); } LONG __init ArcSetEnvironmentVariable(PCHAR name, PCHAR value) { - return romvec->set_evar(name, value); + return ARC_CALL2(set_evar, name, value); } diff -Nru a/arch/mips/arc/file.c b/arch/mips/arc/file.c --- a/arch/mips/arc/file.c Tue Jul 1 18:44:32 2003 +++ b/arch/mips/arc/file.c Tue Jul 1 18:44:32 2003 @@ -1,59 +1,75 @@ /* - * file.c: ARCS firmware interface to files. + * 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) 1996 David S. Miller (dm@engr.sgi.com) + * ARC firmware interface. * - * $Id: file.c,v 1.1 1998/10/18 13:32:08 tsbogend Exp $ + * Copyright (C) 1994, 1995, 1996, 1999 Ralf Baechle + * Copyright (C) 1999 Silicon Graphics, Inc. */ #include + +#include #include -long __init prom_getvdirent(unsigned long fd, struct linux_vdirent *ent, unsigned long num, unsigned long *cnt) +LONG __init +ArcGetDirectoryEntry(ULONG FileID, struct linux_vdirent *Buffer, + ULONG N, ULONG *Count) { - return romvec->get_vdirent(fd, ent, num, cnt); + return ARC_CALL4(get_vdirent, FileID, Buffer, N, Count); } -long __init prom_open(char *name, enum linux_omode md, unsigned long *fd) +LONG __init +ArcOpen(CHAR *Path, enum linux_omode OpenMode, ULONG *FileID) { - return romvec->open(name, md, fd); + return ARC_CALL3(open, Path, OpenMode, FileID); } -long __init prom_close(unsigned long fd) +LONG __init +ArcClose(ULONG FileID) { - return romvec->close(fd); + return ARC_CALL1(close, FileID); } -long __init prom_read(unsigned long fd, void *buf, unsigned long num, unsigned long *cnt) +LONG __init +ArcRead(ULONG FileID, VOID *Buffer, ULONG N, ULONG *Count) { - return romvec->read(fd, buf, num, cnt); + return ARC_CALL4(read, FileID, Buffer, N, Count); } -long __init prom_getrstatus(unsigned long fd) +LONG __init +ArcGetReadStatus(ULONG FileID) { - return romvec->get_rstatus(fd); + return ARC_CALL1(get_rstatus, FileID); } -long __init prom_write(unsigned long fd, void *buf, unsigned long num, unsigned long *cnt) +LONG __init +ArcWrite(ULONG FileID, PVOID Buffer, ULONG N, PULONG Count) { - return romvec->write(fd, buf, num, cnt); + return ARC_CALL4(write, FileID, Buffer, N, Count); } -long __init prom_seek(unsigned long fd, struct linux_bigint *off, enum linux_seekmode sm) +LONG __init +ArcSeek(ULONG FileID, struct linux_bigint *Position, enum linux_seekmode SeekMode) { - return romvec->seek(fd, off, sm); + return ARC_CALL3(seek, FileID, Position, SeekMode); } -long __init prom_mount(char *name, enum linux_mountops op) +LONG __init +ArcMount(char *name, enum linux_mountops op) { - return romvec->mount(name, op); + return ARC_CALL2(mount, name, op); } -long __init prom_getfinfo(unsigned long fd, struct linux_finfo *buf) +LONG __init +ArcGetFileInformation(ULONG FileID, struct linux_finfo *Information) { - return romvec->get_finfo(fd, buf); + return ARC_CALL2(get_finfo, FileID, Information); } -long __init prom_setfinfo(unsigned long fd, unsigned long flags, unsigned long msk) +LONG __init ArcSetFileInformation(ULONG FileID, ULONG AttributeFlags, + ULONG AttributeMask) { - return romvec->set_finfo(fd, flags, msk); + return ARC_CALL3(set_finfo, FileID, AttributeFlags, AttributeMask); } diff -Nru a/arch/mips/arc/identify.c b/arch/mips/arc/identify.c --- a/arch/mips/arc/identify.c Tue Jul 1 18:44:33 2003 +++ b/arch/mips/arc/identify.c Tue Jul 1 18:44:33 2003 @@ -1,65 +1,117 @@ /* + * 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. + * * identify.c: identify machine by looking up system identifier * * Copyright (C) 1998 Thomas Bogendoerfer - * + * * This code is based on arch/mips/sgi/kernel/system.c, which is - * + * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) */ +#include #include #include #include #include -#include #include #include struct smatch { - char *name; + char *arcname; + char *liname; int group; int type; int flags; }; static struct smatch mach_table[] = { - {"SGI-IP22", MACH_GROUP_SGI, MACH_SGI_INDY, PROM_FLAG_ARCS}, - {"Microsoft-Jazz", MACH_GROUP_JAZZ, MACH_MIPS_MAGNUM_4000, 0}, - {"PICA-61", MACH_GROUP_JAZZ, MACH_ACER_PICA_61, 0}, - {"RM200PCI", MACH_GROUP_SNI_RM, MACH_SNI_RM200_PCI, 0} + { "SGI-IP22", + "SGI Indy", + MACH_GROUP_SGI, + MACH_SGI_IP22, + PROM_FLAG_ARCS + }, { "SGI-IP27", + "SGI Origin", + MACH_GROUP_SGI, + MACH_SGI_IP27, + PROM_FLAG_ARCS + }, { "SGI-IP28", + "SGI IP28", + MACH_GROUP_SGI, + MACH_SGI_IP28, + PROM_FLAG_ARCS + }, { "SGI-IP32", + "SGI IP32", + MACH_GROUP_SGI, + MACH_SGI_IP32, + PROM_FLAG_ARCS + }, { "Microsoft-Jazz", + "Jazz MIPS_Magnum_4000", + MACH_GROUP_JAZZ, + MACH_MIPS_MAGNUM_4000, + 0 + }, { "PICA-61", + "Jazz Acer_PICA_61", + MACH_GROUP_JAZZ, + MACH_ACER_PICA_61, + 0 + }, { "RM200PCI", + "SNI RM200_PCI", + MACH_GROUP_SNI_RM, + MACH_SNI_RM200_PCI, + 0 + } }; int prom_flags; -static struct smatch *__init string_to_mach(char *s) +static struct smatch * __init string_to_mach(const char *s) { int i; for (i = 0; i < (sizeof(mach_table) / sizeof (mach_table[0])); i++) { - if (!strcmp(s, mach_table[i].name)) + if (!strcmp(s, mach_table[i].arcname)) return &mach_table[i]; } - prom_printf("\nYeee, could not determine architecture type <%s>\n", - s); - prom_printf("press a key to reboot\n"); - prom_getchar(); - romvec->imode(); - return NULL; + + panic("Yeee, could not determine architecture type <%s>", s); +} + +char *system_type; + +const char *get_system_type(void) +{ + return system_type; } void __init prom_identify_arch(void) { pcomponent *p; struct smatch *mach; + const char *iname; /* - * The root component tells us what machine architecture we - * have here. + * The root component tells us what machine architecture we have here. */ - p = prom_getchild(PROM_NULL_COMPONENT); - printk("ARCH: %s\n", p->iname); - mach = string_to_mach(p->iname); + p = ArcGetChild(PROM_NULL_COMPONENT); + if (p == NULL) { +#ifdef CONFIG_SGI_IP27 + /* IP27 PROM misbehaves, seems to not implement ARC + GetChild(). So we just assume it's an IP27. */ + iname = "SGI-IP27"; +#else + iname = "Unknown"; +#endif + } else + iname = (char *) (long) p->iname; + + printk("ARCH: %s\n", iname); + mach = string_to_mach(iname); + system_type = mach->liname; mips_machgroup = mach->group; mips_machtype = mach->type; diff -Nru a/arch/mips/arc/init.c b/arch/mips/arc/init.c --- a/arch/mips/arc/init.c Tue Jul 1 18:44:34 2003 +++ b/arch/mips/arc/init.c Tue Jul 1 18:44:34 2003 @@ -1,5 +1,5 @@ /* - * This file is subject to the terms and conditions of the GNU General Public+ + * 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. * @@ -16,38 +16,17 @@ /* Master romvec interface. */ struct linux_romvec *romvec; -struct linux_promblock *sgi_pblock; int prom_argc; -char **prom_argv, **prom_envp; -unsigned short prom_vers, prom_rev; - -extern void prom_testtree(void); - -extern void arc_setup_console(void); +LONG *_prom_argv, *_prom_envp; void __init prom_init(int argc, char **argv, char **envp, int *prom_vec) { - struct linux_promblock *pb; - + PSYSTEM_PARAMETER_BLOCK pb = PROMBLOCK; romvec = ROMVECTOR; - pb = sgi_pblock = PROMBLOCK; prom_argc = argc; - prom_argv = argv; - prom_envp = envp; + _prom_argv = (LONG *) argv; + _prom_envp = (LONG *) envp; -#if 0 - /* arc_printf should not use prom_printf as soon as we free - * the prom buffers - This horribly breaks on Indys with framebuffer - * as it simply stops after initialising swap - On the Indigo2 serial - * console you will get A LOT illegal instructions - Only enable - * this for early init crashes - This also brings up artefacts of - * printing everything twice on serial console and on GFX Console - * this has the effect of having the prom printing everything - * in the small rectangle and the kernel printing around. - */ - - arc_setup_console(); -#endif if (pb->magic != 0x53435241) { prom_printf("Aieee, bad prom vector magic %08lx\n", pb->magic); while(1) @@ -55,19 +34,14 @@ } prom_init_cmdline(); - - prom_vers = pb->ver; - prom_rev = pb->rev; prom_identify_arch(); - printk("PROMLIB: ARC firmware Version %d Revision %d\n", - prom_vers, prom_rev); + printk(KERN_INFO "PROMLIB: ARC firmware Version %d Revision %d\n", + pb->ver, pb->rev); prom_meminit(); #ifdef DEBUG_PROM_INIT - { - prom_printf("Press a key to reboot\n"); - (void) prom_getchar(); - romvec->imode(); - } + prom_printf("Press a key to reboot\n"); + prom_getchar(); + ArcEnterInteractiveMode(); #endif } diff -Nru a/arch/mips/arc/memory.c b/arch/mips/arc/memory.c --- a/arch/mips/arc/memory.c Tue Jul 1 18:44:36 2003 +++ b/arch/mips/arc/memory.c Tue Jul 1 18:44:36 2003 @@ -2,7 +2,14 @@ * memory.c: PROM library functions for acquiring/using memory descriptors * given to us from the ARCS firmware. * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * Copyright (C) 1996 by David S. Miller + * Copyright (C) 1999, 2000, 2001 by Ralf Baechle + * Copyright (C) 1999, 2000 by Silicon Graphics, Inc. + * + * PROM library functions for acquiring/using memory descriptors given to us + * from the ARCS firmware. This is only used when CONFIG_ARC_MEMORY is set + * because on some machines like SGI IP27 the ARC memory configuration data + * completly bogus and alternate easier to use mechanisms are available. */ #include #include @@ -19,10 +26,9 @@ #undef DEBUG -struct linux_mdesc * __init -ArcGetMemoryDescriptor(struct linux_mdesc *Current) +struct linux_mdesc * __init ArcGetMemoryDescriptor(struct linux_mdesc *Current) { - return romvec->get_mdesc(Current); + return (struct linux_mdesc *) ARC_CALL1(get_mdesc, Current); } #ifdef DEBUG /* convenient for debugging */ @@ -47,7 +53,8 @@ "FirmwarePermanent", "FreeContiguous" }; -#define mtypes(a) (prom_flags & PROM_FLAG_ARCS) ? arcs_mtypes[a.arcs] : arc_mtypes[a.arc] +#define mtypes(a) (prom_flags & PROM_FLAG_ARCS) ? arcs_mtypes[a.arcs] \ + : arc_mtypes[a.arc] #endif static inline int memtype_classify_arcs (union linux_memtypes type) @@ -92,7 +99,7 @@ static int __init prom_memtype_classify (union linux_memtypes type) { - if (prom_flags & PROM_FLAG_ARCS) /* SGI is ``different'' ... */ + if (prom_flags & PROM_FLAG_ARCS) /* SGI is ``different'' ... */ return memtype_classify_arcs(type); return memtype_classify_arc(type); @@ -128,8 +135,7 @@ } } -void __init -prom_free_prom_memory (void) +void __init prom_free_prom_memory (void) { unsigned long freed = 0; unsigned long addr; @@ -149,5 +155,5 @@ freed += PAGE_SIZE; } } - printk("Freeing prom memory: %ldkb freed\n", freed >> 10); + printk(KERN_INFO "Freeing prom memory: %ldkb freed\n", freed >> 10); } diff -Nru a/arch/mips/arc/misc.c b/arch/mips/arc/misc.c --- a/arch/mips/arc/misc.c Tue Jul 1 18:44:32 2003 +++ b/arch/mips/arc/misc.c Tue Jul 1 18:44:32 2003 @@ -1,13 +1,21 @@ /* - * misc.c: Miscellaneous ARCS PROM routines. + * 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. + * + * Miscellaneous ARCS PROM routines. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * Copyright (C) 1999 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 1999 Silicon Graphics, Inc. */ #include #include #include #include + +#include #include #include #include @@ -15,68 +23,81 @@ extern void *sgiwd93_host; extern void reset_wd33c93(void *instance); -void prom_halt(void) +VOID +ArcHalt(VOID) { bc_disable(); - cli(); + local_irq_disable(); #ifdef CONFIG_SCSI_SGIWD93 reset_wd33c93(sgiwd93_host); #endif - romvec->halt(); + ARC_CALL0(halt); +never: goto never; } -void prom_powerdown(void) +VOID +ArcPowerDown(VOID) { bc_disable(); - cli(); + local_irq_disable(); #ifdef CONFIG_SCSI_SGIWD93 reset_wd33c93(sgiwd93_host); #endif - romvec->pdown(); + ARC_CALL0(pdown); +never: goto never; } /* XXX is this a soft reset basically? XXX */ -void prom_restart(void) +VOID +ArcRestart(VOID) { bc_disable(); - cli(); + local_irq_disable(); #ifdef CONFIG_SCSI_SGIWD93 reset_wd33c93(sgiwd93_host); #endif - romvec->restart(); + ARC_CALL0(restart); +never: goto never; } -void prom_reboot(void) +VOID +ArcReboot(VOID) { bc_disable(); - cli(); + local_irq_disable(); #ifdef CONFIG_SCSI_SGIWD93 reset_wd33c93(sgiwd93_host); #endif - romvec->reboot(); + ARC_CALL0(reboot); +never: goto never; } -void ArcEnterInteractiveMode(void) +VOID +ArcEnterInteractiveMode(VOID) { bc_disable(); - cli(); + local_irq_disable(); #ifdef CONFIG_SCSI_SGIWD93 reset_wd33c93(sgiwd93_host); #endif - romvec->imode(); + ARC_CALL0(imode); +never: goto never; } -long prom_cfgsave(void) +LONG +ArcSaveConfiguration(VOID) { - return romvec->cfg_save(); + return ARC_CALL0(cfg_save); } -struct linux_sysid *prom_getsysid(void) +struct linux_sysid * +ArcGetSystemId(VOID) { - return romvec->get_sysid(); + return (struct linux_sysid *) ARC_CALL0(get_sysid); } -void __init prom_cacheflush(void) +VOID __init +ArcFlushAllCaches(VOID) { - romvec->cache_flush(); + ARC_CALL0(cache_flush); } diff -Nru a/arch/mips/arc/promlib.c b/arch/mips/arc/promlib.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/arc/promlib.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,43 @@ +/* + * 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) 1996 David S. Miller (dm@sgi.com) + * Compability with board caches, Ulf Carlsson + */ +#include +#include +#include + +/* + * IP22 boardcache is not compatible with board caches. Thus we disable it + * during romvec action. Since r4xx0.c is always compiled and linked with your + * kernel, this shouldn't cause any harm regardless what MIPS processor you + * have. + * + * The ARC write and read functions seem to interfere with the serial lines + * in some way. You should be careful with them. + */ + +void prom_putchar(char c) +{ + ULONG cnt; + CHAR it = c; + + bc_disable(); + ArcWrite(1, &it, 1, &cnt); + bc_enable(); +} + +char prom_getchar(void) +{ + ULONG cnt; + CHAR c; + + bc_disable(); + ArcRead(0, &c, 1, &cnt); + bc_enable(); + + return c; +} diff -Nru a/arch/mips/arc/salone.c b/arch/mips/arc/salone.c --- a/arch/mips/arc/salone.c Tue Jul 1 18:44:39 2003 +++ b/arch/mips/arc/salone.c Tue Jul 1 18:44:39 2003 @@ -1,25 +1,24 @@ /* - * salone.c: Routines to load into memory and execute stand-along - * program images using ARCS PROM firmware. + * Routines to load into memory and execute stand-along program images using + * ARCS PROM firmware. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * - * $Id: salone.c,v 1.1 1998/10/18 13:32:09 tsbogend Exp $ */ #include #include -long __init prom_load(char *name, unsigned long end, unsigned long *pc, unsigned long *eaddr) +LONG __init ArcLoad(CHAR *Path, ULONG TopAddr, ULONG *ExecAddr, ULONG *LowAddr) { - return romvec->load(name, end, pc, eaddr); + return ARC_CALL4(load, Path, TopAddr, ExecAddr, LowAddr); } -long __init prom_invoke(unsigned long pc, unsigned long sp, long argc, char **argv, char **envp) +LONG __init ArcInvoke(ULONG ExecAddr, ULONG StackAddr, ULONG Argc, CHAR *Argv[], + CHAR *Envp[]) { - return romvec->invoke(pc, sp, argc, argv, envp); + return ARC_CALL5(invoke, ExecAddr, StackAddr, Argc, Argv, Envp); } -long __init prom_exec(char *name, long argc, char **argv, char **envp) +LONG __init ArcExecute(CHAR *Path, LONG Argc, CHAR *Argv[], CHAR *Envp[]) { - return romvec->exec(name, argc, argv, envp); + return ARC_CALL4(exec, Path, Argc, Argv, Envp); } diff -Nru a/arch/mips/arc/time.c b/arch/mips/arc/time.c --- a/arch/mips/arc/time.c Tue Jul 1 18:44:34 2003 +++ b/arch/mips/arc/time.c Tue Jul 1 18:44:34 2003 @@ -1,19 +1,25 @@ /* - * time.c: Extracting time information from ARCS prom. + * 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) 1996 David S. Miller (dm@engr.sgi.com) + * Extracting time information from ARCS prom. * - * $Id: time.c,v 1.1 1998/10/18 13:32:10 tsbogend Exp $ + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) */ #include + +#include #include -struct linux_tinfo * __init prom_gettinfo(void) +struct linux_tinfo * __init +ArcGetTime(VOID) { - return romvec->get_tinfo(); + return (struct linux_tinfo *) ARC_CALL0(get_tinfo); } -unsigned long __init prom_getrtime(void) +ULONG __init +ArcGetRelativeTime(VOID) { - return romvec->get_rtime(); + return ARC_CALL0(get_rtime); } diff -Nru a/arch/mips/arc/tree.c b/arch/mips/arc/tree.c --- a/arch/mips/arc/tree.c Tue Jul 1 18:44:35 2003 +++ b/arch/mips/arc/tree.c Tue Jul 1 18:44:35 2003 @@ -1,72 +1,88 @@ /* - * tree.c: PROM component device tree code. + * 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) 1996 David S. Miller (dm@engr.sgi.com) + * PROM component device tree code. * - * $Id: tree.c,v 1.1 1998/10/18 13:32:10 tsbogend Exp $ + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * Copyright (C) 1999 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 1999 Silicon Graphics, Inc. */ #include +#include #include -#define DEBUG_PROM_TREE +#undef DEBUG_PROM_TREE -pcomponent * __init prom_getsibling(pcomponent *this) +pcomponent * __init +ArcGetPeer(pcomponent *Current) { - if(this == PROM_NULL_COMPONENT) + if (Current == PROM_NULL_COMPONENT) return PROM_NULL_COMPONENT; - return romvec->next_component(this); + + return (pcomponent *) ARC_CALL1(next_component, Current); } -pcomponent * __init prom_getchild(pcomponent *this) +pcomponent * __init +ArcGetChild(pcomponent *Current) { - return romvec->child_component(this); + return (pcomponent *) ARC_CALL1(child_component, Current); } -pcomponent * __init prom_getparent(pcomponent *child) +pcomponent * __init +ArcGetParent(pcomponent *Current) { - if(child == PROM_NULL_COMPONENT) + if (Current == PROM_NULL_COMPONENT) return PROM_NULL_COMPONENT; - return romvec->parent_component(child); + + return (pcomponent *) ARC_CALL1(parent_component, Current); } -long __init prom_getcdata(void *buffer, pcomponent *this) +LONG __init +ArcGetConfigurationData(VOID *Buffer, pcomponent *Current) { - return romvec->component_data(buffer, this); + return ARC_CALL2(component_data, Buffer, Current); } -pcomponent * __init prom_childadd(pcomponent *this, pcomponent *tmp, void *data) +pcomponent * __init +ArcAddChild(pcomponent *Current, pcomponent *Template, VOID *ConfigurationData) { - return romvec->child_add(this, tmp, data); + return (pcomponent *) + ARC_CALL3(child_add, Current, Template, ConfigurationData); } -long __init prom_delcomponent(pcomponent *this) +LONG __init +ArcDeleteComponent(pcomponent *ComponentToDelete) { - return romvec->comp_del(this); + return ARC_CALL1(comp_del, ComponentToDelete); } -pcomponent * __init prom_componentbypath(char *path) +pcomponent * __init +ArcGetComponent(CHAR *Path) { - return romvec->component_by_path(path); + return (pcomponent *)ARC_CALL1(component_by_path, Path); } #ifdef DEBUG_PROM_TREE + static char *classes[] = { "system", "processor", "cache", "adapter", "controller", "peripheral", "memory" }; static char *types[] = { - "arc", "cpu", "fpu", "picache", "pdcache", "sicache", "sdcache", "sccache", - "memdev", "eisa adapter", "tc adapter", "scsi adapter", "dti adapter", - "multi-func adapter", "disk controller", "tp controller", - "cdrom controller", "worm controller", "serial controller", - "net controller", "display controller", "parallel controller", - "pointer controller", "keyboard controller", "audio controller", - "misc controller", "disk peripheral", "floppy peripheral", - "tp peripheral", "modem peripheral", "monitor peripheral", - "printer peripheral", "pointer peripheral", "keyboard peripheral", - "terminal peripheral", "line peripheral", "net peripheral", - "misc peripheral", "anonymous" + "arc", "cpu", "fpu", "picache", "pdcache", "sicache", "sdcache", + "sccache", "memdev", "eisa adapter", "tc adapter", "scsi adapter", + "dti adapter", "multi-func adapter", "disk controller", + "tp controller", "cdrom controller", "worm controller", + "serial controller", "net controller", "display controller", + "parallel controller", "pointer controller", "keyboard controller", + "audio controller", "misc controller", "disk peripheral", + "floppy peripheral", "tp peripheral", "modem peripheral", + "monitor peripheral", "printer peripheral", "pointer peripheral", + "keyboard peripheral", "terminal peripheral", "line peripheral", + "net peripheral", "misc peripheral", "anonymous" }; static char *iflags[] = { @@ -74,7 +90,8 @@ "input", "output" }; -static void __init dump_component(pcomponent *p) +static void __init +dump_component(pcomponent *p) { prom_printf("[%p]:class<%s>type<%s>flags<%s>ver<%d>rev<%d>", p, classes[p->class], types[p->type], @@ -83,27 +100,28 @@ p->key, p->amask, (int)p->cdsize, (int)p->ilen, p->iname); } -static void __init traverse(pcomponent *p, int op) +static void __init +traverse(pcomponent *p, int op) { dump_component(p); - if(prom_getchild(p)) - traverse(prom_getchild(p), 1); - if(prom_getsibling(p) && op) - traverse(prom_getsibling(p), 1); + if(ArcGetChild(p)) + traverse(ArcGetChild(p), 1); + if(ArcGetPeer(p) && op) + traverse(ArcGetPeer(p), 1); } -void __init prom_testtree(void) +void __init +prom_testtree(void) { pcomponent *p; - p = prom_getchild(PROM_NULL_COMPONENT); + p = ArcGetChild(PROM_NULL_COMPONENT); dump_component(p); - p = prom_getchild(p); + p = ArcGetChild(p); while(p) { dump_component(p); - p = prom_getsibling(p); + p = ArcGetPeer(p); } - prom_printf("press a key\n"); - prom_getchar(); } -#endif + +#endif /* DEBUG_PROM_TREE */ diff -Nru a/arch/mips/au1000/common/Makefile b/arch/mips/au1000/common/Makefile --- a/arch/mips/au1000/common/Makefile Tue Jul 1 18:44:38 2003 +++ b/arch/mips/au1000/common/Makefile Tue Jul 1 18:44:38 2003 @@ -5,14 +5,14 @@ # # Makefile for the Alchemy Au1000 CPU, generic files. # +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# -obj-y := prom.o dbg_io.o int-handler.o irq.o puts.o time.o reset.o +obj-y += prom.o int-handler.o dma.o irq.o puts.o \ + time.o reset.o clocks.o power.o -obj-$(CONFIG_AU1000_UART) += serial.o -obj-$(CONFIG_REMOTE_DEBUG) += dbg_io.o -obj-$(CONFIG_BLK_DEV_INITRD) += ramdisk.o - -EXTRA_AFLAGS := $(CFLAGS) - -ramdisk.o: - mkramobj ramdisk ramdisk.o +obj-$(CONFIG_AU1X00_USB_DEVICE) += usbdev.o +obj-$(CONFIG_KGDB) += dbg_io.o +obj-$(CONFIG_RTC) += rtc.o diff -Nru a/arch/mips/au1000/common/clocks.c b/arch/mips/au1000/common/clocks.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/common/clocks.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,97 @@ +/* + * BRIEF MODULE DESCRIPTION + * Simple Au1000 clocks routines. + * + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +static unsigned int au1x00_clock; // Hz +static unsigned int lcd_clock; // KHz +static unsigned long uart_baud_base; + +/* + * Set the au1000_clock + */ +void set_au1x00_speed(unsigned int new_freq) +{ + au1x00_clock = new_freq; +} + +unsigned int get_au1x00_speed(void) +{ + return au1x00_clock; +} + + + +/* + * The UART baud base is not known at compile time ... if + * we want to be able to use the same code on different + * speed CPUs. + */ +unsigned long get_au1x00_uart_baud_base(void) +{ + return uart_baud_base; +} + +void set_au1x00_uart_baud_base(unsigned long new_baud_base) +{ + uart_baud_base = new_baud_base; +} + +/* + * Calculate the Au1x00's LCD clock based on the current + * cpu clock and the system bus clock, and try to keep it + * below 40 MHz (the Pb1000 board can lock-up if the LCD + * clock is over 40 MHz). + */ +void set_au1x00_lcd_clock(void) +{ + unsigned int static_cfg0; + unsigned int sys_busclk = + (get_au1x00_speed()/1000) / + ((int)(au_readl(SYS_POWERCTRL)&0x03) + 2); + + static_cfg0 = au_readl(MEM_STCFG0); + + if (static_cfg0 & (1<<11)) + lcd_clock = sys_busclk / 5; /* note: BCLK switching fails with D5 */ + else + lcd_clock = sys_busclk / 4; + + if (lcd_clock > 50000) /* Epson MAX */ + printk("%s: warning: LCD clock too high (%d KHz)\n", + __FUNCTION__, lcd_clock); +} + +unsigned int get_au1x00_lcd_clock(void) +{ + return lcd_clock; +} + +EXPORT_SYMBOL(get_au1x00_lcd_clock); diff -Nru a/arch/mips/au1000/common/dbg_io.c b/arch/mips/au1000/common/dbg_io.c --- a/arch/mips/au1000/common/dbg_io.c Tue Jul 1 18:44:38 2003 +++ b/arch/mips/au1000/common/dbg_io.c Tue Jul 1 18:44:38 2003 @@ -3,13 +3,13 @@ #include #include -#ifdef CONFIG_REMOTE_DEBUG +#ifdef CONFIG_KGDB /* * FIXME the user should be able to select the * uart to be used for debugging. */ -#define DEBUG_BASE UART2_ADDR +#define DEBUG_BASE UART_DEBUG_BASE /**/ /* we need uint32 uint8 */ @@ -53,8 +53,11 @@ #define UART_MOD_CNTRL 0x100 /* Module Control */ /* memory-mapped read/write of the port */ -#define UART16550_READ(y) (inl(DEBUG_BASE + y) & 0xff) -#define UART16550_WRITE(y,z) (outl(z&0xff, DEBUG_BASE + y)) +#define UART16550_READ(y) (au_readl(DEBUG_BASE + y) & 0xff) +#define UART16550_WRITE(y,z) (au_writel(z&0xff, DEBUG_BASE + y)) + +extern unsigned long get_au1x00_uart_baud_base(void); +extern unsigned long cal_r4koff(void); void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop) { @@ -68,16 +71,16 @@ UART16550_WRITE(UART_IER, 0); /* set up baud rate */ - { + { uint32 divisor; /* set divisor */ - divisor = get_au1000_uart_baud() / baud; + divisor = get_au1x00_uart_baud_base() / baud; UART16550_WRITE(UART_CLK, divisor & 0xffff); } /* set data format */ - UART16550_WRITE(UART_LCR, data | parity | stop); + UART16550_WRITE(UART_LCR, (data | parity | stop)); } static int remoteDebugInitialized = 0; @@ -99,7 +102,8 @@ int putDebugChar(uint8 byte) { - int i; +// int i; + if (!remoteDebugInitialized) { remoteDebugInitialized = 1; debugInit(UART16550_BAUD_115200, diff -Nru a/arch/mips/au1000/common/dma.c b/arch/mips/au1000/common/dma.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/common/dma.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,217 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * A DMA channel allocator for Au1000. API is modeled loosely off of + * linux/kernel/dma.c. + * + * Copyright 2000 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * stevel@mvista.com or source@mvista.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +/* + * A note on resource allocation: + * + * All drivers needing DMA channels, should allocate and release them + * through the public routines `request_dma()' and `free_dma()'. + * + * In order to avoid problems, all processes should allocate resources in + * the same sequence and release them in the reverse order. + * + * So, when allocating DMAs and IRQs, first allocate the DMA, then the IRQ. + * When releasing them, first release the IRQ, then release the DMA. The + * main reason for this order is that, if you are requesting the DMA buffer + * done interrupt, you won't know the irq number until the DMA channel is + * returned from request_dma. + */ + + +spinlock_t au1000_dma_spin_lock = SPIN_LOCK_UNLOCKED; + +struct dma_chan au1000_dma_table[NUM_AU1000_DMA_CHANNELS] = { + {dev_id:-1,}, + {dev_id:-1,}, + {dev_id:-1,}, + {dev_id:-1,}, + {dev_id:-1,}, + {dev_id:-1,}, + {dev_id:-1,}, + {dev_id:-1,} +}; + +// Device FIFO addresses and default DMA modes +static const struct { + unsigned int fifo_addr; + unsigned int dma_mode; +} dma_dev_table[DMA_NUM_DEV] = { + {UART0_ADDR + UART_TX, 0}, + {UART0_ADDR + UART_RX, 0}, + {0, 0}, + {0, 0}, + {AC97C_DATA, DMA_DW16 }, // coherent + {AC97C_DATA, DMA_DR | DMA_DW16 }, // coherent + {UART3_ADDR + UART_TX, DMA_DW8 | DMA_NC}, + {UART3_ADDR + UART_RX, DMA_DR | DMA_DW8 | DMA_NC}, + {USBD_EP0RD, DMA_DR | DMA_DW8 | DMA_NC}, + {USBD_EP0WR, DMA_DW8 | DMA_NC}, + {USBD_EP2WR, DMA_DW8 | DMA_NC}, + {USBD_EP3WR, DMA_DW8 | DMA_NC}, + {USBD_EP4RD, DMA_DR | DMA_DW8 | DMA_NC}, + {USBD_EP5RD, DMA_DR | DMA_DW8 | DMA_NC}, + {I2S_DATA, DMA_DW32 | DMA_NC}, + {I2S_DATA, DMA_DR | DMA_DW32 | DMA_NC} +}; + + +int au1000_dma_read_proc(char *buf, char **start, off_t fpos, + int length, int *eof, void *data) +{ + int i, len = 0; + struct dma_chan *chan; + + for (i = 0; i < NUM_AU1000_DMA_CHANNELS; i++) { + if ((chan = get_dma_chan(i)) != NULL) { + len += sprintf(buf + len, "%2d: %s\n", + i, chan->dev_str); + } + } + + if (fpos >= len) { + *start = buf; + *eof = 1; + return 0; + } + *start = buf + fpos; + if ((len -= fpos) > length) + return length; + *eof = 1; + return len; +} + + +void dump_au1000_dma_channel(unsigned int dmanr) +{ + struct dma_chan *chan; + + if (dmanr > NUM_AU1000_DMA_CHANNELS) + return; + chan = &au1000_dma_table[dmanr]; + + printk(KERN_INFO "Au1000 DMA%d Register Dump:\n", dmanr); + printk(KERN_INFO " mode = 0x%08x\n", + au_readl(chan->io + DMA_MODE_SET)); + printk(KERN_INFO " addr = 0x%08x\n", + au_readl(chan->io + DMA_PERIPHERAL_ADDR)); + printk(KERN_INFO " start0 = 0x%08x\n", + au_readl(chan->io + DMA_BUFFER0_START)); + printk(KERN_INFO " start1 = 0x%08x\n", + au_readl(chan->io + DMA_BUFFER1_START)); + printk(KERN_INFO " count0 = 0x%08x\n", + au_readl(chan->io + DMA_BUFFER0_COUNT)); + printk(KERN_INFO " count1 = 0x%08x\n", + au_readl(chan->io + DMA_BUFFER1_COUNT)); +} + + +/* + * Finds a free channel, and binds the requested device to it. + * Returns the allocated channel number, or negative on error. + * Requests the DMA done IRQ if irqhandler != NULL. + */ +int request_au1000_dma(int dev_id, const char *dev_str, + void (*irqhandler)(int, void *, struct pt_regs *), + unsigned long irqflags, + void *irq_dev_id) +{ + struct dma_chan *chan; + int i, ret; + + if (dev_id < 0 || dev_id >= DMA_NUM_DEV) + return -EINVAL; + + for (i = 0; i < NUM_AU1000_DMA_CHANNELS; i++) { + if (au1000_dma_table[i].dev_id < 0) + break; + } + if (i == NUM_AU1000_DMA_CHANNELS) + return -ENODEV; + + chan = &au1000_dma_table[i]; + + if (irqhandler) { + chan->irq = AU1000_DMA_INT_BASE + i; + chan->irq_dev = irq_dev_id; + if ((ret = request_irq(chan->irq, irqhandler, irqflags, + dev_str, chan->irq_dev))) { + chan->irq = 0; + chan->irq_dev = NULL; + return ret; + } + } else { + chan->irq = 0; + chan->irq_dev = NULL; + } + + // fill it in + chan->io = DMA_CHANNEL_BASE + i * DMA_CHANNEL_LEN; + chan->dev_id = dev_id; + chan->dev_str = dev_str; + chan->fifo_addr = dma_dev_table[dev_id].fifo_addr; + chan->mode = dma_dev_table[dev_id].dma_mode; + + /* initialize the channel before returning */ + init_dma(i); + + return i; +} + + +void free_au1000_dma(unsigned int dmanr) +{ + struct dma_chan *chan = get_dma_chan(dmanr); + if (!chan) { + printk("Trying to free DMA%d\n", dmanr); + return; + } + + disable_dma(dmanr); + if (chan->irq) + free_irq(chan->irq, chan->irq_dev); + + chan->irq = 0; + chan->irq_dev = NULL; + chan->dev_id = -1; +} diff -Nru a/arch/mips/au1000/common/int-handler.S b/arch/mips/au1000/common/int-handler.S --- a/arch/mips/au1000/common/int-handler.S Tue Jul 1 18:44:34 2003 +++ b/arch/mips/au1000/common/int-handler.S Tue Jul 1 18:44:34 2003 @@ -9,7 +9,6 @@ * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. */ -#include #include #include #include @@ -40,32 +39,30 @@ 1: andi a0, t0, CAUSEF_IP2 # Interrupt Controller 0, Request 0 - beq a0, zero, 2f - move a0,sp + beq a0, zero, 2f + move a0,sp jal intc0_req0_irqdispatch j ret_from_irq 2: andi a0, t0, CAUSEF_IP3 # Interrupt Controller 0, Request 1 - beq a0, zero, 3f - move a0,sp + beq a0, zero, 3f + move a0,sp jal intc0_req1_irqdispatch j ret_from_irq 3: andi a0, t0, CAUSEF_IP4 # Interrupt Controller 1, Request 0 - beq a0, zero, 4f - move a0,sp + beq a0, zero, 4f + move a0,sp jal intc1_req0_irqdispatch j ret_from_irq 4: andi a0, t0, CAUSEF_IP5 # Interrupt Controller 1, Request 1 - beq a0, zero, 5f - move a0, sp + beq a0, zero, 5f + move a0, sp jal intc1_req1_irqdispatch j ret_from_irq -5: +5: move a0, sp - jal mips_spurious_interrupt -done: - j ret_from_irq + j spurious_interrupt END(au1000_IRQ) diff -Nru a/arch/mips/au1000/common/irq.c b/arch/mips/au1000/common/irq.c --- a/arch/mips/au1000/common/irq.c Tue Jul 1 18:44:34 2003 +++ b/arch/mips/au1000/common/irq.c Tue Jul 1 18:44:34 2003 @@ -28,6 +28,7 @@ */ #include #include +#include #include #include #include @@ -47,7 +48,21 @@ #include #include -#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5) +#if defined(CONFIG_MIPS_PB1000) +#include +#elif defined(CONFIG_MIPS_PB1500) +#include +#elif defined(CONFIG_MIPS_PB1100) +#include +#elif defined(CONFIG_MIPS_DB1000) +#include +#elif defined(CONFIG_MIPS_DB1100) +#include +#elif defined(CONFIG_MIPS_DB1500) +#include +#else +#error unsupported Alchemy board +#endif #undef DEBUG_IRQ #ifdef DEBUG_IRQ @@ -63,16 +78,13 @@ #define EXT_INTC1_REQ1 5 /* IP 5 */ #define MIPS_TIMER_IP 7 /* IP 7 */ -#ifdef CONFIG_REMOTE_DEBUG +#ifdef CONFIG_KGDB extern void breakpoint(void); #endif extern asmlinkage void au1000_IRQ(void); - extern void set_debug_traps(void); -extern irq_cpustat_t irq_stat []; -extern irq_desc_t irq_desc[NR_IRQS]; - +extern irq_cpustat_t irq_stat [NR_CPUS]; unsigned int local_bh_count[NR_CPUS]; unsigned int local_irq_count[NR_CPUS]; @@ -82,154 +94,113 @@ static inline void mask_and_ack_level_irq(unsigned int irq_nr); static inline void mask_and_ack_rise_edge_irq(unsigned int irq_nr); static inline void mask_and_ack_fall_edge_irq(unsigned int irq_nr); -static inline void local_enable_irq(unsigned int irq_nr); -static inline void local_disable_irq(unsigned int irq_nr); +inline void local_enable_irq(unsigned int irq_nr); +inline void local_disable_irq(unsigned int irq_nr); -unsigned long spurious_interrupts; -extern unsigned int do_IRQ(int irq, struct pt_regs *regs); extern void __init init_generic_irq(void); -static inline void sync(void) -{ - __asm volatile ("sync"); -} - - -/* Function for careful CP0 interrupt mask access */ -static inline void modify_cp0_intmask(unsigned clr_mask, unsigned set_mask) -{ - unsigned long status = read_32bit_cp0_register(CP0_STATUS); - status &= ~((clr_mask & 0xFF) << 8); - status |= (set_mask & 0xFF) << 8; - write_32bit_cp0_register(CP0_STATUS, status); -} - - -static inline void mask_cpu_irq_input(unsigned int irq_nr) -{ - modify_cp0_intmask(irq_nr, 0); -} - - -static inline void unmask_cpu_irq_input(unsigned int irq_nr) -{ - modify_cp0_intmask(0, irq_nr); -} - - -static void disable_cpu_irq_input(unsigned int irq_nr) -{ - unsigned long flags; - - save_and_cli(flags); - mask_cpu_irq_input(irq_nr); - restore_flags(flags); -} - - -static void enable_cpu_irq_input(unsigned int irq_nr) -{ - unsigned long flags; - - save_and_cli(flags); - unmask_cpu_irq_input(irq_nr); - restore_flags(flags); -} +#ifdef CONFIG_PM +extern void counter0_irq(int irq, void *dev_id, struct pt_regs *regs); +#endif +static spinlock_t irq_lock = SPIN_LOCK_UNLOCKED; static void setup_local_irq(unsigned int irq_nr, int type, int int_req) { + if (irq_nr > AU1000_MAX_INTR) return; /* Config2[n], Config1[n], Config0[n] */ if (irq_nr > AU1000_LAST_INTC0_INT) { switch (type) { case INTC_INT_RISE_EDGE: /* 0:0:1 */ - outl(1< AU1000_LAST_INTC0_INT) { - outl(1< AU1000_LAST_INTC0_INT) { - outl(1< AU1000_LAST_INTC0_INT) { - outl(1< AU1000_LAST_INTC0_INT) { - outl(1<>= 1; } } @@ -417,55 +548,84 @@ void intc0_req1_irqdispatch(struct pt_regs *regs) { int irq = 0, i; - unsigned long int_request; + static unsigned long intc0_req1 = 0; - int_request = inl(INTC0_REQ1_INT); + intc0_req1 = au_readl(IC0_REQ1INT); - if (!int_request) return; + if (!intc0_req1) return; for (i=0; i<32; i++) { - if ((int_request & 0x1)) { - do_IRQ(irq, regs); + if ((intc0_req1 & (1<>= 1; } } +/* + * Interrupt Controller 1: + * interrupts 32 - 63 + */ void intc1_req0_irqdispatch(struct pt_regs *regs) { int irq = 0, i; - unsigned long int_request; + static unsigned long intc1_req0 = 0; - int_request = inl(INTC1_REQ0_INT); + intc1_req0 |= au_readl(IC1_REQ0INT); - if (!int_request) return; + if (!intc1_req0) return; +#if defined(CONFIG_MIPS_PB1000) && defined(DEBUG_IRQ) + au_writel(1, CPLD_AUX0); /* debug led 0 */ +#endif for (i=0; i<32; i++) { - if ((int_request & 0x1)) { - do_IRQ(irq, regs); + if ((intc1_req0 & (1<>= 1; } +#if defined(CONFIG_MIPS_PB1000) && defined(DEBUG_IRQ) + au_writel(0, CPLD_AUX0); +#endif } void intc1_req1_irqdispatch(struct pt_regs *regs) { int irq = 0, i; - unsigned long int_request; + static unsigned long intc1_req1 = 0; - int_request = inl(INTC1_REQ1_INT); + intc1_req1 |= au_readl(IC1_REQ1INT); - if (!int_request) return; + if (!intc1_req1) return; for (i=0; i<32; i++) { - if ((int_request & 0x1)) { - do_IRQ(irq, regs); + if ((intc1_req1 & (1<>= 1; } } diff -Nru a/arch/mips/au1000/common/power.c b/arch/mips/au1000/common/power.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/common/power.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,332 @@ +/* + * BRIEF MODULE DESCRIPTION + * Au1000 Power Management routines. + * + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * Some of the routines are right out of init/main.c, whose + * copyrights apply here. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define DEBUG 1 +#ifdef DEBUG +# define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args) +#else +# define DPRINTK(fmt, args...) +#endif + +extern void au1k_wait(void); +static void calibrate_delay(void); + +extern void set_au1000_speed(unsigned int new_freq); +extern unsigned int get_au1000_speed(void); +extern unsigned long get_au1000_uart_baud_base(void); +extern void set_au1000_uart_baud_base(unsigned long new_baud_base); +extern unsigned long save_local_and_disable(int controller); +extern void restore_local_and_enable(int controller, unsigned long mask); +extern void local_enable_irq(unsigned int irq_nr); + +/* Quick acpi hack. This will have to change! */ +#define CTL_ACPI 9999 +#define ACPI_S1_SLP_TYP 19 +#define ACPI_SLEEP 21 + +#ifdef CONFIG_PM + +static spinlock_t pm_lock = SPIN_LOCK_UNLOCKED; + +unsigned long suspend_mode; + +void wakeup_from_suspend(void) +{ + suspend_mode = 0; +} + +int au_sleep(void) +{ + unsigned long wakeup, flags; + spin_lock_irqsave(&pm_lock,flags); + + flush_cache_all(); + /* pin 6 is gpio */ + au_writel(au_readl(SYS_PINSTATERD) & ~(1 << 11), SYS_PINSTATERD); + + /* gpio 6 can cause a wake up event */ + wakeup = au_readl(SYS_WAKEMSK); + wakeup &= ~(1 << 8); /* turn off match20 wakeup */ + wakeup |= 1 << 6; /* turn on gpio 6 wakeup */ + au_writel(wakeup, SYS_WAKEMSK); + + au_writel(1, SYS_WAKESRC); /* clear cause */ + au_writel(1, SYS_SLPPWR); /* prepare to sleep */ + + __asm__("la $4, 1f\n\t" + "lui $5, 0xb190\n\t" + "ori $5, 0x18\n\t" + "sw $4, 0($5)\n\t" + "li $4, 1\n\t" + "lui $5, 0xb190\n\t" + "ori $5, 0x7c\n\t" + "sw $4, 0($5)\n\t" "sync\n\t" "1:\t\n\t" "nop\n\t"); + + /* after a wakeup, the cpu vectors back to 0x1fc00000 so + * it's up to the boot code to get us back here. + */ + spin_unlock_irqrestore(&pm_lock, flags); + return 0; +} + +static int pm_do_sleep(ctl_table * ctl, int write, struct file *file, + void *buffer, size_t * len) +{ + int retval = 0; + + if (!write) { + *len = 0; + } else { + retval = pm_send_all(PM_SUSPEND, (void *) 2); + if (retval) + return retval; + + au_sleep(); + retval = pm_send_all(PM_RESUME, (void *) 0); + } + return retval; +} + +static int pm_do_suspend(ctl_table * ctl, int write, struct file *file, + void *buffer, size_t * len) +{ + int retval = 0; + + if (!write) { + *len = 0; + } else { + retval = pm_send_all(PM_SUSPEND, (void *) 2); + if (retval) + return retval; + suspend_mode = 1; + au1k_wait(); + retval = pm_send_all(PM_RESUME, (void *) 0); + } + return retval; +} + + +static int pm_do_freq(ctl_table * ctl, int write, struct file *file, + void *buffer, size_t * len) +{ + int retval = 0, i; + unsigned long val, pll; +#define TMPBUFLEN 64 +#define MAX_CPU_FREQ 396 + char buf[8], *p; + unsigned long flags, intc0_mask, intc1_mask; + unsigned long old_baud_base, old_cpu_freq, baud_rate, old_clk, + old_refresh; + unsigned long new_baud_base, new_cpu_freq, new_clk, new_refresh; + + spin_lock_irqsave(&pm_lock, flags); + if (!write) { + *len = 0; + } else { + /* Parse the new frequency */ + if (*len > TMPBUFLEN - 1) { + spin_unlock_irqrestore(&pm_lock, flags); + return -EFAULT; + } + if (copy_from_user(buf, buffer, *len)) { + spin_unlock_irqrestore(&pm_lock, flags); + return -EFAULT; + } + buf[*len] = 0; + p = buf; + val = simple_strtoul(p, &p, 0); + if (val > MAX_CPU_FREQ) { + spin_unlock_irqrestore(&pm_lock, flags); + return -EFAULT; + } + + pll = val / 12; + if ((pll > 33) || (pll < 7)) { /* 396 MHz max, 84 MHz min */ + /* revisit this for higher speed cpus */ + spin_unlock_irqrestore(&pm_lock, flags); + return -EFAULT; + } + + old_baud_base = get_au1000_uart_baud_base(); + old_cpu_freq = get_au1000_speed(); + + new_cpu_freq = pll * 12 * 1000000; + new_baud_base = (new_cpu_freq / 4) / 16; + set_au1000_speed(new_cpu_freq); + set_au1000_uart_baud_base(new_baud_base); + + old_refresh = au_readl(MEM_SDREFCFG) & 0x1ffffff; + new_refresh = + ((old_refresh * new_cpu_freq) / + old_cpu_freq) | (au_readl(MEM_SDREFCFG) & ~0x1ffffff); + + au_writel(pll, SYS_CPUPLL); + au_sync_delay(1); + au_writel(new_refresh, MEM_SDREFCFG); + au_sync_delay(1); + + for (i = 0; i < 4; i++) { + if (au_readl + (UART_BASE + UART_MOD_CNTRL + + i * 0x00100000) == 3) { + old_clk = + au_readl(UART_BASE + UART_CLK + + i * 0x00100000); + // baud_rate = baud_base/clk + baud_rate = old_baud_base / old_clk; + /* we won't get an exact baud rate and the error + * could be significant enough that our new + * calculation will result in a clock that will + * give us a baud rate that's too far off from + * what we really want. + */ + if (baud_rate > 100000) + baud_rate = 115200; + else if (baud_rate > 50000) + baud_rate = 57600; + else if (baud_rate > 30000) + baud_rate = 38400; + else if (baud_rate > 17000) + baud_rate = 19200; + else + (baud_rate = 9600); + // new_clk = new_baud_base/baud_rate + new_clk = new_baud_base / baud_rate; + au_writel(new_clk, + UART_BASE + UART_CLK + + i * 0x00100000); + au_sync_delay(10); + } + } + } + + + /* We don't want _any_ interrupts other than + * match20. Otherwise our calibrate_delay() + * calculation will be off, potentially a lot. + */ + intc0_mask = save_local_and_disable(0); + intc1_mask = save_local_and_disable(1); + local_enable_irq(AU1000_TOY_MATCH2_INT); + spin_unlock_irqrestore(&pm_lock, flags); + calibrate_delay(); + restore_local_and_enable(0, intc0_mask); + restore_local_and_enable(1, intc1_mask); + return retval; +} + + +static struct ctl_table pm_table[] = { + {ACPI_S1_SLP_TYP, "suspend", NULL, 0, 0600, NULL, &pm_do_suspend}, + {ACPI_SLEEP, "sleep", NULL, 0, 0600, NULL, &pm_do_sleep}, + {CTL_ACPI, "freq", NULL, 0, 0600, NULL, &pm_do_freq}, + {0} +}; + +static struct ctl_table pm_dir_table[] = { + {CTL_ACPI, "pm", NULL, 0, 0555, pm_table}, + {0} +}; + +/* + * Initialize power interface + */ +static int __init pm_init(void) +{ + register_sysctl_table(pm_dir_table, 1); + return 0; +} + +__initcall(pm_init); + + +/* + * This is right out of init/main.c + */ + +/* This is the number of bits of precision for the loops_per_jiffy. Each + bit takes on average 1.5/HZ seconds. This (like the original) is a little + better than 1% */ +#define LPS_PREC 8 + +static void calibrate_delay(void) +{ + unsigned long ticks, loopbit; + int lps_precision = LPS_PREC; + + loops_per_jiffy = (1 << 12); + + while (loops_per_jiffy <<= 1) { + /* wait for "start of" clock tick */ + ticks = jiffies; + while (ticks == jiffies) + /* nothing */ ; + /* Go .. */ + ticks = jiffies; + __delay(loops_per_jiffy); + ticks = jiffies - ticks; + if (ticks) + break; + } + +/* Do a binary approximation to get loops_per_jiffy set to equal one clock + (up to lps_precision bits) */ + loops_per_jiffy >>= 1; + loopbit = loops_per_jiffy; + while (lps_precision-- && (loopbit >>= 1)) { + loops_per_jiffy |= loopbit; + ticks = jiffies; + while (ticks == jiffies); + ticks = jiffies; + __delay(loops_per_jiffy); + if (jiffies != ticks) /* longer than 1 tick */ + loops_per_jiffy &= ~loopbit; + } +} + +void au1k_wait(void) +{ + __asm__("nop\n\t" "nop\n\t"); +} + +#endif /* CONFIG_PM */ diff -Nru a/arch/mips/au1000/common/prom.c b/arch/mips/au1000/common/prom.c --- a/arch/mips/au1000/common/prom.c Tue Jul 1 18:44:36 2003 +++ b/arch/mips/au1000/common/prom.c Tue Jul 1 18:44:36 2003 @@ -4,11 +4,11 @@ * PROM library initialisation code, assuming a version of * pmon is the boot code. * - * Copyright 2000 MontaVista Software Inc. + * Copyright 2000,2001 MontaVista Software Inc. * Author: MontaVista Software, Inc. * ppopov@mvista.com or source@mvista.com * - * This file was derived from Carsten Langgaard's + * This file was derived from Carsten Langgaard's * arch/mips/mips-boards/xx files. * * Carsten Langgaard, carstenl@mips.com @@ -35,7 +35,7 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include +#include #include #include #include @@ -44,22 +44,23 @@ /* #define DEBUG_CMDLINE */ -char arcs_cmdline[COMMAND_LINE_SIZE]; -int prom_argc; -char **prom_argv, **prom_envp; +char arcs_cmdline[CL_SIZE]; +extern int prom_argc; +extern char **prom_argv, **prom_envp; -typedef struct { - char *name; -/* char *val; */ -} t_env_var; +typedef struct +{ + char *name; +/* char *val; */ +}t_env_var; -char * __init prom_getcmdline(void) +char * prom_getcmdline(void) { return &(arcs_cmdline[0]); } -void __init prom_init_cmdline(void) +void prom_init_cmdline(void) { char *cp; int actr; @@ -101,20 +102,57 @@ return(NULL); } -static inline unsigned char str2hexnum(unsigned char c) +inline unsigned char str2hexnum(unsigned char c) { if(c >= '0' && c <= '9') - return c - '0'; + return c - '0'; if(c >= 'a' && c <= 'f') - return c - 'a' + 10; + return c - 'a' + 10; + if(c >= 'A' && c <= 'F') + return c - 'A' + 10; return 0; /* foo */ } -int __init page_is_ram(unsigned long pagenr) +inline void str2eaddr(unsigned char *ea, unsigned char *str) { - return 1; + int i; + + for(i = 0; i < 6; i++) { + unsigned char num; + + if((*str == '.') || (*str == ':')) + str++; + num = str2hexnum(*str++) << 4; + num |= (str2hexnum(*str++)); + ea[i] = num; + } } -void prom_free_prom_memory (void) +int get_ethernet_addr(char *ethernet_addr) { + char *ethaddr_str; + + ethaddr_str = prom_getenv("ethaddr"); + if (!ethaddr_str) { + printk("ethaddr not set in boot prom\n"); + return -1; + } + str2eaddr(ethernet_addr, ethaddr_str); + +#if 0 + { + int i; + + printk("get_ethernet_addr: "); + for (i=0; i<5; i++) + printk("%02x:", (unsigned char)*(ethernet_addr+i)); + printk("%02x\n", *(ethernet_addr+i)); + } +#endif + + return 0; } + +void prom_free_prom_memory (void) {} +EXPORT_SYMBOL(prom_getcmdline); +EXPORT_SYMBOL(get_ethernet_addr); diff -Nru a/arch/mips/au1000/common/puts.c b/arch/mips/au1000/common/puts.c --- a/arch/mips/au1000/common/puts.c Tue Jul 1 18:44:37 2003 +++ b/arch/mips/au1000/common/puts.c Tue Jul 1 18:44:37 2003 @@ -29,8 +29,9 @@ */ #include +#include -#define SERIAL_BASE 0xB1100000 /* au1000, uart 0 */ +#define SERIAL_BASE UART_BASE #define SER_CMD 0x7 #define SER_DATA 0x1 #define TX_BUSY 0x20 diff -Nru a/arch/mips/au1000/common/reset.c b/arch/mips/au1000/common/reset.c --- a/arch/mips/au1000/common/reset.c Tue Jul 1 18:44:31 2003 +++ b/arch/mips/au1000/common/reset.c Tue Jul 1 18:44:31 2003 @@ -27,7 +27,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 675 Mass Ave, Cambridge, MA 02139, USA. */ - +#include #include #include #include @@ -35,23 +35,107 @@ #include #include #include +#include + +extern int au_sleep(void); void au1000_restart(char *command) { - set_cp0_status(ST0_BEV | ST0_ERL); - set_cp0_config(CONF_CM_UNCACHED); + /* Set all integrated peripherals to disabled states */ + u32 prid = read_c0_prid(); + + printk(KERN_NOTICE "\n** Resetting Integrated Peripherals\n"); + switch (prid & 0xFF000000) + { + case 0x00000000: /* Au1000 */ + au_writel(0x02, 0xb0000010); /* ac97_enable */ + au_writel(0x08, 0xb017fffc); /* usbh_enable - early errata */ + asm("sync"); + au_writel(0x00, 0xb017fffc); /* usbh_enable */ + au_writel(0x00, 0xb0200058); /* usbd_enable */ + au_writel(0x00, 0xb0300040); /* ir_enable */ + au_writel(0x00, 0xb0520000); /* macen0 */ + au_writel(0x00, 0xb0520004); /* macen1 */ + au_writel(0x00, 0xb1000008); /* i2s_enable */ + au_writel(0x00, 0xb1100100); /* uart0_enable */ + au_writel(0x00, 0xb1200100); /* uart1_enable */ + au_writel(0x00, 0xb1300100); /* uart2_enable */ + au_writel(0x00, 0xb1400100); /* uart3_enable */ + au_writel(0x02, 0xb1600100); /* ssi0_enable */ + au_writel(0x02, 0xb1680100); /* ssi1_enable */ + au_writel(0x00, 0xb1900020); /* sys_freqctrl0 */ + au_writel(0x00, 0xb1900024); /* sys_freqctrl1 */ + au_writel(0x00, 0xb1900028); /* sys_clksrc */ + au_writel(0x00, 0xb1900100); /* sys_pininputen */ + break; + case 0x01000000: /* Au1500 */ + au_writel(0x02, 0xb0000010); /* ac97_enable */ + au_writel(0x08, 0xb017fffc); /* usbh_enable - early errata */ + asm("sync"); + au_writel(0x00, 0xb017fffc); /* usbh_enable */ + au_writel(0x00, 0xb0200058); /* usbd_enable */ + au_writel(0x00, 0xb1520000); /* macen0 */ + au_writel(0x00, 0xb1520004); /* macen1 */ + au_writel(0x00, 0xb1100100); /* uart0_enable */ + au_writel(0x00, 0xb1400100); /* uart3_enable */ + au_writel(0x00, 0xb1900020); /* sys_freqctrl0 */ + au_writel(0x00, 0xb1900024); /* sys_freqctrl1 */ + au_writel(0x00, 0xb1900028); /* sys_clksrc */ + au_writel(0x00, 0xb1900100); /* sys_pininputen */ + break; + case 0x02000000: /* Au1100 */ + au_writel(0x02, 0xb0000010); /* ac97_enable */ + au_writel(0x08, 0xb017fffc); /* usbh_enable - early errata */ + asm("sync"); + au_writel(0x00, 0xb017fffc); /* usbh_enable */ + au_writel(0x00, 0xb0200058); /* usbd_enable */ + au_writel(0x00, 0xb0300040); /* ir_enable */ + au_writel(0x00, 0xb0520000); /* macen0 */ + au_writel(0x00, 0xb1000008); /* i2s_enable */ + au_writel(0x00, 0xb1100100); /* uart0_enable */ + au_writel(0x00, 0xb1200100); /* uart1_enable */ + au_writel(0x00, 0xb1400100); /* uart3_enable */ + au_writel(0x02, 0xb1600100); /* ssi0_enable */ + au_writel(0x02, 0xb1680100); /* ssi1_enable */ + au_writel(0x00, 0xb1900020); /* sys_freqctrl0 */ + au_writel(0x00, 0xb1900024); /* sys_freqctrl1 */ + au_writel(0x00, 0xb1900028); /* sys_clksrc */ + au_writel(0x00, 0xb1900100); /* sys_pininputen */ + break; + + default: + break; + } + + set_c0_status(ST0_BEV | ST0_ERL); + set_c0_config(CONF_CM_UNCACHED); flush_cache_all(); - write_32bit_cp0_register(CP0_WIRED, 0); + write_c0_wired(0); + +#if defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_DB1000) || defined(CONFIG_MIPS_DB1100) || defined(CONFIG_MIPS_DB1500) + /* Do a HW reset if the board can do it */ + + au_writel(0x00000000, 0xAE00001C); +#endif + __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); } void au1000_halt(void) { printk(KERN_NOTICE "\n** You can safely turn off the power\n"); +#ifdef CONFIG_PM + au_sleep(); + + /* should not get here */ + printk(KERN_ERR "Unable to put cpu in sleep mode\n"); + while(1); +#else while (1) __asm__(".set\tmips3\n\t" "wait\n\t" ".set\tmips0"); +#endif } void au1000_power_off(void) diff -Nru a/arch/mips/au1000/common/rtc.c b/arch/mips/au1000/common/rtc.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/common/rtc.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,37 @@ +/* + * 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. + * + * RTC routines for PC style attached Dallas chip. + * + * Copyright (C) 1998, 2001 by Ralf Baechle + */ +#include +#include +#include + +#define PB1500_RTC_ADDR 0xAC000000 + +unsigned char std_rtc_read_data(unsigned long offset) +{ + offset <<= 2; + return (u8)(au_readl(offset + PB1500_RTC_ADDR) & 0xff); +} + +static void std_rtc_write_data(unsigned char data, unsigned long offset) +{ + offset <<= 2; + au_writel(data, offset + PB1500_RTC_ADDR); +} + +static int std_rtc_bcd_mode(void) +{ + return 1; +} + +struct rtc_ops pb1500_rtc_ops = { + &std_rtc_read_data, + &std_rtc_write_data, + &std_rtc_bcd_mode +}; diff -Nru a/arch/mips/au1000/common/serial.c b/arch/mips/au1000/common/serial.c --- a/arch/mips/au1000/common/serial.c Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,2980 +0,0 @@ -/* - * - * BRIEF MODULE DESCRIPTION - * Au1000 serial port driver. - * - * Copyright 2001 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * ppopov@mvista.com or source@mvista.com - * - * Derived almost entirely from drivers/char/serial.c: - * - * Copyright (C) 1991, 1992 Linus Torvalds - * Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, - * 1998, 1999 Theodore Ts'o - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -static char *serial_version = "1.01"; -static char *serial_revdate = "2001-02-08"; - - -#include -#include - -#undef SERIAL_PARANOIA_CHECK -#define CONFIG_SERIAL_NOPAUSE_IO -#define SERIAL_DO_RESTART - - -/* Set of debugging defines */ - -#undef SERIAL_DEBUG_INTR -#undef SERIAL_DEBUG_OPEN -#undef SERIAL_DEBUG_FLOW -#undef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT -#undef SERIAL_DEBUG_PCI -#undef SERIAL_DEBUG_AUTOCONF - -#ifdef MODULE -#undef CONFIG_AU1000_SERIAL_CONSOLE -#endif - -#define CONFIG_SERIAL_RSA - -#define RS_STROBE_TIME (10*HZ) -#define RS_ISR_PASS_LIMIT 256 - -/* - * End of serial driver configuration section. - */ - -#include - -#include -#ifdef LOCAL_HEADERS -#include "serial_local.h" -#else -#include -#include -#include -#include -#define LOCAL_VERSTRING "" -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_AU1000_SERIAL_CONSOLE -#include -#endif -#ifdef CONFIG_MAGIC_SYSRQ -#include -#endif - -#include -#include -#include -#include - -#ifdef CONFIG_MAC_SERIAL -#define SERIAL_DEV_OFFSET 2 -#else -#define SERIAL_DEV_OFFSET 0 -#endif - -#ifdef SERIAL_INLINE -#define _INLINE_ inline -#else -#define _INLINE_ -#endif - -static char *serial_name = "Serial driver"; - -static DECLARE_TASK_QUEUE(tq_serial); - -static struct tty_driver *serial_driver; - -static struct timer_list serial_timer; - -extern unsigned long get_au1000_uart_baud(void); - -/* serial subtype definitions */ -#ifndef SERIAL_TYPE_NORMAL -#define SERIAL_TYPE_NORMAL 1 -#endif - -/* number of characters left in xmit buffer before we ask for more */ -#define WAKEUP_CHARS 256 - -/* - * IRQ_timeout - How long the timeout should be for each IRQ - * should be after the IRQ has been active. - */ - -static struct async_struct *IRQ_ports[NR_IRQS]; -static int IRQ_timeout[NR_IRQS]; -#ifdef CONFIG_AU1000_SERIAL_CONSOLE -static struct console sercons; -static int lsr_break_flag; -#endif -#if defined(CONFIG_AU1000_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) -static unsigned long break_pressed; /* break, really ... */ -#endif - -static void autoconfig(struct serial_state * state); -static void change_speed(struct async_struct *info, struct termios *old); -static void rs_wait_until_sent(struct tty_struct *tty, int timeout); - -/* - * Here we define the default xmit fifo size used for each type of - * UART - */ -static struct serial_uart_config uart_config[] = { - { "unknown", 1, 0 }, - { "8250", 1, 0 }, - { "16450", 1, 0 }, - { "16550", 1, 0 }, - { 0, 0} -}; - - -static struct serial_state rs_table[RS_TABLE_SIZE] = { - SERIAL_PORT_DFNS /* Defined in serial.h */ -}; - -#define NR_PORTS (sizeof(rs_table)/sizeof(struct serial_state)) - -#ifndef PREPARE_FUNC -#define PREPARE_FUNC(dev) (dev->prepare) -#define ACTIVATE_FUNC(dev) (dev->activate) -#define DEACTIVATE_FUNC(dev) (dev->deactivate) -#endif - -#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) - -#if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT) -#define DBG_CNT(s) printk("(%s): [%x], refc=%d, serc=%d, ttyc=%d -> %s\n", \ - tty->name, (info->flags), serial_driver->refcount, info->count,tty->count,s) -#else -#define DBG_CNT(s) -#endif - -/* - * tmp_buf is used as a temporary buffer by serial_write. We need to - * lock it in case the copy_from_user blocks while swapping in a page, - * and some other program tries to do a serial write at the same time. - * Since the lock will only come under contention when the system is - * swapping and available memory is low, it makes sense to share one - * buffer across all the serial ports, since it significantly saves - * memory if large numbers of serial ports are open. - */ -static unsigned char *tmp_buf; -#ifdef DECLARE_MUTEX -static DECLARE_MUTEX(tmp_buf_sem); -#else -static struct semaphore tmp_buf_sem = MUTEX; -#endif - - -static inline int serial_paranoia_check(struct async_struct *info, - char *name, const char *routine) -{ -#ifdef SERIAL_PARANOIA_CHECK - static const char *badmagic = - "Warning: bad magic number for serial struct (%s) in %s\n"; - static const char *badinfo = - "Warning: null async_struct for (%s) in %s\n"; - - if (!info) { - printk(badinfo, name, routine); - return 1; - } - if (info->magic != SERIAL_MAGIC) { - printk(badmagic, name, routine); - return 1; - } -#endif - return 0; -} - - -static _INLINE_ unsigned int serial_in(struct async_struct *info, int offset) -{ - return (inl(info->port+offset) & 0xff); -} - -static _INLINE_ void serial_out(struct async_struct *info, int offset, int value) -{ - outl(value & 0xff, info->port+offset); -} - - -/* - * We used to support using pause I/O for certain machines. We - * haven't supported this for a while, but just in case it's badly - * needed for certain old 386 machines, I've left these #define's - * in.... - */ -#define serial_inp(info, offset) serial_in(info, offset) -#define serial_outp(info, offset, value) serial_out(info, offset, value) - - -/* - * ------------------------------------------------------------ - * rs_stop() and rs_start() - * - * This routines are called before setting or resetting tty->stopped. - * They enable or disable transmitter interrupts, as necessary. - * ------------------------------------------------------------ - */ -static void rs_stop(struct tty_struct *tty) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_stop")) - return; - - save_flags(flags); cli(); - if (info->IER & UART_IER_THRI) { - info->IER &= ~UART_IER_THRI; - serial_out(info, UART_IER, info->IER); - } - restore_flags(flags); -} - -static void rs_start(struct tty_struct *tty) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_start")) - return; - - save_flags(flags); cli(); - if (info->xmit.head != info->xmit.tail - && info->xmit.buf - && !(info->IER & UART_IER_THRI)) { - info->IER |= UART_IER_THRI; - serial_out(info, UART_IER, info->IER); - } - restore_flags(flags); -} - -/* - * ---------------------------------------------------------------------- - * - * Here starts the interrupt handling routines. All of the following - * subroutines are declared as inline and are folded into - * rs_interrupt(). They were separated out for readability's sake. - * - * Note: rs_interrupt() is a "fast" interrupt, which means that it - * runs with interrupts turned off. People who may want to modify - * rs_interrupt() should try to keep the interrupt handler as fast as - * possible. After you are done making modifications, it is not a bad - * idea to do: - * - * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c - * - * and look at the resulting assemble code in serial.s. - * - * - Ted Ts'o (tytso@mit.edu), 7-Mar-93 - * ----------------------------------------------------------------------- - */ - -/* - * This routine is used by the interrupt handler to schedule - * processing in the software interrupt portion of the driver. - */ -static _INLINE_ void rs_sched_event(struct async_struct *info, - int event) -{ - info->event |= 1 << event; - queue_task(&info->tqueue, &tq_serial); - mark_bh(SERIAL_BH); -} - -static _INLINE_ void receive_chars(struct async_struct *info, - int *status, struct pt_regs * regs) -{ - struct tty_struct *tty = info->tty; - unsigned char ch; - int ignored = 0; - struct async_icount *icount; - - icount = &info->state->icount; - do { - ch = serial_inp(info, UART_RX); - if (tty->flip.count >= TTY_FLIPBUF_SIZE) - goto ignore_char; - *tty->flip.char_buf_ptr = ch; - icount->rx++; - -#ifdef SERIAL_DEBUG_INTR - printk("DR%02x:%02x...", ch, *status); -#endif - *tty->flip.flag_buf_ptr = 0; - if (*status & (UART_LSR_BI | UART_LSR_PE | - UART_LSR_FE | UART_LSR_OE)) { - /* - * For statistics only - */ - if (*status & UART_LSR_BI) { - *status &= ~(UART_LSR_FE | UART_LSR_PE); - icount->brk++; - /* - * We do the SysRQ and SAK checking - * here because otherwise the break - * may get masked by ignore_status_mask - * or read_status_mask. - */ -#if defined(CONFIG_AU1000_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) - if (info->line == sercons.index) { - if (!break_pressed) { - break_pressed = jiffies; - goto ignore_char; - } - break_pressed = 0; - } -#endif - if (info->flags & ASYNC_SAK) - do_SAK(tty); - } else if (*status & UART_LSR_PE) - icount->parity++; - else if (*status & UART_LSR_FE) - icount->frame++; - if (*status & UART_LSR_OE) - icount->overrun++; - - /* - * Now check to see if character should be - * ignored, and mask off conditions which - * should be ignored. - */ - if (*status & info->ignore_status_mask) { - if (++ignored > 100) - break; - goto ignore_char; - } - *status &= info->read_status_mask; - -#ifdef CONFIG_AU1000_SERIAL_CONSOLE - if (info->line == sercons.index) { - /* Recover the break flag from console xmit */ - *status |= lsr_break_flag; - lsr_break_flag = 0; - } -#endif - if (*status & (UART_LSR_BI)) { -#ifdef SERIAL_DEBUG_INTR - printk("handling break...."); -#endif - *tty->flip.flag_buf_ptr = TTY_BREAK; - } else if (*status & UART_LSR_PE) - *tty->flip.flag_buf_ptr = TTY_PARITY; - else if (*status & UART_LSR_FE) - *tty->flip.flag_buf_ptr = TTY_FRAME; - if (*status & UART_LSR_OE) { - /* - * Overrun is special, since it's - * reported immediately, and doesn't - * affect the current character - */ - tty->flip.count++; - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - *tty->flip.flag_buf_ptr = TTY_OVERRUN; - if (tty->flip.count >= TTY_FLIPBUF_SIZE) - goto ignore_char; - } - } -#if defined(CONFIG_AU1000_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) - if (break_pressed && info->line == sercons.index) { - if (ch != 0 && - time_before(jiffies, break_pressed + HZ*5)) { - handle_sysrq(ch, regs, NULL); - break_pressed = 0; - goto ignore_char; - } - break_pressed = 0; - } -#endif - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - tty->flip.count++; - ignore_char: - *status = serial_inp(info, UART_LSR); - } while (*status & UART_LSR_DR); - tty_flip_buffer_push(tty); -} - -static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done) -{ - int count; - - if (info->x_char) { - serial_outp(info, UART_TX, info->x_char); - info->state->icount.tx++; - info->x_char = 0; - if (intr_done) - *intr_done = 0; - return; - } - if (info->xmit.head == info->xmit.tail - || info->tty->stopped - || info->tty->hw_stopped) { - info->IER &= ~UART_IER_THRI; - serial_out(info, UART_IER, info->IER); - return; - } - - count = info->xmit_fifo_size; - do { - serial_out(info, UART_TX, info->xmit.buf[info->xmit.tail]); - info->xmit.tail = (info->xmit.tail + 1) & (SERIAL_XMIT_SIZE-1); - info->state->icount.tx++; - if (info->xmit.head == info->xmit.tail) - break; - } while (--count > 0); - - if (CIRC_CNT(info->xmit.head, - info->xmit.tail, - SERIAL_XMIT_SIZE) < WAKEUP_CHARS) - rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); - -#ifdef SERIAL_DEBUG_INTR - printk("THRE..."); -#endif - if (intr_done) - *intr_done = 0; - - if (info->xmit.head == info->xmit.tail) { - info->IER &= ~UART_IER_THRI; - serial_out(info, UART_IER, info->IER); - } -} - -static _INLINE_ void check_modem_status(struct async_struct *info) -{ - int status; - struct async_icount *icount; - - status = serial_in(info, UART_MSR); - - if (status & UART_MSR_ANY_DELTA) { - icount = &info->state->icount; - /* update input line counters */ - if (status & UART_MSR_TERI) - icount->rng++; - if (status & UART_MSR_DDSR) - icount->dsr++; - if (status & UART_MSR_DDCD) { - icount->dcd++; -#ifdef CONFIG_HARD_PPS - if ((info->flags & ASYNC_HARDPPS_CD) && - (status & UART_MSR_DCD)) - hardpps(); -#endif - } - if (status & UART_MSR_DCTS) - icount->cts++; - wake_up_interruptible(&info->delta_msr_wait); - } - - if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) { -#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR)) - printk("ttys%d CD now %s...", info->line, - (status & UART_MSR_DCD) ? "on" : "off"); -#endif - if (status & UART_MSR_DCD) - wake_up_interruptible(&info->open_wait); - else { -#ifdef SERIAL_DEBUG_OPEN - printk("doing serial hangup..."); -#endif - if (info->tty) - tty_hangup(info->tty); - } - } - if (info->flags & ASYNC_CTS_FLOW) { - if (info->tty->hw_stopped) { - if (status & UART_MSR_CTS) { -#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW)) - printk("CTS tx start..."); -#endif - info->tty->hw_stopped = 0; - info->IER |= UART_IER_THRI; - serial_out(info, UART_IER, info->IER); - rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); - return; - } - } else { - if (!(status & UART_MSR_CTS)) { -#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW)) - printk("CTS tx stop..."); -#endif - info->tty->hw_stopped = 1; - info->IER &= ~UART_IER_THRI; - serial_out(info, UART_IER, info->IER); - } - } - } -} - - - -/* - * This is the serial driver's interrupt routine for a single port - */ -static void rs_interrupt_single(int irq, void *dev_id, struct pt_regs * regs) -{ - int status; - int pass_counter = 0; - struct async_struct * info; - -#ifdef SERIAL_DEBUG_INTR - printk("rs_interrupt_single(%d)...", irq); -#endif - - info = IRQ_ports[irq]; - if (!info || !info->tty) - return; - - do { - status = serial_inp(info, UART_LSR); -#ifdef SERIAL_DEBUG_INTR - printk("status = %x...", status); -#endif - if (status & UART_LSR_DR) - receive_chars(info, &status, regs); - check_modem_status(info); - if (status & UART_LSR_THRE) - transmit_chars(info, 0); - if (pass_counter++ > RS_ISR_PASS_LIMIT) { -#if 0 - printk("rs_single loop break.\n"); -#endif - break; - } - } while (!(serial_in(info, UART_IIR) & UART_IIR_NO_INT)); - info->last_active = jiffies; -#ifdef SERIAL_DEBUG_INTR - printk("end.\n"); -#endif -} - - -/* - * ------------------------------------------------------------------- - * Here ends the serial interrupt routines. - * ------------------------------------------------------------------- - */ - -/* - * This routine is used to handle the "bottom half" processing for the - * serial driver, known also the "software interrupt" processing. - * This processing is done at the kernel interrupt level, after the - * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This - * is where time-consuming activities which can not be done in the - * interrupt driver proper are done; the interrupt driver schedules - * them using rs_sched_event(), and they get done here. - */ -static void do_serial_bh(void) -{ - run_task_queue(&tq_serial); -} - -static void do_softint(void *private_) -{ - struct async_struct *info = (struct async_struct *) private_; - struct tty_struct *tty; - - tty = info->tty; - if (!tty) - return; - - if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) { - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); - wake_up_interruptible(&tty->write_wait); -#ifdef SERIAL_HAVE_POLL_WAIT - wake_up_interruptible(&tty->poll_wait); -#endif - } -} - -/* - * This subroutine is called when the RS_TIMER goes off. It is used - * by the serial driver to handle ports that do not have an interrupt - * (irq=0). This doesn't work very well for 16450's, but gives barely - * passable results for a 16550A. (Although at the expense of much - * CPU overhead). - */ -static void rs_timer(unsigned long dummy) -{ - static unsigned long last_strobe; - struct async_struct *info; - unsigned int i; - unsigned long flags; - - if ((jiffies - last_strobe) >= RS_STROBE_TIME) { - for (i=0; i < NR_IRQS; i++) { - info = IRQ_ports[i]; - if (!info) - continue; - save_flags(flags); cli(); - rs_interrupt_single(i, NULL, NULL); - restore_flags(flags); - } - } - last_strobe = jiffies; - mod_timer(&serial_timer, jiffies + RS_STROBE_TIME); - -#if 0 - if (IRQ_ports[0]) { - save_flags(flags); cli(); - rs_interrupt_single(0, NULL, NULL); - restore_flags(flags); - - mod_timer(&serial_timer, jiffies + IRQ_timeout[0]); - } -#endif -} - -/* - * --------------------------------------------------------------- - * Low level utility subroutines for the serial driver: routines to - * figure out the appropriate timeout for an interrupt chain, routines - * to initialize and startup a serial port, and routines to shutdown a - * serial port. Useful stuff like that. - * --------------------------------------------------------------- - */ - -/* - * This routine figures out the correct timeout for a particular IRQ. - * It uses the smallest timeout of all of the serial ports in a - * particular interrupt chain. Now only used for IRQ 0.... - */ -static void figure_IRQ_timeout(int irq) -{ - struct async_struct *info; - int timeout = 60*HZ; /* 60 seconds === a long time :-) */ - - info = IRQ_ports[irq]; - if (!info) { - IRQ_timeout[irq] = 60*HZ; - return; - } - while (info) { - if (info->timeout < timeout) - timeout = info->timeout; - info = info->next_port; - } - if (!irq) - timeout = timeout / 2; - IRQ_timeout[irq] = (timeout > 3) ? timeout-2 : 1; -} - - -static int startup(struct async_struct * info) -{ - unsigned long flags; - int retval=0; - void (*handler)(int, void *, struct pt_regs *); - struct serial_state *state= info->state; - unsigned long page; - - page = get_zeroed_page(GFP_KERNEL); - if (!page) - return -ENOMEM; - - save_flags(flags); cli(); - - if (info->flags & ASYNC_INITIALIZED) { - free_page(page); - goto errout; - } - - if (!CONFIGURED_SERIAL_PORT(state) || !state->type) { - if (info->tty) - set_bit(TTY_IO_ERROR, &info->tty->flags); - free_page(page); - goto errout; - } - if (info->xmit.buf) - free_page(page); - else - info->xmit.buf = (unsigned char *) page; - - - if (inl(UART_MOD_CNTRL + state->port) != 0x3) { - outl(3, UART_MOD_CNTRL + state->port); - } -#ifdef SERIAL_DEBUG_OPEN - printk("starting up ttys%d (irq %d)...", info->line, state->irq); -#endif - - - /* - * Clear the FIFO buffers and disable them - * (they will be reenabled in change_speed()) - */ - if (uart_config[state->type].flags & UART_CLEAR_FIFO) { - serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO); - serial_outp(info, UART_FCR, (UART_FCR_ENABLE_FIFO | - UART_FCR_CLEAR_RCVR | - UART_FCR_CLEAR_XMIT)); - serial_outp(info, UART_FCR, 0); - } - - /* - * Clear the interrupt registers. - */ - (void) serial_inp(info, UART_LSR); - (void) serial_inp(info, UART_RX); - (void) serial_inp(info, UART_IIR); - (void) serial_inp(info, UART_MSR); - - /* - * At this point there's no way the LSR could still be 0xFF; - * if it is, then bail out, because there's likely no UART - * here. - */ - if (!(info->flags & ASYNC_BUGGY_UART) && - (serial_inp(info, UART_LSR) == 0xff)) { - printk("LSR safety check engaged!\n"); - if (capable(CAP_SYS_ADMIN)) { - if (info->tty) - set_bit(TTY_IO_ERROR, &info->tty->flags); - } else - retval = -ENODEV; - goto errout; - } - - /* - * Allocate the IRQ if necessary - */ -#if 0 - /* au1000, uart0 irq is 0 */ - if (state->irq && (!IRQ_ports[state->irq] || !IRQ_ports[state->irq]->next_port)) { -#endif - if ((!IRQ_ports[state->irq] || !IRQ_ports[state->irq]->next_port)) { - if (IRQ_ports[state->irq]) { - retval = -EBUSY; - goto errout; - } else - handler = rs_interrupt_single; - - retval = request_irq(state->irq, handler, SA_SHIRQ, - "serial", &IRQ_ports[state->irq]); - if (retval) { - if (capable(CAP_SYS_ADMIN)) { - if (info->tty) - set_bit(TTY_IO_ERROR, - &info->tty->flags); - retval = 0; - } - goto errout; - } - } - - /* - * Insert serial port into IRQ chain. - */ - info->prev_port = 0; - info->next_port = IRQ_ports[state->irq]; - if (info->next_port) - info->next_port->prev_port = info; - IRQ_ports[state->irq] = info; - figure_IRQ_timeout(state->irq); - - /* - * Now, initialize the UART - */ - serial_outp(info, UART_LCR, UART_LCR_WLEN8); - - info->MCR = 0; - if (info->tty->termios->c_cflag & CBAUD) - info->MCR = UART_MCR_DTR | UART_MCR_RTS; - { - if (state->irq != 0) - info->MCR |= UART_MCR_OUT2; - } - info->MCR |= ALPHA_KLUDGE_MCR; /* Don't ask */ - serial_outp(info, UART_MCR, info->MCR); - - /* - * Finally, enable interrupts - */ - info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI; - serial_outp(info, UART_IER, info->IER); /* enable interrupts */ - - - /* - * And clear the interrupt registers again for luck. - */ - (void)serial_inp(info, UART_LSR); - (void)serial_inp(info, UART_RX); - (void)serial_inp(info, UART_IIR); - (void)serial_inp(info, UART_MSR); - - if (info->tty) - clear_bit(TTY_IO_ERROR, &info->tty->flags); - info->xmit.head = info->xmit.tail = 0; - - /* - * Set up serial timers... - */ - mod_timer(&serial_timer, jiffies + 2*HZ/100); - - /* - * Set up the tty->alt_speed kludge - */ - if (info->tty) { - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - info->tty->alt_speed = 57600; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - info->tty->alt_speed = 115200; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) - info->tty->alt_speed = 230400; - if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) - info->tty->alt_speed = 460800; - } - - /* - * and set the speed of the serial port - */ - change_speed(info, 0); - - info->flags |= ASYNC_INITIALIZED; - restore_flags(flags); - return 0; - -errout: - restore_flags(flags); - return retval; -} - -/* - * This routine will shutdown a serial port; interrupts are disabled, and - * DTR is dropped if the hangup on close termio flag is on. - */ -static void shutdown(struct async_struct * info) -{ - unsigned long flags; - struct serial_state *state; - int retval; - - if (!(info->flags & ASYNC_INITIALIZED)) - return; - - state = info->state; - -#ifdef SERIAL_DEBUG_OPEN - printk("Shutting down serial port %d (irq %d)....", info->line, - state->irq); -#endif - - save_flags(flags); cli(); /* Disable interrupts */ - - /* - * clear delta_msr_wait queue to avoid mem leaks: we may free the irq - * here so the queue might never be waken up - */ - wake_up_interruptible(&info->delta_msr_wait); - - /* - * First unlink the serial port from the IRQ chain... - */ - if (info->next_port) - info->next_port->prev_port = info->prev_port; - if (info->prev_port) - info->prev_port->next_port = info->next_port; - else - IRQ_ports[state->irq] = info->next_port; - figure_IRQ_timeout(state->irq); - - /* - * Free the IRQ, if necessary - */ -// if (state->irq && (!IRQ_ports[state->irq] || - if ((!IRQ_ports[state->irq] || - !IRQ_ports[state->irq]->next_port)) { - if (IRQ_ports[state->irq]) { - free_irq(state->irq, &IRQ_ports[state->irq]); - retval = request_irq(state->irq, rs_interrupt_single, - SA_SHIRQ, "serial", - &IRQ_ports[state->irq]); - - if (retval) - printk("serial shutdown: request_irq: error %d" - " Couldn't reacquire IRQ.\n", retval); - } else - free_irq(state->irq, &IRQ_ports[state->irq]); - } - - if (info->xmit.buf) { - unsigned long pg = (unsigned long) info->xmit.buf; - info->xmit.buf = 0; - free_page(pg); - } - - info->IER = 0; - serial_outp(info, UART_IER, 0x00); /* disable all intrs */ - info->MCR &= ~UART_MCR_OUT2; - info->MCR |= ALPHA_KLUDGE_MCR; /* Don't ask */ - - /* disable break condition */ - serial_out(info, UART_LCR, serial_inp(info, UART_LCR) & ~UART_LCR_SBC); - - if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) - info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS); - serial_outp(info, UART_MCR, info->MCR); - - /* disable FIFO's */ - serial_outp(info, UART_FCR, (UART_FCR_ENABLE_FIFO | - UART_FCR_CLEAR_RCVR | - UART_FCR_CLEAR_XMIT)); - serial_outp(info, UART_FCR, 0); - - (void)serial_in(info, UART_RX); /* read data port to reset things */ - - if (info->tty) - set_bit(TTY_IO_ERROR, &info->tty->flags); - - info->flags &= ~ASYNC_INITIALIZED; - restore_flags(flags); -} - - -/* - * This routine is called to set the UART divisor registers to match - * the specified baud rate for a serial port. - */ -static void change_speed(struct async_struct *info, - struct termios *old_termios) -{ - int quot = 0, baud_base, baud; - unsigned cflag, cval, fcr = 0; - int bits; - unsigned long flags; - - if (!info->tty || !info->tty->termios) - return; - cflag = info->tty->termios->c_cflag; - if (!CONFIGURED_SERIAL_PORT(info)) - return; - - /* byte size and parity */ - switch (cflag & CSIZE) { - case CS5: cval = 0x00; bits = 7; break; - case CS6: cval = 0x01; bits = 8; break; - case CS7: cval = 0x02; bits = 9; break; - case CS8: cval = 0x03; bits = 10; break; - /* Never happens, but GCC is too dumb to figure it out */ - default: cval = 0x00; bits = 7; break; - } - if (cflag & CSTOPB) { - cval |= 0x04; - bits++; - } - if (cflag & PARENB) { - cval |= UART_LCR_PARITY; - bits++; - } - if (!(cflag & PARODD)) - cval |= UART_LCR_EPAR; -#ifdef CMSPAR - if (cflag & CMSPAR) - cval |= UART_LCR_SPAR; -#endif - - /* Determine divisor based on baud rate */ - baud = tty_get_baud_rate(info->tty); - if (!baud) { - baud = 9600; /* B0 transition handled in rs_set_termios */ - } - baud_base = info->state->baud_base; - //if (baud == 38400 && - if (((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) { - quot = info->state->custom_divisor; - } - else { - if (baud == 134) - /* Special case since 134 is really 134.5 */ - quot = (2*baud_base / 269); - else if (baud) - quot = baud_base / baud; - } - /* If the quotient is zero refuse the change */ - if (!quot && old_termios) { - info->tty->termios->c_cflag &= ~CBAUD; - info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD); - baud = tty_get_baud_rate(info->tty); - if (!baud) - baud = 9600; - if (baud == 38400 && - ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) - quot = info->state->custom_divisor; - else { - if (baud == 134) - /* Special case since 134 is really 134.5 */ - quot = (2*baud_base / 269); - else if (baud) - quot = baud_base / baud; - } - } - /* As a last resort, if the quotient is zero, default to 9600 bps */ - if (!quot) - quot = baud_base / 9600; - - info->quot = quot; - info->timeout = ((info->xmit_fifo_size*HZ*bits*quot) / baud_base); - info->timeout += HZ/50; /* Add .02 seconds of slop */ - - /* Set up FIFO's */ - if (uart_config[info->state->type].flags & UART_USE_FIFO) { - if ((info->state->baud_base / quot) < 2400) - fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIGGER_1; - else - fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIGGER_8; - } - - /* CTS flow control flag and modem status interrupts */ - info->IER &= ~UART_IER_MSI; - if (info->flags & ASYNC_HARDPPS_CD) - info->IER |= UART_IER_MSI; - if (cflag & CRTSCTS) { - info->flags |= ASYNC_CTS_FLOW; - info->IER |= UART_IER_MSI; - } else - info->flags &= ~ASYNC_CTS_FLOW; - if (cflag & CLOCAL) - info->flags &= ~ASYNC_CHECK_CD; - else { - info->flags |= ASYNC_CHECK_CD; - info->IER |= UART_IER_MSI; - } - serial_out(info, UART_IER, info->IER); - - /* - * Set up parity check flag - */ -#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) - - info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR; - if (I_INPCK(info->tty)) - info->read_status_mask |= UART_LSR_FE | UART_LSR_PE; - if (I_BRKINT(info->tty) || I_PARMRK(info->tty)) - info->read_status_mask |= UART_LSR_BI; - - /* - * Characters to ignore - */ - info->ignore_status_mask = 0; - if (I_IGNPAR(info->tty)) - info->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE; - if (I_IGNBRK(info->tty)) { - info->ignore_status_mask |= UART_LSR_BI; - /* - * If we're ignore parity and break indicators, ignore - * overruns too. (For real raw support). - */ - if (I_IGNPAR(info->tty)) - info->ignore_status_mask |= UART_LSR_OE; - } - /* - * !!! ignore all characters if CREAD is not set - */ - if ((cflag & CREAD) == 0) - info->ignore_status_mask |= UART_LSR_DR; - save_flags(flags); cli(); - - serial_outp(info, UART_CLK, quot & 0xffff); - serial_outp(info, UART_LCR, cval); - info->LCR = cval; /* Save LCR */ - restore_flags(flags); -} - -static void rs_put_char(struct tty_struct *tty, unsigned char ch) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_put_char")) - return; - - if (!tty || !info->xmit.buf) - return; - - save_flags(flags); cli(); - if (CIRC_SPACE(info->xmit.head, - info->xmit.tail, - SERIAL_XMIT_SIZE) == 0) { - restore_flags(flags); - return; - } - - info->xmit.buf[info->xmit.head] = ch; - info->xmit.head = (info->xmit.head + 1) & (SERIAL_XMIT_SIZE-1); - restore_flags(flags); -} - -static void rs_flush_chars(struct tty_struct *tty) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_flush_chars")) - return; - - if (info->xmit.head == info->xmit.tail - || tty->stopped - || tty->hw_stopped - || !info->xmit.buf) - return; - - save_flags(flags); cli(); - info->IER |= UART_IER_THRI; - serial_out(info, UART_IER, info->IER); - restore_flags(flags); -} - -static int rs_write(struct tty_struct * tty, int from_user, - const unsigned char *buf, int count) -{ - int c, ret = 0; - struct async_struct *info = (struct async_struct *)tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_write")) - return 0; - - if (!tty || !info->xmit.buf || !tmp_buf) - return 0; - - save_flags(flags); - if (from_user) { - down(&tmp_buf_sem); - while (1) { - int c1; - c = CIRC_SPACE_TO_END(info->xmit.head, - info->xmit.tail, - SERIAL_XMIT_SIZE); - if (count < c) - c = count; - if (c <= 0) - break; - - c -= copy_from_user(tmp_buf, buf, c); - if (!c) { - if (!ret) - ret = -EFAULT; - break; - } - cli(); - c1 = CIRC_SPACE_TO_END(info->xmit.head, - info->xmit.tail, - SERIAL_XMIT_SIZE); - if (c1 < c) - c = c1; - memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c); - info->xmit.head = ((info->xmit.head + c) & - (SERIAL_XMIT_SIZE-1)); - restore_flags(flags); - buf += c; - count -= c; - ret += c; - } - up(&tmp_buf_sem); - } else { - cli(); - while (1) { - c = CIRC_SPACE_TO_END(info->xmit.head, - info->xmit.tail, - SERIAL_XMIT_SIZE); - if (count < c) - c = count; - if (c <= 0) { - break; - } - memcpy(info->xmit.buf + info->xmit.head, buf, c); - info->xmit.head = ((info->xmit.head + c) & - (SERIAL_XMIT_SIZE-1)); - buf += c; - count -= c; - ret += c; - } - restore_flags(flags); - } - if (info->xmit.head != info->xmit.tail - && !tty->stopped - && !tty->hw_stopped - && !(info->IER & UART_IER_THRI)) { - info->IER |= UART_IER_THRI; - serial_out(info, UART_IER, info->IER); - } - return ret; -} - -static int rs_write_room(struct tty_struct *tty) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - - if (serial_paranoia_check(info, tty->name, "rs_write_room")) - return 0; - return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); -} - -static int rs_chars_in_buffer(struct tty_struct *tty) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - - if (serial_paranoia_check(info, tty->name, "rs_chars_in_buffer")) - return 0; - return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); -} - -static void rs_flush_buffer(struct tty_struct *tty) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_flush_buffer")) - return; - save_flags(flags); cli(); - info->xmit.head = info->xmit.tail = 0; - restore_flags(flags); - wake_up_interruptible(&tty->write_wait); -#ifdef SERIAL_HAVE_POLL_WAIT - wake_up_interruptible(&tty->poll_wait); -#endif - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); -} - -/* - * This function is used to send a high-priority XON/XOFF character to - * the device - */ -static void rs_send_xchar(struct tty_struct *tty, char ch) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - - if (serial_paranoia_check(info, tty->name, "rs_send_char")) - return; - - info->x_char = ch; - if (ch) { - /* Make sure transmit interrupts are on */ - info->IER |= UART_IER_THRI; - serial_out(info, UART_IER, info->IER); - } -} - -/* - * ------------------------------------------------------------ - * rs_throttle() - * - * This routine is called by the upper-layer tty layer to signal that - * incoming characters should be throttled. - * ------------------------------------------------------------ - */ -static void rs_throttle(struct tty_struct * tty) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - unsigned long flags; -#ifdef SERIAL_DEBUG_THROTTLE - char buf[64]; - - printk("throttle %s: %d....\n", tty_name(tty, buf), - tty->ldisc.chars_in_buffer(tty)); -#endif - - if (serial_paranoia_check(info, tty->name, "rs_throttle")) - return; - - if (I_IXOFF(tty)) - rs_send_xchar(tty, STOP_CHAR(tty)); - - if (tty->termios->c_cflag & CRTSCTS) - info->MCR &= ~UART_MCR_RTS; - - save_flags(flags); cli(); - serial_out(info, UART_MCR, info->MCR); - restore_flags(flags); -} - -static void rs_unthrottle(struct tty_struct * tty) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - unsigned long flags; -#ifdef SERIAL_DEBUG_THROTTLE - char buf[64]; - - printk("unthrottle %s: %d....\n", tty_name(tty, buf), - tty->ldisc.chars_in_buffer(tty)); -#endif - - if (serial_paranoia_check(info, tty->name, "rs_unthrottle")) - return; - - if (I_IXOFF(tty)) { - if (info->x_char) - info->x_char = 0; - else - rs_send_xchar(tty, START_CHAR(tty)); - } - if (tty->termios->c_cflag & CRTSCTS) - info->MCR |= UART_MCR_RTS; - save_flags(flags); cli(); - serial_out(info, UART_MCR, info->MCR); - restore_flags(flags); -} - -/* - * ------------------------------------------------------------ - * rs_ioctl() and friends - * ------------------------------------------------------------ - */ - -static int get_serial_info(struct async_struct * info, - struct serial_struct * retinfo) -{ - struct serial_struct tmp; - struct serial_state *state = info->state; - - if (!retinfo) - return -EFAULT; - memset(&tmp, 0, sizeof(tmp)); - tmp.type = state->type; - tmp.line = state->line; - tmp.port = state->port; - if (HIGH_BITS_OFFSET) - tmp.port_high = state->port >> HIGH_BITS_OFFSET; - else - tmp.port_high = 0; - tmp.irq = state->irq; - tmp.flags = state->flags; - tmp.xmit_fifo_size = state->xmit_fifo_size; - tmp.baud_base = state->baud_base; - tmp.close_delay = state->close_delay; - tmp.closing_wait = state->closing_wait; - tmp.custom_divisor = state->custom_divisor; - tmp.hub6 = state->hub6; - tmp.io_type = state->io_type; - if (copy_to_user(retinfo,&tmp,sizeof(*retinfo))) - return -EFAULT; - return 0; -} - -static int set_serial_info(struct async_struct * info, - struct serial_struct * new_info) -{ - struct serial_struct new_serial; - struct serial_state old_state, *state; - unsigned int i,change_irq,change_port; - int retval = 0; - unsigned long new_port; - - if (copy_from_user(&new_serial,new_info,sizeof(new_serial))) - return -EFAULT; - state = info->state; - old_state = *state; - - new_port = new_serial.port; - if (HIGH_BITS_OFFSET) - new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET; - - change_irq = new_serial.irq != state->irq; - change_port = (new_port != ((int) state->port)) || - (new_serial.hub6 != state->hub6); - - if (!capable(CAP_SYS_ADMIN)) { - if (change_irq || change_port || - (new_serial.baud_base != state->baud_base) || - (new_serial.type != state->type) || - (new_serial.close_delay != state->close_delay) || - (new_serial.xmit_fifo_size != state->xmit_fifo_size) || - ((new_serial.flags & ~ASYNC_USR_MASK) != - (state->flags & ~ASYNC_USR_MASK))) - return -EPERM; - state->flags = ((state->flags & ~ASYNC_USR_MASK) | - (new_serial.flags & ASYNC_USR_MASK)); - info->flags = ((info->flags & ~ASYNC_USR_MASK) | - (new_serial.flags & ASYNC_USR_MASK)); - state->custom_divisor = new_serial.custom_divisor; - goto check_and_exit; - } - - new_serial.irq = irq_canonicalize(new_serial.irq); - - if ((new_serial.irq >= NR_IRQS) || (new_serial.irq < 0) || - (new_serial.baud_base < 9600)|| (new_serial.type < PORT_UNKNOWN) || - (new_serial.type > PORT_MAX) || (new_serial.type == PORT_CIRRUS) || - (new_serial.type == PORT_STARTECH)) { - return -EINVAL; - } - - if ((new_serial.type != state->type) || - (new_serial.xmit_fifo_size <= 0)) - new_serial.xmit_fifo_size = - uart_config[new_serial.type].dfl_xmit_fifo_size; - - /* Make sure address is not already in use */ - if (new_serial.type) { - for (i = 0 ; i < NR_PORTS; i++) - if ((state != &rs_table[i]) && - (rs_table[i].port == new_port) && - rs_table[i].type) - return -EADDRINUSE; - } - - if ((change_port || change_irq) && (state->count > 1)) - return -EBUSY; - - /* - * OK, past this point, all the error checking has been done. - * At this point, we start making changes..... - */ - - state->baud_base = new_serial.baud_base; - state->flags = ((state->flags & ~ASYNC_FLAGS) | - (new_serial.flags & ASYNC_FLAGS)); - info->flags = ((state->flags & ~ASYNC_INTERNAL_FLAGS) | - (info->flags & ASYNC_INTERNAL_FLAGS)); - state->custom_divisor = new_serial.custom_divisor; - state->close_delay = new_serial.close_delay * HZ/100; - state->closing_wait = new_serial.closing_wait * HZ/100; - info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; - info->xmit_fifo_size = state->xmit_fifo_size = - new_serial.xmit_fifo_size; - - if ((state->type != PORT_UNKNOWN) && state->port) { - release_region(state->port,8); - } - state->type = new_serial.type; - if (change_port || change_irq) { - /* - * We need to shutdown the serial port at the old - * port/irq combination. - */ - shutdown(info); - state->irq = new_serial.irq; - info->port = state->port = new_port; - info->hub6 = state->hub6 = new_serial.hub6; - if (info->hub6) - info->io_type = state->io_type = SERIAL_IO_HUB6; - else if (info->io_type == SERIAL_IO_HUB6) - info->io_type = state->io_type = SERIAL_IO_PORT; - } - if ((state->type != PORT_UNKNOWN) && state->port) { - request_region(state->port,8,"serial(set)"); - } - - -check_and_exit: - if (!state->port || !state->type) - return 0; - if (info->flags & ASYNC_INITIALIZED) { - if (((old_state.flags & ASYNC_SPD_MASK) != - (state->flags & ASYNC_SPD_MASK)) || - (old_state.custom_divisor != state->custom_divisor)) { - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - info->tty->alt_speed = 57600; - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - info->tty->alt_speed = 115200; - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) - info->tty->alt_speed = 230400; - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) - info->tty->alt_speed = 460800; - change_speed(info, 0); - } - } else { - retval = startup(info); - } - return retval; -} - - -/* - * get_lsr_info - get line status register info - * - * Purpose: Let user call ioctl() to get info when the UART physically - * is emptied. On bus types like RS485, the transmitter must - * release the bus after transmitting. This must be done when - * the transmit shift register is empty, not be done when the - * transmit holding register is empty. This functionality - * allows an RS485 driver to be written in user space. - */ -static int get_lsr_info(struct async_struct * info, unsigned int *value) -{ - unsigned char status; - unsigned int result; - unsigned long flags; - - save_flags(flags); cli(); - status = serial_in(info, UART_LSR); - restore_flags(flags); - result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0); - - /* - * If we're about to load something into the transmit - * register, we'll pretend the transmitter isn't empty to - * avoid a race condition (depending on when the transmit - * interrupt happens). - */ - if (info->x_char || - ((CIRC_CNT(info->xmit.head, info->xmit.tail, - SERIAL_XMIT_SIZE) > 0) && - !info->tty->stopped && !info->tty->hw_stopped)) - result &= TIOCSER_TEMT; - - if (copy_to_user(value, &result, sizeof(int))) - return -EFAULT; - return 0; -} - - -static int get_modem_info(struct async_struct * info, unsigned int *value) -{ - unsigned char control, status; - unsigned int result; - unsigned long flags; - - control = info->MCR; - save_flags(flags); cli(); - status = serial_in(info, UART_MSR); - restore_flags(flags); - result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) - | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) -#ifdef TIOCM_OUT1 - | ((control & UART_MCR_OUT1) ? TIOCM_OUT1 : 0) - | ((control & UART_MCR_OUT2) ? TIOCM_OUT2 : 0) -#endif - | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) - | ((status & UART_MSR_RI) ? TIOCM_RNG : 0) - | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) - | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0); - - if (copy_to_user(value, &result, sizeof(int))) - return -EFAULT; - return 0; -} - -static int set_modem_info(struct async_struct * info, unsigned int cmd, - unsigned int *value) -{ - unsigned int arg; - unsigned long flags; - - if (copy_from_user(&arg, value, sizeof(int))) - return -EFAULT; - - switch (cmd) { - case TIOCMBIS: - if (arg & TIOCM_RTS) - info->MCR |= UART_MCR_RTS; - if (arg & TIOCM_DTR) - info->MCR |= UART_MCR_DTR; -#ifdef TIOCM_OUT1 - if (arg & TIOCM_OUT1) - info->MCR |= UART_MCR_OUT1; - if (arg & TIOCM_OUT2) - info->MCR |= UART_MCR_OUT2; -#endif - if (arg & TIOCM_LOOP) - info->MCR |= UART_MCR_LOOP; - break; - case TIOCMBIC: - if (arg & TIOCM_RTS) - info->MCR &= ~UART_MCR_RTS; - if (arg & TIOCM_DTR) - info->MCR &= ~UART_MCR_DTR; -#ifdef TIOCM_OUT1 - if (arg & TIOCM_OUT1) - info->MCR &= ~UART_MCR_OUT1; - if (arg & TIOCM_OUT2) - info->MCR &= ~UART_MCR_OUT2; -#endif - if (arg & TIOCM_LOOP) - info->MCR &= ~UART_MCR_LOOP; - break; - case TIOCMSET: - info->MCR = ((info->MCR & ~(UART_MCR_RTS | -#ifdef TIOCM_OUT1 - UART_MCR_OUT1 | - UART_MCR_OUT2 | -#endif - UART_MCR_LOOP | - UART_MCR_DTR)) - | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0) -#ifdef TIOCM_OUT1 - | ((arg & TIOCM_OUT1) ? UART_MCR_OUT1 : 0) - | ((arg & TIOCM_OUT2) ? UART_MCR_OUT2 : 0) -#endif - | ((arg & TIOCM_LOOP) ? UART_MCR_LOOP : 0) - | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0)); - break; - default: - return -EINVAL; - } - save_flags(flags); cli(); - info->MCR |= ALPHA_KLUDGE_MCR; /* Don't ask */ - serial_out(info, UART_MCR, info->MCR); - restore_flags(flags); - return 0; -} - -static int do_autoconfig(struct async_struct * info) -{ - int retval; - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - if (info->state->count > 1) - return -EBUSY; - - shutdown(info); - - autoconfig(info->state); - retval = startup(info); - if (retval) - return retval; - return 0; -} - -/* - * rs_break() --- routine which turns the break handling on or off - */ -static void rs_break(struct tty_struct *tty, int break_state) -{ - struct async_struct * info = (struct async_struct *)tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_break")) - return; - - if (!CONFIGURED_SERIAL_PORT(info)) - return; - save_flags(flags); cli(); - if (break_state == -1) - info->LCR |= UART_LCR_SBC; - else - info->LCR &= ~UART_LCR_SBC; - serial_out(info, UART_LCR, info->LCR); - restore_flags(flags); -} - - -static int rs_ioctl(struct tty_struct *tty, struct file * file, - unsigned int cmd, unsigned long arg) -{ - struct async_struct * info = (struct async_struct *)tty->driver_data; - struct async_icount cprev, cnow; /* kernel counter temps */ - struct serial_icounter_struct icount; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_ioctl")) - return -ENODEV; - - if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && - (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) && - (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - } - - switch (cmd) { - case TIOCMGET: - return get_modem_info(info, (unsigned int *) arg); - case TIOCMBIS: - case TIOCMBIC: - case TIOCMSET: - return set_modem_info(info, cmd, (unsigned int *) arg); - case TIOCGSERIAL: - return get_serial_info(info, - (struct serial_struct *) arg); - case TIOCSSERIAL: - return set_serial_info(info, - (struct serial_struct *) arg); - case TIOCSERCONFIG: - return do_autoconfig(info); - - case TIOCSERGETLSR: /* Get line status register */ - return get_lsr_info(info, (unsigned int *) arg); - - case TIOCSERGSTRUCT: - if (copy_to_user((struct async_struct *) arg, - info, sizeof(struct async_struct))) - return -EFAULT; - return 0; - - - /* - * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change - * - mask passed in arg for lines of interest - * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) - * Caller should use TIOCGICOUNT to see which one it was - */ - case TIOCMIWAIT: - save_flags(flags); cli(); - /* note the counters on entry */ - cprev = info->state->icount; - restore_flags(flags); - /* Force modem status interrupts on */ - info->IER |= UART_IER_MSI; - serial_out(info, UART_IER, info->IER); - while (1) { - interruptible_sleep_on(&info->delta_msr_wait); - /* see if a signal did it */ - if (signal_pending(current)) - return -ERESTARTSYS; - save_flags(flags); cli(); - cnow = info->state->icount; /* atomic copy */ - restore_flags(flags); - if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && - cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) - return -EIO; /* no change => error */ - if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || - ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || - ((arg & TIOCM_CD) && (cnow.dcd != cprev.dcd)) || - ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) { - return 0; - } - cprev = cnow; - } - /* NOTREACHED */ - - /* - * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) - * Return: write counters to the user passed counter struct - * NB: both 1->0 and 0->1 transitions are counted except for - * RI where only 0->1 is counted. - */ - case TIOCGICOUNT: - save_flags(flags); cli(); - cnow = info->state->icount; - restore_flags(flags); - icount.cts = cnow.cts; - icount.dsr = cnow.dsr; - icount.rng = cnow.rng; - icount.dcd = cnow.dcd; - icount.rx = cnow.rx; - icount.tx = cnow.tx; - icount.frame = cnow.frame; - icount.overrun = cnow.overrun; - icount.parity = cnow.parity; - icount.brk = cnow.brk; - icount.buf_overrun = cnow.buf_overrun; - - if (copy_to_user((void *)arg, &icount, sizeof(icount))) - return -EFAULT; - return 0; - case TIOCSERGWILD: - case TIOCSERSWILD: - /* "setserial -W" is called in Debian boot */ - printk ("TIOCSER?WILD ioctl obsolete, ignored.\n"); - return 0; - - default: - return -ENOIOCTLCMD; - } - return 0; -} - -static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - unsigned long flags; - unsigned int cflag = tty->termios->c_cflag; - - if ( (cflag == old_termios->c_cflag) - && ( RELEVANT_IFLAG(tty->termios->c_iflag) - == RELEVANT_IFLAG(old_termios->c_iflag))) - return; - - change_speed(info, old_termios); - - /* Handle transition to B0 status */ - if ((old_termios->c_cflag & CBAUD) && - !(cflag & CBAUD)) { - info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS); - save_flags(flags); cli(); - serial_out(info, UART_MCR, info->MCR); - restore_flags(flags); - } - - /* Handle transition away from B0 status */ - if (!(old_termios->c_cflag & CBAUD) && - (cflag & CBAUD)) { - info->MCR |= UART_MCR_DTR; - if (!(tty->termios->c_cflag & CRTSCTS) || - !test_bit(TTY_THROTTLED, &tty->flags)) { - info->MCR |= UART_MCR_RTS; - } - save_flags(flags); cli(); - serial_out(info, UART_MCR, info->MCR); - restore_flags(flags); - } - - /* Handle turning off CRTSCTS */ - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios->c_cflag & CRTSCTS)) { - tty->hw_stopped = 0; - rs_start(tty); - } -} - -/* - * ------------------------------------------------------------ - * rs_close() - * - * This routine is called when the serial port gets closed. First, we - * wait for the last remaining data to be sent. Then, we unlink its - * async structure from the interrupt chain if necessary, and we free - * that IRQ if nothing is left in the chain. - * ------------------------------------------------------------ - */ -static void rs_close(struct tty_struct *tty, struct file * filp) -{ - struct async_struct * info = (struct async_struct *)tty->driver_data; - struct serial_state *state; - unsigned long flags; - - if (!info || serial_paranoia_check(info, tty->name, "rs_close")) - return; - - state = info->state; - - save_flags(flags); cli(); - - if (tty_hung_up_p(filp)) { - DBG_CNT("before DEC-hung"); - MOD_DEC_USE_COUNT; - restore_flags(flags); - return; - } - -#ifdef SERIAL_DEBUG_OPEN - printk("rs_close ttys%d, count = %d\n", info->line, state->count); -#endif - if ((tty->count == 1) && (state->count != 1)) { - /* - * Uh, oh. tty->count is 1, which means that the tty - * structure will be freed. state->count should always - * be one in these conditions. If it's greater than - * one, we've got real problems, since it means the - * serial port won't be shutdown. - */ - printk("rs_close: bad serial port count; tty->count is 1, " - "state->count is %d\n", state->count); - state->count = 1; - } - if (--state->count < 0) { - printk("rs_close: bad serial port count for ttys%d: %d\n", - info->line, state->count); - state->count = 0; - } - if (state->count) { - DBG_CNT("before DEC-2"); - MOD_DEC_USE_COUNT; - restore_flags(flags); - return; - } - info->flags |= ASYNC_CLOSING; - restore_flags(flags); - /* - * Now we wait for the transmit buffer to clear; and we notify - * the line discipline to only process XON/XOFF characters. - */ - tty->closing = 1; - if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE) - tty_wait_until_sent(tty, info->closing_wait); - /* - * At this point we stop accepting input. To do this, we - * disable the receive line status interrupts, and tell the - * interrupt driver to stop checking the data ready bit in the - * line status register. - */ - info->IER &= ~UART_IER_RLSI; - info->read_status_mask &= ~UART_LSR_DR; - if (info->flags & ASYNC_INITIALIZED) { - serial_out(info, UART_IER, info->IER); - /* - * Before we drop DTR, make sure the UART transmitter - * has completely drained; this is especially - * important if there is a transmit FIFO! - */ - rs_wait_until_sent(tty, info->timeout); - } - shutdown(info); - if (tty->driver->flush_buffer) - tty->driver->flush_buffer(tty); - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); - tty->closing = 0; - info->event = 0; - info->tty = 0; - if (info->blocked_open) { - if (info->close_delay) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(info->close_delay); - } - wake_up_interruptible(&info->open_wait); - } - info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); - wake_up_interruptible(&info->close_wait); - MOD_DEC_USE_COUNT; -} - -/* - * rs_wait_until_sent() --- wait until the transmitter is empty - */ -static void rs_wait_until_sent(struct tty_struct *tty, int timeout) -{ - struct async_struct * info = (struct async_struct *)tty->driver_data; - unsigned long orig_jiffies, char_time; - int lsr; - - if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent")) - return; - - if (info->state->type == PORT_UNKNOWN) - return; - - if (info->xmit_fifo_size == 0) - return; /* Just in case.... */ - - orig_jiffies = jiffies; - /* - * Set the check interval to be 1/5 of the estimated time to - * send a single character, and make it at least 1. The check - * interval should also be less than the timeout. - * - * Note: we have to use pretty tight timings here to satisfy - * the NIST-PCTS. - */ - char_time = (info->timeout - HZ/50) / info->xmit_fifo_size; - char_time = char_time / 5; - if (char_time == 0) - char_time = 1; - if (timeout && timeout < char_time) - char_time = timeout; - /* - * If the transmitter hasn't cleared in twice the approximate - * amount of time to send the entire FIFO, it probably won't - * ever clear. This assumes the UART isn't doing flow - * control, which is currently the case. Hence, if it ever - * takes longer than info->timeout, this is probably due to a - * UART bug of some kind. So, we clamp the timeout parameter at - * 2*info->timeout. - */ - if (!timeout || timeout > 2*info->timeout) - timeout = 2*info->timeout; -#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT - printk("In rs_wait_until_sent(%d) check=%lu...", timeout, char_time); - printk("jiff=%lu...", jiffies); -#endif - while (!((lsr = serial_inp(info, UART_LSR)) & UART_LSR_TEMT)) { -#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT - printk("lsr = %d (jiff=%lu)...", lsr, jiffies); -#endif - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(char_time); - if (signal_pending(current)) - break; - if (timeout && time_after(jiffies, orig_jiffies + timeout)) - break; - } - set_current_state(TASK_RUNNING); -#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT - printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); -#endif -} - -/* - * rs_hangup() --- called by tty_hangup() when a hangup is signaled. - */ -static void rs_hangup(struct tty_struct *tty) -{ - struct async_struct * info = (struct async_struct *)tty->driver_data; - struct serial_state *state = info->state; - - if (serial_paranoia_check(info, tty->name, "rs_hangup")) - return; - - state = info->state; - - rs_flush_buffer(tty); - if (info->flags & ASYNC_CLOSING) - return; - shutdown(info); - info->event = 0; - state->count = 0; - info->flags &= ~ASYNC_NORMAL_ACTIVE; - info->tty = 0; - wake_up_interruptible(&info->open_wait); -} - -/* - * ------------------------------------------------------------ - * rs_open() and friends - * ------------------------------------------------------------ - */ -static int block_til_ready(struct tty_struct *tty, struct file * filp, - struct async_struct *info) -{ - DECLARE_WAITQUEUE(wait, current); - struct serial_state *state = info->state; - int retval; - int do_clocal = 0, extra_count = 0; - unsigned long flags; - - /* - * If the device is in the middle of being closed, then block - * until it's done, and then try again. - */ - if (tty_hung_up_p(filp) || - (info->flags & ASYNC_CLOSING)) { - if (info->flags & ASYNC_CLOSING) - interruptible_sleep_on(&info->close_wait); -#ifdef SERIAL_DO_RESTART - return ((info->flags & ASYNC_HUP_NOTIFY) ? - -EAGAIN : -ERESTARTSYS); -#else - return -EAGAIN; -#endif - } - - /* - * If non-blocking mode is set, or the port is not enabled, - * then make the check up front and then exit. - */ - if ((filp->f_flags & O_NONBLOCK) || - (tty->flags & (1 << TTY_IO_ERROR))) { - info->flags |= ASYNC_NORMAL_ACTIVE; - return 0; - } - - if (tty->termios->c_cflag & CLOCAL) - do_clocal = 1; - - /* - * Block waiting for the carrier detect and the line to become - * free (i.e., not in use by the callout). While we are in - * this loop, state->count is dropped by one, so that - * rs_close() knows when to free things. We restore it upon - * exit, either normal or abnormal. - */ - retval = 0; - add_wait_queue(&info->open_wait, &wait); -#ifdef SERIAL_DEBUG_OPEN - printk("block_til_ready before block: ttys%d, count = %d\n", - state->line, state->count); -#endif - save_flags(flags); cli(); - if (!tty_hung_up_p(filp)) { - extra_count = 1; - state->count--; - } - restore_flags(flags); - info->blocked_open++; - while (1) { - save_flags(flags); cli(); - if (tty->termios->c_cflag & CBAUD) - serial_out(info, UART_MCR, - serial_inp(info, UART_MCR) | - (UART_MCR_DTR | UART_MCR_RTS)); - restore_flags(flags); - set_current_state(TASK_INTERRUPTIBLE); - if (tty_hung_up_p(filp) || - !(info->flags & ASYNC_INITIALIZED)) { -#ifdef SERIAL_DO_RESTART - if (info->flags & ASYNC_HUP_NOTIFY) - retval = -EAGAIN; - else - retval = -ERESTARTSYS; -#else - retval = -EAGAIN; -#endif - break; - } - if (!(info->flags & ASYNC_CLOSING) && - (do_clocal || (serial_in(info, UART_MSR) & - UART_MSR_DCD))) - break; - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } -#ifdef SERIAL_DEBUG_OPEN - printk("block_til_ready blocking: ttys%d, count = %d\n", - info->line, state->count); -#endif - schedule(); - } - set_current_state(TASK_RUNNING); - remove_wait_queue(&info->open_wait, &wait); - if (extra_count) - state->count++; - info->blocked_open--; -#ifdef SERIAL_DEBUG_OPEN - printk("block_til_ready after blocking: ttys%d, count = %d\n", - info->line, state->count); -#endif - if (retval) - return retval; - info->flags |= ASYNC_NORMAL_ACTIVE; - return 0; -} - -static int get_async_struct(int line, struct async_struct **ret_info) -{ - struct async_struct *info; - struct serial_state *sstate; - - sstate = rs_table + line; - sstate->count++; - if (sstate->info) { - *ret_info = sstate->info; - return 0; - } - info = kmalloc(sizeof(struct async_struct), GFP_KERNEL); - if (!info) { - sstate->count--; - return -ENOMEM; - } - memset(info, 0, sizeof(struct async_struct)); - init_waitqueue_head(&info->open_wait); - init_waitqueue_head(&info->close_wait); - init_waitqueue_head(&info->delta_msr_wait); - info->magic = SERIAL_MAGIC; - info->port = sstate->port; - info->flags = sstate->flags; - info->io_type = sstate->io_type; - info->iomem_base = sstate->iomem_base; - info->iomem_reg_shift = sstate->iomem_reg_shift; - info->xmit_fifo_size = sstate->xmit_fifo_size; - info->line = line; - info->tqueue.routine = do_softint; - info->tqueue.data = info; - info->state = sstate; - if (sstate->info) { - kfree(info); - *ret_info = sstate->info; - return 0; - } - *ret_info = sstate->info = info; - return 0; -} - -/* - * This routine is called whenever a serial port is opened. It - * enables interrupts for a serial port, linking in its async structure into - * the IRQ chain. It also performs the serial-specific - * initialization for the tty structure. - */ -static int rs_open(struct tty_struct *tty, struct file * filp) -{ - struct async_struct *info; - int retval, line; - unsigned long page; - - MOD_INC_USE_COUNT; - line = tty->index; - if ((line < 0) || (line >= NR_PORTS)) { - MOD_DEC_USE_COUNT; - return -ENODEV; - } - retval = get_async_struct(line, &info); - if (retval) { - MOD_DEC_USE_COUNT; - return retval; - } - tty->driver_data = info; - info->tty = tty; - if (serial_paranoia_check(info, tty->name, "rs_open")) { - MOD_DEC_USE_COUNT; - return -ENODEV; - } - -#ifdef SERIAL_DEBUG_OPEN - printk("rs_open %s, count = %d\n", tty->name, info->state->count); -#endif - info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; - - if (!tmp_buf) { - page = get_zeroed_page(GFP_KERNEL); - if (!page) { - MOD_DEC_USE_COUNT; - return -ENOMEM; - } - if (tmp_buf) - free_page(page); - else - tmp_buf = (unsigned char *) page; - } - - /* - * If the port is the middle of closing, bail out now - */ - if (tty_hung_up_p(filp) || - (info->flags & ASYNC_CLOSING)) { - if (info->flags & ASYNC_CLOSING) - interruptible_sleep_on(&info->close_wait); - MOD_DEC_USE_COUNT; -#ifdef SERIAL_DO_RESTART - return ((info->flags & ASYNC_HUP_NOTIFY) ? - -EAGAIN : -ERESTARTSYS); -#else - return -EAGAIN; -#endif - } - - /* - * Start up serial port - */ - retval = startup(info); - if (retval) { - MOD_DEC_USE_COUNT; - return retval; - } - - retval = block_til_ready(tty, filp, info); - if (retval) { -#ifdef SERIAL_DEBUG_OPEN - printk("rs_open returning after block_til_ready with %d\n", - retval); -#endif - MOD_DEC_USE_COUNT; - return retval; - } - -#ifdef CONFIG_AU1000_SERIAL_CONSOLE - if (sercons.cflag && sercons.index == line) { - tty->termios->c_cflag = sercons.cflag; - sercons.cflag = 0; - change_speed(info, 0); - } -#endif - -#ifdef SERIAL_DEBUG_OPEN - printk("rs_open %s successful...", tty->name); -#endif - return 0; -} - -/* - * /proc fs routines.... - */ - -static inline int line_info(char *buf, struct serial_state *state) -{ - struct async_struct *info = state->info, scr_info; - char stat_buf[30], control, status; - int ret; - unsigned long flags; - - ret = sprintf(buf, "%d: uart:%s port:%lX irq:%d", - state->line, uart_config[state->type].name, - state->port, state->irq); - - if (!state->port || (state->type == PORT_UNKNOWN)) { - ret += sprintf(buf+ret, "\n"); - return ret; - } - - /* - * Figure out the current RS-232 lines - */ - if (!info) { - info = &scr_info; /* This is just for serial_{in,out} */ - - info->magic = SERIAL_MAGIC; - info->port = state->port; - info->flags = state->flags; - info->quot = 0; - info->tty = 0; - } - save_flags(flags); cli(); - status = serial_in(info, UART_MSR); - control = info != &scr_info ? info->MCR : serial_in(info, UART_MCR); - restore_flags(flags); - - stat_buf[0] = 0; - stat_buf[1] = 0; - if (control & UART_MCR_RTS) - strcat(stat_buf, "|RTS"); - if (status & UART_MSR_CTS) - strcat(stat_buf, "|CTS"); - if (control & UART_MCR_DTR) - strcat(stat_buf, "|DTR"); - if (status & UART_MSR_DSR) - strcat(stat_buf, "|DSR"); - if (status & UART_MSR_DCD) - strcat(stat_buf, "|CD"); - if (status & UART_MSR_RI) - strcat(stat_buf, "|RI"); - - if (info->quot) { - ret += sprintf(buf+ret, " baud:%d", - state->baud_base / info->quot); - } - - ret += sprintf(buf+ret, " tx:%d rx:%d", - state->icount.tx, state->icount.rx); - - if (state->icount.frame) - ret += sprintf(buf+ret, " fe:%d", state->icount.frame); - - if (state->icount.parity) - ret += sprintf(buf+ret, " pe:%d", state->icount.parity); - - if (state->icount.brk) - ret += sprintf(buf+ret, " brk:%d", state->icount.brk); - - if (state->icount.overrun) - ret += sprintf(buf+ret, " oe:%d", state->icount.overrun); - - /* - * Last thing is the RS-232 status lines - */ - ret += sprintf(buf+ret, " %s\n", stat_buf+1); - return ret; -} - -int rs_read_proc(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - int i, len = 0, l; - off_t begin = 0; - - len += sprintf(page, "serinfo:1.0 driver:%s%s revision:%s\n", - serial_version, LOCAL_VERSTRING, serial_revdate); - for (i = 0; i < NR_PORTS && len < 4000; i++) { - l = line_info(page + len, &rs_table[i]); - len += l; - if (len+begin > off+count) - goto done; - if (len+begin < off) { - begin += len; - len = 0; - } - } - *eof = 1; -done: - if (off >= len+begin) - return 0; - *start = page + (off-begin); - return ((count < begin+len-off) ? count : begin+len-off); -} - -/* - * --------------------------------------------------------------------- - * rs_init() and friends - * - * rs_init() is called at boot-time to initialize the serial driver. - * --------------------------------------------------------------------- - */ - -/* - * This routine prints out the appropriate serial driver version - * number, and identifies which options were configured into this - * driver. - */ -static char serial_options[] __initdata = - " no serial options enabled\n"; -#undef SERIAL_OPT - -static _INLINE_ void show_serial_version(void) -{ - printk(KERN_INFO "%s version %s%s (%s) with%s", serial_name, - serial_version, LOCAL_VERSTRING, serial_revdate, - serial_options); -} - - -/* - * This routine is called by rs_init() to initialize a specific serial - * port. It determines what type of UART chip this serial port is - * using: 8250, 16450, 16550, 16550A. The important question is - * whether or not this UART is a 16550A or not, since this will - * determine whether or not we can use its FIFO features or not. - */ -static void autoconfig(struct serial_state * state) -{ - struct async_struct *info, scr_info; - unsigned long flags; - - -#ifdef SERIAL_DEBUG_AUTOCONF - printk("Testing ttyS%d (0x%04lx, 0x%04x)...\n", state->line, - state->port, (unsigned) state->iomem_base); -#endif - - if (!CONFIGURED_SERIAL_PORT(state)) - return; - - if (inl(UART_MOD_CNTRL + state->port) != 0x3) { - outl(3, UART_MOD_CNTRL + state->port); - } - - state->type = PORT_16550; - info = &scr_info; /* This is just for serial_{in,out} */ - - info->magic = SERIAL_MAGIC; - info->state = state; - info->port = state->port; - info->flags = state->flags; - info->io_type = state->io_type; - info->iomem_base = state->iomem_base; - info->iomem_reg_shift = state->iomem_reg_shift; - - - save_flags(flags); cli(); - state->xmit_fifo_size = uart_config[state->type].dfl_xmit_fifo_size; - - if (info->port) { - request_region(info->port,8,"serial(auto)"); - } - - /* - * Reset the UART. - */ - serial_outp(info, UART_FCR, (UART_FCR_ENABLE_FIFO | - UART_FCR_CLEAR_RCVR | - UART_FCR_CLEAR_XMIT)); - serial_outp(info, UART_FCR, 0); - (void)serial_in(info, UART_RX); - serial_outp(info, UART_IER, 0); - - restore_flags(flags); -} - -int register_serial(struct serial_struct *req); -void unregister_serial(int line); - -EXPORT_SYMBOL(register_serial); -EXPORT_SYMBOL(unregister_serial); - -static struct tty_operations serial_ops = { - .open = rs_open, - .close = rs_close, - .write = rs_write, - .put_char = rs_put_char, - .flush_chars = rs_flush_chars, - .write_room = rs_write_room, - .chars_in_buffer = rs_chars_in_buffer, - .flush_buffer = rs_flush_buffer, - .ioctl = rs_ioctl, - .throttle = rs_throttle, - .unthrottle = rs_unthrottle, - .set_termios = rs_set_termios, - .stop = rs_stop, - .start = rs_start, - .hangup = rs_hangup, - .break_ctl = rs_break, - .send_xchar = rs_send_xchar, - .wait_until_sent = rs_wait_until_sent, - .read_proc = rs_read_proc, -}; - - -/* - * The serial driver boot-time initialization code! - */ -static int __init rs_init(void) -{ - int i; - struct serial_state * state; - - serial_driver = alloc_tty_driver(NR_PORTS); - if (!serial_driver) - return -ENOMEM; - - init_bh(SERIAL_BH, do_serial_bh); - init_timer(&serial_timer); - serial_timer.function = rs_timer; - mod_timer(&serial_timer, jiffies + RS_STROBE_TIME); - - for (i = 0; i < NR_IRQS; i++) { - IRQ_ports[i] = 0; - IRQ_timeout[i] = 0; - } -#ifdef CONFIG_AU1000_SERIAL_CONSOLE - /* - * The interrupt of the serial console port - * can't be shared. - */ - if (sercons.flags & CON_CONSDEV) { - for(i = 0; i < NR_PORTS; i++) - if (i != sercons.index && - rs_table[i].irq == rs_table[sercons.index].irq) - rs_table[i].irq = 0; - } -#endif - show_serial_version(); - - /* Initialize the tty_driver structure */ - - serial_driver->driver_name = "serial"; - serial_driver->devfs_name = "tts/"; - serial_driver->name = "ttyS"; - serial_driver->major = TTY_MAJOR; - serial_driver->minor_start = 64 + SERIAL_DEV_OFFSET; - serial_driver->type = TTY_DRIVER_TYPE_SERIAL; - serial_driver->subtype = SERIAL_TYPE_NORMAL; - serial_driver->init_termios = tty_std_termios; - serial_driver->init_termios.c_cflag = - B9600 | CS8 | CREAD | HUPCL | CLOCAL; - serial_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS; - tty_set_operations(serial_driver, &serial_ops); - - if (tty_register_driver(serial_driver)) - panic("Couldn't register serial driver\n"); - - for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) { - state->baud_base = get_au1000_uart_baud(); - state->magic = SSTATE_MAGIC; - state->line = i; - state->type = PORT_UNKNOWN; - state->custom_divisor = 0; - state->close_delay = 5*HZ/10; - state->closing_wait = 30*HZ; - state->icount.cts = state->icount.dsr = - state->icount.rng = state->icount.dcd = 0; - state->icount.rx = state->icount.tx = 0; - state->icount.frame = state->icount.parity = 0; - state->icount.overrun = state->icount.brk = 0; - state->irq = irq_canonicalize(state->irq); - if (state->hub6) - state->io_type = SERIAL_IO_HUB6; - if (state->port && check_region(state->port,8)) { - continue; - } - - if (state->flags & ASYNC_BOOT_AUTOCONF) { - autoconfig(state); - } - } - for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) { - if (state->type == PORT_UNKNOWN) { - continue; - } - printk(KERN_INFO "ttyS%02d%s at 0x%04lx (irq = %d) is a %s\n", - state->line + SERIAL_DEV_OFFSET, - (state->flags & ASYNC_FOURPORT) ? " FourPort" : "", - state->port, state->irq, - uart_config[state->type].name); - tty_register_device(serial_driver, state->line, NULL); - } - return 0; -} - -/* - * register_serial and unregister_serial allows for 16x50 serial ports to be - * configured at run-time, to support PCMCIA modems. - */ - -/** - * register_serial - configure a 16x50 serial port at runtime - * @req: request structure - * - * Configure the serial port specified by the request. If the - * port exists and is in use an error is returned. If the port - * is not currently in the table it is added. - * - * The port is then probed and if necessary the IRQ is autodetected - * If this fails an error is returned. - * - * On success the port is ready to use and the line number is returned. - */ - -int register_serial(struct serial_struct *req) -{ - int i; - unsigned long flags; - struct serial_state *state; - struct async_struct *info; - unsigned long port; - - port = req->port; - if (HIGH_BITS_OFFSET) - port += (unsigned long) req->port_high << HIGH_BITS_OFFSET; - - save_flags(flags); cli(); - for (i = 0; i < NR_PORTS; i++) { - if ((rs_table[i].port == port) && - (rs_table[i].iomem_base == req->iomem_base)) - break; - } - if (i == NR_PORTS) { - for (i = 0; i < NR_PORTS; i++) - if ((rs_table[i].type == PORT_UNKNOWN) && - (rs_table[i].count == 0)) - break; - } - if (i == NR_PORTS) { - restore_flags(flags); - return -1; - } - state = &rs_table[i]; - if (rs_table[i].count) { - restore_flags(flags); - printk("Couldn't configure serial #%d (port=%ld,irq=%d): " - "device already open\n", i, port, req->irq); - return -1; - } - state->irq = req->irq; - state->port = port; - state->flags = req->flags; - state->io_type = req->io_type; - state->iomem_base = req->iomem_base; - state->iomem_reg_shift = req->iomem_reg_shift; - if (req->baud_base) - state->baud_base = req->baud_base; - if ((info = state->info) != NULL) { - info->port = port; - info->flags = req->flags; - info->io_type = req->io_type; - info->iomem_base = req->iomem_base; - info->iomem_reg_shift = req->iomem_reg_shift; - } - autoconfig(state); - if (state->type == PORT_UNKNOWN) { - restore_flags(flags); - printk("register_serial(): autoconfig failed\n"); - return -1; - } - restore_flags(flags); - - printk(KERN_INFO "ttyS%02d at %s 0x%04lx (irq = %d) is a %s\n", - state->line + SERIAL_DEV_OFFSET, - state->iomem_base ? "iomem" : "port", - state->iomem_base ? (unsigned long)state->iomem_base : - state->port, state->irq, uart_config[state->type].name); - tty_register_device(serial_driver, state->line, NULL); - return state->line + SERIAL_DEV_OFFSET; -} - -/** - * unregister_serial - deconfigure a 16x50 serial port - * @line: line to deconfigure - * - * The port specified is deconfigured and its resources are freed. Any - * user of the port is disconnected as if carrier was dropped. Line is - * the port number returned by register_serial(). - */ - -void unregister_serial(int line) -{ - unsigned long flags; - struct serial_state *state = &rs_table[line]; - - save_flags(flags); cli(); - if (state->info && state->info->tty) - tty_hangup(state->info->tty); - state->type = PORT_UNKNOWN; - printk(KERN_INFO "tty%02d unloaded\n", state->line); - /* These will be hidden, because they are devices that will no longer - * be available to the system. (ie, PCMCIA modems, once ejected) - */ - tty_unregister_device(serial_driver, state->line); - restore_flags(flags); -} - -static void __exit rs_fini(void) -{ - unsigned long flags; - int e1, e2; - int i; - struct async_struct *info; - - /* printk("Unloading %s: version %s\n", serial_name, serial_version); */ - del_timer_sync(&serial_timer); - save_flags(flags); cli(); - remove_bh(SERIAL_BH); - if ((e1 = tty_unregister_driver(serial_driver))) - printk("serial: failed to unregister serial driver (%d)\n", - e1); - restore_flags(flags); - put_tty_driver(serial_driver); - - for (i = 0; i < NR_PORTS; i++) { - if ((info = rs_table[i].info)) { - rs_table[i].info = NULL; - kfree(info); - } - if ((rs_table[i].type != PORT_UNKNOWN) && rs_table[i].port) { - release_region(rs_table[i].port, 8); - } - } - if (tmp_buf) { - unsigned long pg = (unsigned long) tmp_buf; - tmp_buf = NULL; - free_page(pg); - } -} - -module_init(rs_init); -module_exit(rs_fini); -MODULE_DESCRIPTION("Au1000 serial driver"); - - -/* - * ------------------------------------------------------------ - * Serial console driver - * ------------------------------------------------------------ - */ -#ifdef CONFIG_AU1000_SERIAL_CONSOLE - -#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) - -static struct async_struct async_sercons; - -/* - * Wait for transmitter & holding register to empty - */ -static inline void wait_for_xmitr(struct async_struct *info) -{ - unsigned int status, tmout = 0xffffff; - - do { - status = serial_in(info, UART_LSR); - - if (status & UART_LSR_BI) - lsr_break_flag = UART_LSR_BI; - - if (--tmout == 0) - break; - } while((status & BOTH_EMPTY) != BOTH_EMPTY); -} - - -/* - * Print a string to the serial port trying not to disturb - * any possible real use of the port... - * - * The console_lock must be held when we get here. - */ -static void serial_console_write(struct console *co, const char *s, - unsigned count) -{ - static struct async_struct *info = &async_sercons; - int ier; - unsigned i; - - /* - * First save the IER then disable the interrupts - */ - ier = serial_in(info, UART_IER); - serial_out(info, UART_IER, 0x00); - - /* - * Now, do each character - */ - for (i = 0; i < count; i++, s++) { - wait_for_xmitr(info); - - /* - * Send the character out. - * If a LF, also do CR... - */ - serial_out(info, UART_TX, *s); - if (*s == 10) { - wait_for_xmitr(info); - serial_out(info, UART_TX, 13); - } - } - - /* - * Finally, Wait for transmitter & holding register to empty - * and restore the IER - */ - wait_for_xmitr(info); - serial_out(info, UART_IER, ier); -} - -static struct tty_driver *serial_console_device(struct console *c, int *index) -{ - *index = c->index - SERIAL_DEV_OFFSET; - return serial_driver; -} - -/* - * Setup initial baud/bits/parity. We do two things here: - * - construct a cflag setting for the first rs_open() - * - initialize the serial port - * Return non-zero if we didn't find a serial port. - */ -static int __init serial_console_setup(struct console *co, char *options) -{ - static struct async_struct *info; - struct serial_state *state; - unsigned cval; - int baud = 9600; - int bits = 8; - int parity = 'n'; - int cflag = CREAD | HUPCL | CLOCAL; - int quot = 0; - char *s; - - if (options) { - baud = simple_strtoul(options, NULL, 10); - s = options; - while(*s >= '0' && *s <= '9') - s++; - if (*s) parity = *s++; - if (*s) bits = *s - '0'; - } - - /* - * Now construct a cflag setting. - */ - switch(baud) { - case 1200: - cflag |= B1200; - break; - case 2400: - cflag |= B2400; - break; - case 4800: - cflag |= B4800; - break; - case 19200: - cflag |= B19200; - break; - case 38400: - cflag |= B38400; - break; - case 57600: - cflag |= B57600; - break; - case 115200: - cflag |= B115200; - break; - case 9600: - default: - cflag |= B9600; - break; - } - switch(bits) { - case 7: - cflag |= CS7; - break; - default: - case 8: - cflag |= CS8; - break; - } - switch(parity) { - case 'o': case 'O': - cflag |= PARODD; - break; - case 'e': case 'E': - cflag |= PARENB; - break; - } - co->cflag = cflag; - - /* - * Divisor, bytesize and parity - */ - state = rs_table + co->index; - info = &async_sercons; - info->magic = SERIAL_MAGIC; - info->state = state; - info->port = state->port; - info->flags = state->flags; - info->io_type = state->io_type; - info->iomem_base = state->iomem_base; - info->iomem_reg_shift = state->iomem_reg_shift; - state->baud_base = get_au1000_uart_baud(); - quot = state->baud_base / baud; - - cval = cflag & (CSIZE | CSTOPB); - cval >>= 4; - if (cflag & PARENB) - cval |= UART_LCR_PARITY; - if (!(cflag & PARODD)) - cval |= UART_LCR_EPAR; - - /* - * Disable UART interrupts, set DTR and RTS high - * and set speed. - */ - serial_out(info, UART_CLK, quot & 0xffff); - serial_out(info, UART_IER, 0); - serial_out(info, UART_MCR, UART_MCR_DTR | UART_MCR_RTS); - - /* - * If we read 0xff from the LSR, there is no UART here. - */ - if (serial_in(info, UART_LSR) == 0xff) - return -1; - - return 0; -} - -static struct console sercons = { - .name = "ttyS", - .write = serial_console_write, - .device = serial_console_device, - .setup = serial_console_setup, - .flags = CON_PRINTBUFFER, - .index = -1, -}; - -/* - * Register console. - */ -static void __init au1000_serial_console_init(void) -{ - register_console(&sercons); -} -console_initcall(au1000_serial_console_init); -#endif - -/* - Local variables: - compile-command: "gcc -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strict-aliasing -pipe -fno-strength-reduce -march=i586 -DMODULE -DMODVERSIONS -include ../../include/linux/modversions.h -DEXPORT_SYMTAB -c serial.c" - End: -*/ diff -Nru a/arch/mips/au1000/common/time.c b/arch/mips/au1000/common/time.c --- a/arch/mips/au1000/common/time.c Tue Jul 1 18:44:34 2003 +++ b/arch/mips/au1000/common/time.c Tue Jul 1 18:44:34 2003 @@ -5,8 +5,6 @@ * Carsten Langgaard, carstenl@mips.com * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -20,10 +18,9 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. * - * ######################################################################## - * * Setting up the clock on the MIPS boards. */ +#include #include #include #include @@ -33,27 +30,39 @@ #include #include +#include +#include #include #include #include #include +extern void startup_match20_interrupt(void); +extern void do_softirq(void); extern volatile unsigned long wall_jiffies; unsigned long missed_heart_beats = 0; -unsigned long uart_baud_base; static unsigned long r4k_offset; /* Amount to increment compare reg each time */ static unsigned long r4k_cur; /* What counter should be at next timer irq */ +extern unsigned int mips_counter_frequency; + +/* Cycle counter value at the previous timer interrupt.. */ +static unsigned int timerhi = 0, timerlo = 0; -#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5) +#ifdef CONFIG_PM +#define MATCH20_INC 328 +extern void startup_match20_interrupt(void); +static unsigned long last_pc0, last_match20; +#endif + +static spinlock_t time_lock = SPIN_LOCK_UNLOCKED; static inline void ack_r4ktimer(unsigned long newval) { - write_32bit_cp0_register(CP0_COMPARE, newval); + write_c0_compare(newval); } - /* * There are a lot of conceptually broken versions of the MIPS timer interrupt * handler floating around. This one is rather different, but the algorithm @@ -62,108 +71,201 @@ unsigned long wtimer; void mips_timer_interrupt(struct pt_regs *regs) { - int irq = 7; + int irq = 63; + unsigned long count; + int cpu = smp_processor_id(); + + irq_enter(); + kstat_cpu(cpu).irqs[irq]++; + +#ifdef CONFIG_PM + printk(KERN_ERR "Unexpected CP0 interrupt\n"); + regs->cp0_status &= ~IE_IRQ5; /* disable CP0 interrupt */ + return; +#endif if (r4k_offset == 0) goto null; do { + count = read_c0_count(); + timerhi += (count < timerlo); /* Wrap around */ + timerlo = count; + kstat_cpu(0).irqs[irq]++; do_timer(regs); r4k_cur += r4k_offset; ack_r4ktimer(r4k_cur); - } while (((unsigned long)read_32bit_cp0_register(CP0_COUNT) + } while (((unsigned long)read_c0_count() - r4k_cur) < 0x7fffffff); + irq_exit(); + + if (softirq_pending(cpu)) + do_softirq(); return; null: ack_r4ktimer(0); } -/* +#ifdef CONFIG_PM +void counter0_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned long pc0; + int time_elapsed; + static int jiffie_drift = 0; + + kstat_cpu(0).irqs[irq]++; + if (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20) { + /* should never happen! */ + printk(KERN_WARNING "counter 0 w status eror\n"); + return; + } + + pc0 = au_readl(SYS_TOYREAD); + if (pc0 < last_match20) { + /* counter overflowed */ + time_elapsed = (0xffffffff - last_match20) + pc0; + } + else { + time_elapsed = pc0 - last_match20; + } + + while (time_elapsed > 0) { + do_timer(regs); + time_elapsed -= MATCH20_INC; + last_match20 += MATCH20_INC; + jiffie_drift++; + } + + last_pc0 = pc0; + au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2); + au_sync(); + + /* our counter ticks at 10.009765625 ms/tick, we we're running + * almost 10uS too slow per tick. + */ + + if (jiffie_drift >= 999) { + jiffie_drift -= 999; + do_timer(regs); /* increment jiffies by one */ + } +} +#endif + +/* * Figure out the r4k offset, the amount to increment the compare - * register for each time tick. + * register for each time tick. * Use the Programmable Counter 1 to do this. */ unsigned long cal_r4koff(void) { unsigned long count; - unsigned long cpu_pll; unsigned long cpu_speed; unsigned long start, end; unsigned long counter; - int i; int trim_divide = 16; + unsigned long flags; - counter = inl(PC_COUNTER_CNTRL); - outl(counter | PC_CNTRL_EN1, PC_COUNTER_CNTRL); + spin_lock_irqsave(&time_lock, flags); - while (inl(PC_COUNTER_CNTRL) & PC_CNTRL_T1S); - outl(trim_divide-1, PC1_TRIM); /* RTC now ticks at 32.768/16 kHz */ - while (inl(PC_COUNTER_CNTRL) & PC_CNTRL_T1S); - - while (inl(PC_COUNTER_CNTRL) & PC_CNTRL_C1S); - outl (0, PC1_COUNTER_WRITE); - while (inl(PC_COUNTER_CNTRL) & PC_CNTRL_C1S); + counter = au_readl(SYS_COUNTER_CNTRL); + au_writel(counter | SYS_CNTRL_EN1, SYS_COUNTER_CNTRL); - start = inl(PC1_COUNTER_READ); + while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S); + au_writel(trim_divide-1, SYS_RTCTRIM); /* RTC now ticks at 32.768/16 kHz */ + while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S); + + while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S); + au_writel (0, SYS_TOYWRITE); + while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S); + + start = au_readl(SYS_RTCREAD); start += 2; /* wait for the beginning of a new tick */ - while (inl(PC1_COUNTER_READ) < start); + while (au_readl(SYS_RTCREAD) < start); /* Start r4k counter. */ - write_32bit_cp0_register(CP0_COUNT, 0); + write_c0_count(0); end = start + (32768 / trim_divide)/2; /* wait 0.5 seconds */ - while (end > inl(PC1_COUNTER_READ)); + while (end > au_readl(SYS_RTCREAD)); - count = read_32bit_cp0_register(CP0_COUNT); + count = read_c0_count(); cpu_speed = count * 2; - uart_baud_base = (((cpu_speed) / 4) / 16); + mips_counter_frequency = count; + set_au1x00_uart_baud_base(((cpu_speed) / 4) / 16); + spin_unlock_irqrestore(&time_lock, flags); return (cpu_speed / HZ); } -static unsigned long __init get_mips_time(void) -{ - return inl(PC0_COUNTER_READ); -} - -void __init time_init(void) +void __init au1x_time_init(void) { - unsigned int est_freq, flags; + unsigned int est_freq; printk("calculating r4koff... "); r4k_offset = cal_r4koff(); printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset); - //est_freq = 2*r4k_offset*HZ; - est_freq = r4k_offset*HZ; + //est_freq = 2*r4k_offset*HZ; + est_freq = r4k_offset*HZ; est_freq += 5000; /* round */ est_freq -= est_freq%10000; - printk("CPU frequency %d.%02d MHz\n", est_freq/1000000, + printk("CPU frequency %d.%02d MHz\n", est_freq/1000000, (est_freq%1000000)*100/1000000); - r4k_cur = (read_32bit_cp0_register(CP0_COUNT) + r4k_offset); + set_au1x00_speed(est_freq); + set_au1x00_lcd_clock(); // program the LCD clock + r4k_cur = (read_c0_count() + r4k_offset); - write_32bit_cp0_register(CP0_COMPARE, r4k_cur); - set_cp0_status(ALLINTS); + write_c0_compare(r4k_cur); - /* Read time from the RTC chipset. */ - write_seqlock_irqsave (&xtime_lock, flags); - xtime.tv_sec = get_mips_time(); - xtime.tv_usec = 0; - write_sequnlock_irqrestore(&xtime_lock, flags); + /* no RTC on the pb1000 */ + xtime.tv_sec = 0; + //xtime.tv_usec = 0; + +#ifdef CONFIG_PM + /* + * setup counter 0, since it keeps ticking after a + * 'wait' instruction has been executed. The CP0 timer and + * counter 1 do NOT continue running after 'wait' + * + * It's too early to call request_irq() here, so we handle + * counter 0 interrupt as a special irq and it doesn't show + * up under /proc/interrupts. + */ + while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S); + au_writel(0, SYS_TOYWRITE); + while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S); + + au_writel(au_readl(SYS_WAKEMSK) | (1<<8), SYS_WAKEMSK); + au_writel(~0, SYS_WAKESRC); + au_sync(); + while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20); + + /* setup match20 to interrupt once every 10ms */ + last_pc0 = last_match20 = au_readl(SYS_TOYREAD); + au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2); + au_sync(); + while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20); + startup_match20_interrupt(); +#endif + + //set_c0_status(ALLINTS); + au_sync(); } -/* This is for machines which generate the exact clock. */ -#define USECS_PER_JIFFY (1000000/HZ) -#define USECS_PER_JIFFY_FRAC ((1000000ULL << 32) / HZ & 0xffffffff) +void __init au1x_timer_setup(struct irqaction *irq) +{ -/* Cycle counter value at the previous timer interrupt.. */ +} -static unsigned int timerhi = 0, timerlo = 0; +/* This is for machines which generate the exact clock. */ +#define USECS_PER_JIFFY (1000000/HZ) +#define USECS_PER_JIFFY_FRAC (0x100000000*1000000/HZ&0xffffffff) +#ifndef CONFIG_PM static unsigned long div64_32(unsigned long v1, unsigned long v2, unsigned long v3) { @@ -171,13 +273,30 @@ do_div64_32(r0, v1, v2, v3); return r0; } +#endif - -/* - * FIXME: Does playing with the RP bit in c0_status interfere with this code? - */ static unsigned long do_fast_gettimeoffset(void) { +#ifdef CONFIG_PM + unsigned long pc0; + unsigned long offset; + + pc0 = au_readl(SYS_TOYREAD); + if (pc0 < last_pc0) { + offset = 0xffffffff - last_pc0 + pc0; + printk("offset over: %x\n", (unsigned)offset); + } + else { + offset = (unsigned long)(((pc0 - last_pc0) * 305) / 10); + } + if ((pc0-last_pc0) > 2*MATCH20_INC) { + printk("huge offset %x, last_pc0 %x last_match20 %x pc0 %x\n", + (unsigned)offset, (unsigned)last_pc0, + (unsigned)last_match20, (unsigned)pc0); + } + au_sync(); + return offset; +#else u32 count; unsigned long res, tmp; unsigned long r0; @@ -206,7 +325,7 @@ } /* Get last timer tick in absolute kernel time */ - count = read_32bit_cp0_register(CP0_COUNT); + count = read_c0_count(); /* .. relative to previous jiffy (32 bits is enough) */ count -= timerlo; @@ -218,73 +337,12 @@ "r" (quotient)); /* - * Due to possible jiffies inconsistencies, we need to check + * Due to possible jiffies inconsistencies, we need to check * the result so that we'll get a timer that is monotonic. */ if (res >= USECS_PER_JIFFY) res = USECS_PER_JIFFY-1; return res; -} - -void do_gettimeofday(struct timeval *tv) -{ - unsigned long flags; - unsigned long seq; - - do { - seq = read_seqbegin_irqsave(&xtime_lock, flags); - - *tv = xtime; - tv->tv_usec += do_fast_gettimeoffset(); - - /* - * xtime is atomically updated in timer_bh. jiffies - wall_jiffies - * is nonzero if the timer bottom half hasnt executed yet. - */ - if (jiffies - wall_jiffies) - tv->tv_usec += USECS_PER_JIFFY; - - } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); - - - if (tv->tv_usec >= 1000000) { - tv->tv_usec -= 1000000; - tv->tv_sec++; - } -} - -void do_settimeofday(struct timeval *tv) -{ - write_seqlock_irq (&xtime_lock); - - /* This is revolting. We need to set the xtime.tv_usec correctly. - * However, the value in this location is is value at the last tick. - * Discover what correction gettimeofday would have done, and then - * undo it! - */ - tv->tv_usec -= do_fast_gettimeoffset(); - - if (tv->tv_usec < 0) { - tv->tv_usec += 1000000; - tv->tv_sec--; - } - - xtime = *tv; - time_adjust = 0; /* stop active adjtime() */ - time_status |= STA_UNSYNC; - time_maxerror = NTP_PHASE_LIMIT; - time_esterror = NTP_PHASE_LIMIT; - - write_sequnlock_irq (&xtime_lock); -} - -/* - * The UART baud base is not known at compile time ... if - * we want to be able to use the same code on different - * speed CPUs. - */ -unsigned long get_au1000_uart_baud() -{ - return uart_baud_base; +#endif } diff -Nru a/arch/mips/au1000/common/usbdev.c b/arch/mips/au1000/common/usbdev.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/common/usbdev.c Tue Jul 1 18:44:39 2003 @@ -0,0 +1,1562 @@ +/* + * BRIEF MODULE DESCRIPTION + * Au1000 USB Device-Side (device layer) + * + * Copyright 2001-2002 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * stevel@mvista.com or source@mvista.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define DEBUG +#include + +#include +#include +#include +#include +#include +#include +#include + +#ifdef DEBUG +#undef VDEBUG +#ifdef VDEBUG +#define vdbg(fmt, arg...) printk(KERN_DEBUG __FILE__ ": " fmt "\n" , ## arg) +#else +#define vdbg(fmt, arg...) do {} while (0) +#endif +#else +#define vdbg(fmt, arg...) do {} while (0) +#endif + +#define MAX(a,b) (((a)>(b))?(a):(b)) + +#define ALLOC_FLAGS (in_interrupt () ? GFP_ATOMIC : GFP_KERNEL) + +#define EP_FIFO_DEPTH 8 + +typedef enum { + SETUP_STAGE = 0, + DATA_STAGE, + STATUS_STAGE +} ep0_stage_t; + +typedef struct { + int read_fifo; + int write_fifo; + int ctrl_stat; + int read_fifo_status; + int write_fifo_status; +} endpoint_reg_t; + +typedef struct { + usbdev_pkt_t *head; + usbdev_pkt_t *tail; + int count; +} pkt_list_t; + +typedef struct { + int active; + struct usb_endpoint_descriptor *desc; + endpoint_reg_t *reg; + /* Only one of these are used, unless this is the control ep */ + pkt_list_t inlist; + pkt_list_t outlist; + unsigned int indma, outdma; /* DMA channel numbers for IN, OUT */ + /* following are extracted from endpoint descriptor for easy access */ + int max_pkt_size; + int type; + int direction; + /* WE assign endpoint addresses! */ + int address; + spinlock_t lock; +} endpoint_t; + + +static struct usb_dev { + endpoint_t ep[6]; + ep0_stage_t ep0_stage; + + struct usb_device_descriptor * dev_desc; + struct usb_interface_descriptor* if_desc; + struct usb_config_descriptor * conf_desc; + u8 * full_conf_desc; + struct usb_string_descriptor * str_desc[6]; + + /* callback to function layer */ + void (*func_cb)(usbdev_cb_type_t type, unsigned long arg, + void *cb_data); + void* cb_data; + + usbdev_state_t state; // device state + int suspended; // suspended flag + int address; // device address + int interface; + int num_ep; + u8 alternate_setting; + u8 configuration; // configuration value + int remote_wakeup_en; +} usbdev; + + +static endpoint_reg_t ep_reg[] = { + // FIFO's 0 and 1 are EP0 default control + {USBD_EP0RD, USBD_EP0WR, USBD_EP0CS, USBD_EP0RDSTAT, USBD_EP0WRSTAT }, + {0}, + // FIFO 2 is EP2, IN + { -1, USBD_EP2WR, USBD_EP2CS, -1, USBD_EP2WRSTAT }, + // FIFO 3 is EP3, IN + { -1, USBD_EP3WR, USBD_EP3CS, -1, USBD_EP3WRSTAT }, + // FIFO 4 is EP4, OUT + {USBD_EP4RD, -1, USBD_EP4CS, USBD_EP4RDSTAT, -1 }, + // FIFO 5 is EP5, OUT + {USBD_EP5RD, -1, USBD_EP5CS, USBD_EP5RDSTAT, -1 } +}; + +static struct { + unsigned int id; + const char *str; +} ep_dma_id[] = { + { DMA_ID_USBDEV_EP0_TX, "USBDev EP0 IN" }, + { DMA_ID_USBDEV_EP0_RX, "USBDev EP0 OUT" }, + { DMA_ID_USBDEV_EP2_TX, "USBDev EP2 IN" }, + { DMA_ID_USBDEV_EP3_TX, "USBDev EP3 IN" }, + { DMA_ID_USBDEV_EP4_RX, "USBDev EP4 OUT" }, + { DMA_ID_USBDEV_EP5_RX, "USBDev EP5 OUT" } +}; + +#define DIR_OUT 0 +#define DIR_IN (1<<3) + +#define CONTROL_EP USB_ENDPOINT_XFER_CONTROL +#define BULK_EP USB_ENDPOINT_XFER_BULK + +static inline endpoint_t * +epaddr_to_ep(struct usb_dev* dev, int ep_addr) +{ + if (ep_addr >= 0 && ep_addr < 2) + return &dev->ep[0]; + if (ep_addr < 6) + return &dev->ep[ep_addr]; + return NULL; +} + +static const char* std_req_name[] = { + "GET_STATUS", + "CLEAR_FEATURE", + "RESERVED", + "SET_FEATURE", + "RESERVED", + "SET_ADDRESS", + "GET_DESCRIPTOR", + "SET_DESCRIPTOR", + "GET_CONFIGURATION", + "SET_CONFIGURATION", + "GET_INTERFACE", + "SET_INTERFACE", + "SYNCH_FRAME" +}; + +static inline const char* +get_std_req_name(int req) +{ + return (req >= 0 && req <= 12) ? std_req_name[req] : "UNKNOWN"; +} + +#if 0 +static void +dump_setup(struct usb_ctrlrequest* s) +{ + dbg(__FUNCTION__ ": requesttype=%d", s->requesttype); + dbg(__FUNCTION__ ": request=%d %s", s->request, + get_std_req_name(s->request)); + dbg(__FUNCTION__ ": value=0x%04x", s->wValue); + dbg(__FUNCTION__ ": index=%d", s->index); + dbg(__FUNCTION__ ": length=%d", s->length); +} +#endif + +static inline usbdev_pkt_t * +alloc_packet(endpoint_t * ep, int data_size, void* data) +{ + usbdev_pkt_t* pkt = + (usbdev_pkt_t *)kmalloc(sizeof(usbdev_pkt_t) + data_size, + ALLOC_FLAGS); + if (!pkt) + return NULL; + pkt->ep_addr = ep->address; + pkt->size = data_size; + pkt->status = 0; + pkt->next = NULL; + if (data) + memcpy(pkt->payload, data, data_size); + + return pkt; +} + + +/* + * Link a packet to the tail of the enpoint's packet list. + * EP spinlock must be held when calling. + */ +static void +link_tail(endpoint_t * ep, pkt_list_t * list, usbdev_pkt_t * pkt) +{ + if (!list->tail) { + list->head = list->tail = pkt; + list->count = 1; + } else { + list->tail->next = pkt; + list->tail = pkt; + list->count++; + } +} + +/* + * Unlink and return a packet from the head of the given packet + * list. It is the responsibility of the caller to free the packet. + * EP spinlock must be held when calling. + */ +static usbdev_pkt_t * +unlink_head(pkt_list_t * list) +{ + usbdev_pkt_t *pkt; + + pkt = list->head; + if (!pkt || !list->count) { + return NULL; + } + + list->head = pkt->next; + if (!list->head) { + list->head = list->tail = NULL; + list->count = 0; + } else + list->count--; + + return pkt; +} + +/* + * Create and attach a new packet to the tail of the enpoint's + * packet list. EP spinlock must be held when calling. + */ +static usbdev_pkt_t * +add_packet(endpoint_t * ep, pkt_list_t * list, int size) +{ + usbdev_pkt_t *pkt = alloc_packet(ep, size, NULL); + if (!pkt) + return NULL; + + link_tail(ep, list, pkt); + return pkt; +} + + +/* + * Unlink and free a packet from the head of the enpoint's + * packet list. EP spinlock must be held when calling. + */ +static inline void +free_packet(pkt_list_t * list) +{ + kfree(unlink_head(list)); +} + +/* EP spinlock must be held when calling. */ +static inline void +flush_pkt_list(pkt_list_t * list) +{ + while (list->count) + free_packet(list); +} + +/* EP spinlock must be held when calling */ +static inline void +flush_write_fifo(endpoint_t * ep) +{ + if (ep->reg->write_fifo_status >= 0) { + au_writel(USBDEV_FSTAT_FLUSH | USBDEV_FSTAT_UF | + USBDEV_FSTAT_OF, + ep->reg->write_fifo_status); + //udelay(100); + //au_writel(USBDEV_FSTAT_UF | USBDEV_FSTAT_OF, + // ep->reg->write_fifo_status); + } +} + +/* EP spinlock must be held when calling */ +static inline void +flush_read_fifo(endpoint_t * ep) +{ + if (ep->reg->read_fifo_status >= 0) { + au_writel(USBDEV_FSTAT_FLUSH | USBDEV_FSTAT_UF | + USBDEV_FSTAT_OF, + ep->reg->read_fifo_status); + //udelay(100); + //au_writel(USBDEV_FSTAT_UF | USBDEV_FSTAT_OF, + // ep->reg->read_fifo_status); + } +} + + +/* EP spinlock must be held when calling. */ +static void +endpoint_flush(endpoint_t * ep) +{ + // First, flush all packets + flush_pkt_list(&ep->inlist); + flush_pkt_list(&ep->outlist); + + // Now flush the endpoint's h/w FIFO(s) + flush_write_fifo(ep); + flush_read_fifo(ep); +} + +/* EP spinlock must be held when calling. */ +static void +endpoint_stall(endpoint_t * ep) +{ + u32 cs; + + warn(__FUNCTION__); + + cs = au_readl(ep->reg->ctrl_stat) | USBDEV_CS_STALL; + au_writel(cs, ep->reg->ctrl_stat); +} + +/* EP spinlock must be held when calling. */ +static void +endpoint_unstall(endpoint_t * ep) +{ + u32 cs; + + warn(__FUNCTION__); + + cs = au_readl(ep->reg->ctrl_stat) & ~USBDEV_CS_STALL; + au_writel(cs, ep->reg->ctrl_stat); +} + +static void +endpoint_reset_datatoggle(endpoint_t * ep) +{ + // FIXME: is this possible? +} + + +/* EP spinlock must be held when calling. */ +static int +endpoint_fifo_read(endpoint_t * ep) +{ + int read_count = 0; + u8 *bufptr; + usbdev_pkt_t *pkt = ep->outlist.tail; + + if (!pkt) + return -EINVAL; + + bufptr = &pkt->payload[pkt->size]; + while (au_readl(ep->reg->read_fifo_status) & USBDEV_FSTAT_FCNT_MASK) { + *bufptr++ = au_readl(ep->reg->read_fifo) & 0xff; + read_count++; + pkt->size++; + } + + return read_count; +} + +#if 0 +/* EP spinlock must be held when calling. */ +static int +endpoint_fifo_write(endpoint_t * ep, int index) +{ + int write_count = 0; + u8 *bufptr; + usbdev_pkt_t *pkt = ep->inlist.head; + + if (!pkt) + return -EINVAL; + + bufptr = &pkt->payload[index]; + while ((au_readl(ep->reg->write_fifo_status) & + USBDEV_FSTAT_FCNT_MASK) < EP_FIFO_DEPTH) { + if (bufptr < pkt->payload + pkt->size) { + au_writel(*bufptr++, ep->reg->write_fifo); + write_count++; + } else { + break; + } + } + + return write_count; +} +#endif + +/* + * This routine is called to restart transmission of a packet. + * The endpoint's TSIZE must be set to the new packet's size, + * and DMA to the write FIFO needs to be restarted. + * EP spinlock must be held when calling. + */ +static void +kickstart_send_packet(endpoint_t * ep) +{ + u32 cs; + usbdev_pkt_t *pkt = ep->inlist.head; + + vdbg(__FUNCTION__ ": ep%d, pkt=%p", ep->address, pkt); + + if (!pkt) { + err(__FUNCTION__ ": head=NULL! list->count=%d", + ep->inlist.count); + return; + } + + dma_cache_wback_inv((unsigned long)pkt->payload, pkt->size); + + /* + * make sure FIFO is empty + */ + flush_write_fifo(ep); + + cs = au_readl(ep->reg->ctrl_stat) & USBDEV_CS_STALL; + cs |= (pkt->size << USBDEV_CS_TSIZE_BIT); + au_writel(cs, ep->reg->ctrl_stat); + + if (get_dma_active_buffer(ep->indma) == 1) { + set_dma_count1(ep->indma, pkt->size); + set_dma_addr1(ep->indma, virt_to_phys(pkt->payload)); + enable_dma_buffer1(ep->indma); // reenable + } else { + set_dma_count0(ep->indma, pkt->size); + set_dma_addr0(ep->indma, virt_to_phys(pkt->payload)); + enable_dma_buffer0(ep->indma); // reenable + } + if (dma_halted(ep->indma)) + start_dma(ep->indma); +} + + +/* + * This routine is called when a packet in the inlist has been + * completed. Frees the completed packet and starts sending the + * next. EP spinlock must be held when calling. + */ +static usbdev_pkt_t * +send_packet_complete(endpoint_t * ep) +{ + usbdev_pkt_t *pkt = unlink_head(&ep->inlist); + + if (pkt) { + pkt->status = + (au_readl(ep->reg->ctrl_stat) & USBDEV_CS_NAK) ? + PKT_STATUS_NAK : PKT_STATUS_ACK; + + vdbg(__FUNCTION__ ": ep%d, %s pkt=%p, list count=%d", + ep->address, (pkt->status & PKT_STATUS_NAK) ? + "NAK" : "ACK", pkt, ep->inlist.count); + } + + /* + * The write fifo should already be drained if things are + * working right, but flush it anyway just in case. + */ + flush_write_fifo(ep); + + // begin transmitting next packet in the inlist + if (ep->inlist.count) { + kickstart_send_packet(ep); + } + + return pkt; +} + +/* + * Add a new packet to the tail of the given ep's packet + * inlist. The transmit complete interrupt frees packets from + * the head of this list. EP spinlock must be held when calling. + */ +static int +send_packet(struct usb_dev* dev, usbdev_pkt_t *pkt, int async) +{ + pkt_list_t *list; + endpoint_t* ep; + + if (!pkt || !(ep = epaddr_to_ep(dev, pkt->ep_addr))) + return -EINVAL; + + if (!pkt->size) + return 0; + + list = &ep->inlist; + + if (!async && list->count) { + halt_dma(ep->indma); + flush_pkt_list(list); + } + + link_tail(ep, list, pkt); + + vdbg(__FUNCTION__ ": ep%d, pkt=%p, size=%d, list count=%d", + ep->address, pkt, pkt->size, list->count); + + if (list->count == 1) { + /* + * if the packet count is one, it means the list was empty, + * and no more data will go out this ep until we kick-start + * it again. + */ + kickstart_send_packet(ep); + } + + return pkt->size; +} + +/* + * This routine is called to restart reception of a packet. + * EP spinlock must be held when calling. + */ +static void +kickstart_receive_packet(endpoint_t * ep) +{ + usbdev_pkt_t *pkt; + + // get and link a new packet for next reception + if (!(pkt = add_packet(ep, &ep->outlist, ep->max_pkt_size))) { + err(__FUNCTION__ ": could not alloc new packet"); + return; + } + + if (get_dma_active_buffer(ep->outdma) == 1) { + clear_dma_done1(ep->outdma); + set_dma_count1(ep->outdma, ep->max_pkt_size); + set_dma_count0(ep->outdma, 0); + set_dma_addr1(ep->outdma, virt_to_phys(pkt->payload)); + enable_dma_buffer1(ep->outdma); // reenable + } else { + clear_dma_done0(ep->outdma); + set_dma_count0(ep->outdma, ep->max_pkt_size); + set_dma_count1(ep->outdma, 0); + set_dma_addr0(ep->outdma, virt_to_phys(pkt->payload)); + enable_dma_buffer0(ep->outdma); // reenable + } + if (dma_halted(ep->outdma)) + start_dma(ep->outdma); +} + + +/* + * This routine is called when a packet in the outlist has been + * completed (received) and we need to prepare for a new packet + * to be received. Halts DMA and computes the packet size from the + * remaining DMA counter. Then prepares a new packet for reception + * and restarts DMA. FIXME: what if another packet comes in + * on top of the completed packet? Counter would be wrong. + * EP spinlock must be held when calling. + */ +static usbdev_pkt_t * +receive_packet_complete(endpoint_t * ep) +{ + usbdev_pkt_t *pkt = ep->outlist.tail; + u32 cs; + + halt_dma(ep->outdma); + + cs = au_readl(ep->reg->ctrl_stat); + + if (!pkt) + return NULL; + + pkt->size = ep->max_pkt_size - get_dma_residue(ep->outdma); + if (pkt->size) + dma_cache_inv((unsigned long)pkt->payload, pkt->size); + /* + * need to pull out any remaining bytes in the FIFO. + */ + endpoint_fifo_read(ep); + /* + * should be drained now, but flush anyway just in case. + */ + flush_read_fifo(ep); + + pkt->status = (cs & USBDEV_CS_NAK) ? PKT_STATUS_NAK : PKT_STATUS_ACK; + if (ep->address == 0 && (cs & USBDEV_CS_SU)) + pkt->status |= PKT_STATUS_SU; + + vdbg(__FUNCTION__ ": ep%d, %s pkt=%p, size=%d", + ep->address, (pkt->status & PKT_STATUS_NAK) ? + "NAK" : "ACK", pkt, pkt->size); + + kickstart_receive_packet(ep); + + return pkt; +} + + +/* + **************************************************************************** + * Here starts the standard device request handlers. They are + * all called by do_setup() via a table of function pointers. + **************************************************************************** + */ + +static ep0_stage_t +do_get_status(struct usb_dev* dev, struct usb_ctrlrequest* setup) +{ + switch (setup->bRequestType) { + case 0x80: // Device + // FIXME: send device status + break; + case 0x81: // Interface + // FIXME: send interface status + break; + case 0x82: // End Point + // FIXME: send endpoint status + break; + default: + // Invalid Command + endpoint_stall(&dev->ep[0]); // Stall End Point 0 + break; + } + + return STATUS_STAGE; +} + +static ep0_stage_t +do_clear_feature(struct usb_dev* dev, struct usb_ctrlrequest* setup) +{ + switch (setup->bRequestType) { + case 0x00: // Device + if ((le16_to_cpu(setup->wValue) & 0xff) == 1) + dev->remote_wakeup_en = 0; + else + endpoint_stall(&dev->ep[0]); + break; + case 0x02: // End Point + if ((le16_to_cpu(setup->wValue) & 0xff) == 0) { + endpoint_t *ep = + epaddr_to_ep(dev, + le16_to_cpu(setup->wIndex) & 0xff); + + endpoint_unstall(ep); + endpoint_reset_datatoggle(ep); + } else + endpoint_stall(&dev->ep[0]); + break; + } + + return SETUP_STAGE; +} + +static ep0_stage_t +do_reserved(struct usb_dev* dev, struct usb_ctrlrequest* setup) +{ + // Invalid request, stall End Point 0 + endpoint_stall(&dev->ep[0]); + return SETUP_STAGE; +} + +static ep0_stage_t +do_set_feature(struct usb_dev* dev, struct usb_ctrlrequest* setup) +{ + switch (setup->bRequestType) { + case 0x00: // Device + if ((le16_to_cpu(setup->wValue) & 0xff) == 1) + dev->remote_wakeup_en = 1; + else + endpoint_stall(&dev->ep[0]); + break; + case 0x02: // End Point + if ((le16_to_cpu(setup->wValue) & 0xff) == 0) { + endpoint_t *ep = + epaddr_to_ep(dev, + le16_to_cpu(setup->wIndex) & 0xff); + + endpoint_stall(ep); + } else + endpoint_stall(&dev->ep[0]); + break; + } + + return SETUP_STAGE; +} + +static ep0_stage_t +do_set_address(struct usb_dev* dev, struct usb_ctrlrequest* setup) +{ + int new_state = dev->state; + int new_addr = le16_to_cpu(setup->wValue); + + dbg(__FUNCTION__ ": our address=%d", new_addr); + + if (new_addr > 127) { + // usb spec doesn't tell us what to do, so just go to + // default state + new_state = DEFAULT; + dev->address = 0; + } else if (dev->address != new_addr) { + dev->address = new_addr; + new_state = ADDRESS; + } + + if (dev->state != new_state) { + dev->state = new_state; + /* inform function layer of usbdev state change */ + dev->func_cb(CB_NEW_STATE, dev->state, dev->cb_data); + } + + return SETUP_STAGE; +} + +static ep0_stage_t +do_get_descriptor(struct usb_dev* dev, struct usb_ctrlrequest* setup) +{ + int strnum, desc_len = le16_to_cpu(setup->wLength); + + switch (le16_to_cpu(setup->wValue) >> 8) { + case USB_DT_DEVICE: + // send device descriptor! + desc_len = desc_len > dev->dev_desc->bLength ? + dev->dev_desc->bLength : desc_len; + dbg("sending device desc, size=%d", desc_len); + send_packet(dev, alloc_packet(&dev->ep[0], desc_len, + dev->dev_desc), 0); + break; + case USB_DT_CONFIG: + // If the config descr index in low-byte of + // setup->wValue is valid, send config descr, + // otherwise stall ep0. + if ((le16_to_cpu(setup->wValue) & 0xff) == 0) { + // send config descriptor! + if (desc_len <= USB_DT_CONFIG_SIZE) { + dbg("sending partial config desc, size=%d", + desc_len); + send_packet(dev, + alloc_packet(&dev->ep[0], + desc_len, + dev->conf_desc), + 0); + } else { + int len = dev->conf_desc->wTotalLength; + dbg("sending whole config desc," + " size=%d, our size=%d", desc_len, len); + desc_len = desc_len > len ? len : desc_len; + send_packet(dev, + alloc_packet(&dev->ep[0], + desc_len, + dev->full_conf_desc), + 0); + } + } else + endpoint_stall(&dev->ep[0]); + break; + case USB_DT_STRING: + // If the string descr index in low-byte of setup->wValue + // is valid, send string descr, otherwise stall ep0. + strnum = le16_to_cpu(setup->wValue) & 0xff; + if (strnum >= 0 && strnum < 6) { + struct usb_string_descriptor *desc = + dev->str_desc[strnum]; + desc_len = desc_len > desc->bLength ? + desc->bLength : desc_len; + dbg("sending string desc %d", strnum); + send_packet(dev, + alloc_packet(&dev->ep[0], desc_len, + desc), 0); + } else + endpoint_stall(&dev->ep[0]); + break; + default: + // Invalid request + err("invalid get desc=%d, stalled", + le16_to_cpu(setup->wValue) >> 8); + endpoint_stall(&dev->ep[0]); // Stall endpoint 0 + break; + } + + return STATUS_STAGE; +} + +static ep0_stage_t +do_set_descriptor(struct usb_dev* dev, struct usb_ctrlrequest* setup) +{ + // TODO: implement + // there will be an OUT data stage (the descriptor to set) + return DATA_STAGE; +} + +static ep0_stage_t +do_get_configuration(struct usb_dev* dev, struct usb_ctrlrequest* setup) +{ + // send dev->configuration + dbg("sending config"); + send_packet(dev, alloc_packet(&dev->ep[0], 1, &dev->configuration), + 0); + return STATUS_STAGE; +} + +static ep0_stage_t +do_set_configuration(struct usb_dev* dev, struct usb_ctrlrequest* setup) +{ + // set active config to low-byte of setup->wValue + dev->configuration = le16_to_cpu(setup->wValue) & 0xff; + dbg("set config, config=%d", dev->configuration); + if (!dev->configuration && dev->state > DEFAULT) { + dev->state = ADDRESS; + /* inform function layer of usbdev state change */ + dev->func_cb(CB_NEW_STATE, dev->state, dev->cb_data); + } else if (dev->configuration == 1) { + dev->state = CONFIGURED; + /* inform function layer of usbdev state change */ + dev->func_cb(CB_NEW_STATE, dev->state, dev->cb_data); + } else { + // FIXME: "respond with request error" - how? + } + + return SETUP_STAGE; +} + +static ep0_stage_t +do_get_interface(struct usb_dev* dev, struct usb_ctrlrequest* setup) +{ + // interface must be zero. + if ((le16_to_cpu(setup->wIndex) & 0xff) || dev->state == ADDRESS) { + // FIXME: respond with "request error". how? + } else if (dev->state == CONFIGURED) { + // send dev->alternate_setting + dbg("sending alt setting"); + send_packet(dev, alloc_packet(&dev->ep[0], 1, + &dev->alternate_setting), 0); + } + + return STATUS_STAGE; + +} + +static ep0_stage_t +do_set_interface(struct usb_dev* dev, struct usb_ctrlrequest* setup) +{ + if (dev->state == ADDRESS) { + // FIXME: respond with "request error". how? + } else if (dev->state == CONFIGURED) { + dev->interface = le16_to_cpu(setup->wIndex) & 0xff; + dev->alternate_setting = + le16_to_cpu(setup->wValue) & 0xff; + // interface and alternate_setting must be zero + if (dev->interface || dev->alternate_setting) { + // FIXME: respond with "request error". how? + } + } + + return SETUP_STAGE; +} + +static ep0_stage_t +do_synch_frame(struct usb_dev* dev, struct usb_ctrlrequest* setup) +{ + // TODO + return SETUP_STAGE; +} + +typedef ep0_stage_t (*req_method_t)(struct usb_dev* dev, + struct usb_ctrlrequest* setup); + + +/* Table of the standard device request handlers */ +static const req_method_t req_method[] = { + do_get_status, + do_clear_feature, + do_reserved, + do_set_feature, + do_reserved, + do_set_address, + do_get_descriptor, + do_set_descriptor, + do_get_configuration, + do_set_configuration, + do_get_interface, + do_set_interface, + do_synch_frame +}; + + +// SETUP packet request dispatcher +static void +do_setup (struct usb_dev* dev, struct usb_ctrlrequest* setup) +{ + req_method_t m; + + dbg(__FUNCTION__ ": req %d %s", setup->bRequestType, + get_std_req_name(setup->bRequestType)); + + if ((setup->bRequestType & USB_TYPE_MASK) != USB_TYPE_STANDARD || + (setup->bRequestType & USB_RECIP_MASK) != USB_RECIP_DEVICE) { + err(__FUNCTION__ ": invalid requesttype 0x%02x", + setup->bRequestType); + return; + } + + if ((setup->bRequestType & 0x80) == USB_DIR_OUT && setup->wLength) + dbg(__FUNCTION__ ": OUT phase! length=%d", setup->wLength); + + if (setup->bRequestType < sizeof(req_method)/sizeof(req_method_t)) + m = req_method[setup->bRequestType]; + else + m = do_reserved; + + dev->ep0_stage = (*m)(dev, setup); +} + +/* + * A SETUP, DATA0, or DATA1 packet has been received + * on the default control endpoint's fifo. + */ +static void +process_ep0_receive (struct usb_dev* dev) +{ + endpoint_t *ep0 = &dev->ep[0]; + usbdev_pkt_t *pkt; + + spin_lock(&ep0->lock); + + // complete packet and prepare a new packet + pkt = receive_packet_complete(ep0); + if (!pkt) { + // FIXME: should put a warn/err here. + spin_unlock(&ep0->lock); + return; + } + + // unlink immediately from endpoint. + unlink_head(&ep0->outlist); + + // override current stage if h/w says it's a setup packet + if (pkt->status & PKT_STATUS_SU) + dev->ep0_stage = SETUP_STAGE; + + switch (dev->ep0_stage) { + case SETUP_STAGE: + vdbg("SU bit is %s in setup stage", + (pkt->status & PKT_STATUS_SU) ? "set" : "not set"); + + if (pkt->size == sizeof(struct usb_ctrlrequest)) { +#ifdef VDEBUG + if (pkt->status & PKT_STATUS_ACK) + vdbg("received SETUP"); + else + vdbg("received NAK SETUP"); +#endif + do_setup(dev, (struct usb_ctrlrequest*)pkt->payload); + } else + err(__FUNCTION__ ": wrong size SETUP received"); + break; + case DATA_STAGE: + /* + * this setup has an OUT data stage. Of the standard + * device requests, only set_descriptor has this stage, + * so this packet is that descriptor. TODO: drop it for + * now, set_descriptor not implemented. + * + * Need to place a byte in the write FIFO here, to prepare + * to send a zero-length DATA ack packet to the host in the + * STATUS stage. + */ + au_writel(0, ep0->reg->write_fifo); + dbg("received OUT stage DATAx on EP0, size=%d", pkt->size); + dev->ep0_stage = SETUP_STAGE; + break; + case STATUS_STAGE: + // this setup had an IN data stage, and host is ACK'ing + // the packet we sent during that stage. + if (pkt->size != 0) + warn("received non-zero ACK on EP0??"); +#ifdef VDEBUG + else + vdbg("received ACK on EP0"); +#endif + dev->ep0_stage = SETUP_STAGE; + break; + } + + spin_unlock(&ep0->lock); + // we're done processing the packet, free it + kfree(pkt); +} + + +/* + * A DATA0/1 packet has been received on one of the OUT endpoints (4 or 5) + */ +static void +process_ep_receive (struct usb_dev* dev, endpoint_t *ep) +{ + usbdev_pkt_t *pkt; + + spin_lock(&ep->lock); + pkt = receive_packet_complete(ep); + spin_unlock(&ep->lock); + + dev->func_cb(CB_PKT_COMPLETE, (unsigned long)pkt, dev->cb_data); +} + + + +/* This ISR handles the receive complete and suspend events */ +static void +req_sus_intr (int irq, void *dev_id, struct pt_regs *regs) +{ + struct usb_dev *dev = (struct usb_dev *) dev_id; + u32 status; + + status = au_readl(USBD_INTSTAT); + au_writel(status, USBD_INTSTAT); // ack'em + + if (status & (1<<0)) + process_ep0_receive(dev); + if (status & (1<<4)) + process_ep_receive(dev, &dev->ep[4]); + if (status & (1<<5)) + process_ep_receive(dev, &dev->ep[5]); +} + + +/* This ISR handles the DMA done events on EP0 */ +static void +dma_done_ep0_intr(int irq, void *dev_id, struct pt_regs *regs) +{ + struct usb_dev *dev = (struct usb_dev *) dev_id; + usbdev_pkt_t* pkt; + endpoint_t *ep0 = &dev->ep[0]; + u32 cs0, buff_done; + + spin_lock(&ep0->lock); + cs0 = au_readl(ep0->reg->ctrl_stat); + + // first check packet transmit done + if ((buff_done = get_dma_buffer_done(ep0->indma)) != 0) { + // transmitted a DATAx packet during DATA stage + // on control endpoint 0 + // clear DMA done bit + if (buff_done & DMA_D0) + clear_dma_done0(ep0->indma); + if (buff_done & DMA_D1) + clear_dma_done1(ep0->indma); + + pkt = send_packet_complete(ep0); + if (pkt) + kfree(pkt); + } + + /* + * Now check packet receive done. Shouldn't get these, + * the receive packet complete intr should happen + * before the DMA done intr occurs. + */ + if ((buff_done = get_dma_buffer_done(ep0->outdma)) != 0) { + // clear DMA done bit + if (buff_done & DMA_D0) + clear_dma_done0(ep0->outdma); + if (buff_done & DMA_D1) + clear_dma_done1(ep0->outdma); + + //process_ep0_receive(dev); + } + + spin_unlock(&ep0->lock); +} + +/* This ISR handles the DMA done events on endpoints 2,3,4,5 */ +static void +dma_done_ep_intr(int irq, void *dev_id, struct pt_regs *regs) +{ + struct usb_dev *dev = (struct usb_dev *) dev_id; + int i; + + for (i = 2; i < 6; i++) { + u32 buff_done; + usbdev_pkt_t* pkt; + endpoint_t *ep = &dev->ep[i]; + + if (!ep->active) continue; + + spin_lock(&ep->lock); + + if (ep->direction == USB_DIR_IN) { + buff_done = get_dma_buffer_done(ep->indma); + if (buff_done != 0) { + // transmitted a DATAx pkt on the IN ep + // clear DMA done bit + if (buff_done & DMA_D0) + clear_dma_done0(ep->indma); + if (buff_done & DMA_D1) + clear_dma_done1(ep->indma); + + pkt = send_packet_complete(ep); + + spin_unlock(&ep->lock); + dev->func_cb(CB_PKT_COMPLETE, + (unsigned long)pkt, + dev->cb_data); + spin_lock(&ep->lock); + } + } else { + /* + * Check packet receive done (OUT ep). Shouldn't get + * these, the rx packet complete intr should happen + * before the DMA done intr occurs. + */ + buff_done = get_dma_buffer_done(ep->outdma); + if (buff_done != 0) { + // received a DATAx pkt on the OUT ep + // clear DMA done bit + if (buff_done & DMA_D0) + clear_dma_done0(ep->outdma); + if (buff_done & DMA_D1) + clear_dma_done1(ep->outdma); + + //process_ep_receive(dev, ep); + } + } + + spin_unlock(&ep->lock); + } +} + + +/*************************************************************************** + * Here begins the external interface functions + *************************************************************************** + */ + +/* + * allocate a new packet + */ +int +usbdev_alloc_packet(int ep_addr, int data_size, usbdev_pkt_t** pkt) +{ + endpoint_t * ep = epaddr_to_ep(&usbdev, ep_addr); + usbdev_pkt_t* lpkt = NULL; + + if (!ep || !ep->active || ep->address < 2) + return -ENODEV; + if (data_size > ep->max_pkt_size) + return -EINVAL; + + lpkt = *pkt = alloc_packet(ep, data_size, NULL); + if (!lpkt) + return -ENOMEM; + return 0; +} + + +/* + * packet send + */ +int +usbdev_send_packet(int ep_addr, usbdev_pkt_t * pkt) +{ + unsigned long flags; + int count; + endpoint_t * ep; + + if (!pkt || !(ep = epaddr_to_ep(&usbdev, pkt->ep_addr)) || + !ep->active || ep->address < 2) + return -ENODEV; + if (ep->direction != USB_DIR_IN) + return -EINVAL; + + spin_lock_irqsave(&ep->lock, flags); + count = send_packet(&usbdev, pkt, 1); + spin_unlock_irqrestore(&ep->lock, flags); + + return count; +} + +/* + * packet receive + */ +int +usbdev_receive_packet(int ep_addr, usbdev_pkt_t** pkt) +{ + unsigned long flags; + usbdev_pkt_t* lpkt = NULL; + endpoint_t *ep = epaddr_to_ep(&usbdev, ep_addr); + + if (!ep || !ep->active || ep->address < 2) + return -ENODEV; + if (ep->direction != USB_DIR_OUT) + return -EINVAL; + + spin_lock_irqsave(&ep->lock, flags); + if (ep->outlist.count > 1) + lpkt = unlink_head(&ep->outlist); + spin_unlock_irqrestore(&ep->lock, flags); + + if (!lpkt) { + /* no packet available */ + *pkt = NULL; + return -ENODATA; + } + + *pkt = lpkt; + + return lpkt->size; +} + + +/* + * return total queued byte count on the endpoint. + */ +int +usbdev_get_byte_count(int ep_addr) +{ + unsigned long flags; + pkt_list_t *list; + usbdev_pkt_t *scan; + int count = 0; + endpoint_t * ep = epaddr_to_ep(&usbdev, ep_addr); + + if (!ep || !ep->active || ep->address < 2) + return -ENODEV; + + if (ep->direction == USB_DIR_IN) { + list = &ep->inlist; + + spin_lock_irqsave(&ep->lock, flags); + for (scan = list->head; scan; scan = scan->next) + count += scan->size; + spin_unlock_irqrestore(&ep->lock, flags); + } else { + list = &ep->outlist; + + spin_lock_irqsave(&ep->lock, flags); + if (list->count > 1) { + for (scan = list->head; scan != list->tail; + scan = scan->next) + count += scan->size; + } + spin_unlock_irqrestore(&ep->lock, flags); + } + + return count; +} + + +void +usbdev_exit(void) +{ + endpoint_t *ep; + int i; + + au_writel(0, USBD_INTEN); // disable usb dev ints + au_writel(0, USBD_ENABLE); // disable usb dev + + free_irq(AU1000_USB_DEV_REQ_INT, &usbdev); + free_irq(AU1000_USB_DEV_SUS_INT, &usbdev); + + // free all control endpoint resources + ep = &usbdev.ep[0]; + free_au1000_dma(ep->indma); + free_au1000_dma(ep->outdma); + endpoint_flush(ep); + + // free ep resources + for (i = 2; i < 6; i++) { + ep = &usbdev.ep[i]; + if (!ep->active) continue; + + if (ep->direction == USB_DIR_IN) { + free_au1000_dma(ep->indma); + } else { + free_au1000_dma(ep->outdma); + } + endpoint_flush(ep); + } + + if (usbdev.full_conf_desc) + kfree(usbdev.full_conf_desc); +} + +int +usbdev_init(struct usb_device_descriptor* dev_desc, + struct usb_config_descriptor* config_desc, + struct usb_interface_descriptor* if_desc, + struct usb_endpoint_descriptor* ep_desc, + struct usb_string_descriptor* str_desc[], + void (*cb)(usbdev_cb_type_t, unsigned long, void *), + void* cb_data) +{ + endpoint_t *ep0; + int i, ret=0; + u8* fcd; + + if (dev_desc->bNumConfigurations > 1 || + config_desc->bNumInterfaces > 1 || + if_desc->bNumEndpoints > 4) { + err("Only one config, one i/f, and no more " + "than 4 ep's allowed"); + ret = -EINVAL; + goto out; + } + + if (!cb) { + err("Function-layer callback required"); + ret = -EINVAL; + goto out; + } + + if (dev_desc->bMaxPacketSize0 != USBDEV_EP0_MAX_PACKET_SIZE) { + warn("EP0 Max Packet size must be %d", + USBDEV_EP0_MAX_PACKET_SIZE); + dev_desc->bMaxPacketSize0 = USBDEV_EP0_MAX_PACKET_SIZE; + } + + memset(&usbdev, 0, sizeof(struct usb_dev)); + + usbdev.state = DEFAULT; + usbdev.dev_desc = dev_desc; + usbdev.if_desc = if_desc; + usbdev.conf_desc = config_desc; + for (i=0; i<6; i++) + usbdev.str_desc[i] = str_desc[i]; + usbdev.func_cb = cb; + usbdev.cb_data = cb_data; + + /* Initialize default control endpoint */ + ep0 = &usbdev.ep[0]; + ep0->active = 1; + ep0->type = CONTROL_EP; + ep0->max_pkt_size = USBDEV_EP0_MAX_PACKET_SIZE; + spin_lock_init(&ep0->lock); + ep0->desc = NULL; // ep0 has no descriptor + ep0->address = 0; + ep0->direction = 0; + ep0->reg = &ep_reg[0]; + + /* Initialize the other requested endpoints */ + for (i = 0; i < if_desc->bNumEndpoints; i++) { + struct usb_endpoint_descriptor* epd = &ep_desc[i]; + endpoint_t *ep; + + if ((epd->bEndpointAddress & 0x80) == USB_DIR_IN) { + ep = &usbdev.ep[2]; + ep->address = 2; + if (ep->active) { + ep = &usbdev.ep[3]; + ep->address = 3; + if (ep->active) { + err("too many IN ep's requested"); + ret = -ENODEV; + goto out; + } + } + } else { + ep = &usbdev.ep[4]; + ep->address = 4; + if (ep->active) { + ep = &usbdev.ep[5]; + ep->address = 5; + if (ep->active) { + err("too many OUT ep's requested"); + ret = -ENODEV; + goto out; + } + } + } + + ep->active = 1; + epd->bEndpointAddress &= ~0x0f; + epd->bEndpointAddress |= (u8)ep->address; + ep->direction = epd->bEndpointAddress & 0x80; + ep->type = epd->bmAttributes & 0x03; + ep->max_pkt_size = epd->wMaxPacketSize; + spin_lock_init(&ep->lock); + ep->desc = epd; + ep->reg = &ep_reg[ep->address]; + } + + /* + * initialize the full config descriptor + */ + usbdev.full_conf_desc = fcd = kmalloc(config_desc->wTotalLength, + ALLOC_FLAGS); + if (!fcd) { + err("failed to alloc full config descriptor"); + ret = -ENOMEM; + goto out; + } + + memcpy(fcd, config_desc, USB_DT_CONFIG_SIZE); + fcd += USB_DT_CONFIG_SIZE; + memcpy(fcd, if_desc, USB_DT_INTERFACE_SIZE); + fcd += USB_DT_INTERFACE_SIZE; + for (i = 0; i < if_desc->bNumEndpoints; i++) { + memcpy(fcd, &ep_desc[i], USB_DT_ENDPOINT_SIZE); + fcd += USB_DT_ENDPOINT_SIZE; + } + + /* Now we're ready to enable the controller */ + au_writel(0x0002, USBD_ENABLE); + udelay(100); + au_writel(0x0003, USBD_ENABLE); + udelay(100); + + /* build and send config table based on ep descriptors */ + for (i = 0; i < 6; i++) { + endpoint_t *ep; + if (i == 1) + continue; // skip dummy ep + ep = &usbdev.ep[i]; + if (ep->active) { + au_writel((ep->address << 4) | 0x04, USBD_CONFIG); + au_writel(((ep->max_pkt_size & 0x380) >> 7) | + (ep->direction >> 4) | (ep->type << 4), + USBD_CONFIG); + au_writel((ep->max_pkt_size & 0x7f) << 1, USBD_CONFIG); + au_writel(0x00, USBD_CONFIG); + au_writel(ep->address, USBD_CONFIG); + } else { + u8 dir = (i==2 || i==3) ? DIR_IN : DIR_OUT; + au_writel((i << 4) | 0x04, USBD_CONFIG); + au_writel(((16 & 0x380) >> 7) | dir | + (BULK_EP << 4), USBD_CONFIG); + au_writel((16 & 0x7f) << 1, USBD_CONFIG); + au_writel(0x00, USBD_CONFIG); + au_writel(i, USBD_CONFIG); + } + } + + /* + * Enable Receive FIFO Complete interrupts only. Transmit + * complete is being handled by the DMA done interrupts. + */ + au_writel(0x31, USBD_INTEN); + + /* + * Controller is now enabled, request DMA and IRQ + * resources. + */ + + /* request the USB device transfer complete interrupt */ + if (request_irq(AU1000_USB_DEV_REQ_INT, req_sus_intr, SA_INTERRUPT, + "USBdev req", &usbdev)) { + err("Can't get device request intr"); + ret = -ENXIO; + goto out; + } + /* request the USB device suspend interrupt */ + if (request_irq(AU1000_USB_DEV_SUS_INT, req_sus_intr, SA_INTERRUPT, + "USBdev sus", &usbdev)) { + err("Can't get device suspend intr"); + ret = -ENXIO; + goto out; + } + + /* Request EP0 DMA and IRQ */ + if ((ep0->indma = request_au1000_dma(ep_dma_id[0].id, + ep_dma_id[0].str, + dma_done_ep0_intr, + SA_INTERRUPT, + &usbdev)) < 0) { + err("Can't get %s DMA", ep_dma_id[0].str); + ret = -ENXIO; + goto out; + } + if ((ep0->outdma = request_au1000_dma(ep_dma_id[1].id, + ep_dma_id[1].str, + NULL, 0, NULL)) < 0) { + err("Can't get %s DMA", ep_dma_id[1].str); + ret = -ENXIO; + goto out; + } + + // Flush the ep0 buffers and FIFOs + endpoint_flush(ep0); + // start packet reception on ep0 + kickstart_receive_packet(ep0); + + /* Request DMA and IRQ for the other endpoints */ + for (i = 2; i < 6; i++) { + endpoint_t *ep = &usbdev.ep[i]; + if (!ep->active) + continue; + + // Flush the endpoint buffers and FIFOs + endpoint_flush(ep); + + if (ep->direction == USB_DIR_IN) { + ep->indma = + request_au1000_dma(ep_dma_id[ep->address].id, + ep_dma_id[ep->address].str, + dma_done_ep_intr, + SA_INTERRUPT, + &usbdev); + if (ep->indma < 0) { + err("Can't get %s DMA", + ep_dma_id[ep->address].str); + ret = -ENXIO; + goto out; + } + } else { + ep->outdma = + request_au1000_dma(ep_dma_id[ep->address].id, + ep_dma_id[ep->address].str, + NULL, 0, NULL); + if (ep->outdma < 0) { + err("Can't get %s DMA", + ep_dma_id[ep->address].str); + ret = -ENXIO; + goto out; + } + + // start packet reception on OUT endpoint + kickstart_receive_packet(ep); + } + } + + out: + if (ret) + usbdev_exit(); + return ret; +} + +EXPORT_SYMBOL(usbdev_init); +EXPORT_SYMBOL(usbdev_exit); +EXPORT_SYMBOL(usbdev_alloc_packet); +EXPORT_SYMBOL(usbdev_receive_packet); +EXPORT_SYMBOL(usbdev_send_packet); +EXPORT_SYMBOL(usbdev_get_byte_count); diff -Nru a/arch/mips/au1000/db1x00/Makefile b/arch/mips/au1000/db1x00/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/db1x00/Makefile Tue Jul 1 18:44:40 2003 @@ -0,0 +1,20 @@ +# +# Copyright 2000 MontaVista Software Inc. +# Author: MontaVista Software, Inc. +# ppopov@mvista.com or source@mvista.com +# +# Makefile for the Alchemy Semiconductor PB1000 board. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +.S.s: + $(CPP) $(CFLAGS) $< -o $*.s +.S.o: + $(CC) $(CFLAGS) -c $< -o $*.o + +O_TARGET := db1x00.o + +obj-y := init.o setup.o diff -Nru a/arch/mips/au1000/db1x00/init.c b/arch/mips/au1000/db1x00/init.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/db1x00/init.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,73 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * PB1000 board setup + * + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int prom_argc; +char **prom_argv, **prom_envp; +extern void __init prom_init_cmdline(void); +extern char *prom_getenv(char *envname); + +const char *get_system_type(void) +{ + return "Alchemy Db1000"; +} + +int __init prom_init(int argc, char **argv, char **envp, int *prom_vec) +{ + unsigned char *memsize_str; + unsigned long memsize; + + prom_argc = argc; + prom_argv = argv; + prom_envp = envp; + + mips_machgroup = MACH_GROUP_ALCHEMY; + mips_machtype = MACH_DB1000; /* set the platform # */ + prom_init_cmdline(); + + memsize_str = prom_getenv("memsize"); + if (!memsize_str) { + memsize = 0x04000000; + } else { + memsize = simple_strtol(memsize_str, NULL, 0); + } + add_memory_region(0, memsize, BOOT_MEM_RAM); + return 0; +} diff -Nru a/arch/mips/au1000/db1x00/setup.c b/arch/mips/au1000/db1x00/setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/db1x00/setup.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,230 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * Alchemy Db1000 board setup. + * + * Copyright 2000 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_BLK_DEV_INITRD +extern unsigned long initrd_start, initrd_end; +extern void * __rd_start, * __rd_end; +#endif + +#ifdef CONFIG_BLK_DEV_IDE +extern struct ide_ops std_ide_ops; +extern struct ide_ops *ide_ops; +#endif + +extern struct rtc_ops no_rtc_ops; +extern char * __init prom_getcmdline(void); +extern void au1000_restart(char *); +extern void au1000_halt(void); +extern void au1000_power_off(void); +extern struct resource ioport_resource; +extern struct resource iomem_resource; +#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_SOC_AU1500) +extern phys_t (*fixup_bigphys_addr)(phys_t phys_addr, phys_t size); +static phys_t db_fixup_bigphys_addr(phys_t phys_addr, phys_t size); +#endif + +void __init au1x00_setup(void) +{ + char *argptr; + u32 pin_func, static_cfg0; + u32 sys_freqctrl, sys_clksrc; + u32 prid = read_c0_prid(); + + argptr = prom_getcmdline(); + + /* Various early Au1000 Errata corrected by this */ + set_c0_config(1<<19); /* Config[OD] */ + +#ifdef CONFIG_AU1X00_SERIAL_CONSOLE + if ((argptr = strstr(argptr, "console=")) == NULL) { + argptr = prom_getcmdline(); + strcat(argptr, " console=ttyS0,115200"); + } +#endif + +#ifdef CONFIG_FB_AU1100 + if ((argptr = strstr(argptr, "video=")) == NULL) { + argptr = prom_getcmdline(); + /* default panel */ + //strcat(argptr, " video=au1100fb:panel:Sharp_320x240_16"); + strcat(argptr, " video=au1100fb:panel:s10,nohwcursor"); + } +#endif + +#if defined(CONFIG_SOUND_AU1X00) && !defined(CONFIG_SOC_AU1000) + // au1000 does not support vra, au1500 and au1100 do + strcat(argptr, " au1000_audio=vra"); + argptr = prom_getcmdline(); +#endif + + rtc_ops = &no_rtc_ops; + _machine_restart = au1000_restart; + _machine_halt = au1000_halt; + _machine_power_off = au1000_power_off; +#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_SOC_AU1500) + fixup_bigphys_addr = db_fixup_bigphys_addr; +#endif + + // IO/MEM resources. + set_io_port_base(0); +#ifdef CONFIG_SOC_AU1500 + ioport_resource.start = 0x00000000; +#else + /* don't allow any legacy ports probing */ + ioport_resource.start = 0x10000000; +#endif + ioport_resource.end = 0xffffffff; + iomem_resource.start = 0x10000000; + iomem_resource.end = 0xffffffff; + +#ifdef CONFIG_BLK_DEV_INITRD + ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); + initrd_start = (unsigned long)&__rd_start; + initrd_end = (unsigned long)&__rd_end; +#endif + + // + // NOTE: + // + // YAMON (specifically reset_db1500.s) enables 32khz osc + // YAMON (specifically reset_db1x00.s) setups all clocking and GPIOs + // YAMON (specifically reset_db1500.s) setups all PCI + // + +#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE) +#ifdef CONFIG_USB_OHCI + if ((argptr = strstr(argptr, "usb_ohci=")) == NULL) { + char usb_args[80]; + argptr = prom_getcmdline(); + memset(usb_args, 0, sizeof(usb_args)); + sprintf(usb_args, " usb_ohci=base:0x%x,len:0x%x,irq:%d", + USB_OHCI_BASE, USB_OHCI_LEN, AU1000_USB_HOST_INT); + strcat(argptr, usb_args); + } +#endif + +#ifdef CONFIG_USB_OHCI + // enable host controller and wait for reset done + au_writel(0x08, USB_HOST_CONFIG); + udelay(1000); + au_writel(0x0E, USB_HOST_CONFIG); + udelay(1000); + au_readl(USB_HOST_CONFIG); // throw away first read + while (!(au_readl(USB_HOST_CONFIG) & 0x10)) + au_readl(USB_HOST_CONFIG); +#endif + +#ifdef CONFIG_AU1X00_USB_DEVICE + // 2nd USB port is USB device + pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000); + au_writel(pin_func, SYS_PINFUNC); +#endif + +#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE) + +#ifdef CONFIG_FB + // Needed if PCI video card in use + conswitchp = &dummy_con; +#endif + +#ifndef CONFIG_SERIAL_NONSTANDARD + /* don't touch the default serial console */ + au_writel(0, UART_ADDR + UART_CLK); +#endif + //au_writel(0, UART3_ADDR + UART_CLK); + +#ifdef CONFIG_BLK_DEV_IDE + ide_ops = &std_ide_ops; +#endif + +#if 0 + //// FIX!!! must be valid for au1000, au1500 and au1100 + /* Enable Au1000 BCLK switching */ + switch (prid & 0x000000FF) + { + case 0x00: /* DA */ + case 0x01: /* HA */ + case 0x02: /* HB */ + break; + default: /* HC and newer */ + au_writel(0x00000060, 0xb190003c); + break; + } +#endif + + au_writel(0, 0xAE000010); /* turn off pcmcia power */ + +#ifdef CONFIG_MIPS_DB1000 + printk("AMD Alchemy Au1000/Db1000 Board\n"); +#endif +#ifdef CONFIG_MIPS_DB1500 + printk("AMD Alchemy Au1500/Db1500 Board\n"); +#endif +#ifdef CONFIG_MIPS_DB1100 + printk("AMD Alchemy Au1100/Db1100 Board\n"); +#endif +} + +#if defined(CONFIG_64BIT_PHYS_ADDR) && defined(CONFIG_SOC_AU1500) +static phys_t db_fixup_bigphys_addr(phys_t phys_addr, phys_t size) +{ + u32 pci_start = (u32)Au1500_PCI_MEM_START; + u32 pci_end = (u32)Au1500_PCI_MEM_END; + + /* Don't fixup 36 bit addresses */ + if ((phys_addr >> 32) != 0) return phys_addr; + + /* check for pci memory window */ + if ((phys_addr >= pci_start) && ((phys_addr + size) < pci_end)) { + return (phys_t)((phys_addr - pci_start) + + Au1500_PCI_MEM_START); + } + else + return phys_addr; +} +#endif diff -Nru a/arch/mips/au1000/pb1000/Makefile b/arch/mips/au1000/pb1000/Makefile --- a/arch/mips/au1000/pb1000/Makefile Tue Jul 1 18:44:37 2003 +++ b/arch/mips/au1000/pb1000/Makefile Tue Jul 1 18:44:37 2003 @@ -5,5 +5,13 @@ # # Makefile for the Alchemy Semiconductor PB1000 board. # +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +USE_STANDARD_AS_RULE := true + +O_TARGET := pb1000.o obj-y := init.o setup.o diff -Nru a/arch/mips/au1000/pb1000/init.c b/arch/mips/au1000/pb1000/init.c --- a/arch/mips/au1000/pb1000/init.c Tue Jul 1 18:44:33 2003 +++ b/arch/mips/au1000/pb1000/init.c Tue Jul 1 18:44:33 2003 @@ -33,27 +33,39 @@ #include #include #include -#include #include #include #include -extern int prom_argc; -extern char **prom_argv, **prom_envp; +int prom_argc; +char **prom_argv, **prom_envp; extern void __init prom_init_cmdline(void); +extern char *prom_getenv(char *envname); + +const char *get_system_type(void) +{ + return "Alchemy Pb1000"; +} int __init prom_init(int argc, char **argv, char **envp, int *prom_vec) { + unsigned char *memsize_str; + unsigned long memsize; + prom_argc = argc; prom_argv = argv; prom_envp = envp; mips_machgroup = MACH_GROUP_ALCHEMY; - mips_machtype = MACH_PB1000; + mips_machtype = MACH_PB1000; prom_init_cmdline(); - - add_memory_region(1, 64 << 20, BOOT_MEM_RAM); - + memsize_str = prom_getenv("memsize"); + if (!memsize_str) { + memsize = 0x04000000; + } else { + memsize = simple_strtol(memsize_str, NULL, 0); + } + add_memory_region(0, memsize, BOOT_MEM_RAM); return 0; } diff -Nru a/arch/mips/au1000/pb1000/setup.c b/arch/mips/au1000/pb1000/setup.c --- a/arch/mips/au1000/pb1000/setup.c Tue Jul 1 18:44:37 2003 +++ b/arch/mips/au1000/pb1000/setup.c Tue Jul 1 18:44:37 2003 @@ -1,7 +1,7 @@ /* * * BRIEF MODULE DESCRIPTION - * Au1000-based board setup. + * Alchemy Pb1000 board setup. * * Copyright 2000 MontaVista Software Inc. * Author: MontaVista Software, Inc. @@ -31,88 +31,271 @@ #include #include #include +#include #include #include +#include +#include #include +#include #include #include #include #include #include +#include #include +#include -#if defined(CONFIG_AU1000_SERIAL_CONSOLE) -extern void console_setup(char *, int *); +#ifdef CONFIG_USB_OHCI +// Enable the workaround for the OHCI DoneHead +// register corruption problem. +#define CONFIG_AU1000_OHCI_FIX +#endif + +#if defined(CONFIG_AU1X00_SERIAL_CONSOLE) char serial_console[20]; #endif -void (*__wbflush) (void); +#ifdef CONFIG_BLK_DEV_INITRD +extern unsigned long initrd_start, initrd_end; +extern void * __rd_start, * __rd_end; +#endif + +#ifdef CONFIG_BLK_DEV_IDE +extern struct ide_ops std_ide_ops; +extern struct ide_ops *ide_ops; +#endif + extern struct rtc_ops no_rtc_ops; extern char * __init prom_getcmdline(void); -extern void au1000_restart(void); +extern void au1000_restart(char *); extern void au1000_halt(void); extern void au1000_power_off(void); +extern struct resource ioport_resource; +extern struct resource iomem_resource; -struct { - struct resource ram; - struct resource io; - struct resource sram; - struct resource flash; - struct resource boot; - struct resource pcmcia; - struct resource lcd; -} au1000_resources = { - { "RAM", 0, 0x3FFFFFF, IORESOURCE_MEM }, - { "I/O", 0x10000000, 0x119FFFFF }, - { "SRAM", 0x1e000000, 0x1E03FFFF }, - { "System Flash", 0x1F800000, 0x1FBFFFFF }, - { "Boot ROM", 0x1FC00000, 0x1FFFFFFF }, - { "PCMCIA", 0x20000000, 0x27FFFFFF }, - { "LCD", 0x60000000, 0x603FFFFF }, -}; - -void au1000_wbflush(void) -{ - __asm__ volatile ("sync"); -} - -void __init au1000_setup(void) +void __init au1x00_setup(void) { char *argptr; + u32 pin_func, static_cfg0; + u32 sys_freqctrl, sys_clksrc; + u32 prid = read_c0_prid(); argptr = prom_getcmdline(); -#ifdef CONFIG_AU1000_SERIAL_CONSOLE - if ((argptr = strstr(argptr, "console=ttyS0")) == NULL) { + /* Various early Au1000 Errata corrected by this */ + set_c0_config(1<<19); /* Config[OD] */ + +#ifdef CONFIG_AU1X00_SERIAL_CONSOLE + if ((argptr = strstr(argptr, "console=")) == NULL) { argptr = prom_getcmdline(); strcat(argptr, " console=ttyS0,115200"); } -#endif +#endif - //set_cp0_status(ST0_FR,0); rtc_ops = &no_rtc_ops; - __wbflush = au1000_wbflush; _machine_restart = au1000_restart; _machine_halt = au1000_halt; _machine_power_off = au1000_power_off; - /* - * IO/MEM resources. - */ - mips_io_port_base = KSEG1; - ioport_resource.start = au1000_resources.io.start; - ioport_resource.end = au1000_resources.lcd.end; + // IO/MEM resources. + set_io_port_base(0); + ioport_resource.start = 0x10000000; + ioport_resource.end = 0xffffffff; + iomem_resource.start = 0x10000000; + iomem_resource.end = 0xffffffff; #ifdef CONFIG_BLK_DEV_INITRD ROOT_DEV = Root_RAM0; + initrd_start = (unsigned long)&__rd_start; + initrd_end = (unsigned long)&__rd_end; #endif - outl(PC_CNTRL_E0 | PC_CNTRL_EN0 | PC_CNTRL_EN0, PC_COUNTER_CNTRL); - while (inl(PC_COUNTER_CNTRL) & PC_CNTRL_T0S); - outl(0x8000-1, PC0_TRIM); + // set AUX clock to 12MHz * 8 = 96 MHz + au_writel(8, SYS_AUXPLL); + au_writel(0, SYS_PINSTATERD); + udelay(100); + +#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE) +#ifdef CONFIG_USB_OHCI + if ((argptr = strstr(argptr, "usb_ohci=")) == NULL) { + char usb_args[80]; + argptr = prom_getcmdline(); + memset(usb_args, 0, sizeof(usb_args)); + sprintf(usb_args, " usb_ohci=base:0x%x,len:0x%x,irq:%d", + USB_OHCI_BASE, USB_OHCI_LEN, AU1000_USB_HOST_INT); + strcat(argptr, usb_args); + } +#endif - printk("Alchemy Semi PB1000 Board\n"); - printk("Au1000/PB1000 port (C) 2001 MontaVista Software, Inc. (source@mvista.com)\n"); -} + /* zero and disable FREQ2 */ + sys_freqctrl = au_readl(SYS_FREQCTRL0); + sys_freqctrl &= ~0xFFF00000; + au_writel(sys_freqctrl, SYS_FREQCTRL0); + + /* zero and disable USBH/USBD clocks */ + sys_clksrc = au_readl(SYS_CLKSRC); + sys_clksrc &= ~0x00007FE0; + au_writel(sys_clksrc, SYS_CLKSRC); + + sys_freqctrl = au_readl(SYS_FREQCTRL0); + sys_freqctrl &= ~0xFFF00000; + + sys_clksrc = au_readl(SYS_CLKSRC); + sys_clksrc &= ~0x00007FE0; + + switch (prid & 0x000000FF) + { + case 0x00: /* DA */ + case 0x01: /* HA */ + case 0x02: /* HB */ + /* CPU core freq to 48MHz to slow it way down... */ + au_writel(4, SYS_CPUPLL); + + /* + * Setup 48MHz FREQ2 from CPUPLL for USB Host + */ + /* FRDIV2=3 -> div by 8 of 384MHz -> 48MHz */ + sys_freqctrl |= ((3<<22) | (1<<21) | (0<<20)); + au_writel(sys_freqctrl, SYS_FREQCTRL0); + + /* CPU core freq to 384MHz */ + au_writel(0x20, SYS_CPUPLL); + + printk("Au1000: 48MHz OHCI workaround enabled\n"); + break; + + default: /* HC and newer */ + // FREQ2 = aux/2 = 48 MHz + sys_freqctrl |= ((0<<22) | (1<<21) | (1<<20)); + au_writel(sys_freqctrl, SYS_FREQCTRL0); + break; + } + + /* + * Route 48MHz FREQ2 into USB Host and/or Device + */ +#ifdef CONFIG_USB_OHCI + sys_clksrc |= ((4<<12) | (0<<11) | (0<<10)); +#endif +#ifdef CONFIG_AU1X00_USB_DEVICE + sys_clksrc |= ((4<<7) | (0<<6) | (0<<5)); +#endif + au_writel(sys_clksrc, SYS_CLKSRC); +#ifdef CONFIG_USB_OHCI + // enable host controller and wait for reset done + au_writel(0x08, USB_HOST_CONFIG); + udelay(1000); + au_writel(0x0E, USB_HOST_CONFIG); + udelay(1000); + au_readl(USB_HOST_CONFIG); // throw away first read + while (!(au_readl(USB_HOST_CONFIG) & 0x10)) + au_readl(USB_HOST_CONFIG); +#endif + + // configure pins GPIO[14:9] as GPIO + pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8080); + +#ifndef CONFIG_AU1X00_USB_DEVICE + // 2nd USB port is USB host + pin_func |= 0x8000; +#endif + au_writel(pin_func, SYS_PINFUNC); + au_writel(0x2800, SYS_TRIOUTCLR); + au_writel(0x0030, SYS_OUTPUTCLR); +#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE) + + // make gpio 15 an input (for interrupt line) + pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x100); + // we don't need I2S, so make it available for GPIO[31:29] + pin_func |= (1<<5); + au_writel(pin_func, SYS_PINFUNC); + + au_writel(0x8000, SYS_TRIOUTCLR); + +#ifdef CONFIG_FB + conswitchp = &dummy_con; +#endif + + static_cfg0 = au_readl(MEM_STCFG0) & (u32)(~0xc00); + au_writel(static_cfg0, MEM_STCFG0); + + // configure RCE2* for LCD + au_writel(0x00000004, MEM_STCFG2); + + // MEM_STTIME2 + au_writel(0x09000000, MEM_STTIME2); + + // Set 32-bit base address decoding for RCE2* + au_writel(0x10003ff0, MEM_STADDR2); + + // PCI CPLD setup + // expand CE0 to cover PCI + au_writel(0x11803e40, MEM_STADDR1); + + // burst visibility on + au_writel(au_readl(MEM_STCFG0) | 0x1000, MEM_STCFG0); + + au_writel(0x83, MEM_STCFG1); // ewait enabled, flash timing + au_writel(0x33030a10, MEM_STTIME1); // slower timing for FPGA + + /* setup the static bus controller */ + au_writel(0x00000002, MEM_STCFG3); /* type = PCMCIA */ + au_writel(0x280E3D07, MEM_STTIME3); /* 250ns cycle time */ + au_writel(0x10000000, MEM_STADDR3); /* any PCMCIA select */ + +#ifdef CONFIG_FB_E1356 + if ((argptr = strstr(argptr, "video=")) == NULL) { + argptr = prom_getcmdline(); + strcat(argptr, " video=e1356fb:system:pb1000,mmunalign:1"); + } +#endif // CONFIG_FB_E1356 + + +#ifdef CONFIG_PCI + au_writel(0, PCI_BRIDGE_CONFIG); // set extend byte to 0 + au_writel(0, SDRAM_MBAR); // set mbar to 0 + au_writel(0x2, SDRAM_CMD); // enable memory accesses + au_sync_delay(1); +#endif + +#ifndef CONFIG_SERIAL_NONSTANDARD + /* don't touch the default serial console */ + au_writel(0, UART0_ADDR + UART_CLK); +#endif + au_writel(0, UART1_ADDR + UART_CLK); + au_writel(0, UART2_ADDR + UART_CLK); + au_writel(0, UART3_ADDR + UART_CLK); + +#ifdef CONFIG_BLK_DEV_IDE + ide_ops = &std_ide_ops; +#endif + + // setup irda clocks + // aux clock, divide by 2, clock from 2/4 divider + au_writel(au_readl(SYS_CLKSRC) | 0x7, SYS_CLKSRC); + pin_func = au_readl(SYS_PINFUNC) & (u32)(~(1<<2)); // clear IRTXD + au_writel(pin_func, SYS_PINFUNC); + + while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_E0S); + au_writel(SYS_CNTRL_E0 | SYS_CNTRL_EN0, SYS_COUNTER_CNTRL); + au_sync(); + while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T0S); + au_writel(0, SYS_TOYTRIM); + + /* Enable Au1000 BCLK switching - note: sed1356 must not use + * its BCLK (Au1000 LCLK) for any timings */ + switch (prid & 0x000000FF) + { + case 0x00: /* DA */ + case 0x01: /* HA */ + case 0x02: /* HB */ + break; + default: /* HC and newer */ + au_writel(0x00000060, 0xb190003c); + break; + } +} diff -Nru a/arch/mips/au1000/pb1100/Makefile b/arch/mips/au1000/pb1100/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/pb1100/Makefile Tue Jul 1 18:44:40 2003 @@ -0,0 +1,17 @@ +# +# Copyright 2000,2001 MontaVista Software Inc. +# Author: MontaVista Software, Inc. +# ppopov@mvista.com or source@mvista.com +# +# Makefile for the Alchemy Semiconductor Pb1100 board. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +USE_STANDARD_AS_RULE := true + +O_TARGET := pb1100.o + +obj-y := init.o setup.o diff -Nru a/arch/mips/au1000/pb1100/init.c b/arch/mips/au1000/pb1100/init.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/pb1100/init.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,73 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * Pb1100 board setup + * + * Copyright 2002 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int prom_argc; +char **prom_argv, **prom_envp; +extern void __init prom_init_cmdline(void); +extern char *prom_getenv(char *envname); + +const char *get_system_type(void) +{ + return "Alchemy Pb1100"; +} + +int __init prom_init(int argc, char **argv, char **envp, int *prom_vec) +{ + unsigned char *memsize_str; + unsigned long memsize; + + prom_argc = argc; + prom_argv = argv; + prom_envp = envp; + + mips_machgroup = MACH_GROUP_ALCHEMY; + mips_machtype = MACH_PB1100; + + prom_init_cmdline(); + memsize_str = prom_getenv("memsize"); + if (!memsize_str) { + memsize = 0x04000000; + } else { + memsize = simple_strtol(memsize_str, NULL, 0); + } + add_memory_region(0, memsize, BOOT_MEM_RAM); + return 0; +} diff -Nru a/arch/mips/au1000/pb1100/setup.c b/arch/mips/au1000/pb1100/setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/pb1100/setup.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,248 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * Alchemy Pb1100 board setup. + * + * Copyright 2002 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_USB_OHCI +// Enable the workaround for the OHCI DoneHead +// register corruption problem. +#define CONFIG_AU1000_OHCI_FIX +#endif + +#if defined(CONFIG_AU1X00_SERIAL_CONSOLE) +extern void console_setup(char *, int *); +char serial_console[20]; +#endif + +#ifdef CONFIG_BLK_DEV_INITRD +extern unsigned long initrd_start, initrd_end; +extern void * __rd_start, * __rd_end; +#endif + +#ifdef CONFIG_BLK_DEV_IDE +extern struct ide_ops std_ide_ops; +extern struct ide_ops *ide_ops; +#endif + +#ifdef CONFIG_RTC +extern struct rtc_ops pb1500_rtc_ops; +#endif + +extern char * __init prom_getcmdline(void); +extern void au1000_restart(char *); +extern void au1000_halt(void); +extern void au1000_power_off(void); +extern struct resource ioport_resource; +extern struct resource iomem_resource; + + +void __init au1x00_setup(void) +{ + char *argptr; + u32 pin_func, static_cfg0; + u32 sys_freqctrl, sys_clksrc; + + argptr = prom_getcmdline(); + + /* NOTE: The memory map is established by YAMON 2.08+ */ + + /* Various early Au1000 Errata corrected by this */ + set_c0_config(1<<19); /* Config[OD] */ + +#ifdef CONFIG_AU1X00_SERIAL_CONSOLE + if ((argptr = strstr(argptr, "console=")) == NULL) { + argptr = prom_getcmdline(); + strcat(argptr, " console=ttyS0,115200"); + } +#endif + +#ifdef CONFIG_SOUND_AU1X00 + strcat(argptr, " au1000_audio=vra"); + argptr = prom_getcmdline(); +#endif + + _machine_restart = au1000_restart; + _machine_halt = au1000_halt; + _machine_power_off = au1000_power_off; + + // IO/MEM resources. + set_io_port_base(0); + ioport_resource.start = 0x10000000; + ioport_resource.end = 0xffffffff; + iomem_resource.start = 0x10000000; + iomem_resource.end = 0xffffffff; + +#ifdef CONFIG_BLK_DEV_INITRD + ROOT_DEV = Root_RAM0; + initrd_start = (unsigned long)&__rd_start; + initrd_end = (unsigned long)&__rd_end; +#endif + + // set AUX clock to 12MHz * 8 = 96 MHz + au_writel(8, SYS_AUXPLL); + au_writel(0, SYS_PININPUTEN); + udelay(100); + +#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE) +#ifdef CONFIG_USB_OHCI + if ((argptr = strstr(argptr, "usb_ohci=")) == NULL) { + char usb_args[80]; + argptr = prom_getcmdline(); + memset(usb_args, 0, sizeof(usb_args)); + sprintf(usb_args, " usb_ohci=base:0x%x,len:0x%x,irq:%d", + USB_OHCI_BASE, USB_OHCI_LEN, AU1000_USB_HOST_INT); + strcat(argptr, usb_args); + } +#endif + // configure pins GPIO[14:9] as GPIO + pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x80); + + /* zero and disable FREQ2 */ + sys_freqctrl = au_readl(SYS_FREQCTRL0); + sys_freqctrl &= ~0xFFF00000; + au_writel(sys_freqctrl, SYS_FREQCTRL0); + + /* zero and disable USBH/USBD/IrDA clock */ + sys_clksrc = au_readl(SYS_CLKSRC); + sys_clksrc &= ~0x0000001F; + au_writel(sys_clksrc, SYS_CLKSRC); + + sys_freqctrl = au_readl(SYS_FREQCTRL0); + sys_freqctrl &= ~0xFFF00000; + + sys_clksrc = au_readl(SYS_CLKSRC); + sys_clksrc &= ~0x0000001F; + + // FREQ2 = aux/2 = 48 MHz + sys_freqctrl |= ((0<<22) | (1<<21) | (1<<20)); + au_writel(sys_freqctrl, SYS_FREQCTRL0); + + /* + * Route 48MHz FREQ2 into USBH/USBD/IrDA + */ + sys_clksrc |= ((4<<2) | (0<<1) | 0 ); + au_writel(sys_clksrc, SYS_CLKSRC); + + /* setup the static bus controller */ + au_writel(0x00000002, MEM_STCFG3); /* type = PCMCIA */ + au_writel(0x280E3D07, MEM_STTIME3); /* 250ns cycle time */ + au_writel(0x10000000, MEM_STADDR3); /* any PCMCIA select */ + + // get USB Functionality pin state (device vs host drive pins) + pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000); +#ifndef CONFIG_AU1X00_USB_DEVICE + // 2nd USB port is USB host + pin_func |= 0x8000; +#endif + au_writel(pin_func, SYS_PINFUNC); +#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE) + +#ifdef CONFIG_USB_OHCI + // enable host controller and wait for reset done + au_writel(0x08, USB_HOST_CONFIG); + udelay(1000); + au_writel(0x0c, USB_HOST_CONFIG); + udelay(1000); + au_readl(USB_HOST_CONFIG); + while (!(au_readl(USB_HOST_CONFIG) & 0x10)) + ; + au_readl(USB_HOST_CONFIG); +#endif + +#ifdef CONFIG_FB + conswitchp = &dummy_con; +#endif + +#ifdef CONFIG_FB_AU1100 + if ((argptr = strstr(argptr, "video=")) == NULL) { + argptr = prom_getcmdline(); + /* default panel */ + strcat(argptr, " video=au1100fb:panel:Sharp_320x240_16"); + } +#endif + +#ifdef CONFIG_FB_E1356 + if ((argptr = strstr(argptr, "video=")) == NULL) { + argptr = prom_getcmdline(); + strcat(argptr, " video=e1356fb:system:pb1500"); + } +#endif + +#ifndef CONFIG_SERIAL_NONSTANDARD + /* don't touch the default serial console */ + au_writel(0, UART0_ADDR + UART_CLK); +#endif + au_writel(0, UART1_ADDR + UART_CLK); + au_writel(0, UART3_ADDR + UART_CLK); + +#ifdef CONFIG_BLK_DEV_IDE + ide_ops = &std_ide_ops; +#endif + + while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_E0S); + au_writel(SYS_CNTRL_E0 | SYS_CNTRL_EN0, SYS_COUNTER_CNTRL); + au_sync(); + while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T0S); + au_writel(0, SYS_TOYTRIM); + + au_writel(0x00000060, 0xb190003c); + +#ifdef CONFIG_RTC + rtc_ops = &pb1500_rtc_ops; + // Enable the RTC if not already enabled + if (!(readb(0xac000028) & 0x20)) { + writeb(readb(0xac000028) | 0x20, 0xac000028); + au_sync(); + } + // Put the clock in BCD mode + if (readb(0xac00002C) & 0x4) { /* reg B */ + writeb(readb(0xac00002c) & ~0x4, 0xac00002c); + au_sync(); + } +#endif +} diff -Nru a/arch/mips/au1000/pb1500/Makefile b/arch/mips/au1000/pb1500/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/pb1500/Makefile Tue Jul 1 18:44:39 2003 @@ -0,0 +1,13 @@ +# +# Copyright 2000,2001 MontaVista Software Inc. +# Author: MontaVista Software, Inc. +# ppopov@mvista.com or source@mvista.com +# +# Makefile for the Alchemy Semiconductor Pb1500 board. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +lib-y := init.o setup.o diff -Nru a/arch/mips/au1000/pb1500/init.c b/arch/mips/au1000/pb1500/init.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/pb1500/init.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,71 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * PB1500 board setup + * + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int prom_argc; +char **prom_argv, **prom_envp; +extern void __init prom_init_cmdline(void); +extern char *prom_getenv(char *envname); + +const char *get_system_type(void) +{ + return "Alchemy Pb1500"; +} + +int __init prom_init(int argc, char **argv, char **envp, int *prom_vec) +{ + unsigned char *memsize_str; + unsigned long memsize; + + prom_argc = argc; + prom_argv = argv; + prom_envp = envp; + + mips_machgroup = MACH_GROUP_ALCHEMY; + mips_machtype = MACH_PB1500; + + prom_init_cmdline(); + memsize_str = prom_getenv("memsize"); + if (!memsize_str) { + memsize = 0x04000000; + } else { + memsize = simple_strtol(memsize_str, NULL, 0); + } + add_memory_region(0, memsize, BOOT_MEM_RAM); + return 0; +} diff -Nru a/arch/mips/au1000/pb1500/setup.c b/arch/mips/au1000/pb1500/setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/au1000/pb1500/setup.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,293 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * Alchemy Pb1000 board setup. + * + * Copyright 2000 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_USB_OHCI +// Enable the workaround for the OHCI DoneHead +// register corruption problem. +#define CONFIG_AU1000_OHCI_FIX +#endif + +#ifdef CONFIG_BLK_DEV_INITRD +extern unsigned long initrd_start, initrd_end; +extern void * __rd_start, * __rd_end; +#endif + +#ifdef CONFIG_BLK_DEV_IDE +extern struct ide_ops std_ide_ops; +extern struct ide_ops *ide_ops; +#endif + +#ifdef CONFIG_RTC +extern struct rtc_ops pb1500_rtc_ops; +#endif + +extern char * __init prom_getcmdline(void); +extern void __init au1x_time_init(void); +extern void __init au1x_timer_setup(struct irqaction *irq); +extern void au1000_restart(char *); +extern void au1000_halt(void); +extern void au1000_power_off(void); +extern struct resource ioport_resource; +extern struct resource iomem_resource; +#ifdef CONFIG_64BIT_PHYS_ADDR +extern phys_t (*fixup_bigphys_addr)(phys_t phys_addr, phys_t size); +static phys_t pb1500_fixup_bigphys_addr(phys_t phys_addr, phys_t size); +#endif + + +void __init au1x00_setup(void) +{ + char *argptr; + u32 pin_func, static_cfg0; + u32 sys_freqctrl, sys_clksrc; + + argptr = prom_getcmdline(); + + /* NOTE: The memory map is established by YAMON 2.08+ */ + + /* Various early Au1500 Errata corrected by this */ + set_c0_config(1<<19); /* Config[OD] */ + + board_time_init = au1x_time_init; + board_timer_setup = au1x_timer_setup; + +#ifdef CONFIG_SERIAL_AU1X00_CONSOLE + if ((argptr = strstr(argptr, "console=")) == NULL) { + argptr = prom_getcmdline(); + strcat(argptr, " console=ttyS0,115200"); + } +#endif + +#ifdef CONFIG_SOUND_AU1X00 + strcat(argptr, " au1000_audio=vra"); + argptr = prom_getcmdline(); +#endif + + _machine_restart = au1000_restart; + _machine_halt = au1000_halt; + _machine_power_off = au1000_power_off; +#ifdef CONFIG_64BIT_PHYS_ADDR + fixup_bigphys_addr = pb1500_fixup_bigphys_addr; +#endif + + // IO/MEM resources. + set_io_port_base(0); + ioport_resource.start = 0x00000000; + ioport_resource.end = 0xffffffff; + iomem_resource.start = 0x10000000; + iomem_resource.end = 0xffffffff; + +#ifdef CONFIG_BLK_DEV_INITRD + ROOT_DEV = Root_RAM0; + initrd_start = (unsigned long)&__rd_start; + initrd_end = (unsigned long)&__rd_end; +#endif + + // set AUX clock to 12MHz * 8 = 96 MHz + au_writel(8, SYS_AUXPLL); + au_writel(0, SYS_PINSTATERD); + udelay(100); + +#if defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE) +#ifdef CONFIG_USB_OHCI + if ((argptr = strstr(argptr, "usb_ohci=")) == NULL) { + char usb_args[80]; + argptr = prom_getcmdline(); + memset(usb_args, 0, sizeof(usb_args)); + sprintf(usb_args, " usb_ohci=base:0x%x,len:0x%x,irq:%d", + USB_OHCI_BASE, USB_OHCI_LEN, AU1000_USB_HOST_INT); + strcat(argptr, usb_args); + } +#endif + + /* GPIO201 is input for PCMCIA card detect */ + /* GPIO203 is input for PCMCIA interrupt request */ + au_writel(au_readl(GPIO2_DIR) & (u32)(~((1<<1)|(1<<3))), GPIO2_DIR); + + /* zero and disable FREQ2 */ + sys_freqctrl = au_readl(SYS_FREQCTRL0); + sys_freqctrl &= ~0xFFF00000; + au_writel(sys_freqctrl, SYS_FREQCTRL0); + + /* zero and disable USBH/USBD clocks */ + sys_clksrc = au_readl(SYS_CLKSRC); + sys_clksrc &= ~0x00007FE0; + au_writel(sys_clksrc, SYS_CLKSRC); + + sys_freqctrl = au_readl(SYS_FREQCTRL0); + sys_freqctrl &= ~0xFFF00000; + + sys_clksrc = au_readl(SYS_CLKSRC); + sys_clksrc &= ~0x00007FE0; + + // FREQ2 = aux/2 = 48 MHz + sys_freqctrl |= ((0<<22) | (1<<21) | (1<<20)); + au_writel(sys_freqctrl, SYS_FREQCTRL0); + + /* + * Route 48MHz FREQ2 into USB Host and/or Device + */ +#ifdef CONFIG_USB_OHCI + sys_clksrc |= ((4<<12) | (0<<11) | (0<<10)); +#endif +#ifdef CONFIG_AU1X00_USB_DEVICE + sys_clksrc |= ((4<<7) | (0<<6) | (0<<5)); +#endif + au_writel(sys_clksrc, SYS_CLKSRC); + + + pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8000); +#ifndef CONFIG_AU1X00_USB_DEVICE + // 2nd USB port is USB host + pin_func |= 0x8000; +#endif + au_writel(pin_func, SYS_PINFUNC); +#endif // defined (CONFIG_USB_OHCI) || defined (CONFIG_AU1X00_USB_DEVICE) + + +#ifdef CONFIG_USB_OHCI + // enable host controller and wait for reset done + au_writel(0x08, USB_HOST_CONFIG); + udelay(1000); + au_writel(0x0c, USB_HOST_CONFIG); + udelay(1000); + au_readl(USB_HOST_CONFIG); + while (!(au_readl(USB_HOST_CONFIG) & 0x10)) + ; + au_readl(USB_HOST_CONFIG); +#endif + +#ifdef CONFIG_FB + conswitchp = &dummy_con; +#endif + +#ifdef CONFIG_FB_E1356 + if ((argptr = strstr(argptr, "video=")) == NULL) { + argptr = prom_getcmdline(); + strcat(argptr, " video=e1356fb:system:pb1500"); + } +#elif defined (CONFIG_FB_XPERT98) + if ((argptr = strstr(argptr, "video=")) == NULL) { + argptr = prom_getcmdline(); + strcat(argptr, " video=atyfb:1024x768-8@70"); + } +#endif // CONFIG_FB_E1356 + +#ifndef CONFIG_SERIAL_AU1X00_CONSOLE + /* don't touch the default serial console */ + au_writel(0, UART0_ADDR + UART_CLK); +#endif + au_writel(0, UART3_ADDR + UART_CLK); + +#ifdef CONFIG_BLK_DEV_IDE + ide_ops = &std_ide_ops; +#endif + +#ifdef CONFIG_PCI + // Setup PCI bus controller + au_writel(0, Au1500_PCI_CMEM); + au_writel(0x00003fff, Au1500_CFG_BASE); +#if defined(__MIPSEB__) + au_writel(0xf | (2<<6) | (1<<4), Au1500_PCI_CFG); +#else + au_writel(0xf, Au1500_PCI_CFG); +#endif + au_writel(0xf0000000, Au1500_PCI_MWMASK_DEV); + au_writel(0, Au1500_PCI_MWBASE_REV_CCL); + au_writel(0x02a00356, Au1500_PCI_STATCMD); + au_writel(0x00003c04, Au1500_PCI_HDRTYPE); + au_writel(0x00000008, Au1500_PCI_MBAR); + au_sync(); +#endif + + while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_E0S); + au_writel(SYS_CNTRL_E0 | SYS_CNTRL_EN0, SYS_COUNTER_CNTRL); + au_sync(); + while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T0S); + au_writel(0, SYS_TOYTRIM); + + /* Enable BCLK switching */ + au_writel(0x00000060, 0xb190003c); + +#ifdef CONFIG_RTC + rtc_ops = &pb1500_rtc_ops; + // Enable the RTC if not already enabled + if (!(au_readl(0xac000028) & 0x20)) { + printk("enabling clock ...\n"); + au_writel((au_readl(0xac000028) | 0x20), 0xac000028); + } + // Put the clock in BCD mode + if (readl(0xac00002C) & 0x4) { /* reg B */ + au_writel(au_readl(0xac00002c) & ~0x4, 0xac00002c); + au_sync(); + } +#endif +} + +#ifdef CONFIG_64BIT_PHYS_ADDR +static phys_t pb1500_fixup_bigphys_addr(phys_t phys_addr, + phys_t size) +{ + u32 pci_start = (u32)Au1500_PCI_MEM_START; + u32 pci_end = (u32)Au1500_PCI_MEM_END; + + /* Don't fixup 36 bit addresses */ + if ((phys_addr >> 32) != 0) return phys_addr; + + /* check for pci memory window */ + if ((phys_addr >= pci_start) && ((phys_addr + size) < pci_end)) { + return (phys_t)((phys_addr - pci_start) + + Au1500_PCI_MEM_START); + } + else + return phys_addr; +} +#endif diff -Nru a/arch/mips/baget/Makefile b/arch/mips/baget/Makefile --- a/arch/mips/baget/Makefile Tue Jul 1 18:44:39 2003 +++ b/arch/mips/baget/Makefile Tue Jul 1 18:44:39 2003 @@ -4,10 +4,11 @@ # obj-y := baget.o print.o setup.o time.o irq.o bagetIRQ.o \ - reset.o wbflush.o -obj-$(CONFIG_SERIAL) += vacserial.o + reset.o obj-$(CONFIG_VAC_RTC) += vacrtc.o +EXTRA_AFLAGS := $(CFLAGS) + bagetIRQ.o : bagetIRQ.S $(CC) $(CFLAGS) -c -o $@ $< @@ -28,7 +29,7 @@ dummy.o: dummy.c image.bin ramdisk.bin $(CC) $(CFLAGS) -c -o $@ $< $(OBJCOPY) --add-section=.vmlinux=image.bin \ - --add-section=.ramdisk=ramdisk.bin $@ + --add-section=.ramdisk=ramdisk.bin $@ balo.h: image $(NM) $< | awk ' \ @@ -39,13 +40,13 @@ /balo_ramdisk_size/ { printf "#define RAMDISK_SIZE 0x%s\n", $$1 } \ ' > $@ balo.o: balo.c balo.h - $(CC) $(CFLAGS) -c $< + $(CC) $(CFLAGS) -c $< balo_supp.o: balo_supp.S $(CC) $(CFLAGS) -c $< balo: balo.o dummy.o balo_supp.o print.o - $(LD) $(LDFLAGS) -T ld.script.balo -o $@ $^ + $(LD) $(LDFLAGS) -T ld.script.balo -o $@ $^ clean: rm -f balo balo.h dummy.c image image.bin diff -Nru a/arch/mips/baget/baget.c b/arch/mips/baget/baget.c --- a/arch/mips/baget/baget.c Tue Jul 1 18:44:36 2003 +++ b/arch/mips/baget/baget.c Tue Jul 1 18:44:36 2003 @@ -1,5 +1,4 @@ -/* $Id: baget.c,v 1.1 1999/01/17 03:49:37 ralf Exp $ - * +/* * baget.c: Baget low level stuff * * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov @@ -21,7 +20,7 @@ * Following code is based on routines from 'mm/vmalloc.c' * Additional parameters ioaddr is needed to iterate across real I/O address. */ -static inline int alloc_area_pte(pte_t * pte, unsigned long address, +static inline int alloc_area_pte(pte_t * pte, unsigned long address, unsigned long size, unsigned long ioaddr) { unsigned long end; @@ -36,7 +35,7 @@ printk("kseg2_alloc_io: page already exists\n"); /* * For MIPS looks pretty to have transparent mapping - * for KSEG2 areas -- user can't access one, and no + * for KSEG2 areas -- user can't access one, and no * problems with virtual <--> physical translation. */ page = ioaddr & PAGE_MASK; @@ -50,7 +49,7 @@ return 0; } -static inline int alloc_area_pmd(pmd_t * pmd, unsigned long address, +static inline int alloc_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size, unsigned long ioaddr) { unsigned long end; diff -Nru a/arch/mips/baget/bagetIRQ.S b/arch/mips/baget/bagetIRQ.S --- a/arch/mips/baget/bagetIRQ.S Tue Jul 1 18:44:37 2003 +++ b/arch/mips/baget/bagetIRQ.S Tue Jul 1 18:44:37 2003 @@ -1,9 +1,8 @@ -/* $Id: bagetIRQ.S,v 1.1 1999/01/17 03:49:37 ralf Exp $ +/* * bagetIRQ.S: Interrupt exception dispatch code for Baget/MIPS * * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov */ - #include #include #include @@ -25,28 +24,28 @@ .set push .set noreorder jal a1 - .set pop - move a0, sp + .set pop + move a0, sp la a1, ret_from_irq jr a1 END(bagetIRQ) - + #define DBE_HANDLER 0x1C - + NESTED(try_read, PT_SIZE, sp) mfc0 t3, CP0_STATUS # save flags and CLI # disable interrupts li t0, KSEG2 - sltu t1, t0, a0 # Is it KSEG2 address ? - beqz t1, mapped # No - already mapped ! - - move t0, a0 + sltu t1, t0, a0 # Is it KSEG2 address ? + beqz t1, mapped # No - already mapped ! + + move t0, a0 ori t0, 0xfff xori t0, 0xfff # round address to page - ori t1, t0, 0xf00 # prepare EntryLo (N,V,D,G) + ori t1, t0, 0xf00 # prepare EntryLo (N,V,D,G) mfc0 t2, CP0_ENTRYHI # save ASID value mtc0 zero, CP0_INDEX @@ -57,15 +56,15 @@ tlbwi # ... and write ones nop nop - mtc0 t2, CP0_ENTRYHI - -mapped: + mtc0 t2, CP0_ENTRYHI + +mapped: la t0, exception_handlers lw t1, DBE_HANDLER(t0) # save real handler - la t2, dbe_handler + la t2, dbe_handler sw t2, DBE_HANDLER(t0) # set temporary local handler li v0, -1 # default (failure) value - + li t2, 1 beq t2, a1, 1f li t2, 2 @@ -81,13 +80,13 @@ b out 4: lw v0, (a0) # word - -out: + +out: sw t1, DBE_HANDLER(t0) # restore real handler mtc0 t3, CP0_STATUS # restore CPU flags - jr ra - -dbe_handler: + jr ra + +dbe_handler: li v0, -1 # mark our failure .set push .set noreorder diff -Nru a/arch/mips/baget/balo.c b/arch/mips/baget/balo.c --- a/arch/mips/baget/balo.c Tue Jul 1 18:44:36 2003 +++ b/arch/mips/baget/balo.c Tue Jul 1 18:44:36 2003 @@ -1,9 +1,7 @@ -/* $Id$ - * +/* * balo.c: BAget LOader * * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov - * */ #include #include @@ -18,7 +16,7 @@ static void mem_move (long *to, long *from, long size) { - while (size > 0) { + while (size > 0) { *to++ = *from++; size -= sizeof(long); } @@ -42,27 +40,29 @@ static __inline__ void reset_and_jump(int start, int mem_upper) { + unsigned long tmp; + __asm__ __volatile__( ".set\tnoreorder\n\t" ".set\tnoat\n\t" - "mfc0\t$1,$12\n\t" + "mfc0\t$1, $12\n\t" "nop\n\t" "nop\n\t" "nop\n\t" - "ori\t$1,$1,0xff00\n\t" - "xori\t$1,$1,0xff00\n\t" - "mtc0\t$1,$12\n\t" + "ori\t$1, $1, 0xff00\n\t" + "xori\t$1, $1, 0xff00\n\t" + "mtc0\t$1, $12\n\t" "nop\n\t" "nop\n\t" "nop\n\t" - "move\t$4,%1\n\t" - "jr\t%0\n\t" + "move\t%0, %2\n\t" + "jr\t%1\n\t" "nop\n\t" ".set\tat\n\t" - ".set\treorder" - : /* no outputs */ - :"Ir" (start), "Ir" (mem_upper) - :"$1", "$4", "memory"); + ".set\treorder" + : "=&r" (tmp) + : "Ir" (start), "Ir" (mem_upper) + : "memory"); } static void start_kernel(void) @@ -71,7 +71,7 @@ extern char _ramdisk_start, _ramdisk_end; outs( "Relocating Linux... " ); - mem_move((long*)KSEG0, (long*)&_vmlinux_start, + mem_move((long*)KSEG0, (long*)&_vmlinux_start, &_vmlinux_end-&_vmlinux_start); outs("done.\n"); @@ -86,7 +86,7 @@ outs("done.\n"); } - { + { extern void flush_cache_low(int isize, int dsize); flush_cache_low(256*1024,256*1024); } @@ -102,10 +102,10 @@ balo_state = MEM_PROBE; outs("RAM: <"); while(mem_limit < mem_limit_dbe) { - if (can_write(mem_limit) && *mem_limit != 0) + if (can_write(mem_limit) && *mem_limit != 0) break; /* cycle found */ outc('.'); - if (can_write(mem_limit)) + if (can_write(mem_limit)) *mem_limit = -1; /* mark */ mem_limit += 0x40000; } @@ -124,7 +124,7 @@ } void int_handler(struct pt_regs *regs) -{ +{ switch (balo_state) { case BALO_INIT: balo_printf("\nBALO: trap in balo itself.\n"); @@ -162,7 +162,7 @@ while(1) { *mem_limit_dbe; - if (can_write(mem_limit_dbe)) + if (can_write(mem_limit_dbe)) *mem_limit_dbe = 0; mem_limit_dbe += 0x40000; /* +1M */ @@ -174,7 +174,7 @@ { extern void except_vec3_generic(void); - cli(); + cli(); outs(banner); memcpy((void *)(KSEG0 + 0x80), &except_vec3_generic, 0x80); mem_init(); diff -Nru a/arch/mips/baget/balo_supp.S b/arch/mips/baget/balo_supp.S --- a/arch/mips/baget/balo_supp.S Tue Jul 1 18:44:35 2003 +++ b/arch/mips/baget/balo_supp.S Tue Jul 1 18:44:35 2003 @@ -1,18 +1,17 @@ -/* $Id: balo_supp.S,v 1.1 1999/01/17 03:49:38 ralf Exp $ +/* * balo_supp.S: BAget Loader supplement * * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov */ - #include #include #include #include #include - + .text .set mips1 - + /* General exception vector. */ NESTED(except_vec3_generic, 0, sp) .set noat @@ -21,7 +20,7 @@ END(except_vec3_generic) NESTED(except_vec3_generic_code, 0, sp) - SAVE_ALL + SAVE_ALL mfc0 k1, CP0_CAUSE la k0, int_cause sw k1, (k0) @@ -34,7 +33,7 @@ la k0, badvaddr sw k1, (k0) - la k0, int_handler + la k0, int_handler .set noreorder jal k0 .set reorder @@ -48,7 +47,7 @@ .set at .set macro .set noreorder - + move t1, a0 # ISIZE move t2, a1 # DSIZE @@ -89,7 +88,7 @@ sb zero, -8(t0) bne t0, t1, 1b sb zero, -4(t0) - + la v0, 1f or v0, KSEG1 j v0 # Run uncached diff -Nru a/arch/mips/baget/irq.c b/arch/mips/baget/irq.c --- a/arch/mips/baget/irq.c Tue Jul 1 18:44:36 2003 +++ b/arch/mips/baget/irq.c Tue Jul 1 18:44:36 2003 @@ -17,7 +17,6 @@ #include #include #include -#include #include #include @@ -28,24 +27,24 @@ #include -unsigned long spurious_count = 0; +volatile unsigned long irq_err_count; /* * This table is a correspondence between IRQ numbers and CPU PILs */ - -static int irq_to_pil_map[BAGET_IRQ_NR] = { + +static int irq_to_pil_map[BAGET_IRQ_NR] = { 7/*fixme: dma_err -1*/,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 0x00 - 0x0f */ -1,-1,-1,-1, 3,-1,-1,-1, 2, 2, 2,-1, 3,-1,-1,3/*fixme: lance*/, /* 0x10 - 0x1f */ -1,-1,-1,-1,-1,-1, 5,-1,-1,-1,-1,-1, 7,-1,-1,-1, /* 0x20 - 0x2f */ -1, 3, 2/*fixme systimer:3*/, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 /* 0x30 - 0x3f */ }; -static inline int irq_to_pil(int irq_nr) +static inline int irq_to_pil(int irq_nr) { int pil = -1; - if (irq_nr >= BAGET_IRQ_NR) + if (irq_nr >= BAGET_IRQ_NR) baget_printk("irq_to_pil: too large irq_nr = 0x%x\n", irq_nr); else { pil = irq_to_pil_map[irq_nr]; @@ -60,13 +59,13 @@ static inline void modify_cp0_intmask(unsigned clr_mask, unsigned set_mask) { - unsigned long status = read_32bit_cp0_register(CP0_STATUS); + unsigned long status = read_c0_status(); status &= ~((clr_mask & 0xFF) << 8); status |= (set_mask & 0xFF) << 8; - write_32bit_cp0_register(CP0_STATUS, status); + write_c0_status(status); } -/* +/* * These two functions may be used for unconditional IRQ * masking via their PIL protection. */ @@ -92,26 +91,26 @@ static volatile unsigned int pil_in_use[BAGET_PIL_NR] = { 0, }; -void mask_irq_count(int irq_nr) +void mask_irq_count(int irq_nr) { unsigned long flags; int pil = irq_to_pil(irq_nr); - - save_and_cli(flags); + + local_irq_save(flags); if (!--pil_in_use[pil]) mask_irq(irq_nr); - restore_flags(flags); + local_irq_restore(flags); } -void unmask_irq_count(int irq_nr) +void unmask_irq_count(int irq_nr) { unsigned long flags; int pil = irq_to_pil(irq_nr); - - save_and_cli(flags); + + local_irq_save(flags); if (!pil_in_use[pil]++) unmask_irq(irq_nr); - restore_flags(flags); + local_irq_restore(flags); } /* @@ -122,18 +121,18 @@ { unsigned long flags; - save_and_cli(flags); + local_irq_save(flags); mask_irq(irq_nr); - restore_flags(flags); + local_irq_restore(flags); } void enable_irq(unsigned int irq_nr) { unsigned long flags; - save_and_cli(flags); + local_irq_save(flags); unmask_irq(irq_nr); - restore_flags(flags); + local_irq_restore(flags); } /* @@ -142,31 +141,31 @@ */ static struct irqaction *irq_action[BAGET_IRQ_NR] = { NULL, }; -int show_interrupts(struct seq_file *p, void *v) +int get_irq_list(char *buf) { - int i; + int i, len = 0; struct irqaction * action; unsigned long flags; for (i = 0 ; i < BAGET_IRQ_NR ; i++) { local_irq_save(flags); action = irq_action[i]; - if (!action) - goto skip; - seq_printf(p, "%2d: %8d %c %s", + if (!action) + gotos skip; + len += sprintf(buf+len, "%2d: %8d %c %s", i, kstat_cpu(0).irqs[i], (action->flags & SA_INTERRUPT) ? '+' : ' ', action->name); for (action=action->next; action; action = action->next) { - seq_printf(p, ",%s %s", + len += sprintf(buf+len, ",%s %s", (action->flags & SA_INTERRUPT) ? " +" : "", action->name); } - seq_putc(p, '\n'); + len += sprintf(buf+len, "\n"); skip: local_irq_restore(flags); } - return 0; + return len; } @@ -183,10 +182,10 @@ int do_random, cpu; cpu = smp_processor_id(); - irq_enter(cpu, irq); - kstat_cpu(cpu).irqs[irq]++; + irq_enter(); + kstat_cpus(cpu)[irq]++; - mask_irq(irq); + mask_irq(irq); action = *(irq + irq_action); if (action) { if (!(action->flags & SA_INTERRUPT)) @@ -205,7 +204,7 @@ printk("do_IRQ: Unregistered IRQ (0x%X) occurred\n", irq); } unmask_irq(irq); - irq_exit(cpu, irq); + irq_exit(); /* unmasking and bottom half handling is done magically for us. */ } @@ -213,14 +212,14 @@ /* * What to do in case of 'no VIC register available' for current interrupt */ -static void vic_reg_error(unsigned long address, unsigned char active_pils) +static void vic_reg_error(unsigned long address, unsigned char active_pils) { printk("\nNo VIC register found: reg=%08lx active_pils=%02x\n" - "Current interrupt mask from CP0_CAUSE: %02x\n", - address, 0xff & active_pils, - 0xff & (read_32bit_cp0_register(CP0_CAUSE)>>8)); + "Current interrupt mask from CP0_CAUSE: %02x\n", + address, 0xff & active_pils, + 0xff & (read_c0_cause()>>8)); { int i; for (i=0; i<10000; i++) udelay(1000); } -} +} static char baget_fpu_irq = BAGET_FPU_IRQ; #define BAGET_INT_FPU {(unsigned long)&baget_fpu_irq, 1} @@ -230,27 +229,27 @@ */ asmlinkage void baget_interrupt(struct pt_regs *regs) { - static struct baget_int_reg int_reg[BAGET_PIL_NR] = { + static struct baget_int_reg int_reg[BAGET_PIL_NR] = { BAGET_INT_NONE, BAGET_INT_NONE, BAGET_INT0_ACK, BAGET_INT1_ACK, - BAGET_INT_NONE, BAGET_INT_FPU, BAGET_INT_NONE, BAGET_INT5_ACK + BAGET_INT_NONE, BAGET_INT_FPU, BAGET_INT_NONE, BAGET_INT5_ACK }; unsigned char active_pils; - while ((active_pils = read_32bit_cp0_register(CP0_CAUSE)>>8)) { + while ((active_pils = read_c0_cause()>>8)) { int pil; struct baget_int_reg* reg; for (pil = 0; pil < BAGET_PIL_NR; pil++) { if (!(active_pils & (1<address) { extern int try_read(unsigned long,int); int irq = try_read(reg->address, reg->size); - if (irq != -1) + if (irq != -1) do_IRQ(BAGET_IRQ_MASK(irq), regs); - else + else vic_reg_error(reg->address, active_pils); } else { printk("baget_interrupt: unknown interrupt " @@ -291,9 +290,9 @@ if (new->flags & SA_SAMPLE_RANDOM) rand_initialize_irq(irq); - save_and_cli(flags); + local_irq_save(flags); *p = new; - restore_flags(flags); + local_irq_restore(flags); if (!shared) { unmask_irq_count(irq); @@ -302,9 +301,9 @@ return 0; } -int request_irq(unsigned int irq, +int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, + unsigned long irqflags, const char * devname, void *dev_id) { @@ -315,12 +314,12 @@ return -EINVAL; if (!handler) return -EINVAL; - if (irq_to_pil_map[irq] < 0) + if (irq_to_pil_map[irq] < 0) return -EINVAL; action = (struct irqaction *) kmalloc(sizeof(struct irqaction), GFP_KERNEL); - if (!action) + if (!action) return -ENOMEM; action->handler = handler; @@ -337,13 +336,13 @@ return retval; } - + void free_irq(unsigned int irq, void *dev_id) { struct irqaction * action, **p; unsigned long flags; - if (irq >= BAGET_IRQ_NR) + if (irq >= BAGET_IRQ_NR) printk("Trying to free IRQ%d\n",irq); for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) { @@ -351,11 +350,11 @@ continue; /* Found it - now free it */ - save_and_cli(flags); + local_irq_save(flags); *p = action->next; if (!irq[irq_action]) unmask_irq_count(irq); - restore_flags(flags); + local_irq_restore(flags); kfree(action); return; } @@ -380,7 +379,7 @@ *(volatile char*) BAGET_WRERR_ACK = 0; } -static struct irqaction irq0 = +static struct irqaction irq0 = { write_err_interrupt, SA_INTERRUPT, 0, "bus write error", NULL, NULL}; void __init init_IRQ(void) @@ -393,6 +392,6 @@ /* Enable interrupts for pils 2 and 3 (lines 0 and 1) */ modify_cp0_intmask(0, (1<<2)|(1<<3)); - if (setup_baget_irq(0, &irq0) < 0) + if (setup_baget_irq(0, &irq0) < 0) printk("init_IRQ: unable to register write_err irq\n"); } diff -Nru a/arch/mips/baget/ld.script.balo b/arch/mips/baget/ld.script.balo --- a/arch/mips/baget/ld.script.balo Tue Jul 1 18:44:31 2003 +++ b/arch/mips/baget/ld.script.balo Tue Jul 1 18:44:31 2003 @@ -1,4 +1,4 @@ -OUTPUT_FORMAT("elf32-bigmips") +OUTPUT_FORMAT("elf32-tradbigmips") OUTPUT_ARCH(mips) ENTRY(balo_entry) SECTIONS @@ -42,13 +42,13 @@ /* Startup code */ . = ALIGN(4096); __init_begin = .; - *(.text.init) - *(.data.init) + *(.text.init) + *(.data.init) . = ALIGN(4096); /* Align double page for init_task_union */ __init_end = .; - *(.fini) - *(.reginfo) + *(.fini) + *(.reginfo) /* Adjust the address for the data segment. We want to adjust up to the same address within the page on the next page up. It would be more correct to do this: @@ -68,18 +68,18 @@ *(.data) CONSTRUCTORS - *(.data1) + *(.data1) _gp = . + 0x8000; - *(.lit8) - *(.lit4) - *(.ctors) - *(.dtors) - *(.got.plt) *(.got) - *(.dynamic) + *(.lit8) + *(.lit4) + *(.ctors) + *(.dtors) + *(.got.plt) *(.got) + *(.dynamic) /* We want the small data sections together, so single-instruction offsets can access them all, and initialized data all before uninitialized, so we can shorten the on-disk segment size. */ - *(.sdata) + *(.sdata) _edata = .; PROVIDE (edata = .); @@ -96,21 +96,21 @@ /* These are needed for ELF backends which have not yet been converted to the new style linker. */ - *(.stab) - *(.stabstr) + *(.stab) + *(.stabstr) /* DWARF debug sections. Symbols in the .debug DWARF section are relative to the beginning of the section so we begin .debug at 0. It's not clear yet what needs to happen for the others. */ - *(.debug) - *(.debug_srcinfo) - *(.debug_aranges) - *(.debug_pubnames) - *(.debug_sfnames) - *(.line) + *(.debug) + *(.debug_srcinfo) + *(.debug_aranges) + *(.debug_pubnames) + *(.debug_sfnames) + *(.line) /* These must appear regardless of . */ - *(.gptab.data) *(.gptab.sdata) - *(.gptab.bss) *(.gptab.sbss) + *(.gptab.data) *(.gptab.sdata) + *(.gptab.bss) *(.gptab.sbss) _vmlinux_start = .; *(.vmlinux) diff -Nru a/arch/mips/baget/print.c b/arch/mips/baget/print.c --- a/arch/mips/baget/print.c Tue Jul 1 18:44:35 2003 +++ b/arch/mips/baget/print.c Tue Jul 1 18:44:35 2003 @@ -1,9 +1,7 @@ -/* $Id: print.c,v 1.1 1999/01/17 03:49:38 ralf Exp $ - * +/* * print.c: Simple print fascility * * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov - * */ #include #include @@ -16,7 +14,7 @@ */ // #define BAGET_PRINTK -/* +/* * This function is same for BALO and Linux baget_printk, * and normally prints characted to second (UART A) console. */ @@ -27,7 +25,7 @@ { int i; vac_outb(c, VAC_UART_B_TX); - for (i=0; i<10000; i++) + for (i=0; i<10000; i++) delay(); } @@ -38,7 +36,7 @@ outc_low(c); } -void outs(char *s) +void outs(char *s) { while(*s) outc(*s++); } @@ -79,7 +77,7 @@ void __init balo_printf( char *f, ... ) { int *arg = (int*)&f + 1; - char c; + char c; int format = 0; while((c = *f++) != 0) { @@ -112,7 +110,7 @@ } void __init balo_hungup(void) -{ +{ outs("Hunging up.\n"); - while(1); + while(1); } diff -Nru a/arch/mips/baget/prom/init.c b/arch/mips/baget/prom/init.c --- a/arch/mips/baget/prom/init.c Tue Jul 1 18:44:34 2003 +++ b/arch/mips/baget/prom/init.c Tue Jul 1 18:44:34 2003 @@ -1,13 +1,19 @@ /* * init.c: PROM library initialisation code. * - * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov + * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov */ #include #include #include -char arcs_cmdline[COMMAND_LINE_SIZE]; +char arcs_cmdline[CL_SIZE]; + +const char *get_system_type(void) +{ + /* Should probably return one of "BT23-201", "BT23-202" */ + return "Baget"; +} void __init prom_init(unsigned int mem_upper) { diff -Nru a/arch/mips/baget/setup.c b/arch/mips/baget/setup.c --- a/arch/mips/baget/setup.c Tue Jul 1 18:44:31 2003 +++ b/arch/mips/baget/setup.c Tue Jul 1 18:44:31 2003 @@ -1,9 +1,7 @@ -/* $Id: setup.c,v 1.4 1999/10/09 00:00:57 ralf Exp $ - * +/* * setup.c: Baget/MIPS specific setup, including init of the feature struct. * * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov - * */ #include #include @@ -17,9 +15,9 @@ long int vac_memory_upper; #define CACHEABLE_STR(val) ((val) ? "not cached" : "cached") - + static void __init vac_show(void) -{ +{ int i; unsigned short val, decode = vac_inw(VAC_DECODE_CTRL); unsigned short a24_base = vac_inw(VAC_A24_BASE); @@ -38,7 +36,7 @@ VAC_IOSEL3_CTRL, VAC_IOSEL4_CTRL, VAC_IOSEL5_CTRL }; - + printk("[DSACKi %s, DRAMCS%s qualified, boundary%s qualified%s]\n", (decode & VAC_DECODE_DSACKI) ? "on" : "off", (decode & VAC_DECODE_QFY_DRAMCS) ? "" : " not", @@ -72,24 +70,24 @@ VAC_ICFSEL_MODULE_VAL(vac_inw(VAC_ICFSEL_BASE)))<<4, (decode & VAC_DECODE_QFY_ICFSEL) ? "qualified" : ""); - + printk("region0 at 00000000 (%dMB)\t[dram, %s, delay %d cpuclk" ", cached]\n", (vac_inw(VAC_DRAM_MASK)+1)>>4, (decode & VAC_DECODE_DSACK) ? "D32" : "3state", VAC_DECODE_CPUCLK_VAL(decode)); - + for (i = 0; i < sizeof(regs)/sizeof(regs[0]); i++) { - unsigned long from = + unsigned long from = ((unsigned long)vac_inw(bndr[i]))<<16; - unsigned long to = + unsigned long to = ((unsigned long) - ((i+1 == sizeof(bndr)/sizeof(bndr[0])) ? + ((i+1 == sizeof(bndr)/sizeof(bndr[0])) ? 0xff00 : vac_inw(bndr[i+1])))<<16; - - + + val = vac_inw(regs[i]); - printk("region%d at %08lx (%dMB)\t[%s %s/%s, %s]\n", + printk("region%d at %08lx (%dMB)\t[%s %s/%s, %s]\n", i+1, from, (unsigned int)((to - from) >> 20), @@ -97,13 +95,13 @@ asiz[VAC_REG_ASIZ_VAL(val)], ((val & VAC_REG_WORD) ? "D16" : "D32"), CACHEABLE_STR(val&VAC_A24_A24_CACHINH)); - + if (a24_addr >= from && a24_addr < to) printk("\ta24 at %08lx (%dMB)\t[vme, A24/%s, %s]\n", a24_addr, min((unsigned int)(a24_addr - from)>>20, 32U), (a24_base & VAC_A24_DATAPATH) ? "user" : - ((a24_base & VAC_A24_D32_ENABLE) ? + ((a24_base & VAC_A24_D32_ENABLE) ? "D32" : "D16"), CACHEABLE_STR(a24_base & VAC_A24_A24_CACHINH)); } @@ -123,7 +121,7 @@ (VAC_CTRL_DELAY_IOWR_VAL(val)&1) ? ".5" : "", VAC_CTRL_DELAY_IOSELI_VAL(val)/2, (VAC_CTRL_DELAY_IOSELI_VAL(val)&1) ? ".5" : ""); - + printk("region5 at fff00000 (896KB)\t[local io, %s]\n", CACHEABLE_STR(vac_inw(VAC_A24_BASE) & VAC_A24_IO_CACHINH)); @@ -132,7 +130,7 @@ printk("\tio%d[ack %d cpuclk%s, %s%srecovery %d cpuclk, " "\n\t read %d%s cpuclk, write %d%s cpuclk, " "assert %d%s%s cpuclk]\n", - i, + i, VAC_CTRL_DELAY_DSACKI_VAL(val), state[val & (VAC_CTRL_IORD|VAC_CTRL_IOWR)], (val & VAC_CTRL_DSACK0) ? "dsack0*, " : "", @@ -144,15 +142,15 @@ (VAC_CTRL_DELAY_IOWR_VAL(val)&1) ? ".5" : "", VAC_CTRL_DELAY_IOSELI_VAL(val)/2, (VAC_CTRL_DELAY_IOSELI_VAL(val)&1) ? ".5" : "", - (vac_inw(VAC_DEV_LOC) & VAC_DEV_LOC_IOSEL(i)) ? + (vac_inw(VAC_DEV_LOC) & VAC_DEV_LOC_IOSEL(i)) ? ", id" : ""); } - + printk("region6 at fffe0000 (128KB)\t[vme, A16/%s, " "not cached]\n", - (a24_base & VAC_A24_A16D32_ENABLE) ? + (a24_base & VAC_A24_A16D32_ENABLE) ? ((a24_base & VAC_A24_A16D32) ? "D32" : "D16") : "user"); - + val = vac_inw(VAC_SHRCS_CTRL); printk("shared[ack %d cpuclk%s, %s%srecovery %d cpuclk, " "read %d%s, write %d%s, assert %d%s]\n", @@ -183,8 +181,8 @@ default: panic("Unknown VAC revision number"); } - - vac_outw(mem_limit-1, VAC_DRAM_MASK); + + vac_outw(mem_limit-1, VAC_DRAM_MASK); vac_outw(mem_limit, VAC_BNDR2); vac_outw(mem_limit, VAC_BNDR3); vac_outw(((BAGET_A24M_BASE>>16)&~VAC_A24_D32_ENABLE)|VAC_A24_DATAPATH, @@ -294,19 +292,19 @@ vac_outw(VAC_INT_CTRL_TIMER_PIO10| VAC_INT_CTRL_UART_B_PIO7| VAC_INT_CTRL_UART_A_PIO7,VAC_INT_CTRL); - /* + /* * Set quadro speed for both UARTs. * To do it we need use formulae from VIC/VAC manual, * keeping in mind Baget's 50MHz frequency... */ - vac_outw((500000/(384*16))<<8,VAC_CPU_CLK_DIV); + vac_outw((500000/(384*16))<<8,VAC_CPU_CLK_DIV); } static void __init vic_show(void) { unsigned char val; char *timeout[] = { "4", "16", "32", "64", "128", "256", "disabled" }; - char *deadlock[] = { "[dedlk only]", "[dedlk only]", + char *deadlock[] = { "[dedlk only]", "[dedlk only]", "[dedlk], [halt w/ rmc], [lberr]", "[dedlk], [halt w/o rmc], [lberr]" }; @@ -319,7 +317,7 @@ printk("metastability delay "); printk("%s ", deadlock[VIC_IFACE_CFG_DEADLOCK_VAL(val)]); - + printk("interrupts: "); val = vic_inb(VIC_ERR_INT); @@ -332,7 +330,7 @@ if (!(val & VIC_ERR_INT_ACFAIL)) printk("[acfail] "); printk("\n"); - + printk("timeouts: "); val = vic_inb(VIC_XFER_TIMO); printk("local %s, vme %s ", @@ -358,7 +356,7 @@ printk("[local boundary cross]"); if (val & VIC_BXFER_DEF_VME_CROSS) printk("[vme boundary cross]"); - + } static void __init vic_init(void) @@ -373,7 +371,7 @@ vic_outb(VIC_INT_IPL(3)|VIC_INT_DISABLE,VIC_VME_INT2); vic_outb(VIC_INT_IPL(3)|VIC_INT_DISABLE,VIC_VME_INT3); vic_outb(VIC_INT_IPL(3)|VIC_INT_DISABLE,VIC_VME_INT4); -/* +/* vic_outb(VIC_INT_IPL(3)|VIC_INT_DISABLE, VIC_VME_INT5); */ vic_outb(VIC_INT_IPL(3)|VIC_INT_DISABLE, VIC_VME_INT6); @@ -388,7 +386,7 @@ VIC_INT_HIGH|VIC_INT_DISABLE, VIC_LINT3); vic_outb(VIC_INT_IPL(3)|VIC_INT_NOAUTO|VIC_INT_EDGE| VIC_INT_LOW|VIC_INT_DISABLE, VIC_LINT4); -/* +/* vic_outb(VIC_INT_IPL(3)|VIC_INT_NOAUTO|VIC_INT_LEVEL| VIC_INT_LOW|VIC_INT_DISABLE, VIC_LINT5); */ @@ -447,7 +445,7 @@ VIC_RELEASE_RWD, VIC_RELEASE); vic_outb(VIC_IC6_RUN, VIC_IC6); vic_outb(0, VIC_IC7); - + vic_show(); } @@ -471,7 +469,7 @@ extern void baget_machine_restart(char *command); extern void baget_machine_halt(void); extern void baget_machine_power_off(void); - + void __init baget_setup(void) { printk("BT23/63-201n found.\n"); diff -Nru a/arch/mips/baget/time.c b/arch/mips/baget/time.c --- a/arch/mips/baget/time.c Tue Jul 1 18:44:31 2003 +++ b/arch/mips/baget/time.c Tue Jul 1 18:44:31 2003 @@ -20,23 +20,23 @@ #include #include #include -#include +#include #include -/* +/* * To have precision clock, we need to fix available clock frequency */ #define FREQ_NOM 79125 /* Baget frequency ratio */ #define FREQ_DEN 10000 -static inline int timer_intr_valid(void) +static inline int timer_intr_valid(void) { static unsigned long long ticks, valid_ticks; if (ticks++ * FREQ_DEN >= valid_ticks * FREQ_NOM) { - /* - * We need no overflow checks, + /* + * We need no overflow checks, * due baget unable to work 3000 years... * At least without reboot... */ @@ -62,10 +62,10 @@ vic_outb(ss0cr0, VIC_SS0CR0); vic_outb(VIC_INT_IPL(6)|VIC_INT_NOAUTO|VIC_INT_EDGE| - VIC_INT_LOW|VIC_INT_ENABLE, VIC_LINT2); + VIC_INT_LOW|VIC_INT_ENABLE, VIC_LINT2); } -static struct irqaction timer_irq = +static struct irqaction timer_irq = { timer_interrupt, SA_INTERRUPT, 0, "timer", NULL, NULL}; void __init time_init(void) @@ -82,17 +82,19 @@ do { seq = read_seqbegin(&xtime_lock); - *tv = xtime; + tv->tv_sec = xtime.tv_sec; + tv->tv_usec = xtime.tv_nsec / 1000; } while (read_seqretry(&xtime_lock, seq)); } void do_settimeofday(struct timeval *tv) { - write_seqlock_irq (&xtime_lock); - xtime = *tv; + write_seqlock_irq(&xtime_lock); + xtime.tv_usec = tv->tv_sec; + xtime.tv_nsec = tv->tv_usec; time_adjust = 0; /* stop active adjtime() */ time_status |= STA_UNSYNC; time_maxerror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT; - write_sequnlock_irq (&xtime_lock); + write_sequnlock_irq(&xtime_lock); } diff -Nru a/arch/mips/baget/vacserial.c b/arch/mips/baget/vacserial.c --- a/arch/mips/baget/vacserial.c Tue Jul 1 18:44:36 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,2837 +0,0 @@ -/* - * vacserial.c: VAC UART serial driver - * This code stealed and adopted from linux/drivers/char/serial.c - * See that for author info - * - * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov - */ - -#undef SERIAL_PARANOIA_CHECK -#define CONFIG_SERIAL_NOPAUSE_IO -#define SERIAL_DO_RESTART - -#define CONFIG_SERIAL_SHARE_IRQ - -/* Set of debugging defines */ - -#undef SERIAL_DEBUG_INTR -#undef SERIAL_DEBUG_OPEN -#undef SERIAL_DEBUG_FLOW -#undef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT - -#define RS_STROBE_TIME (10*HZ) -#define RS_ISR_PASS_LIMIT 2 /* Beget is not a super-computer (old=256) */ - -#define IRQ_T(state) \ - ((state->flags & ASYNC_SHARE_IRQ) ? SA_SHIRQ : SA_INTERRUPT) - -#define SERIAL_INLINE - -#if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT) -#define DBG_CNT(s) baget_printk("(%s):[%x] refc=%d, serc=%d, ttyc=%d-> %s\n", \ - tty->name,(info->flags),serial_driver->refcount,info->count,tty->count,s) -#else -#define DBG_CNT(s) -#endif - -#define QUAD_UART_SPEED /* Useful for Baget */ - -/* - * End of serial driver configuration section. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_SERIAL_CONSOLE -#include -#endif - -#include -#include -#include -#include -#include -#include -#include - -#define BAGET_VAC_UART_IRQ 0x35 - -/* - * Implementation note: - * It was descovered by means of advanced electronic tools, - * if the driver works via TX_READY interrupts then VIC generates - * strange self-eliminating traps. Thus, the driver is rewritten to work - * via TX_EMPTY - */ - -/* VAC-specific check/debug switches */ - -#undef CHECK_REG_INDEX -#undef DEBUG_IO_PORT_A - -#ifdef SERIAL_INLINE -#define _INLINE_ inline -#endif - -static char *serial_name = "VAC Serial driver"; -static char *serial_version = "4.26"; - -static DECLARE_TASK_QUEUE(tq_serial); - -static struct tty_driver *serial_driver; - -/* number of characters left in xmit buffer before we ask for more */ -#define WAKEUP_CHARS 256 - -/* - * IRQ_timeout - How long the timeout should be for each IRQ - * should be after the IRQ has been active. - */ - -static struct async_struct *IRQ_ports[NR_IRQS]; -static int IRQ_timeout[NR_IRQS]; -#ifdef CONFIG_SERIAL_CONSOLE -static struct console sercons; -#endif - -static void autoconfig(struct serial_state * info); -static void change_speed(struct async_struct *info); -static void rs_wait_until_sent(struct tty_struct *tty, int timeout); -static void rs_timer(unsigned long dummy); - -static struct timer_list vacs_timer; - -/* - * Here we define the default xmit fifo size used for each type of - * UART - */ -static struct serial_uart_config uart_config[] = { - { "unknown", 1, 0 }, /* Must go first -- used as unassigned */ - { "VAC UART", 1, 0 } -}; -#define VAC_UART_TYPE 1 /* Just index in above array */ - -static struct serial_state rs_table[] = { -/* - * VAC has tricky layout for pair of his SIO registers, - * so we need special function to access ones. - * To identify port we use their TX offset - */ - { 0, 9600, VAC_UART_B_TX, BAGET_VAC_UART_IRQ, - STD_COM_FLAGS }, /* VAC UART B */ - { 0, 9600, VAC_UART_A_TX, BAGET_VAC_UART_IRQ, - STD_COM_FLAGS } /* VAC UART A */ -}; - -#define NR_PORTS (sizeof(rs_table)/sizeof(struct serial_state)) - -#ifndef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif - -/* - * tmp_buf is used as a temporary buffer by serial_write. We need to - * lock it in case the copy_from_user blocks while swapping in a page, - * and some other program tries to do a serial write at the same time. - * Since the lock will only come under contention when the system is - * swapping and available memory is low, it makes sense to share one - * buffer across all the serial ports, since it significantly saves - * memory if large numbers of serial ports are open. - */ -static unsigned char *tmp_buf; -static DECLARE_MUTEX(tmp_buf_sem); - -static inline int serial_paranoia_check(struct async_struct *info, - char *name, const char *routine) -{ -#ifdef SERIAL_PARANOIA_CHECK - static const char *badmagic = - "Warning: bad magic number for serial struct (%s) in %s\n"; - static const char *badinfo = - "Warning: null async_struct for (%s) in %s\n"; - - if (!info) { - printk(badinfo, name, routine); - return 1; - } - if (info->magic != SERIAL_MAGIC) { - printk(badmagic, name, routine); - return 1; - } -#endif - return 0; -} - -/* - To unify UART A/B access we will use following function - to compute register offsets by register index. - */ - -#define VAC_UART_MODE 0 -#define VAC_UART_TX 1 -#define VAC_UART_RX 2 -#define VAC_UART_INT_MASK 3 -#define VAC_UART_INT_STATUS 4 - -#define VAC_UART_REG_NR 5 - -static inline int uart_offset_map(unsigned long port, int reg_index) -{ - static const unsigned int ind_to_reg[VAC_UART_REG_NR][NR_PORTS] = { - { VAC_UART_B_MODE, VAC_UART_A_MODE }, - { VAC_UART_B_TX, VAC_UART_A_TX }, - { VAC_UART_B_RX, VAC_UART_A_RX }, - { VAC_UART_B_INT_MASK, VAC_UART_A_INT_MASK }, - { VAC_UART_B_INT_STATUS, VAC_UART_A_INT_STATUS } - }; -#ifdef CHECK_REG_INDEX - if (reg_index > VAC_UART_REG_NR) panic("vacserial: bad reg_index"); -#endif - return ind_to_reg[reg_index][port == VAC_UART_B_TX ? 0 : 1]; -} - -static inline unsigned int serial_inw(struct async_struct *info, int offset) -{ - int val = vac_inw(uart_offset_map(info->port,offset)); -#ifdef DEBUG_IO_PORT_A - if (info->port == VAC_UART_A_TX) - printk("UART_A_IN: reg = 0x%04x, val = 0x%04x\n", - uart_offset_map(info->port,offset), val); -#endif - return val; -} - -static inline unsigned int serial_inp(struct async_struct *info, int offset) -{ - return serial_inw(info, offset); -} - -static inline unsigned int serial_in(struct async_struct *info, int offset) -{ - return serial_inw(info, offset); -} - -static inline void serial_outw(struct async_struct *info,int offset, int value) -{ -#ifdef DEBUG_IO_PORT_A - if (info->port == VAC_UART_A_TX) - printk("UART_A_OUT: offset = 0x%04x, val = 0x%04x\n", - uart_offset_map(info->port,offset), value); -#endif - vac_outw(value, uart_offset_map(info->port,offset)); -} - -static inline void serial_outp(struct async_struct *info,int offset, int value) -{ - serial_outw(info,offset,value); -} - -static inline void serial_out(struct async_struct *info,int offset, int value) -{ - serial_outw(info,offset,value); -} - -/* - * ------------------------------------------------------------ - * rs_stop() and rs_start() - * - * This routines are called before setting or resetting tty->stopped. - * They enable or disable transmitter interrupts, as necessary. - * ------------------------------------------------------------ - */ -static void rs_stop(struct tty_struct *tty) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_stop")) - return; - - save_flags(flags); cli(); - if (info->IER & VAC_UART_INT_TX_EMPTY) { - info->IER &= ~VAC_UART_INT_TX_EMPTY; - serial_out(info, VAC_UART_INT_MASK, info->IER); - } - restore_flags(flags); -} - -static void rs_start(struct tty_struct *tty) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_start")) - return; - - save_flags(flags); cli(); - if (info->xmit_cnt && info->xmit_buf - && !(info->IER & VAC_UART_INT_TX_EMPTY)) { - info->IER |= VAC_UART_INT_TX_EMPTY; - serial_out(info, VAC_UART_INT_MASK, info->IER); - } - restore_flags(flags); -} - -/* - * ---------------------------------------------------------------------- - * - * Here starts the interrupt handling routines. All of the following - * subroutines are declared as inline and are folded into - * rs_interrupt(). They were separated out for readability's sake. - * - * Note: rs_interrupt() is a "fast" interrupt, which means that it - * runs with interrupts turned off. People who may want to modify - * rs_interrupt() should try to keep the interrupt handler as fast as - * possible. After you are done making modifications, it is not a bad - * idea to do: - * - * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c - * - * and look at the resulting assemble code in serial.s. - * - * - Ted Ts'o (tytso@mit.edu), 7-Mar-93 - * ----------------------------------------------------------------------- - */ - -/* - * This routine is used by the interrupt handler to schedule - * processing in the software interrupt portion of the driver. - */ -static _INLINE_ void rs_sched_event(struct async_struct *info, - int event) -{ - info->event |= 1 << event; - queue_task(&info->tqueue, &tq_serial); - mark_bh(SERIAL_BH); -} - -static _INLINE_ void receive_chars(struct async_struct *info, - int *status) -{ - struct tty_struct *tty = info->tty; - unsigned short rx; - unsigned char ch; - int ignored = 0; - struct async_icount *icount; - - icount = &info->state->icount; - do { - rx = serial_inw(info, VAC_UART_RX); - ch = VAC_UART_RX_DATA_MASK & rx; - - if (tty->flip.count >= TTY_FLIPBUF_SIZE) - break; - *tty->flip.char_buf_ptr = ch; - icount->rx++; - -#ifdef SERIAL_DEBUG_INTR - baget_printk("DR%02x:%02x...", rx, *status); -#endif - *tty->flip.flag_buf_ptr = 0; - if (*status & (VAC_UART_STATUS_RX_BREAK_CHANGE - | VAC_UART_STATUS_RX_ERR_PARITY - | VAC_UART_STATUS_RX_ERR_FRAME - | VAC_UART_STATUS_RX_ERR_OVERRUN)) { - /* - * For statistics only - */ - if (*status & VAC_UART_STATUS_RX_BREAK_CHANGE) { - *status &= ~(VAC_UART_STATUS_RX_ERR_FRAME - | VAC_UART_STATUS_RX_ERR_PARITY); - icount->brk++; - } else if (*status & VAC_UART_STATUS_RX_ERR_PARITY) - icount->parity++; - else if (*status & VAC_UART_STATUS_RX_ERR_FRAME) - icount->frame++; - if (*status & VAC_UART_STATUS_RX_ERR_OVERRUN) - icount->overrun++; - - /* - * Now check to see if character should be - * ignored, and mask off conditions which - * should be ignored. - */ - if (*status & info->ignore_status_mask) { - if (++ignored > 100) - break; - goto ignore_char; - } - *status &= info->read_status_mask; - - if (*status & (VAC_UART_STATUS_RX_BREAK_CHANGE)) { -#ifdef SERIAL_DEBUG_INTR - baget_printk("handling break...."); -#endif - *tty->flip.flag_buf_ptr = TTY_BREAK; - if (info->flags & ASYNC_SAK) - do_SAK(tty); - } else if (*status & VAC_UART_STATUS_RX_ERR_PARITY) - *tty->flip.flag_buf_ptr = TTY_PARITY; - else if (*status & VAC_UART_STATUS_RX_ERR_FRAME) - *tty->flip.flag_buf_ptr = TTY_FRAME; - if (*status & VAC_UART_STATUS_RX_ERR_OVERRUN) { - /* - * Overrun is special, since it's - * reported immediately, and doesn't - * affect the current character - */ - if (tty->flip.count < TTY_FLIPBUF_SIZE) { - tty->flip.count++; - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - *tty->flip.flag_buf_ptr = TTY_OVERRUN; - } - } - } - tty->flip.flag_buf_ptr++; - tty->flip.char_buf_ptr++; - tty->flip.count++; - ignore_char: - *status = serial_inw(info, VAC_UART_INT_STATUS); - } while ((*status & VAC_UART_STATUS_RX_READY)); - tty_flip_buffer_push(tty); -} - -static _INLINE_ void transmit_chars(struct async_struct *info, int *intr_done) -{ - int count; - - if (info->x_char) { - serial_outw(info, VAC_UART_TX, - (((unsigned short)info->x_char)<<8)); - info->state->icount.tx++; - info->x_char = 0; - if (intr_done) - *intr_done = 0; - return; - } - if ((info->xmit_cnt <= 0) || info->tty->stopped || - info->tty->hw_stopped) { - info->IER &= ~VAC_UART_INT_TX_EMPTY; - serial_outw(info, VAC_UART_INT_MASK, info->IER); - return; - } - count = info->xmit_fifo_size; - do { - serial_out(info, VAC_UART_TX, - (unsigned short)info->xmit_buf[info->xmit_tail++] \ - << 8); - info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1); - info->state->icount.tx++; - if (--info->xmit_cnt <= 0) - break; - } while (--count > 0); - - if (info->xmit_cnt < WAKEUP_CHARS) - rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); - -#ifdef SERIAL_DEBUG_INTR - baget_printk("THRE..."); -#endif - if (intr_done) - *intr_done = 0; - - if (info->xmit_cnt <= 0) { - info->IER &= ~VAC_UART_INT_TX_EMPTY; - serial_outw(info, VAC_UART_INT_MASK, info->IER); - } -} - -static _INLINE_ void check_modem_status(struct async_struct *info) -{ -#if 0 /* VAC hasn't modem control */ - wake_up_interruptible(&info->open_wait); - rs_sched_event(info, RS_EVENT_WRITE_WAKEUP); -#endif -} - -#ifdef CONFIG_SERIAL_SHARE_IRQ - - -/* - * Specific functions needed for VAC UART interrupt enter/leave - */ - -#define VAC_INT_CTRL_UART_ENABLE \ - (VAC_INT_CTRL_TIMER_PIO10|VAC_INT_CTRL_UART_B_PIO7|VAC_INT_CTRL_UART_A_PIO7) - -#define VAC_INT_CTRL_UART_DISABLE(info) \ - (VAC_INT_CTRL_TIMER_PIO10 | \ - ((info->port == VAC_UART_A_TX) ? \ - (VAC_INT_CTRL_UART_A_DISABLE|VAC_INT_CTRL_UART_B_PIO7) : \ - (VAC_INT_CTRL_UART_A_PIO7|VAC_INT_CTRL_UART_B_DISABLE))) - -/* - * Following two functions were proposed by Pavel Osipenko - * to make VAC/VIC behaviour more regular. - */ -static void intr_begin(struct async_struct* info) -{ - serial_outw(info, VAC_UART_INT_MASK, 0); -} - -static void intr_end(struct async_struct* info) -{ - vac_outw(VAC_INT_CTRL_UART_DISABLE(info), VAC_INT_CTRL); - vac_outw(VAC_INT_CTRL_UART_ENABLE, VAC_INT_CTRL); - - serial_outw(info, VAC_UART_INT_MASK, info->IER); -} - -/* - * This is the serial driver's generic interrupt routine - */ -static void rs_interrupt(int irq, void *dev_id, struct pt_regs * regs) -{ - int status; - struct async_struct * info; - int pass_counter = 0; - struct async_struct *end_mark = 0; - -#ifdef SERIAL_DEBUG_INTR - baget_printk("rs_interrupt(%d)...", irq); -#endif - - info = IRQ_ports[irq]; - if (!info) - return; - - do { - intr_begin(info); /* Mark we begin port handling */ - - if (!info->tty || - (serial_inw (info, VAC_UART_INT_STATUS) - & VAC_UART_STATUS_INTS) == 0) - { - if (!end_mark) - end_mark = info; - goto next; - } - end_mark = 0; - - info->last_active = jiffies; - - status = serial_inw(info, VAC_UART_INT_STATUS); -#ifdef SERIAL_DEBUG_INTR - baget_printk("status = %x...", status); -#endif - if (status & VAC_UART_STATUS_RX_READY) { - receive_chars(info, &status); - } - check_modem_status(info); - if (status & VAC_UART_STATUS_TX_EMPTY) - transmit_chars(info, 0); - - next: - intr_end(info); /* Mark this port handled */ - - info = info->next_port; - if (!info) { - info = IRQ_ports[irq]; - if (pass_counter++ > RS_ISR_PASS_LIMIT) { - break; /* Prevent infinite loops */ - } - continue; - } - } while (end_mark != info); -#ifdef SERIAL_DEBUG_INTR - baget_printk("end.\n"); -#endif - - -} -#endif /* #ifdef CONFIG_SERIAL_SHARE_IRQ */ - - -/* The original driver was simplified here: - two functions were joined to reduce code */ - -#define rs_interrupt_single rs_interrupt - - -/* - * ------------------------------------------------------------------- - * Here ends the serial interrupt routines. - * ------------------------------------------------------------------- - */ - -/* - * This routine is used to handle the "bottom half" processing for the - * serial driver, known also the "software interrupt" processing. - * This processing is done at the kernel interrupt level, after the - * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This - * is where time-consuming activities which can not be done in the - * interrupt driver proper are done; the interrupt driver schedules - * them using rs_sched_event(), and they get done here. - */ -static void do_serial_bh(void) -{ - run_task_queue(&tq_serial); -} - -static void do_softint(void *private_) -{ - struct async_struct *info = (struct async_struct *) private_; - struct tty_struct *tty; - - tty = info->tty; - if (!tty) - return; - - if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) { - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); - wake_up_interruptible(&tty->write_wait); - } -} - -/* - * --------------------------------------------------------------- - * Low level utility subroutines for the serial driver: routines to - * figure out the appropriate timeout for an interrupt chain, routines - * to initialize and startup a serial port, and routines to shutdown a - * serial port. Useful stuff like that. - * --------------------------------------------------------------- - */ - -/* - * This routine figures out the correct timeout for a particular IRQ. - * It uses the smallest timeout of all of the serial ports in a - * particular interrupt chain. Now only used for IRQ 0.... - */ -static void figure_IRQ_timeout(int irq) -{ - struct async_struct *info; - int timeout = 60*HZ; /* 60 seconds === a long time :-) */ - - info = IRQ_ports[irq]; - if (!info) { - IRQ_timeout[irq] = 60*HZ; - return; - } - while (info) { - if (info->timeout < timeout) - timeout = info->timeout; - info = info->next_port; - } - if (!irq) - timeout = timeout / 2; - IRQ_timeout[irq] = timeout ? timeout : 1; -} - -static int startup(struct async_struct * info) -{ - unsigned long flags; - int retval=0; - void (*handler)(int, void *, struct pt_regs *); - struct serial_state *state= info->state; - unsigned long page; - - page = get_zeroed_page(GFP_KERNEL); - if (!page) - return -ENOMEM; - - save_flags(flags); cli(); - - if (info->flags & ASYNC_INITIALIZED) { - free_page(page); - goto errout; - } - if (!state->port || !state->type) { - if (info->tty) - set_bit(TTY_IO_ERROR, &info->tty->flags); - free_page(page); - goto errout; - } - if (info->xmit_buf) - free_page(page); - else - info->xmit_buf = (unsigned char *) page; - -#ifdef SERIAL_DEBUG_OPEN - baget_printk("starting up ttys%d (irq %d)...", info->line, state->irq); -#endif - - if (uart_config[info->state->type].flags & UART_STARTECH) { - /* Wake up UART */ - serial_outp(info, VAC_UART_MODE, 0); - serial_outp(info, VAC_UART_INT_MASK, 0); - } - - /* - * Allocate the IRQ if necessary - */ - if (state->irq && (!IRQ_ports[state->irq] || - !IRQ_ports[state->irq]->next_port)) { - - if (IRQ_ports[state->irq]) { -#ifdef CONFIG_SERIAL_SHARE_IRQ - free_irq(state->irq, NULL); - handler = rs_interrupt; -#else - retval = -EBUSY; - goto errout; -#endif /* CONFIG_SERIAL_SHARE_IRQ */ - } else - handler = rs_interrupt_single; - - - retval = request_irq(state->irq, handler, IRQ_T(state), - "serial", NULL); - if (retval) { - if (capable(CAP_SYS_ADMIN)) { - if (info->tty) - set_bit(TTY_IO_ERROR, - &info->tty->flags); - retval = 0; - } - goto errout; - } - } - - /* - * Insert serial port into IRQ chain. - */ - info->prev_port = 0; - info->next_port = IRQ_ports[state->irq]; - if (info->next_port) - info->next_port->prev_port = info; - IRQ_ports[state->irq] = info; - figure_IRQ_timeout(state->irq); - - /* - * Clear the interrupt registers. - */ - /* (void) serial_inw(info, VAC_UART_INT_STATUS); */ /* (see above) */ - (void) serial_inw(info, VAC_UART_RX); - - /* - * Now, initialize the UART - */ - serial_outp(info, VAC_UART_MODE, VAC_UART_MODE_INITIAL); /*reset DLAB*/ - - /* - * Finally, enable interrupts - */ - info->IER = VAC_UART_INT_RX_BREAK_CHANGE | VAC_UART_INT_RX_ERRS | \ - VAC_UART_INT_RX_READY; - serial_outp(info, VAC_UART_INT_MASK, info->IER); /*enable interrupts*/ - - /* - * And clear the interrupt registers again for luck. - */ - (void)serial_inp(info, VAC_UART_INT_STATUS); - (void)serial_inp(info, VAC_UART_RX); - - if (info->tty) - clear_bit(TTY_IO_ERROR, &info->tty->flags); - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - - /* - * Set up serial timers... - */ - mod_timer(&vacs_timer, jiffies + 2*HZ/100); - - /* - * and set the speed of the serial port - */ - change_speed(info); - - info->flags |= ASYNC_INITIALIZED; - restore_flags(flags); - return 0; - -errout: - restore_flags(flags); - return retval; -} - -/* - * This routine will shutdown a serial port; interrupts are disabled, and - * DTR is dropped if the hangup on close termio flag is on. - */ -static void shutdown(struct async_struct * info) -{ - unsigned long flags; - struct serial_state *state; - int retval; - - if (!(info->flags & ASYNC_INITIALIZED)) - return; - - state = info->state; - -#ifdef SERIAL_DEBUG_OPEN - baget_printk("Shutting down serial port %d (irq %d)....", info->line, - state->irq); -#endif - - save_flags(flags); cli(); /* Disable interrupts */ - - /* - * clear delta_msr_wait queue to avoid mem leaks: we may free the irq - * here so the queue might never be waken up - */ - wake_up_interruptible(&info->delta_msr_wait); - - /* - * First unlink the serial port from the IRQ chain... - */ - if (info->next_port) - info->next_port->prev_port = info->prev_port; - if (info->prev_port) - info->prev_port->next_port = info->next_port; - else - IRQ_ports[state->irq] = info->next_port; - figure_IRQ_timeout(state->irq); - - /* - * Free the IRQ, if necessary - */ - if (state->irq && (!IRQ_ports[state->irq] || - !IRQ_ports[state->irq]->next_port)) { - if (IRQ_ports[state->irq]) { - free_irq(state->irq, NULL); - retval = request_irq(state->irq, rs_interrupt_single, - IRQ_T(state), "serial", NULL); - - if (retval) - printk("serial shutdown: request_irq: error %d" - " Couldn't reacquire IRQ.\n", retval); - } else - free_irq(state->irq, NULL); - } - - if (info->xmit_buf) { - free_page((unsigned long) info->xmit_buf); - info->xmit_buf = 0; - } - - info->IER = 0; - serial_outp(info, VAC_UART_INT_MASK, 0x00); /* disable all intrs */ - - /* disable break condition */ - serial_out(info, VAC_UART_MODE, serial_inp(info, VAC_UART_MODE) & \ - ~VAC_UART_MODE_SEND_BREAK); - - if (info->tty) - set_bit(TTY_IO_ERROR, &info->tty->flags); - - info->flags &= ~ASYNC_INITIALIZED; - restore_flags(flags); -} - -/* - * When we set line mode, we call this function - * for Baget-specific adjustments. - */ - -static inline unsigned short vac_uart_mode_fixup (unsigned short cval) -{ -#ifdef QUAD_UART_SPEED - /* - * When we are using 4-x advantage in speed: - * - * Disadvantage : can't support 75, 150 bauds - * Advantage : can support 19200, 38400 bauds - */ - char speed = 7 & (cval >> 10); - cval &= ~(7 << 10); - cval |= VAC_UART_MODE_BAUD(speed-2); -#endif - - /* - * In general, we have Tx and Rx ON all time - * and use int mask flag for their disabling. - */ - cval |= VAC_UART_MODE_RX_ENABLE; - cval |= VAC_UART_MODE_TX_ENABLE; - cval |= VAC_UART_MODE_CHAR_RX_ENABLE; - cval |= VAC_UART_MODE_CHAR_TX_ENABLE; - - /* Low 4 bits are not used in UART */ - cval &= ~0xf; - - return cval; -} - -/* - * This routine is called to set the UART divisor registers to match - * the specified baud rate for a serial port. - */ -static void change_speed(struct async_struct *info) -{ - unsigned short port; - int quot = 0, baud_base, baud; - unsigned cflag, cval; - int bits; - unsigned long flags; - - if (!info->tty || !info->tty->termios) - return; - cflag = info->tty->termios->c_cflag; - if (!(port = info->port)) - return; - - /* byte size and parity */ - switch (cflag & CSIZE) { - case CS7: cval = 0x0; bits = 9; break; - case CS8: cval = VAC_UART_MODE_8BIT_CHAR; bits = 10; break; - /* Never happens, but GCC is too dumb to figure it out */ - case CS5: - case CS6: - default: cval = 0x0; bits = 9; break; - } - cval &= ~VAC_UART_MODE_PARITY_ENABLE; - if (cflag & PARENB) { - cval |= VAC_UART_MODE_PARITY_ENABLE; - bits++; - } - if (cflag & PARODD) - cval |= VAC_UART_MODE_PARITY_ODD; - - /* Determine divisor based on baud rate */ - baud = tty_get_baud_rate(info->tty); - if (!baud) - baud = 9600; /* B0 transition handled in rs_set_termios */ - baud_base = info->state->baud_base; - if (baud == 38400 && - ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)) - quot = info->state->custom_divisor; - else { - if (baud == 134) - /* Special case since 134 is really 134.5 */ - quot = (2*baud_base / 269); - else if (baud) - quot = baud_base / baud; - } - /* If the quotient is ever zero, default to 9600 bps */ - if (!quot) - quot = baud_base / 9600; - info->quot = quot; - info->timeout = ((info->xmit_fifo_size*HZ*bits*quot) / baud_base); - info->timeout += HZ/50; /* Add .02 seconds of slop */ - - serial_out(info, VAC_UART_INT_MASK, info->IER); - - /* - * Set up parity check flag - */ -#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) - - info->read_status_mask = VAC_UART_STATUS_RX_ERR_OVERRUN | \ - VAC_UART_STATUS_TX_EMPTY | VAC_UART_STATUS_RX_READY; - if (I_INPCK(info->tty)) - info->read_status_mask |= VAC_UART_STATUS_RX_ERR_FRAME | \ - VAC_UART_STATUS_RX_ERR_PARITY; - if (I_BRKINT(info->tty) || I_PARMRK(info->tty)) - info->read_status_mask |= VAC_UART_STATUS_RX_BREAK_CHANGE; - - /* - * Characters to ignore - */ - info->ignore_status_mask = 0; - if (I_IGNPAR(info->tty)) - info->ignore_status_mask |= VAC_UART_STATUS_RX_ERR_PARITY | \ - VAC_UART_STATUS_RX_ERR_FRAME; - if (I_IGNBRK(info->tty)) { - info->ignore_status_mask |= VAC_UART_STATUS_RX_BREAK_CHANGE; - /* - * If we're ignore parity and break indicators, ignore - * overruns too. (For real raw support). - */ - if (I_IGNPAR(info->tty)) - info->ignore_status_mask |= \ - VAC_UART_STATUS_RX_ERR_OVERRUN; - } - /* - * !!! ignore all characters if CREAD is not set - */ - if ((cflag & CREAD) == 0) - info->ignore_status_mask |= VAC_UART_STATUS_RX_READY; - save_flags(flags); cli(); - - - switch (baud) { - default: - case 9600: - cval |= VAC_UART_MODE_BAUD(7); - break; - case 4800: - cval |= VAC_UART_MODE_BAUD(6); - break; - case 2400: - cval |= VAC_UART_MODE_BAUD(5); - break; - case 1200: - cval |= VAC_UART_MODE_BAUD(4); - break; - case 600: - cval |= VAC_UART_MODE_BAUD(3); - break; - case 300: - cval |= VAC_UART_MODE_BAUD(2); - break; -#ifndef QUAD_UART_SPEED - case 150: -#else - case 38400: -#endif - cval |= VAC_UART_MODE_BAUD(1); - break; -#ifndef QUAD_UART_SPEED - case 75: -#else - case 19200: -#endif - cval |= VAC_UART_MODE_BAUD(0); - break; - } - - /* Baget VAC need some adjustments for computed value */ - cval = vac_uart_mode_fixup(cval); - - serial_outp(info, VAC_UART_MODE, cval); - restore_flags(flags); -} - -static void rs_put_char(struct tty_struct *tty, unsigned char ch) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_put_char")) - return; - - if (!tty || !info->xmit_buf) - return; - - save_flags(flags); cli(); - if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1) { - restore_flags(flags); - return; - } - - info->xmit_buf[info->xmit_head++] = ch; - info->xmit_head &= SERIAL_XMIT_SIZE-1; - info->xmit_cnt++; - restore_flags(flags); -} - -static void rs_flush_chars(struct tty_struct *tty) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_flush_chars")) - return; - - if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped || - !info->xmit_buf) - return; - - save_flags(flags); cli(); - info->IER |= VAC_UART_INT_TX_EMPTY; - serial_out(info, VAC_UART_INT_MASK, info->IER); - restore_flags(flags); -} - -static int rs_write(struct tty_struct * tty, int from_user, - const unsigned char *buf, int count) -{ - int c, ret = 0; - struct async_struct *info = (struct async_struct *)tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_write")) - return 0; - - if (!tty || !info->xmit_buf || !tmp_buf) - return 0; - - save_flags(flags); - if (from_user) { - down(&tmp_buf_sem); - while (1) { - c = MIN(count, - MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - if (c <= 0) - break; - - c -= copy_from_user(tmp_buf, buf, c); - if (!c) { - if (!ret) - ret = -EFAULT; - break; - } - cli(); - c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); - info->xmit_head = ((info->xmit_head + c) & - (SERIAL_XMIT_SIZE-1)); - info->xmit_cnt += c; - restore_flags(flags); - buf += c; - count -= c; - ret += c; - } - up(&tmp_buf_sem); - } else { - while (1) { - cli(); - c = MIN(count, - MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, - SERIAL_XMIT_SIZE - info->xmit_head)); - if (c <= 0) { - restore_flags(flags); - break; - } - memcpy(info->xmit_buf + info->xmit_head, buf, c); - info->xmit_head = ((info->xmit_head + c) & - (SERIAL_XMIT_SIZE-1)); - info->xmit_cnt += c; - restore_flags(flags); - buf += c; - count -= c; - ret += c; - } - } - if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped && - !(info->IER & VAC_UART_INT_TX_EMPTY)) { - info->IER |= VAC_UART_INT_TX_EMPTY; - serial_out(info, VAC_UART_INT_MASK, info->IER); - } - return ret; -} - -static int rs_write_room(struct tty_struct *tty) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - int ret; - - if (serial_paranoia_check(info, tty->name, "rs_write_room")) - return 0; - ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; - if (ret < 0) - ret = 0; - return ret; -} - -static int rs_chars_in_buffer(struct tty_struct *tty) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - - if (serial_paranoia_check(info, tty->name, "rs_chars_in_buffer")) - return 0; - return info->xmit_cnt; -} - -static void rs_flush_buffer(struct tty_struct *tty) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_flush_buffer")) - return; - - save_flags(flags); cli(); - info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; - restore_flags(flags); - - wake_up_interruptible(&tty->write_wait); - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup)(tty); -} - -/* - * This function is used to send a high-priority XON/XOFF character to - * the device - */ -static void rs_send_xchar(struct tty_struct *tty, char ch) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - - if (serial_paranoia_check(info, tty->name, "rs_send_char")) - return; - - info->x_char = ch; - if (ch) { - /* Make sure transmit interrupts are on */ - info->IER |= VAC_UART_INT_TX_EMPTY; - serial_out(info, VAC_UART_INT_MASK, info->IER); - } -} - -/* - * ------------------------------------------------------------ - * rs_throttle() - * - * This routine is called by the upper-layer tty layer to signal that - * incoming characters should be throttled. - * ------------------------------------------------------------ - */ -static void rs_throttle(struct tty_struct * tty) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - -#ifdef SERIAL_DEBUG_THROTTLE - char buf[64]; - - baget_printk("throttle %s: %d....\n", tty_name(tty, buf), - tty->ldisc.chars_in_buffer(tty)); -#endif - - if (serial_paranoia_check(info, tty->name, "rs_throttle")) - return; - - if (I_IXOFF(tty)) - rs_send_xchar(tty, STOP_CHAR(tty)); -} - -static void rs_unthrottle(struct tty_struct * tty) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; -#ifdef SERIAL_DEBUG_THROTTLE - char buf[64]; - - baget_printk("unthrottle %s: %d....\n", tty_name(tty, buf), - tty->ldisc.chars_in_buffer(tty)); -#endif - - if (serial_paranoia_check(info, tty->name, "rs_unthrottle")) - return; - - if (I_IXOFF(tty)) { - if (info->x_char) - info->x_char = 0; - else - rs_send_xchar(tty, START_CHAR(tty)); - } -} - -/* - * ------------------------------------------------------------ - * rs_ioctl() and friends - * ------------------------------------------------------------ - */ - -static int get_serial_info(struct async_struct * info, - struct serial_struct * retinfo) -{ - struct serial_struct tmp; - struct serial_state *state = info->state; - - if (!retinfo) - return -EFAULT; - memset(&tmp, 0, sizeof(tmp)); - tmp.type = state->type; - tmp.line = state->line; - tmp.port = state->port; - tmp.irq = state->irq; - tmp.flags = state->flags; - tmp.xmit_fifo_size = state->xmit_fifo_size; - tmp.baud_base = state->baud_base; - tmp.close_delay = state->close_delay; - tmp.closing_wait = state->closing_wait; - tmp.custom_divisor = state->custom_divisor; - tmp.hub6 = state->hub6; - if (copy_to_user(retinfo,&tmp,sizeof(*retinfo))) - return -EFAULT; - return 0; -} - -static int set_serial_info(struct async_struct * info, - struct serial_struct * new_info) -{ - struct serial_struct new_serial; - struct serial_state old_state, *state; - unsigned int i,change_irq,change_port; - int retval = 0; - - if (copy_from_user(&new_serial,new_info,sizeof(new_serial))) - return -EFAULT; - state = info->state; - old_state = *state; - - change_irq = new_serial.irq != state->irq; - change_port = (new_serial.port != state->port) || - (new_serial.hub6 != state->hub6); - - if (!capable(CAP_SYS_ADMIN)) { - if (change_irq || change_port || - (new_serial.baud_base != state->baud_base) || - (new_serial.type != state->type) || - (new_serial.close_delay != state->close_delay) || - (new_serial.xmit_fifo_size != state->xmit_fifo_size) || - ((new_serial.flags & ~ASYNC_USR_MASK) != - (state->flags & ~ASYNC_USR_MASK))) - return -EPERM; - state->flags = ((state->flags & ~ASYNC_USR_MASK) | - (new_serial.flags & ASYNC_USR_MASK)); - info->flags = ((state->flags & ~ASYNC_USR_MASK) | - (info->flags & ASYNC_USR_MASK)); - state->custom_divisor = new_serial.custom_divisor; - goto check_and_exit; - } - - new_serial.irq = new_serial.irq; - - if ((new_serial.irq >= NR_IRQS) || (new_serial.port > 0xffff) || - (new_serial.baud_base == 0) || (new_serial.type < PORT_UNKNOWN) || - (new_serial.type > PORT_MAX) || (new_serial.type == PORT_CIRRUS) || - (new_serial.type == PORT_STARTECH)) { - return -EINVAL; - } - - if ((new_serial.type != state->type) || - (new_serial.xmit_fifo_size <= 0)) - new_serial.xmit_fifo_size = - uart_config[state->type].dfl_xmit_fifo_size; - - /* Make sure address is not already in use */ - if (new_serial.type) { - for (i = 0 ; i < NR_PORTS; i++) - if ((state != &rs_table[i]) && - (rs_table[i].port == new_serial.port) && - rs_table[i].type) - return -EADDRINUSE; - } - - if ((change_port || change_irq) && (state->count > 1)) - return -EBUSY; - - /* - * OK, past this point, all the error checking has been done. - * At this point, we start making changes..... - */ - - state->baud_base = new_serial.baud_base; - state->flags = ((state->flags & ~ASYNC_FLAGS) | - (new_serial.flags & ASYNC_FLAGS)); - info->flags = ((state->flags & ~ASYNC_INTERNAL_FLAGS) | - (info->flags & ASYNC_INTERNAL_FLAGS)); - state->custom_divisor = new_serial.custom_divisor; - state->type = new_serial.type; - state->close_delay = new_serial.close_delay * HZ/100; - state->closing_wait = new_serial.closing_wait * HZ/100; - info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; - info->xmit_fifo_size = state->xmit_fifo_size = - new_serial.xmit_fifo_size; - - release_region(state->port,8); - if (change_port || change_irq) { - /* - * We need to shutdown the serial port at the old - * port/irq combination. - */ - shutdown(info); - state->irq = new_serial.irq; - info->port = state->port = new_serial.port; - info->hub6 = state->hub6 = new_serial.hub6; - } - if (state->type != PORT_UNKNOWN) - request_region(state->port,8,"serial(set)"); - - -check_and_exit: - if (!state->port || !state->type) - return 0; - if (info->flags & ASYNC_INITIALIZED) { - if (((old_state.flags & ASYNC_SPD_MASK) != - (state->flags & ASYNC_SPD_MASK)) || - (old_state.custom_divisor != state->custom_divisor)) { - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) - info->tty->alt_speed = 57600; - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) - info->tty->alt_speed = 115200; - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) - info->tty->alt_speed = 230400; - if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) - info->tty->alt_speed = 460800; - change_speed(info); - } - } else - retval = startup(info); - return retval; -} - - -/* - * get_lsr_info - get line status register info - * - * Purpose: Let user call ioctl() to get info when the UART physically - * is emptied. On bus types like RS485, the transmitter must - * release the bus after transmitting. This must be done when - * the transmit shift register is empty, not be done when the - * transmit holding register is empty. This functionality - * allows an RS485 driver to be written in user space. - */ -static int get_lsr_info(struct async_struct * info, unsigned int *value) -{ - unsigned short status; - unsigned int result; - unsigned long flags; - - save_flags(flags); cli(); - status = serial_inw(info, VAC_UART_INT_STATUS); - restore_flags(flags); - result = ((status & VAC_UART_STATUS_TX_EMPTY) ? TIOCSER_TEMT : 0); - return put_user(result,value); -} - - -static int get_modem_info(struct async_struct * info, unsigned int *value) -{ - unsigned int result; - - result = TIOCM_CAR | TIOCM_DSR; - return put_user(result,value); -} - -static int set_modem_info(struct async_struct * info, unsigned int cmd, - unsigned int *value) -{ - unsigned int arg; - - if (get_user(arg, value)) - return -EFAULT; - switch (cmd) { - default: - return -EINVAL; - } - return 0; -} - -static int do_autoconfig(struct async_struct * info) -{ - int retval; - - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - - if (info->state->count > 1) - return -EBUSY; - - shutdown(info); - - autoconfig(info->state); - - retval = startup(info); - if (retval) - return retval; - return 0; -} - -/* - * rs_break() --- routine which turns the break handling on or off - */ -static void rs_break(struct tty_struct *tty, int break_state) -{ - struct async_struct * info = (struct async_struct *)tty->driver_data; - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_break")) - return; - - if (!info->port) - return; - save_flags(flags); cli(); - if (break_state == -1) - serial_outp(info, VAC_UART_MODE, - serial_inp(info, VAC_UART_MODE) | \ - VAC_UART_MODE_SEND_BREAK); - else - serial_outp(info, VAC_UART_MODE, - serial_inp(info, VAC_UART_MODE) & \ - ~VAC_UART_MODE_SEND_BREAK); - restore_flags(flags); -} - -static int rs_ioctl(struct tty_struct *tty, struct file * file, - unsigned int cmd, unsigned long arg) -{ - int error; - struct async_struct * info = (struct async_struct *)tty->driver_data; - struct async_icount cprev, cnow; /* kernel counter temps */ - struct serial_icounter_struct *p_cuser; /* user space */ - unsigned long flags; - - if (serial_paranoia_check(info, tty->name, "rs_ioctl")) - return -ENODEV; - - if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && - (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) && - (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - } - - switch (cmd) { - case TIOCMGET: - return get_modem_info(info, (unsigned int *) arg); - case TIOCMBIS: - case TIOCMBIC: - case TIOCMSET: - return set_modem_info(info, cmd, (unsigned int *) arg); - case TIOCGSERIAL: - return get_serial_info(info, - (struct serial_struct *) arg); - case TIOCSSERIAL: - return set_serial_info(info, - (struct serial_struct *) arg); - case TIOCSERCONFIG: - return do_autoconfig(info); - - case TIOCSERGETLSR: /* Get line status register */ - return get_lsr_info(info, (unsigned int *) arg); - - case TIOCSERGSTRUCT: - if (copy_to_user((struct async_struct *) arg, - info, sizeof(struct async_struct))) - return -EFAULT; - return 0; - - /* - * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)to change - * - mask passed in arg for lines of interest - * (use |'ed TIOCM_RNG/DSR/CD/CTS for masking) - * Caller should use TIOCGICOUNT to see which one it was - */ - case TIOCMIWAIT: - save_flags(flags); cli(); - /* note the counters on entry */ - cprev = info->state->icount; - restore_flags(flags); - while (1) { - interruptible_sleep_on(&info->delta_msr_wait); - /* see if a signal did it */ - if (signal_pending(current)) - return -ERESTARTSYS; - save_flags(flags); cli(); - cnow = info->state->icount; /* atomic copy */ - restore_flags(flags); - if (cnow.rng == cprev.rng && - cnow.dsr == cprev.dsr && - cnow.dcd == cprev.dcd && - cnow.cts == cprev.cts) - return -EIO; /* no change => error */ - if ( ((arg & TIOCM_RNG) && - (cnow.rng != cprev.rng)) || - ((arg & TIOCM_DSR) && - (cnow.dsr != cprev.dsr)) || - ((arg & TIOCM_CD) && - (cnow.dcd != cprev.dcd)) || - ((arg & TIOCM_CTS) && - (cnow.cts != cprev.cts)) ) { - return 0; - } - cprev = cnow; - } - /* NOTREACHED */ - - /* - * Get counter of input serial line interrupts (DCD,RI,DSR,CTS) - * Return: write counters to the user passed counter struct - * NB: both 1->0 and 0->1 transitions are counted except for - * RI where only 0->1 is counted. - */ - case TIOCGICOUNT: - save_flags(flags); cli(); - cnow = info->state->icount; - restore_flags(flags); - p_cuser = (struct serial_icounter_struct *) arg; - error = put_user(cnow.cts, &p_cuser->cts); - if (error) return error; - error = put_user(cnow.dsr, &p_cuser->dsr); - if (error) return error; - error = put_user(cnow.rng, &p_cuser->rng); - if (error) return error; - error = put_user(cnow.dcd, &p_cuser->dcd); - if (error) return error; - error = put_user(cnow.rx, &p_cuser->rx); - if (error) return error; - error = put_user(cnow.tx, &p_cuser->tx); - if (error) return error; - error = put_user(cnow.frame, &p_cuser->frame); - if (error) return error; - error = put_user(cnow.overrun, &p_cuser->overrun); - if (error) return error; - error = put_user(cnow.parity, &p_cuser->parity); - if (error) return error; - error = put_user(cnow.brk, &p_cuser->brk); - if (error) return error; - error = put_user(cnow.buf_overrun, &p_cuser->buf_overrun); - - if (error) return error; - return 0; - - case TIOCSERGWILD: - case TIOCSERSWILD: - /* "setserial -W" is called in Debian boot */ - printk ("TIOCSER?WILD ioctl obsolete, ignored.\n"); - return 0; - - default: - return -ENOIOCTLCMD; - } - return 0; -} - -static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios) -{ - struct async_struct *info = (struct async_struct *)tty->driver_data; - unsigned int cflag = tty->termios->c_cflag; - - if ( (cflag == old_termios->c_cflag) - && ( RELEVANT_IFLAG(tty->termios->c_iflag) - == RELEVANT_IFLAG(old_termios->c_iflag))) - return; - - change_speed(info); - - /* Handle turning off CRTSCTS */ - if ((old_termios->c_cflag & CRTSCTS) && - !(cflag & CRTSCTS)) { - tty->hw_stopped = 0; - rs_start(tty); - } - -} - -/* - * ------------------------------------------------------------ - * rs_close() - * - * This routine is called when the serial port gets closed. First, we - * wait for the last remaining data to be sent. Then, we unlink its - * async structure from the interrupt chain if necessary, and we free - * that IRQ if nothing is left in the chain. - * ------------------------------------------------------------ - */ -static void rs_close(struct tty_struct *tty, struct file * filp) -{ - struct async_struct * info = (struct async_struct *)tty->driver_data; - struct serial_state *state; - unsigned long flags; - - if (!info || serial_paranoia_check(info, tty->name, "rs_close")) - return; - - state = info->state; - - save_flags(flags); cli(); - - if (tty_hung_up_p(filp)) { - DBG_CNT("before DEC-hung"); - MOD_DEC_USE_COUNT; - restore_flags(flags); - return; - } - -#ifdef SERIAL_DEBUG_OPEN - baget_printk("rs_close ttys%d, count = %d\n", - info->line, state->count); -#endif - if ((tty->count == 1) && (state->count != 1)) { - /* - * Uh, oh. tty->count is 1, which means that the tty - * structure will be freed. state->count should always - * be one in these conditions. If it's greater than - * one, we've got real problems, since it means the - * serial port won't be shutdown. - */ - baget_printk("rs_close: bad serial port count; " - "tty->count is 1, " - "state->count is %d\n", state->count); - state->count = 1; - } - if (--state->count < 0) { - baget_printk("rs_close: bad serial port count for " - "ttys%d: %d\n", - info->line, state->count); - state->count = 0; - } - if (state->count) { - DBG_CNT("before DEC-2"); - MOD_DEC_USE_COUNT; - restore_flags(flags); - return; - } - info->flags |= ASYNC_CLOSING; - /* - * Now we wait for the transmit buffer to clear; and we notify - * the line discipline to only process XON/XOFF characters. - */ - tty->closing = 1; - if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE) - tty_wait_until_sent(tty, info->closing_wait); - /* - * At this point we stop accepting input. To do this, we - * disable the receive line status interrupts, and tell the - * interrupt driver to stop checking the data ready bit in the - * line status register. - */ - info->IER &= ~(VAC_UART_INT_RX_BREAK_CHANGE | VAC_UART_INT_RX_ERRS); - info->read_status_mask &= ~VAC_UART_STATUS_RX_READY; - if (info->flags & ASYNC_INITIALIZED) { - serial_outw(info, VAC_UART_INT_MASK, info->IER); - /* - * Before we drop DTR, make sure the UART transmitter - * has completely drained; this is especially - * important if there is a transmit FIFO! - */ - rs_wait_until_sent(tty, info->timeout); - } - shutdown(info); - if (tty->driver->flush_buffer) - tty->driver->flush_buffer(tty); - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); - tty->closing = 0; - info->event = 0; - info->tty = 0; - if (info->blocked_open) { - if (info->close_delay) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(info->close_delay); - } - wake_up_interruptible(&info->open_wait); - } - info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); - wake_up_interruptible(&info->close_wait); - MOD_DEC_USE_COUNT; - restore_flags(flags); -} - -/* - * rs_wait_until_sent() --- wait until the transmitter is empty - */ -static void rs_wait_until_sent(struct tty_struct *tty, int timeout) -{ - struct async_struct * info = (struct async_struct *)tty->driver_data; - unsigned long orig_jiffies, char_time; - int lsr; - - if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent")) - return; - - if (info->state->type == PORT_UNKNOWN) - return; - - if (info->xmit_fifo_size == 0) - return; /* Just in case.... */ - - orig_jiffies = jiffies; - /* - * Set the check interval to be 1/5 of the estimated time to - * send a single character, and make it at least 1. The check - * interval should also be less than the timeout. - * - * Note: we have to use pretty tight timings here to satisfy - * the NIST-PCTS. - */ - char_time = (info->timeout - HZ/50) / info->xmit_fifo_size; - char_time = char_time / 5; - if (char_time == 0) - char_time = 1; - if (timeout) - char_time = MIN(char_time, timeout); -#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT - baget_printk("In rs_wait_until_sent(%d) check=%lu...", - timeout, char_time); - baget_printk("jiff=%lu...", jiffies); -#endif - while (!((lsr = serial_inp(info, VAC_UART_INT_STATUS)) & \ - VAC_UART_STATUS_TX_EMPTY)) { -#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT - baget_printk("lsr = %d (jiff=%lu)...", lsr, jiffies); -#endif - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(char_time); - if (signal_pending(current)) - break; - if (timeout && time_after(jiffies, orig_jiffies + timeout)) - break; - } - current->state = TASK_RUNNING; -#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT - baget_printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); -#endif -} - -/* - * rs_hangup() --- called by tty_hangup() when a hangup is signaled. - */ -static void rs_hangup(struct tty_struct *tty) -{ - struct async_struct * info = (struct async_struct *)tty->driver_data; - struct serial_state *state = info->state; - - if (serial_paranoia_check(info, tty->name, "rs_hangup")) - return; - - state = info->state; - - rs_flush_buffer(tty); - shutdown(info); - info->event = 0; - state->count = 0; - info->flags &= ~ASYNC_NORMAL_ACTIVE; - info->tty = 0; - wake_up_interruptible(&info->open_wait); -} - -/* - * ------------------------------------------------------------ - * rs_open() and friends - * ------------------------------------------------------------ - */ -static int block_til_ready(struct tty_struct *tty, struct file * filp, - struct async_struct *info) -{ - DECLARE_WAITQUEUE(wait, current); - struct serial_state *state = info->state; - int retval; - int do_clocal = 0, extra_count = 0; - unsigned long flags; - - /* - * If the device is in the middle of being closed, then block - * until it's done, and then try again. - */ - if (tty_hung_up_p(filp) || - (info->flags & ASYNC_CLOSING)) { - if (info->flags & ASYNC_CLOSING) - interruptible_sleep_on(&info->close_wait); -#ifdef SERIAL_DO_RESTART - return ((info->flags & ASYNC_HUP_NOTIFY) ? - -EAGAIN : -ERESTARTSYS); -#else - return -EAGAIN; -#endif - } - - /* - * If non-blocking mode is set, or the port is not enabled, - * then make the check up front and then exit. - */ - if ((filp->f_flags & O_NONBLOCK) || - (tty->flags & (1 << TTY_IO_ERROR))) { - info->flags |= ASYNC_NORMAL_ACTIVE; - return 0; - } - - if (tty->termios->c_cflag & CLOCAL) - do_clocal = 1; - - /* - * Block waiting for the carrier detect and the line to become - * free (i.e., not in use by the callout). While we are in - * this loop, state->count is dropped by one, so that - * rs_close() knows when to free things. We restore it upon - * exit, either normal or abnormal. - */ - retval = 0; - add_wait_queue(&info->open_wait, &wait); -#ifdef SERIAL_DEBUG_OPEN - baget_printk("block_til_ready before block: ttys%d, count = %d\n", - state->line, state->count); -#endif - save_flags(flags); cli(); - if (!tty_hung_up_p(filp)) { - extra_count = 1; - state->count--; - } - restore_flags(flags); - info->blocked_open++; - while (1) { - set_current_state(TASK_INTERRUPTIBLE); - if (tty_hung_up_p(filp) || - !(info->flags & ASYNC_INITIALIZED)) { -#ifdef SERIAL_DO_RESTART - if (info->flags & ASYNC_HUP_NOTIFY) - retval = -EAGAIN; - else - retval = -ERESTARTSYS; -#else - retval = -EAGAIN; -#endif - break; - } - if (!(info->flags & ASYNC_CLOSING)) - break; - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } -#ifdef SERIAL_DEBUG_OPEN - baget_printk("block_til_ready blocking: ttys%d, count = %d\n", - info->line, state->count); -#endif - schedule(); - } - current->state = TASK_RUNNING; - remove_wait_queue(&info->open_wait, &wait); - if (extra_count) - state->count++; - info->blocked_open--; -#ifdef SERIAL_DEBUG_OPEN - baget_printk("block_til_ready after blocking: ttys%d, count = %d\n", - info->line, state->count); -#endif - if (retval) - return retval; - info->flags |= ASYNC_NORMAL_ACTIVE; - return 0; -} - -static int get_async_struct(int line, struct async_struct **ret_info) -{ - struct async_struct *info; - struct serial_state *sstate; - - sstate = rs_table + line; - sstate->count++; - if (sstate->info) { - *ret_info = sstate->info; - return 0; - } - info = kmalloc(sizeof(struct async_struct), GFP_KERNEL); - if (!info) { - sstate->count--; - return -ENOMEM; - } - memset(info, 0, sizeof(struct async_struct)); - init_waitqueue_head(&info->open_wait); - init_waitqueue_head(&info->close_wait); - init_waitqueue_head(&info->delta_msr_wait); - info->magic = SERIAL_MAGIC; - info->port = sstate->port; - info->flags = sstate->flags; - info->xmit_fifo_size = sstate->xmit_fifo_size; - info->line = line; - info->tqueue.routine = do_softint; - info->tqueue.data = info; - info->state = sstate; - if (sstate->info) { - kfree(info); - *ret_info = sstate->info; - return 0; - } - *ret_info = sstate->info = info; - return 0; -} - -/* - * This routine is called whenever a serial port is opened. It - * enables interrupts for a serial port, linking in its async structure into - * the IRQ chain. It also performs the serial-specific - * initialization for the tty structure. - */ -static int rs_open(struct tty_struct *tty, struct file * filp) -{ - struct async_struct *info; - int retval, line; - unsigned long page; - - MOD_INC_USE_COUNT; - line = tty->index; - if ((line < 0) || (line >= NR_PORTS)) { - MOD_DEC_USE_COUNT; - return -ENODEV; - } - retval = get_async_struct(line, &info); - if (retval) { - MOD_DEC_USE_COUNT; - return retval; - } - tty->driver_data = info; - info->tty = tty; - if (serial_paranoia_check(info, tty->name, "rs_open")) { - /* MOD_DEC_USE_COUNT; "info->tty" will cause this */ - return -ENODEV; - } - -#ifdef SERIAL_DEBUG_OPEN - baget_printk("rs_open %s, count = %d\n", tty->name, - info->state->count); -#endif - info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; - - if (!tmp_buf) { - page = get_zeroed_page(GFP_KERNEL); - if (!page) { - /* MOD_DEC_USE_COUNT; "info->tty" will cause this */ - return -ENOMEM; - } - if (tmp_buf) - free_page(page); - else - tmp_buf = (unsigned char *) page; - } - - /* - * If the port is the middle of closing, bail out now - */ - if (tty_hung_up_p(filp) || - (info->flags & ASYNC_CLOSING)) { - if (info->flags & ASYNC_CLOSING) - interruptible_sleep_on(&info->close_wait); - /* MOD_DEC_USE_COUNT; "info->tty" will cause this */ -#ifdef SERIAL_DO_RESTART - return ((info->flags & ASYNC_HUP_NOTIFY) ? - -EAGAIN : -ERESTARTSYS); -#else - return -EAGAIN; -#endif - } - - /* - * Start up serial port - */ - retval = startup(info); - if (retval) { - /* MOD_DEC_USE_COUNT; "info->tty" will cause this */ - return retval; - } - - retval = block_til_ready(tty, filp, info); - if (retval) { - /* MOD_DEC_USE_COUNT; "info->tty" will cause this */ -#ifdef SERIAL_DEBUG_OPEN - baget_printk("rs_open returning after block_til_ready " - "with %d\n", - retval); -#endif - return retval; - } - -#ifdef CONFIG_SERIAL_CONSOLE - if (sercons.cflag && sercons.index == line) { - tty->termios->c_cflag = sercons.cflag; - sercons.cflag = 0; - change_speed(info); - } -#endif - -#ifdef SERIAL_DEBUG_OPEN - baget_printk("rs_open %s successful...", tty->name); -#endif - return 0; -} - -/* - * /proc fs routines.... - */ - -static inline int line_info(char *buf, struct serial_state *state) -{ - struct async_struct *info = state->info, scr_info; - int ret; - - ret = sprintf(buf, "%d: uart:%s port:%X irq:%d", - state->line, uart_config[state->type].name, - state->port, state->irq); - - if (!state->port || (state->type == PORT_UNKNOWN)) { - ret += sprintf(buf+ret, "\n"); - return ret; - } - - /* - * Figure out the current RS-232 lines - */ - if (!info) { - info = &scr_info; /* This is just for serial_{in,out} */ - - info->magic = SERIAL_MAGIC; - info->port = state->port; - info->flags = state->flags; - info->quot = 0; - info->tty = 0; - } - - if (info->quot) { - ret += sprintf(buf+ret, " baud:%d", - state->baud_base / info->quot); - } - - ret += sprintf(buf+ret, " tx:%d rx:%d", - state->icount.tx, state->icount.rx); - - if (state->icount.frame) - ret += sprintf(buf+ret, " fe:%d", state->icount.frame); - - if (state->icount.parity) - ret += sprintf(buf+ret, " pe:%d", state->icount.parity); - - if (state->icount.brk) - ret += sprintf(buf+ret, " brk:%d", state->icount.brk); - - if (state->icount.overrun) - ret += sprintf(buf+ret, " oe:%d", state->icount.overrun); - - return ret; -} - -int rs_read_proc(char *page, char **start, off_t off, int count, - int *eof, void *data) -{ - int i, len = 0, l; - off_t begin = 0; - - len += sprintf(page, "serinfo:1.0 driver:%s\n", serial_version); - for (i = 0; i < NR_PORTS && len < 4000; i++) { - l = line_info(page + len, &rs_table[i]); - len += l; - if (len+begin > off+count) - goto done; - if (len+begin < off) { - begin += len; - len = 0; - } - } - *eof = 1; -done: - if (off >= len+begin) - return 0; - *start = page + (off-begin); - return ((count < begin+len-off) ? count : begin+len-off); -} - -/* - * --------------------------------------------------------------------- - * rs_init() and friends - * - * rs_init() is called at boot-time to initialize the serial driver. - * --------------------------------------------------------------------- - */ - -/* - * This routine prints out the appropriate serial driver version - * number, and identifies which options were configured into this - * driver. - */ -static _INLINE_ void show_serial_version(void) -{ - printk(KERN_INFO "%s version %s with", serial_name, serial_version); -#ifdef CONFIG_SERIAL_SHARE_IRQ - printk(" SHARE_IRQ"); -#endif -#define SERIAL_OPT -#ifdef CONFIG_SERIAL_DETECT_IRQ - printk(" DETECT_IRQ"); -#endif -#ifdef SERIAL_OPT - printk(" enabled\n"); -#else - printk(" no serial options enabled\n"); -#endif -#undef SERIAL_OPT -} - - -/* - * This routine is called by rs_init() to initialize a specific serial - * port. It determines what type of UART chip this serial port is - * using: 8250, 16450, 16550, 16550A. The important question is - * whether or not this UART is a 16550A or not, since this will - * determine whether or not we can use its FIFO features or not. - */ - -/* - * Functionality of this function is reduced: we already know we have a VAC, - * but still need to perform some important actions (see code :-). - */ -static void autoconfig(struct serial_state * state) -{ - struct async_struct *info, scr_info; - unsigned long flags; - - /* Setting up important parameters */ - state->type = VAC_UART_TYPE; - state->xmit_fifo_size = uart_config[state->type].dfl_xmit_fifo_size; - - info = &scr_info; /* This is just for serial_{in,out} */ - - info->magic = SERIAL_MAGIC; - info->port = state->port; - info->flags = state->flags; - - save_flags(flags); cli(); - - /* + Flush VAC input fifo */ - (void)serial_in(info, VAC_UART_RX); - (void)serial_in(info, VAC_UART_RX); - (void)serial_in(info, VAC_UART_RX); - (void)serial_in(info, VAC_UART_RX); - - /* Disable interrupts */ - serial_outp(info, VAC_UART_INT_MASK, 0); - - restore_flags(flags); -} - -int register_serial(struct serial_struct *req); -void unregister_serial(int line); - -EXPORT_SYMBOL(register_serial); -EXPORT_SYMBOL(unregister_serial); - -/* - * Important function for VAC UART check and reanimation. - */ - -static void rs_timer(unsigned long dummy) -{ - static unsigned long last_strobe = 0; - struct async_struct *info; - unsigned int i; - unsigned long flags; - - if ((jiffies - last_strobe) >= RS_STROBE_TIME) { - for (i=1; i < NR_IRQS; i++) { - info = IRQ_ports[i]; - if (!info) - continue; - save_flags(flags); cli(); -#ifdef CONFIG_SERIAL_SHARE_IRQ - if (info->next_port) { - do { - serial_out(info, VAC_UART_INT_MASK, 0); - info->IER |= VAC_UART_INT_TX_EMPTY; - serial_out(info, VAC_UART_INT_MASK, - info->IER); - info = info->next_port; - } while (info); - rs_interrupt(i, NULL, NULL); - } else -#endif /* CONFIG_SERIAL_SHARE_IRQ */ - rs_interrupt_single(i, NULL, NULL); - restore_flags(flags); - } - } - last_strobe = jiffies; - mod_timer(&vacs_timer, jiffies + RS_STROBE_TIME); - - /* - * It looks this code for case we share IRQ with console... - */ - - if (IRQ_ports[0]) { - save_flags(flags); cli(); -#ifdef CONFIG_SERIAL_SHARE_IRQ - rs_interrupt(0, NULL, NULL); -#else - rs_interrupt_single(0, NULL, NULL); -#endif - restore_flags(flags); - - mod_timer(&vacs_timer, jiffies + IRQ_timeout[0] - 2); - } -} - -static struct tty_operations rs_ops = { - .open = rs_open, - .close = rs_close, - .write = rs_write, - .put_char = rs_put_char, - .flush_chars = rs_flush_chars, - .write_room = rs_write_room, - .chars_in_buffer = rs_chars_in_buffer, - .flush_buffer = rs_flush_buffer, - .ioctl = rs_ioctl, - .throttle = rs_throttle, - .unthrottle = rs_unthrottle, - .send_xchar = rs_send_xchar, - .set_termios = rs_set_termios, - .stop = rs_stop, - .start = rs_start, - .hangup = rs_hangup, - .break_ctl = rs_break, - .wait_until_sent = rs_wait_until_sent, - .read_proc = rs_read_proc, -}; - -/* - * The serial driver boot-time initialization code! - */ -int __init rs_init(void) -{ - int i; - struct serial_state * state; - extern void atomwide_serial_init (void); - extern void dualsp_serial_init (void); - -#ifdef CONFIG_ATOMWIDE_SERIAL - atomwide_serial_init (); -#endif -#ifdef CONFIG_DUALSP_SERIAL - dualsp_serial_init (); -#endif - - init_bh(SERIAL_BH, do_serial_bh); - init_timer(&vacs_timer); - vacs_timer.function = rs_timer; - vacs_timer.expires = 0; - - for (i = 0; i < NR_IRQS; i++) { - IRQ_ports[i] = 0; - IRQ_timeout[i] = 0; - } - - -/* - * It is not a good idea to share interrupts with console, - * but it looks we cannot avoid it. - */ -#if 0 - -#ifdef CONFIG_SERIAL_CONSOLE - /* - * The interrupt of the serial console port - * can't be shared. - */ - if (sercons.flags & CON_CONSDEV) { - for(i = 0; i < NR_PORTS; i++) - if (i != sercons.index && - rs_table[i].irq == rs_table[sercons.index].irq) - rs_table[i].irq = 0; - } -#endif - -#endif - serial_driver = alloc_tty_driver(NR_PORTS); - if (!serial_driver) - return -ENOMEM; - - show_serial_version(); - - /* Initialize the tty_driver structure */ - - serial_driver->driver_name = "serial"; - serial_driver->name = "ttyS"; - serial_driver->major = TTY_MAJOR; - serial_driver->minor_start = 64; - serial_driver->type = TTY_DRIVER_TYPE_SERIAL; - serial_driver->subtype = SERIAL_TYPE_NORMAL; - serial_driver->init_termios = tty_std_termios; - serial_driver->init_termios.c_cflag = - B9600 | CS8 | CREAD | HUPCL | CLOCAL; - serial_driver->flags = TTY_DRIVER_REAL_RAW; - tty_set_operations(serial_driver, &rs_ops); - - if (tty_register_driver(serial_driver)) - panic("Couldn't register serial driver\n"); - - for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) { - state->magic = SSTATE_MAGIC; - state->line = i; - state->type = PORT_UNKNOWN; - state->custom_divisor = 0; - state->close_delay = 5*HZ/10; - state->closing_wait = 30*HZ; - state->icount.cts = state->icount.dsr = - state->icount.rng = state->icount.dcd = 0; - state->icount.rx = state->icount.tx = 0; - state->icount.frame = state->icount.parity = 0; - state->icount.overrun = state->icount.brk = 0; - state->irq = state->irq; - if (check_region(state->port,8)) - continue; - if (state->flags & ASYNC_BOOT_AUTOCONF) - autoconfig(state); - } - - /* - * Detect the IRQ only once every port is initialised, - * because some 16450 do not reset to 0 the MCR register. - */ - for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) { - if (state->type == PORT_UNKNOWN) - continue; - printk(KERN_INFO "ttyS%02d%s at 0x%04x (irq = %d) is a %s\n", - state->line, - (state->flags & ASYNC_FOURPORT) ? " FourPort" : "", - state->port, state->irq, - uart_config[state->type].name); - } - return 0; -} - -/* - * register_serial and unregister_serial allows for serial ports to be - * configured at run-time, to support PCMCIA modems. - */ -int register_serial(struct serial_struct *req) -{ - int i; - unsigned long flags; - struct serial_state *state; - - save_flags(flags); - cli(); - for (i = 0; i < NR_PORTS; i++) { - if (rs_table[i].port == req->port) - break; - } - if (i == NR_PORTS) { - for (i = 0; i < NR_PORTS; i++) - if ((rs_table[i].type == PORT_UNKNOWN) && - (rs_table[i].count == 0)) - break; - } - if (i == NR_PORTS) { - restore_flags(flags); - return -1; - } - state = &rs_table[i]; - if (rs_table[i].count) { - restore_flags(flags); - printk("Couldn't configure serial #%d (port=%d,irq=%d): " - "device already open\n", i, req->port, req->irq); - return -1; - } - state->irq = req->irq; - state->port = req->port; - state->flags = req->flags; - - autoconfig(state); - if (state->type == PORT_UNKNOWN) { - restore_flags(flags); - printk("register_serial(): autoconfig failed\n"); - return -1; - } - restore_flags(flags); - - printk(KERN_INFO "tty%02d at 0x%04x (irq = %d) is a %s\n", - state->line, state->port, state->irq, - uart_config[state->type].name); - return state->line; -} - -void unregister_serial(int line) -{ - unsigned long flags; - struct serial_state *state = &rs_table[line]; - - save_flags(flags); - cli(); - if (state->info && state->info->tty) - tty_hangup(state->info->tty); - state->type = PORT_UNKNOWN; - printk(KERN_INFO "tty%02d unloaded\n", state->line); - restore_flags(flags); -} - -#ifdef MODULE -int init_module(void) -{ - return rs_init(); -} - -void cleanup_module(void) -{ - unsigned long flags; - int e1, e2; - int i; - - printk("Unloading %s: version %s\n", serial_name, serial_version); - save_flags(flags); - cli(); - - del_timer_sync(&vacs_timer); - remove_bh(SERIAL_BH); - - if ((e1 = tty_unregister_driver(serial_driver))) - printk("SERIAL: failed to unregister serial driver (%d)\n", - e1); - restore_flags(flags); - put_tty_driver(serial_driver); - - for (i = 0; i < NR_PORTS; i++) { - if (rs_table[i].type != PORT_UNKNOWN) - release_region(rs_table[i].port, 8); - } - if (tmp_buf) { - free_page((unsigned long) tmp_buf); - tmp_buf = NULL; - } -} -#endif /* MODULE */ - - -/* - * ------------------------------------------------------------ - * Serial console driver - * ------------------------------------------------------------ - */ -#ifdef CONFIG_SERIAL_CONSOLE - -#define BOTH_EMPTY (VAC_UART_STATUS_TX_EMPTY | VAC_UART_STATUS_TX_EMPTY) - -/* - * Wait for transmitter & holding register to empty - */ -static inline void wait_for_xmitr(struct async_struct *info) -{ - int lsr; - unsigned int tmout = 1000000; - - do { - lsr = serial_inp(info, VAC_UART_INT_STATUS); - if (--tmout == 0) break; - } while ((lsr & BOTH_EMPTY) != BOTH_EMPTY); -} - -/* - * Print a string to the serial port trying not to disturb - * any possible real use of the port... - */ -static void serial_console_write(struct console *co, const char *s, - unsigned count) -{ - struct serial_state *ser; - int ier; - unsigned i; - struct async_struct scr_info; /* serial_{in,out} because HUB6 */ - - ser = rs_table + co->index; - scr_info.magic = SERIAL_MAGIC; - scr_info.port = ser->port; - scr_info.flags = ser->flags; - - /* - * First save the IER then disable the interrupts - */ - ier = serial_inp(&scr_info, VAC_UART_INT_MASK); - serial_outw(&scr_info, VAC_UART_INT_MASK, 0x00); - - /* - * Now, do each character - */ - for (i = 0; i < count; i++, s++) { - wait_for_xmitr(&scr_info); - - /* - * Send the character out. - * If a LF, also do CR... - */ - serial_outp(&scr_info, VAC_UART_TX, (unsigned short)*s << 8); - if (*s == 10) { - wait_for_xmitr(&scr_info); - serial_outp(&scr_info, VAC_UART_TX, 13 << 8); - } - } - - /* - * Finally, Wait for transmitter & holding register to empty - * and restore the IER - */ - wait_for_xmitr(&scr_info); - serial_outp(&scr_info, VAC_UART_INT_MASK, ier); -} - -static struct tty_driver *serial_console_device(struct console *c, int *index) -{ - *index = c->index; - return serial_driver; -} - -/* - * Setup initial baud/bits/parity. We do two things here: - * - construct a cflag setting for the first rs_open() - * - initialize the serial port - * Return non-zero if we didn't find a serial port. - */ -static int __init serial_console_setup(struct console *co, char *options) -{ - struct serial_state *ser; - unsigned cval; - int baud = 9600; - int bits = 8; - int parity = 'n'; - int cflag = CREAD | HUPCL | CLOCAL; - int quot = 0; - char *s; - struct async_struct scr_info; /* serial_{in,out} because HUB6 */ - - if (options) { - baud = simple_strtoul(options, NULL, 10); - s = options; - while(*s >= '0' && *s <= '9') - s++; - if (*s) parity = *s++; - if (*s) bits = *s - '0'; - } - - /* - * Now construct a cflag setting. - */ - switch(baud) { - case 1200: - cflag |= B1200; - break; - case 2400: - cflag |= B2400; - break; - case 4800: - cflag |= B4800; - break; - case 19200: - cflag |= B19200; - break; - case 38400: - cflag |= B38400; - break; - case 57600: - cflag |= B57600; - break; - case 115200: - cflag |= B115200; - break; - case 9600: - default: - cflag |= B9600; - break; - } - switch(bits) { - case 7: - cflag |= CS7; - break; - default: - case 8: - cflag |= CS8; - break; - } - switch(parity) { - case 'o': case 'O': - cflag |= PARODD; - break; - case 'e': case 'E': - cflag |= PARENB; - break; - } - co->cflag = cflag; - - /* - * Divisor, bytesize and parity - */ - ser = rs_table + co->index; - scr_info.magic = SERIAL_MAGIC; - scr_info.port = ser->port; - scr_info.flags = ser->flags; - - quot = ser->baud_base / baud; - cval = cflag & (CSIZE | CSTOPB); - - cval >>= 4; - - cval &= ~VAC_UART_MODE_PARITY_ENABLE; - if (cflag & PARENB) - cval |= VAC_UART_MODE_PARITY_ENABLE; - if (cflag & PARODD) - cval |= VAC_UART_MODE_PARITY_ODD; - - /* - * Disable UART interrupts, set DTR and RTS high - * and set speed. - */ - switch (baud) { - default: - case 9600: - cval |= VAC_UART_MODE_BAUD(7); - break; - case 4800: - cval |= VAC_UART_MODE_BAUD(6); - break; - case 2400: - cval |= VAC_UART_MODE_BAUD(5); - break; - case 1200: - cval |= VAC_UART_MODE_BAUD(4); - break; - case 600: - cval |= VAC_UART_MODE_BAUD(3); - break; - case 300: - cval |= VAC_UART_MODE_BAUD(2); - break; -#ifndef QUAD_UART_SPEED - case 150: -#else - case 38400: -#endif - cval |= VAC_UART_MODE_BAUD(1); - break; -#ifndef QUAD_UART_SPEED - case 75: -#else - case 19200: -#endif - cval |= VAC_UART_MODE_BAUD(0); - break; - } - - /* Baget VAC need some adjustments for computed value */ - cval = vac_uart_mode_fixup(cval); - - serial_outp(&scr_info, VAC_UART_MODE, cval); - serial_outp(&scr_info, VAC_UART_INT_MASK, 0); - - return 0; -} - -static struct console sercons = { - .name = "ttyS", - .write = serial_console_write, - .device = serial_console_device, - .setup = serial_console_setup, - .flags = CON_PRINTBUFFER, - .index = -1, -}; - -/* - * Register console. - */ -long __init serial_console_init(long kmem_start, long kmem_end) -{ - register_console(&sercons); - return kmem_start; -} -#endif - -#ifdef CONFIG_REMOTE_DEBUG -#undef PRINT_DEBUG_PORT_INFO - -/* - * This is the interface to the remote debugger stub. - * I've put that here to be able to control the serial - * device more directly. - */ - -static int initialized; - -static int rs_debug_init(struct async_struct *info) -{ - int quot; - - autoconfig(info); /* autoconfigure ttyS0, whatever that is */ - -#ifdef PRINT_DEBUG_PORT_INFO - baget_printk("kgdb debug interface:: tty%02d at 0x%04x", - info->line, info->port); - switch (info->type) { - case PORT_8250: - baget_printk(" is a 8250\n"); - break; - case PORT_16450: - baget_printk(" is a 16450\n"); - break; - case PORT_16550: - baget_printk(" is a 16550\n"); - break; - case PORT_16550A: - baget_printk(" is a 16550A\n"); - break; - case PORT_16650: - baget_printk(" is a 16650\n"); - break; - default: - baget_printk(" is of unknown type -- unusable\n"); - break; - } -#endif - - if (info->port == PORT_UNKNOWN) - return -1; - - /* - * Clear all interrupts - */ - - (void)serial_inp(info, VAC_UART_INT_STATUS); - (void)serial_inp(info, VAC_UART_RX); - - /* - * Now, initialize the UART - */ - serial_outp(info,VAC_UART_MODE,VAC_UART_MODE_INITIAL); /* reset DLAB */ - if (info->flags & ASYNC_FOURPORT) { - info->MCR = UART_MCR_DTR | UART_MCR_RTS; - info->MCR_noint = UART_MCR_DTR | UART_MCR_OUT1; - } else { - info->MCR = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2; - info->MCR_noint = UART_MCR_DTR | UART_MCR_RTS; - } - - info->MCR = info->MCR_noint; /* no interrupts, please */ - /* - * and set the speed of the serial port - * (currently hardwired to 9600 8N1 - */ - - quot = info->baud_base / 9600; /* baud rate is fixed to 9600 */ - /* FIXME: if rs_debug interface is needed, we need to set speed here */ - - return 0; -} - -int putDebugChar(char c) -{ - struct async_struct *info = rs_table; - - if (!initialized) { /* need to init device first */ - if (rs_debug_init(info) == 0) - initialized = 1; - else - return 0; - } - - while ((serial_inw(info, VAC_UART_INT_STATUS) & \ - VAC_UART_STATUS_TX_EMPTY) == 0) - ; - serial_out(info, VAC_UART_TX, (unsigned short)c << 8); - - return 1; -} - -char getDebugChar(void) -{ - struct async_struct *info = rs_table; - - if (!initialized) { /* need to init device first */ - if (rs_debug_init(info) == 0) - initialized = 1; - else - return 0; - } - while (!(serial_inw(info, VAC_UART_INT_STATUS) & \ - VAC_UART_STATUS_RX_READY)) - ; - - return(serial_inp(info, VAC_UART_RX)); -} - -#endif /* CONFIG_REMOTE_DEBUG */ diff -Nru a/arch/mips/baget/wbflush.c b/arch/mips/baget/wbflush.c --- a/arch/mips/baget/wbflush.c Tue Jul 1 18:44:36 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,24 +0,0 @@ -/* - * Setup the right wbflush routine for Baget/MIPS. - * - * Copyright (C) 1999 Gleb Raiko & Vladimir Roganov - */ - -#include -#include - -void (*__wbflush) (void); - -static void wbflush_baget(void); - -void __init wbflush_setup(void) -{ - __wbflush = wbflush_baget; -} - -/* - * Baget/MIPS doesn't need to write back the WB. - */ -static void wbflush_baget(void) -{ -} diff -Nru a/arch/mips/boot/Makefile b/arch/mips/boot/Makefile --- a/arch/mips/boot/Makefile Tue Jul 1 18:44:37 2003 +++ b/arch/mips/boot/Makefile Tue Jul 1 18:44:37 2003 @@ -3,11 +3,9 @@ # License. See the file "COPYING" in the main directory of this archive # for more details. # -# Copyright (C) 1995, 1998, 2001 by Ralf Baechle +# Copyright (C) 1995, 1998, 2001, 2002 by Ralf Baechle # -OBJS = milo.o a.out.o - # # Some DECstations need all possible sections of an ECOFF executable # @@ -21,25 +19,33 @@ # Drop some uninteresting sections in the kernel. # This is only relevant for ELF kernels but doesn't hurt a.out # -drop-sections = .reginfo .mdebug +drop-sections = .reginfo .mdebug .comment .note strip-flags = $(addprefix --remove-section=,$(drop-sections)) all: vmlinux.ecoff addinitrd -vmlinux.ecoff: elf2ecoff $(TOPDIR)/vmlinux - ./elf2ecoff $(TOPDIR)/vmlinux vmlinux.ecoff $(E2EFLAGS) +vmlinux.rm200: vmlinux + $(OBJCOPY) \ + --change-addresses=0xfffffffc \ + -O elf32-tradlittlemips \ + $(strip-flags) \ + $< $@ + +vmlinux.ecoff: $(obj)/elf2ecoff vmlinux + ./elf2ecoff vmlinux $(obj)/vmlinux.ecoff $(E2EFLAGS) -elf2ecoff: elf2ecoff.c +$(obj)/elf2ecoff: $(obj)/elf2ecoff.c $(HOSTCC) -o $@ $^ -addinitrd: addinitrd.c +$(obj)/addinitrd: $(obj)/addinitrd.c $(HOSTCC) -o $@ $^ -clean: - rm -f vmlinux.ecoff - rm -f zImage zImage.tmp - -mrproper: - rm -f vmlinux.ecoff - rm -f addinitrd - rm -f elf2ecoff +archhelp: + @echo '* vmlinux.rm200 - Bootable kernel image for RM200C' + +CLEAN_FILES += addinitrd \ + elf2ecoff \ + vmlinux.ecoff \ + vmlinux.rm200 \ + zImage.tmp \ + zImage diff -Nru a/arch/mips/boot/addinitrd.c b/arch/mips/boot/addinitrd.c --- a/arch/mips/boot/addinitrd.c Tue Jul 1 18:44:36 2003 +++ b/arch/mips/boot/addinitrd.c Tue Jul 1 18:44:36 2003 @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include "ecoff.h" @@ -44,7 +46,7 @@ char buf[1024]; unsigned long loadaddr; unsigned long initrd_header[2]; - int i; + int i,cnt; int swab = 0; if (argc != 4) { @@ -60,7 +62,6 @@ die ("read aout header"); if (read (fd_vmlinux, esecs, sizeof esecs) != sizeof esecs) die ("read section headers"); - /* * check whether the file is good for us */ @@ -81,7 +82,7 @@ die ("open initrd"); if (fstat (fd_initrd, &st) < 0) die ("fstat initrd"); - loadaddr = ((SWAB(esecs[2].s_vaddr) + SWAB(esecs[2].s_size) + loadaddr = ((SWAB(esecs[2].s_vaddr) + SWAB(esecs[2].s_size) + MIPS_PAGE_SIZE-1) & ~MIPS_PAGE_MASK) - 8; if (loadaddr < (SWAB(esecs[2].s_vaddr) + SWAB(esecs[2].s_size))) loadaddr += MIPS_PAGE_SIZE; @@ -98,9 +99,20 @@ die ("write aout header"); if (write (fd_outfile, esecs, sizeof esecs) != sizeof esecs) die ("write section headers"); - while ((i = read (fd_vmlinux, buf, sizeof buf)) > 0) + /* skip padding */ + if(lseek(fd_vmlinux, SWAB(esecs[0].s_scnptr), SEEK_SET) == (off_t)-1) + die ("lseek vmlinux"); + if(lseek(fd_outfile, SWAB(esecs[0].s_scnptr), SEEK_SET) == (off_t)-1) + die ("lseek outfile"); + /* copy text segment */ + cnt = SWAB(eaout.tsize); + while (cnt) { + if ((i = read (fd_vmlinux, buf, sizeof buf)) <= 0) + die ("read vmlinux"); if (write (fd_outfile, buf, i) != i) die ("write vmlinux"); + cnt -= i; + } if (write (fd_outfile, initrd_header, sizeof initrd_header) != sizeof initrd_header) die ("write initrd header"); while ((i = read (fd_initrd, buf, sizeof buf)) > 0) diff -Nru a/arch/mips/boot/elf2ecoff.c b/arch/mips/boot/elf2ecoff.c --- a/arch/mips/boot/elf2ecoff.c Tue Jul 1 18:44:39 2003 +++ b/arch/mips/boot/elf2ecoff.c Tue Jul 1 18:44:39 2003 @@ -41,487 +41,114 @@ #include #include #include +#include +#include #include "ecoff.h" /* * Some extra ELF definitions */ -#define PT_MIPS_REGINFO 0x70000000 /* Register usage information */ +#define PT_MIPS_REGINFO 0x70000000 /* Register usage information */ /* -------------------------------------------------------------------- */ struct sect { - unsigned long vaddr; - unsigned long len; + unsigned long vaddr; + unsigned long len; }; -int phcmp (); -char *saveRead (int file, off_t offset, off_t len, char *name); -int copy (int, int, off_t, off_t); -int translate_syms (int, int, off_t, off_t, off_t, off_t); -void convert_elf_hdr (Elf32_Ehdr *); -void convert_elf_phdrs (Elf32_Phdr *, int); -void convert_elf_shdrs (Elf32_Shdr *, int); -void convert_ecoff_filehdr(struct filehdr *); -void convert_ecoff_aouthdr(struct aouthdr *); -void convert_ecoff_esecs(struct scnhdr *, int); -extern int errno; int *symTypeTable; int must_convert_endian = 0; int format_bigendian = 0; -main (int argc, char **argv, char **envp) +static void copy(int out, int in, off_t offset, off_t size) { - Elf32_Ehdr ex; - Elf32_Phdr *ph; - Elf32_Shdr *sh; - Elf32_Sym *symtab; - char *shstrtab; - int strtabix, symtabix; - int i, pad; - struct sect text, data, bss; - struct filehdr efh; - struct aouthdr eah; - struct scnhdr esecs [6]; - int infile, outfile; - unsigned long cur_vma = ULONG_MAX; - int addflag = 0; - int nosecs; - - text.len = data.len = bss.len = 0; - text.vaddr = data.vaddr = bss.vaddr = 0; - - /* Check args... */ - if (argc < 3 || argc > 4) - { - usage: - fprintf (stderr, - "usage: elf2aout [-a]\n"); - exit (1); - } - if (argc == 4) - { - if (strcmp (argv [3], "-a")) - goto usage; - addflag = 1; - } - - /* Try the input file... */ - if ((infile = open (argv [1], O_RDONLY)) < 0) - { - fprintf (stderr, "Can't open %s for read: %s\n", - argv [1], strerror (errno)); - exit (1); - } - - /* Read the header, which is at the beginning of the file... */ - i = read (infile, &ex, sizeof ex); - if (i != sizeof ex) - { - fprintf (stderr, "ex: %s: %s.\n", - argv [1], i ? strerror (errno) : "End of file reached"); - exit (1); - } - - if (ex.e_ident[EI_DATA] == ELFDATA2MSB) - format_bigendian = 1; - - if (ntohs (0xaa55) == 0xaa55) { - if (!format_bigendian) - must_convert_endian = 1; - } else { - if (format_bigendian) - must_convert_endian = 1; - } - if (must_convert_endian) - convert_elf_hdr (&ex); - - /* Read the program headers... */ - ph = (Elf32_Phdr *)saveRead (infile, ex.e_phoff, - ex.e_phnum * sizeof (Elf32_Phdr), "ph"); - if (must_convert_endian) - convert_elf_phdrs (ph, ex.e_phnum); - /* Read the section headers... */ - sh = (Elf32_Shdr *)saveRead (infile, ex.e_shoff, - ex.e_shnum * sizeof (Elf32_Shdr), "sh"); - if (must_convert_endian) - convert_elf_shdrs (sh, ex.e_shnum); - /* Read in the section string table. */ - shstrtab = saveRead (infile, sh [ex.e_shstrndx].sh_offset, - sh [ex.e_shstrndx].sh_size, "shstrtab"); - - /* Figure out if we can cram the program header into an ECOFF - header... Basically, we can't handle anything but loadable - segments, but we can ignore some kinds of segments. We can't - handle holes in the address space. Segments may be out of order, - so we sort them first. */ - - qsort (ph, ex.e_phnum, sizeof (Elf32_Phdr), phcmp); - - for (i = 0; i < ex.e_phnum; i++) - { - /* Section types we can ignore... */ - if (ph [i].p_type == PT_NULL || ph [i].p_type == PT_NOTE || - ph [i].p_type == PT_PHDR || ph [i].p_type == PT_MIPS_REGINFO) - continue; - /* Section types we can't handle... */ - else if (ph [i].p_type != PT_LOAD) - { - fprintf (stderr, "Program header %d type %d can't be converted.\n"); - exit (1); - } - /* Writable (data) segment? */ - if (ph [i].p_flags & PF_W) - { - struct sect ndata, nbss; - - ndata.vaddr = ph [i].p_vaddr; - ndata.len = ph [i].p_filesz; - nbss.vaddr = ph [i].p_vaddr + ph [i].p_filesz; - nbss.len = ph [i].p_memsz - ph [i].p_filesz; - - combine (&data, &ndata, 0); - combine (&bss, &nbss, 1); - } - else - { - struct sect ntxt; - - ntxt.vaddr = ph [i].p_vaddr; - ntxt.len = ph [i].p_filesz; - - combine (&text, &ntxt, 0); - } - /* Remember the lowest segment start address. */ - if (ph [i].p_vaddr < cur_vma) - cur_vma = ph [i].p_vaddr; - } - - /* Sections must be in order to be converted... */ - if (text.vaddr > data.vaddr || data.vaddr > bss.vaddr || - text.vaddr + text.len > data.vaddr || data.vaddr + data.len > bss.vaddr) - { - fprintf (stderr, "Sections ordering prevents a.out conversion.\n"); - exit (1); - } - - /* If there's a data section but no text section, then the loader - combined everything into one section. That needs to be the - text section, so just make the data section zero length following - text. */ - if (data.len && !text.len) - { - text = data; - data.vaddr = text.vaddr + text.len; - data.len = 0; - } - - /* If there is a gap between text and data, we'll fill it when we copy - the data, so update the length of the text segment as represented in - a.out to reflect that, since a.out doesn't allow gaps in the program - address space. */ - if (text.vaddr + text.len < data.vaddr) - text.len = data.vaddr - text.vaddr; - - /* We now have enough information to cons up an a.out header... */ - eah.magic = OMAGIC; - eah.vstamp = 200; - eah.tsize = text.len; - eah.dsize = data.len; - eah.bsize = bss.len; - eah.entry = ex.e_entry; - eah.text_start = text.vaddr; - eah.data_start = data.vaddr; - eah.bss_start = bss.vaddr; - eah.gprmask = 0xf3fffffe; - memset (&eah.cprmask, '\0', sizeof eah.cprmask); - eah.gp_value = 0; /* unused. */ - - if (format_bigendian) - efh.f_magic = MIPSEBMAGIC; - else - efh.f_magic = MIPSELMAGIC; - if (addflag) - nosecs = 6; - else - nosecs = 3; - efh.f_nscns = nosecs; - efh.f_timdat = 0; /* bogus */ - efh.f_symptr = 0; - efh.f_nsyms = 0; - efh.f_opthdr = sizeof eah; - efh.f_flags = 0x100f; /* Stripped, not sharable. */ - - memset (esecs, 0, sizeof esecs); - strcpy (esecs [0].s_name, ".text"); - strcpy (esecs [1].s_name, ".data"); - strcpy (esecs [2].s_name, ".bss"); - if (addflag) { - strcpy (esecs [3].s_name, ".rdata"); - strcpy (esecs [4].s_name, ".sdata"); - strcpy (esecs [5].s_name, ".sbss"); - } - esecs [0].s_paddr = esecs [0].s_vaddr = eah.text_start; - esecs [1].s_paddr = esecs [1].s_vaddr = eah.data_start; - esecs [2].s_paddr = esecs [2].s_vaddr = eah.bss_start; - if (addflag) { - esecs [3].s_paddr = esecs [3].s_vaddr = 0; - esecs [4].s_paddr = esecs [4].s_vaddr = 0; - esecs [5].s_paddr = esecs [5].s_vaddr = 0; - } - esecs [0].s_size = eah.tsize; - esecs [1].s_size = eah.dsize; - esecs [2].s_size = eah.bsize; - if (addflag) { - esecs [3].s_size = 0; - esecs [4].s_size = 0; - esecs [5].s_size = 0; - } - esecs [0].s_scnptr = N_TXTOFF (efh, eah); - esecs [1].s_scnptr = N_DATOFF (efh, eah); -#define ECOFF_SEGMENT_ALIGNMENT(a) 0x10 -#define ECOFF_ROUND(s,a) (((s)+(a)-1)&~((a)-1)) - esecs [2].s_scnptr = esecs [1].s_scnptr + - ECOFF_ROUND (esecs [1].s_size, ECOFF_SEGMENT_ALIGNMENT (&eah)); - if (addflag) { - esecs [3].s_scnptr = 0; - esecs [4].s_scnptr = 0; - esecs [5].s_scnptr = 0; - } - esecs [0].s_relptr = esecs [1].s_relptr - = esecs [2].s_relptr = 0; - esecs [0].s_lnnoptr = esecs [1].s_lnnoptr - = esecs [2].s_lnnoptr = 0; - esecs [0].s_nreloc = esecs [1].s_nreloc = esecs [2].s_nreloc = 0; - esecs [0].s_nlnno = esecs [1].s_nlnno = esecs [2].s_nlnno = 0; - if (addflag) { - esecs [3].s_relptr = esecs [4].s_relptr - = esecs [5].s_relptr = 0; - esecs [3].s_lnnoptr = esecs [4].s_lnnoptr - = esecs [5].s_lnnoptr = 0; - esecs [3].s_nreloc = esecs [4].s_nreloc = esecs [5].s_nreloc = 0; - esecs [3].s_nlnno = esecs [4].s_nlnno = esecs [5].s_nlnno = 0; - } - esecs [0].s_flags = 0x20; - esecs [1].s_flags = 0x40; - esecs [2].s_flags = 0x82; - if (addflag) { - esecs [3].s_flags = 0x100; - esecs [4].s_flags = 0x200; - esecs [5].s_flags = 0x400; - } - - /* Make the output file... */ - if ((outfile = open (argv [2], O_WRONLY | O_CREAT, 0777)) < 0) - { - fprintf (stderr, "Unable to create %s: %s\n", argv [2], strerror (errno)); - exit (1); - } - - if (must_convert_endian) - convert_ecoff_filehdr (&efh); - /* Write the headers... */ - i = write (outfile, &efh, sizeof efh); - if (i != sizeof efh) - { - perror ("efh: write"); - exit (1); - - for (i = 0; i < nosecs; i++) - { - printf ("Section %d: %s phys %x size %x file offset %x\n", - i, esecs [i].s_name, esecs [i].s_paddr, - esecs [i].s_size, esecs [i].s_scnptr); - } - } - fprintf (stderr, "wrote %d byte file header.\n", i); - - if (must_convert_endian) - convert_ecoff_aouthdr (&eah); - i = write (outfile, &eah, sizeof eah); - if (i != sizeof eah) - { - perror ("eah: write"); - exit (1); - } - fprintf (stderr, "wrote %d byte a.out header.\n", i); - - if (must_convert_endian) - convert_ecoff_esecs (&esecs[0], nosecs); - i = write (outfile, &esecs, nosecs * sizeof(struct scnhdr)); - if (i != nosecs * sizeof(struct scnhdr)) - { - perror ("esecs: write"); - exit (1); - } - fprintf (stderr, "wrote %d bytes of section headers.\n", i); - - if (pad = ((sizeof efh + sizeof eah + nosecs * sizeof(struct scnhdr)) & 15)) - { - pad = 16 - pad; - i = write (outfile, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0", pad); - if (i < 0) - { - perror ("ipad: write"); - exit (1); - } - fprintf (stderr, "wrote %d byte pad.\n", i); - } + char ibuf[4096]; + int remaining, cur, count; - /* Copy the loadable sections. Zero-fill any gaps less than 64k; - complain about any zero-filling, and die if we're asked to zero-fill - more than 64k. */ - for (i = 0; i < ex.e_phnum; i++) - { - /* Unprocessable sections were handled above, so just verify that - the section can be loaded before copying. */ - if (ph [i].p_type == PT_LOAD && ph [i].p_filesz) - { - if (cur_vma != ph [i].p_vaddr) - { - unsigned long gap = ph [i].p_vaddr - cur_vma; - char obuf [1024]; - if (gap > 65536) - { - fprintf (stderr, "Intersegment gap (%d bytes) too large.\n", - gap); - exit (1); + /* Go to the start of the ELF symbol table... */ + if (lseek(in, offset, SEEK_SET) < 0) { + perror("copy: lseek"); + exit(1); + } + + remaining = size; + while (remaining) { + cur = remaining; + if (cur > sizeof ibuf) + cur = sizeof ibuf; + remaining -= cur; + if ((count = read(in, ibuf, cur)) != cur) { + fprintf(stderr, "copy: read: %s\n", + count ? strerror(errno) : + "premature end of file"); + exit(1); } - fprintf (stderr, "Warning: %d byte intersegment gap.\n", gap); - memset (obuf, 0, sizeof obuf); - while (gap) - { - int count = write (outfile, obuf, (gap > sizeof obuf - ? sizeof obuf : gap)); - if (count < 0) - { - fprintf (stderr, "Error writing gap: %s\n", - strerror (errno)); - exit (1); - } - gap -= count; + if ((count = write(out, ibuf, cur)) != cur) { + perror("copy: write"); + exit(1); } - } -fprintf (stderr, "writing %d bytes...\n", ph [i].p_filesz); - copy (outfile, infile, ph [i].p_offset, ph [i].p_filesz); - cur_vma = ph [i].p_vaddr + ph [i].p_filesz; - } - } - - /* - * Write a page of padding for boot PROMS that read entire pages. - * Without this, they may attempt to read past the end of the - * data section, incur an error, and refuse to boot. - */ - { - char obuf[4096]; - memset(obuf, 0, sizeof obuf); - if (write(outfile, obuf, sizeof(obuf)) != sizeof(obuf)) { - fprintf(stderr, "Error writing PROM padding: %s\n", - strerror(errno)); - exit(1); - } - } - - /* Looks like we won... */ - exit (0); -} - -copy (out, in, offset, size) - int out, in; - off_t offset, size; -{ - char ibuf [4096]; - int remaining, cur, count; - - /* Go to the start of the ELF symbol table... */ - if (lseek (in, offset, SEEK_SET) < 0) - { - perror ("copy: lseek"); - exit (1); - } - - remaining = size; - while (remaining) - { - cur = remaining; - if (cur > sizeof ibuf) - cur = sizeof ibuf; - remaining -= cur; - if ((count = read (in, ibuf, cur)) != cur) - { - fprintf (stderr, "copy: read: %s\n", - count ? strerror (errno) : "premature end of file"); - exit (1); - } - if ((count = write (out, ibuf, cur)) != cur) - { - perror ("copy: write"); - exit (1); } - } } -/* Combine two segments, which must be contiguous. If pad is true, it's - okay for there to be padding between. */ -combine (base, new, pad) - struct sect *base, *new; - int pad; -{ - if (!base -> len) - *base = *new; - else if (new -> len) - { - if (base -> vaddr + base -> len != new -> vaddr) - { - if (pad) - base -> len = new -> vaddr - base -> vaddr; - else - { - fprintf (stderr, - "Non-contiguous data can't be converted.\n"); - exit (1); - } +/* + * Combine two segments, which must be contiguous. If pad is true, it's + * okay for there to be padding between. + */ +static void combine(struct sect *base, struct sect *new, int pad) +{ + if (!base->len) + *base = *new; + else if (new->len) { + if (base->vaddr + base->len != new->vaddr) { + if (pad) + base->len = new->vaddr - base->vaddr; + else { + fprintf(stderr, + "Non-contiguous data can't be converted.\n"); + exit(1); + } + } + base->len += new->len; } - base -> len += new -> len; - } } -phcmp (h1, h2) - Elf32_Phdr *h1, *h2; +static int phcmp(const void *v1, const void *v2) { - if (h1 -> p_vaddr > h2 -> p_vaddr) - return 1; - else if (h1 -> p_vaddr < h2 -> p_vaddr) - return -1; - else - return 0; + const Elf32_Phdr *h1 = v1; + const Elf32_Phdr *h2 = v2; + + if (h1->p_vaddr > h2->p_vaddr) + return 1; + else if (h1->p_vaddr < h2->p_vaddr) + return -1; + else + return 0; } -char *saveRead (int file, off_t offset, off_t len, char *name) +static char *saveRead(int file, off_t offset, off_t len, char *name) { - char *tmp; - int count; - off_t off; - if ((off = lseek (file, offset, SEEK_SET)) < 0) - { - fprintf (stderr, "%s: fseek: %s\n", name, strerror (errno)); - exit (1); - } - if (!(tmp = (char *)malloc (len))) - { - fprintf (stderr, "%s: Can't allocate %d bytes.\n", name, len); - exit (1); - } - count = read (file, tmp, len); - if (count != len) - { - fprintf (stderr, "%s: read: %s.\n", - name, count ? strerror (errno) : "End of file reached"); - exit (1); - } - return tmp; + char *tmp; + int count; + off_t off; + if ((off = lseek(file, offset, SEEK_SET)) < 0) { + fprintf(stderr, "%s: fseek: %s\n", name, strerror(errno)); + exit(1); + } + if (!(tmp = (char *) malloc(len))) { + fprintf(stderr, "%s: Can't allocate %ld bytes.\n", name, + len); + exit(1); + } + count = read(file, tmp, len); + if (count != len) { + fprintf(stderr, "%s: read: %s.\n", + name, + count ? strerror(errno) : "End of file reached"); + exit(1); + } + return tmp; } #define swab16(x) \ @@ -536,101 +163,454 @@ (((unsigned int)(x) & (unsigned int)0x00ff0000UL) >> 8) | \ (((unsigned int)(x) & (unsigned int)0xff000000UL) >> 24) )) -void convert_elf_hdr (Elf32_Ehdr *e) +static void convert_elf_hdr(Elf32_Ehdr * e) { - e->e_type = swab16(e->e_type); - e->e_machine = swab16(e->e_machine); - e->e_version = swab32(e->e_version); - e->e_entry = swab32(e->e_entry); - e->e_phoff = swab32(e->e_phoff); - e->e_shoff = swab32(e->e_shoff); - e->e_flags = swab32(e->e_flags); - e->e_ehsize = swab16(e->e_ehsize); + e->e_type = swab16(e->e_type); + e->e_machine = swab16(e->e_machine); + e->e_version = swab32(e->e_version); + e->e_entry = swab32(e->e_entry); + e->e_phoff = swab32(e->e_phoff); + e->e_shoff = swab32(e->e_shoff); + e->e_flags = swab32(e->e_flags); + e->e_ehsize = swab16(e->e_ehsize); e->e_phentsize = swab16(e->e_phentsize); - e->e_phnum = swab16(e->e_phnum); + e->e_phnum = swab16(e->e_phnum); e->e_shentsize = swab16(e->e_shentsize); - e->e_shnum = swab16(e->e_shnum); - e->e_shstrndx = swab16(e->e_shstrndx); + e->e_shnum = swab16(e->e_shnum); + e->e_shstrndx = swab16(e->e_shstrndx); } -void convert_elf_phdrs (Elf32_Phdr *p, int num) +static void convert_elf_phdrs(Elf32_Phdr * p, int num) { int i; - for (i = 0; i < num; i++,p++) { - p->p_type = swab32(p->p_type); + for (i = 0; i < num; i++, p++) { + p->p_type = swab32(p->p_type); p->p_offset = swab32(p->p_offset); - p->p_vaddr = swab32(p->p_vaddr); - p->p_paddr = swab32(p->p_paddr); + p->p_vaddr = swab32(p->p_vaddr); + p->p_paddr = swab32(p->p_paddr); p->p_filesz = swab32(p->p_filesz); - p->p_memsz = swab32(p->p_memsz); - p->p_flags = swab32(p->p_flags); - p->p_align = swab32(p->p_align); + p->p_memsz = swab32(p->p_memsz); + p->p_flags = swab32(p->p_flags); + p->p_align = swab32(p->p_align); } } -void convert_elf_shdrs (Elf32_Shdr *s, int num) +static void convert_elf_shdrs(Elf32_Shdr * s, int num) { int i; - for (i = 0; i < num; i++,s++) { - s->sh_name = swab32(s->sh_name); - s->sh_type = swab32(s->sh_type); - s->sh_flags = swab32(s->sh_flags); - s->sh_addr = swab32(s->sh_addr); - s->sh_offset = swab32(s->sh_offset); - s->sh_size = swab32(s->sh_size); - s->sh_link = swab32(s->sh_link); - s->sh_info = swab32(s->sh_info); + for (i = 0; i < num; i++, s++) { + s->sh_name = swab32(s->sh_name); + s->sh_type = swab32(s->sh_type); + s->sh_flags = swab32(s->sh_flags); + s->sh_addr = swab32(s->sh_addr); + s->sh_offset = swab32(s->sh_offset); + s->sh_size = swab32(s->sh_size); + s->sh_link = swab32(s->sh_link); + s->sh_info = swab32(s->sh_info); s->sh_addralign = swab32(s->sh_addralign); - s->sh_entsize = swab32(s->sh_entsize); + s->sh_entsize = swab32(s->sh_entsize); } } -void convert_ecoff_filehdr(struct filehdr *f) +static void convert_ecoff_filehdr(struct filehdr *f) { - f->f_magic = swab16(f->f_magic); - f->f_nscns = swab16(f->f_nscns); + f->f_magic = swab16(f->f_magic); + f->f_nscns = swab16(f->f_nscns); f->f_timdat = swab32(f->f_timdat); f->f_symptr = swab32(f->f_symptr); - f->f_nsyms = swab32(f->f_nsyms); + f->f_nsyms = swab32(f->f_nsyms); f->f_opthdr = swab16(f->f_opthdr); - f->f_flags = swab16(f->f_flags); + f->f_flags = swab16(f->f_flags); } -void convert_ecoff_aouthdr(struct aouthdr *a) +static void convert_ecoff_aouthdr(struct aouthdr *a) { - a->magic = swab16(a->magic); - a->vstamp = swab16(a->vstamp); - a->tsize = swab32(a->tsize); - a->dsize = swab32(a->dsize); - a->bsize = swab32(a->bsize); - a->entry = swab32(a->entry); + a->magic = swab16(a->magic); + a->vstamp = swab16(a->vstamp); + a->tsize = swab32(a->tsize); + a->dsize = swab32(a->dsize); + a->bsize = swab32(a->bsize); + a->entry = swab32(a->entry); a->text_start = swab32(a->text_start); a->data_start = swab32(a->data_start); - a->bss_start = swab32(a->bss_start); - a->gprmask = swab32(a->gprmask); + a->bss_start = swab32(a->bss_start); + a->gprmask = swab32(a->gprmask); a->cprmask[0] = swab32(a->cprmask[0]); a->cprmask[1] = swab32(a->cprmask[1]); a->cprmask[2] = swab32(a->cprmask[2]); a->cprmask[3] = swab32(a->cprmask[3]); - a->gp_value = swab32(a->gp_value); + a->gp_value = swab32(a->gp_value); } -void convert_ecoff_esecs(struct scnhdr *s, int num) +static void convert_ecoff_esecs(struct scnhdr *s, int num) { int i; for (i = 0; i < num; i++, s++) { - s->s_paddr = swab32(s->s_paddr); - s->s_vaddr = swab32(s->s_vaddr); - s->s_size = swab32(s->s_size); - s->s_scnptr = swab32(s->s_scnptr); - s->s_relptr = swab32(s->s_relptr); + s->s_paddr = swab32(s->s_paddr); + s->s_vaddr = swab32(s->s_vaddr); + s->s_size = swab32(s->s_size); + s->s_scnptr = swab32(s->s_scnptr); + s->s_relptr = swab32(s->s_relptr); s->s_lnnoptr = swab32(s->s_lnnoptr); - s->s_nreloc = swab16(s->s_nreloc); - s->s_nlnno = swab16(s->s_nlnno); - s->s_flags = swab32(s->s_flags); + s->s_nreloc = swab16(s->s_nreloc); + s->s_nlnno = swab16(s->s_nlnno); + s->s_flags = swab32(s->s_flags); + } +} + +int main(int argc, char *argv[]) +{ + Elf32_Ehdr ex; + Elf32_Phdr *ph; + Elf32_Shdr *sh; + char *shstrtab; + int i, pad; + struct sect text, data, bss; + struct filehdr efh; + struct aouthdr eah; + struct scnhdr esecs[6]; + int infile, outfile; + unsigned long cur_vma = ULONG_MAX; + int addflag = 0; + int nosecs; + + text.len = data.len = bss.len = 0; + text.vaddr = data.vaddr = bss.vaddr = 0; + + /* Check args... */ + if (argc < 3 || argc > 4) { + usage: + fprintf(stderr, + "usage: elf2ecoff [-a]\n"); + exit(1); + } + if (argc == 4) { + if (strcmp(argv[3], "-a")) + goto usage; + addflag = 1; + } + + /* Try the input file... */ + if ((infile = open(argv[1], O_RDONLY)) < 0) { + fprintf(stderr, "Can't open %s for read: %s\n", + argv[1], strerror(errno)); + exit(1); + } + + /* Read the header, which is at the beginning of the file... */ + i = read(infile, &ex, sizeof ex); + if (i != sizeof ex) { + fprintf(stderr, "ex: %s: %s.\n", + argv[1], + i ? strerror(errno) : "End of file reached"); + exit(1); + } + + if (ex.e_ident[EI_DATA] == ELFDATA2MSB) + format_bigendian = 1; + + if (ntohs(0xaa55) == 0xaa55) { + if (!format_bigendian) + must_convert_endian = 1; + } else { + if (format_bigendian) + must_convert_endian = 1; + } + if (must_convert_endian) + convert_elf_hdr(&ex); + + /* Read the program headers... */ + ph = (Elf32_Phdr *) saveRead(infile, ex.e_phoff, + ex.e_phnum * sizeof(Elf32_Phdr), + "ph"); + if (must_convert_endian) + convert_elf_phdrs(ph, ex.e_phnum); + /* Read the section headers... */ + sh = (Elf32_Shdr *) saveRead(infile, ex.e_shoff, + ex.e_shnum * sizeof(Elf32_Shdr), + "sh"); + if (must_convert_endian) + convert_elf_shdrs(sh, ex.e_shnum); + /* Read in the section string table. */ + shstrtab = saveRead(infile, sh[ex.e_shstrndx].sh_offset, + sh[ex.e_shstrndx].sh_size, "shstrtab"); + + /* Figure out if we can cram the program header into an ECOFF + header... Basically, we can't handle anything but loadable + segments, but we can ignore some kinds of segments. We can't + handle holes in the address space. Segments may be out of order, + so we sort them first. */ + + qsort(ph, ex.e_phnum, sizeof(Elf32_Phdr), phcmp); + + for (i = 0; i < ex.e_phnum; i++) { + /* Section types we can ignore... */ + if (ph[i].p_type == PT_NULL || ph[i].p_type == PT_NOTE || + ph[i].p_type == PT_PHDR + || ph[i].p_type == PT_MIPS_REGINFO) + continue; + /* Section types we can't handle... */ + else if (ph[i].p_type != PT_LOAD) { + fprintf(stderr, + "Program header %d type %d can't be converted.\n", + ex.e_phnum, ph[i].p_type); + exit(1); + } + /* Writable (data) segment? */ + if (ph[i].p_flags & PF_W) { + struct sect ndata, nbss; + + ndata.vaddr = ph[i].p_vaddr; + ndata.len = ph[i].p_filesz; + nbss.vaddr = ph[i].p_vaddr + ph[i].p_filesz; + nbss.len = ph[i].p_memsz - ph[i].p_filesz; + + combine(&data, &ndata, 0); + combine(&bss, &nbss, 1); + } else { + struct sect ntxt; + + ntxt.vaddr = ph[i].p_vaddr; + ntxt.len = ph[i].p_filesz; + + combine(&text, &ntxt, 0); + } + /* Remember the lowest segment start address. */ + if (ph[i].p_vaddr < cur_vma) + cur_vma = ph[i].p_vaddr; + } + + /* Sections must be in order to be converted... */ + if (text.vaddr > data.vaddr || data.vaddr > bss.vaddr || + text.vaddr + text.len > data.vaddr + || data.vaddr + data.len > bss.vaddr) { + fprintf(stderr, + "Sections ordering prevents a.out conversion.\n"); + exit(1); + } + + /* If there's a data section but no text section, then the loader + combined everything into one section. That needs to be the + text section, so just make the data section zero length following + text. */ + if (data.len && !text.len) { + text = data; + data.vaddr = text.vaddr + text.len; + data.len = 0; + } + + /* If there is a gap between text and data, we'll fill it when we copy + the data, so update the length of the text segment as represented in + a.out to reflect that, since a.out doesn't allow gaps in the program + address space. */ + if (text.vaddr + text.len < data.vaddr) + text.len = data.vaddr - text.vaddr; + + /* We now have enough information to cons up an a.out header... */ + eah.magic = OMAGIC; + eah.vstamp = 200; + eah.tsize = text.len; + eah.dsize = data.len; + eah.bsize = bss.len; + eah.entry = ex.e_entry; + eah.text_start = text.vaddr; + eah.data_start = data.vaddr; + eah.bss_start = bss.vaddr; + eah.gprmask = 0xf3fffffe; + memset(&eah.cprmask, '\0', sizeof eah.cprmask); + eah.gp_value = 0; /* unused. */ + + if (format_bigendian) + efh.f_magic = MIPSEBMAGIC; + else + efh.f_magic = MIPSELMAGIC; + if (addflag) + nosecs = 6; + else + nosecs = 3; + efh.f_nscns = nosecs; + efh.f_timdat = 0; /* bogus */ + efh.f_symptr = 0; + efh.f_nsyms = 0; + efh.f_opthdr = sizeof eah; + efh.f_flags = 0x100f; /* Stripped, not sharable. */ + + memset(esecs, 0, sizeof esecs); + strcpy(esecs[0].s_name, ".text"); + strcpy(esecs[1].s_name, ".data"); + strcpy(esecs[2].s_name, ".bss"); + if (addflag) { + strcpy(esecs[3].s_name, ".rdata"); + strcpy(esecs[4].s_name, ".sdata"); + strcpy(esecs[5].s_name, ".sbss"); + } + esecs[0].s_paddr = esecs[0].s_vaddr = eah.text_start; + esecs[1].s_paddr = esecs[1].s_vaddr = eah.data_start; + esecs[2].s_paddr = esecs[2].s_vaddr = eah.bss_start; + if (addflag) { + esecs[3].s_paddr = esecs[3].s_vaddr = 0; + esecs[4].s_paddr = esecs[4].s_vaddr = 0; + esecs[5].s_paddr = esecs[5].s_vaddr = 0; + } + esecs[0].s_size = eah.tsize; + esecs[1].s_size = eah.dsize; + esecs[2].s_size = eah.bsize; + if (addflag) { + esecs[3].s_size = 0; + esecs[4].s_size = 0; + esecs[5].s_size = 0; } + esecs[0].s_scnptr = N_TXTOFF(efh, eah); + esecs[1].s_scnptr = N_DATOFF(efh, eah); +#define ECOFF_SEGMENT_ALIGNMENT(a) 0x10 +#define ECOFF_ROUND(s,a) (((s)+(a)-1)&~((a)-1)) + esecs[2].s_scnptr = esecs[1].s_scnptr + + ECOFF_ROUND(esecs[1].s_size, ECOFF_SEGMENT_ALIGNMENT(&eah)); + if (addflag) { + esecs[3].s_scnptr = 0; + esecs[4].s_scnptr = 0; + esecs[5].s_scnptr = 0; + } + esecs[0].s_relptr = esecs[1].s_relptr = esecs[2].s_relptr = 0; + esecs[0].s_lnnoptr = esecs[1].s_lnnoptr = esecs[2].s_lnnoptr = 0; + esecs[0].s_nreloc = esecs[1].s_nreloc = esecs[2].s_nreloc = 0; + esecs[0].s_nlnno = esecs[1].s_nlnno = esecs[2].s_nlnno = 0; + if (addflag) { + esecs[3].s_relptr = esecs[4].s_relptr + = esecs[5].s_relptr = 0; + esecs[3].s_lnnoptr = esecs[4].s_lnnoptr + = esecs[5].s_lnnoptr = 0; + esecs[3].s_nreloc = esecs[4].s_nreloc = esecs[5].s_nreloc = + 0; + esecs[3].s_nlnno = esecs[4].s_nlnno = esecs[5].s_nlnno = 0; + } + esecs[0].s_flags = 0x20; + esecs[1].s_flags = 0x40; + esecs[2].s_flags = 0x82; + if (addflag) { + esecs[3].s_flags = 0x100; + esecs[4].s_flags = 0x200; + esecs[5].s_flags = 0x400; + } + + /* Make the output file... */ + if ((outfile = open(argv[2], O_WRONLY | O_CREAT, 0777)) < 0) { + fprintf(stderr, "Unable to create %s: %s\n", argv[2], + strerror(errno)); + exit(1); + } + + if (must_convert_endian) + convert_ecoff_filehdr(&efh); + /* Write the headers... */ + i = write(outfile, &efh, sizeof efh); + if (i != sizeof efh) { + perror("efh: write"); + exit(1); + + for (i = 0; i < nosecs; i++) { + printf + ("Section %d: %s phys %lx size %lx file offset %lx\n", + i, esecs[i].s_name, esecs[i].s_paddr, + esecs[i].s_size, esecs[i].s_scnptr); + } + } + fprintf(stderr, "wrote %d byte file header.\n", i); + + if (must_convert_endian) + convert_ecoff_aouthdr(&eah); + i = write(outfile, &eah, sizeof eah); + if (i != sizeof eah) { + perror("eah: write"); + exit(1); + } + fprintf(stderr, "wrote %d byte a.out header.\n", i); + + if (must_convert_endian) + convert_ecoff_esecs(&esecs[0], nosecs); + i = write(outfile, &esecs, nosecs * sizeof(struct scnhdr)); + if (i != nosecs * sizeof(struct scnhdr)) { + perror("esecs: write"); + exit(1); + } + fprintf(stderr, "wrote %d bytes of section headers.\n", i); + + pad = (sizeof(efh) + sizeof(eah) + nosecs * sizeof(struct scnhdr)) & 15; + if (pad) { + pad = 16 - pad; + i = write(outfile, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0", pad); + if (i < 0) { + perror("ipad: write"); + exit(1); + } + fprintf(stderr, "wrote %d byte pad.\n", i); + } + + /* + * Copy the loadable sections. Zero-fill any gaps less than 64k; + * complain about any zero-filling, and die if we're asked to zero-fill + * more than 64k. + */ + for (i = 0; i < ex.e_phnum; i++) { + /* Unprocessable sections were handled above, so just verify that + the section can be loaded before copying. */ + if (ph[i].p_type == PT_LOAD && ph[i].p_filesz) { + if (cur_vma != ph[i].p_vaddr) { + unsigned long gap = + ph[i].p_vaddr - cur_vma; + char obuf[1024]; + if (gap > 65536) { + fprintf(stderr, + "Intersegment gap (%ld bytes) too large.\n", + gap); + exit(1); + } + fprintf(stderr, + "Warning: %ld byte intersegment gap.\n", + gap); + memset(obuf, 0, sizeof obuf); + while (gap) { + int count = + write(outfile, obuf, + (gap > + sizeof obuf ? sizeof + obuf : gap)); + if (count < 0) { + fprintf(stderr, + "Error writing gap: %s\n", + strerror(errno)); + exit(1); + } + gap -= count; + } + } + fprintf(stderr, "writing %d bytes...\n", + ph[i].p_filesz); + copy(outfile, infile, ph[i].p_offset, + ph[i].p_filesz); + cur_vma = ph[i].p_vaddr + ph[i].p_filesz; + } + } + + /* + * Write a page of padding for boot PROMS that read entire pages. + * Without this, they may attempt to read past the end of the + * data section, incur an error, and refuse to boot. + */ + { + char obuf[4096]; + memset(obuf, 0, sizeof obuf); + if (write(outfile, obuf, sizeof(obuf)) != sizeof(obuf)) { + fprintf(stderr, "Error writing PROM padding: %s\n", + strerror(errno)); + exit(1); + } + } + + /* Looks like we won... */ + exit(0); } diff -Nru a/arch/mips/cobalt/Makefile b/arch/mips/cobalt/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/cobalt/Makefile Tue Jul 1 18:44:40 2003 @@ -0,0 +1,7 @@ +# +# Makefile for the Cobalt micro systems family specific parts of the kernel +# + +obj-y := irq.o int-handler.o reset.o setup.o via.o promcon.o + +EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips/cobalt/int-handler.S b/arch/mips/cobalt/int-handler.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/cobalt/int-handler.S Tue Jul 1 18:44:40 2003 @@ -0,0 +1,104 @@ +/* + * Cobalt interrupt handler + * + * 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) 1995, 1996, 1997 by Ralf Baechle + * Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv) + */ +#include +#include +#include +#include +#include + +/* + * cobalt_handle_int: Interrupt handler for Cobalt boards + */ + .text + .set noreorder + .set noat + .align 5 + NESTED(cobalt_handle_int, PT_SIZE, sp) + SAVE_ALL + CLI + .set at + + /* + * Get pending Interrupts + */ + mfc0 s0,CP0_CAUSE # get raw irq status + mfc0 a0,CP0_STATUS # get irq mask + and s0,s0,a0 # compute masked irq status + + andi a0,s0,CAUSEF_IP2 /* Check for Galileo timer */ + beq a0,zero,1f + andi a0,s0,CAUSEF_IP6 /* Check for Via chip */ + + /* Galileo interrupt */ + jal galileo_irq + move a0,sp + j ret_from_irq + nop + +1: + beq a0,zero,1f /* Check IP6 */ + andi a0,s0,CAUSEF_IP3 + + /* Via interrupt */ + jal via_irq + move a0,sp + j ret_from_irq + nop + +1: + beq a0,zero,1f /* Check IP3 */ + andi a0,s0,CAUSEF_IP4 + + /* Ethernet 0 interrupt */ + li a0,COBALT_ETH0_IRQ + jal do_IRQ + move a1,sp + + j ret_from_irq + nop + +1: + beq a0,zero,1f /* Check IP4 */ + andi a0,s0,CAUSEF_IP5 + + /* Ethernet 1 interrupt */ + li a0,COBALT_ETH1_IRQ + jal do_IRQ + move a1,sp + + j ret_from_irq + nop +1: + beq a0,zero,1f /* Check IP5 */ + andi a0,s0,CAUSEF_IP7 + + /* Serial interrupt */ + li a0,COBALT_SERIAL_IRQ + jal do_IRQ + move a1,sp + + j ret_from_irq + nop +1: + beq a0,zero,1f /* Check IP7 */ + nop + + /* PCI interrupt */ + li a0,COBALT_QUBE_SLOT_IRQ + jal do_IRQ + move a1,sp + +1: + j ret_from_irq + nop + + END(cobalt_handle_int) + diff -Nru a/arch/mips/cobalt/irq.c b/arch/mips/cobalt/irq.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/cobalt/irq.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,143 @@ +/* + * IRQ vector handles + * + * 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) 1995, 1996, 1997 by Ralf Baechle + * Copyright (C) 2001 by Liam Davies (ldavies@agile.tv) + * + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +/* Cobalt Exception handler */ +extern void cobalt_handle_int(void); + +/* Via masking routines */ +extern void unmask_irq(unsigned int irqr); +extern void mask_irq(unsigned int irq); + + +/* + * We have two types of interrupts that we handle, ones that come + * in through the CPU interrupt lines, and ones that come in on + * the via chip. The CPU mappings are: + * 0,1 - S/W (ignored) + * 2 - Galileo chip (timer) + * 3 - Tulip 0 + NCR SCSI + * 4 - Tulip 1 + * 5 - 16550 UART + * 6 - VIA southbridge PIC + * 7 - unused + * + * The VIA chip is a master/slave 8259 setup and has the + * following interrupts + * 8 - RTC + * 9 - PCI + * 14 - IDE0 + * 15 - IDE1 + * + * In the table we use a 1 to indicate that we use a VIA interrupt + * line, and IE_IRQx to indicate that we use a CPU interrupt line + * + * We map all of these onto linux IRQ #s 0-15 and forget the rest + */ +#define NOINT_LINE 0 +#define CPUINT_LINE(x) IE_IRQ##x +#define VIAINT_LINE 1 + +#define COBALT_IRQS 16 + +static unsigned short irqnr_to_type[COBALT_IRQS] = +{ CPUINT_LINE(0), NOINT_LINE, VIAINT_LINE, NOINT_LINE, + CPUINT_LINE(1), NOINT_LINE, NOINT_LINE, CPUINT_LINE(3), + VIAINT_LINE, VIAINT_LINE, NOINT_LINE, NOINT_LINE, + NOINT_LINE, CPUINT_LINE(2), VIAINT_LINE, VIAINT_LINE }; + +/* + * Cobalt CPU irq + */ + +static void enable_cpu_irq(unsigned int irq) +{ + unsigned long flags; + + local_irq_save(flags); + change_c0_status(irqnr_to_type[irq], irqnr_to_type[irq]); + local_irq_restore(flags); +} + +static unsigned startup_cpu_irq(unsigned int irq) +{ + enable_cpu_irq(irq); + + return 0; +} + +static void disable_cpu_irq(unsigned int irq) +{ + unsigned long flags; + + local_irq_save(flags); + change_c0_status(irqnr_to_type[irq], ~(irqnr_to_type[irq])); + local_irq_restore(flags); +} + +#define shutdown_cpu_irq disable_cpu_irq +#define mask_and_ack_cpu_irq disable_cpu_irq + +static void end_cpu_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_cpu_irq(irq); +} + +static struct hw_interrupt_type cobalt_cpu_irq_type = { + "Cobalt CPU", + startup_cpu_irq, + shutdown_cpu_irq, + enable_cpu_irq, + disable_cpu_irq, + mask_and_ack_cpu_irq, + end_cpu_irq, + NULL +}; + +void __init init_IRQ(void) +{ + int i; + + /* Initialise all of the IRQ descriptors */ + init_i8259_irqs(); + + /* Map the irqnr to the type int we have */ + for (i=0; i < COBALT_IRQS; i++) { + if (irqnr_to_type[i] >= CPUINT_LINE(0)) + /* cobalt_cpu_irq_type */ + irq_desc[i].handler = &cobalt_cpu_irq_type; + } + + /* Mask all cpu interrupts + (except IE4, we already masked those at VIA level) */ + clear_c0_status(ST0_IM); + set_c0_status(IE_IRQ4); + + cli(); + + set_except_vector(0, cobalt_handle_int); +} diff -Nru a/arch/mips/cobalt/promcon.c b/arch/mips/cobalt/promcon.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/cobalt/promcon.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,91 @@ +/* + * PROM console for Cobalt Raq2 + * + * 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) 1995, 1996, 1997 by Ralf Baechle + * Copyright (C) 2001 by Liam Davies (ldavies@agile.tv) + * + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +static unsigned long port = 0xc800000; + +static __inline__ void ns16550_cons_put_char(char ch, unsigned long ioaddr) +{ + char lsr; + + do { + lsr = inb(ioaddr + UART_LSR); + } while ((lsr & (UART_LSR_TEMT | UART_LSR_THRE)) != (UART_LSR_TEMT | UART_LSR_THRE)); + outb(ch, ioaddr + UART_TX); +} + +static __inline__ char ns16550_cons_get_char(unsigned long ioaddr) +{ + while ((inb(ioaddr + UART_LSR) & UART_LSR_DR) == 0) + udelay(1); + return inb(ioaddr + UART_RX); +} + +void ns16550_console_write(struct console *co, const char *s, unsigned count) +{ + char lsr, ier; + unsigned i; + + ier = inb(port + UART_IER); + outb(0x00, port + UART_IER); + for (i=0; i < count; i++, s++) { + + if(*s == '\n') + ns16550_cons_put_char('\r', port); + ns16550_cons_put_char(*s, port); + } + + do { + lsr = inb(port + UART_LSR); + } while ((lsr & (UART_LSR_TEMT | UART_LSR_THRE)) != (UART_LSR_TEMT | UART_LSR_THRE)); + + outb(ier, port + UART_IER); +} + +char getDebugChar(void) +{ + return ns16550_cons_get_char(port); +} + +void putDebugChar(char kgdb_char) +{ + ns16550_cons_put_char(kgdb_char, port); +} + +static kdev_t +ns16550_console_dev(struct console *c) +{ + return mk_kdev(TTY_MAJOR, 64 + c->index); +} + +static struct console ns16550_console = { + .name = "prom", + .setup = NULL, + .write = ns16550_console_write, + .device = ns16550_console_dev, + .flags = CON_PRINTBUFFER, + .index = -1, +}; + +void __init ns16550_setup_console(void) +{ + register_console(&ns16550_console); +} diff -Nru a/arch/mips/cobalt/reset.c b/arch/mips/cobalt/reset.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/cobalt/reset.c Tue Jul 1 18:44:39 2003 @@ -0,0 +1,68 @@ +/* + * Cobalt Reset operations + * + * 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) 1995, 1996, 1997 by Ralf Baechle + * Copyright (C) 2001 by Liam Davies (ldavies@agile.tv) + */ +#include +#include +#include +#include +#include +#include +#include +#include + +void cobalt_machine_restart(char *command) +{ + *(volatile char *)0xbc000000 = 0x0f; + + /* + * Ouch, we're still alive ... This time we take the silver bullet ... + * ... and find that we leave the hardware in a state in which the + * kernel in the flush locks up somewhen during of after the PCI + * detection stuff. + */ + set_c0_status(ST0_BEV | ST0_ERL); + change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); + flush_cache_all(); + write_c0_wired(0); + __asm__ __volatile__( + "jr\t%0" + : + : "r" (0xbfc00000)); +} + +extern int led_state; +#define kLED 0xBC000000 +#define LEDSet(x) (*(volatile unsigned char *) kLED) = (( unsigned char)x) + +void cobalt_machine_halt(void) +{ + int mark; + + /* Blink our cute? little LED (number 3)... */ + while (1) { + led_state = led_state | ( 1 << 3 ); + LEDSet(led_state); + mark = jiffies; + while (jiffies<(mark+HZ)); + led_state = led_state & ~( 1 << 3 ); + LEDSet(led_state); + mark = jiffies; + while (jiffies<(mark+HZ)); + } +} + +/* + * This triggers the luser mode device driver for the power switch ;-) + */ +void cobalt_machine_power_off(void) +{ + printk("You can switch the machine off now.\n"); + cobalt_machine_halt(); +} diff -Nru a/arch/mips/cobalt/setup.c b/arch/mips/cobalt/setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/cobalt/setup.c Tue Jul 1 18:44:39 2003 @@ -0,0 +1,113 @@ +/* + * Setup pointers to hardware dependent routines. + * + * 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) 1996, 1997 by Ralf Baechle + * Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv) + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +extern void cobalt_machine_restart(char *command); +extern void cobalt_machine_halt(void); +extern void cobalt_machine_power_off(void); + +extern struct rtc_ops std_rtc_ops; +extern struct ide_ops std_ide_ops; + + +char arcs_cmdline[CL_SIZE] = { + "console=ttyS0,115200 " +#ifdef CONFIG_IP_PNP + "ip=on " +#endif +#ifdef CONFIG_ROOT_NFS + "root=/dev/nfs " +#else + "root=/dev/hda1 " +#endif + }; + +const char *get_system_type(void) +{ + return "MIPS Cobalt"; +} + + +static void __init cobalt_time_init(void) +{ + rtc_ops = &std_rtc_ops; +} + +static void __init cobalt_timer_setup(struct irqaction *irq) +{ + /* Load timer value for 150 Hz */ + GALILEO_OUTL(500000, GT_TC0_OFS); + + /* Register our timer interrupt */ + setup_irq(COBALT_TIMER_IRQ, irq); + + /* Enable timer ints */ + GALILEO_OUTL((GALILEO_ENTC0 | GALILEO_SELTC0), GT_TC_CONTROL_OFS); + /* Unmask timer int */ + GALILEO_OUTL(0x100, GT_INTRMASK_OFS); +} + + +void __init cobalt_setup(void) +{ + + _machine_restart = cobalt_machine_restart; + _machine_halt = cobalt_machine_halt; + _machine_power_off = cobalt_machine_power_off; + + board_time_init = cobalt_time_init; + board_timer_setup = cobalt_timer_setup; + +#ifdef CONFIG_BLK_DEV_IDE + ide_ops = &std_ide_ops; +#endif + + set_io_port_base(KSEG1ADDR(0x10000000)); + + /* + * This is a prom style console. We just poke at the + * UART to make it talk. + * Only use this console if you really screw up and can't + * get to the stage of setting up a real serial console. + */ + /*ns16550_setup_console();*/ +} + +/* Prom init. We read our one and only communication with the + firmware. Grab the amount of installed memory */ +void __init prom_init(int argc) +{ + mips_machgroup = MACH_GROUP_COBALT; + + add_memory_region(0x0, argc & 0x7fffffff, BOOT_MEM_RAM); +} + +void __init prom_free_prom_memory(void) +{ + /* Nothing to do! */ +} diff -Nru a/arch/mips/cobalt/via.c b/arch/mips/cobalt/via.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/cobalt/via.c Tue Jul 1 18:44:39 2003 @@ -0,0 +1,67 @@ +/* + * VIA chipset irq handling + * + * 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) 1996, 1997 by Ralf Baechle + * Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv) + * + */ + +#include +#include + +#include +#include +#include + +#include + +asmlinkage void via_irq(struct pt_regs *regs) +{ + char mstat, sstat; + + /* Read Master Status */ + outb(0x0C, 0x20); + mstat = inb(0x20); + + if (mstat < 0) { + mstat &= 0x7f; + if (mstat != 2) { + do_IRQ(mstat, regs); + outb(mstat | 0x20, 0x20); + } else { + sstat = inb(0xA0); + + /* Slave interrupt */ + outb(0x0C, 0xA0); + sstat = inb(0xA0); + + if (sstat < 0) { + do_IRQ((sstat + 8) & 0x7f, regs); + outb(0x22, 0x20); + outb((sstat & 0x7f) | 0x20, 0xA0); + } else { + printk("Spurious slave interrupt...\n"); + } + } + } else + printk("Spurious master interrupt..."); +} + +asmlinkage void galileo_irq(struct pt_regs *regs) +{ + unsigned long irq_src; + + irq_src = GALILEO_INL(GT_INTRCAUSE_OFS); + + /* Check for timer irq ... */ + if (irq_src & GALILEO_T0EXP) { + /* Clear the int line */ + GALILEO_OUTL(0, GT_INTRCAUSE_OFS); + do_IRQ(COBALT_TIMER_IRQ, regs); + } else + printk("Spurious Galileo interrupt...\n"); +} diff -Nru a/arch/mips/ddb5074/Makefile b/arch/mips/ddb5074/Makefile --- a/arch/mips/ddb5074/Makefile Tue Jul 1 18:44:32 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,8 +0,0 @@ -# -# Makefile for the NEC DDB Vrc-5074 specific kernel interface routines -# under Linux. -# - -EXTRA_AFLAGS := $(CFLAGS) - -obj-y := setup.o irq.o time.o prom.o pci.o int-handler.o nile4.o diff -Nru a/arch/mips/ddb5074/int-handler.S b/arch/mips/ddb5074/int-handler.S --- a/arch/mips/ddb5074/int-handler.S Tue Jul 1 18:44:36 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,120 +0,0 @@ -/* - * arch/mips/ddb5074/int-handler.S -- NEC DDB Vrc-5074 interrupt handler - * - * Based on arch/mips/sgi/kernel/indyIRQ.S - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * - * Copyright (C) 2000 Geert Uytterhoeven - * Sony Software Development Center Europe (SDCE), Brussels - */ -#include -#include -#include -#include - -/* A lot of complication here is taken away because: - * - * 1) We handle one interrupt and return, sitting in a loop and moving across - * all the pending IRQ bits in the cause register is _NOT_ the answer, the - * common case is one pending IRQ so optimize in that direction. - * - * 2) We need not check against bits in the status register IRQ mask, that - * would make this routine slow as hell. - * - * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in - * between like BSD spl() brain-damage. - * - * Furthermore, the IRQs on the INDY look basically (barring software IRQs - * which we don't use at all) like: - * - * MIPS IRQ Source - * -------- ------ - * 0 Software (ignored) - * 1 Software (ignored) - * 2 Local IRQ level zero - * 3 Local IRQ level one - * 4 8254 Timer zero - * 5 8254 Timer one - * 6 Bus Error - * 7 R4k timer (what we use) - * - * We handle the IRQ according to _our_ priority which is: - * - * Highest ---- R4k Timer - * Local IRQ zero - * Local IRQ one - * Bus Error - * 8254 Timer zero - * Lowest ---- 8254 Timer one - * - * then we just return, if multiple IRQs are pending then we will just take - * another exception, big deal. - */ - - .text - .set noreorder - .set noat - .align 5 - NESTED(ddbIRQ, PT_SIZE, sp) - SAVE_ALL - CLI - .set at - mfc0 s0, CP0_CAUSE # get irq mask - -#if 1 - mfc0 t2,CP0_STATUS # get enabled interrupts - and s0,t2 # isolate allowed ones -#endif - /* First we check for r4k counter/timer IRQ. */ - andi a0, s0, CAUSEF_IP2 # delay slot, check local level zero - beq a0, zero, 1f - andi a0, s0, CAUSEF_IP3 # delay slot, check local level one - - /* Wheee, local level zero interrupt. */ - jal ddb_local0_irqdispatch - move a0, sp # delay slot - - j ret_from_irq - nop # delay slot - -1: - beq a0, zero, 1f - andi a0, s0, CAUSEF_IP6 # delay slot, check bus error - - /* Wheee, local level one interrupt. */ - move a0, sp - jal ddb_local1_irqdispatch - nop - - j ret_from_irq - nop - -1: - beq a0, zero, 1f - nop - - /* Wheee, an asynchronous bus error... */ - move a0, sp - jal ddb_buserror_irq - nop - - j ret_from_irq - nop - -1: - /* Here by mistake? This is possible, what can happen - * is that by the time we take the exception the IRQ - * pin goes low, so just leave if this is the case. - */ - andi a0, s0, (CAUSEF_IP4 | CAUSEF_IP5) - beq a0, zero, 1f - - /* Must be one of the 8254 timers... */ - move a0, sp - jal ddb_8254timer_irq - nop -1: - j ret_from_irq - nop - END(ddbIRQ) diff -Nru a/arch/mips/ddb5074/irq.c b/arch/mips/ddb5074/irq.c --- a/arch/mips/ddb5074/irq.c Tue Jul 1 18:44:39 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,226 +0,0 @@ -/* - * arch/mips/ddb5074/irq.c -- NEC DDB Vrc-5074 interrupt routines - * - * Copyright (C) 2000 Geert Uytterhoeven - * Sony Software Development Center Europe (SDCE), Brussels - */ -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - - -extern void __init i8259_init(void); -extern void i8259_disable_irq(unsigned int irq_nr); -extern void i8259_enable_irq(unsigned int irq_nr); - -extern asmlinkage void ddbIRQ(void); -extern asmlinkage void i8259_do_irq(int irq, struct pt_regs *regs); -extern asmlinkage void do_IRQ(int irq, struct pt_regs *regs); - - -void no_action(int cpl, void *dev_id, struct pt_regs *regs) -{ -} - - -#define M1543_PNP_CONFIG 0x03f0 /* PnP Config Port */ -#define M1543_PNP_INDEX 0x03f0 /* PnP Index Port */ -#define M1543_PNP_DATA 0x03f1 /* PnP Data Port */ - -#define M1543_PNP_ALT_CONFIG 0x0370 /* Alternative PnP Config Port */ -#define M1543_PNP_ALT_INDEX 0x0370 /* Alternative PnP Index Port */ -#define M1543_PNP_ALT_DATA 0x0371 /* Alternative PnP Data Port */ - -#define M1543_INT1_MASTER_CTRL 0x0020 /* INT_1 (master) Control Register */ -#define M1543_INT1_MASTER_MASK 0x0021 /* INT_1 (master) Mask Register */ - -#define M1543_INT1_SLAVE_CTRL 0x00a0 /* INT_1 (slave) Control Register */ -#define M1543_INT1_SLAVE_MASK 0x00a1 /* INT_1 (slave) Mask Register */ - -#define M1543_INT1_MASTER_ELCR 0x04d0 /* INT_1 (master) Edge/Level Control */ -#define M1543_INT1_SLAVE_ELCR 0x04d1 /* INT_1 (slave) Edge/Level Control */ - - -static void m1543_irq_setup(void) -{ - /* - * The ALI M1543 has 13 interrupt inputs, IRQ1..IRQ13. Not all - * the possible IO sources in the M1543 are in use by us. We will - * use the following mapping: - * - * IRQ1 - keyboard (default set by M1543) - * IRQ3 - reserved for UART B (default set by M1543) (note that - * the schematics for the DDB Vrc-5074 board seem to - * indicate that IRQ3 is connected to the DS1386 - * watchdog timer interrupt output so we might have - * a conflict) - * IRQ4 - reserved for UART A (default set by M1543) - * IRQ5 - parallel (default set by M1543) - * IRQ8 - DS1386 time of day (RTC) interrupt - * IRQ12 - mouse - */ - - /* - * Assing mouse interrupt to IRQ12 - */ - - /* Enter configuration mode */ - outb(0x51, M1543_PNP_CONFIG); - outb(0x23, M1543_PNP_CONFIG); - - /* Select logical device 7 (Keyboard) */ - outb(0x07, M1543_PNP_INDEX); - outb(0x07, M1543_PNP_DATA); - - /* Select IRQ12 */ - outb(0x72, M1543_PNP_INDEX); - outb(0x0c, M1543_PNP_DATA); - - /* Leave configration mode */ - outb(0xbb, M1543_PNP_CONFIG); - - - /* Initialize the 8259 PIC in the M1543 */ - i8259_init(); - - /* Enable the interrupt cascade */ - nile4_enable_irq(NILE4_INT_INTE); - - request_region(M1543_PNP_CONFIG, 2, "M1543 config"); - request_region(M1543_INT1_MASTER_ELCR, 2, "pic ELCR"); -} - -static void nile4_irq_setup(void) -{ - int i; - - /* Map all interrupts to CPU int #0 */ - nile4_map_irq_all(0); - - /* PCI INTA#-E# must be level triggered */ - nile4_set_pci_irq_level_or_edge(0, 1); - nile4_set_pci_irq_level_or_edge(1, 1); - nile4_set_pci_irq_level_or_edge(2, 1); - nile4_set_pci_irq_level_or_edge(3, 1); - nile4_set_pci_irq_level_or_edge(4, 1); - - /* PCI INTA#-D# must be active low, INTE# must be active high */ - nile4_set_pci_irq_polarity(0, 0); - nile4_set_pci_irq_polarity(1, 0); - nile4_set_pci_irq_polarity(2, 0); - nile4_set_pci_irq_polarity(3, 0); - nile4_set_pci_irq_polarity(4, 1); - - for (i = 0; i < 16; i++) - nile4_clear_irq(i); - - /* Enable CPU int #0 */ - nile4_enable_irq_output(0); - - request_mem_region(NILE4_BASE, NILE4_SIZE, "Nile 4"); -} - - -/* - * IRQ2 is cascade interrupt to second interrupt controller - */ -static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL }; - - -void disable_irq(unsigned int irq_nr) -{ - if (is_i8259_irq(irq_nr)) - i8259_disable_irq(irq_nr); - else - nile4_disable_irq(irq_to_nile4(irq_nr)); -} - -void enable_irq(unsigned int irq_nr) -{ - if (is_i8259_irq(irq_nr)) - i8259_enable_irq(irq_nr); - else - nile4_enable_irq(irq_to_nile4(irq_nr)); -} - -int table[16] = { 0, }; - -void ddb_local0_irqdispatch(struct pt_regs *regs) -{ - u32 mask; - int nile4_irq; -#if 1 - volatile static int nesting = 0; - if (nesting++ == 0) - ddb5074_led_d3(1); - ddb5074_led_hex(nesting < 16 ? nesting : 15); -#endif - - mask = nile4_get_irq_stat(0); - nile4_clear_irq_mask(mask); - - /* Handle the timer interrupt first */ - if (mask & (1 << NILE4_INT_GPT)) { - nile4_disable_irq(NILE4_INT_GPT); - do_IRQ(nile4_to_irq(NILE4_INT_GPT), regs); - nile4_enable_irq(NILE4_INT_GPT); - mask &= ~(1 << NILE4_INT_GPT); - } - for (nile4_irq = 0; mask; nile4_irq++, mask >>= 1) - if (mask & 1) { - nile4_disable_irq(nile4_irq); - if (nile4_irq == NILE4_INT_INTE) { - int i8259_irq = nile4_i8259_iack(); - i8259_do_irq(i8259_irq, regs); - } else - do_IRQ(nile4_to_irq(nile4_irq), regs); - nile4_enable_irq(nile4_irq); - } -#if 1 - if (--nesting == 0) - ddb5074_led_d3(0); - ddb5074_led_hex(nesting < 16 ? nesting : 15); -#endif -} - -void ddb_local1_irqdispatch(void) -{ - printk("ddb_local1_irqdispatch called\n"); -} - -void ddb_buserror_irq(void) -{ - printk("ddb_buserror_irq called\n"); -} - -void ddb_8254timer_irq(void) -{ - printk("ddb_8254timer_irq called\n"); -} - -void __init ddb_irq_setup(void) -{ -#ifdef CONFIG_REMOTE_DEBUG - if (remote_debug) - set_debug_traps(); - breakpoint(); /* you may move this line to whereever you want :-) */ -#endif - request_region(0x20, 0x20, "pic1"); - request_region(0xa0, 0x20, "pic2"); - i8259_setup_irq(2, &irq2); - - nile4_irq_setup(); - m1543_irq_setup(); - - set_except_vector(0, ddbIRQ); -} diff -Nru a/arch/mips/ddb5074/nile4.c b/arch/mips/ddb5074/nile4.c --- a/arch/mips/ddb5074/nile4.c Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,292 +0,0 @@ -/* - * arch/mips/ddb5074/nile4.c -- NEC Vrc-5074 Nile 4 support routines - * - * Copyright (C) 2000 Geert Uytterhoeven - * Sony Software Development Center Europe (SDCE), Brussels - */ -#include -#include - -#include - - -/* - * Physical Device Address Registers - * - * Note: 32 bit addressing only! - */ -void nile4_set_pdar(u32 pdar, u32 phys, u32 size, int width, - int on_memory_bus, int visible) -{ - u32 maskbits; - u32 widthbits; - - if (pdar > NILE4_BOOTCS || (pdar & 7)) { - printk("nile4_set_pdar: invalid pdar %d\n", pdar); - return; - } - if (pdar == NILE4_INTCS && size != 0x00200000) { - printk("nile4_set_pdar: INTCS size must be 2 MB\n"); - return; - } - switch (size) { -#if 0 /* We don't support 4 GB yet */ - case 0x100000000: /* 4 GB */ - maskbits = 4; - break; -#endif - case 0x80000000: /* 2 GB */ - maskbits = 5; - break; - case 0x40000000: /* 1 GB */ - maskbits = 6; - break; - case 0x20000000: /* 512 MB */ - maskbits = 7; - break; - case 0x10000000: /* 256 MB */ - maskbits = 8; - break; - case 0x08000000: /* 128 MB */ - maskbits = 9; - break; - case 0x04000000: /* 64 MB */ - maskbits = 10; - break; - case 0x02000000: /* 32 MB */ - maskbits = 11; - break; - case 0x01000000: /* 16 MB */ - maskbits = 12; - break; - case 0x00800000: /* 8 MB */ - maskbits = 13; - break; - case 0x00400000: /* 4 MB */ - maskbits = 14; - break; - case 0x00200000: /* 2 MB */ - maskbits = 15; - break; - case 0: /* OFF */ - maskbits = 0; - break; - default: - printk("nile4_set_pdar: unsupported size %p\n", (void *) size); - return; - } - switch (width) { - case 8: - widthbits = 0; - break; - case 16: - widthbits = 1; - break; - case 32: - widthbits = 2; - break; - case 64: - widthbits = 3; - break; - default: - printk("nile4_set_pdar: unsupported width %d\n", width); - return; - } - nile4_out32(pdar, maskbits | (on_memory_bus ? 0x10 : 0) | - (visible ? 0x20 : 0) | (widthbits << 6) | - (phys & 0xffe00000)); - nile4_out32(pdar + 4, 0); - /* - * When programming a PDAR, the register should be read immediately - * after writing it. This ensures that address decoders are properly - * configured. - */ - nile4_in32(pdar); - nile4_in32(pdar + 4); -} - - -/* - * PCI Master Registers - * - * Note: 32 bit addressing only! - */ -void nile4_set_pmr(u32 pmr, u32 type, u32 addr) -{ - if (pmr != NILE4_PCIINIT0 && pmr != NILE4_PCIINIT1) { - printk("nile4_set_pmr: invalid pmr %d\n", pmr); - return; - } - switch (type) { - case NILE4_PCICMD_IACK: /* PCI Interrupt Acknowledge */ - case NILE4_PCICMD_IO: /* PCI I/O Space */ - case NILE4_PCICMD_MEM: /* PCI Memory Space */ - case NILE4_PCICMD_CFG: /* PCI Configuration Space */ - break; - default: - printk("nile4_set_pmr: invalid type %d\n", type); - return; - } - nile4_out32(pmr, (type << 1) | 0x10 | (addr & 0xffe00000)); - nile4_out32(pmr + 4, 0); -} - - -/* - * Interrupt Programming - */ -void nile4_map_irq(int nile4_irq, int cpu_irq) -{ - u32 offset, t; - - offset = NILE4_INTCTRL; - if (nile4_irq >= 8) { - offset += 4; - nile4_irq -= 8; - } - t = nile4_in32(offset); - t &= ~(7 << (nile4_irq * 4)); - t |= cpu_irq << (nile4_irq * 4); - nile4_out32(offset, t); -} - -void nile4_map_irq_all(int cpu_irq) -{ - u32 all, t; - - all = cpu_irq; - all |= all << 4; - all |= all << 8; - all |= all << 16; - t = nile4_in32(NILE4_INTCTRL); - t &= 0x88888888; - t |= all; - nile4_out32(NILE4_INTCTRL, t); - t = nile4_in32(NILE4_INTCTRL + 4); - t &= 0x88888888; - t |= all; - nile4_out32(NILE4_INTCTRL + 4, t); -} - -void nile4_enable_irq(int nile4_irq) -{ - u32 offset, t; - - offset = NILE4_INTCTRL; - if (nile4_irq >= 8) { - offset += 4; - nile4_irq -= 8; - } - t = nile4_in32(offset); - t |= 8 << (nile4_irq * 4); - nile4_out32(offset, t); -} - -void nile4_disable_irq(int nile4_irq) -{ - u32 offset, t; - - offset = NILE4_INTCTRL; - if (nile4_irq >= 8) { - offset += 4; - nile4_irq -= 8; - } - t = nile4_in32(offset); - t &= ~(8 << (nile4_irq * 4)); - nile4_out32(offset, t); -} - -void nile4_disable_irq_all(void) -{ - nile4_out32(NILE4_INTCTRL, 0); - nile4_out32(NILE4_INTCTRL + 4, 0); -} - -u16 nile4_get_irq_stat(int cpu_irq) -{ - return nile4_in16(NILE4_INTSTAT0 + cpu_irq * 2); -} - -void nile4_enable_irq_output(int cpu_irq) -{ - u32 t; - - t = nile4_in32(NILE4_INTSTAT1 + 4); - t |= 1 << (16 + cpu_irq); - nile4_out32(NILE4_INTSTAT1, t); -} - -void nile4_disable_irq_output(int cpu_irq) -{ - u32 t; - - t = nile4_in32(NILE4_INTSTAT1 + 4); - t &= ~(1 << (16 + cpu_irq)); - nile4_out32(NILE4_INTSTAT1, t); -} - -void nile4_set_pci_irq_polarity(int pci_irq, int high) -{ - u32 t; - - t = nile4_in32(NILE4_INTPPES); - if (high) - t &= ~(1 << (pci_irq * 2)); - else - t |= 1 << (pci_irq * 2); - nile4_out32(NILE4_INTPPES, t); -} - -void nile4_set_pci_irq_level_or_edge(int pci_irq, int level) -{ - u32 t; - - t = nile4_in32(NILE4_INTPPES); - if (level) - t |= 2 << (pci_irq * 2); - else - t &= ~(2 << (pci_irq * 2)); - nile4_out32(NILE4_INTPPES, t); -} - -void nile4_clear_irq(int nile4_irq) -{ - nile4_out32(NILE4_INTCLR, 1 << nile4_irq); -} - -void nile4_clear_irq_mask(u32 mask) -{ - nile4_out32(NILE4_INTCLR, mask); -} - -u8 nile4_i8259_iack(void) -{ - u8 irq; - - /* Set window 0 for interrupt acknowledge */ - nile4_set_pmr(NILE4_PCIINIT0, NILE4_PCICMD_IACK, 0); - irq = *(volatile u8 *) NILE4_PCI_IACK_BASE; - /* Set window 0 for PCI I/O space */ - nile4_set_pmr(NILE4_PCIINIT0, NILE4_PCICMD_IO, 0); - return irq; -} - -#if 0 -void nile4_dump_irq_status(void) -{ - printk("CPUSTAT = %p:%p\n", (void *) nile4_in32(NILE4_CPUSTAT + 4), - (void *) nile4_in32(NILE4_CPUSTAT)); - printk("INTCTRL = %p:%p\n", (void *) nile4_in32(NILE4_INTCTRL + 4), - (void *) nile4_in32(NILE4_INTCTRL)); - printk("INTSTAT0 = %p:%p\n", - (void *) nile4_in32(NILE4_INTSTAT0 + 4), - (void *) nile4_in32(NILE4_INTSTAT0)); - printk("INTSTAT1 = %p:%p\n", - (void *) nile4_in32(NILE4_INTSTAT1 + 4), - (void *) nile4_in32(NILE4_INTSTAT1)); - printk("INTCLR = %p:%p\n", (void *) nile4_in32(NILE4_INTCLR + 4), - (void *) nile4_in32(NILE4_INTCLR)); - printk("INTPPES = %p:%p\n", (void *) nile4_in32(NILE4_INTPPES + 4), - (void *) nile4_in32(NILE4_INTPPES)); -} -#endif diff -Nru a/arch/mips/ddb5074/pci.c b/arch/mips/ddb5074/pci.c --- a/arch/mips/ddb5074/pci.c Tue Jul 1 18:44:35 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,366 +0,0 @@ -/* - * arch/mips/ddb5074/pci.c -- NEC DDB Vrc-5074 PCI access routines - * - * Copyright (C) 2000 Geert Uytterhoeven - * Albert Dorofeev - * Sony Software Development Center Europe (SDCE), Brussels - */ -#include -#include -#include -#include -#include -#include - -#include - - -static u32 nile4_pre_pci_access0(int slot_num) -{ - u32 pci_addr = 0; - u32 virt_addr = NILE4_PCI_CFG_BASE; - - /* Set window 1 address 8000000 - 64 bit - 2 MB (PCI config space) */ - nile4_set_pdar(NILE4_PCIW1, PHYSADDR(virt_addr), 0x00200000, 64, 0, - 0); - if (slot_num > 2) - pci_addr = 0x00040000 << slot_num; - else - virt_addr += 0x00040000 << slot_num; - nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_CFG, pci_addr); - return virt_addr; -} - -static void nile4_post_pci_access0(void) -{ - /* - * Set window 1 back to address 8000000 - 64 bit - 128 MB - * (PCI IO space) - */ - nile4_set_pdar(NILE4_PCIW1, PHYSADDR(NILE4_PCI_MEM_BASE), - 0x08000000, 64, 1, 1); - nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_MEM, 0); -} - - -static int nile4_pci_read(struct pci_bus *bus, unsigned int devfn, int where, - int size, u32 * val) -{ - int status, slot_num, func_num; - u32 result, base; - - switch (size) { - case 4: - /* - * For starters let's do configuration cycle 0 only - * (one bus only) - */ - if (bus->number) - return PCIBIOS_FUNC_NOT_SUPPORTED; - - slot_num = PCI_SLOT(devfn); - func_num = PCI_FUNC(devfn); - if (slot_num == 5) { - /* - * This is Nile 4 and it will crash if we access it - * like other devices - */ - *val = nile4_in32(NILE4_PCI_BASE + where); - return PCIBIOS_SUCCESSFUL; - } - base = nile4_pre_pci_access0(slot_num); - *val = *((volatile u32 *) (base + (func_num << 8) + - (where & 0xfc))); - nile4_post_pci_access0(); - return PCIBIOS_SUCCESSFUL; - - case 2: - status = nile4_pci_read(bus, devfn, where, 4, &result); - if (status != PCIBIOS_SUCCESSFUL) - return status; - if (where & 2) - result >>= 16; - *val = (u16)(result & 0xffff); - break; - case 1: - status = nile4_pci_read(bus, devfn, where, 4, &result); - if (status != PCIBIOS_SUCCESSFUL) - return status; - if (where & 1) - result >>= 8; - if (where & 2) - result >>= 16; - *val = (u8)(result & 0xff); - break; - } - return PCIBIOS_SUCCESSFUL; -} - - -static int nile4_pci_write(struct pci_bus *bus, unsigned int devfn, int where, - int size, u32 val) -{ - int status, slot_num, func_num, shift = 0; - u32 result, base; - - switch (size) { - case 4: - /* - * For starters let's do configuration cycle 0 only - * (one bus only) - */ - if (bus->number) - return PCIBIOS_FUNC_NOT_SUPPORTED; - - slot_num = PCI_SLOT(devfn); - func_num = PCI_FUNC(devfn); - if (slot_num == 5) { - /* - * This is Nile 4 and it will crash if we access - * it like other devices - */ - nile4_out32(NILE4_PCI_BASE + where, val); - return PCIBIOS_SUCCESSFUL; - } - base = nile4_pre_pci_access0(slot_num); - *((volatile u32 *) (base + (func_num << 8) + - (where & 0xfc))) = val; - nile4_post_pci_access0(); - return PCIBIOS_SUCCESSFUL; - - case 2: - status = nile4_pci_read(bus, devfn, where, 4, &result); - if (status != PCIBIOS_SUCCESSFUL) - return status; - if (where & 2) - shift += 16; - result &= ~(0xffff << shift); - result |= (u16)(val << shift); - break; - case 1: - status = nile4_pci_read(bus, devfn, where, 4, &result); - if (status != PCIBIOS_SUCCESSFUL) - return status; - if (where & 2) - shift += 16; - if (where & 1) - shift += 8; - result &= ~(0xff << shift); - result |= (u8)(val << shift); - break; - } - return nile4_pci_write(bus, devfn, where, 4, result); -} - -struct pci_ops nile4_pci_ops = { - .read = nile4_pci_read, - .write = nile4_pci_write, -}; - -struct { - struct resource ram; - struct resource flash; - struct resource isa_io; - struct resource pci_io; - struct resource isa_mem; - struct resource pci_mem; - struct resource nile4; - struct resource boot; -} ddb5074_resources = { - { "RAM", 0x00000000, 0x03ffffff, - IORESOURCE_MEM | PCI_BASE_ADDRESS_MEM_TYPE_64}, - { "Flash ROM", 0x04000000, 0x043fffff}, - { "Nile4 ISA I/O", 0x06000000, 0x060fffff}, - { "Nile4 PCI I/O", 0x06100000, 0x07ffffff}, - { "Nile4 ISA mem", 0x08000000, 0x08ffffff, IORESOURCE_MEM}, - { "Nile4 PCI mem", 0x09000000, 0x0fffffff, IORESOURCE_MEM}, - { "Nile4 ctrl", 0x1fa00000, 0x1fbfffff, - IORESOURCE_MEM | PCI_BASE_ADDRESS_MEM_TYPE_64}, - { "Boot ROM", 0x1fc00000, 0x1fffffff} -}; - -static void __init ddb5074_pci_fixup(void) -{ - struct pci_dev *dev = NULL; - - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - if (dev->vendor == PCI_VENDOR_ID_NEC && - dev->device == PCI_DEVICE_ID_NEC_NILE4) { - /* - * The first 64-bit PCI base register should point to - * the Nile4 control registers. Unfortunately this - * isn't the case, so we fix it ourselves. This allows - * the serial driver to find the UART. - */ - dev->resource[0] = ddb5074_resources.nile4; - request_resource(&iomem_resource, - &dev->resource[0]); - /* - * The second 64-bit PCI base register points to the - * first memory bank. Unfortunately the address is - * wrong, so we fix it (again). - */ - dev->resource[2] = ddb5074_resources.ram; - request_resource(&iomem_resource, - &dev->resource[2]); - } else if (dev->vendor == PCI_VENDOR_ID_AL - && dev->device == PCI_DEVICE_ID_AL_M7101) { - /* - * It's nice to have the LEDs on the GPIO pins - * available for debugging - */ - extern struct pci_dev *pci_pmu; - u8 t8; - - pci_pmu = dev; /* for LEDs D2 and D3 */ - /* Program the lines for LEDs D2 and D3 to output */ - nile4_pci_read_config_byte(dev, 0x7d, &t8); - t8 |= 0xc0; - nile4_pci_write_config_byte(dev, 0x7d, t8); - /* Turn LEDs D2 and D3 off */ - nile4_pci_read_config_byte(dev, 0x7e, &t8); - t8 |= 0xc0; - nile4_pci_write_config_byte(dev, 0x7e, t8); - } - } -} - -static void __init pcibios_fixup_irqs(void) -{ - struct pci_dev *dev = NULL; - int slot_num; - - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - slot_num = PCI_SLOT(dev->devfn); - switch (slot_num) { - case 0: - dev->irq = nile4_to_irq(NILE4_INT_INTE); - break; - case 1: - dev->irq = nile4_to_irq(NILE4_INT_INTA); - break; - case 2: /* slot 1 */ - dev->irq = nile4_to_irq(NILE4_INT_INTA); - break; - case 3: /* slot 2 */ - dev->irq = nile4_to_irq(NILE4_INT_INTB); - break; - case 4: /* slot 3 */ - dev->irq = nile4_to_irq(NILE4_INT_INTC); - break; - case 5: - /* - * Fixup so the serial driver can use the UART - */ - dev->irq = nile4_to_irq(NILE4_INT_UART); - break; - case 13: - dev->irq = nile4_to_irq(NILE4_INT_INTE); - break; - default: - break; - } - } -} - -void __init pcibios_init(void) -{ - printk("PCI: Probing PCI hardware\n"); - ioport_resource.end = 0x1ffffff; /* 32 MB */ - iomem_resource.end = 0x1fffffff; /* 512 MB */ - /* `ram' and `nile4' are requested through the Nile4 pci_dev */ - request_resource(&iomem_resource, &ddb5074_resources.flash); - request_resource(&iomem_resource, &ddb5074_resources.isa_io); - request_resource(&iomem_resource, &ddb5074_resources.pci_io); - request_resource(&iomem_resource, &ddb5074_resources.isa_mem); - request_resource(&iomem_resource, &ddb5074_resources.pci_mem); - request_resource(&iomem_resource, &ddb5074_resources.boot); - - pci_scan_bus(0, &nile4_pci_ops, NULL); - ddb5074_pci_fixup(); - pci_assign_unassigned_resources(); - pcibios_fixup_irqs(); -} - -void __init pcibios_fixup_bus(struct pci_bus *bus) -{ - bus->resource[1] = &ddb5074_resources.pci_mem; -} - -char *pcibios_setup(char *str) -{ - return str; -} - -void __init pcibios_update_irq(struct pci_dev *dev, int irq) -{ - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); -} - -int pcibios_enable_resources(struct pci_dev *dev) -{ - u16 cmd, old_cmd; - int idx; - struct resource *r; - - /* - * Don't touch the Nile 4 - */ - if (dev->vendor == PCI_VENDOR_ID_NEC && - dev->device == PCI_DEVICE_ID_NEC_NILE4) return 0; - - pci_read_config_word(dev, PCI_COMMAND, &cmd); - old_cmd = cmd; - for (idx = 0; idx < 6; idx++) { - r = &dev->resource[idx]; - if (!r->start && r->end) { - printk(KERN_ERR "PCI: Device %s not available because " - "of resource collisions\n", dev->slot_name); - return -EINVAL; - } - if (r->flags & IORESOURCE_IO) - cmd |= PCI_COMMAND_IO; - if (r->flags & IORESOURCE_MEM) - cmd |= PCI_COMMAND_MEMORY; - } - if (cmd != old_cmd) { - printk("PCI: Enabling device %s (%04x -> %04x)\n", - dev->slot_name, old_cmd, cmd); - pci_write_config_word(dev, PCI_COMMAND, cmd); - } - return 0; -} - -int pcibios_enable_device(struct pci_dev *dev) -{ - return pcibios_enable_resources(dev); -} - -void pcibios_align_resource(void *data, struct resource *res, - unsigned long size, unsigned long align) -{ - struct pci_dev *dev = data; - - if (res->flags & IORESOURCE_IO) { - unsigned long start = res->start; - - /* We need to avoid collisions with `mirrored' VGA ports - and other strange ISA hardware, so we always want the - addresses kilobyte aligned. */ - if (size > 0x100) { - printk(KERN_ERR "PCI: I/O Region %s/%d too large" - " (%ld bytes)\n", dev->slot_name, - dev->resource - res, size); - } - - start = (start + 1024 - 1) & ~(1024 - 1); - res->start = start; - } -} - -unsigned __init int pcibios_assign_all_busses(void) -{ - return 1; -} - -struct pci_fixup pcibios_fixups[] = { }; diff -Nru a/arch/mips/ddb5074/prom.c b/arch/mips/ddb5074/prom.c --- a/arch/mips/ddb5074/prom.c Tue Jul 1 18:44:32 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,36 +0,0 @@ -/* - * arch/mips/ddb5074/prom.c -- NEC DDB Vrc-5074 PROM routines - * - * Copyright (C) 2000 Geert Uytterhoeven - * Sony Software Development Center Europe (SDCE), Brussels - */ -#include -#include -#include -#include - -#include -#include - - -char arcs_cmdline[COMMAND_LINE_SIZE]; - -void __init prom_init(const char *s) -{ - int i = 0; - - if (s != (void *) -1) - while (*s && i < sizeof(arcs_cmdline) - 1) - arcs_cmdline[i++] = *s++; - arcs_cmdline[i] = '\0'; - - mips_machgroup = MACH_GROUP_NEC_DDB; - mips_machtype = MACH_NEC_DDB5074; - - /* 64 MB non-upgradable */ - add_memory_region(0, 64 << 20, BOOT_MEM_RAM); -} - -void __init prom_free_prom_memory(void) -{ -} diff -Nru a/arch/mips/ddb5074/setup.c b/arch/mips/ddb5074/setup.c --- a/arch/mips/ddb5074/setup.c Tue Jul 1 18:44:36 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,246 +0,0 @@ -/* - * arch/mips/ddb5074/setup.c -- NEC DDB Vrc-5074 setup routines - * - * Copyright (C) 2000 Geert Uytterhoeven - * Sony Software Development Center Europe (SDCE), Brussels - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - - -#ifdef CONFIG_REMOTE_DEBUG -extern void rs_kgdb_hook(int); -extern void breakpoint(void); -#endif - -#if defined(CONFIG_SERIAL_CONSOLE) -extern void console_setup(char *); -#endif - -extern struct ide_ops std_ide_ops; -extern struct rtc_ops ddb_rtc_ops; - -static void (*back_to_prom) (void) = (void (*)(void)) 0xbfc00000; - -static void ddb_machine_restart(char *command) -{ - u32 t; - - /* PCI cold reset */ - t = nile4_in32(NILE4_PCICTRL + 4); - t |= 0x40000000; - nile4_out32(NILE4_PCICTRL + 4, t); - /* CPU cold reset */ - t = nile4_in32(NILE4_CPUSTAT); - t |= 1; - nile4_out32(NILE4_CPUSTAT, t); - /* Call the PROM */ - back_to_prom(); -} - -static void ddb_machine_halt(void) -{ - printk("DDB Vrc-5074 halted.\n"); - do { - } while (1); -} - -static void ddb_machine_power_off(void) -{ - printk("DDB Vrc-5074 halted. Please turn off the power.\n"); - do { - } while (1); -} - -extern void ddb_irq_setup(void); - -void (*board_time_init) (struct irqaction * irq); - - -static void __init ddb_time_init(struct irqaction *irq) -{ - /* set the clock to 1 Hz */ - nile4_out32(NILE4_T2CTRL, 1000000); - /* enable the General-Purpose Timer */ - nile4_out32(NILE4_T2CTRL + 4, 0x00000001); - /* reset timer */ - nile4_out32(NILE4_T2CNTR, 0); - /* enable interrupt */ - nile4_enable_irq(NILE4_INT_GPT); - i8259_setup_irq(nile4_to_irq(NILE4_INT_GPT), irq); - change_cp0_status(ST0_IM, - IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4); -} - -void __init ddb_setup(void) -{ - extern int panic_timeout; - - irq_setup = ddb_irq_setup; - mips_io_port_base = NILE4_PCI_IO_BASE; - isa_slot_offset = NILE4_PCI_MEM_BASE; - request_region(0x00, 0x20, "dma1"); - request_region(0x40, 0x20, "timer"); - request_region(0x70, 0x10, "rtc"); - request_region(0x80, 0x10, "dma page reg"); - request_region(0xc0, 0x20, "dma2"); - board_time_init = ddb_time_init; - - _machine_restart = ddb_machine_restart; - _machine_halt = ddb_machine_halt; - _machine_power_off = ddb_machine_power_off; - -#ifdef CONFIG_BLK_DEV_IDE - ide_ops = &std_ide_ops; -#endif - rtc_ops = &ddb_rtc_ops; - - /* Reboot on panic */ - panic_timeout = 180; -} - - -#define USE_NILE4_SERIAL 0 - -#if USE_NILE4_SERIAL -#define ns16550_in(reg) nile4_in8((reg)*8) -#define ns16550_out(reg, val) nile4_out8((reg)*8, (val)) -#else -#define NS16550_BASE (NILE4_PCI_IO_BASE+0x03f8) -static inline u8 ns16550_in(u32 reg) -{ - return *(volatile u8 *) (NS16550_BASE + reg); -} - -static inline void ns16550_out(u32 reg, u8 val) -{ - *(volatile u8 *) (NS16550_BASE + reg) = val; -} -#endif - -#define NS16550_RBR 0 -#define NS16550_THR 0 -#define NS16550_DLL 0 -#define NS16550_IER 1 -#define NS16550_DLM 1 -#define NS16550_FCR 2 -#define NS16550_IIR 2 -#define NS16550_LCR 3 -#define NS16550_MCR 4 -#define NS16550_LSR 5 -#define NS16550_MSR 6 -#define NS16550_SCR 7 - -#define NS16550_LSR_DR 0x01 /* Data ready */ -#define NS16550_LSR_OE 0x02 /* Overrun */ -#define NS16550_LSR_PE 0x04 /* Parity error */ -#define NS16550_LSR_FE 0x08 /* Framing error */ -#define NS16550_LSR_BI 0x10 /* Break */ -#define NS16550_LSR_THRE 0x20 /* Xmit holding register empty */ -#define NS16550_LSR_TEMT 0x40 /* Xmitter empty */ -#define NS16550_LSR_ERR 0x80 /* Error */ - - -void _serinit(void) -{ -#if USE_NILE4_SERIAL - ns16550_out(NS16550_LCR, 0x80); - ns16550_out(NS16550_DLM, 0x00); - ns16550_out(NS16550_DLL, 0x36); /* 9600 baud */ - ns16550_out(NS16550_LCR, 0x00); - ns16550_out(NS16550_LCR, 0x03); - ns16550_out(NS16550_FCR, 0x47); -#else - /* done by PMON */ -#endif -} - -void _putc(char c) -{ - while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_THRE)); - ns16550_out(NS16550_THR, c); - if (c == '\n') { - while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_THRE)); - ns16550_out(NS16550_THR, '\r'); - } -} - -void _puts(const char *s) -{ - char c; - while ((c = *s++)) - _putc(c); -} - -char _getc(void) -{ - while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_DR)); - return ns16550_in(NS16550_RBR); -} - -int _testc(void) -{ - return (ns16550_in(NS16550_LSR) & NS16550_LSR_DR) != 0; -} - - -/* - * Hexadecimal 7-segment LED - */ -void ddb5074_led_hex(int hex) -{ - outb(hex, 0x80); -} - - -/* - * LEDs D2 and D3, connected to the GPIO pins of the PMU in the ALi M1543 - */ -struct pci_dev *pci_pmu = NULL; - -void ddb5074_led_d2(int on) -{ - u8 t; - - if (pci_pmu) { - pci_read_config_byte(pci_pmu, 0x7e, &t); - if (on) - t &= 0x7f; - else - t |= 0x80; - pci_write_config_byte(pci_pmu, 0x7e, t); - } -} - -void ddb5074_led_d3(int on) -{ - u8 t; - - if (pci_pmu) { - pci_read_config_byte(pci_pmu, 0x7e, &t); - if (on) - t &= 0xbf; - else - t |= 0x40; - pci_write_config_byte(pci_pmu, 0x7e, t); - } -} diff -Nru a/arch/mips/ddb5074/time.c b/arch/mips/ddb5074/time.c --- a/arch/mips/ddb5074/time.c Tue Jul 1 18:44:35 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,32 +0,0 @@ -/* - * arch/mips/ddb5074/time.c -- Timer routines - * - * Copyright (C) 2000 Geert Uytterhoeven - * Sony Software Development Center Europe (SDCE), Brussels - */ -#include -#include - -static unsigned char ddb_rtc_read_data(unsigned long addr) -{ - outb_p(addr, RTC_PORT(0)); - - return inb_p(RTC_PORT(1)); -} - -static void ddb_rtc_write_data(unsigned char data, unsigned long addr) -{ - outb_p(addr, RTC_PORT(0)); - outb_p(data, RTC_PORT(1)); -} - -static int ddb_rtc_bcd_mode(void) -{ - return 1; -} - -struct rtc_ops ddb_rtc_ops = { - ddb_rtc_read_data, - ddb_rtc_write_data, - ddb_rtc_bcd_mode -}; diff -Nru a/arch/mips/ddb5476/Makefile b/arch/mips/ddb5476/Makefile --- a/arch/mips/ddb5476/Makefile Tue Jul 1 18:44:36 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,10 +0,0 @@ -# -# Makefile for the NEC DDB Vrc-5074 specific kernel interface routines -# under Linux. -# - -EXTRA_AFLAGS := $(CFLAGS) - -obj-y += setup.o irq.o time.o prom.o pci.o \ - int-handler.o nile4.o -obj-$(CONFIG_REMOTE_DEBUG) += dbg_io.o diff -Nru a/arch/mips/ddb5476/dbg_io.c b/arch/mips/ddb5476/dbg_io.c --- a/arch/mips/ddb5476/dbg_io.c Tue Jul 1 18:44:35 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,125 +0,0 @@ - -#include - -#if (defined(CONFIG_DDB5476) && defined(CONFIG_REMOTE_DEBUG)) - -/* --- CONFIG --- */ - -/* we need uint32 uint8 */ -/* #include "types.h" */ -typedef unsigned char uint8; -typedef unsigned int uint32; - -/* --- END OF CONFIG --- */ - -#define UART16550_BAUD_2400 2400 -#define UART16550_BAUD_4800 4800 -#define UART16550_BAUD_9600 9600 -#define UART16550_BAUD_19200 19200 -#define UART16550_BAUD_38400 38400 -#define UART16550_BAUD_57600 57600 -#define UART16550_BAUD_115200 115200 - -#define UART16550_PARITY_NONE 0 -#define UART16550_PARITY_ODD 0x08 -#define UART16550_PARITY_EVEN 0x18 -#define UART16550_PARITY_MARK 0x28 -#define UART16550_PARITY_SPACE 0x38 - -#define UART16550_DATA_5BIT 0x0 -#define UART16550_DATA_6BIT 0x1 -#define UART16550_DATA_7BIT 0x2 -#define UART16550_DATA_8BIT 0x3 - -#define UART16550_STOP_1BIT 0x0 -#define UART16550_STOP_2BIT 0x4 - -/* ----------------------------------------------------- */ - -/* === CONFIG === */ - -/* [jsun] we use the second serial port for kdb */ -#define BASE 0xa60002f8 -#define MAX_BAUD 115200 - -/* === END OF CONFIG === */ - -/* register offset */ -#define OFS_RCV_BUFFER 0 -#define OFS_TRANS_HOLD 0 -#define OFS_SEND_BUFFER 0 -#define OFS_INTR_ENABLE 1 -#define OFS_INTR_ID 2 -#define OFS_DATA_FORMAT 3 -#define OFS_LINE_CONTROL 3 -#define OFS_MODEM_CONTROL 4 -#define OFS_RS232_OUTPUT 4 -#define OFS_LINE_STATUS 5 -#define OFS_MODEM_STATUS 6 -#define OFS_RS232_INPUT 6 -#define OFS_SCRATCH_PAD 7 - -#define OFS_DIVISOR_LSB 0 -#define OFS_DIVISOR_MSB 1 - - -/* memory-mapped read/write of the port */ -#define UART16550_READ(y) (*((volatile uint8*)(BASE + y))) -#define UART16550_WRITE(y, z) ((*((volatile uint8*)(BASE + y))) = z) - -void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop) -{ - /* disable interrupts */ - UART16550_WRITE(OFS_INTR_ENABLE, 0); - - /* set up buad rate */ - { - uint32 divisor; - - /* set DIAB bit */ - UART16550_WRITE(OFS_LINE_CONTROL, 0x80); - - /* set divisor */ - divisor = MAX_BAUD / baud; - UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff); - UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8); - - /* clear DIAB bit */ - UART16550_WRITE(OFS_LINE_CONTROL, 0x0); - } - - /* set data format */ - UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop); -} - -static int remoteDebugInitialized = 0; - -uint8 getDebugChar(void) -{ - if (!remoteDebugInitialized) { - remoteDebugInitialized = 1; - debugInit(UART16550_BAUD_38400, - UART16550_DATA_8BIT, - UART16550_PARITY_NONE, UART16550_STOP_1BIT); - } - - while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0); - return UART16550_READ(OFS_RCV_BUFFER); -} - - -int putDebugChar(uint8 byte) -{ - if (!remoteDebugInitialized) { - remoteDebugInitialized = 1; - debugInit(UART16550_BAUD_9600, - UART16550_DATA_8BIT, - UART16550_PARITY_NONE, UART16550_STOP_1BIT); - } - - while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0); - UART16550_WRITE(OFS_SEND_BUFFER, byte); - return 1; -} - -#endif diff -Nru a/arch/mips/ddb5476/int-handler.S b/arch/mips/ddb5476/int-handler.S --- a/arch/mips/ddb5476/int-handler.S Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,136 +0,0 @@ -/* - * arch/mips/ddb5074/int-handler.S -- NEC DDB Vrc-5074 interrupt handler - * - * Based on arch/mips/sgi/kernel/indyIRQ.S - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * - * Copyright (C) 2000 Geert Uytterhoeven - * Sony Software Development Center Europe (SDCE), Brussels - */ -#include -#include -#include -#include - -/* - * A lot of complication here is taken away because: - * - * 1) We handle one interrupt and return, sitting in a loop and moving across - * all the pending IRQ bits in the cause register is _NOT_ the answer, the - * common case is one pending IRQ so optimize in that direction. - * - * 2) We need not check against bits in the status register IRQ mask, that - * would make this routine slow as hell. - * - * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in - * between like BSD spl() brain-damage. - * - * Furthermore, the IRQs on the INDY look basically (barring software IRQs - * which we don't use at all) like: - * - * MIPS IRQ Source - * -------- ------ - * 0 Software (ignored) - * 1 Software (ignored) - * 2 Local IRQ level zero - * 3 Local IRQ level one - * 4 8254 Timer zero - * 5 8254 Timer one - * 6 Bus Error - * 7 R4k timer (what we use) - * - * We handle the IRQ according to _our_ priority which is: - * - * Highest ---- R4k Timer - * Local IRQ zero - * Local IRQ one - * Bus Error - * 8254 Timer zero - * Lowest ---- 8254 Timer one - * - * then we just return, if multiple IRQs are pending then we will just take - * another exception, big deal. - */ - - .text - .set noreorder - .set noat - .align 5 - NESTED(ddbIRQ, PT_SIZE, sp) - SAVE_ALL - CLI - .set at - mfc0 s1, CP0_CAUSE # get irq mask - -#if 1 - mfc0 t2,CP0_STATUS # get enabled interrupts - and s0, s1, t2 # isolate allowed ones -#endif - /* First we check for r4k counter/timer IRQ. */ - andi a0, s0, CAUSEF_IP7 # cpu timer */ - bnez a0, cpu_timer_irq - andi a0, s0, CAUSEF_IP2 # delay slot, check local level zero - beq a0, zero, 1f - andi a0, s0, CAUSEF_IP3 # delay slot, check local level one - - /* Wheee, local level zero interrupt. */ - jal ddb_local0_irqdispatch - move a0, sp # delay slot - - j ret_from_irq - nop # delay slot - -1: - beq a0, zero, 1f - andi a0, s0, CAUSEF_IP6 # delay slot, check bus error - - /* Wheee, local level one interrupt. */ - move a0, sp - jal ddb_local1_irqdispatch - nop - - j ret_from_irq - nop - -1: - beq a0, zero, 1f - nop - - /* Wheee, an asynchronous bus error... */ - move a0, sp - jal ddb_buserror_irq - nop - - j ret_from_irq - nop - -1: - /* Here by mistake? This is possible, what can happen - * is that by the time we take the exception the IRQ - * pin goes low, so just leave if this is the case. - */ - andi a0, s0, (CAUSEF_IP4 | CAUSEF_IP5) - beq a0, zero, 1f - - /* Must be one of the 8254 timers... */ - move a0, sp - jal ddb_8254timer_irq - nop -1: - /* phamtom interrupt */ - move a0, s1 - jal ddb_phantom_irq - nop - j ret_from_irq - nop - -cpu_timer_irq: - li a0, 0 - move a1, sp - jal do_IRQ - /* jal ll_timer_interrupt */ - nop - j ret_from_irq - nop - END(ddbIRQ) diff -Nru a/arch/mips/ddb5476/irq.c b/arch/mips/ddb5476/irq.c --- a/arch/mips/ddb5476/irq.c Tue Jul 1 18:44:37 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,251 +0,0 @@ -/* - * arch/mips/ddb5476/irq.c -- NEC DDB Vrc-5476 interrupt routines - * - * Copyright (C) 2000 Geert Uytterhoeven - * Sony Software Development Center Europe (SDCE), Brussels - */ -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -extern void __init i8259_init(void); -extern void i8259_disable_irq(unsigned int irq_nr); -extern void i8259_enable_irq(unsigned int irq_nr); - -extern asmlinkage void ddbIRQ(void); -extern asmlinkage void i8259_do_irq(int irq, struct pt_regs *regs); -extern asmlinkage void do_IRQ(int irq, struct pt_regs *regs); - - -void no_action(int cpl, void *dev_id, struct pt_regs *regs) -{ -} - - -#define M1543_PNP_CONFIG 0x03f0 /* PnP Config Port */ -#define M1543_PNP_INDEX 0x03f0 /* PnP Index Port */ -#define M1543_PNP_DATA 0x03f1 /* PnP Data Port */ - -#define M1543_PNP_ALT_CONFIG 0x0370 /* Alternative PnP Config Port */ -#define M1543_PNP_ALT_INDEX 0x0370 /* Alternative PnP Index Port */ -#define M1543_PNP_ALT_DATA 0x0371 /* Alternative PnP Data Port */ - -#define M1543_INT1_MASTER_CTRL 0x0020 /* INT_1 (master) Control Register */ -#define M1543_INT1_MASTER_MASK 0x0021 /* INT_1 (master) Mask Register */ - -#define M1543_INT1_SLAVE_CTRL 0x00a0 /* INT_1 (slave) Control Register */ -#define M1543_INT1_SLAVE_MASK 0x00a1 /* INT_1 (slave) Mask Register */ - -#define M1543_INT1_MASTER_ELCR 0x04d0 /* INT_1 (master) Edge/Level Control */ -#define M1543_INT1_SLAVE_ELCR 0x04d1 /* INT_1 (slave) Edge/Level Control */ - -static struct { - struct resource m1543_config; - struct resource pic_elcr; -} m1543_ioport = { - { "M1543 config", M1543_PNP_CONFIG, M1543_PNP_CONFIG + 1, - IORESOURCE_BUSY}, - { "pic ELCR", M1543_INT1_MASTER_ELCR, M1543_INT1_MASTER_ELCR + 1, - IORESOURCE_BUSY} -}; - -static void m1543_irq_setup(void) -{ - /* - * The ALI M1543 has 13 interrupt inputs, IRQ1..IRQ13. Not all - * the possible IO sources in the M1543 are in use by us. We will - * use the following mapping: - * - * IRQ1 - keyboard (default set by M1543) - * IRQ3 - reserved for UART B (default set by M1543) (note that - * the schematics for the DDB Vrc-5476 board seem to - * indicate that IRQ3 is connected to the DS1386 - * watchdog timer interrupt output so we might have - * a conflict) - * IRQ4 - reserved for UART A (default set by M1543) - * IRQ5 - parallel (default set by M1543) - * IRQ8 - DS1386 time of day (RTC) interrupt - * IRQ9 - USB (hardwired in ddb_setup) - * IRQ10 - PMU (hardwired in ddb_setup) - * IRQ12 - mouse - * IRQ14,15 - IDE controller (need to be confirmed, jsun) - */ - - /* - * Assing mouse interrupt to IRQ12 - */ - - /* Enter configuration mode */ - outb(0x51, M1543_PNP_CONFIG); - outb(0x23, M1543_PNP_CONFIG); - - /* Select logical device 7 (Keyboard) */ - outb(0x07, M1543_PNP_INDEX); - outb(0x07, M1543_PNP_DATA); - - /* Select IRQ12 */ - outb(0x72, M1543_PNP_INDEX); - outb(0x0c, M1543_PNP_DATA); - - /* Leave configration mode */ - outb(0xbb, M1543_PNP_CONFIG); - - - /* Initialize the 8259 PIC in the M1543 */ - i8259_init(); - - /* Enable the interrupt cascade from M1543 */ - nile4_enable_irq(NILE4_INT_INTC); - - /* request io ports */ - if (request_resource(&ioport_resource, &m1543_ioport.m1543_config) - || request_resource(&ioport_resource, &m1543_ioport.pic_elcr)) { - printk("m1543_irq_setup : requesting io ports failed.\n"); - for (;;); - } -} - -static void nile4_irq_setup(void) -{ - int i; - - /* Map all interrupts to CPU int #0 */ - nile4_map_irq_all(0); - - /* PCI INTA#-E# must be level triggered */ - nile4_set_pci_irq_level_or_edge(0, 1); - nile4_set_pci_irq_level_or_edge(1, 1); - nile4_set_pci_irq_level_or_edge(2, 1); - nile4_set_pci_irq_level_or_edge(3, 1); - - /* PCI INTA#, B#, D# must be active low, INTC# must be active high */ - nile4_set_pci_irq_polarity(0, 0); - nile4_set_pci_irq_polarity(1, 0); - nile4_set_pci_irq_polarity(2, 1); - nile4_set_pci_irq_polarity(3, 0); - - for (i = 0; i < 16; i++) - nile4_clear_irq(i); - - /* Enable CPU int #0 */ - nile4_enable_irq_output(0); - - /* memory resource acquire in ddb_setup */ -} - - -/* - * IRQ2 is cascade interrupt to second interrupt controller - */ -static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL }; - - -void disable_irq(unsigned int irq_nr) -{ - if (is_i8259_irq(irq_nr)) - i8259_disable_irq(irq_nr); - else - nile4_disable_irq(irq_to_nile4(irq_nr)); -} - -void enable_irq(unsigned int irq_nr) -{ - if (is_i8259_irq(irq_nr)) - i8259_enable_irq(irq_nr); - else - nile4_enable_irq(irq_to_nile4(irq_nr)); -} - -int table[16] = { 0, }; - -void ddb_local0_irqdispatch(struct pt_regs *regs) -{ - u32 mask; - int nile4_irq; -#if 0 - volatile static int nesting = 0; - if (nesting++ == 0) - ddb5476_led_d3(1); - ddb5476_led_hex(nesting < 16 ? nesting : 15); -#endif - - mask = nile4_get_irq_stat(0); - nile4_clear_irq_mask(mask); - - /* Handle the timer interrupt first */ - if (mask & (1 << NILE4_INT_GPT)) { - nile4_disable_irq(NILE4_INT_GPT); - do_IRQ(nile4_to_irq(NILE4_INT_GPT), regs); - nile4_enable_irq(NILE4_INT_GPT); - mask &= ~(1 << NILE4_INT_GPT); - } - for (nile4_irq = 0; mask; nile4_irq++, mask >>= 1) - if (mask & 1) { - nile4_disable_irq(nile4_irq); - if (nile4_irq == NILE4_INT_INTC) { - int i8259_irq = nile4_i8259_iack(); - i8259_do_irq(i8259_irq, regs); - } else { - do_IRQ(nile4_to_irq(nile4_irq), regs); - } - nile4_enable_irq(nile4_irq); - } -#if 0 - if (--nesting == 0) - ddb5476_led_d3(0); - ddb5476_led_hex(nesting < 16 ? nesting : 15); -#endif -} - -void ddb_local1_irqdispatch(void) -{ - printk("ddb_local1_irqdispatch called\n"); -} - -void ddb_buserror_irq(void) -{ - printk("ddb_buserror_irq called\n"); -} - -void ddb_8254timer_irq(void) -{ - printk("ddb_8254timer_irq called\n"); -} - -void ddb_phantom_irq(unsigned long cause) -{ - printk("phantom interrupts detected : \n"); - printk("\tcause \t\t0x%08x\n", cause); - printk("\tcause reg\t0x%08x\n", - read_32bit_cp0_register(CP0_CAUSE)); - printk("\tstatus reg\t0x%08x\n", - read_32bit_cp0_register(CP0_STATUS)); -} - -void __init ddb_irq_setup(void) -{ -#ifdef CONFIG_REMOTE_DEBUG - printk("Wait for gdb client connection ...\n"); - set_debug_traps(); - breakpoint(); /* you may move this line to whereever you want :-) */ -#endif - i8259_setup_irq(2, &irq2); - - nile4_irq_setup(); - m1543_irq_setup(); - - /* we pin #0 - #4 (no internal timer) */ - change_cp0_status(ST0_IM, - IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4); - - set_except_vector(0, ddbIRQ); -} diff -Nru a/arch/mips/ddb5476/nile4.c b/arch/mips/ddb5476/nile4.c --- a/arch/mips/ddb5476/nile4.c Tue Jul 1 18:44:36 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,293 +0,0 @@ -/* - * arch/mips/ddb5074/nile4.c -- NEC Vrc-5074 Nile 4 support routines - * - * Copyright (C) 2000 Geert Uytterhoeven - * Sony Software Development Center Europe (SDCE), Brussels - */ -#include -#include - -#include - - -/* - * Physical Device Address Registers - * - * Note: 32 bit addressing only! - */ -void nile4_set_pdar(u32 pdar, u32 phys, u32 size, int width, - int on_memory_bus, int visible) -{ - u32 maskbits; - u32 widthbits; - - if (pdar > NILE4_BOOTCS || (pdar & 7)) { - printk("nile4_set_pdar: invalid pdar %d\n", pdar); - return; - } - if (pdar == NILE4_INTCS && size != 0x00200000) { - printk("nile4_set_pdar: INTCS size must be 2 MB\n"); - return; - } - switch (size) { -#if 0 /* We don't support 4 GB yet */ - case 0x100000000: /* 4 GB */ - maskbits = 4; - break; -#endif - case 0x80000000: /* 2 GB */ - maskbits = 5; - break; - case 0x40000000: /* 1 GB */ - maskbits = 6; - break; - case 0x20000000: /* 512 MB */ - maskbits = 7; - break; - case 0x10000000: /* 256 MB */ - maskbits = 8; - break; - case 0x08000000: /* 128 MB */ - maskbits = 9; - break; - case 0x04000000: /* 64 MB */ - maskbits = 10; - break; - case 0x02000000: /* 32 MB */ - maskbits = 11; - break; - case 0x01000000: /* 16 MB */ - maskbits = 12; - break; - case 0x00800000: /* 8 MB */ - maskbits = 13; - break; - case 0x00400000: /* 4 MB */ - maskbits = 14; - break; - case 0x00200000: /* 2 MB */ - maskbits = 15; - break; - case 0: /* OFF */ - maskbits = 0; - break; - default: - printk("nile4_set_pdar: unsupported size %p\n", - (void *) size); - return; - } - switch (width) { - case 8: - widthbits = 0; - break; - case 16: - widthbits = 1; - break; - case 32: - widthbits = 2; - break; - case 64: - widthbits = 3; - break; - default: - printk("nile4_set_pdar: unsupported width %d\n", width); - return; - } - nile4_out32(pdar, maskbits | (on_memory_bus ? 0x10 : 0) | - (visible ? 0x20 : 0) | (widthbits << 6) | - (phys & 0xffe00000)); - nile4_out32(pdar + 4, 0); - /* - * When programming a PDAR, the register should be read immediately - * after writing it. This ensures that address decoders are properly - * configured. - */ - nile4_in32(pdar); - nile4_in32(pdar + 4); -} - - -/* - * PCI Master Registers - * - * Note: 32 bit addressing only! - */ -void nile4_set_pmr(u32 pmr, u32 type, u32 addr) -{ - if (pmr != NILE4_PCIINIT0 && pmr != NILE4_PCIINIT1) { - printk("nile4_set_pmr: invalid pmr %d\n", pmr); - return; - } - switch (type) { - case NILE4_PCICMD_IACK: /* PCI Interrupt Acknowledge */ - case NILE4_PCICMD_IO: /* PCI I/O Space */ - case NILE4_PCICMD_MEM: /* PCI Memory Space */ - case NILE4_PCICMD_CFG: /* PCI Configuration Space */ - break; - default: - printk("nile4_set_pmr: invalid type %d\n", type); - return; - } - nile4_out32(pmr, (type << 1) | 0x10 | (addr & 0xffe00000)); - nile4_out32(pmr + 4, 0); -} - - -/* - * Interrupt Programming - */ -void nile4_map_irq(int nile4_irq, int cpu_irq) -{ - u32 offset, t; - - offset = NILE4_INTCTRL; - if (nile4_irq >= 8) { - offset += 4; - nile4_irq -= 8; - } - t = nile4_in32(offset); - t &= ~(7 << (nile4_irq * 4)); - t |= cpu_irq << (nile4_irq * 4); - nile4_out32(offset, t); -} - -void nile4_map_irq_all(int cpu_irq) -{ - u32 all, t; - - all = cpu_irq; - all |= all << 4; - all |= all << 8; - all |= all << 16; - t = nile4_in32(NILE4_INTCTRL); - t &= 0x88888888; - t |= all; - nile4_out32(NILE4_INTCTRL, t); - t = nile4_in32(NILE4_INTCTRL + 4); - t &= 0x88888888; - t |= all; - nile4_out32(NILE4_INTCTRL + 4, t); -} - -void nile4_enable_irq(int nile4_irq) -{ - u32 offset, t; - - offset = NILE4_INTCTRL; - if (nile4_irq >= 8) { - offset += 4; - nile4_irq -= 8; - } - t = nile4_in32(offset); - t |= 8 << (nile4_irq * 4); - nile4_out32(offset, t); -} - -void nile4_disable_irq(int nile4_irq) -{ - u32 offset, t; - - offset = NILE4_INTCTRL; - if (nile4_irq >= 8) { - offset += 4; - nile4_irq -= 8; - } - t = nile4_in32(offset); - t &= ~(8 << (nile4_irq * 4)); - nile4_out32(offset, t); -} - -void nile4_disable_irq_all(void) -{ - nile4_out32(NILE4_INTCTRL, 0); - nile4_out32(NILE4_INTCTRL + 4, 0); -} - -u16 nile4_get_irq_stat(int cpu_irq) -{ - return nile4_in16(NILE4_INTSTAT0 + cpu_irq * 2); -} - -void nile4_enable_irq_output(int cpu_irq) -{ - u32 t; - - t = nile4_in32(NILE4_INTSTAT1 + 4); - t |= 1 << (16 + cpu_irq); - nile4_out32(NILE4_INTSTAT1, t); -} - -void nile4_disable_irq_output(int cpu_irq) -{ - u32 t; - - t = nile4_in32(NILE4_INTSTAT1 + 4); - t &= ~(1 << (16 + cpu_irq)); - nile4_out32(NILE4_INTSTAT1, t); -} - -void nile4_set_pci_irq_polarity(int pci_irq, int high) -{ - u32 t; - - t = nile4_in32(NILE4_INTPPES); - if (high) - t &= ~(1 << (pci_irq * 2)); - else - t |= 1 << (pci_irq * 2); - nile4_out32(NILE4_INTPPES, t); -} - -void nile4_set_pci_irq_level_or_edge(int pci_irq, int level) -{ - u32 t; - - t = nile4_in32(NILE4_INTPPES); - if (level) - t |= 2 << (pci_irq * 2); - else - t &= ~(2 << (pci_irq * 2)); - nile4_out32(NILE4_INTPPES, t); -} - -void nile4_clear_irq(int nile4_irq) -{ - nile4_out32(NILE4_INTCLR, 1 << nile4_irq); -} - -void nile4_clear_irq_mask(u32 mask) -{ - nile4_out32(NILE4_INTCLR, mask); -} - -u8 nile4_i8259_iack(void) -{ - u8 irq; - - /* Set window 0 for interrupt acknowledge */ - nile4_set_pmr(NILE4_PCIINIT0, NILE4_PCICMD_IACK, 0); - irq = *(volatile u8 *) NILE4_PCI_IACK_BASE; - /* Set window 0 for PCI I/O space */ - nile4_set_pmr(NILE4_PCIINIT0, NILE4_PCICMD_IO, 0); - return irq; -} - -#if 0 -void nile4_dump_irq_status(void) -{ - printk("CPUSTAT = %p:%p\n", (void *) nile4_in32(NILE4_CPUSTAT + 4), - (void *) nile4_in32(NILE4_CPUSTAT)); - printk("INTCTRL = %p:%p\n", (void *) nile4_in32(NILE4_INTCTRL + 4), - (void *) nile4_in32(NILE4_INTCTRL)); - printk("INTSTAT0 = %p:%p\n", - (void *) nile4_in32(NILE4_INTSTAT0 + 4), - (void *) nile4_in32(NILE4_INTSTAT0)); - printk("INTSTAT1 = %p:%p\n", - (void *) nile4_in32(NILE4_INTSTAT1 + 4), - (void *) nile4_in32(NILE4_INTSTAT1)); - printk("INTCLR = %p:%p\n", (void *) nile4_in32(NILE4_INTCLR + 4), - (void *) nile4_in32(NILE4_INTCLR)); - printk("INTPPES = %p:%p\n", (void *) nile4_in32(NILE4_INTPPES + 4), - (void *) nile4_in32(NILE4_INTPPES)); -} -#endif diff -Nru a/arch/mips/ddb5476/pci.c b/arch/mips/ddb5476/pci.c --- a/arch/mips/ddb5476/pci.c Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,430 +0,0 @@ -/* - * arch/mips/ddb5476/pci.c -- NEC DDB Vrc-5074 PCI access routines - * - * Copyright (C) 2000 Geert Uytterhoeven - * Albert Dorofeev - * Sony Software Development Center Europe (SDCE), Brussels - */ -#include -#include -#include -#include -#include -#include - -#include - -static u32 nile4_pre_pci_access0(int slot_num) -{ - u32 pci_addr = 0; - u32 virt_addr = NILE4_PCI_CFG_BASE; - - /* work around the bug for Vrc5476 */ - if (slot_num == 13) - return NILE4_BASE + NILE4_PCI_BASE; - - /* Set window 1 address 08000000 - 32 bit - 128 MB (PCI config space) */ - nile4_set_pdar(NILE4_PCIW1, PHYSADDR(virt_addr), 0x08000000, 32, 0, - 0); - - // [jsun] we start scanning from addr:10, - // with 128M we can go up to addr:26 (slot 16) - if (slot_num <= 16) { - virt_addr += 0x00000400 << slot_num; - } else { - /* for high slot, we have to set higher PCI base addr */ - pci_addr = 0x00000400 << slot_num; - } - nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_CFG, pci_addr); - return virt_addr; -} - -static void nile4_post_pci_access0(void) -{ - /* - * Set window 1 back to address 08000000 - 32 bit - 128 MB - * (PCI IO space) - */ - nile4_set_pdar(NILE4_PCIW1, PHYSADDR(NILE4_PCI_MEM_BASE), - 0x08000000, 32, 1, 1); - // nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_MEM, 0); - nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_MEM, 0x08000000); -} - -static int nile4_pci_read(struct pci_bus *bus, unsigned int devfn, int where, - int size, u32 * val) -{ - int status, slot_num, func_num; - u32 result, base, addr; - - if(size == 4) { - /* Do we need to generate type 1 configure transaction? */ - if (bus->number) { - /* FIXME - not working yet */ - return PCIBIOS_FUNC_NOT_SUPPORTED; - /* - * the largest type 1 configuration addr is 16M, - * < 256M config space - */ - slot_num = 0; - addr = (bus->number << 16) | (devfn < 8) | where | 1; - } else { - slot_num = PCI_SLOT(devfn); - func_num = PCI_FUNC(devfn); - addr = (func_num << 8) + where; - } - base = nile4_pre_pci_access0(slot_num); - *val = *(volatile u32 *) (base + addr); - nile4_post_pci_access0(); - return PCIBIOS_SUCCESSFUL; - } - - status = nile4_pci_read(bus, devfn, where & ~3, 4, &result); - if (status != PCIBIOS_SUCCESSFUL) - return status; - switch (size) { - case 1: - if (where & 1) - result >>= 8; - if (where & 2) - result >>= 16; - *val = (u8)(result & 0xff); - break; - case 2: - if (where & 2) - result >>= 16; - *val = (u16)(result & 0xffff); - break; - } - return PCIBIOS_SUCCESSFUL; -} - -static int nile4_pci_write(struct pci_bus *bus, unsigned int devfn, int where, - int size, u32 val) -{ - int status, slot_num, func_num, shift = 0; - u32 result, base, addr; - - status = nile4_pci_read(bus, devfn, where & ~3, 4, &result); - if (status != PCIBIOS_SUCCESSFUL) - return status; - switch (size) { - case 1: - if (where & 2) - shift += 16; - if (where & 1) - shift += 8; - result &= ~(0xff << shift); - result |= val << shift; - break; - case 2: - if (where & 2) - shift += 16; - result &= ~(0xffff << shift); - result |= val << shift; - break; - case 4: - /* Do we need to generate type 1 configure transaction? */ - if (bus->number) { - /* FIXME - not working yet */ - return PCIBIOS_FUNC_NOT_SUPPORTED; - - /* the largest type 1 configuration addr is 16M, - * < 256M config space */ - slot_num = 0; - addr = (bus->number << 16) | (devfn < 8) | - where | 1; - } else { - slot_num = PCI_SLOT(devfn); - func_num = PCI_FUNC(devfn); - addr = (func_num << 8) + where; - } - - base = nile4_pre_pci_access0(slot_num); - *(volatile u32 *) (base + addr) = val; - nile4_post_pci_access0(); - return PCIBIOS_SUCCESSFUL; - } - return nile4_pci_write(bus, devfn, where & ~3, 4, result); -} - -struct pci_ops nile4_pci_ops = { - .read = nile4_pci_read, - .write = nile4_pci_write, -}; - -struct { - struct resource ram; - struct resource flash; - struct resource isa_io; - struct resource pci_io; - struct resource isa_mem; - struct resource pci_mem; - struct resource nile4; - struct resource boot; -} ddb5476_resources = { - // { "RAM", 0x00000000, 0x03ffffff, IORESOURCE_MEM | PCI_BASE_ADDRESS_MEM_TYPE_64 }, - { - "RAM", 0x00000000, 0x03ffffff, IORESOURCE_MEM}, { - "Flash ROM", 0x04000000, 0x043fffff}, { - "Nile4 ISA I/O", 0x06000000, 0x060fffff}, { - "Nile4 PCI I/O", 0x06100000, 0x07ffffff}, { - "Nile4 ISA mem", 0x08000000, 0x08ffffff, IORESOURCE_MEM}, { - "Nile4 PCI mem", 0x09000000, 0x0fffffff, IORESOURCE_MEM}, - // { "Nile4 ctrl", 0x1fa00000, 0x1fbfffff, IORESOURCE_MEM | PCI_BASE_ADDRESS_MEM_TYPE_64 }, - { - "Nile4 ctrl", 0x1fa00000, 0x1fbfffff, IORESOURCE_MEM}, { - "Boot ROM", 0x1fc00000, 0x1fffffff} -}; - -struct resource M5229_resources[5] = { - {"M5229 BAR0", 0x1f0, 0x1f3, IORESOURCE_IO}, - {"M5229 BAR1", 0x3f4, 0x3f7, IORESOURCE_IO}, - {"M5229 BAR2", 0x170, 0x173, IORESOURCE_IO}, - {"M5229 BAR3", 0x374, 0x377, IORESOURCE_IO}, - {"M5229 BAR4", 0xf000, 0xf00f, IORESOURCE_IO} -}; - -static void __init ddb5476_pci_fixup(void) -{ - struct pci_dev *dev = NULL; - - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - if (dev->vendor == PCI_VENDOR_ID_NEC && - dev->device == PCI_DEVICE_ID_NEC_VRC5476) { - /* - * The first 64-bit PCI base register should point to - * the Nile4 control registers. Unfortunately this - * isn't the case, so we fix it ourselves. This allows - * the serial driver to find the UART. - */ - dev->resource[0] = ddb5476_resources.nile4; - request_resource(&iomem_resource, - &dev->resource[0]); - /* - * The second 64-bit PCI base register points to the - * first memory bank. Unfortunately the address is - * wrong, so we fix it (again). - */ - - /* [jsun] We cannot request the resource anymore, - * because kernel/setup.c has already reserved "System - * RAM" resource at the same spot. - * The fundamental problem here is that PCI host - * controller should not put system RAM mapping in BAR - * and make subject to PCI resource assignement. - * Current fix is a total hack. We set parent to 1 so - * so that PCI resource assignement code is fooled to - * think the resource is assigned, and will not attempt - * to mess with it. - */ - dev->resource[2] = ddb5476_resources.ram; - if (request_resource(&iomem_resource, - &dev->resource[2]) ) { - dev->resource[2].parent = 0x1; - } - - } else if (dev->vendor == PCI_VENDOR_ID_AL - && dev->device == PCI_DEVICE_ID_AL_M7101) { - /* - * It's nice to have the LEDs on the GPIO pins - * available for debugging - */ - extern struct pci_dev *pci_pmu; - u8 t8; - - pci_pmu = dev; /* for LEDs D2 and D3 */ - /* Program the lines for LEDs D2 and D3 to output */ - nile4_pci_read(dev->bus, dev->devfn, 0x7d, 1, &t8); - t8 |= 0xc0; - nile4_pci_write(dev->bus, dev->devfn, 0x7d, 1, t8); - /* Turn LEDs D2 and D3 off */ - nile4_pci_read(dev->bus, dev->devfn, 0x7e, 1, &t8); - t8 |= 0xc0; - nile4_pci_write(dev->bus, dev->devfn, 0x7e, 1, t8); - } else if (dev->vendor == PCI_VENDOR_ID_AL && - dev->device == 0x5229) { - int i; - for (i = 0; i < 5; i++) { - dev->resource[i] = M5229_resources[i]; - request_resource(&ioport_resource, - &dev->resource[i]); - } - } - } -} - -static void __init pcibios_fixup_irqs(void) -{ - struct pci_dev *dev = NULL; - int slot_num; - - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - slot_num = PCI_SLOT(dev->devfn); - switch (slot_num) { - case 3: /* re-programmed to USB */ - dev->irq = 9; /* hard-coded; see irq.c */ - break; - case 4: /* re-programmed to PMU */ - dev->irq = 10; /* hard-coded; see irq.c */ - break; - case 6: /* on-board pci-pci bridge */ - dev->irq = 0xff; - break; - case 7: /* on-board ether */ - dev->irq = nile4_to_irq(NILE4_INT_INTB); - break; - case 8: /* ISA-PCI bridge */ - dev->irq = nile4_to_irq(NILE4_INT_INTC); - break; - case 9: /* ext slot #3 */ - dev->irq = nile4_to_irq(NILE4_INT_INTD); - break; - case 10: /* ext slot #4 */ - dev->irq = nile4_to_irq(NILE4_INT_INTA); - break; - case 13: /* Vrc5476 */ - dev->irq = 0xff; - break; - case 14: /* HD controller, M5229 */ - dev->irq = 14; - break; - default: - printk - ("JSUN : in pcibios_fixup_irqs - unkown slot %d\n", - slot_num); - panic - ("JSUN : in pcibios_fixup_irqs - unkown slot.\n"); - } - } -} - -void __init pcibios_init(void) -{ - printk("PCI: Emulate bios initialization \n"); - /* [jsun] we need to set BAR0 so that SDRAM 0 appears at 0x0 in PCI */ - *(long *) (NILE4_BASE + NILE4_BAR0) = 0x8; - - printk("PCI: Probing PCI hardware\n"); - ioport_resource.end = 0x1ffffff; /* 32 MB */ - iomem_resource.end = 0x1fffffff; /* 512 MB */ - - /* `ram' and `nile4' are requested through the Nile4 pci_dev */ - request_resource(&iomem_resource, &ddb5476_resources.flash); - request_resource(&iomem_resource, &ddb5476_resources.isa_io); - request_resource(&iomem_resource, &ddb5476_resources.pci_io); - request_resource(&iomem_resource, &ddb5476_resources.isa_mem); - request_resource(&iomem_resource, &ddb5476_resources.pci_mem); - request_resource(&iomem_resource, &ddb5476_resources.boot); - - pci_scan_bus(0, &nile4_pci_ops, NULL); - ddb5476_pci_fixup(); - pci_assign_unassigned_resources(); - pcibios_fixup_irqs(); -} - -void __init pcibios_fixup_bus(struct pci_bus *bus) -{ - /* [jsun] we don't know how to fix sub-buses yet */ - if (bus->number == 0) { - bus->resource[1] = &ddb5476_resources.pci_mem; - } -} - -char *pcibios_setup(char *str) -{ - return str; -} - -void __init pcibios_update_irq(struct pci_dev *dev, int irq) -{ - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); -} - -#if 0 /* original DDB5074 code */ -void __devinit -pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region, - struct resource *res) -{ - /* - * our caller figure out range by going through the dev structures. - * I guess this is the place to fix things up if the bus is using a - * different view of the addressing space. - */ - - if (bus->number == 0) { - ranges->io_start -= bus->resource[0]->start; - ranges->io_end -= bus->resource[0]->start; - ranges->mem_start -= bus->resource[1]->start; - ranges->mem_end -= bus->resource[1]->start; - } -} -#endif - -int pcibios_enable_resources(struct pci_dev *dev) -{ - u16 cmd, old_cmd; - int idx; - struct resource *r; - - /* - * Don't touch the Nile 4 - */ - if (dev->vendor == PCI_VENDOR_ID_NEC && - dev->device == PCI_DEVICE_ID_NEC_VRC5476) return 0; - - pci_read_config_word(dev, PCI_COMMAND, &cmd); - old_cmd = cmd; - for (idx = 0; idx < 6; idx++) { - r = &dev->resource[idx]; - if (!r->start && r->end) { - printk(KERN_ERR "PCI: Device %s not available because " - "of resource collisions\n", dev->slot_name); - return -EINVAL; - } - if (r->flags & IORESOURCE_IO) - cmd |= PCI_COMMAND_IO; - if (r->flags & IORESOURCE_MEM) - cmd |= PCI_COMMAND_MEMORY; - } - if (cmd != old_cmd) { - printk("PCI: Enabling device %s (%04x -> %04x)\n", - dev->slot_name, old_cmd, cmd); - pci_write_config_word(dev, PCI_COMMAND, cmd); - } - return 0; -} - -int pcibios_enable_device(struct pci_dev *dev) -{ - return pcibios_enable_resources(dev); -} - -void pcibios_align_resource(void *data, struct resource *res, - unsigned long size, unsigned long align) -{ - struct pci_dev *dev = data; - - if (res->flags & IORESOURCE_IO) { - unsigned long start = res->start; - - /* We need to avoid collisions with `mirrored' VGA ports - and other strange ISA hardware, so we always want the - addresses kilobyte aligned. */ - if (size > 0x100) { - printk(KERN_ERR "PCI: I/O Region %s/%d too large" - " (%ld bytes)\n", dev->slot_name, - dev->resource - res, size); - } - - start = (start + 1024 - 1) & ~(1024 - 1); - res->start = start; - } -} - -unsigned __init int pcibios_assign_all_busses(void) -{ - return 1; -} - -struct pci_fixup pcibios_fixups[] = { {0} }; diff -Nru a/arch/mips/ddb5476/prom.c b/arch/mips/ddb5476/prom.c --- a/arch/mips/ddb5476/prom.c Tue Jul 1 18:44:38 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,43 +0,0 @@ -/* - * arch/mips/ddb5476/prom.c -- NEC DDB Vrc-5476 PROM routines - * - * Copyright (C) 2000 Geert Uytterhoeven - * Sony Software Development Center Europe (SDCE), Brussels - * - * Jun Sun - modified for DDB5476. - */ -#include -#include -#include -#include - -#include -#include - - -char arcs_cmdline[COMMAND_LINE_SIZE]; - -/* [jsun@junsun.net] PMON passes arguments in C main() style */ -void __init prom_init(int argc, const char **arg) -{ - int i; - - /* arg[0] is "g", the rest is boot parameters */ - arcs_cmdline[0] = '\0'; - for (i = 1; i < argc; i++) { - if (strlen(arcs_cmdline) + strlen(arg[i] + 1) - >= sizeof(arcs_cmdline)) - break; - strcat(arcs_cmdline, arg[i]); - strcat(arcs_cmdline, " "); - } - - mips_machgroup = MACH_GROUP_NEC_DDB; - mips_machtype = MACH_NEC_DDB5476; - /* 64 MB non-upgradable */ - add_memory_region(0, 64 << 20, BOOT_MEM_RAM); -} - -void __init prom_free_prom_memory(void) -{ -} diff -Nru a/arch/mips/ddb5476/setup.c b/arch/mips/ddb5476/setup.c --- a/arch/mips/ddb5476/setup.c Tue Jul 1 18:44:36 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,393 +0,0 @@ -/* - * arch/mips/ddb5476/setup.c -- NEC DDB Vrc-5476 setup routines - * - * Copyright (C) 2000 Geert Uytterhoeven - * Sony Software Development Center Europe (SDCE), Brussels - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - - -#ifdef CONFIG_REMOTE_DEBUG -extern void rs_kgdb_hook(int); -extern void breakpoint(void); -#endif - -#if defined(CONFIG_SERIAL_CONSOLE) -extern void console_setup(char *); -#endif - -extern struct ide_ops std_ide_ops; -extern struct rtc_ops ddb_rtc_ops; -extern struct kbd_ops std_kbd_ops; - -static void (*back_to_prom) (void) = (void (*)(void)) 0xbfc00000; - -static void ddb_machine_restart(char *command) -{ - u32 t; - - /* PCI cold reset */ - t = nile4_in32(NILE4_PCICTRL + 4); - t |= 0x40000000; - nile4_out32(NILE4_PCICTRL + 4, t); - /* CPU cold reset */ - t = nile4_in32(NILE4_CPUSTAT); - t |= 1; - nile4_out32(NILE4_CPUSTAT, t); - /* Call the PROM */ - back_to_prom(); -} - -static void ddb_machine_halt(void) -{ - printk("DDB Vrc-5476 halted.\n"); - while (1); -} - -static void ddb_machine_power_off(void) -{ - printk("DDB Vrc-5476 halted. Please turn off the power.\n"); - while (1); -} - -extern void ddb_irq_setup(void); - -static void __init ddb_time_init(struct irqaction *irq) -{ - printk("ddb_time_init invoked.\n"); - mips_counter_frequency = 83000000; -} - -static void __init ddb_timer_setup(struct irqaction *irq) -{ - unsigned int count; - - /* we are using the cpu counter for timer interrupts */ - i8259_setup_irq(0, irq); - set_cp0_status(IE_IRQ5); - - /* to generate the first timer interrupt */ - count = read_32bit_cp0_register(CP0_COUNT); - write_32bit_cp0_register(CP0_COMPARE, count + 1000); - -#if 0 /* the old way to do timer interrupt */ - /* set the clock to 100 Hz */ - nile4_out32(NILE4_T2CTRL, 830000); - /* enable the General-Purpose Timer */ - nile4_out32(NILE4_T2CTRL + 4, 0x00000001); - /* reset timer */ - nile4_out32(NILE4_T2CNTR, 0); - /* enable interrupt */ - nile4_enable_irq(NILE4_INT_GPT); - i8259_setup_irq(nile4_to_irq(NILE4_INT_GPT), irq); -#endif -} - -static struct { - struct resource dma1; - struct resource pic1; - struct resource timer; - struct resource rtc; - struct resource dma_page_reg; - struct resource pic2; - struct resource dma2; -} ddb5476_ioport = { - { - "dma1", 0x00, 0x1f, IORESOURCE_BUSY}, { - "pic1", 0x20, 0x3f, IORESOURCE_BUSY}, { - "timer", 0x40, 0x5f, IORESOURCE_BUSY}, { - "rtc", 0x70, 0x7f, IORESOURCE_BUSY}, { - "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY}, { - "pic2", 0xa0, 0xbf, IORESOURCE_BUSY}, { - "dma2", 0xc0, 0xdf, IORESOURCE_BUSY} -}; - -static struct { - struct resource nile4; -} ddb5476_iomem = { - { "Nile 4", NILE4_BASE, NILE4_BASE + NILE4_SIZE - 1, IORESOURCE_BUSY} -}; - -void __init ddb_setup(void) -{ - extern int panic_timeout; - - irq_setup = ddb_irq_setup; - mips_io_port_base = NILE4_PCI_IO_BASE; - isa_slot_offset = NILE4_PCI_MEM_BASE; - - board_time_init = ddb_time_init; - board_timer_setup = ddb_timer_setup; - - _machine_restart = ddb_machine_restart; - _machine_halt = ddb_machine_halt; - _machine_power_off = ddb_machine_power_off; - - /* request io port/mem resources */ - if (request_resource(&ioport_resource, &ddb5476_ioport.dma1) || - request_resource(&ioport_resource, &ddb5476_ioport.pic1) || - request_resource(&ioport_resource, &ddb5476_ioport.timer) || - request_resource(&ioport_resource, &ddb5476_ioport.rtc) || - request_resource(&ioport_resource, - &ddb5476_ioport.dma_page_reg) - || request_resource(&ioport_resource, &ddb5476_ioport.pic2) - || request_resource(&ioport_resource, &ddb5476_ioport.dma2) - || request_resource(&iomem_resource, &ddb5476_iomem.nile4)) { - printk - ("ddb_setup - requesting oo port resources failed.\n"); - for (;;); - } -#ifdef CONFIG_BLK_DEV_IDE - ide_ops = &std_ide_ops; -#endif - rtc_ops = &ddb_rtc_ops; - -#ifdef CONFIG_PC_KEYB - kbd_ops = &std_kbd_ops; -#endif - - /* Reboot on panic */ - panic_timeout = 180; - - /* [jsun] we need to set BAR0 so that SDRAM 0 appears at 0x0 in PCI */ - /* *(long*)0xbfa00218 = 0x8; */ - -#ifdef CONFIG_FB - conswitchp = &dummy_con; -#endif - - - /* board initialization stuff - non-fundamental, but need to be set - * before kernel runs */ - - /* setup I/O space */ - nile4_set_pdar(NILE4_PCIW0, - PHYSADDR(NILE4_PCI_IO_BASE), 0x02000000, 32, 0, 0); - nile4_set_pmr(NILE4_PCIINIT0, NILE4_PCICMD_IO, 0); - - /* map config space to 0xa8000000, 128MB */ - nile4_set_pdar(NILE4_PCIW1, - PHYSADDR(NILE4_PCI_CFG_BASE), 0x08000000, 32, 0, 0); - nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_CFG, 0x0); - - /* ----- M1543 PCI setup ------ */ - - /* we know M1543 PCI-ISA controller is at addr:18 */ - /* xxxx1010 makes USB at addr:13 and PMU at addr:14 */ - *(volatile unsigned char *) 0xa8040072 &= 0xf0; - *(volatile unsigned char *) 0xa8040072 |= 0xa; - - /* setup USB interrupt to IRQ 9, (bit 0:3 - 0001) - * no IOCHRDY signal, (bit 7 - 1) - * M1543C & M7101 VID and Subsys Device ID are read-only (bit 6 - 1) - * Bypass USB Master INTAJ level to edge conversion (bit 4 - 0) - */ - *(unsigned char *) 0xa8040074 = 0xc1; - - /* setup PMU(SCI to IRQ 10 (bit 0:3 - 0011) - * SCI routing to IRQ 13 disabled (bit 7 - 1) - * SCI interrupt level to edge conversion bypassed (bit 4 - 0) - */ - *(unsigned char *) 0xa8040076 = 0x83; - - /* setup IDE controller - * enable IDE controller (bit 6 - 1) - * IDE IDSEL to be addr:24 (bit 4:5 - 11) - * no IDE ATA Secondary Bus Signal Pad Control (bit 3 - 0) - * no IDE ATA Primary Bus Signal Pad Control (bit 2 - 0) - * primary IRQ is 14, secondary is 15 (bit 1:0 - 01 - */ - // *(unsigned char*)0xa8040058 = 0x71; - // *(unsigned char*)0xa8040058 = 0x79; - // *(unsigned char*)0xa8040058 = 0x74; // use SIRQ, primary tri-state - *(unsigned char *) 0xa8040058 = 0x75; // primary tri-state - -#if 0 - /* this is not necessary if M5229 does not use SIRQ */ - *(unsigned char *) 0xa8040044 = 0x0d; // primary to IRQ 14 - *(unsigned char *) 0xa8040075 = 0x0d; // secondary to IRQ 14 -#endif - - /* enable IDE in the M5229 config register 0x50 (bit 0 - 1) */ - /* M5229 IDSEL is addr:24; see above setting */ - *(unsigned char *) 0xa9000050 |= 0x1; - - /* enable bus master (bit 2) and IO decoding (bit 0) */ - *(unsigned char *) 0xa9000004 |= 0x5; - - /* enable native, copied from arch/ppc/k2boot/head.S */ - /* TODO - need volatile, need to be portable */ - *(unsigned char *) 0xa9000009 = 0xff; - - /* ----- end of M1543 PCI setup ------ */ - - /* ----- reset on-board ether chip ------ */ - *((volatile u32 *) 0xa8020004) |= 1; /* decode I/O */ - *((volatile u32 *) 0xa8020010) = 0; /* set BAR address */ - - /* send reset command */ - *((volatile u32 *) 0xa6000000) = 1; /* do a soft reset */ - - /* disable ether chip */ - *((volatile u32 *) 0xa8020004) = 0; /* disable any decoding */ - - /* put it into sleep */ - *((volatile u32 *) 0xa8020040) = 0x80000000; - - /* ----- end of reset on-board ether chip ------ */ - - /* ----- set pci window 1 to pci memory space -------- */ - nile4_set_pdar(NILE4_PCIW1, - PHYSADDR(NILE4_PCI_MEM_BASE), 0x08000000, 32, 0, 0); - // nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_MEM, 0); - nile4_set_pmr(NILE4_PCIINIT1, NILE4_PCICMD_MEM, 0x08000000); - -} - -#define USE_NILE4_SERIAL 0 - -#if USE_NILE4_SERIAL -#define ns16550_in(reg) nile4_in8((reg)*8) -#define ns16550_out(reg, val) nile4_out8((reg)*8, (val)) -#else -#define NS16550_BASE (NILE4_PCI_IO_BASE+0x03f8) -static inline u8 ns16550_in(u32 reg) -{ - return *(volatile u8 *) (NS16550_BASE + reg); -} - -static inline void ns16550_out(u32 reg, u8 val) -{ - *(volatile u8 *) (NS16550_BASE + reg) = val; -} -#endif - -#define NS16550_RBR 0 -#define NS16550_THR 0 -#define NS16550_DLL 0 -#define NS16550_IER 1 -#define NS16550_DLM 1 -#define NS16550_FCR 2 -#define NS16550_IIR 2 -#define NS16550_LCR 3 -#define NS16550_MCR 4 -#define NS16550_LSR 5 -#define NS16550_MSR 6 -#define NS16550_SCR 7 - -#define NS16550_LSR_DR 0x01 /* Data ready */ -#define NS16550_LSR_OE 0x02 /* Overrun */ -#define NS16550_LSR_PE 0x04 /* Parity error */ -#define NS16550_LSR_FE 0x08 /* Framing error */ -#define NS16550_LSR_BI 0x10 /* Break */ -#define NS16550_LSR_THRE 0x20 /* Xmit holding register empty */ -#define NS16550_LSR_TEMT 0x40 /* Xmitter empty */ -#define NS16550_LSR_ERR 0x80 /* Error */ - - -void _serinit(void) -{ -#if USE_NILE4_SERIAL - ns16550_out(NS16550_LCR, 0x80); - ns16550_out(NS16550_DLM, 0x00); - ns16550_out(NS16550_DLL, 0x36); /* 9600 baud */ - ns16550_out(NS16550_LCR, 0x00); - ns16550_out(NS16550_LCR, 0x03); - ns16550_out(NS16550_FCR, 0x47); -#else - /* done by PMON */ -#endif -} - -void _putc(char c) -{ - while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_THRE)); - ns16550_out(NS16550_THR, c); - if (c == '\n') { - while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_THRE)); - ns16550_out(NS16550_THR, '\r'); - } -} - -void _puts(const char *s) -{ - char c; - - while ((c = *s++)) - _putc(c); -} - -char _getc(void) -{ - while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_DR)); - - return ns16550_in(NS16550_RBR); -} - -int _testc(void) -{ - return (ns16550_in(NS16550_LSR) & NS16550_LSR_DR) != 0; -} - - -/* - * Hexadecimal 7-segment LED - */ -void ddb5476_led_hex(int hex) -{ - outb(hex, 0x80); -} - - -/* - * LEDs D2 and D3, connected to the GPIO pins of the PMU in the ALi M1543 - */ -struct pci_dev *pci_pmu = NULL; - -void ddb5476_led_d2(int on) -{ - u8 t; - - if (pci_pmu) { - pci_read_config_byte(pci_pmu, 0x7e, &t); - if (on) - t &= 0x7f; - else - t |= 0x80; - pci_write_config_byte(pci_pmu, 0x7e, t); - } -} - -void ddb5476_led_d3(int on) -{ - u8 t; - - if (pci_pmu) { - pci_read_config_byte(pci_pmu, 0x7e, &t); - if (on) - t &= 0xbf; - else - t |= 0x40; - pci_write_config_byte(pci_pmu, 0x7e, t); - } -} diff -Nru a/arch/mips/ddb5476/time.c b/arch/mips/ddb5476/time.c --- a/arch/mips/ddb5476/time.c Tue Jul 1 18:44:36 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,32 +0,0 @@ -/* - * arch/mips/ddb5074/time.c -- Timer routines - * - * Copyright (C) 2000 Geert Uytterhoeven - * Sony Software Development Center Europe (SDCE), Brussels - */ -#include - -#include - -static unsigned char ddb_rtc_read_data(unsigned long addr) -{ - outb_p(addr, RTC_PORT(0)); - return inb_p(RTC_PORT(1)); -} - -static void ddb_rtc_write_data(unsigned char data, unsigned long addr) -{ - outb_p(addr, RTC_PORT(0)); - outb_p(data, RTC_PORT(1)); -} - -static int ddb_rtc_bcd_mode(void) -{ - return 1; -} - -struct rtc_ops ddb_rtc_ops = { - ddb_rtc_read_data, - ddb_rtc_write_data, - ddb_rtc_bcd_mode -}; diff -Nru a/arch/mips/ddb5xxx/common/Makefile b/arch/mips/ddb5xxx/common/Makefile --- a/arch/mips/ddb5xxx/common/Makefile Tue Jul 1 18:44:38 2003 +++ b/arch/mips/ddb5xxx/common/Makefile Tue Jul 1 18:44:38 2003 @@ -2,4 +2,4 @@ # Makefile for the common code of NEC DDB-Vrc5xxx board # -obj-y += irq.o irq_cpu.o nile4.o prom.o pci.o pci_auto.o rtc_ds1386.o +obj-y += irq.o nile4.o prom.o rtc_ds1386.o diff -Nru a/arch/mips/ddb5xxx/common/irq.c b/arch/mips/ddb5xxx/common/irq.c --- a/arch/mips/ddb5xxx/common/irq.c Tue Jul 1 18:44:36 2003 +++ b/arch/mips/ddb5xxx/common/irq.c Tue Jul 1 18:44:36 2003 @@ -13,12 +13,13 @@ */ #include #include +#include void (*irq_setup)(void); void __init init_IRQ(void) { -#ifdef CONFIG_REMOTE_DEBUG +#ifdef CONFIG_KGDB extern void breakpoint(void); extern void set_debug_traps(void); @@ -26,6 +27,8 @@ set_debug_traps(); breakpoint(); #endif + /* set up default irq controller */ + init_generic_irq(); /* invoke board-specific irq setup */ irq_setup(); diff -Nru a/arch/mips/ddb5xxx/common/irq_cpu.c b/arch/mips/ddb5xxx/common/irq_cpu.c --- a/arch/mips/ddb5xxx/common/irq_cpu.c Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,115 +0,0 @@ -/*********************************************************************** - * Copyright 2001 MontaVista Software Inc. - * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net - * - * arch/mips/ddb5xxx/common/irq_cpu.c - * This file define the irq handler for MIPS CPU interrupts. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - *********************************************************************** - */ - -/* - * Almost all MIPS CPUs define 8 interrupt sources. They are typically - * level triggered (i.e., cannot be cleared from CPU; must be cleared from - * device). The first two are software interrupts. The last one is - * usually cpu timer interrupt if coutner register is present. - * - * This file exports one global function: - * mips_cpu_irq_init(u32 irq_base); - */ - -#include -#include -#include - -#include - -/* [jsun] sooner or later we should move this debug stuff to MIPS common */ -#include - -static int mips_cpu_irq_base=-1; - -static void -mips_cpu_irq_enable(unsigned int irq) -{ - MIPS_ASSERT(mips_cpu_irq_base != -1); - MIPS_ASSERT(irq >= mips_cpu_irq_base); - MIPS_ASSERT(irq < mips_cpu_irq_base+8); - - clear_cp0_cause( 1 << (irq - mips_cpu_irq_base + 8)); - set_cp0_status(1 << (irq - mips_cpu_irq_base + 8)); -} - -static void -mips_cpu_irq_disable(unsigned int irq) -{ - MIPS_ASSERT(mips_cpu_irq_base != -1); - MIPS_ASSERT(irq >= mips_cpu_irq_base); - MIPS_ASSERT(irq < mips_cpu_irq_base+8); - - clear_cp0_status(1 << (irq - mips_cpu_irq_base + 8)); -} - -static unsigned int mips_cpu_irq_startup(unsigned int irq) -{ - mips_cpu_irq_enable(irq); - return 0; -} - -#define mips_cpu_irq_shutdown mips_cpu_irq_disable - -static void -mips_cpu_irq_ack(unsigned int irq) -{ - MIPS_ASSERT(mips_cpu_irq_base != -1); - MIPS_ASSERT(irq >= mips_cpu_irq_base); - MIPS_ASSERT(irq < mips_cpu_irq_base+8); - - /* although we attemp to clear the IP bit in cause reigster, I think - * usually it is cleared by device (irq source) - */ - clear_cp0_cause( 1 << (irq - mips_cpu_irq_base + 8)); - - /* I am not fully convinced that I should disable irq here */ -} - -static void -mips_cpu_irq_end(unsigned int irq) -{ - MIPS_ASSERT(mips_cpu_irq_base != -1); - MIPS_ASSERT(irq >= mips_cpu_irq_base); - MIPS_ASSERT(irq < mips_cpu_irq_base+8); - /* I am not fully convinced that I should enable irq here */ -} - -static hw_irq_controller mips_cpu_irq_controller = { - "CPU_irq", - mips_cpu_irq_startup, - mips_cpu_irq_shutdown, - mips_cpu_irq_enable, - mips_cpu_irq_disable, - mips_cpu_irq_ack, - mips_cpu_irq_end, - NULL /* no affinity stuff for UP */ -}; - - -void -mips_cpu_irq_init(u32 irq_base) -{ - extern irq_desc_t irq_desc[]; - u32 i; - - for (i= irq_base; i< irq_base+8; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = NULL; - irq_desc[i].depth = 1; - irq_desc[i].handler = &mips_cpu_irq_controller; - } - - mips_cpu_irq_base = irq_base; -} diff -Nru a/arch/mips/ddb5xxx/common/nile4.c b/arch/mips/ddb5xxx/common/nile4.c --- a/arch/mips/ddb5xxx/common/nile4.c Tue Jul 1 18:44:36 2003 +++ b/arch/mips/ddb5xxx/common/nile4.c Tue Jul 1 18:44:36 2003 @@ -1,4 +1,4 @@ -/*********************************************************************** +/* * * Copyright 2001 MontaVista Software Inc. * Author: jsun@mvista.com or jsun@junsun.net @@ -12,19 +12,14 @@ * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. - * - *********************************************************************** */ - -#include #include #include #include -#include u32 -ddb_calc_pdar(u32 phys, u32 size, int width, +ddb_calc_pdar(u32 phys, u32 size, int width, int on_memory_bus, int pci_visible) { u32 maskbits; @@ -73,7 +68,7 @@ maskbits = 0; break; default: - panic("nile4_set_pdar: unsupported size %p\n", (void *) size); + panic("nile4_set_pdar: unsupported size %p", (void *) size); } switch (width) { case 8: @@ -89,7 +84,7 @@ widthbits = 3; break; default: - panic("nile4_set_pdar: unsupported width %d\n", width); + panic("nile4_set_pdar: unsupported width %d", width); } return maskbits | (on_memory_bus ? 0x10 : 0) | @@ -128,7 +123,7 @@ case DDB_PCICMD_CFG: /* PCI Configuration Space */ break; default: - panic("nile4_set_pmr: invalid type %d\n", type); + panic("nile4_set_pmr: invalid type %d", type); } ddb_out32(pmr, (type << 1) | (addr & 0xffe00000) | options ); ddb_out32(pmr + 4, 0); diff -Nru a/arch/mips/ddb5xxx/common/pci.c b/arch/mips/ddb5xxx/common/pci.c --- a/arch/mips/ddb5xxx/common/pci.c Tue Jul 1 18:44:39 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,172 +0,0 @@ -/*********************************************************************** - * Copyright 2001 MontaVista Software Inc. - * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net - * - * arch/mips/ddb5xxx/common/pci.c - * Common PCI routines for DDB5xxx - as a matter of fact, meant for all - * MIPS machines. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - *********************************************************************** - */ - -/* - * This file contains common PCI routines meant to be shared for - * all MIPS machines. - * - * Strategies: - * - * . We rely on pci_auto.c file to assign PCI resources (MEM and IO) - * TODO: this should be optional for some machines where they do have - * a real "pcibios" that does resource assignment. - * - * . We then use pci_scan_bus() to "discover" all the resources for - * later use by Linux. - * - * . We finally reply on a board supplied function, pcibios_fixup_irq(), to - * to assign the interrupts. We may use setup-irq.c under drivers/pci - * later. - * - * . Specifically, we will *NOT* use pci_assign_unassigned_resources(), - * because we assume all PCI devices should have the resources correctly - * assigned and recorded. - * - * Limitations: - * - * . We "collapse" all IO and MEM spaces in sub-buses under a top-level bus - * into a contiguous range. - * - * . In the case of Memory space, the rnage is 1:1 mapping with CPU physical - * address space. - * - * . In the case of IO space, it starts from 0, and the beginning address - * is mapped to KSEG0ADDR(mips_io_port) in the CPU physical address. - * - * . These are the current MIPS limitations (by ioremap, etc). In the - * future, we may remove them. - * - * Credits: - * Most of the code are derived from the pci routines from PPC and Alpha, - * which were mostly writtne by - * Cort Dougan, cort@fsmlabs.com - * Matt Porter, mporter@mvista.com - * Dave Rusling david.rusling@reo.mts.dec.com - * David Mosberger davidm@cs.arizona.edu - */ - -#include -#include -#include -#include - -#include -#include - - -struct pci_fixup pcibios_fixups[] = { {0} }; - - -extern int pciauto_assign_resources(int busno, struct pci_channel * hose); -void __init pcibios_init(void) -{ - struct pci_channel *p; - struct pci_bus *bus; - int busno; - - /* assign resources */ - busno=0; - for (p= mips_pci_channels; p->pci_ops != NULL; p++) { - busno = pciauto_assign_resources(busno, p) + 1; - } - - /* scan the buses */ - busno = 0; - for (p= mips_pci_channels; p->pci_ops != NULL; p++) { - bus = pci_scan_bus(busno, p->pci_ops, p); - busno = bus->subordinate+1; - } - - /* fixup irqs (board specific routines) */ - pcibios_fixup_irqs(); - - /* - * should we do a fixup of ioport_resource and iomem_resource - * based on mips_pci_channels? - * Let us wait and see if this is a common need and whether there - * are exceptions. Until then, each board should adjust them - * perhaps in their setup() function. - */ -} - -int pcibios_enable_device(struct pci_dev *dev) -{ - /* pciauto_assign_resources() will enable all devices found */ - return 0; -} - -unsigned long __init -pci_bridge_check_io(struct pci_dev *bridge) -{ - u16 io; - - pci_read_config_word(bridge, PCI_IO_BASE, &io); - if (!io) { - pci_write_config_word(bridge, PCI_IO_BASE, 0xf0f0); - pci_read_config_word(bridge, PCI_IO_BASE, &io); - pci_write_config_word(bridge, PCI_IO_BASE, 0x0); - } - if (io) - return IORESOURCE_IO; - printk(KERN_WARNING "PCI: bridge %s does not support I/O forwarding!\n", - bridge->name); - return 0; -} - -void __init pcibios_fixup_bus(struct pci_bus *bus) -{ - /* Propogate hose info into the subordinate devices. */ - - struct pci_channel *hose = bus->sysdata; - struct pci_dev *dev = bus->self; - - if (!dev) { - /* Root bus */ - bus->resource[0] = hose->io_resource; - bus->resource[1] = hose->mem_resource; - } else { - /* This is a bridge. Do not care how it's initialized, - just link its resources to the bus ones */ - int i; - - for(i=0; i<3; i++) { - bus->resource[i] = - &dev->resource[PCI_BRIDGE_RESOURCES+i]; - bus->resource[i]->name = bus->name; - } - bus->resource[0]->flags |= pci_bridge_check_io(dev); - bus->resource[1]->flags |= IORESOURCE_MEM; - /* For now, propagate hose limits to the bus; - we'll adjust them later. */ - bus->resource[0]->end = hose->io_resource->end; - bus->resource[1]->end = hose->mem_resource->end; - /* Turn off downstream PF memory address range by default */ - bus->resource[2]->start = 1024*1024; - bus->resource[2]->end = bus->resource[2]->start - 1; - } -} - -char *pcibios_setup(char *str) -{ - return str; -} - -void -pcibios_align_resource(void *data, struct resource *res, - unsigned long size, unsigned long align) -{ - /* this should not be called */ - MIPS_ASSERT(1 == 0); -} diff -Nru a/arch/mips/ddb5xxx/common/pci_auto.c b/arch/mips/ddb5xxx/common/pci_auto.c --- a/arch/mips/ddb5xxx/common/pci_auto.c Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,396 +0,0 @@ -/* - * arch/ppc/kernel/pci_auto.c - * - * PCI autoconfiguration library - * - * Author: Matt Porter - * - * Copyright 2000, 2001 MontaVista Software Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -/* - * Modified for MIPS by Jun Sun, jsun@mvista.com - * - * . Simplify the interface between pci_auto and the rest: a single function. - * . Assign resources from low address to upper address. - * . change most int to u32. - */ - -#include -#include -#include -#include - -#include -#include - -#define DEBUG -#ifdef DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - -/* These are used for config access before all the PCI probing - has been done. */ -int early_read_config_byte(struct pci_channel *hose, int bus, int dev_fn, int where, u8 *val); -int early_read_config_word(struct pci_channel *hose, int bus, int dev_fn, int where, u16 *val); -int early_read_config_dword(struct pci_channel *hose, int bus, int dev_fn, int where, u32 *val); -int early_write_config_byte(struct pci_channel *hose, int bus, int dev_fn, int where, u8 val); -int early_write_config_word(struct pci_channel *hose, int bus, int dev_fn, int where, u16 val); -int early_write_config_dword(struct pci_channel *hose, int bus, int dev_fn, int where, u32 val); - -static u32 pciauto_lower_iospc; -static u32 pciauto_upper_iospc; - -static u32 pciauto_lower_memspc; -static u32 pciauto_upper_memspc; - -void __init -pciauto_setup_bars(struct pci_channel *hose, - int current_bus, - int pci_devfn) -{ - u32 bar_response, bar_size, bar_value; - u32 bar, addr_mask, bar_nr = 0; - u32 * upper_limit; - u32 * lower_limit; - int found_mem64 = 0; - - DBG("PCI Autoconfig: Found Bus %d, Device %d, Function %d\n", - current_bus, PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn) ); - - for (bar = PCI_BASE_ADDRESS_0; bar <= PCI_BASE_ADDRESS_5; bar+=4) - { - /* Tickle the BAR and get the response */ - early_write_config_dword(hose, - current_bus, - pci_devfn, - bar, - 0xffffffff); - early_read_config_dword(hose, - current_bus, - pci_devfn, - bar, - &bar_response); - - /* If BAR is not implemented go to the next BAR */ - if (!bar_response) - continue; - - /* Check the BAR type and set our address mask */ - if (bar_response & PCI_BASE_ADDRESS_SPACE) - { - addr_mask = PCI_BASE_ADDRESS_IO_MASK; - upper_limit = &pciauto_upper_iospc; - lower_limit = &pciauto_lower_iospc; - DBG("PCI Autoconfig: BAR %d, I/O, ", bar_nr); - } - else - { - if ( (bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == - PCI_BASE_ADDRESS_MEM_TYPE_64) - found_mem64 = 1; - - addr_mask = PCI_BASE_ADDRESS_MEM_MASK; - upper_limit = &pciauto_upper_memspc; - lower_limit = &pciauto_lower_memspc; - DBG("PCI Autoconfig: BAR %d, Mem, ", bar_nr); - } - - /* Calculate requested size */ - bar_size = ~(bar_response & addr_mask) + 1; - - /* Allocate a base address */ - bar_value = ((*lower_limit - 1) & ~(bar_size - 1)) + bar_size; - MIPS_ASSERT(bar_value + bar_size <= *upper_limit); - - /* Write it out and update our limit */ - early_write_config_dword(hose, - current_bus, - pci_devfn, - bar, - bar_value); - - *lower_limit = bar_value + bar_size; - - /* - * If we are a 64-bit decoder then increment to the - * upper 32 bits of the bar and force it to locate - * in the lower 4GB of memory. - */ - if (found_mem64) - { - bar += 4; - early_write_config_dword(hose, - current_bus, - pci_devfn, - bar, - 0x00000000); - } - - bar_nr++; - - DBG("size=0x%x, address=0x%x\n", - bar_size, bar_value); - } - -} - -void __init -pciauto_prescan_setup_bridge(struct pci_channel *hose, - int current_bus, - int pci_devfn, - int sub_bus) -{ - int cmdstat; - - /* Configure bus number registers */ - early_write_config_byte(hose, - current_bus, - pci_devfn, - PCI_PRIMARY_BUS, - current_bus); - early_write_config_byte(hose, - current_bus, - pci_devfn, - PCI_SECONDARY_BUS, - sub_bus + 1); - early_write_config_byte(hose, - current_bus, - pci_devfn, - PCI_SUBORDINATE_BUS, - 0xff); - - /* Round memory allocator to 1MB boundary */ - pciauto_upper_memspc &= ~(0x100000 - 1); - - /* Round I/O allocator to 4KB boundary */ - pciauto_upper_iospc &= ~(0x1000 - 1); - - /* Set up memory and I/O filter limits, assume 32-bit I/O space */ - early_write_config_word(hose, - current_bus, - pci_devfn, - PCI_MEMORY_LIMIT, - ((pciauto_upper_memspc - 1) & 0xfff00000) >> 16); - early_write_config_byte(hose, - current_bus, - pci_devfn, - PCI_IO_LIMIT, - ((pciauto_upper_iospc - 1) & 0x0000f000) >> 8); - early_write_config_word(hose, - current_bus, - pci_devfn, - PCI_IO_LIMIT_UPPER16, - ((pciauto_upper_iospc - 1) & 0xffff0000) >> 16); - - /* We don't support prefetchable memory for now, so disable */ - early_write_config_word(hose, - current_bus, - pci_devfn, - PCI_PREF_MEMORY_BASE, - 0x1000); - early_write_config_word(hose, - current_bus, - pci_devfn, - PCI_PREF_MEMORY_LIMIT, - 0x1000); - - /* Enable memory and I/O accesses, enable bus master */ - early_read_config_dword(hose, - current_bus, - pci_devfn, - PCI_COMMAND, - &cmdstat); - early_write_config_dword(hose, - current_bus, - pci_devfn, - PCI_COMMAND, - cmdstat | - PCI_COMMAND_IO | - PCI_COMMAND_MEMORY | - PCI_COMMAND_MASTER); -} - -void __init -pciauto_postscan_setup_bridge(struct pci_channel *hose, - int current_bus, - int pci_devfn, - int sub_bus) -{ - /* Configure bus number registers */ - early_write_config_byte(hose, - current_bus, - pci_devfn, - PCI_SUBORDINATE_BUS, - sub_bus); - - /* Round memory allocator to 1MB boundary */ - pciauto_upper_memspc &= ~(0x100000 - 1); - early_write_config_word(hose, - current_bus, - pci_devfn, - PCI_MEMORY_BASE, - pciauto_upper_memspc >> 16); - - /* Round I/O allocator to 4KB boundary */ - pciauto_upper_iospc &= ~(0x1000 - 1); - early_write_config_byte(hose, - current_bus, - pci_devfn, - PCI_IO_BASE, - (pciauto_upper_iospc & 0x0000f000) >> 8); - early_write_config_word(hose, - current_bus, - pci_devfn, - PCI_IO_BASE_UPPER16, - pciauto_upper_iospc >> 16); -} - -#define PCIAUTO_IDE_MODE_MASK 0x05 - -int __init -pciauto_bus_scan(struct pci_channel *hose, int current_bus) -{ - int sub_bus; - u32 pci_devfn, pci_class, cmdstat, found_multi=0; - unsigned short vid; - unsigned char header_type; - - sub_bus = current_bus; - - for (pci_devfn=0; pci_devfn<0xff; pci_devfn++) { - - if (PCI_FUNC(pci_devfn) && !found_multi) - continue; - - early_read_config_byte(hose, - current_bus, - pci_devfn, - PCI_HEADER_TYPE, - &header_type); - - if (!PCI_FUNC(pci_devfn)) - found_multi = header_type & 0x80; - - early_read_config_word(hose, - current_bus, - pci_devfn, - PCI_VENDOR_ID, - &vid); - - if (vid == 0xffff) continue; - - early_read_config_dword(hose, - current_bus, - pci_devfn, - PCI_CLASS_REVISION, &pci_class); - if ( (pci_class >> 16) == PCI_CLASS_BRIDGE_PCI ) { - DBG("PCI Autoconfig: Found P2P bridge, device %d\n", PCI_SLOT(pci_devfn)); - pciauto_prescan_setup_bridge(hose, - current_bus, - pci_devfn, - sub_bus); - sub_bus = pciauto_bus_scan(hose, sub_bus+1); - pciauto_postscan_setup_bridge(hose, - current_bus, - pci_devfn, - sub_bus); - - } else if ((pci_class >> 16) == PCI_CLASS_STORAGE_IDE) { - - unsigned char prg_iface; - - early_read_config_byte(hose, - current_bus, - pci_devfn, - PCI_CLASS_PROG, - &prg_iface); - if (!(prg_iface & PCIAUTO_IDE_MODE_MASK)) { - DBG("PCI Autoconfig: Skipping legacy mode IDE controller\n"); - continue; - } - } - - /* - * Found a peripheral, enable some standard - * settings - */ - early_read_config_dword(hose, - current_bus, - pci_devfn, - PCI_COMMAND, - &cmdstat); - early_write_config_dword(hose, - current_bus, - pci_devfn, - PCI_COMMAND, - cmdstat | - PCI_COMMAND_IO | - PCI_COMMAND_MEMORY | - PCI_COMMAND_MASTER); - early_write_config_byte(hose, - current_bus, - pci_devfn, - PCI_LATENCY_TIMER, - 0x80); - - /* Allocate PCI I/O and/or memory space */ - pciauto_setup_bars(hose, - current_bus, - pci_devfn); - } - return sub_bus; -} - -int __init -pciauto_assign_resources(int busno, struct pci_channel *hose) -{ - /* setup resource limits */ - pciauto_lower_iospc = hose->io_resource->start; - pciauto_upper_iospc = hose->io_resource->end + 1; - pciauto_lower_memspc = hose->mem_resource->start; - pciauto_upper_memspc = hose->mem_resource->end + 1; - - return pciauto_bus_scan(hose, busno); -} - - -/* - * These functions are used early on before PCI scanning is done - * and all of the pci_dev and pci_bus structures have been created. - */ -static struct pci_dev * -fake_pci_dev(struct pci_channel *hose, int busnr, int devfn) -{ - static struct pci_dev dev; - static struct pci_bus bus; - - dev.bus = &bus; - dev.sysdata = hose; - dev.devfn = devfn; - bus.number = busnr; - bus.ops = hose->pci_ops; - return &dev; -} - -#define EARLY_PCI_OP(rw, size, type) \ -int early_##rw##_config_##size(struct pci_channel *hose, int bus, \ - int devfn, int offset, type value) \ -{ \ - return pci_##rw##_config_##size(fake_pci_dev(hose, bus, devfn), \ - offset, value); \ -} - -EARLY_PCI_OP(read, byte, u8 *) -EARLY_PCI_OP(read, word, u16 *) -EARLY_PCI_OP(read, dword, u32 *) -EARLY_PCI_OP(write, byte, u8) -EARLY_PCI_OP(write, word, u16) -EARLY_PCI_OP(write, dword, u32) diff -Nru a/arch/mips/ddb5xxx/common/prom.c b/arch/mips/ddb5xxx/common/prom.c --- a/arch/mips/ddb5xxx/common/prom.c Tue Jul 1 18:44:37 2003 +++ b/arch/mips/ddb5xxx/common/prom.c Tue Jul 1 18:44:37 2003 @@ -22,8 +22,21 @@ #include #include #include +#include -char arcs_cmdline[COMMAND_LINE_SIZE]; +char arcs_cmdline[CL_SIZE]; + +const char *get_system_type(void) +{ + switch (mips_machtype) { + case MACH_NEC_DDB5074: return "NEC DDB Vrc-5074"; + case MACH_NEC_DDB5476: return "NEC DDB Vrc-5476"; + case MACH_NEC_DDB5477: return "NEC DDB Vrc-5477"; + case MACH_NEC_ROCKHOPPER: return "NEC Rockhopper"; + case MACH_NEC_ROCKHOPPERII: return "NEC RockhopperII"; + default: return "Unknown NEC board"; + } +} /* [jsun@junsun.net] PMON passes arguments in C main() style */ void __init prom_init(int argc, const char **arg) @@ -40,19 +53,91 @@ strcat(arcs_cmdline, " "); } + /* by default all these boards use dhcp/nfs root fs */ + strcat(arcs_cmdline, "ip=bootp"); + mips_machgroup = MACH_GROUP_NEC_DDB; #if defined(CONFIG_DDB5074) mips_machtype = MACH_NEC_DDB5074; + add_memory_region(0, DDB_SDRAM_SIZE, BOOT_MEM_RAM); #elif defined(CONFIG_DDB5476) mips_machtype = MACH_NEC_DDB5476; + add_memory_region(0, DDB_SDRAM_SIZE, BOOT_MEM_RAM); #elif defined(CONFIG_DDB5477) - mips_machtype = MACH_NEC_DDB5477; + ddb5477_runtime_detection(); + add_memory_region(0, board_ram_size, BOOT_MEM_RAM); #endif - - add_memory_region(0, DDB_SDRAM_SIZE, BOOT_MEM_RAM); } void __init prom_free_prom_memory(void) { } + +#if defined(CONFIG_DDB5477) + +#define DEFAULT_LCS1_BASE 0x19000000 +#define TESTVAL1 'K' +#define TESTVAL2 'S' + +int board_ram_size; +void ddb5477_runtime_detection(void) +{ + volatile char *test_offset; + char saved_test_byte; + + /* Determine if this is a DDB5477 board, or a BSB-VR0300 + base board. We can tell by checking for the location of + the NVRAM. It lives at the beginning of LCS1 on the DDB5477, + and the beginning of LCS1 on the BSB-VR0300 is flash memory. + The first 2K of the NVRAM are reserved, so don't we'll poke + around just after that. + */ + + /* We can only use the PCI bus to distinquish between + the Rockhopper and RockhopperII backplanes and this must + wait until ddb5477_board_init() in setup.c after the 5477 + is initialized. So, until then handle + both Rockhopper and RockhopperII backplanes as Rockhopper 1 + */ + + test_offset = (char *)KSEG1ADDR(DEFAULT_LCS1_BASE + 0x800); + saved_test_byte = *test_offset; + + *test_offset = TESTVAL1; + if (*test_offset != TESTVAL1) { + /* We couldn't set our test value, so it must not be NVRAM, + so it's a BSB_VR0300 */ + mips_machtype = MACH_NEC_ROCKHOPPER; + } else { + /* We may have gotten lucky, and the TESTVAL1 was already + stored at the test location, so we must check a second + test value */ + *test_offset = TESTVAL2; + if (*test_offset != TESTVAL2) { + /* OK, we couldn't set this value either, so it must + definately be a BSB_VR0300 */ + mips_machtype = MACH_NEC_ROCKHOPPER; + } else { + /* We could change the value twice, so it must be + NVRAM, so it's a DDB_VRC5477 */ + mips_machtype = MACH_NEC_DDB5477; + } + } + /* Restore the original byte */ + *test_offset = saved_test_byte; + + /* before we know a better way, we will trust PMON for getting + * RAM size + */ + board_ram_size = 1 << (36 - (ddb_in32(DDB_SDRAM0) & 0xf)); + + db_run(printk("DDB run-time detection : %s, %d MB RAM\n", + mips_machtype == MACH_NEC_DDB5477 ? + "DDB5477" : "Rockhopper", + board_ram_size >> 20)); + + /* we can't handle ram size > 128 MB */ + db_assert(board_ram_size <= (128 << 20)); +} +#endif diff -Nru a/arch/mips/ddb5xxx/common/rtc_ds1386.c b/arch/mips/ddb5xxx/common/rtc_ds1386.c --- a/arch/mips/ddb5xxx/common/rtc_ds1386.c Tue Jul 1 18:44:37 2003 +++ b/arch/mips/ddb5xxx/common/rtc_ds1386.c Tue Jul 1 18:44:37 2003 @@ -25,7 +25,8 @@ #include #include -#include +#include +#include #define EPOCH 2000 @@ -36,7 +37,7 @@ static unsigned long rtc_ds1386_get_time(void) -{ +{ u8 byte; u8 temp; unsigned int year, month, day, hour, minute, second; @@ -73,7 +74,7 @@ return mktime(year, month, day, hour, minute, second); } -static int +static int rtc_ds1386_set_time(unsigned long t) { struct rtc_time tm; @@ -89,6 +90,7 @@ /* convert */ to_tm(t, &tm); + /* check each field one by one */ year = BIN2BCD(tm.tm_year - EPOCH); if (year != READ_RTC(0xA)) { @@ -96,7 +98,7 @@ } temp = READ_RTC(0x9); - month = BIN2BCD(tm.tm_mon); + month = BIN2BCD(tm.tm_mon+1); /* tm_mon starts from 0 to 11 */ if (month != (temp & 0x1f)) { WRITE_RTC( 0x9, (month & 0x1f) | (temp & ~0x1f) ); @@ -131,7 +133,7 @@ if (second != READ_RTC(0x1)) { WRITE_RTC(0x1, second); } - + return 0; } @@ -139,10 +141,10 @@ rtc_ds1386_init(unsigned long base) { unsigned char byte; - + /* remember the base */ rtc_base = base; - MIPS_ASSERT((rtc_base & 0xe0000000) == KSEG1); + db_assert((rtc_base & 0xe0000000) == KSEG1); /* turn on RTC if it is not on */ byte = READ_RTC(0x9); diff -Nru a/arch/mips/ddb5xxx/ddb5074/Makefile b/arch/mips/ddb5xxx/ddb5074/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/ddb5xxx/ddb5074/Makefile Tue Jul 1 18:44:32 2003 @@ -0,0 +1,8 @@ +# +# Makefile for the NEC DDB Vrc-5074 specific kernel interface routines +# under Linux. +# + +obj-y += setup.o irq.o int-handler.o nile4_pic.o time.o + +EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips/ddb5xxx/ddb5074/int-handler.S b/arch/mips/ddb5xxx/ddb5074/int-handler.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/ddb5xxx/ddb5074/int-handler.S Tue Jul 1 18:44:36 2003 @@ -0,0 +1,120 @@ +/* + * arch/mips/ddb5074/int-handler.S -- NEC DDB Vrc-5074 interrupt handler + * + * Based on arch/mips/sgi/kernel/indyIRQ.S + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * Copyright (C) 2000 Geert Uytterhoeven + * Sony Software Development Center Europe (SDCE), Brussels + */ +#include +#include +#include +#include + +/* A lot of complication here is taken away because: + * + * 1) We handle one interrupt and return, sitting in a loop and moving across + * all the pending IRQ bits in the cause register is _NOT_ the answer, the + * common case is one pending IRQ so optimize in that direction. + * + * 2) We need not check against bits in the status register IRQ mask, that + * would make this routine slow as hell. + * + * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in + * between like BSD spl() brain-damage. + * + * Furthermore, the IRQs on the INDY look basically (barring software IRQs + * which we don't use at all) like: + * + * MIPS IRQ Source + * -------- ------ + * 0 Software (ignored) + * 1 Software (ignored) + * 2 Local IRQ level zero + * 3 Local IRQ level one + * 4 8254 Timer zero + * 5 8254 Timer one + * 6 Bus Error + * 7 R4k timer (what we use) + * + * We handle the IRQ according to _our_ priority which is: + * + * Highest ---- R4k Timer + * Local IRQ zero + * Local IRQ one + * Bus Error + * 8254 Timer zero + * Lowest ---- 8254 Timer one + * + * then we just return, if multiple IRQs are pending then we will just take + * another exception, big deal. + */ + + .text + .set noreorder + .set noat + .align 5 + NESTED(ddbIRQ, PT_SIZE, sp) + SAVE_ALL + CLI + .set at + mfc0 s0, CP0_CAUSE # get irq mask + +#if 1 + mfc0 t2,CP0_STATUS # get enabled interrupts + and s0,t2 # isolate allowed ones +#endif + /* First we check for r4k counter/timer IRQ. */ + andi a0, s0, CAUSEF_IP2 # delay slot, check local level zero + beq a0, zero, 1f + andi a0, s0, CAUSEF_IP3 # delay slot, check local level one + + /* Wheee, local level zero interrupt. */ + jal ddb_local0_irqdispatch + move a0, sp # delay slot + + j ret_from_irq + nop # delay slot + +1: + beq a0, zero, 1f + andi a0, s0, CAUSEF_IP6 # delay slot, check bus error + + /* Wheee, local level one interrupt. */ + move a0, sp + jal ddb_local1_irqdispatch + nop + + j ret_from_irq + nop + +1: + beq a0, zero, 1f + nop + + /* Wheee, an asynchronous bus error... */ + move a0, sp + jal ddb_buserror_irq + nop + + j ret_from_irq + nop + +1: + /* Here by mistake? This is possible, what can happen + * is that by the time we take the exception the IRQ + * pin goes low, so just leave if this is the case. + */ + andi a0, s0, (CAUSEF_IP4 | CAUSEF_IP5) + beq a0, zero, 1f + + /* Must be one of the 8254 timers... */ + move a0, sp + jal ddb_8254timer_irq + nop +1: + j ret_from_irq + nop + END(ddbIRQ) diff -Nru a/arch/mips/ddb5xxx/ddb5074/irq.c b/arch/mips/ddb5xxx/ddb5074/irq.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/ddb5xxx/ddb5074/irq.c Tue Jul 1 18:44:39 2003 @@ -0,0 +1,168 @@ +/* + * arch/mips/ddb5074/irq.c -- NEC DDB Vrc-5074 interrupt routines + * + * Copyright (C) 2000 Geert Uytterhoeven + * Sony Software Development Center Europe (SDCE), Brussels + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + +extern asmlinkage void ddbIRQ(void); + +static struct irqaction irq_cascade = { no_action, 0, 0, "cascade", NULL, NULL }; + +#define M1543_PNP_CONFIG 0x03f0 /* PnP Config Port */ +#define M1543_PNP_INDEX 0x03f0 /* PnP Index Port */ +#define M1543_PNP_DATA 0x03f1 /* PnP Data Port */ + +#define M1543_PNP_ALT_CONFIG 0x0370 /* Alternative PnP Config Port */ +#define M1543_PNP_ALT_INDEX 0x0370 /* Alternative PnP Index Port */ +#define M1543_PNP_ALT_DATA 0x0371 /* Alternative PnP Data Port */ + +#define M1543_INT1_MASTER_CTRL 0x0020 /* INT_1 (master) Control Register */ +#define M1543_INT1_MASTER_MASK 0x0021 /* INT_1 (master) Mask Register */ + +#define M1543_INT1_SLAVE_CTRL 0x00a0 /* INT_1 (slave) Control Register */ +#define M1543_INT1_SLAVE_MASK 0x00a1 /* INT_1 (slave) Mask Register */ + +#define M1543_INT1_MASTER_ELCR 0x04d0 /* INT_1 (master) Edge/Level Control */ +#define M1543_INT1_SLAVE_ELCR 0x04d1 /* INT_1 (slave) Edge/Level Control */ + + +static void m1543_irq_setup(void) +{ + /* + * The ALI M1543 has 13 interrupt inputs, IRQ1..IRQ13. Not all + * the possible IO sources in the M1543 are in use by us. We will + * use the following mapping: + * + * IRQ1 - keyboard (default set by M1543) + * IRQ3 - reserved for UART B (default set by M1543) (note that + * the schematics for the DDB Vrc-5074 board seem to + * indicate that IRQ3 is connected to the DS1386 + * watchdog timer interrupt output so we might have + * a conflict) + * IRQ4 - reserved for UART A (default set by M1543) + * IRQ5 - parallel (default set by M1543) + * IRQ8 - DS1386 time of day (RTC) interrupt + * IRQ12 - mouse + */ + + /* + * Assing mouse interrupt to IRQ12 + */ + + /* Enter configuration mode */ + outb(0x51, M1543_PNP_CONFIG); + outb(0x23, M1543_PNP_CONFIG); + + /* Select logical device 7 (Keyboard) */ + outb(0x07, M1543_PNP_INDEX); + outb(0x07, M1543_PNP_DATA); + + /* Select IRQ12 */ + outb(0x72, M1543_PNP_INDEX); + outb(0x0c, M1543_PNP_DATA); + + outb(0x30, M1543_PNP_INDEX); + printk("device 7, 0x30: %02x\n",inb(M1543_PNP_DATA)); + + outb(0x70, M1543_PNP_INDEX); + printk("device 7, 0x70: %02x\n",inb(M1543_PNP_DATA)); + + /* Leave configration mode */ + outb(0xbb, M1543_PNP_CONFIG); + + +} + +void ddb_local0_irqdispatch(struct pt_regs *regs) +{ + u32 mask; + int nile4_irq; + + mask = nile4_get_irq_stat(0); + + /* Handle the timer interrupt first */ +#if 0 + if (mask & (1 << NILE4_INT_GPT)) { + do_IRQ(nile4_to_irq(NILE4_INT_GPT), regs); + mask &= ~(1 << NILE4_INT_GPT); + } +#endif + for (nile4_irq = 0; mask; nile4_irq++, mask >>= 1) + if (mask & 1) { + if (nile4_irq == NILE4_INT_INTE) { + int i8259_irq; + + nile4_clear_irq(NILE4_INT_INTE); + i8259_irq = nile4_i8259_iack(); + do_IRQ(i8259_irq, regs); + } else + do_IRQ(nile4_to_irq(nile4_irq), regs); + + } +} + +void ddb_local1_irqdispatch(void) +{ + printk("ddb_local1_irqdispatch called\n"); +} + +void ddb_buserror_irq(void) +{ + printk("ddb_buserror_irq called\n"); +} + +void ddb_8254timer_irq(void) +{ + printk("ddb_8254timer_irq called\n"); +} + +void __init ddb_irq_setup(void) +{ +#ifdef CONFIG_KGDB + if (remote_debug) + set_debug_traps(); + breakpoint(); /* you may move this line to whereever you want :-) */ +#endif + + /* setup cascade interrupts */ + setup_irq(NILE4_IRQ_BASE + NILE4_INT_INTE, &irq_cascade); + setup_irq(CPU_IRQ_BASE + CPU_NILE4_CASCADE, &irq_cascade); + + set_except_vector(0, ddbIRQ); + + nile4_irq_setup(NILE4_IRQ_BASE); + m1543_irq_setup(); + init_i8259_irqs(); + + + printk("CPU_IRQ_BASE: %d\n",CPU_IRQ_BASE); + + mips_cpu_irq_init(CPU_IRQ_BASE); + + printk("enabling 8259 cascade\n"); + + ddb5074_led_hex(0); + + /* Enable the interrupt cascade */ + nile4_enable_irq(NILE4_IRQ_BASE+IRQ_I8259_CASCADE); + + +} diff -Nru a/arch/mips/ddb5xxx/ddb5074/nile4_pic.c b/arch/mips/ddb5xxx/ddb5074/nile4_pic.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/ddb5xxx/ddb5074/nile4_pic.c Tue Jul 1 18:44:34 2003 @@ -0,0 +1,288 @@ +/* + * arch/mips/ddb5476/nile4.c -- + * low-level PIC code for NEC Vrc-5476 (Nile 4) + * + * Copyright (C) 2000 Geert Uytterhoeven + * Sony Software Development Center Europe (SDCE), Brussels + * + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + */ +#include +#include +#include +#include + +#include + +#include + +static int irq_base; + +/* + * Interrupt Programming + */ +void nile4_map_irq(int nile4_irq, int cpu_irq) +{ + u32 offset, t; + + offset = DDB_INTCTRL; + if (nile4_irq >= 8) { + offset += 4; + nile4_irq -= 8; + } + t = ddb_in32(offset); + t &= ~(7 << (nile4_irq * 4)); + t |= cpu_irq << (nile4_irq * 4); + ddb_out32(offset, t); +} + +void nile4_map_irq_all(int cpu_irq) +{ + u32 all, t; + + all = cpu_irq; + all |= all << 4; + all |= all << 8; + all |= all << 16; + t = ddb_in32(DDB_INTCTRL); + t &= 0x88888888; + t |= all; + ddb_out32(DDB_INTCTRL, t); + t = ddb_in32(DDB_INTCTRL + 4); + t &= 0x88888888; + t |= all; + ddb_out32(DDB_INTCTRL + 4, t); +} + +void nile4_enable_irq(unsigned int nile4_irq) +{ + u32 offset, t; + + nile4_irq-=irq_base; + + ddb5074_led_hex(8); + + offset = DDB_INTCTRL; + if (nile4_irq >= 8) { + offset += 4; + nile4_irq -= 8; + } + ddb5074_led_hex(9); + t = ddb_in32(offset); + ddb5074_led_hex(0xa); + t |= 8 << (nile4_irq * 4); + ddb_out32(offset, t); + ddb5074_led_hex(0xb); +} + +void nile4_disable_irq(unsigned int nile4_irq) +{ + u32 offset, t; + + nile4_irq-=irq_base; + + offset = DDB_INTCTRL; + if (nile4_irq >= 8) { + offset += 4; + nile4_irq -= 8; + } + t = ddb_in32(offset); + t &= ~(8 << (nile4_irq * 4)); + ddb_out32(offset, t); +} + +void nile4_disable_irq_all(void) +{ + ddb_out32(DDB_INTCTRL, 0); + ddb_out32(DDB_INTCTRL + 4, 0); +} + +u16 nile4_get_irq_stat(int cpu_irq) +{ + return ddb_in16(DDB_INTSTAT0 + cpu_irq * 2); +} + +void nile4_enable_irq_output(int cpu_irq) +{ + u32 t; + + t = ddb_in32(DDB_INTSTAT1 + 4); + t |= 1 << (16 + cpu_irq); + ddb_out32(DDB_INTSTAT1, t); +} + +void nile4_disable_irq_output(int cpu_irq) +{ + u32 t; + + t = ddb_in32(DDB_INTSTAT1 + 4); + t &= ~(1 << (16 + cpu_irq)); + ddb_out32(DDB_INTSTAT1, t); +} + +void nile4_set_pci_irq_polarity(int pci_irq, int high) +{ + u32 t; + + t = ddb_in32(DDB_INTPPES); + if (high) + t &= ~(1 << (pci_irq * 2)); + else + t |= 1 << (pci_irq * 2); + ddb_out32(DDB_INTPPES, t); +} + +void nile4_set_pci_irq_level_or_edge(int pci_irq, int level) +{ + u32 t; + + t = ddb_in32(DDB_INTPPES); + if (level) + t |= 2 << (pci_irq * 2); + else + t &= ~(2 << (pci_irq * 2)); + ddb_out32(DDB_INTPPES, t); +} + +void nile4_clear_irq(int nile4_irq) +{ + nile4_irq-=irq_base; + ddb_out32(DDB_INTCLR, 1 << nile4_irq); +} + +void nile4_clear_irq_mask(u32 mask) +{ + ddb_out32(DDB_INTCLR, mask); +} + +u8 nile4_i8259_iack(void) +{ + u8 irq; + u32 reg; + + /* Set window 0 for interrupt acknowledge */ + reg = ddb_in32(DDB_PCIINIT0); + + ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IACK, 0, DDB_PCI_ACCESS_32); + irq = *(volatile u8 *) KSEG1ADDR(DDB_PCI_IACK_BASE); + /* restore window 0 for PCI I/O space */ + // ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IO, 0, DDB_PCI_ACCESS_32); + ddb_out32(DDB_PCIINIT0, reg); + + /* i8269.c set the base vector to be 0x0 */ + return irq ; +} + +static unsigned int nile4_irq_startup(unsigned int irq) { + + nile4_enable_irq(irq); + return 0; + +} + +static void nile4_ack_irq(unsigned int irq) { + + ddb5074_led_hex(4); + + nile4_clear_irq(irq); + ddb5074_led_hex(2); + nile4_disable_irq(irq); + + ddb5074_led_hex(0); +} + +static void nile4_irq_end(unsigned int irq) { + + ddb5074_led_hex(3); + if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { + ddb5074_led_hex(5); + nile4_enable_irq(irq); + ddb5074_led_hex(7); + } + + ddb5074_led_hex(1); +} + +#define nile4_irq_shutdown nile4_disable_irq + +static hw_irq_controller nile4_irq_controller = { + "nile4", + nile4_irq_startup, + nile4_irq_shutdown, + nile4_enable_irq, + nile4_disable_irq, + nile4_ack_irq, + nile4_irq_end, + NULL +}; + +void nile4_irq_setup(u32 base) { + + int i; + extern irq_desc_t irq_desc[]; + + irq_base=base; + + /* Map all interrupts to CPU int #0 */ + nile4_map_irq_all(0); + + /* PCI INTA#-E# must be level triggered */ + nile4_set_pci_irq_level_or_edge(0, 1); + nile4_set_pci_irq_level_or_edge(1, 1); + nile4_set_pci_irq_level_or_edge(2, 1); + nile4_set_pci_irq_level_or_edge(3, 1); + nile4_set_pci_irq_level_or_edge(4, 1); + + /* PCI INTA#-D# must be active low, INTE# must be active high */ + nile4_set_pci_irq_polarity(0, 0); + nile4_set_pci_irq_polarity(1, 0); + nile4_set_pci_irq_polarity(2, 0); + nile4_set_pci_irq_polarity(3, 0); + nile4_set_pci_irq_polarity(4, 1); + + + for (i = 0; i < 16; i++) { + nile4_clear_irq(i); + nile4_disable_irq(i); + } + + /* Enable CPU int #0 */ + nile4_enable_irq_output(0); + + for (i= base; i< base + NUM_NILE4_INTERRUPTS; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = NULL; + irq_desc[i].depth = 1; + irq_desc[i].handler = &nile4_irq_controller; + } + +} + +#if defined(CONFIG_RUNTIME_DEBUG) +void nile4_dump_irq_status(void) +{ + printk(KERN_DEBUG " + CPUSTAT = %p:%p\n", (void *) ddb_in32(DDB_CPUSTAT + 4), + (void *) ddb_in32(DDB_CPUSTAT)); + printk(KERN_DEBUG " + INTCTRL = %p:%p\n", (void *) ddb_in32(DDB_INTCTRL + 4), + (void *) ddb_in32(DDB_INTCTRL)); + printk(KERN_DEBUG + "INTSTAT0 = %p:%p\n", + (void *) ddb_in32(DDB_INTSTAT0 + 4), + (void *) ddb_in32(DDB_INTSTAT0)); + printk(KERN_DEBUG + "INTSTAT1 = %p:%p\n", + (void *) ddb_in32(DDB_INTSTAT1 + 4), + (void *) ddb_in32(DDB_INTSTAT1)); + printk(KERN_DEBUG + "INTCLR = %p:%p\n", (void *) ddb_in32(DDB_INTCLR + 4), + (void *) ddb_in32(DDB_INTCLR)); + printk(KERN_DEBUG + "INTPPES = %p:%p\n", (void *) ddb_in32(DDB_INTPPES + 4), + (void *) ddb_in32(DDB_INTPPES)); +} + +#endif diff -Nru a/arch/mips/ddb5xxx/ddb5074/setup.c b/arch/mips/ddb5xxx/ddb5074/setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/ddb5xxx/ddb5074/setup.c Tue Jul 1 18:44:36 2003 @@ -0,0 +1,265 @@ +/* + * arch/mips/ddb5074/setup.c -- NEC DDB Vrc-5074 setup routines + * + * Copyright (C) 2000 Geert Uytterhoeven + * Sony Software Development Center Europe (SDCE), Brussels + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef CONFIG_KGDB +extern void rs_kgdb_hook(int); +extern void breakpoint(void); +#endif + +#if defined(CONFIG_SERIAL_CONSOLE) +extern void console_setup(char *); +#endif + +extern struct ide_ops std_ide_ops; +extern struct kbd_ops std_kbd_ops; +extern struct rtc_ops ddb_rtc_ops; + +static void (*back_to_prom) (void) = (void (*)(void)) 0xbfc00000; + +static void ddb_machine_restart(char *command) +{ + u32 t; + + /* PCI cold reset */ + t = nile4_in32(NILE4_PCICTRL + 4); + t |= 0x40000000; + nile4_out32(NILE4_PCICTRL + 4, t); + /* CPU cold reset */ + t = nile4_in32(NILE4_CPUSTAT); + t |= 1; + nile4_out32(NILE4_CPUSTAT, t); + /* Call the PROM */ + back_to_prom(); +} + +static void ddb_machine_halt(void) +{ + printk("DDB Vrc-5074 halted.\n"); + do { + } while (1); +} + +static void ddb_machine_power_off(void) +{ + printk("DDB Vrc-5074 halted. Please turn off the power.\n"); + do { + } while (1); +} + +extern void ddb_irq_setup(void); +extern void rtc_ds1386_init(unsigned long base); + +extern void (*board_timer_setup) (struct irqaction * irq); + +static void __init ddb_timer_init(struct irqaction *irq) +{ + /* set the clock to 1 Hz */ + nile4_out32(NILE4_T2CTRL, 1000000); + /* enable the General-Purpose Timer */ + nile4_out32(NILE4_T2CTRL + 4, 0x00000001); + /* reset timer */ + nile4_out32(NILE4_T2CNTR, 0); + /* enable interrupt */ + setup_irq(nile4_to_irq(NILE4_INT_GPT), irq); + nile4_enable_irq(nile4_to_irq(NILE4_INT_GPT)); + change_c0_status(ST0_IM, + IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4); + +} + +static void __init ddb_time_init(void) +{ + /* we have ds1396 RTC chip */ + rtc_ds1386_init(KSEG1ADDR(DDB_PCI_MEM_BASE)); +} + + + +void __init ddb_setup(void) +{ + extern int panic_timeout; + + irq_setup = ddb_irq_setup; + set_io_port_base(NILE4_PCI_IO_BASE); + isa_slot_offset = NILE4_PCI_MEM_BASE; + board_timer_setup = ddb_timer_init; + board_time_init = ddb_time_init; + + + _machine_restart = ddb_machine_restart; + _machine_halt = ddb_machine_halt; + _machine_power_off = ddb_machine_power_off; + +#ifdef CONFIG_BLK_DEV_IDE + ide_ops = &std_ide_ops; +#endif + + rtc_ops = &ddb_rtc_ops; + + ddb_out32(DDB_BAR0, 0); + + ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IO, 0, 0x10); + ddb_set_pmr(DDB_PCIINIT1, DDB_PCICMD_MEM, DDB_PCI_MEM_BASE , 0x10); + +#ifdef CONFIG_FB + conswitchp = &dummy_con; +#endif + + /* Reboot on panic */ + panic_timeout = 180; +} + + +#define USE_NILE4_SERIAL 0 + +#if USE_NILE4_SERIAL +#define ns16550_in(reg) nile4_in8((reg)*8) +#define ns16550_out(reg, val) nile4_out8((reg)*8, (val)) +#else +#define NS16550_BASE (NILE4_PCI_IO_BASE+0x03f8) +static inline u8 ns16550_in(u32 reg) +{ + return *(volatile u8 *) (NS16550_BASE + reg); +} + +static inline void ns16550_out(u32 reg, u8 val) +{ + *(volatile u8 *) (NS16550_BASE + reg) = val; +} +#endif + +#define NS16550_RBR 0 +#define NS16550_THR 0 +#define NS16550_DLL 0 +#define NS16550_IER 1 +#define NS16550_DLM 1 +#define NS16550_FCR 2 +#define NS16550_IIR 2 +#define NS16550_LCR 3 +#define NS16550_MCR 4 +#define NS16550_LSR 5 +#define NS16550_MSR 6 +#define NS16550_SCR 7 + +#define NS16550_LSR_DR 0x01 /* Data ready */ +#define NS16550_LSR_OE 0x02 /* Overrun */ +#define NS16550_LSR_PE 0x04 /* Parity error */ +#define NS16550_LSR_FE 0x08 /* Framing error */ +#define NS16550_LSR_BI 0x10 /* Break */ +#define NS16550_LSR_THRE 0x20 /* Xmit holding register empty */ +#define NS16550_LSR_TEMT 0x40 /* Xmitter empty */ +#define NS16550_LSR_ERR 0x80 /* Error */ + + +void _serinit(void) +{ +#if USE_NILE4_SERIAL + ns16550_out(NS16550_LCR, 0x80); + ns16550_out(NS16550_DLM, 0x00); + ns16550_out(NS16550_DLL, 0x36); /* 9600 baud */ + ns16550_out(NS16550_LCR, 0x00); + ns16550_out(NS16550_LCR, 0x03); + ns16550_out(NS16550_FCR, 0x47); +#else + /* done by PMON */ +#endif +} + +void _putc(char c) +{ + while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_THRE)); + ns16550_out(NS16550_THR, c); + if (c == '\n') { + while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_THRE)); + ns16550_out(NS16550_THR, '\r'); + } +} + +void _puts(const char *s) +{ + char c; + while ((c = *s++)) + _putc(c); +} + +char _getc(void) +{ + while (!(ns16550_in(NS16550_LSR) & NS16550_LSR_DR)); + return ns16550_in(NS16550_RBR); +} + +int _testc(void) +{ + return (ns16550_in(NS16550_LSR) & NS16550_LSR_DR) != 0; +} + + +/* + * Hexadecimal 7-segment LED + */ +void ddb5074_led_hex(int hex) +{ + outb(hex, 0x80); +} + + +/* + * LEDs D2 and D3, connected to the GPIO pins of the PMU in the ALi M1543 + */ +struct pci_dev *pci_pmu = NULL; + +void ddb5074_led_d2(int on) +{ + u8 t; + + if (pci_pmu) { + pci_read_config_byte(pci_pmu, 0x7e, &t); + if (on) + t &= 0x7f; + else + t |= 0x80; + pci_write_config_byte(pci_pmu, 0x7e, t); + } +} + +void ddb5074_led_d3(int on) +{ + u8 t; + + if (pci_pmu) { + pci_read_config_byte(pci_pmu, 0x7e, &t); + if (on) + t &= 0xbf; + else + t |= 0x40; + pci_write_config_byte(pci_pmu, 0x7e, t); + } +} diff -Nru a/arch/mips/ddb5xxx/ddb5074/time.c b/arch/mips/ddb5xxx/ddb5074/time.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/ddb5xxx/ddb5074/time.c Tue Jul 1 18:44:35 2003 @@ -0,0 +1,33 @@ +/* + * arch/mips/ddb5074/time.c -- Timer routines + * + * Copyright (C) 2000 Geert Uytterhoeven + * Sony Software Development Center Europe (SDCE), Brussels + * + */ +#include +#include +#include +#include + + +static unsigned char ddb_rtc_read_data(unsigned long addr) +{ + return *(volatile unsigned char *)(KSEG1ADDR(DDB_PCI_MEM_BASE)+addr); +} + +static void ddb_rtc_write_data(unsigned char data, unsigned long addr) +{ + *(volatile unsigned char *)(KSEG1ADDR(DDB_PCI_MEM_BASE)+addr)=data; +} + +static int ddb_rtc_bcd_mode(void) +{ + return 1; +} + +struct rtc_ops ddb_rtc_ops = { + ddb_rtc_read_data, + ddb_rtc_write_data, + ddb_rtc_bcd_mode +}; diff -Nru a/arch/mips/ddb5xxx/ddb5476/Makefile b/arch/mips/ddb5xxx/ddb5476/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/ddb5xxx/ddb5476/Makefile Tue Jul 1 18:44:36 2003 @@ -0,0 +1,9 @@ +# +# Makefile for the NEC DDB Vrc-5476 specific kernel interface routines +# under Linux. +# + +obj-y += setup.o irq.o int-handler.o nile4_pic.o vrc5476_irq.o +obj-$(CONFIG_KGDB) += dbg_io.o + +EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips/ddb5xxx/ddb5476/dbg_io.c b/arch/mips/ddb5xxx/ddb5476/dbg_io.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/ddb5xxx/ddb5476/dbg_io.c Tue Jul 1 18:44:35 2003 @@ -0,0 +1,136 @@ +/* + * kgdb io functions for DDB5476. We use the second serial port. + * + * Copyright (C) 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +/* ======================= CONFIG ======================== */ + +/* [jsun] we use the second serial port for kdb */ +#define BASE 0xa60002f8 +#define MAX_BAUD 115200 + +/* distance in bytes between two serial registers */ +#define REG_OFFSET 1 + +/* + * 0 - kgdb does serial init + * 1 - kgdb skip serial init + */ +static int remoteDebugInitialized = 0; + +/* + * the default baud rate *if* kgdb does serial init + */ +#define BAUD_DEFAULT UART16550_BAUD_38400 + +/* ======================= END OF CONFIG ======================== */ + +typedef unsigned char uint8; +typedef unsigned int uint32; + +#define UART16550_BAUD_2400 2400 +#define UART16550_BAUD_4800 4800 +#define UART16550_BAUD_9600 9600 +#define UART16550_BAUD_19200 19200 +#define UART16550_BAUD_38400 38400 +#define UART16550_BAUD_57600 57600 +#define UART16550_BAUD_115200 115200 + +#define UART16550_PARITY_NONE 0 +#define UART16550_PARITY_ODD 0x08 +#define UART16550_PARITY_EVEN 0x18 +#define UART16550_PARITY_MARK 0x28 +#define UART16550_PARITY_SPACE 0x38 + +#define UART16550_DATA_5BIT 0x0 +#define UART16550_DATA_6BIT 0x1 +#define UART16550_DATA_7BIT 0x2 +#define UART16550_DATA_8BIT 0x3 + +#define UART16550_STOP_1BIT 0x0 +#define UART16550_STOP_2BIT 0x4 + +/* register offset */ +#define OFS_RCV_BUFFER 0 +#define OFS_TRANS_HOLD 0 +#define OFS_SEND_BUFFER 0 +#define OFS_INTR_ENABLE (1*REG_OFFSET) +#define OFS_INTR_ID (2*REG_OFFSET) +#define OFS_DATA_FORMAT (3*REG_OFFSET) +#define OFS_LINE_CONTROL (3*REG_OFFSET) +#define OFS_MODEM_CONTROL (4*REG_OFFSET) +#define OFS_RS232_OUTPUT (4*REG_OFFSET) +#define OFS_LINE_STATUS (5*REG_OFFSET) +#define OFS_MODEM_STATUS (6*REG_OFFSET) +#define OFS_RS232_INPUT (6*REG_OFFSET) +#define OFS_SCRATCH_PAD (7*REG_OFFSET) + +#define OFS_DIVISOR_LSB (0*REG_OFFSET) +#define OFS_DIVISOR_MSB (1*REG_OFFSET) + + +/* memory-mapped read/write of the port */ +#define UART16550_READ(y) (*((volatile uint8*)(BASE + y))) +#define UART16550_WRITE(y, z) ((*((volatile uint8*)(BASE + y))) = z) + +void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop) +{ + /* disable interrupts */ + UART16550_WRITE(OFS_INTR_ENABLE, 0); + + /* set up buad rate */ + { + uint32 divisor; + + /* set DIAB bit */ + UART16550_WRITE(OFS_LINE_CONTROL, 0x80); + + /* set divisor */ + divisor = MAX_BAUD / baud; + UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff); + UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8); + + /* clear DIAB bit */ + UART16550_WRITE(OFS_LINE_CONTROL, 0x0); + } + + /* set data format */ + UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop); +} + + +uint8 getDebugChar(void) +{ + if (!remoteDebugInitialized) { + remoteDebugInitialized = 1; + debugInit(BAUD_DEFAULT, + UART16550_DATA_8BIT, + UART16550_PARITY_NONE, UART16550_STOP_1BIT); + } + + while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0); + return UART16550_READ(OFS_RCV_BUFFER); +} + + +int putDebugChar(uint8 byte) +{ + if (!remoteDebugInitialized) { + remoteDebugInitialized = 1; + debugInit(BAUD_DEFAULT, + UART16550_DATA_8BIT, + UART16550_PARITY_NONE, UART16550_STOP_1BIT); + } + + while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0); + UART16550_WRITE(OFS_SEND_BUFFER, byte); + return 1; +} diff -Nru a/arch/mips/ddb5xxx/ddb5476/int-handler.S b/arch/mips/ddb5xxx/ddb5476/int-handler.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/ddb5xxx/ddb5476/int-handler.S Tue Jul 1 18:44:34 2003 @@ -0,0 +1,112 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * First-level interrupt dispatcher for ddb5476 + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include +#include +#include + +#include + +/* + * first level interrupt dispatcher for ocelot board - + * We check for the timer first, then check PCI ints A and D. + * Then check for serial IRQ and fall through. + */ + .align 5 + NESTED(ddb5476_handle_int, PT_SIZE, sp) + SAVE_ALL + CLI + .set at + .set noreorder + mfc0 t0, CP0_CAUSE + mfc0 t2, CP0_STATUS + + and t0, t2 + + andi t1, t0, STATUSF_IP7 /* cpu timer */ + bnez t1, ll_cpu_ip7 + andi t1, t0, STATUSF_IP2 /* vrc5476 & i8259 */ + bnez t1, ll_cpu_ip2 + andi t1, t0, STATUSF_IP3 + bnez t1, ll_cpu_ip3 + andi t1, t0, STATUSF_IP4 + bnez t1, ll_cpu_ip4 + andi t1, t0, STATUSF_IP5 + bnez t1, ll_cpu_ip5 + andi t1, t0, STATUSF_IP6 + bnez t1, ll_cpu_ip6 + andi t1, t0, STATUSF_IP0 /* software int 0 */ + bnez t1, ll_cpu_ip0 + andi t1, t0, STATUSF_IP1 /* software int 1 */ + bnez t1, ll_cpu_ip1 + nop + + .set reorder + + /* wrong alarm or masked ... */ + // j spurious_interrupt + move a0, sp + jal vrc5476_irq_dispatch + j ret_from_irq + nop + + .align 5 + +ll_cpu_ip0: + li a0, CPU_IRQ_BASE + 0 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_cpu_ip1: + li a0, CPU_IRQ_BASE + 1 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_cpu_ip2: /* jump to second-level dispatching */ + move a0, sp + jal vrc5476_irq_dispatch + j ret_from_irq + +ll_cpu_ip3: + li a0, CPU_IRQ_BASE + 3 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_cpu_ip4: + li a0, CPU_IRQ_BASE + 4 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_cpu_ip5: + li a0, CPU_IRQ_BASE + 5 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_cpu_ip6: + li a0, CPU_IRQ_BASE + 6 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_cpu_ip7: + li a0, CPU_IRQ_BASE + 7 + move a1, sp + jal do_IRQ + j ret_from_irq + + END(ddb5476_handle_int) diff -Nru a/arch/mips/ddb5xxx/ddb5476/irq.c b/arch/mips/ddb5xxx/ddb5476/irq.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/ddb5xxx/ddb5476/irq.c Tue Jul 1 18:44:37 2003 @@ -0,0 +1,143 @@ +/* + * arch/mips/ddb5476/irq.c -- NEC DDB Vrc-5476 interrupt routines + * + * Copyright (C) 2000 Geert Uytterhoeven + * Sony Software Development Center Europe (SDCE), Brussels + * + * Re-write the whole thing to use new irq.c file. + * Copyright (C) 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + */ +#include +#include +#include +#include + +#include +#include +#include + +#include + +#define M1543_PNP_CONFIG 0x03f0 /* PnP Config Port */ +#define M1543_PNP_INDEX 0x03f0 /* PnP Index Port */ +#define M1543_PNP_DATA 0x03f1 /* PnP Data Port */ + +#define M1543_PNP_ALT_CONFIG 0x0370 /* Alternative PnP Config Port */ +#define M1543_PNP_ALT_INDEX 0x0370 /* Alternative PnP Index Port */ +#define M1543_PNP_ALT_DATA 0x0371 /* Alternative PnP Data Port */ + +#define M1543_INT1_MASTER_CTRL 0x0020 /* INT_1 (master) Control Register */ +#define M1543_INT1_MASTER_MASK 0x0021 /* INT_1 (master) Mask Register */ + +#define M1543_INT1_SLAVE_CTRL 0x00a0 /* INT_1 (slave) Control Register */ +#define M1543_INT1_SLAVE_MASK 0x00a1 /* INT_1 (slave) Mask Register */ + +#define M1543_INT1_MASTER_ELCR 0x04d0 /* INT_1 (master) Edge/Level Control */ +#define M1543_INT1_SLAVE_ELCR 0x04d1 /* INT_1 (slave) Edge/Level Control */ + +static void m1543_irq_setup(void) +{ + /* + * The ALI M1543 has 13 interrupt inputs, IRQ1..IRQ13. Not all + * the possible IO sources in the M1543 are in use by us. We will + * use the following mapping: + * + * IRQ1 - keyboard (default set by M1543) + * IRQ3 - reserved for UART B (default set by M1543) (note that + * the schematics for the DDB Vrc-5476 board seem to + * indicate that IRQ3 is connected to the DS1386 + * watchdog timer interrupt output so we might have + * a conflict) + * IRQ4 - reserved for UART A (default set by M1543) + * IRQ5 - parallel (default set by M1543) + * IRQ8 - DS1386 time of day (RTC) interrupt + * IRQ9 - USB (hardwired in ddb_setup) + * IRQ10 - PMU (hardwired in ddb_setup) + * IRQ12 - mouse + * IRQ14,15 - IDE controller (need to be confirmed, jsun) + */ + + /* + * Assing mouse interrupt to IRQ12 + */ + + /* Enter configuration mode */ + outb(0x51, M1543_PNP_CONFIG); + outb(0x23, M1543_PNP_CONFIG); + + /* Select logical device 7 (Keyboard) */ + outb(0x07, M1543_PNP_INDEX); + outb(0x07, M1543_PNP_DATA); + + /* Select IRQ12 */ + outb(0x72, M1543_PNP_INDEX); + outb(0x0c, M1543_PNP_DATA); + + /* Leave configration mode */ + outb(0xbb, M1543_PNP_CONFIG); +} + +static void nile4_irq_setup(void) +{ + int i; + + /* Map all interrupts to CPU int #0 (IP2) */ + nile4_map_irq_all(0); + + /* PCI INTA#-E# must be level triggered */ + nile4_set_pci_irq_level_or_edge(0, 1); + nile4_set_pci_irq_level_or_edge(1, 1); + nile4_set_pci_irq_level_or_edge(2, 1); + nile4_set_pci_irq_level_or_edge(3, 1); + + /* PCI INTA#, B#, D# must be active low, INTC# must be active high */ + nile4_set_pci_irq_polarity(0, 0); + nile4_set_pci_irq_polarity(1, 0); + nile4_set_pci_irq_polarity(2, 1); + nile4_set_pci_irq_polarity(3, 0); + + for (i = 0; i < 16; i++) + nile4_clear_irq(i); + + /* Enable CPU int #0 */ + nile4_enable_irq_output(0); + + /* memory resource acquire in ddb_setup */ +} + +static struct irqaction irq_cascade = { no_action, 0, 0, "cascade", NULL, NULL }; +static struct irqaction irq_error = { no_action, 0, 0, "error", NULL, NULL }; + +extern asmlinkage void ddb5476_handle_int(void); +extern int setup_irq(unsigned int irq, struct irqaction *irqaction); +extern void mips_cpu_irq_init(u32 irq_base); +extern void vrc5476_irq_init(u32 irq_base); + +void __init ddb5476_irq_setup(void) +{ + /* hardware initialization */ + nile4_irq_setup(); + m1543_irq_setup(); + + /* controller setup */ + init_i8259_irqs(); + vrc5476_irq_init(VRC5476_IRQ_BASE); + mips_cpu_irq_init(CPU_IRQ_BASE); + + /* setup cascade interrupts */ + setup_irq(VRC5476_IRQ_BASE + VRC5476_I8259_CASCADE, &irq_cascade); + setup_irq(CPU_IRQ_BASE + CPU_VRC5476_CASCADE, &irq_cascade); + + /* setup error interrupts for debugging */ + setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_CPCE, &irq_error); + setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_CNTD, &irq_error); + setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_MCE, &irq_error); + setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_LBRT, &irq_error); + setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_PCIS, &irq_error); + setup_irq(VRC5476_IRQ_BASE + VRC5476_IRQ_PCI, &irq_error); + + /* setup the grandpa intr vector */ + set_except_vector(0, ddb5476_handle_int); +} diff -Nru a/arch/mips/ddb5xxx/ddb5476/nile4_pic.c b/arch/mips/ddb5xxx/ddb5476/nile4_pic.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/ddb5xxx/ddb5476/nile4_pic.c Tue Jul 1 18:44:36 2003 @@ -0,0 +1,190 @@ +/* + * arch/mips/ddb5476/nile4.c -- + * low-level PIC code for NEC Vrc-5476 (Nile 4) + * + * Copyright (C) 2000 Geert Uytterhoeven + * Sony Software Development Center Europe (SDCE), Brussels + * + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + */ +#include +#include +#include + +#include + +#include + + +/* + * Interrupt Programming + */ +void nile4_map_irq(int nile4_irq, int cpu_irq) +{ + u32 offset, t; + + offset = DDB_INTCTRL; + if (nile4_irq >= 8) { + offset += 4; + nile4_irq -= 8; + } + t = ddb_in32(offset); + t &= ~(7 << (nile4_irq * 4)); + t |= cpu_irq << (nile4_irq * 4); + ddb_out32(offset, t); +} + +void nile4_map_irq_all(int cpu_irq) +{ + u32 all, t; + + all = cpu_irq; + all |= all << 4; + all |= all << 8; + all |= all << 16; + t = ddb_in32(DDB_INTCTRL); + t &= 0x88888888; + t |= all; + ddb_out32(DDB_INTCTRL, t); + t = ddb_in32(DDB_INTCTRL + 4); + t &= 0x88888888; + t |= all; + ddb_out32(DDB_INTCTRL + 4, t); +} + +void nile4_enable_irq(int nile4_irq) +{ + u32 offset, t; + + offset = DDB_INTCTRL; + if (nile4_irq >= 8) { + offset += 4; + nile4_irq -= 8; + } + t = ddb_in32(offset); + t |= 8 << (nile4_irq * 4); + ddb_out32(offset, t); +} + +void nile4_disable_irq(int nile4_irq) +{ + u32 offset, t; + + offset = DDB_INTCTRL; + if (nile4_irq >= 8) { + offset += 4; + nile4_irq -= 8; + } + t = ddb_in32(offset); + t &= ~(8 << (nile4_irq * 4)); + ddb_out32(offset, t); +} + +void nile4_disable_irq_all(void) +{ + ddb_out32(DDB_INTCTRL, 0); + ddb_out32(DDB_INTCTRL + 4, 0); +} + +u16 nile4_get_irq_stat(int cpu_irq) +{ + return ddb_in16(DDB_INTSTAT0 + cpu_irq * 2); +} + +void nile4_enable_irq_output(int cpu_irq) +{ + u32 t; + + t = ddb_in32(DDB_INTSTAT1 + 4); + t |= 1 << (16 + cpu_irq); + ddb_out32(DDB_INTSTAT1, t); +} + +void nile4_disable_irq_output(int cpu_irq) +{ + u32 t; + + t = ddb_in32(DDB_INTSTAT1 + 4); + t &= ~(1 << (16 + cpu_irq)); + ddb_out32(DDB_INTSTAT1, t); +} + +void nile4_set_pci_irq_polarity(int pci_irq, int high) +{ + u32 t; + + t = ddb_in32(DDB_INTPPES); + if (high) + t &= ~(1 << (pci_irq * 2)); + else + t |= 1 << (pci_irq * 2); + ddb_out32(DDB_INTPPES, t); +} + +void nile4_set_pci_irq_level_or_edge(int pci_irq, int level) +{ + u32 t; + + t = ddb_in32(DDB_INTPPES); + if (level) + t |= 2 << (pci_irq * 2); + else + t &= ~(2 << (pci_irq * 2)); + ddb_out32(DDB_INTPPES, t); +} + +void nile4_clear_irq(int nile4_irq) +{ + ddb_out32(DDB_INTCLR, 1 << nile4_irq); +} + +void nile4_clear_irq_mask(u32 mask) +{ + ddb_out32(DDB_INTCLR, mask); +} + +u8 nile4_i8259_iack(void) +{ + u8 irq; + u32 reg; + + /* Set window 0 for interrupt acknowledge */ + reg = ddb_in32(DDB_PCIINIT0); + + ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IACK, 0, DDB_PCI_ACCESS_32); + irq = *(volatile u8 *) KSEG1ADDR(DDB_PCI_IACK_BASE); + /* restore window 0 for PCI I/O space */ + // ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IO, 0, DDB_PCI_ACCESS_32); + ddb_out32(DDB_PCIINIT0, reg); + + /* i8269.c set the base vector to be 0x0 */ + return irq + I8259_IRQ_BASE; +} + +#if defined(CONFIG_RUNTIME_DEBUG) +void nile4_dump_irq_status(void) +{ + printk(KERN_DEBUG " + CPUSTAT = %p:%p\n", (void *) ddb_in32(DDB_CPUSTAT + 4), + (void *) ddb_in32(DDB_CPUSTAT)); + printk(KERN_DEBUG " + INTCTRL = %p:%p\n", (void *) ddb_in32(DDB_INTCTRL + 4), + (void *) ddb_in32(DDB_INTCTRL)); + printk(KERN_DEBUG + "INTSTAT0 = %p:%p\n", + (void *) ddb_in32(DDB_INTSTAT0 + 4), + (void *) ddb_in32(DDB_INTSTAT0)); + printk(KERN_DEBUG + "INTSTAT1 = %p:%p\n", + (void *) ddb_in32(DDB_INTSTAT1 + 4), + (void *) ddb_in32(DDB_INTSTAT1)); + printk(KERN_DEBUG + "INTCLR = %p:%p\n", (void *) ddb_in32(DDB_INTCLR + 4), + (void *) ddb_in32(DDB_INTCLR)); + printk(KERN_DEBUG + "INTPPES = %p:%p\n", (void *) ddb_in32(DDB_INTPPES + 4), + (void *) ddb_in32(DDB_INTPPES)); +} +#endif diff -Nru a/arch/mips/ddb5xxx/ddb5476/setup.c b/arch/mips/ddb5xxx/ddb5476/setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/ddb5xxx/ddb5476/setup.c Tue Jul 1 18:44:36 2003 @@ -0,0 +1,326 @@ +/* + * arch/mips/ddb5476/setup.c -- NEC DDB Vrc-5476 setup routines + * + * Copyright (C) 2000 Geert Uytterhoeven + * Sony Software Development Center Europe (SDCE), Brussels + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +// #define USE_CPU_COUNTER_TIMER /* whether we use cpu counter */ + +#ifdef USE_CPU_COUNTER_TIMER + +#define CPU_COUNTER_FREQUENCY 83000000 +#else +/* otherwise we use general purpose timer */ +#define TIMER_FREQUENCY 83000000 +#define TIMER_BASE DDB_T2CTRL +#define TIMER_IRQ (VRC5476_IRQ_BASE + VRC5476_IRQ_GPT) +#endif + +#ifdef CONFIG_KGDB +extern void breakpoint(void); +#endif + +extern struct ide_ops std_ide_ops; +extern struct kbd_ops std_kbd_ops; + +static void (*back_to_prom) (void) = (void (*)(void)) 0xbfc00000; + +static void ddb_machine_restart(char *command) +{ + u32 t; + + /* PCI cold reset */ + t = ddb_in32(DDB_PCICTRL + 4); + t |= 0x40000000; + ddb_out32(DDB_PCICTRL + 4, t); + /* CPU cold reset */ + t = ddb_in32(DDB_CPUSTAT); + t |= 1; + ddb_out32(DDB_CPUSTAT, t); + /* Call the PROM */ + back_to_prom(); +} + +static void ddb_machine_halt(void) +{ + printk(KERN_NOTICE "DDB Vrc-5476 halted.\n"); + while (1); +} + +static void ddb_machine_power_off(void) +{ + printk(KERN_NOTICE "DDB Vrc-5476 halted. Please turn off the power.\n"); + while (1); +} + +extern void ddb_irq_setup(void); +extern void rtc_ds1386_init(unsigned long base); + +static void __init ddb_time_init(void) +{ +#if defined(USE_CPU_COUNTER_TIMER) + mips_counter_frequency = CPU_COUNTER_FREQUENCY; +#endif + + /* we have ds1396 RTC chip */ + rtc_ds1386_init(KSEG1ADDR(DDB_PCI_MEM_BASE)); +} + + +extern int setup_irq(unsigned int irq, struct irqaction *irqaction); +static void __init ddb_timer_setup(struct irqaction *irq) +{ +#if defined(USE_CPU_COUNTER_TIMER) + + unsigned int count; + + /* we are using the cpu counter for timer interrupts */ + setup_irq(CPU_IRQ_BASE + 7, irq); + + /* to generate the first timer interrupt */ + count = read_c0_count(); + write_c0_compare(count + 1000); + +#else + + ddb_out32(TIMER_BASE, TIMER_FREQUENCY/HZ); + ddb_out32(TIMER_BASE+4, 0x1); /* enable timer */ + setup_irq(TIMER_IRQ, irq); +#endif +} + +static struct { + struct resource dma1; + struct resource pic1; + struct resource timer; + struct resource rtc; + struct resource dma_page_reg; + struct resource pic2; + struct resource dma2; +} ddb5476_ioport = { + { + "dma1", 0x00, 0x1f, IORESOURCE_BUSY}, { + "pic1", 0x20, 0x3f, IORESOURCE_BUSY}, { + "timer", 0x40, 0x5f, IORESOURCE_BUSY}, { + "rtc", 0x70, 0x7f, IORESOURCE_BUSY}, { + "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY}, { + "pic2", 0xa0, 0xbf, IORESOURCE_BUSY}, { + "dma2", 0xc0, 0xdf, IORESOURCE_BUSY} +}; + +static struct { + struct resource nile4; +} ddb5476_iomem = { + { "Nile 4", DDB_BASE, DDB_BASE + DDB_SIZE - 1, IORESOURCE_BUSY} +}; + + +static void ddb5476_board_init(void); +extern void ddb5476_irq_setup(void); +extern void (*irq_setup)(void); + +void __init +ddb_setup(void) +{ + extern int panic_timeout; + + irq_setup = ddb5476_irq_setup; + set_io_port_base(KSEG1ADDR(DDB_PCI_IO_BASE)); + + board_time_init = ddb_time_init; + board_timer_setup = ddb_timer_setup; + + _machine_restart = ddb_machine_restart; + _machine_halt = ddb_machine_halt; + _machine_power_off = ddb_machine_power_off; + + /* request io port/mem resources */ + if (request_resource(&ioport_resource, &ddb5476_ioport.dma1) || + request_resource(&ioport_resource, &ddb5476_ioport.pic1) || + request_resource(&ioport_resource, &ddb5476_ioport.timer) || + request_resource(&ioport_resource, &ddb5476_ioport.rtc) || + request_resource(&ioport_resource, + &ddb5476_ioport.dma_page_reg) + || request_resource(&ioport_resource, &ddb5476_ioport.pic2) + || request_resource(&ioport_resource, &ddb5476_ioport.dma2) + || request_resource(&iomem_resource, &ddb5476_iomem.nile4)) { + printk + ("ddb_setup - requesting oo port resources failed.\n"); + for (;;); + } +#ifdef CONFIG_BLK_DEV_IDE + ide_ops = &std_ide_ops; +#endif + + /* Reboot on panic */ + panic_timeout = 180; + + /* [jsun] we need to set BAR0 so that SDRAM 0 appears at 0x0 in PCI */ + /* *(long*)0xbfa00218 = 0x8; */ + +#ifdef CONFIG_FB + conswitchp = &dummy_con; +#endif + + /* board initialization stuff */ + ddb5476_board_init(); +} + +/* + * We don't trust bios. We essentially does hardware re-initialization + * as complete as possible, as far as we know we can safely do. + */ +static void ddb5476_board_init(void) +{ + /* ----------- setup PDARs ------------ */ + /* check SDRAM0, whether we are on MEM bus does not matter */ + db_assert((ddb_in32(DDB_SDRAM0) & 0xffffffef) == + ddb_calc_pdar(DDB_SDRAM_BASE, DDB_SDRAM_SIZE, 32, 0, 1)); + + /* SDRAM1 should be turned off. What is this for anyway ? */ + db_assert( (ddb_in32(DDB_SDRAM1) & 0xf) == 0); + + /* flash 1&2, DDB status, DDB control */ + ddb_set_pdar(DDB_DCS2, DDB_DCS2_BASE, DDB_DCS2_SIZE, 16, 0, 0); + ddb_set_pdar(DDB_DCS3, DDB_DCS3_BASE, DDB_DCS3_SIZE, 16, 0, 0); + ddb_set_pdar(DDB_DCS4, DDB_DCS4_BASE, DDB_DCS4_SIZE, 8, 0, 0); + ddb_set_pdar(DDB_DCS5, DDB_DCS5_BASE, DDB_DCS5_SIZE, 8, 0, 0); + + /* shut off other pdar so they don't accidentally get into the way */ + ddb_set_pdar(DDB_DCS6, 0xffffffff, 0, 32, 0, 0); + ddb_set_pdar(DDB_DCS7, 0xffffffff, 0, 32, 0, 0); + ddb_set_pdar(DDB_DCS8, 0xffffffff, 0, 32, 0, 0); + + /* verify VRC5477 base addr */ + /* don't care about some details */ + db_assert((ddb_in32(DDB_INTCS) & 0xffffff0f) == + ddb_calc_pdar(DDB_INTCS_BASE, DDB_INTCS_SIZE, 8, 0, 0)); + + /* verify BOOT ROM addr */ + /* don't care about some details */ + db_assert((ddb_in32(DDB_BOOTCS) & 0xffffff0f) == + ddb_calc_pdar(DDB_BOOTCS_BASE, DDB_BOOTCS_SIZE, 8, 0, 0)); + + /* setup PCI windows - window1 for MEM/config, window0 for IO */ + ddb_set_pdar(DDB_PCIW0, DDB_PCI_IO_BASE, DDB_PCI_IO_SIZE, 32, 0, 1); + ddb_set_pmr(DDB_PCIINIT0, DDB_PCICMD_IO, 0, DDB_PCI_ACCESS_32); + + ddb_set_pdar(DDB_PCIW1, DDB_PCI_MEM_BASE, DDB_PCI_MEM_SIZE, 32, 0, 1); + ddb_set_pmr(DDB_PCIINIT1, DDB_PCICMD_MEM, DDB_PCI_MEM_BASE, DDB_PCI_ACCESS_32); + + /* ----------- setup PDARs ------------ */ + /* this is problematic - it will reset Aladin which cause we loose + * serial port, and we don't know how to set up Aladin chip again. + */ + // ddb_pci_reset_bus(); + + ddb_out32(DDB_BAR0, 0x00000008); + + ddb_out32(DDB_BARC, 0xffffffff); + ddb_out32(DDB_BARB, 0xffffffff); + ddb_out32(DDB_BAR1, 0xffffffff); + ddb_out32(DDB_BAR2, 0xffffffff); + ddb_out32(DDB_BAR3, 0xffffffff); + ddb_out32(DDB_BAR4, 0xffffffff); + ddb_out32(DDB_BAR5, 0xffffffff); + ddb_out32(DDB_BAR6, 0xffffffff); + ddb_out32(DDB_BAR7, 0xffffffff); + ddb_out32(DDB_BAR8, 0xffffffff); + + /* ----------- switch PCI1 to PCI CONFIG space ------------ */ + ddb_set_pdar(DDB_PCIW1, DDB_PCI_CONFIG_BASE, DDB_PCI_CONFIG_SIZE, 32, 0, 1); + ddb_set_pmr(DDB_PCIINIT1, DDB_PCICMD_CFG, 0x0, DDB_PCI_ACCESS_32); + + /* ----- M1543 PCI setup ------ */ + + /* we know M1543 PCI-ISA controller is at addr:18 */ + /* xxxx1010 makes USB at addr:13 and PMU at addr:14 */ + *(volatile unsigned char *) 0xa8040072 &= 0xf0; + *(volatile unsigned char *) 0xa8040072 |= 0xa; + + /* setup USB interrupt to IRQ 9, (bit 0:3 - 0001) + * no IOCHRDY signal, (bit 7 - 1) + * M1543C & M7101 VID and Subsys Device ID are read-only (bit 6 - 1) + * Make USB Master INTAJ level to edge conversion (bit 4 - 1) + */ + *(unsigned char *) 0xa8040074 = 0xd1; + + /* setup PMU(SCI to IRQ 10 (bit 0:3 - 0011) + * SCI routing to IRQ 13 disabled (bit 7 - 1) + * SCI interrupt level to edge conversion bypassed (bit 4 - 0) + */ + *(unsigned char *) 0xa8040076 = 0x83; + + /* setup IDE controller + * enable IDE controller (bit 6 - 1) + * IDE IDSEL to be addr:24 (bit 4:5 - 11) + * no IDE ATA Secondary Bus Signal Pad Control (bit 3 - 0) + * no IDE ATA Primary Bus Signal Pad Control (bit 2 - 0) + * primary IRQ is 14, secondary is 15 (bit 1:0 - 01 + */ + // *(unsigned char*)0xa8040058 = 0x71; + // *(unsigned char*)0xa8040058 = 0x79; + // *(unsigned char*)0xa8040058 = 0x74; // use SIRQ, primary tri-state + *(unsigned char *) 0xa8040058 = 0x75; // primary tri-state + +#if 0 + /* this is not necessary if M5229 does not use SIRQ */ + *(unsigned char *) 0xa8040044 = 0x0d; // primary to IRQ 14 + *(unsigned char *) 0xa8040075 = 0x0d; // secondary to IRQ 14 +#endif + + /* enable IDE in the M5229 config register 0x50 (bit 0 - 1) */ + /* M5229 IDSEL is addr:24; see above setting */ + *(unsigned char *) 0xa9000050 |= 0x1; + + /* enable bus master (bit 2) and IO decoding (bit 0) */ + *(unsigned char *) 0xa9000004 |= 0x5; + + /* enable native, copied from arch/ppc/k2boot/head.S */ + /* TODO - need volatile, need to be portable */ + *(unsigned char *) 0xa9000009 = 0xff; + + /* ----- end of M1543 PCI setup ------ */ + + /* ----- reset on-board ether chip ------ */ + *((volatile u32 *) 0xa8020004) |= 1; /* decode I/O */ + *((volatile u32 *) 0xa8020010) = 0; /* set BAR address */ + + /* send reset command */ + *((volatile u32 *) 0xa6000000) = 1; /* do a soft reset */ + + /* disable ether chip */ + *((volatile u32 *) 0xa8020004) = 0; /* disable any decoding */ + + /* put it into sleep */ + *((volatile u32 *) 0xa8020040) = 0x80000000; + + /* ----- end of reset on-board ether chip ------ */ + + /* ----------- switch PCI1 back to PCI MEM space ------------ */ + ddb_set_pdar(DDB_PCIW1, DDB_PCI_MEM_BASE, DDB_PCI_MEM_SIZE, 32, 0, 1); + ddb_set_pmr(DDB_PCIINIT1, DDB_PCICMD_MEM, DDB_PCI_MEM_BASE, DDB_PCI_ACCESS_32); +} diff -Nru a/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c b/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/ddb5xxx/ddb5476/vrc5476_irq.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,113 @@ +/* + * The irq controller for vrc5476. + * + * Copyright (C) 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ +#include +#include +#include +#include +#include + +#include + +#include + +static int irq_base; + +static void vrc5476_irq_enable(uint irq) +{ + nile4_enable_irq(irq - irq_base); +} + +static void vrc5476_irq_disable(uint irq) +{ + nile4_disable_irq(irq - irq_base); +} + +static unsigned int vrc5476_irq_startup(uint irq) +{ + nile4_enable_irq(irq - irq_base); + return 0; +} + +#define vrc5476_irq_shutdown vrc5476_irq_disable + +static void vrc5476_irq_ack(uint irq) +{ + nile4_clear_irq(irq - irq_base); + nile4_disable_irq(irq - irq_base); +} + +static void vrc5476_irq_end(uint irq) +{ + if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + vrc5476_irq_enable(irq); +} + +static hw_irq_controller vrc5476_irq_controller = { + "vrc5476", + vrc5476_irq_startup, + vrc5476_irq_shutdown, + vrc5476_irq_enable, + vrc5476_irq_disable, + vrc5476_irq_ack, + vrc5476_irq_end, + NULL /* no affinity stuff for UP */ +}; + +void __init +vrc5476_irq_init(u32 base) +{ + extern irq_desc_t irq_desc[]; + u32 i; + + irq_base = base; + for (i= base; i< base + NUM_VRC5476_IRQ; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = NULL; + irq_desc[i].depth = 1; + irq_desc[i].handler = &vrc5476_irq_controller; + } +} + + +asmlinkage void +vrc5476_irq_dispatch(struct pt_regs *regs) +{ + extern void spurious_interrupt(void); + + u32 mask; + int nile4_irq; + + mask = nile4_get_irq_stat(0); + + /* quick check for possible time interrupt */ + if (mask & (1 << VRC5476_IRQ_GPT)) { + do_IRQ(VRC5476_IRQ_BASE + VRC5476_IRQ_GPT, regs); + return; + } + + /* check for i8259 interrupts */ + if (mask & (1 << VRC5476_I8259_CASCADE)) { + int i8259_irq = nile4_i8259_iack(); + do_IRQ(I8259_IRQ_BASE + i8259_irq, regs); + return; + } + + /* regular nile4 interrupts (we should not really have any */ + for (nile4_irq = 0; mask; nile4_irq++, mask >>= 1) { + if (mask & 1) { + do_IRQ(VRC5476_IRQ_BASE + nile4_irq, regs); + return; + } + } + spurious_interrupt(); +} diff -Nru a/arch/mips/ddb5xxx/ddb5477/Makefile b/arch/mips/ddb5xxx/ddb5477/Makefile --- a/arch/mips/ddb5xxx/ddb5477/Makefile Tue Jul 1 18:44:34 2003 +++ b/arch/mips/ddb5xxx/ddb5477/Makefile Tue Jul 1 18:44:34 2003 @@ -2,10 +2,9 @@ # Makefile for NEC DDB-Vrc5477 board # -EXTRA_AFLAGS := $(CFLAGS) +obj-y += int-handler.o irq.o irq_5477.o setup.o lcd44780.o -obj-y += int-handler.o irq.o irq_5477.o setup.o pci.o pci_ops.o +obj-$(CONFIG_RUNTIME_DEBUG) += debug.o +obj-$(CONFIG_KGDB) += kgdb_io.o -obj-$(CONFIG_LL_DEBUG) += debug.o -obj-$(CONFIG_REMOTE_DEBUG) += kgdb_io.o -obj-$(CONFIG_BLK_DEV_INITRD) += ramdisk.o +EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips/ddb5xxx/ddb5477/debug.c b/arch/mips/ddb5xxx/ddb5477/debug.c --- a/arch/mips/ddb5xxx/ddb5477/debug.c Tue Jul 1 18:44:32 2003 +++ b/arch/mips/ddb5xxx/ddb5477/debug.c Tue Jul 1 18:44:32 2003 @@ -15,8 +15,6 @@ */ #include -#include -#include /* SA_INTERRUPT */ #include #include @@ -32,9 +30,9 @@ printk("\nshow regs: %s\n", name); for(i=0;regs[i].regname!= NULL; i++) { - printk("%-16s= %08x\t\t(@%08x)\n", - regs[i].regname, - *(unsigned *)(regs[i].regaddr), + printk("%-16s= %08x\t\t(@%08x)\n", + regs[i].regname, + *(unsigned *)(regs[i].regaddr), regs[i].regaddr); } } @@ -58,15 +56,15 @@ void vrc5477_show_int_regs() { jsun_show_regs("interrupt registers", int_regs); - printk("CPU CAUSE = %08x\n", read_32bit_cp0_register(CP0_CAUSE)); - printk("CPU STATUS = %08x\n", read_32bit_cp0_register(CP0_STATUS)); + printk("CPU CAUSE = %08x\n", read_c0_cause()); + printk("CPU STATUS = %08x\n", read_c0_status()); } static Register pdar_regs[] = { {"DDB_SDRAM0", DDB_BASE + DDB_SDRAM0}, {"DDB_SDRAM1", DDB_BASE + DDB_SDRAM1}, - {"DDB_LDCS0", DDB_BASE + DDB_LDCS0}, - {"DDB_LDCS1", DDB_BASE + DDB_LDCS1}, - {"DDB_LDCS2", DDB_BASE + DDB_LDCS2}, + {"DDB_LCS0", DDB_BASE + DDB_LCS0}, + {"DDB_LCS1", DDB_BASE + DDB_LCS1}, + {"DDB_LCS2", DDB_BASE + DDB_LCS2}, {"DDB_INTCS", DDB_BASE + DDB_INTCS}, {"DDB_BOOTCS", DDB_BASE + DDB_BOOTCS}, {"DDB_PCIW0", DDB_BASE + DDB_PCIW0}, diff -Nru a/arch/mips/ddb5xxx/ddb5477/int-handler.S b/arch/mips/ddb5xxx/ddb5477/int-handler.S --- a/arch/mips/ddb5xxx/ddb5477/int-handler.S Tue Jul 1 18:44:36 2003 +++ b/arch/mips/ddb5xxx/ddb5477/int-handler.S Tue Jul 1 18:44:36 2003 @@ -9,13 +9,12 @@ * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. */ -#include - #include #include #include #include #include +#include /* * first level interrupt dispatcher for ocelot board - @@ -28,14 +27,14 @@ CLI .set at .set noreorder - mfc0 t0, CP0_CAUSE + mfc0 t0, CP0_CAUSE mfc0 t2, CP0_STATUS and t0, t2 - + andi t1, t0, STATUSF_IP7 /* cpu timer */ bnez t1, ll_cputimer_irq - andi t1, t0, (STATUSF_IP2 | STATUSF_IP3 | STATUSF_IP4 | STATUSF_IP5 | STATUSF_IP6 ) + andi t1, t0, (STATUSF_IP2 | STATUSF_IP3 | STATUSF_IP4 | STATUSF_IP5 | STATUSF_IP6 ) bnez t1, ll_vrc5477_irq andi t1, t0, STATUSF_IP0 /* software int 0 */ bnez t1, ll_cpu_ip0 @@ -51,26 +50,26 @@ .align 5 -ll_vrc5477_irq: +ll_vrc5477_irq: move a0, sp jal vrc5477_irq_dispatch j ret_from_irq ll_cputimer_irq: - li a0, 7 + li a0, CPU_IRQ_BASE + 7 move a1, sp jal do_IRQ j ret_from_irq -ll_cpu_ip0: - li a0, 0 +ll_cpu_ip0: + li a0, CPU_IRQ_BASE + 0 move a1, sp jal do_IRQ j ret_from_irq -ll_cpu_ip1: - li a0, 1 +ll_cpu_ip1: + li a0, CPU_IRQ_BASE + 1 move a1, sp jal do_IRQ j ret_from_irq diff -Nru a/arch/mips/ddb5xxx/ddb5477/irq.c b/arch/mips/ddb5xxx/ddb5477/irq.c --- a/arch/mips/ddb5xxx/ddb5477/irq.c Tue Jul 1 18:44:32 2003 +++ b/arch/mips/ddb5xxx/ddb5477/irq.c Tue Jul 1 18:44:32 2003 @@ -12,16 +12,20 @@ */ #include #include +#include #include #include #include +#include #include #include +#include +#include +#include + #include -/* [jsun] sooner or later we should move this debug stuff to MIPS common */ -#include /* * IRQ mapping @@ -37,7 +41,7 @@ * 7 - cpu timer (used by default) * * 8-39: 32 Vrc5477 interrupt sources - * (refer to the Vrc5477 manual) + * (refer to the Vrc5477 manual) */ #define PCI0 DDB_INTPPES0 @@ -55,7 +59,7 @@ #define INTD 3 #define INTE 4 -static inline void +static inline void set_pci_int_attr(u32 pci, u32 intn, u32 active, u32 trigger) { u32 reg_value; @@ -63,7 +67,7 @@ reg_value = ddb_in32(pci); reg_bitmask = 0x3 << (intn * 2); - + reg_value &= ~reg_bitmask; reg_value |= (active | trigger) << (intn * 2); ddb_out32(pci, reg_value); @@ -72,26 +76,31 @@ extern void vrc5477_irq_init(u32 base); extern void mips_cpu_irq_init(u32 base); extern asmlinkage void ddb5477_handle_int(void); +extern int setup_irq(unsigned int irq, struct irqaction *irqaction); +static struct irqaction irq_cascade = { no_action, 0, 0, "cascade", NULL, NULL }; void ddb5477_irq_setup(void) { - MIPS_DEBUG(printk("ddb5477_irq_setup invoked.\n")); + db_run(printk("ddb5477_irq_setup invoked.\n")); - /* by default, we disable all interrupts and route all vrc5477 + /* by default, we disable all interrupts and route all vrc5477 * interrupts to pin 0 (irq 2) */ ddb_out32(DDB_INTCTRL0, 0); ddb_out32(DDB_INTCTRL1, 0); ddb_out32(DDB_INTCTRL2, 0); ddb_out32(DDB_INTCTRL3, 0); - clear_cp0_status(0xff00); - set_cp0_status(0x0400); + clear_c0_status(0xff00); + set_c0_status(0x0400); /* setup PCI interrupt attributes */ set_pci_int_attr(PCI0, INTA, ACTIVE_LOW, LEVEL_SENSE); set_pci_int_attr(PCI0, INTB, ACTIVE_LOW, LEVEL_SENSE); - set_pci_int_attr(PCI0, INTC, ACTIVE_LOW, LEVEL_SENSE); + if (mips_machtype == MACH_NEC_ROCKHOPPERII) + set_pci_int_attr(PCI0, INTC, ACTIVE_HIGH, LEVEL_SENSE); + else + set_pci_int_attr(PCI0, INTC, ACTIVE_LOW, LEVEL_SENSE); set_pci_int_attr(PCI0, INTD, ACTIVE_LOW, LEVEL_SENSE); set_pci_int_attr(PCI0, INTE, ACTIVE_LOW, LEVEL_SENSE); @@ -101,9 +110,9 @@ set_pci_int_attr(PCI1, INTD, ACTIVE_LOW, LEVEL_SENSE); set_pci_int_attr(PCI1, INTE, ACTIVE_LOW, LEVEL_SENSE); - /* + /* * for debugging purpose, we enable several error interrupts - * and route them to pin 1. (IP3) + * and route them to pin 1. (IP3) */ /* cpu parity check - 0 */ ll_vrc5477_irq_route(0, 1); ll_vrc5477_irq_enable(0); @@ -121,13 +130,34 @@ ll_vrc5477_irq_route(31, 1); ll_vrc5477_irq_enable(31); /* init all controllers */ - mips_cpu_irq_init(0); - vrc5477_irq_init(8); + init_i8259_irqs(); + mips_cpu_irq_init(CPU_IRQ_BASE); + vrc5477_irq_init(VRC5477_IRQ_BASE); + + + /* setup cascade interrupts */ + setup_irq(VRC5477_IRQ_BASE + VRC5477_I8259_CASCADE, &irq_cascade); + setup_irq(CPU_IRQ_BASE + CPU_VRC5477_CASCADE, &irq_cascade); /* hook up the first-level interrupt handler */ set_except_vector(0, ddb5477_handle_int); } +u8 i8259_interrupt_ack(void) +{ + u8 irq; + u32 reg; + + /* Set window 0 for interrupt acknowledge */ + reg = ddb_in32(DDB_PCIINIT10); + + ddb_set_pmr(DDB_PCIINIT10, DDB_PCICMD_IACK, 0, DDB_PCI_ACCESS_32); + irq = *(volatile u8 *) KSEG1ADDR(DDB_PCI_IACK_BASE); + ddb_out32(DDB_PCIINIT10, reg); + + /* i8259.c set the base vector to be 0x0 */ + return irq + I8259_IRQ_BASE; +} /* * the first level int-handler will jump here if it is a vrc5477 irq */ @@ -135,29 +165,38 @@ asmlinkage void vrc5477_irq_dispatch(struct pt_regs *regs) { - extern unsigned int do_IRQ(int irq, struct pt_regs *regs); - u32 intStatus; u32 bitmask; u32 i; - MIPS_ASSERT(ddb_in32(DDB_INT2STAT) == 0); - MIPS_ASSERT(ddb_in32(DDB_INT3STAT) == 0); - MIPS_ASSERT(ddb_in32(DDB_INT4STAT) == 0); - MIPS_ASSERT(ddb_in32(DDB_NMISTAT) == 0); + db_assert(ddb_in32(DDB_INT2STAT) == 0); + db_assert(ddb_in32(DDB_INT3STAT) == 0); + db_assert(ddb_in32(DDB_INT4STAT) == 0); + db_assert(ddb_in32(DDB_NMISTAT) == 0); if (ddb_in32(DDB_INT1STAT) != 0) { -#if defined(CONFIG_LL_DEBUG) +#if defined(CONFIG_RUNTIME_DEBUG) vrc5477_show_int_regs(); #endif - panic("error interrupt has happened.\n"); + panic("error interrupt has happened."); } intStatus = ddb_in32(DDB_INT0STAT); + + if (mips_machtype == MACH_NEC_ROCKHOPPERII) { + /* check for i8259 interrupts */ + if (intStatus & (1 << VRC5477_I8259_CASCADE)) { + int i8259_irq = i8259_interrupt_ack(); + do_IRQ(I8259_IRQ_BASE + i8259_irq, regs); + return; + } + } + for (i=0, bitmask=1; i<= NUM_5477_IRQS; bitmask <<=1, i++) { /* do we need to "and" with the int mask? */ if (intStatus & bitmask) { - do_IRQ(8 + i, regs); + do_IRQ(VRC5477_IRQ_BASE + i, regs); + return; } } } diff -Nru a/arch/mips/ddb5xxx/ddb5477/irq_5477.c b/arch/mips/ddb5xxx/ddb5477/irq_5477.c --- a/arch/mips/ddb5xxx/ddb5477/irq_5477.c Tue Jul 1 18:44:33 2003 +++ b/arch/mips/ddb5xxx/ddb5477/irq_5477.c Tue Jul 1 18:44:33 2003 @@ -1,4 +1,4 @@ -/*********************************************************************** +/* * Copyright 2001 MontaVista Software Inc. * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net * @@ -9,7 +9,7 @@ * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. - *********************************************************************** + * */ /* @@ -19,37 +19,36 @@ * vrc5477_irq_init(u32 irq_base); */ -#include +#include #include #include -#include +#include -/* [jsun] sooner or later we should move this debug stuff to MIPS common */ -#include +#include /* number of total irqs supported by Vrc5477 */ #define NUM_5477_IRQ 32 -static int vrc5477_irq_base=-1; +static int vrc5477_irq_base = -1; -static void +static void vrc5477_irq_enable(unsigned int irq) { - MIPS_ASSERT(vrc5477_irq_base != -1); - MIPS_ASSERT(irq >= vrc5477_irq_base); - MIPS_ASSERT(irq < vrc5477_irq_base+ NUM_5477_IRQ); + db_assert(vrc5477_irq_base != -1); + db_assert(irq >= vrc5477_irq_base); + db_assert(irq < vrc5477_irq_base+ NUM_5477_IRQ); ll_vrc5477_irq_enable(irq - vrc5477_irq_base); } -static void +static void vrc5477_irq_disable(unsigned int irq) { - MIPS_ASSERT(vrc5477_irq_base != -1); - MIPS_ASSERT(irq >= vrc5477_irq_base); - MIPS_ASSERT(irq < vrc5477_irq_base + NUM_5477_IRQ); + db_assert(vrc5477_irq_base != -1); + db_assert(irq >= vrc5477_irq_base); + db_assert(irq < vrc5477_irq_base + NUM_5477_IRQ); ll_vrc5477_irq_disable(irq - vrc5477_irq_base); } @@ -65,9 +64,9 @@ static void vrc5477_irq_ack(unsigned int irq) { - MIPS_ASSERT(vrc5477_irq_base != -1); - MIPS_ASSERT(irq >= vrc5477_irq_base); - MIPS_ASSERT(irq < vrc5477_irq_base+ NUM_5477_IRQ); + db_assert(vrc5477_irq_base != -1); + db_assert(irq >= vrc5477_irq_base); + db_assert(irq < vrc5477_irq_base+ NUM_5477_IRQ); /* clear the interrupt bit */ /* some irqs require the driver to clear the sources */ @@ -82,11 +81,12 @@ static void vrc5477_irq_end(unsigned int irq) { - MIPS_ASSERT(vrc5477_irq_base != -1); - MIPS_ASSERT(irq >= vrc5477_irq_base); - MIPS_ASSERT(irq < vrc5477_irq_base + NUM_5477_IRQ); + db_assert(vrc5477_irq_base != -1); + db_assert(irq >= vrc5477_irq_base); + db_assert(irq < vrc5477_irq_base + NUM_5477_IRQ); - ll_vrc5477_irq_enable( irq - vrc5477_irq_base); + if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + ll_vrc5477_irq_enable( irq - vrc5477_irq_base); } hw_irq_controller vrc5477_irq_controller = { @@ -100,7 +100,7 @@ NULL /* no affinity stuff for UP */ }; -void +void vrc5477_irq_init(u32 irq_base) { extern irq_desc_t irq_desc[]; @@ -112,17 +112,8 @@ irq_desc[i].depth = 1; irq_desc[i].handler = &vrc5477_irq_controller; } - - vrc5477_irq_base = irq_base; -} - -int vrc5477_irq_to_irq(int irq) -{ - MIPS_ASSERT(irq >= 0); - MIPS_ASSERT(irq < NUM_5477_IRQ); - - return irq + vrc5477_irq_base; + vrc5477_irq_base = irq_base; } void ll_vrc5477_irq_route(int vrc5477_irq, int ip) @@ -131,10 +122,10 @@ u32 reg_bitmask; u32 reg_index; - MIPS_ASSERT(vrc5477_irq >= 0); - MIPS_ASSERT(vrc5477_irq < NUM_5477_IRQ); - MIPS_ASSERT(ip >= 0); - MIPS_ASSERT((ip < 5) || (ip == 6)); + db_assert(vrc5477_irq >= 0); + db_assert(vrc5477_irq < NUM_5477_IRQ); + db_assert(ip >= 0); + db_assert((ip < 5) || (ip == 6)); reg_index = DDB_INTCTRL0 + vrc5477_irq/8*4; reg_value = ddb_in32(reg_index); @@ -150,13 +141,13 @@ u32 reg_bitmask; u32 reg_index; - MIPS_ASSERT(vrc5477_irq >= 0); - MIPS_ASSERT(vrc5477_irq < NUM_5477_IRQ); + db_assert(vrc5477_irq >= 0); + db_assert(vrc5477_irq < NUM_5477_IRQ); reg_index = DDB_INTCTRL0 + vrc5477_irq/8*4; reg_value = ddb_in32(reg_index); reg_bitmask = 8 << (vrc5477_irq % 8 * 4); - MIPS_ASSERT((reg_value & reg_bitmask) == 0); + db_assert((reg_value & reg_bitmask) == 0); ddb_out32(reg_index, reg_value | reg_bitmask); } @@ -166,14 +157,14 @@ u32 reg_bitmask; u32 reg_index; - MIPS_ASSERT(vrc5477_irq >= 0); - MIPS_ASSERT(vrc5477_irq < NUM_5477_IRQ); + db_assert(vrc5477_irq >= 0); + db_assert(vrc5477_irq < NUM_5477_IRQ); reg_index = DDB_INTCTRL0 + vrc5477_irq/8*4; reg_value = ddb_in32(reg_index); reg_bitmask = 8 << (vrc5477_irq % 8 * 4); /* we assert that the interrupt is enabled (perhaps over-zealous) */ - MIPS_ASSERT( (reg_value & reg_bitmask) != 0); + db_assert( (reg_value & reg_bitmask) != 0); ddb_out32(reg_index, reg_value & ~reg_bitmask); } diff -Nru a/arch/mips/ddb5xxx/ddb5477/kgdb_io.c b/arch/mips/ddb5xxx/ddb5477/kgdb_io.c --- a/arch/mips/ddb5xxx/ddb5477/kgdb_io.c Tue Jul 1 18:44:36 2003 +++ b/arch/mips/ddb5xxx/ddb5477/kgdb_io.c Tue Jul 1 18:44:36 2003 @@ -1,17 +1,41 @@ +/* + * kgdb io functions for DDB5477. We use the second serial port (upper one). + * + * Copyright (C) 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ -#include +/* ======================= CONFIG ======================== */ -#if (defined(CONFIG_DDB5477) && defined(CONFIG_REMOTE_DEBUG)) +/* [jsun] we use the second serial port for kdb */ +#define BASE 0xbfa04240 +#define MAX_BAUD 115200 -/* --- CONFIG --- */ +/* distance in bytes between two serial registers */ +#define REG_OFFSET 8 + +/* + * 0 - kgdb does serial init + * 1 - kgdb skip serial init + */ +static int remoteDebugInitialized = 0; + +/* + * the default baud rate *if* kgdb does serial init + */ +#define BAUD_DEFAULT UART16550_BAUD_38400 + +/* ======================= END OF CONFIG ======================== */ -/* we need uint32 uint8 */ -/* #include "types.h" */ typedef unsigned char uint8; typedef unsigned int uint32; -/* --- END OF CONFIG --- */ - #define UART16550_BAUD_2400 2400 #define UART16550_BAUD_4800 4800 #define UART16550_BAUD_9600 9600 @@ -34,21 +58,10 @@ #define UART16550_STOP_1BIT 0x0 #define UART16550_STOP_2BIT 0x4 -/* ----------------------------------------------------- */ - -/* === CONFIG === */ - -/* [jsun] we use the second serial port for kdb */ -#define BASE 0xbfa04240 -#define MAX_BAUD 115200 -#define REG_OFFSET 8 - -/* === END OF CONFIG === */ - /* register offset */ -#define OFS_RCV_BUFFER (0*REG_OFFSET) -#define OFS_TRANS_HOLD (0*REG_OFFSET) -#define OFS_SEND_BUFFER (0*REG_OFFSET) +#define OFS_RCV_BUFFER 0 +#define OFS_TRANS_HOLD 0 +#define OFS_SEND_BUFFER 0 #define OFS_INTR_ENABLE (1*REG_OFFSET) #define OFS_INTR_ID (2*REG_OFFSET) #define OFS_DATA_FORMAT (3*REG_OFFSET) @@ -70,73 +83,54 @@ void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop) { - /* disable interrupts */ - UART16550_WRITE(OFS_INTR_ENABLE, 0); + /* disable interrupts */ + UART16550_WRITE(OFS_INTR_ENABLE, 0); - /* set up buad rate */ - { - uint32 divisor; - - /* set DIAB bit */ - UART16550_WRITE(OFS_LINE_CONTROL, 0x80); - - /* set divisor */ - divisor = MAX_BAUD / baud; - UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff); - UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8); - - /* clear DIAB bit */ - UART16550_WRITE(OFS_LINE_CONTROL, 0x0); - } + /* set up buad rate */ + { + uint32 divisor; + + /* set DIAB bit */ + UART16550_WRITE(OFS_LINE_CONTROL, 0x80); + + /* set divisor */ + divisor = MAX_BAUD / baud; + UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff); + UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8); + + /* clear DIAB bit */ + UART16550_WRITE(OFS_LINE_CONTROL, 0x0); + } - /* set data format */ - UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop); + /* set data format */ + UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop); } -static int remoteDebugInitialized = 0; - -int debug_state = -1; uint8 getDebugChar(void) { - uint8 c; - if (!remoteDebugInitialized) { - remoteDebugInitialized = 1; - debugInit(UART16550_BAUD_38400, - UART16550_DATA_8BIT, - UART16550_PARITY_NONE, UART16550_STOP_1BIT); - } + if (!remoteDebugInitialized) { + remoteDebugInitialized = 1; + debugInit(BAUD_DEFAULT, + UART16550_DATA_8BIT, + UART16550_PARITY_NONE, UART16550_STOP_1BIT); + } - while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0); - c= UART16550_READ(OFS_RCV_BUFFER); -/* - if (state != 1) { - state = 1; - debug_out("\ngetDebugChar: ", 15); - } - debug_out(&c, 1); -*/ - return c; + while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0); + return UART16550_READ(OFS_RCV_BUFFER); } int putDebugChar(uint8 byte) { - if (!remoteDebugInitialized) { - remoteDebugInitialized = 1; - debugInit(UART16550_BAUD_9600, - UART16550_DATA_8BIT, - UART16550_PARITY_NONE, UART16550_STOP_1BIT); - } - - while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0); - UART16550_WRITE(OFS_SEND_BUFFER, byte); - if (debug_state != 2) { - debug_state = 2; - // debug_out("\nputDebugChar: ", 15); - } - // debug_out(&byte, 1); - return 1; + if (!remoteDebugInitialized) { + remoteDebugInitialized = 1; + debugInit(BAUD_DEFAULT, + UART16550_DATA_8BIT, + UART16550_PARITY_NONE, UART16550_STOP_1BIT); + } + + while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0); + UART16550_WRITE(OFS_SEND_BUFFER, byte); + return 1; } - -#endif diff -Nru a/arch/mips/ddb5xxx/ddb5477/lcd44780.c b/arch/mips/ddb5xxx/ddb5477/lcd44780.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/ddb5xxx/ddb5477/lcd44780.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,92 @@ +/* + * lcd44780.c + * Simple "driver" for a memory-mapped 44780-style LCD display. + * + * Copyright 2001 Bradley D. LaRonde + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#define LCD44780_COMMAND ((volatile unsigned char *)0xbe020000) +#define LCD44780_DATA ((volatile unsigned char *)0xbe020001) + +#define LCD44780_4BIT_1LINE 0x20 +#define LCD44780_4BIT_2LINE 0x28 +#define LCD44780_8BIT_1LINE 0x30 +#define LCD44780_8BIT_2LINE 0x38 +#define LCD44780_MODE_DEC 0x04 +#define LCD44780_MODE_DEC_SHIFT 0x05 +#define LCD44780_MODE_INC 0x06 +#define LCD44780_MODE_INC_SHIFT 0x07 +#define LCD44780_SCROLL_LEFT 0x18 +#define LCD44780_SCROLL_RIGHT 0x1e +#define LCD44780_CURSOR_UNDERLINE 0x0e +#define LCD44780_CURSOR_BLOCK 0x0f +#define LCD44780_CURSOR_OFF 0x0c +#define LCD44780_CLEAR 0x01 +#define LCD44780_BLANK 0x08 +#define LCD44780_RESTORE 0x0c // Same as CURSOR_OFF +#define LCD44780_HOME 0x02 +#define LCD44780_LEFT 0x10 +#define LCD44780_RIGHT 0x14 + +void lcd44780_wait(void) +{ + int i, j; + for(i=0; i < 400; i++) + for(j=0; j < 10000; j++); +} + +void lcd44780_command(unsigned char c) +{ + *LCD44780_COMMAND = c; + lcd44780_wait(); +} + +void lcd44780_data(unsigned char c) +{ + *LCD44780_DATA = c; + lcd44780_wait(); +} + +void lcd44780_puts(const char* s) +{ + int i,j; + int pos = 0; + + lcd44780_command(LCD44780_CLEAR); + while(*s) { + lcd44780_data(*s); + s++; + pos++; + if (pos == 8) { + /* We must write 32 of spaces to get cursor to 2nd line */ + for (j=0; j<32; j++) { + lcd44780_data(' '); + } + } + if (pos == 16) { + /* We have filled all 16 character positions, so stop + outputing data */ + break; + } + } +#ifdef LCD44780_PUTS_PAUSE + for(i = 1; i < 2000; i++) + lcd44780_wait(); +#endif +} + +void lcd44780_init(void) +{ + // The display on the RockHopper is physically a single + // 16 char line (two 8 char lines concatenated). bdl + lcd44780_command(LCD44780_8BIT_2LINE); + lcd44780_command(LCD44780_MODE_INC); + lcd44780_command(LCD44780_CURSOR_BLOCK); + lcd44780_command(LCD44780_CLEAR); +} diff -Nru a/arch/mips/ddb5xxx/ddb5477/lcd44780.h b/arch/mips/ddb5xxx/ddb5477/lcd44780.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/ddb5xxx/ddb5477/lcd44780.h Tue Jul 1 18:44:39 2003 @@ -0,0 +1,15 @@ +/* + * lcd44780.h + * Simple "driver" for a memory-mapped 44780-style LCD display. + * + * Copyright 2001 Bradley D. LaRonde + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +void lcd44780_puts(const char* s); +void lcd44780_init(void); diff -Nru a/arch/mips/ddb5xxx/ddb5477/pci.c b/arch/mips/ddb5xxx/ddb5477/pci.c --- a/arch/mips/ddb5xxx/ddb5477/pci.c Tue Jul 1 18:44:35 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,147 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include - -static struct resource extpci_io_resource = { - "ext pci IO space", - DDB_PCI0_IO_BASE - DDB_PCI_IO_BASE, - DDB_PCI0_IO_BASE - DDB_PCI_IO_BASE + DDB_PCI0_IO_SIZE -1, - IORESOURCE_IO}; - -static struct resource extpci_mem_resource = { - "ext pci memory space", - DDB_PCI0_MEM_BASE, - DDB_PCI0_MEM_BASE + DDB_PCI0_MEM_SIZE -1, - IORESOURCE_MEM}; - -static struct resource iopci_io_resource = { - "io pci IO space", - DDB_PCI1_IO_BASE - DDB_PCI_IO_BASE, - DDB_PCI1_IO_BASE - DDB_PCI_IO_BASE + DDB_PCI1_IO_SIZE -1, - IORESOURCE_IO}; - -static struct resource iopci_mem_resource = { - "ext pci memory space", - DDB_PCI1_MEM_BASE, - DDB_PCI1_MEM_BASE + DDB_PCI1_MEM_SIZE -1, - IORESOURCE_MEM}; - -extern struct pci_ops ddb5477_ext_pci_ops; -extern struct pci_ops ddb5477_io_pci_ops; - -struct pci_channel mips_pci_channels[] = { - { &ddb5477_ext_pci_ops, &extpci_io_resource, &extpci_mem_resource }, - { &ddb5477_io_pci_ops, &iopci_io_resource, &iopci_mem_resource }, - { NULL, NULL, NULL} -}; - - -/* - * we fix up irqs based on the slot number. - * The first entry is at AD:11. - * Fortunately this works because, although we have two pci buses, - * they all have different slot numbers. - * - * This does not work for devices on sub-buses. - * - * Note that the irq number in the array is relative number in vrc5477. - * We need to translate it to global irq number. - */ - -/* - * irq mapping : PCI int # -> vrc5477 irq # - * based on vrc5477 manual page 46 - */ -#define PCI_EXT_INTA 8 -#define PCI_EXT_INTB 9 -#define PCI_EXT_INTC 10 -#define PCI_EXT_INTD 11 -#define PCI_EXT_INTE 12 - -#define PCI_IO_INTA 16 -#define PCI_IO_INTB 17 -#define PCI_IO_INTC 18 -#define PCI_IO_INTD 19 - -/* - * irq mapping : device -> pci int #, - * ddb5477 board manual page 4 and vrc5477 manual page 46 - */ -#define INT_ONBOARD_TULIP PCI_EXT_INTA -#define INT_SLOT1 PCI_EXT_INTB -#define INT_SLOT2 PCI_EXT_INTC -#define INT_SLOT3 PCI_EXT_INTD -#define INT_SLOT4 PCI_EXT_INTE - -#define INT_USB_HOST PCI_IO_INTA -#define INT_USB_PERI PCI_IO_INTB -#define INT_AC97 PCI_IO_INTC - -/* - * based on ddb5477 manual page 11 - */ -#define MAX_SLOT_NUM 21 -static unsigned char irq_map[MAX_SLOT_NUM] = { - /* AD:11 */ 0xff, 0xff, 0xff, 0xff, - /* AD:15 */ INT_ONBOARD_TULIP, INT_SLOT1, INT_SLOT2, INT_SLOT3, - /* AD:19 */ INT_SLOT4, 0xff, 0xff, 0xff, - /* AD:23 */ 0xff, 0xff, 0xff, 0xff, - /* AD:27 */ 0xff, 0xff, INT_AC97, INT_USB_PERI, - /* AD:31 */ INT_USB_HOST -}; - -extern int vrc5477_irq_to_irq(int irq); -void __init pcibios_fixup_irqs(void) -{ - struct pci_dev *dev = NULL; - int slot_num; - - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - slot_num = PCI_SLOT(dev->devfn); - MIPS_ASSERT(slot_num < MAX_SLOT_NUM); - MIPS_ASSERT(irq_map[slot_num] != 0xff); - - pci_write_config_byte(dev, - PCI_INTERRUPT_LINE, - irq_map[slot_num]); - dev->irq = vrc5477_irq_to_irq(irq_map[slot_num]); - } -} - -#if defined(CONFIG_LL_DEBUG) -extern void jsun_scan_pci_bus(void); -extern void jsun_assign_pci_resource(void); -#endif -void __init ddb_pci_reset_bus(void) -{ - u32 temp; - - /* - * I am not sure about the "official" procedure, the following - * steps work as far as I know: - * We first set PCI cold reset bit (bit 31) in PCICTRL-H. - * Then we clear the PCI warm reset bit (bit 30) to 0 in PCICTRL-H. - * The same is true for both PCI channels. - */ - temp = ddb_in32(DDB_PCICTL0_H); - temp |= 0x80000000; - ddb_out32(DDB_PCICTL0_H, temp); - temp &= ~0xc0000000; - ddb_out32(DDB_PCICTL0_H, temp); - - temp = ddb_in32(DDB_PCICTL1_H); - temp |= 0x80000000; - ddb_out32(DDB_PCICTL1_H, temp); - temp &= ~0xc0000000; - ddb_out32(DDB_PCICTL1_H, temp); -} - -unsigned __init int pcibios_assign_all_busses(void) -{ - return 1; -} diff -Nru a/arch/mips/ddb5xxx/ddb5477/pci_ops.c b/arch/mips/ddb5xxx/ddb5477/pci_ops.c --- a/arch/mips/ddb5xxx/ddb5477/pci_ops.c Tue Jul 1 18:44:35 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,381 +0,0 @@ -/*********************************************************************** - * Copyright 2001 MontaVista Software Inc. - * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net - * - * arch/mips/ddb5xxx/ddb5477/pci_ops.c - * Define the pci_ops for DB5477. - * - * Much of the code is derived from the original DDB5074 port by - * Geert Uytterhoeven - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - *********************************************************************** - */ - -/* - * DDB5477 has two PCI channels, external PCI and IOPIC (internal) - * Therefore we provide two sets of pci_ops. - */ - -#include -#include -#include -#include - -#include -#include -#include - -/* - * config_swap structure records what set of pdar/pmr are used - * to access pci config space. It also provides a place hold the - * original values for future restoring. - */ -struct pci_config_swap { - u32 pdar; - u32 pmr; - u32 config_base; - u32 config_size; - u32 pdar_backup; - u32 pmr_backup; -}; - -/* - * On DDB5477, we have two sets of swap registers, for ext PCI and IOPCI. - */ -struct pci_config_swap ext_pci_swap = { - DDB_PCIW0, - DDB_PCIINIT00, - DDB_PCI0_CONFIG_BASE, - DDB_PCI0_CONFIG_SIZE -}; -struct pci_config_swap io_pci_swap = { - DDB_IOPCIW0, - DDB_PCIINIT01, - DDB_PCI1_CONFIG_BASE, - DDB_PCI1_CONFIG_SIZE -}; - - -/* - * access config space - */ -static inline u32 ddb_access_config_base(struct pci_config_swap *swap, - u32 bus,/* 0 means top level bus */ - u32 slot_num) -{ - u32 pci_addr = 0; - u32 pciinit_offset = 0; - u32 virt_addr = swap->config_base; - u32 option; - - /* [jsun] hack for testing */ - // if (slot_num == 4) slot_num = 0; - - /* minimum pdar (window) size is 2MB */ - MIPS_ASSERT(swap->config_size >= (2 << 20)); - - MIPS_ASSERT(slot_num < (1 << 5)); - MIPS_ASSERT(bus < (1 << 8)); - - /* backup registers */ - swap->pdar_backup = ddb_in32(swap->pdar); - swap->pmr_backup = ddb_in32(swap->pmr); - - /* set the pdar (pci window) register */ - ddb_set_pdar(swap->pdar, - swap->config_base, - swap->config_size, - 32, /* 32 bit wide */ - 0, /* not on local memory bus */ - 0); /* not visible from PCI bus (N/A) */ - - /* - * calcuate the absolute pci config addr; - * according to the spec, we start scanning from adr:11 (0x800) - */ - if (bus == 0) { - /* type 0 config */ - pci_addr = 0x800 << slot_num; - } else { - /* type 1 config */ - pci_addr = (bus << 16) | (slot_num << 11); - panic("ddb_access_config_base: we don't support type 1 config Yet"); - } - - /* - * if pci_addr is less than pci config window size, we set - * pciinit_offset to 0 and adjust the virt_address. - * Otherwise we will try to adjust pciinit_offset. - */ - if (pci_addr < swap->config_size) { - virt_addr = KSEG1ADDR(swap->config_base + pci_addr); - pciinit_offset = 0; - } else { - MIPS_ASSERT( (pci_addr & (swap->config_size - 1)) == 0); - virt_addr = KSEG1ADDR(swap->config_base); - pciinit_offset = pci_addr; - } - - /* set the pmr register */ - option = DDB_PCI_ACCESS_32; - if (bus != 0) option |= DDB_PCI_CFGTYPE1; - ddb_set_pmr(swap->pmr, DDB_PCICMD_CFG, pciinit_offset, option); - - return virt_addr; -} - -static inline void ddb_close_config_base(struct pci_config_swap *swap) -{ - ddb_out32(swap->pdar, swap->pdar_backup); - ddb_out32(swap->pmr, swap->pmr_backup); -} - -static int read_config(struct pci_config_swap *swap, - struct pci_bus *bus, - unsigned int devfn, - u32 where, - int size, - u32 *val) -{ - u32 busnum, slot_num, func_num, base, result; - int status - - switch (size) { - case 4: - MIPS_ASSERT((where & 3) == 0); - MIPS_ASSERT(where < (1 << 8)); - - /* check if the bus is top-level */ - if (bus->parent != NULL) { - busnum = bus->number; - MIPS_ASSERT(busnum != 0); - } else { - busnum = 0; - } - - slot_num = PCI_SLOT(devfn); - func_num = PCI_FUNC(devfn); - base = ddb_access_config_base(swap, busnum, slot_num); - *val = *(volatile u32*) (base + (func_num << 8) + where); - ddb_close_config_base(swap); - return PCIBIOS_SUCCESSFUL; - - case 2: - MIPS_ASSERT((where & 1) == 0); - - status = read_config(swap, bus, devfn, where & ~3, 4, - &result); - if (where & 2) result >>= 16; - *val = (u16)(result & 0xffff); - return status; - - case 1: - status = read_config(swap, bus, devfn, where & ~3, 4, - &result); - if (where & 1) result >>= 8; - if (where & 2) result >>= 16; - *val = (u8)(result & 0xff); - return status; - } -} - -static int write_config(struct pci_config_swap *swap, - struct pci_bus *bus, - unsigned int devfn, - u32 where, - int size, - u32 val) -{ - u32 busnum, slot_num, func_num, base, results; - int status, shift = 0; - - switch (size) { - case 4: - MIPS_ASSERT((where & 3) == 0); - MIPS_ASSERT(where < (1 << 8)); - - /* check if the bus is top-level */ - if (bus->parent != NULL) { - busnum = bus->number; - MIPS_ASSERT(busnum != 0); - } else { - busnum = 0; - } - - slot_num = PCI_SLOT(devfn); - func_num = PCI_FUNC(devfn); - base = ddb_access_config_base(swap, busnum, slot_num); - *(volatile u32*) (base + (func_num << 8) + where) = val; - ddb_close_config_base(swap); - return PCIBIOS_SUCCESSFUL; - - case 2: - MIPS_ASSERT((where & 1) == 0); - - status = read_config(swap, bus, devfn, where & ~3, 4, - &result); - if (status != PCIBIOS_SUCCESSFUL) return status; - - if (where & 2) - shift += 16; - result &= ~(0xffff << shift); - result |= (u16)(val << shift); - return write_config(swap, bus, devfn, where & ~3, size, - result); - - case 1: - status = read_config(swap, bus, devfn, where & ~3, 4, - &result); - if (status != PCIBIOS_SUCCESSFUL) return status; - - if (where & 2) - shift += 16; - if (where & 1) - shift += 8; - result &= ~(0xff << shift); - result |= (u8)(val << shift); - return write_config(swap, bus, devfn, where & ~3, size, - result); - } -} - -#define MAKE_PCI_OPS(prefix, rw, pciswap) \ -static int prefix##_##rw##_config(struct pci_bus *bus, unsigned int devfn, \ - int where, int size, u32 val) \ -{ \ - return rw##_config(pciswap, bus, devfn, \ - where, size, val); \ -} - -MAKE_PCI_OPS(extpci, read, &ext_pci_swap) -MAKE_PCI_OPS(extpci, write, &ext_pci_swap) - -MAKE_PCI_OPS(iopci, read, &io_pci_swap) -MAKE_PCI_OPS(iopci, write, &io_pci_swap) - -struct pci_ops ddb5477_ext_pci_ops ={ - .read = extpci_read_config, - .write = extpci_write_config, -}; - - -struct pci_ops ddb5477_io_pci_ops ={ - .read = iopci_read_config, - .write = iopci_write_config, -}; - -#if defined(CONFIG_LL_DEBUG) -void jsun_scan_pci_bus(void) -{ - struct pci_bus bus; - struct pci_dev dev; - unsigned int devfn; - int j; - - bus.parent = NULL; /* we scan the top level only */ - dev.bus = &bus; - dev.sysdata = NULL; - - /* scan ext pci bus and io pci bus*/ - for (j=0; j< 2; j++) { - if (j == 0) { - printk("scan ddb5477 external PCI bus:\n"); - bus.ops = &ddb5477_ext_pci_ops; - } else { - printk("scan ddb5477 IO PCI bus:\n"); - bus.ops = &ddb5477_io_pci_ops; - } - - for (devfn = 0; devfn < 0x100; devfn += 8) { - u32 temp; - u16 temp16; - u8 temp8; - int i; - - dev.devfn = devfn; - MIPS_VERIFY(pci_read_config_dword(&dev, 0, &temp), - == PCIBIOS_SUCCESSFUL); - if (temp == 0xffffffff) continue; - - printk("slot %d: (addr %d) \n", devfn/8, 11+devfn/8); - - /* verify read word and byte */ - MIPS_VERIFY(pci_read_config_word(&dev, 2, &temp16), - == PCIBIOS_SUCCESSFUL); - MIPS_ASSERT(temp16 == (temp >> 16)); - MIPS_VERIFY(pci_read_config_byte(&dev, 3, &temp8), - == PCIBIOS_SUCCESSFUL); - MIPS_ASSERT(temp8 == (temp >> 24)); - MIPS_VERIFY(pci_read_config_byte(&dev, 1, &temp8), - == PCIBIOS_SUCCESSFUL); - MIPS_ASSERT(temp8 == ((temp >> 8) & 0xff)); - - for (i=0; i < 16; i++) { - MIPS_VERIFY(pci_read_config_dword(&dev, i*4, &temp), - == PCIBIOS_SUCCESSFUL); - printk("\t%08X", temp); - if ((i%4) == 3) printk("\n"); - } - } - } -} - - -static void jsun_hardcode_pci_resources_eepro(void) -{ - struct pci_bus bus; - struct pci_dev dev; - u32 temp; - - bus.parent = NULL; /* we scan the top level only */ - bus.ops = &ddb5477_ext_pci_ops; - dev.bus = &bus; - dev.sysdata = NULL; - - /* for slot 5 (ext pci 1) eepro card */ - dev.devfn = 5*8; - pci_read_config_dword(&dev, 0, &temp); - MIPS_ASSERT(temp == 0x12298086); - - pci_write_config_dword(&dev, PCI_BASE_ADDRESS_0, DDB_PCI0_MEM_BASE); - pci_write_config_dword(&dev, PCI_BASE_ADDRESS_1, 0); - pci_write_config_dword(&dev, PCI_BASE_ADDRESS_2, DDB_PCI0_MEM_BASE+0x100000); - pci_write_config_dword(&dev, PCI_INTERRUPT_LINE, 17); -} - -static void jsun_hardcode_pci_resources_onboard_tulip(void) -{ - struct pci_bus bus; - struct pci_dev dev; - u32 temp; - - bus.parent = NULL; /* we scan the top level only */ - bus.ops = &ddb5477_ext_pci_ops; - dev.bus = &bus; - dev.sysdata = NULL; - - /* for slot 4 on board ether chip */ - dev.devfn = 4*8; - pci_read_config_dword(&dev, 0, &temp); - MIPS_ASSERT(temp == 0x00191011); - - pci_write_config_dword(&dev, PCI_BASE_ADDRESS_0, 0x1000); - pci_write_config_dword(&dev, PCI_BASE_ADDRESS_1, DDB_PCI0_MEM_BASE); - pci_write_config_dword(&dev, PCI_INTERRUPT_LINE, 16); -} - -static void jsun_hardcode_pci_resources(void) -{ - jsun_hardcode_pci_resources_onboard_tulip(); -} - -void jsun_assign_pci_resource(void) -{ - jsun_hardcode_pci_resources(); -} - -#endif diff -Nru a/arch/mips/ddb5xxx/ddb5477/setup.c b/arch/mips/ddb5xxx/ddb5477/setup.c --- a/arch/mips/ddb5xxx/ddb5477/setup.c Tue Jul 1 18:44:37 2003 +++ b/arch/mips/ddb5xxx/ddb5477/setup.c Tue Jul 1 18:44:37 2003 @@ -1,4 +1,4 @@ -/*********************************************************************** +/* * * Copyright 2001 MontaVista Software Inc. * Author: jsun@mvista.com or jsun@junsun.net @@ -10,14 +10,10 @@ * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. - * - *********************************************************************** */ - #include #include #include -#include #include #include #include @@ -26,29 +22,35 @@ #include #include #include /* for HZ */ +#include +#include #include +#include +#include #include #include #include #include #include #include +#include +#include +#ifdef CONFIG_PC_KEYB +#include +#endif #include +#include "lcd44780.h" #define USE_CPU_COUNTER_TIMER /* whether we use cpu counter */ -#ifdef USE_CPU_COUNTER_TIMER -#define CPU_COUNTER_FREQUENCY 83000000 -#else -/* otherwise we use special timer 1 */ -#define SP_TIMER_FREQUENCY 83000000 #define SP_TIMER_BASE DDB_SPT1CTRL_L -#define SP_TIMER_IRQ (8 + 6) -#endif +#define SP_TIMER_IRQ VRC5477_IRQ_SPT1 + +static int bus_frequency = CONFIG_DDB5477_BUS_FREQUENCY*1000; static void ddb_machine_restart(char *command) { @@ -61,7 +63,7 @@ /* CPU cold reset */ t = ddb_in32(DDB_CPUSTAT); - MIPS_ASSERT((t&1)); + db_assert((t&1)); ddb_out32(DDB_CPUSTAT, t); /* Call the PROM */ @@ -81,44 +83,89 @@ } extern void rtc_ds1386_init(unsigned long base); + +static unsigned int __init detect_bus_frequency(unsigned long rtc_base) +{ + unsigned int freq; + unsigned char c; + unsigned int t1, t2; + unsigned i; + + ddb_out32(SP_TIMER_BASE, 0xffffffff); + ddb_out32(SP_TIMER_BASE+4, 0x1); + ddb_out32(SP_TIMER_BASE+8, 0xffffffff); + + /* check if rtc is running */ + c= *(volatile unsigned char*)rtc_base; + for(i=0; (c == *(volatile unsigned char*)rtc_base) && (i<100000000); i++); + if (c == *(volatile unsigned char*)rtc_base) { + printk("Failed to detect bus frequency. Use default 83.3MHz.\n"); + return 83333000; + } + + c= *(volatile unsigned char*)rtc_base; + while (c == *(volatile unsigned char*)rtc_base); + /* we are now at the turn of 1/100th second, if no error. */ + t1 = ddb_in32(SP_TIMER_BASE+8); + + for (i=0; i< 10; i++) { + c= *(volatile unsigned char*)rtc_base; + while (c == *(volatile unsigned char*)rtc_base); + /* we are now at the turn of another 1/100th second */ + t2 = ddb_in32(SP_TIMER_BASE+8); + } + + ddb_out32(SP_TIMER_BASE+4, 0x0); /* disable it again */ + + freq = (t1 - t2)*10; + printk("DDB bus frequency detection : %u \n", freq); + return freq; +} + static void __init ddb_time_init(void) { -#if defined(USE_CPU_COUNTER_TIMER) - mips_counter_frequency = CPU_COUNTER_FREQUENCY; -#endif + unsigned long rtc_base; + unsigned int i; /* we have ds1396 RTC chip */ - rtc_ds1386_init(KSEG1ADDR(DDB_LCS1_BASE)); + if (mips_machtype == MACH_NEC_ROCKHOPPER + || mips_machtype == MACH_NEC_ROCKHOPPERII) { + rtc_base = KSEG1ADDR(DDB_LCS2_BASE); + } else { + rtc_base = KSEG1ADDR(DDB_LCS1_BASE); + } + rtc_ds1386_init(rtc_base); + + /* do we need to do run-time detection of bus speed? */ + if (bus_frequency == 0) { + bus_frequency = detect_bus_frequency(rtc_base); + } + + /* mips_counter_frequency is 1/2 of the cpu core freq */ + i = (read_32bit_cp0_register(CP0_CONFIG) >> 28 ) & 7; + if ((current_cpu_data.cputype == CPU_R5432) && (i == 3)) + i = 4; + mips_counter_frequency = bus_frequency*(i+4)/4; } -#if defined(CONFIG_LL_DEBUG) -int board_init_done_flag = 0; -#endif - extern int setup_irq(unsigned int irq, struct irqaction *irqaction); + static void __init ddb_timer_setup(struct irqaction *irq) { #if defined(USE_CPU_COUNTER_TIMER) unsigned int count; /* we are using the cpu counter for timer interrupts */ - setup_irq(7, irq); - - /* to generate the first timer interrupt */ - count = read_32bit_cp0_register(CP0_COUNT); - write_32bit_cp0_register(CP0_COMPARE, count + 1000); + setup_irq(CPU_IRQ_BASE + 7, irq); #else - /* if we don't use Special purpose timer 1 */ - ddb_out32(SP_TIMER_BASE, SP_TIMER_FREQUENCY/HZ); + /* if we use Special purpose timer 1 */ + ddb_out32(SP_TIMER_BASE, bus_frequency/HZ); ddb_out32(SP_TIMER_BASE+4, 0x1); setup_irq(SP_TIMER_IRQ, irq); #endif - - /* this is the last board dependent code */ - MIPS_DEBUG(board_init_done_flag = 1); } static void ddb5477_board_init(void); @@ -126,14 +173,20 @@ #if defined(CONFIG_BLK_DEV_INITRD) extern unsigned long __rd_start, __rd_end, initrd_start, initrd_end; -#endif +#endif void __init ddb_setup(void) { extern int panic_timeout; +#ifdef CONFIG_BLK_DEV_IDE + extern struct ide_ops std_ide_ops; +#endif + + /* initialize board - we don't trust the loader */ + ddb5477_board_init(); irq_setup = ddb5477_irq_setup; - mips_io_port_base = KSEG1ADDR(DDB_PCI_IO_BASE); + set_io_port_base(KSEG1ADDR(DDB_PCI_IO_BASE)); board_time_init = ddb_time_init; board_timer_setup = ddb_timer_setup; @@ -145,47 +198,69 @@ /* setup resource limits */ ioport_resource.end = DDB_PCI0_IO_SIZE + DDB_PCI1_IO_SIZE - 1; iomem_resource.end = 0xffffffff; - + /* Reboot on panic */ panic_timeout = 180; - /* initialize board - we don't trust the loader */ - ddb5477_board_init(); +#ifdef CONFIG_BLK_DEV_IDE + ide_ops = &std_ide_ops; +#endif + + +#ifdef CONFIG_FB + conswitchp = &dummy_con; +#endif #if defined(CONFIG_BLK_DEV_INITRD) ROOT_DEV = Root_RAM0; initrd_start = (unsigned long)&__rd_start; initrd_end = (unsigned long)&__rd_end; #endif - } -static void __init ddb5477_board_init() +static void __init ddb5477_board_init(void) { +#ifdef CONFIG_PC_KEYB + extern struct kbd_ops std_kbd_ops; +#endif /* ----------- setup PDARs ------------ */ /* SDRAM should have been set */ - MIPS_ASSERT(ddb_in32(DDB_SDRAM0) == - ddb_calc_pdar(DDB_SDRAM_BASE, DDB_SDRAM_SIZE, 32, 0, 1)); + db_assert(ddb_in32(DDB_SDRAM0) == + ddb_calc_pdar(DDB_SDRAM_BASE, board_ram_size, 32, 0, 1)); /* SDRAM1 should be turned off. What is this for anyway ? */ - MIPS_ASSERT( (ddb_in32(DDB_SDRAM1) & 0xf) == 0); + db_assert( (ddb_in32(DDB_SDRAM1) & 0xf) == 0); - /* Set LDCSs */ - /* flash */ + /* Setup local bus. */ + + /* Flash U12 PDAR and timing. */ ddb_set_pdar(DDB_LCS0, DDB_LCS0_BASE, DDB_LCS0_SIZE, 16, 0, 0); - /* misc */ - ddb_set_pdar(DDB_LCS1, DDB_LCS1_BASE, DDB_LCS1_SIZE, 8, 0, 0); - /* mezzanie (?) */ - ddb_set_pdar(DDB_LCS2, DDB_LCS2_BASE, DDB_LCS2_SIZE, 16, 0, 0); + ddb_out32(DDB_LCST0, 0x00090842); + + /* We need to setup LCS1 and LCS2 differently based on the + board_version */ + if (mips_machtype == MACH_NEC_ROCKHOPPER) { + /* Flash U13 PDAR and timing. */ + ddb_set_pdar(DDB_LCS1, DDB_LCS1_BASE, DDB_LCS1_SIZE, 16, 0, 0); + ddb_out32(DDB_LCST1, 0x00090842); + + /* EPLD (NVRAM, switch, LCD, and mezzanie). */ + ddb_set_pdar(DDB_LCS2, DDB_LCS2_BASE, DDB_LCS2_SIZE, 8, 0, 0); + } else { + /* misc */ + ddb_set_pdar(DDB_LCS1, DDB_LCS1_BASE, DDB_LCS1_SIZE, 8, 0, 0); + /* mezzanie (?) */ + ddb_set_pdar(DDB_LCS2, DDB_LCS2_BASE, DDB_LCS2_SIZE, 16, 0, 0); + } /* verify VRC5477 base addr */ - MIPS_ASSERT(ddb_in32(DDB_VRC5477) == - ddb_calc_pdar(DDB_VRC5477_BASE, DDB_VRC5477_SIZE, 32, 0, 1)); - + db_assert(ddb_in32(DDB_VRC5477) == + ddb_calc_pdar(DDB_VRC5477_BASE, DDB_VRC5477_SIZE, 32, 0, 1)); + /* verify BOOT ROM addr */ - MIPS_ASSERT(ddb_in32(DDB_BOOTCS) == - ddb_calc_pdar(DDB_BOOTCS_BASE, DDB_BOOTCS_SIZE, 8, 0, 0)); + db_assert(ddb_in32(DDB_BOOTCS) == + ddb_calc_pdar(DDB_BOOTCS_BASE, DDB_BOOTCS_SIZE, 8, 0, 0)); /* setup PCI windows - window0 for MEM/config, window1 for IO */ ddb_set_pdar(DDB_PCIW0, DDB_PCI0_MEM_BASE, DDB_PCI0_MEM_SIZE, 32, 0, 1); @@ -219,7 +294,7 @@ ddb_out32(DDB_BAR51, 0xffffffff); ddb_out32(DDB_BARB1, 0xffffffff); - /* + /* * We use pci master register 0 for memory space / config space * And we use register 1 for IO space. * Note that for memory space, we bump up the pci base address @@ -227,26 +302,133 @@ * For PCI IO space, it starts from 0 in PCI IO space but with * DDB_xx_IO_BASE in CPU physical address space. */ - ddb_set_pmr(DDB_PCIINIT00, DDB_PCICMD_MEM, DDB_PCI0_MEM_BASE, + ddb_set_pmr(DDB_PCIINIT00, DDB_PCICMD_MEM, DDB_PCI0_MEM_BASE, DDB_PCI_ACCESS_32); ddb_set_pmr(DDB_PCIINIT10, DDB_PCICMD_IO, 0, DDB_PCI_ACCESS_32); - ddb_set_pmr(DDB_PCIINIT01, DDB_PCICMD_MEM, DDB_PCI1_MEM_BASE, + ddb_set_pmr(DDB_PCIINIT01, DDB_PCICMD_MEM, DDB_PCI1_MEM_BASE, DDB_PCI_ACCESS_32); - ddb_set_pmr(DDB_PCIINIT11, DDB_PCICMD_IO, DDB_PCI0_IO_SIZE, + ddb_set_pmr(DDB_PCIINIT11, DDB_PCICMD_IO, DDB_PCI0_IO_SIZE, DDB_PCI_ACCESS_32); - + /* PCI cross window should be set properly */ ddb_set_pdar(DDB_BARP00, DDB_PCI1_MEM_BASE, DDB_PCI1_MEM_SIZE, 32, 0, 1); ddb_set_pdar(DDB_BARP10, DDB_PCI1_IO_BASE, DDB_PCI1_IO_SIZE, 32, 0, 1); ddb_set_pdar(DDB_BARP01, DDB_PCI0_MEM_BASE, DDB_PCI0_MEM_SIZE, 32, 0, 1); ddb_set_pdar(DDB_BARP11, DDB_PCI0_IO_BASE, DDB_PCI0_IO_SIZE, 32, 0, 1); + if (mips_machtype == MACH_NEC_ROCKHOPPER + || mips_machtype == MACH_NEC_ROCKHOPPERII) { + /* Disable bus diagnostics. */ + ddb_out32(DDB_PCICTL0_L, 0); + ddb_out32(DDB_PCICTL0_H, 0); + ddb_out32(DDB_PCICTL1_L, 0); + ddb_out32(DDB_PCICTL1_H, 0); + } + + if (mips_machtype == MACH_NEC_ROCKHOPPER) { + u16 vid; + struct pci_bus bus; + struct pci_dev dev_m1533; + extern struct pci_ops ddb5477_ext_pci_ops; + + bus.parent = NULL; /* we scan the top level only */ + bus.ops = &ddb5477_ext_pci_ops; + dev_m1533.bus = &bus; + dev_m1533.sysdata = NULL; + dev_m1533.devfn = 7*8; // slot 7: M1533 SouthBridge. + pci_read_config_word(&dev_m1533, 0, &vid); + if (vid == PCI_VENDOR_ID_AL) { + printk("Changing mips_machtype to MACH_NEC_ROCKHOPPERII\n"); + mips_machtype = MACH_NEC_ROCKHOPPERII; + } + } + /* enable USB input buffers */ ddb_out32(DDB_PIBMISC, 0x00000007); /* For dual-function pins, make them all non-GPIO */ ddb_out32(DDB_GIUFUNSEL, 0x0); // ddb_out32(DDB_GIUFUNSEL, 0xfe0fcfff); /* NEC recommanded value */ + + if (mips_machtype == MACH_NEC_ROCKHOPPERII) { +#ifdef CONFIG_PC_KEYB + printk("kdb_ops is std\n"); + kbd_ops = &std_kbd_ops; +#endif + } + + if (mips_machtype == MACH_NEC_ROCKHOPPERII) { + + /* enable IDE controller on Ali chip (south bridge) */ + u8 temp8; + struct pci_bus bus; + struct pci_dev dev_m1533; + struct pci_dev dev_m5229; + extern struct pci_ops ddb5477_ext_pci_ops; + + /* Setup M1535 registers */ + bus.parent = NULL; /* we scan the top level only */ + bus.ops = &ddb5477_ext_pci_ops; + dev_m1533.bus = &bus; + dev_m1533.sysdata = NULL; + dev_m1533.devfn = 7*8; // slot 7: M1533 SouthBridge. + + /* setup IDE controller + * enable IDE controller (bit 6 - 1) + * IDE IDSEL to be addr:A15 (bit 4:5 - 11) + * disable IDE ATA Secondary Bus Signal Pad Control (bit 3 - 0) + * enable IDE ATA Primary Bus Signal Pad Control (bit 2 - 1) + */ + pci_write_config_byte(&dev_m1533, 0x58, 0x74); + + /* + * positive decode (bit6 -0) + * enable IDE controler interrupt (bit 4 -1) + * setup SIRQ to point to IRQ 14 (bit 3:0 - 1101) + */ + pci_write_config_byte(&dev_m1533, 0x44, 0x1d); + + /* Setup M5229 registers */ + dev_m5229.bus = &bus; + dev_m5229.sysdata = NULL; + dev_m5229.devfn = 4*8; // slot 4 (AD15): M5229 IDE + + /* + * enable IDE in the M5229 config register 0x50 (bit 0 - 1) + * M5229 IDSEL is addr:15; see above setting + */ + pci_read_config_byte(&dev_m5229, 0x50, &temp8); + pci_write_config_byte(&dev_m5229, 0x50, temp8 | 0x1); + + /* + * enable bus master (bit 2) and IO decoding (bit 0) + */ + pci_read_config_byte(&dev_m5229, 0x04, &temp8); + pci_write_config_byte(&dev_m5229, 0x04, temp8 | 0x5); + + /* + * enable native, copied from arch/ppc/k2boot/head.S + * TODO - need volatile, need to be portable + */ + pci_write_config_byte(&dev_m5229, 0x09, 0xef); + + /* Set Primary Channel Command Block Timing */ + pci_write_config_byte(&dev_m5229, 0x59, 0x31); + + /* + * Enable primary channel 40-pin cable + * M5229 register 0x4a (bit 0) + */ + pci_read_config_byte(&dev_m5229, 0x4a, &temp8); + pci_write_config_byte(&dev_m5229, 0x4a, temp8 | 0x1); + } + + if (mips_machtype == MACH_NEC_ROCKHOPPER + || mips_machtype == MACH_NEC_ROCKHOPPERII) { + printk("lcd44780: initializing\n"); + lcd44780_init(); + lcd44780_puts("MontaVista Linux"); + } } diff -Nru a/arch/mips/dec/Makefile b/arch/mips/dec/Makefile --- a/arch/mips/dec/Makefile Tue Jul 1 18:44:34 2003 +++ b/arch/mips/dec/Makefile Tue Jul 1 18:44:34 2003 @@ -2,6 +2,10 @@ # Makefile for the DECstation family specific parts of the kernel # -obj-y := int-handler.o setup.o irq.o time.o reset.o rtc-dec.o wbflush.o +obj-y := ecc-berr.o int-handler.o ioasic-irq.o kn02-irq.o reset.o \ + rtc-dec.o setup.o time.o obj-$(CONFIG_PROM_CONSOLE) += promcon.o +obj-$(CONFIG_CPU_HAS_WB) += wbflush.o + +EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips/dec/boot/Makefile b/arch/mips/dec/boot/Makefile --- a/arch/mips/dec/boot/Makefile Tue Jul 1 18:44:35 2003 +++ b/arch/mips/dec/boot/Makefile Tue Jul 1 18:44:35 2003 @@ -3,8 +3,8 @@ # netboot: all - mipsel-linux-ld -N -G 0 -T ld.ecoff ../../boot/zImage \ - built-in.o ramdisk.img -o nbImage + $(LD) -N -G 0 -T ld.ecoff ../../boot/zImage \ + dec_boot.o ramdisk.img -o nbImage obj-y := decstation.o diff -Nru a/arch/mips/dec/ecc-berr.c b/arch/mips/dec/ecc-berr.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/dec/ecc-berr.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,280 @@ +/* + * linux/arch/mips/dec/ecc-berr.c + * + * Bus error event handling code for systems equipped with ECC + * handling logic, i.e. DECstation/DECsystem 5000/200 (KN02), + * 5000/240 (KN03), 5000/260 (KN05) and DECsystem 5900 (KN03), + * 5900/260 (KN05) systems. + * + * Copyright (c) 2003 Maciej W. Rozycki + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static volatile u32 *kn0x_erraddr; +static volatile u32 *kn0x_chksyn; + +static inline void dec_ecc_be_ack(void) +{ + *kn0x_erraddr = 0; /* any write clears the IRQ */ + iob(); +} + +static int dec_ecc_be_backend(struct pt_regs *regs, int is_fixup, int invoker) +{ + static const char excstr[] = "exception"; + static const char intstr[] = "interrupt"; + static const char cpustr[] = "CPU"; + static const char dmastr[] = "DMA"; + static const char readstr[] = "read"; + static const char mreadstr[] = "memory read"; + static const char writestr[] = "write"; + static const char mwritstr[] = "partial memory write"; + static const char timestr[] = "timeout"; + static const char overstr[] = "overrun"; + static const char eccstr[] = "ECC error"; + + const char *kind, *agent, *cycle, *event; + const char *status = "", *xbit = "", *fmt = ""; + dma_addr_t address; + u16 syn = 0, sngl; + + int i = 0; + + u32 erraddr = *kn0x_erraddr; + u32 chksyn = *kn0x_chksyn; + int action = MIPS_BE_FATAL; + + /* For non-ECC ack ASAP, so any subsequent errors get caught. */ + if ((erraddr & (KN0X_EAR_VALID | KN0X_EAR_ECCERR)) == KN0X_EAR_VALID) + dec_ecc_be_ack(); + + kind = invoker ? intstr : excstr; + + if (!(erraddr & KN0X_EAR_VALID)) { + /* No idea what happened. */ + printk(KERN_ALERT "Unindentified bus error %s.\n", kind); + return action; + } + + agent = (erraddr & KN0X_EAR_CPU) ? cpustr : dmastr; + + if (erraddr & KN0X_EAR_ECCERR) { + /* An ECC error on a CPU or DMA transaction. */ + cycle = (erraddr & KN0X_EAR_WRITE) ? mwritstr : mreadstr; + event = eccstr; + } else { + /* A CPU timeout or a DMA overrun. */ + cycle = (erraddr & KN0X_EAR_WRITE) ? writestr : readstr; + event = (erraddr & KN0X_EAR_CPU) ? timestr : overstr; + } + + address = erraddr & KN0X_EAR_ADDRESS; + /* For ECC errors on reads adjust for MT pipelining. */ + if ((erraddr & (KN0X_EAR_WRITE | KN0X_EAR_ECCERR)) == KN0X_EAR_ECCERR) + address = (address & ~0xfffLL) | ((address - 5) & 0xfffLL); + address <<= 2; + + /* Only CPU errors are fixable. */ + if (erraddr & KN0X_EAR_CPU && is_fixup) + action = MIPS_BE_FIXUP; + + if (erraddr & KN0X_EAR_ECCERR) { + static const u8 data_sbit[32] = { + 0x4f, 0x4a, 0x52, 0x54, 0x57, 0x58, 0x5b, 0x5d, + 0x23, 0x25, 0x26, 0x29, 0x2a, 0x2c, 0x31, 0x34, + 0x0e, 0x0b, 0x13, 0x15, 0x16, 0x19, 0x1a, 0x1c, + 0x62, 0x64, 0x67, 0x68, 0x6b, 0x6d, 0x70, 0x75, + }; + static const u8 data_mbit[25] = { + 0x07, 0x0d, 0x1f, + 0x2f, 0x32, 0x37, 0x38, 0x3b, 0x3d, 0x3e, + 0x43, 0x45, 0x46, 0x49, 0x4c, 0x51, 0x5e, + 0x61, 0x6e, 0x73, 0x76, 0x79, 0x7a, 0x7c, 0x7f, + }; + static const char sbestr[] = "corrected single"; + static const char dbestr[] = "uncorrectable double"; + static const char mbestr[] = "uncorrectable multiple"; + + if (!(address & 0x4)) + syn = chksyn; /* Low bank. */ + else + syn = chksyn >> 16; /* High bank. */ + + if (!(syn & KN0X_ESR_VLDLO)) { + /* Ack now, no rewrite will happen. */ + dec_ecc_be_ack(); + + fmt = KERN_ALERT "%s" "invalid.\n"; + } else { + sngl = syn & KN0X_ESR_SNGLO; + syn &= KN0X_ESR_SYNLO; + + /* + * Multibit errors may be tagged incorrectly; + * check the syndrome explicitly. + */ + for (i = 0; i < 25; i++) + if (syn == data_mbit[i]) + break; + + if (i < 25) { + status = mbestr; + } else if (!sngl) { + status = dbestr; + } else { + volatile u32 *ptr = (void *)KSEG1ADDR(address); + + *ptr = *ptr; /* Rewrite. */ + iob(); + + status = sbestr; + action = MIPS_BE_DISCARD; + } + + /* Ack now, now we've rewritten (or not). */ + dec_ecc_be_ack(); + + if (syn && syn == (syn & -syn)) { + if (syn == 0x01) { + fmt = KERN_ALERT "%s" + "%#04x -- %s bit error " + "at check bit C%s.\n"; + xbit = "X"; + } else { + fmt = KERN_ALERT "%s" + "%#04x -- %s bit error " + "at check bit C%s%u.\n"; + } + i = syn >> 2; + } else { + for (i = 0; i < 32; i++) + if (syn == data_sbit[i]) + break; + if (i < 32) + fmt = KERN_ALERT "%s" + "%#04x -- %s bit error " + "at data bit D%s%u.\n"; + else + fmt = KERN_ALERT "%s" + "%#04x -- %s bit error.\n"; + } + } + } + + if (action != MIPS_BE_FIXUP) + printk(KERN_ALERT "Bus error %s: %s %s %s at %#010lx.\n", + kind, agent, cycle, event, address); + + if (action != MIPS_BE_FIXUP && erraddr & KN0X_EAR_ECCERR) + printk(fmt, " ECC syndrome ", syn, status, xbit, i); + + return action; +} + +int dec_ecc_be_handler(struct pt_regs *regs, int is_fixup) +{ + return dec_ecc_be_backend(regs, is_fixup, 0); +} + +void dec_ecc_be_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + int action = dec_ecc_be_backend(regs, 0, 1); + + if (action == MIPS_BE_DISCARD) + return; + + /* + * FIXME: Find affected processes and kill them, otherwise we + * must die. + * + * The interrupt is asynchronously delivered thus EPC and RA + * may be irrelevant, but are printed for a reference. + */ + printk(KERN_ALERT "Fatal bus interrupt, epc == %08lx, ra == %08lx\n", + regs->cp0_epc, regs->regs[31]); + die("Unrecoverable bus error", regs); +} + + +/* + * Initialization differs a bit between KN02 and KN03/KN05, so we + * need two variants. Once set up, all systems can be handled the + * same way. + */ +static inline void dec_kn02_be_init(void) +{ + volatile u32 *csr = (void *)KN02_CSR_BASE; + unsigned long flags; + + kn0x_erraddr = (void *)(KN02_SLOT_BASE + KN02_ERRADDR); + kn0x_chksyn = (void *)(KN02_SLOT_BASE + KN02_CHKSYN); + + spin_lock_irqsave(&kn02_lock, flags); + + /* Preset write-only bits of the Control Register cache. */ + cached_kn02_csr = *csr | KN03_CSR_LEDS; + + /* Set normal ECC detection and generation. */ + cached_kn02_csr &= ~(KN02_CSR_DIAGCHK | KN02_CSR_DIAGGEN); + /* Enable ECC correction. */ + cached_kn02_csr |= KN02_CSR_CORRECT; + *csr = cached_kn02_csr; + iob(); + + spin_unlock_irqrestore(&kn02_lock, flags); +} + +static inline void dec_kn03_be_init(void) +{ + volatile u32 *mcr = (void *)(KN03_SLOT_BASE + IOASIC_MCR); + volatile u32 *mbcs = (void *)(KN03_SLOT_BASE + KN05_MB_CSR); + + kn0x_erraddr = (void *)(KN03_SLOT_BASE + IOASIC_ERRADDR); + kn0x_chksyn = (void *)(KN03_SLOT_BASE + IOASIC_CHKSYN); + + /* + * Set normal ECC detection and generation, enable ECC correction. + * For KN05 we also need to make sure EE (?) is enabled in the MB. + * Otherwise DBE/IBE exceptions would be masked but bus error + * interrupts would still arrive, resulting in an inevitable crash + * if get_dbe() triggers one. + */ + *mcr = (*mcr & ~(KN03_MCR_DIAGCHK | KN03_MCR_DIAGGEN)) | + KN03_MCR_CORRECT; + if (current_cpu_data.cputype == CPU_R4400SC) + *mbcs |= KN05_MB_CSR_EE; + fast_iob(); +} + +void __init dec_ecc_be_init(void) +{ + if (mips_machtype == MACH_DS5000_200) + dec_kn02_be_init(); + else + dec_kn03_be_init(); + + /* Clear any leftover errors from the firmware. */ + dec_ecc_be_ack(); +} diff -Nru a/arch/mips/dec/int-handler.S b/arch/mips/dec/int-handler.S --- a/arch/mips/dec/int-handler.S Tue Jul 1 18:44:36 2003 +++ b/arch/mips/dec/int-handler.S Tue Jul 1 18:44:36 2003 @@ -2,7 +2,7 @@ * arch/mips/dec/int-handler.S * * Copyright (C) 1995, 1996, 1997 Paul M. Antoine and Harald Koerfgen - * Copyright (C) 2000 Maciej W. Rozycki + * Copyright (C) 2000, 2001, 2002, 2003 Maciej W. Rozycki * * Written by Ralf Baechle and Andreas Busse, modified for DECStation * support by Paul Antoine and Harald Koerfgen. @@ -10,6 +10,8 @@ * completly rewritten: * Copyright (C) 1998 Harald Koerfgen * + * Rewritten extensively for controller-driven IRQ support + * by Maciej W. Rozycki. */ #include #include @@ -17,12 +19,13 @@ #include #include +#include +#include +#include #include #include #include #include -#include -#include .text @@ -84,7 +87,7 @@ * 4 TurboChannel Slot 2 * 5 TurboChannel Slot 3 (ASIC) * 6 Halt button - * 7 FPU + * 7 FPU/R4k timer * * DS5000/2x's, aka kn02ca, aka maxine: * @@ -97,7 +100,7 @@ * 4 I/O write timeout * 5 TurboChannel (ASIC) * 6 Halt Keycode from Access.Bus keyboard (CTRL-ALT-ENTER) - * 7 FPU + * 7 FPU/R4k timer * * DS5000/2xx's, aka kn03, aka 3maxplus: * @@ -110,22 +113,11 @@ * 4 Reserved * 5 Memory * 6 Halt Button - * 7 FPU - * - * We handle the IRQ according to _our_ priority. - * Priority is: - * - * Highest ---- RTC - * SCSI (if separate from TC) - * Ethernet (if separate from TC) - * Serial (if separate from TC) - * TurboChannel (if there is one!) - * Memory Controller (execept kmin) - * Lowest ---- Halt (if there is one!) - * - * then we just return, if multiple IRQs are pending then we will just take - * another exception, big deal. + * 7 FPU/R4k timer * + * We handle the IRQ according to _our_ priority (see setup.c), + * then we just return. If multiple IRQs are pending then we will + * just take another exception, big deal. */ .align 5 NESTED(decstation_handle_int, PT_SIZE, ra) @@ -139,226 +131,166 @@ * Get pending Interrupts */ mfc0 t0,CP0_CAUSE # get pending interrupts - mfc0 t2,CP0_STATUS - la t1,cpu_mask_tbl - and t0,t2 # isolate allowed ones + mfc0 t1,CP0_STATUS +#ifdef CONFIG_MIPS32 + lw t2,cpu_fpu_mask +#endif + andi t0,ST0_IM # CAUSE.CE may be non-zero! + and t0,t1 # isolate allowed ones beqz t0,spurious +#ifdef CONFIG_MIPS32 + and t2,t0 + bnez t2,fpu # handle FPU immediately +#endif + /* * Find irq with highest priority */ -1: lw t2,(t1) - move t3,t0 - and t3,t2 - beq t3,zero,1b - addu t1,PTRSIZE # delay slot + PTR_LA t1,cpu_mask_nr_tbl +1: lw t2,(t1) + nop + and t2,t0 + beqz t2,1b + addu t1,2*PTRSIZE # delay slot /* * Do the low-level stuff */ - lw a0,%lo(cpu_irq_nr-cpu_mask_tbl-PTRSIZE)(t1) - lw t0,%lo(cpu_ivec_tbl-cpu_mask_tbl-PTRSIZE)(t1) - bgez a0, handle_it # irq_nr >= 0? - # irq_nr < 0: t0 contains an address + lw a0,(-PTRSIZE)(t1) + nop + bgez a0,handle_it # irq_nr >= 0? + # irq_nr < 0: it is an address nop - jr t0 - nop # delay slot + jr a0 + # a trick to save a branch: + lui t2,(KN03_IOASIC_BASE>>16)&0xffff + # upper part of IOASIC Address /* * Handle "IRQ Controller" Interrupts * Masked Interrupts are still visible and have to be masked "by hand". */ - EXPORT(kn02_io_int) -kn02_io_int: # 3max - lui t0,KN02_CSR_ADDR>>16 # get interrupt status and mask + FEXPORT(kn02_io_int) # 3max + lui t0,(KN02_CSR_BASE>>16)&0xffff + # get interrupt status and mask lw t0,(t0) - la t1,asic_mask_tbl - move t3,t0 - sll t3,16 # shift interrupt status - b find_int - and t0,t3 # mask out allowed ones - - EXPORT(kn03_io_int) -kn03_io_int: # 3max+ - lui t2,KN03_IOASIC_BASE>>16 # upper part of IOASIC Address - lw t0,SIR(t2) # get status: IOASIC isr - lw t3,SIMR(t2) # get mask: IOASIC isrm - la t1,asic_mask_tbl - b find_int - and t0,t3 # mask out allowed ones - - EXPORT(kn02xa_io_int) -kn02xa_io_int: # 3min/maxine - lui t2,KN02XA_IOASIC_BASE>>16 + nop + andi t1,t0,KN02_IRQ_ALL + b 1f + srl t0,16 # shift interrupt mask + + FEXPORT(kn02xa_io_int) # 3min/maxine + lui t2,(KN02XA_IOASIC_BASE>>16)&0xffff # upper part of IOASIC Address - lw t0,SIR(t2) # get status: IOASIC isr - lw t3,SIMR(t2) # get mask: IOASIC isrm - la t1,asic_mask_tbl - and t0,t3 + + FEXPORT(kn03_io_int) # 3max+ (t2 loaded earlier) + lw t0,IO_REG_SIR(t2) # get status: IOASIC sir + lw t1,IO_REG_SIMR(t2) # get mask: IOASIC simr + nop + +1: and t0,t1 # mask out allowed ones + + beqz t0,spurious /* * Find irq with highest priority */ -find_int: beqz t0,spurious - -1: lw t2,(t1) - move t3,t0 - and t3,t2 - beq zero,t3,1b - addu t1,PTRSIZE # delay slot + PTR_LA t1,asic_mask_nr_tbl +2: lw t2,(t1) + nop + and t2,t0 + beq zero,t2,2b + addu t1,2*PTRSIZE # delay slot /* * Do the low-level stuff */ - lw a0,%lo(asic_irq_nr-asic_mask_tbl-PTRSIZE)(t1) - nop + lw a0,%lo(-PTRSIZE)(t1) + nop + bgez a0,handle_it # irq_nr >= 0? + # irq_nr < 0: it is an address + nop + jr a0 + nop # delay slot + +/* + * Dispatch low-priority interrupts. We reconsider all status + * bits again, which looks like a lose, but it makes the code + * simple and O(log n), so it gets compensated. + */ + FEXPORT(cpu_all_int) # HALT, timers, software junk + li a0,DEC_CPU_IRQ_BASE + srl t0,CAUSEB_IP + li t1,CAUSEF_IP>>CAUSEB_IP # mask + b 1f + li t2,4 # nr of bits / 2 + + FEXPORT(kn02_all_int) # impossible ? + li a0,KN02_IRQ_BASE + li t1,KN02_IRQ_ALL # mask + b 1f + li t2,4 # nr of bits / 2 + + FEXPORT(asic_all_int) # various I/O ASIC junk + li a0,IO_IRQ_BASE + li t1,IO_IRQ_ALL # mask + b 1f + li t2,8 # nr of bits / 2 + +/* + * Dispatch DMA interrupts -- O(log n). + */ + FEXPORT(asic_dma_int) # I/O ASIC DMA events + li a0,IO_IRQ_BASE+IO_INR_DMA + srl t0,IO_INR_DMA + li t1,IO_IRQ_DMA>>IO_INR_DMA # mask + li t2,8 # nr of bits / 2 + + /* + * Find irq with highest priority. + * Highest irq number takes precedence. + */ +1: srlv t3,t1,t2 +2: xor t1,t3 + and t3,t0,t1 + beqz t3,3f + nop + move t0,t3 + addu a0,t2 +3: srl t2,1 + bnez t2,2b + srlv t3,t1,t2 -handle_it: jal do_IRQ +handle_it: + jal do_IRQ move a1,sp + j ret_from_irq nop +#ifdef CONFIG_MIPS32 +fpu: + j handle_fpe_int + nop +#endif + spurious: j spurious_interrupt nop END(decstation_handle_int) -/* - * Interrupt routines common to all DECStations first. - */ - EXPORT(dec_intr_fpu) -dec_intr_fpu: PANIC("Unimplemented FPU interrupt handler") /* - * Generic unimplemented interrupt routines - ivec_tbl is initialised to - * point all interrupts here. The table is then filled in by machine-specific - * initialisation in dec_setup(). + * Generic unimplemented interrupt routines -- cpu_mask_nr_tbl + * and asic_mask_nr_tbl are initialized to point all interrupts here. + * The tables are then filled in by machine-specific initialisation + * in dec_setup(). */ - EXPORT(dec_intr_unimplemented) -dec_intr_unimplemented: - mfc0 a1,CP0_CAUSE # cheats way of printing an arg! - nop # to be sure... - PANIC("Unimplemented cpu interrupt! CP0_CAUSE: 0x%x"); - - EXPORT(asic_intr_unimplemented) -asic_intr_unimplemented: + FEXPORT(dec_intr_unimplemented) move a1,t0 # cheats way of printing an arg! - PANIC("Unimplemented asic interrupt! ASIC ISR: 0x%x"); + PANIC("Unimplemented cpu interrupt! CP0_CAUSE: 0x%08x"); -/* - * FIXME: This interrupt vector table is experimental. It is initialised with - * *_intr_unimplemented and filled in with the addresses of - * machine-specific interrupt routines in dec_setup() Paul 10/5/97. - * - * The mask_tbls contain the interrupt masks which are used. It is - * initialised with all possible interrupt status bits set, so that - * unused Interrupts are catched. Harald - */ - .data - EXPORT(cpu_mask_tbl) -cpu_mask_tbl: - .word 0x00000000 - .word 0x00000000 - .word 0x00000000 - .word 0x00000000 - .word 0x00000000 - .word 0x00000000 - .word 0x00000000 # these two are unlikely - .word 0x00000000 # to be used - .word 0x0000ff00 # End of list - - EXPORT(cpu_irq_nr) -cpu_irq_nr: - .word 0x00000000 - .word 0x00000000 - .word 0x00000000 - .word 0x00000000 - .word 0x00000000 - .word 0x00000000 - .word 0x00000000 # these two are unlikely - .word 0x00000000 # to be used - .word 0x00ffffff # End of list - - EXPORT(cpu_ivec_tbl) -cpu_ivec_tbl: - PTR dec_intr_unimplemented - PTR dec_intr_unimplemented - PTR dec_intr_unimplemented - PTR dec_intr_unimplemented - PTR dec_intr_unimplemented - PTR dec_intr_unimplemented - PTR dec_intr_unimplemented # these two are unlikely - PTR dec_intr_unimplemented # to be used - PTR dec_intr_unimplemented # EOL - - EXPORT(asic_mask_tbl) -asic_mask_tbl: - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0xffffffff # EOL - - EXPORT(asic_irq_nr) -asic_irq_nr: - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0 - .word 0xffffffff # EOL + FEXPORT(asic_intr_unimplemented) + move a1,t0 # cheats way of printing an arg! + PANIC("Unimplemented asic interrupt! ASIC ISR: 0x%08x"); diff -Nru a/arch/mips/dec/ioasic-irq.c b/arch/mips/dec/ioasic-irq.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/dec/ioasic-irq.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,157 @@ +/* + * linux/arch/mips/dec/ioasic-irq.c + * + * DEC I/O ASIC interrupts. + * + * Copyright (c) 2002, 2003 Maciej W. Rozycki + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include + +#include +#include +#include + + +static spinlock_t ioasic_lock = SPIN_LOCK_UNLOCKED; + +static int ioasic_irq_base; + + +static inline void unmask_ioasic_irq(unsigned int irq) +{ + u32 simr; + + simr = ioasic_read(IO_REG_SIMR); + simr |= (1 << (irq - ioasic_irq_base)); + ioasic_write(IO_REG_SIMR, simr); +} + +static inline void mask_ioasic_irq(unsigned int irq) +{ + u32 simr; + + simr = ioasic_read(IO_REG_SIMR); + simr &= ~(1 << (irq - ioasic_irq_base)); + ioasic_write(IO_REG_SIMR, simr); +} + +static inline void clear_ioasic_irq(unsigned int irq) +{ + u32 sir; + + sir = ~(1 << (irq - ioasic_irq_base)); + ioasic_write(IO_REG_SIR, sir); +} + +static inline void enable_ioasic_irq(unsigned int irq) +{ + unsigned long flags; + + spin_lock_irqsave(&ioasic_lock, flags); + unmask_ioasic_irq(irq); + spin_unlock_irqrestore(&ioasic_lock, flags); +} + +static inline void disable_ioasic_irq(unsigned int irq) +{ + unsigned long flags; + + spin_lock_irqsave(&ioasic_lock, flags); + mask_ioasic_irq(irq); + spin_unlock_irqrestore(&ioasic_lock, flags); +} + + +static inline unsigned int startup_ioasic_irq(unsigned int irq) +{ + enable_ioasic_irq(irq); + return 0; +} + +#define shutdown_ioasic_irq disable_ioasic_irq + +static inline void ack_ioasic_irq(unsigned int irq) +{ + spin_lock(&ioasic_lock); + mask_ioasic_irq(irq); + spin_unlock(&ioasic_lock); + fast_iob(); +} + +static inline void end_ioasic_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + enable_ioasic_irq(irq); +} + +static struct hw_interrupt_type ioasic_irq_type = { + .typename = "IO-ASIC", + .startup = startup_ioasic_irq, + .shutdown = shutdown_ioasic_irq, + .enable = enable_ioasic_irq, + .disable = disable_ioasic_irq, + .ack = ack_ioasic_irq, + .end = end_ioasic_irq, +}; + + +#define startup_ioasic_dma_irq startup_ioasic_irq + +#define shutdown_ioasic_dma_irq shutdown_ioasic_irq + +#define enable_ioasic_dma_irq enable_ioasic_irq + +#define disable_ioasic_dma_irq disable_ioasic_irq + +#define ack_ioasic_dma_irq ack_ioasic_irq + +static inline void end_ioasic_dma_irq(unsigned int irq) +{ + clear_ioasic_irq(irq); + fast_iob(); + end_ioasic_irq(irq); +} + +static struct hw_interrupt_type ioasic_dma_irq_type = { + .typename = "IO-ASIC-DMA", + .startup = startup_ioasic_dma_irq, + .shutdown = shutdown_ioasic_dma_irq, + .enable = enable_ioasic_dma_irq, + .disable = disable_ioasic_dma_irq, + .ack = ack_ioasic_dma_irq, + .end = end_ioasic_dma_irq, +}; + + +void __init init_ioasic_irqs(int base) +{ + int i; + + /* Mask interrupts. */ + ioasic_write(IO_REG_SIMR, 0); + fast_iob(); + + for (i = base; i < base + IO_INR_DMA; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = 1; + irq_desc[i].handler = &ioasic_irq_type; + } + for (; i < base + IO_IRQ_LINES; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = 1; + irq_desc[i].handler = &ioasic_dma_irq_type; + } + + ioasic_irq_base = base; +} diff -Nru a/arch/mips/dec/irq.c b/arch/mips/dec/irq.c --- a/arch/mips/dec/irq.c Tue Jul 1 18:44:35 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,302 +0,0 @@ -/* - * Code to handle DECstation IRQs plus some generic interrupt stuff. - * - * Copyright (C) 1992 Linus Torvalds - * Copyright (C) 1994, 1995, 1996, 1997, 2000 Ralf Baechle - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -extern void dec_init_kn01(void); -extern void dec_init_kn230(void); -extern void dec_init_kn02(void); -extern void dec_init_kn02ba(void); -extern void dec_init_kn02ca(void); -extern void dec_init_kn03(void); - -extern asmlinkage void decstation_handle_int(void); - -unsigned long spurious_count = 0; - -static inline void mask_irq(unsigned int irq_nr) -{ - unsigned int dummy; - - if (dec_interrupt[irq_nr].iemask) { /* This is an ASIC interrupt */ - *imr &= ~dec_interrupt[irq_nr].iemask; - dummy = *imr; - dummy = *imr; - } else /* This is a cpu interrupt */ - change_cp0_status(ST0_IM, read_32bit_cp0_register(CP0_STATUS) & ~dec_interrupt[irq_nr].cpu_mask); -} - -static inline void unmask_irq(unsigned int irq_nr) -{ - unsigned int dummy; - - if (dec_interrupt[irq_nr].iemask) { /* This is an ASIC interrupt */ - *imr |= dec_interrupt[irq_nr].iemask; - dummy = *imr; - dummy = *imr; - } - change_cp0_status(ST0_IM, read_32bit_cp0_register(CP0_STATUS) | dec_interrupt[irq_nr].cpu_mask); -} - -void disable_irq(unsigned int irq_nr) -{ - unsigned long flags; - - save_and_cli(flags); - mask_irq(irq_nr); - restore_flags(flags); -} - -void enable_irq(unsigned int irq_nr) -{ - unsigned long flags; - - save_and_cli(flags); - unmask_irq(irq_nr); - restore_flags(flags); -} - -/* - * Pointers to the low-level handlers: first the general ones, then the - * fast ones, then the bad ones. - */ -extern void interrupt(void); - -static struct irqaction *irq_action[32] = -{ - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - -int show_interrupts(struct seq_file *p, void *v) -{ - int i; - struct irqaction *action; - unsigned long flags; - - for (i = 0; i < 32; i++) { - local_irq_save(flags); - action = irq_action[i]; - if (!action) - goto skip; - seq_printf(p, "%2d: %8d %c %s", - i, kstat_cpu(0).irqs[i], - (action->flags & SA_INTERRUPT) ? '+' : ' ', - action->name); - for (action = action->next; action; action = action->next) { - seq_printf(p, ",%s %s", - (action->flags & SA_INTERRUPT) ? " +" : "", - action->name); - } - seq_putc(p, '\n'); -skip: - local_irq_restore(flags); - } - return 0; -} - -/* - * do_IRQ handles IRQ's that have been installed without the - * SA_INTERRUPT flag: it uses the full signal-handling return - * and runs with other interrupts enabled. All relatively slow - * IRQ's should use this format: notably the keyboard/timer - * routines. - */ -asmlinkage void do_IRQ(int irq, struct pt_regs *regs) -{ - struct irqaction *action; - int do_random, cpu; - - cpu = smp_processor_id(); - irq_enter(cpu, irq); - kstat_cpu(cpu).irqs[irq]++; - - mask_irq(irq); - action = *(irq + irq_action); - if (action) { - if (!(action->flags & SA_INTERRUPT)) - local_irq_enable(); - action = *(irq + irq_action); - do_random = 0; - do { - do_random |= action->flags; - action->handler(irq, action->dev_id, regs); - action = action->next; - } while (action); - if (do_random & SA_SAMPLE_RANDOM) - add_interrupt_randomness(irq); - local_irq_disable(); - unmask_irq(irq); - } - irq_exit(cpu, irq); - - /* unmasking and bottom half handling is done magically for us. */ -} - -/* - * Idea is to put all interrupts - * in a single table and differenciate them just by number. - */ -int setup_dec_irq(int irq, struct irqaction *new) -{ - int shared = 0; - struct irqaction *old, **p; - unsigned long flags; - - p = irq_action + irq; - if ((old = *p) != NULL) { - /* Can't share interrupts unless both agree to */ - if (!(old->flags & new->flags & SA_SHIRQ)) - return -EBUSY; - - /* Can't share interrupts unless both are same type */ - if ((old->flags ^ new->flags) & SA_INTERRUPT) - return -EBUSY; - - /* add new interrupt at end of irq queue */ - do { - p = &old->next; - old = *p; - } while (old); - shared = 1; - } - if (new->flags & SA_SAMPLE_RANDOM) - rand_initialize_irq(irq); - - save_and_cli(flags); - *p = new; - - if (!shared) { - unmask_irq(irq); - } - restore_flags(flags); - return 0; -} - -int request_irq(unsigned int irq, - void (*handler) (int, void *, struct pt_regs *), - unsigned long irqflags, - const char *devname, - void *dev_id) -{ - int retval; - struct irqaction *action; - - if (irq >= 32) - return -EINVAL; - if (!handler) - return -EINVAL; - - action = (struct irqaction *) kmalloc(sizeof(struct irqaction), GFP_KERNEL); - if (!action) - return -ENOMEM; - - action->handler = handler; - action->flags = irqflags; - action->mask = 0; - action->name = devname; - action->next = NULL; - action->dev_id = dev_id; - - retval = setup_dec_irq(irq, action); - - if (retval) - kfree(action); - return retval; -} - -void free_irq(unsigned int irq, void *dev_id) -{ - struct irqaction *action, **p; - unsigned long flags; - - if (irq > 39) { - printk("Trying to free IRQ%d\n", irq); - return; - } - for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) { - if (action->dev_id != dev_id) - continue; - - /* Found it - now free it */ - save_and_cli(flags); - *p = action->next; - if (!irq[irq_action]) - mask_irq(irq); - restore_flags(flags); - kfree(action); - return; - } - printk("Trying to free free IRQ%d\n", irq); -} - -unsigned long probe_irq_on(void) -{ - /* TODO */ - return 0; -} - -int probe_irq_off(unsigned long irqs) -{ - /* TODO */ - return 0; -} - -void __init init_IRQ(void) -{ - switch (mips_machtype) { - case MACH_DS23100: - dec_init_kn01(); - break; - case MACH_DS5100: /* DS5100 MIPSMATE */ - dec_init_kn230(); - break; - case MACH_DS5000_200: /* DS5000 3max */ - dec_init_kn02(); - break; - case MACH_DS5000_1XX: /* DS5000/100 3min */ - dec_init_kn02ba(); - break; - case MACH_DS5000_2X0: /* DS5000/240 3max+ */ - dec_init_kn03(); - break; - case MACH_DS5000_XX: /* Personal DS5000/2x */ - dec_init_kn02ca(); - break; - case MACH_DS5800: /* DS5800 Isis */ - panic("Don't know how to set this up!"); - break; - case MACH_DS5400: /* DS5400 MIPSfair */ - panic("Don't know how to set this up!"); - break; - case MACH_DS5500: /* DS5500 MIPSfair-2 */ - panic("Don't know how to set this up!"); - break; - } - set_except_vector(0, decstation_handle_int); -} diff -Nru a/arch/mips/dec/kn02-irq.c b/arch/mips/dec/kn02-irq.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/dec/kn02-irq.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,127 @@ +/* + * linux/arch/mips/dec/kn02-irq.c + * + * DECstation 5000/200 (KN02) Control and Status Register + * interrupts. + * + * Copyright (c) 2002, 2003 Maciej W. Rozycki + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include + +#include + + +/* + * Bits 7:0 of the Control Register are write-only -- the + * corresponding bits of the Status Register have a different + * meaning. Hence we use a cache. It speeds up things a bit + * as well. + * + * There is no default value -- it has to be initialized. + */ +u32 cached_kn02_csr; +spinlock_t kn02_lock = SPIN_LOCK_UNLOCKED; + + +static int kn02_irq_base; + + +static inline void unmask_kn02_irq(unsigned int irq) +{ + volatile u32 *csr = (volatile u32 *)KN02_CSR_BASE; + + cached_kn02_csr |= (1 << (irq - kn02_irq_base + 16)); + *csr = cached_kn02_csr; +} + +static inline void mask_kn02_irq(unsigned int irq) +{ + volatile u32 *csr = (volatile u32 *)KN02_CSR_BASE; + + cached_kn02_csr &= ~(1 << (irq - kn02_irq_base + 16)); + *csr = cached_kn02_csr; +} + +static inline void enable_kn02_irq(unsigned int irq) +{ + unsigned long flags; + + spin_lock_irqsave(&kn02_lock, flags); + unmask_kn02_irq(irq); + spin_unlock_irqrestore(&kn02_lock, flags); +} + +static inline void disable_kn02_irq(unsigned int irq) +{ + unsigned long flags; + + spin_lock_irqsave(&kn02_lock, flags); + mask_kn02_irq(irq); + spin_unlock_irqrestore(&kn02_lock, flags); +} + + +static unsigned int startup_kn02_irq(unsigned int irq) +{ + enable_kn02_irq(irq); + return 0; +} + +#define shutdown_kn02_irq disable_kn02_irq + +static void ack_kn02_irq(unsigned int irq) +{ + spin_lock(&kn02_lock); + mask_kn02_irq(irq); + spin_unlock(&kn02_lock); + iob(); +} + +static void end_kn02_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + enable_kn02_irq(irq); +} + +static struct hw_interrupt_type kn02_irq_type = { + .typename = "KN02-CSR", + .startup = startup_kn02_irq, + .shutdown = shutdown_kn02_irq, + .enable = enable_kn02_irq, + .disable = disable_kn02_irq, + .ack = ack_kn02_irq, + .end = end_kn02_irq, +}; + + +void __init init_kn02_irqs(int base) +{ + volatile u32 *csr = (volatile u32 *)KN02_CSR_BASE; + unsigned long flags; + int i; + + /* Mask interrupts. */ + spin_lock_irqsave(&kn02_lock, flags); + cached_kn02_csr &= ~KN03_CSR_IOINTEN; + *csr = cached_kn02_csr; + iob(); + spin_unlock_irqrestore(&kn02_lock, flags); + + for (i = base; i < base + KN02_IRQ_LINES; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = 1; + irq_desc[i].handler = &kn02_irq_type; + } + + kn02_irq_base = base; +} diff -Nru a/arch/mips/dec/prom/Makefile b/arch/mips/dec/prom/Makefile --- a/arch/mips/dec/prom/Makefile Tue Jul 1 18:44:34 2003 +++ b/arch/mips/dec/prom/Makefile Tue Jul 1 18:44:34 2003 @@ -1,11 +1,11 @@ -# $Id: Makefile,v 1.1 1999/01/17 03:49:44 ralf Exp $ +# # Makefile for the DECstation prom monitor library routines # under Linux. # -lib-y := init.o memory.o cmdline.o identify.o locore.o +lib-y += init.o memory.o cmdline.o identify.o -EXTRA_AFLAGS := $(CFLAGS) +lib-$(CONFIG_MIPS32) += locore.o +lib-$(CONFIG_MIPS64) += call_o32.o -dep: - $(CPP) $(CPPFLAGS) -M *.c > .depend +EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips/dec/prom/call_o32.S b/arch/mips/dec/prom/call_o32.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/dec/prom/call_o32.S Tue Jul 1 18:44:40 2003 @@ -0,0 +1,91 @@ +/* + * arch/mips/dec/call_o32.S + * + * O32 interface for the 64 (or N32) ABI. + * + * Copyright (C) 2002 Maciej W. Rozycki + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include + +/* Maximum number of arguments supported. Must be even! */ +#define O32_ARGC 32 +/* Number of static registers we save. */ +#define O32_STATC 11 +/* Frame size for both of the above. */ +#define O32_FRAMESZ (4 * O32_ARGC + SZREG * O32_STATC) + + .text + +/* + * O32 function call dispatcher, for interfacing 32-bit ROM routines. + * + * The standard 64 (N32) calling sequence is supported, with a0 + * holding a function pointer, a1-a7 -- its first seven arguments + * and the stack -- remaining ones (up to O32_ARGC, including a1-a7). + * Static registers, gp and fp are preserved, v0 holds a result. + * This code relies on the called o32 function for sp and ra + * restoration and thus both this dispatcher and the current stack + * have to be placed in a KSEGx (or KUSEG) address space. Any + * pointers passed have to point to addresses within one of these + * spaces as well. + */ +NESTED(call_o32, O32_FRAMESZ, ra) + REG_SUBU sp,O32_FRAMESZ + + REG_S ra,O32_FRAMESZ-1*SZREG(sp) + REG_S fp,O32_FRAMESZ-2*SZREG(sp) + REG_S gp,O32_FRAMESZ-3*SZREG(sp) + REG_S s7,O32_FRAMESZ-4*SZREG(sp) + REG_S s6,O32_FRAMESZ-5*SZREG(sp) + REG_S s5,O32_FRAMESZ-6*SZREG(sp) + REG_S s4,O32_FRAMESZ-7*SZREG(sp) + REG_S s3,O32_FRAMESZ-8*SZREG(sp) + REG_S s2,O32_FRAMESZ-9*SZREG(sp) + REG_S s1,O32_FRAMESZ-10*SZREG(sp) + REG_S s0,O32_FRAMESZ-11*SZREG(sp) + + move jp,a0 + + sll a0,a1,zero + sll a1,a2,zero + sll a2,a3,zero + sll a3,a4,zero + sw a5,0x10(sp) + sw a6,0x14(sp) + sw a7,0x18(sp) + + PTR_LA t0,O32_FRAMESZ(sp) + PTR_LA t1,0x1c(sp) + li t2,O32_ARGC-7 +1: + lw t3,(t0) + REG_ADDU t0,SZREG + sw t3,(t1) + REG_SUBU t2,1 + REG_ADDU t1,4 + bnez t2,1b + + jalr jp + + REG_L s0,O32_FRAMESZ-11*SZREG(sp) + REG_L s1,O32_FRAMESZ-10*SZREG(sp) + REG_L s2,O32_FRAMESZ-9*SZREG(sp) + REG_L s3,O32_FRAMESZ-8*SZREG(sp) + REG_L s4,O32_FRAMESZ-7*SZREG(sp) + REG_L s5,O32_FRAMESZ-6*SZREG(sp) + REG_L s6,O32_FRAMESZ-5*SZREG(sp) + REG_L s7,O32_FRAMESZ-4*SZREG(sp) + REG_L gp,O32_FRAMESZ-3*SZREG(sp) + REG_L fp,O32_FRAMESZ-2*SZREG(sp) + REG_L ra,O32_FRAMESZ-1*SZREG(sp) + + REG_ADDU sp,O32_FRAMESZ + jr ra +END(call_o32) diff -Nru a/arch/mips/dec/prom/cmdline.c b/arch/mips/dec/prom/cmdline.c --- a/arch/mips/dec/prom/cmdline.c Tue Jul 1 18:44:37 2003 +++ b/arch/mips/dec/prom/cmdline.c Tue Jul 1 18:44:37 2003 @@ -6,32 +6,30 @@ #include #include #include +#include #include - -#include "prom.h" +#include #undef PROM_DEBUG -#ifdef PROM_DEBUG -extern int (*prom_printf)(char *, ...); -#endif - -char arcs_cmdline[COMMAND_LINE_SIZE]; +char arcs_cmdline[CL_SIZE]; -void __init prom_init_cmdline(int argc, char **argv, unsigned long magic) +void __init prom_init_cmdline(s32 argc, s32 *argv, u32 magic) { + char *arg; int start_arg, i; /* * collect args and prepare cmd_line */ - if (magic != REX_PROM_MAGIC) + if (!prom_is_rex(magic)) start_arg = 1; else start_arg = 2; for (i = start_arg; i < argc; i++) { - strcat(arcs_cmdline, argv[i]); + arg = (void *)(long)(argv[i]); + strcat(arcs_cmdline, arg); if (i < (argc - 1)) strcat(arcs_cmdline, " "); } @@ -39,6 +37,4 @@ #ifdef PROM_DEBUG prom_printf("arcs_cmdline: %s\n", &(arcs_cmdline[0])); #endif - } - diff -Nru a/arch/mips/dec/prom/identify.c b/arch/mips/dec/prom/identify.c --- a/arch/mips/dec/prom/identify.c Tue Jul 1 18:44:38 2003 +++ b/arch/mips/dec/prom/identify.c Tue Jul 1 18:44:38 2003 @@ -2,32 +2,104 @@ * identify.c: machine identification code. * * Copyright (C) 1998 Harald Koerfgen and Paul M. Antoine - * - * $Id: identify.c,v 1.2 1999/10/09 00:00:58 ralf Exp $ + * Copyright (C) 2002, 2003 Maciej W. Rozycki */ #include #include +#include #include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include "dectypes.h" -#include "prom.h" - -extern char *(*prom_getenv)(char *); -extern int (*prom_printf)(char *, ...); -extern int (*rex_getsysid)(void); extern unsigned long mips_machgroup; extern unsigned long mips_machtype; -void __init prom_identify_arch (unsigned int magic) +static const char *dec_system_strings[] = { + [MACH_DSUNKNOWN] "unknown DECstation", + [MACH_DS23100] "DECstation 2100/3100", + [MACH_DS5100] "DECsystem 5100", + [MACH_DS5000_200] "DECstation 5000/200", + [MACH_DS5000_1XX] "DECstation 5000/1xx", + [MACH_DS5000_XX] "Personal DECstation 5000/xx", + [MACH_DS5000_2X0] "DECstation 5000/2x0", + [MACH_DS5400] "DECsystem 5400", + [MACH_DS5500] "DECsystem 5500", + [MACH_DS5800] "DECsystem 5800", + [MACH_DS5900] "DECsystem 5900", +}; + +const char *get_system_type(void) { - unsigned char dec_cpunum, dec_firmrev, dec_etc; - int dec_systype; - unsigned long dec_sysid; +#define STR_BUF_LEN 64 + static char system[STR_BUF_LEN]; + static int called = 0; + + if (called == 0) { + called = 1; + snprintf(system, STR_BUF_LEN, "Digital %s", + dec_system_strings[mips_machtype]); + } + + return system; +} + - if (magic != REX_PROM_MAGIC) { +/* + * Setup essential system-specific memory addresses. We need them + * early. Semantically the functions belong to prom/init.c, but they + * are compact enough we want them inlined. --macro + */ +static inline void prom_init_kn01(void) +{ + dec_rtc_base = (void *)KN01_RTC_BASE; + dec_kn_slot_size = KN01_SLOT_SIZE; +} + +static inline void prom_init_kn230(void) +{ + dec_rtc_base = (void *)KN01_RTC_BASE; + dec_kn_slot_size = KN01_SLOT_SIZE; +} + +static inline void prom_init_kn02(void) +{ + dec_rtc_base = (void *)KN02_RTC_BASE; + dec_kn_slot_size = KN02_SLOT_SIZE; +} + +static inline void prom_init_kn02xa(void) +{ + ioasic_base = (void *)KN02XA_IOASIC_BASE; + dec_rtc_base = (void *)KN02XA_RTC_BASE; + dec_kn_slot_size = IOASIC_SLOT_SIZE; +} + +static inline void prom_init_kn03(void) +{ + ioasic_base = (void *)KN03_IOASIC_BASE; + dec_rtc_base = (void *)KN03_RTC_BASE; + dec_kn_slot_size = IOASIC_SLOT_SIZE; +} + + +void __init prom_identify_arch(u32 magic) +{ + unsigned char dec_cpunum, dec_firmrev, dec_etc, dec_systype; + u32 dec_sysid; + + if (!prom_is_rex(magic)) { dec_sysid = simple_strtoul(prom_getenv("systype"), (char **)0, 0); } else { dec_sysid = rex_getsysid(); @@ -49,50 +121,52 @@ * FIXME: This may not be an exhaustive list of DECStations/Servers! * Put all model-specific initialisation calls here. */ - prom_printf("This DECstation is a "); - switch (dec_systype) { case DS2100_3100: - prom_printf("DS2100/3100\n"); mips_machtype = MACH_DS23100; + prom_init_kn01(); break; case DS5100: /* DS5100 MIPSMATE */ - prom_printf("DS5100\n"); mips_machtype = MACH_DS5100; + prom_init_kn230(); break; case DS5000_200: /* DS5000 3max */ - prom_printf("DS5000/200\n"); mips_machtype = MACH_DS5000_200; + prom_init_kn02(); break; case DS5000_1XX: /* DS5000/100 3min */ - prom_printf("DS5000/1xx\n"); mips_machtype = MACH_DS5000_1XX; + prom_init_kn02xa(); break; - case DS5000_2X0: /* DS5000/240 3max+ */ - prom_printf("DS5000/2x0\n"); + case DS5000_2X0: /* DS5000/240 3max+ or DS5900 bigmax */ mips_machtype = MACH_DS5000_2X0; + prom_init_kn03(); + if (!(ioasic_read(IO_REG_SIR) & KN03_IO_INR_3MAXP)) + mips_machtype = MACH_DS5900; break; - case DS5000_XX: /* Personal DS5000/2x */ - prom_printf("Personal DS5000/xx\n"); + case DS5000_XX: /* Personal DS5000/xx maxine */ mips_machtype = MACH_DS5000_XX; + prom_init_kn02xa(); break; case DS5800: /* DS5800 Isis */ - prom_printf("DS5800\n"); mips_machtype = MACH_DS5800; break; case DS5400: /* DS5400 MIPSfair */ - prom_printf("DS5400\n"); mips_machtype = MACH_DS5400; break; case DS5500: /* DS5500 MIPSfair-2 */ - prom_printf("DS5500\n"); mips_machtype = MACH_DS5500; break; default: - prom_printf("unknown, id is %x", dec_systype); mips_machtype = MACH_DSUNKNOWN; break; } -} - + if (mips_machtype == MACH_DSUNKNOWN) + prom_printf("This is an %s, id is %x\n", + dec_system_strings[mips_machtype], + dec_systype); + else + prom_printf("This is a %s\n", + dec_system_strings[mips_machtype]); +} diff -Nru a/arch/mips/dec/prom/init.c b/arch/mips/dec/prom/init.c --- a/arch/mips/dec/prom/init.c Tue Jul 1 18:44:35 2003 +++ b/arch/mips/dec/prom/init.c Tue Jul 1 18:44:35 2003 @@ -2,98 +2,103 @@ * init.c: PROM library initialisation code. * * Copyright (C) 1998 Harald Koerfgen + * Copyright (C) 2002 Maciej W. Rozycki */ -#include #include +#include +#include +#include + #include #include -#include "prom.h" +#include + +#include + + +int (*__rex_bootinit)(void); +int (*__rex_bootread)(void); +int (*__rex_getbitmap)(memmap *); +unsigned long *(*__rex_slot_address)(int); +void *(*__rex_gettcinfo)(void); +int (*__rex_getsysid)(void); +void (*__rex_clear_cache)(void); + +int (*__prom_getchar)(void); +char *(*__prom_getenv)(char *); +int (*__prom_printf)(char *, ...); + +int (*__pmax_open)(char*, int); +int (*__pmax_lseek)(int, long, int); +int (*__pmax_read)(int, void *, int); +int (*__pmax_close)(int); -/* - * PROM Interface (whichprom.c) - */ -typedef struct { - int pagesize; - unsigned char bitmap[0]; -} memmap; - -int (*rex_bootinit)(void); -int (*rex_bootread)(void); -int (*rex_getbitmap)(memmap *); -unsigned long *(*rex_slot_address)(int); -void *(*rex_gettcinfo)(void); -int (*rex_getsysid)(void); -void (*rex_clear_cache)(void); - -int (*prom_getchar)(void); -char *(*prom_getenv)(char *); -int (*prom_printf)(char *, ...); - -int (*pmax_open)(char*, int); -int (*pmax_lseek)(int, long, int); -int (*pmax_read)(int, void *, int); -int (*pmax_close)(int); - -extern void prom_meminit(unsigned int); -extern void prom_identify_arch(unsigned int); -extern void prom_init_cmdline(int, char **, unsigned long); /* * Detect which PROM's the DECSTATION has, and set the callback vectors * appropriately. */ -void __init which_prom(unsigned long magic, int *prom_vec) +void __init which_prom(s32 magic, s32 *prom_vec) { /* * No sign of the REX PROM's magic number means we assume a non-REX * machine (i.e. we're on a DS2100/3100, DS5100 or DS5000/2xx) */ - if (magic == REX_PROM_MAGIC) - { + if (prom_is_rex(magic)) { /* * Set up prom abstraction structure with REX entry points. */ - rex_bootinit = (int (*)(void)) *(prom_vec + REX_PROM_BOOTINIT); - rex_bootread = (int (*)(void)) *(prom_vec + REX_PROM_BOOTREAD); - rex_getbitmap = (int (*)(memmap *)) *(prom_vec + REX_PROM_GETBITMAP); - prom_getchar = (int (*)(void)) *(prom_vec + REX_PROM_GETCHAR); - prom_getenv = (char *(*)(char *)) *(prom_vec + REX_PROM_GETENV); - rex_getsysid = (int (*)(void)) *(prom_vec + REX_PROM_GETSYSID); - rex_gettcinfo = (void *(*)(void)) *(prom_vec + REX_PROM_GETTCINFO); - prom_printf = (int (*)(char *, ...)) *(prom_vec + REX_PROM_PRINTF); - rex_slot_address = (unsigned long *(*)(int)) *(prom_vec + REX_PROM_SLOTADDR); - rex_clear_cache = (void (*)(void)) * (prom_vec + REX_PROM_CLEARCACHE); - } - else - { + __rex_bootinit = + (void *)(long)*(prom_vec + REX_PROM_BOOTINIT); + __rex_bootread = + (void *)(long)*(prom_vec + REX_PROM_BOOTREAD); + __rex_getbitmap = + (void *)(long)*(prom_vec + REX_PROM_GETBITMAP); + __prom_getchar = + (void *)(long)*(prom_vec + REX_PROM_GETCHAR); + __prom_getenv = + (void *)(long)*(prom_vec + REX_PROM_GETENV); + __rex_getsysid = + (void *)(long)*(prom_vec + REX_PROM_GETSYSID); + __rex_gettcinfo = + (void *)(long)*(prom_vec + REX_PROM_GETTCINFO); + __prom_printf = + (void *)(long)*(prom_vec + REX_PROM_PRINTF); + __rex_slot_address = + (void *)(long)*(prom_vec + REX_PROM_SLOTADDR); + __rex_clear_cache = + (void *)(long)*(prom_vec + REX_PROM_CLEARCACHE); + } else { /* * Set up prom abstraction structure with non-REX entry points. */ - prom_getchar = (int (*)(void)) PMAX_PROM_GETCHAR; - prom_getenv = (char *(*)(char *)) PMAX_PROM_GETENV; - prom_printf = (int (*)(char *, ...)) PMAX_PROM_PRINTF; - pmax_open = (int (*)(char *, int)) PMAX_PROM_OPEN; - pmax_lseek = (int (*)(int, long, int)) PMAX_PROM_LSEEK; - pmax_read = (int (*)(int, void *, int)) PMAX_PROM_READ; - pmax_close = (int (*)(int)) PMAX_PROM_CLOSE; + __prom_getchar = (void *)PMAX_PROM_GETCHAR; + __prom_getenv = (void *)PMAX_PROM_GETENV; + __prom_printf = (void *)PMAX_PROM_PRINTF; + __pmax_open = (void *)PMAX_PROM_OPEN; + __pmax_lseek = (void *)PMAX_PROM_LSEEK; + __pmax_read = (void *)PMAX_PROM_READ; + __pmax_close = (void *)PMAX_PROM_CLOSE; } -} +} -int __init prom_init(int argc, char **argv, - unsigned long magic, int *prom_vec) +int __init prom_init(s32 argc, s32 *argv, u32 magic, s32 *prom_vec) { extern void dec_machine_halt(void); - /* Determine which PROM's we have (and therefore which machine we're on!) */ + /* + * Determine which PROM's we have + * (and therefore which machine we're on!) + */ which_prom(magic, prom_vec); - if (magic == REX_PROM_MAGIC) + if (prom_is_rex(magic)) rex_clear_cache(); /* Were we compiled with the right CPU option? */ #if defined(CONFIG_CPU_R3000) - if ((mips_cpu.cputype == CPU_R4000SC) || - (mips_cpu.cputype == CPU_R4400SC)) { + if ((current_cpu_data.cputype == CPU_R4000SC) || + (current_cpu_data.cputype == CPU_R4400SC)) { prom_printf("Sorry, this kernel is compiled for the wrong CPU type!\n"); prom_printf("Please recompile with \"CONFIG_CPU_R4x00 = y\"\n"); dec_machine_halt(); @@ -101,8 +106,8 @@ #endif #if defined(CONFIG_CPU_R4X00) - if ((mips_cpu.cputype == CPU_R3000) || - (mips_cpu.cputype == CPU_R3000A)) { + if ((current_cpu_data.cputype == CPU_R3000) || + (current_cpu_data.cputype == CPU_R3000A)) { prom_printf("Sorry, this kernel is compiled for the wrong CPU type!\n"); prom_printf("Please recompile with \"CONFIG_CPU_R3000 = y\"\n"); dec_machine_halt(); @@ -115,4 +120,3 @@ return 0; } - diff -Nru a/arch/mips/dec/prom/locore.S b/arch/mips/dec/prom/locore.S --- a/arch/mips/dec/prom/locore.S Tue Jul 1 18:44:31 2003 +++ b/arch/mips/dec/prom/locore.S Tue Jul 1 18:44:31 2003 @@ -19,11 +19,11 @@ mfc0 k0, CP0_STATUS la k1, mem_err - sw k0,0(k1) + sw k0, 0(k1) mfc0 k0, CP0_EPC nop - addiu k0,4 # skip the causing instruction + addiu k0, 4 # skip the causing instruction jr k0 rfe END(genexcept_early) diff -Nru a/arch/mips/dec/prom/memory.c b/arch/mips/dec/prom/memory.c --- a/arch/mips/dec/prom/memory.c Tue Jul 1 18:44:31 2003 +++ b/arch/mips/dec/prom/memory.c Tue Jul 1 18:44:31 2003 @@ -2,37 +2,22 @@ * memory.c: memory initialisation code. * * Copyright (C) 1998 Harald Koerfgen, Frieder Streffer and Paul M. Antoine - * Copyright (C) 2000 Maciej W. Rozycki - * - * $Id: memory.c,v 1.3 1999/10/09 00:00:58 ralf Exp $ + * Copyright (C) 2000, 2002 Maciej W. Rozycki */ -#include #include +#include #include #include #include +#include #include -#include - #include - #include +#include +#include +#include -#include "prom.h" - -typedef struct { - int pagesize; - unsigned char bitmap[0]; -} memmap; - -extern int (*rex_getbitmap)(memmap *); - -#undef PROM_DEBUG - -#ifdef PROM_DEBUG -extern int (*prom_printf)(char *, ...); -#endif volatile unsigned long mem_err = 0; /* So we know an error occurred */ @@ -43,10 +28,10 @@ #define CHUNK_SIZE 0x400000 -static void __init pmax_setup_memory_region(void) +static inline void pmax_setup_memory_region(void) { volatile unsigned char *memory_page, dummy; - char old_handler[0x80]; + char old_handler[0x80]; extern char genexcept_early; /* Install exception handler */ @@ -73,14 +58,14 @@ * Use the REX prom calls to get hold of the memory bitmap, and thence * determine memory size. */ -static void __init rex_setup_memory_region(void) +static inline void rex_setup_memory_region(void) { int i, bitmap_size; unsigned long mem_start = 0, mem_size = 0; memmap *bm; /* some free 64k */ - bm = (memmap *) 0x80028000; + bm = (memmap *)KSEG0ADDR(0x28000); bitmap_size = rex_getbitmap(bm); @@ -100,9 +85,9 @@ add_memory_region(mem_start, mem_size, BOOT_MEM_RAM); } -void __init prom_meminit(unsigned int magic) +void __init prom_meminit(u32 magic) { - if (magic != REX_PROM_MAGIC) + if (!prom_is_rex(magic)) pmax_setup_memory_region(); else rex_setup_memory_region(); @@ -111,14 +96,13 @@ void __init prom_free_prom_memory (void) { unsigned long addr, end; - extern char _ftext; /* * Free everything below the kernel itself but leave * the first page reserved for the exception handlers. */ -#ifdef CONFIG_DECLANCE +#if defined(CONFIG_DECLANCE) || defined(CONFIG_DECLANCE_MODULE) /* * Leave 128 KB reserved for Lance memory for * IOASIC DECstations. @@ -126,10 +110,10 @@ * XXX: save this address for use in dec_lance.c? */ if (IOASIC) - end = __pa(&_ftext) - 0x00020000; + end = __pa(&_text) - 0x00020000; else #endif - end = __pa(&_ftext); + end = __pa(&_text); addr = PAGE_SIZE; while (addr < end) { diff -Nru a/arch/mips/dec/prom/prom.h b/arch/mips/dec/prom/prom.h --- a/arch/mips/dec/prom/prom.h Tue Jul 1 18:44:37 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,51 +0,0 @@ -/* - * Miscellaneous definitions used to call the routines contained in the boot - * PROMs on various models of DECSTATION's. - * the rights to redistribute these changes. - */ - -#ifndef __ASM_DEC_PROM_H -#define __ASM_DEC_PROM_H - -/* - * PMAX/3MAX PROM entry points for DS2100/3100's and DS5000/2xx's. Many of - * these will work for MIPSen as well! - */ -#define VEC_RESET 0xBFC00000 /* Prom base address */ -#define PMAX_PROM_ENTRY(x) (VEC_RESET+((x)*8)) /* Prom jump table */ - -#define PMAX_PROM_HALT PMAX_PROM_ENTRY(2) /* valid on MIPSen */ -#define PMAX_PROM_AUTOBOOT PMAX_PROM_ENTRY(5) /* valid on MIPSen */ -#define PMAX_PROM_OPEN PMAX_PROM_ENTRY(6) -#define PMAX_PROM_READ PMAX_PROM_ENTRY(7) -#define PMAX_PROM_CLOSE PMAX_PROM_ENTRY(10) -#define PMAX_PROM_LSEEK PMAX_PROM_ENTRY(11) -#define PMAX_PROM_GETCHAR PMAX_PROM_ENTRY(12) -#define PMAX_PROM_PUTCHAR PMAX_PROM_ENTRY(13) /* 12 on MIPSen */ -#define PMAX_PROM_GETS PMAX_PROM_ENTRY(15) -#define PMAX_PROM_PRINTF PMAX_PROM_ENTRY(17) -#define PMAX_PROM_GETENV PMAX_PROM_ENTRY(33) /* valid on MIPSen */ - -/* - * Magic number indicating REX PROM available on DECSTATION. Found in - * register a2 on transfer of control to program from PROM. - */ -#define REX_PROM_MAGIC 0x30464354 - -/* - * 3MIN/MAXINE PROM entry points for DS5000/1xx's, DS5000/xx's, and - * DS5000/2x0. - */ -#define REX_PROM_GETBITMAP 0x84/4 /* get mem bitmap */ -#define REX_PROM_GETCHAR 0x24/4 /* getch() */ -#define REX_PROM_GETENV 0x64/4 /* get env. variable */ -#define REX_PROM_GETSYSID 0x80/4 /* get system id */ -#define REX_PROM_GETTCINFO 0xa4/4 -#define REX_PROM_PRINTF 0x30/4 /* printf() */ -#define REX_PROM_SLOTADDR 0x6c/4 /* slotaddr */ -#define REX_PROM_BOOTINIT 0x54/4 /* open() */ -#define REX_PROM_BOOTREAD 0x58/4 /* read() */ -#define REX_PROM_CLEARCACHE 0x7c/4 - -#endif /* __ASM_DEC_PROM_H */ - diff -Nru a/arch/mips/dec/promcon.c b/arch/mips/dec/promcon.c --- a/arch/mips/dec/promcon.c Tue Jul 1 18:44:35 2003 +++ b/arch/mips/dec/promcon.c Tue Jul 1 18:44:35 2003 @@ -2,7 +2,7 @@ * Wrap-around code for a console using the * DECstation PROM io-routines. * - * Copyright (c) 1998 Harald Koerfgen + * Copyright (c) 1998 Harald Koerfgen */ #include @@ -12,50 +12,45 @@ #include #include -extern int (*prom_getchar) (void); -extern int (*prom_printf) (char *,...); +#include static void prom_console_write(struct console *co, const char *s, unsigned count) { - unsigned i; + unsigned i; - /* - * Now, do each character - */ - for (i = 0; i < count; i++) { - if (*s == 10) - prom_printf("%c", 13); - prom_printf("%c", *s++); - } + /* + * Now, do each character + */ + for (i = 0; i < count; i++) { + if (*s == 10) + prom_printf("%c", 13); + prom_printf("%c", *s++); + } } static int __init prom_console_setup(struct console *co, char *options) { - return 0; -} - -static kdev_t prom_console_device(struct console *c) -{ - return MKDEV(TTY_MAJOR, 64 + c->index); + return 0; } static struct console sercons = { - .name = "ttyS", - .write = prom_console_write, - .device = prom_console_device, - .setup = prom_console_setup, - .flags = CON_PRINTBUFFER, - .index = -1, + .name = "ttyS", + .write = prom_console_write, + .setup = prom_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, }; /* * Register console. */ -long __init prom_console_init(long kmem_start, long kmem_end) +static int __init prom_console_init(void) { - register_console(&sercons); - return kmem_start; + register_console(&sercons); + + return 0; } +console_initcall(prom_console_init); diff -Nru a/arch/mips/dec/reset.c b/arch/mips/dec/reset.c --- a/arch/mips/dec/reset.c Tue Jul 1 18:44:37 2003 +++ b/arch/mips/dec/reset.c Tue Jul 1 18:44:37 2003 @@ -1,11 +1,14 @@ /* - * $Id: $ - * - * Reset a DECstation machine. + * Reset a DECstation machine. * + * Copyright (C) 199x the Anonymous + * Copyright (C) 2001, 2002, 2003 Maciej W. Rozycki */ -void (*back_to_prom)(void) = (void (*)(void))0xBFC00000; +#include +#include + +#define back_to_prom() (((void (*)(void))KSEG1ADDR(0x1fc00000))()) void dec_machine_restart(char *command) { diff -Nru a/arch/mips/dec/rtc-dec.c b/arch/mips/dec/rtc-dec.c --- a/arch/mips/dec/rtc-dec.c Tue Jul 1 18:44:34 2003 +++ b/arch/mips/dec/rtc-dec.c Tue Jul 1 18:44:34 2003 @@ -3,33 +3,38 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * RTC routines for DECstation style attached Dallas chip. + * RTC routines for DECstation style attached Dallas DS1287 chip. * * Copyright (C) 1998, 2001 by Ralf Baechle * Copyright (C) 1998 by Harald Koerfgen + * Copyright (C) 2002 Maciej W. Rozycki */ + #include +#include +#include -extern char *dec_rtc_base; +volatile u8 *dec_rtc_base; static unsigned char dec_rtc_read_data(unsigned long addr) { - return (dec_rtc_base[addr * 4]); + return dec_rtc_base[addr * 4]; } static void dec_rtc_write_data(unsigned char data, unsigned long addr) { - dec_rtc_base[addr * 4] = data; + dec_rtc_base[addr * 4] = data; } static int dec_rtc_bcd_mode(void) { - return 0; + return 0; } -struct rtc_ops dec_rtc_ops = -{ - &dec_rtc_read_data, - &dec_rtc_write_data, - &dec_rtc_bcd_mode +struct rtc_ops dec_rtc_ops = { + &dec_rtc_read_data, + &dec_rtc_write_data, + &dec_rtc_bcd_mode }; + +EXPORT_SYMBOL(dec_rtc_base); diff -Nru a/arch/mips/dec/setup.c b/arch/mips/dec/setup.c --- a/arch/mips/dec/setup.c Tue Jul 1 18:44:34 2003 +++ b/arch/mips/dec/setup.c Tue Jul 1 18:44:34 2003 @@ -6,478 +6,768 @@ * for more details. * * Copyright (C) 1998 Harald Koerfgen - * Copyright (C) 2000 Maciej W. Rozycki + * Copyright (C) 2000, 2001, 2002, 2003 Maciej W. Rozycki */ +#include #include #include #include #include #include -#include -#include #include +#include +#include +#include + +#include +#include #include +#include +#include #include +#include +#include #include -#include -#include -#include -#include #include #include #include +#include +#include +#include +#include +#include +#include -char *dec_rtc_base = (void *) KN01_RTC_BASE; /* Assume DS2100/3100 initially */ - -volatile unsigned int *ioasic_base; - -decint_t dec_interrupt[NR_INTS]; - -/* - * Information regarding the IRQ Controller - */ - -volatile unsigned int *isr = 0L; /* address of the interrupt status register */ -volatile unsigned int *imr = 0L; /* address of the interrupt mask register */ - extern void dec_machine_restart(char *command); extern void dec_machine_halt(void); extern void dec_machine_power_off(void); extern void dec_intr_halt(int irq, void *dev_id, struct pt_regs *regs); -extern void wbflush_setup(void); +extern asmlinkage void decstation_handle_int(void); -extern struct rtc_ops dec_rtc_ops; +spinlock_t ioasic_ssr_lock; -extern int setup_dec_irq(int, struct irqaction *); +volatile u32 *ioasic_base; +unsigned long dec_kn_slot_size; -void (*board_time_init) (struct irqaction * irq); +/* + * IRQ routing and priority tables. Priorites are set as follows: + * + * KN01 KN230 KN02 KN02-BA KN02-CA KN03 + * + * MEMORY CPU CPU CPU ASIC CPU CPU + * RTC CPU CPU CPU ASIC CPU CPU + * DMA - - - ASIC ASIC ASIC + * SERIAL0 CPU CPU CSR ASIC ASIC ASIC + * SERIAL1 - - - ASIC - ASIC + * SCSI CPU CPU CSR ASIC ASIC ASIC + * ETHERNET CPU * CSR ASIC ASIC ASIC + * other - - - ASIC - - + * TC2 - - CSR CPU ASIC ASIC + * TC1 - - CSR CPU ASIC ASIC + * TC0 - - CSR CPU ASIC ASIC + * other - CPU - CPU ASIC ASIC + * other - - - - CPU CPU + * + * * -- shared with SCSI + */ + +int dec_interrupt[DEC_NR_INTS] = { + [0 ... DEC_NR_INTS - 1] = -1 +}; +int_ptr cpu_mask_nr_tbl[DEC_MAX_CPU_INTS][2] = { + { { .i = ~0 }, { .p = dec_intr_unimplemented } }, +}; +int_ptr asic_mask_nr_tbl[DEC_MAX_ASIC_INTS][2] = { + { { .i = ~0 }, { .p = asic_intr_unimplemented } }, +}; +int cpu_fpu_mask = DEC_CPU_IRQ_MASK(DEC_CPU_INR_FPU); + +static struct irqaction ioirq = { + .handler = no_action, + .name = "cascade", +}; +static struct irqaction fpuirq = { + .handler = no_action, + .name = "fpu", +}; + +static struct irqaction busirq = { + .flags = SA_INTERRUPT, + .name = "bus error", +}; + +static struct irqaction haltirq = { + .handler = dec_intr_halt, + .name = "halt", +}; + + +void (*board_time_init)(struct irqaction *irq); -static struct irqaction irq10 = {dec_intr_halt, 0, 0, "halt", NULL, NULL}; /* * enable the periodic interrupts */ static void __init dec_time_init(struct irqaction *irq) { - /* - * Here we go, enable periodic rtc interrupts. - */ + /* + * Here we go, enable periodic rtc interrupts. + */ #ifndef LOG_2_HZ # define LOG_2_HZ 7 #endif - CMOS_WRITE(RTC_REF_CLCK_32KHZ | (16 - LOG_2_HZ), RTC_REG_A); - CMOS_WRITE(CMOS_READ(RTC_REG_B) | RTC_PIE, RTC_REG_B); - setup_dec_irq(CLOCK, irq); + CMOS_WRITE(RTC_REF_CLCK_32KHZ | (16 - LOG_2_HZ), RTC_REG_A); + CMOS_WRITE(CMOS_READ(RTC_REG_B) | RTC_PIE, RTC_REG_B); + setup_irq(dec_interrupt[DEC_IRQ_RTC], irq); } + /* - * Enable the halt interrupt. + * Bus error (DBE/IBE exceptions and bus interrupts) handling setup. */ -static void __init dec_halt_init(struct irqaction *irq) +void __init dec_be_init(void) { - setup_dec_irq(HALT, irq); + switch (mips_machtype) { + case MACH_DS23100: /* DS2100/DS3100 Pmin/Pmax */ + busirq.flags |= SA_SHIRQ; + break; + case MACH_DS5000_200: /* DS5000/200 3max */ + case MACH_DS5000_2X0: /* DS5000/240 3max+ */ + case MACH_DS5900: /* DS5900 bigmax */ + board_be_handler = dec_ecc_be_handler; + busirq.handler = dec_ecc_be_interrupt; + dec_ecc_be_init(); + break; + } } + void __init decstation_setup(void) { - board_time_init = dec_time_init; + board_be_init = dec_be_init; + board_time_init = dec_time_init; - wbflush_setup(); + wbflush_setup(); - _machine_restart = dec_machine_restart; - _machine_halt = dec_machine_halt; - _machine_power_off = dec_machine_power_off; + _machine_restart = dec_machine_restart; + _machine_halt = dec_machine_halt; + _machine_power_off = dec_machine_power_off; #ifdef CONFIG_FB - conswitchp = &dummy_con; + conswitchp = &dummy_con; #endif - rtc_ops = &dec_rtc_ops; + rtc_ops = &dec_rtc_ops; } + /* - * Machine-specific initialisation for kn01, aka Pmax, aka DS2100, DS3100, - * and possibly also the DS5100. + * Machine-specific initialisation for KN01, aka DS2100 (aka Pmin) + * or DS3100 (aka Pmax). */ +static int kn01_interrupt[DEC_NR_INTS] __initdata = { + [DEC_IRQ_CASCADE] = -1, + [DEC_IRQ_AB_RECV] = -1, + [DEC_IRQ_AB_XMIT] = -1, + [DEC_IRQ_DZ11] = DEC_CPU_IRQ_NR(KN01_CPU_INR_DZ11), + [DEC_IRQ_ASC] = -1, + [DEC_IRQ_FLOPPY] = -1, + [DEC_IRQ_FPU] = DEC_CPU_IRQ_NR(DEC_CPU_INR_FPU), + [DEC_IRQ_HALT] = -1, + [DEC_IRQ_ISDN] = -1, + [DEC_IRQ_LANCE] = DEC_CPU_IRQ_NR(KN01_CPU_INR_LANCE), + [DEC_IRQ_BUS] = DEC_CPU_IRQ_NR(KN01_CPU_INR_BUS), + [DEC_IRQ_PSU] = -1, + [DEC_IRQ_RTC] = DEC_CPU_IRQ_NR(KN01_CPU_INR_RTC), + [DEC_IRQ_SCC0] = -1, + [DEC_IRQ_SCC1] = -1, + [DEC_IRQ_SII] = DEC_CPU_IRQ_NR(KN01_CPU_INR_SII), + [DEC_IRQ_TC0] = -1, + [DEC_IRQ_TC1] = -1, + [DEC_IRQ_TC2] = -1, + [DEC_IRQ_TIMER] = -1, + [DEC_IRQ_VIDEO] = DEC_CPU_IRQ_NR(KN01_CPU_INR_VIDEO), + [DEC_IRQ_ASC_MERR] = -1, + [DEC_IRQ_ASC_ERR] = -1, + [DEC_IRQ_ASC_DMA] = -1, + [DEC_IRQ_FLOPPY_ERR] = -1, + [DEC_IRQ_ISDN_ERR] = -1, + [DEC_IRQ_ISDN_RXDMA] = -1, + [DEC_IRQ_ISDN_TXDMA] = -1, + [DEC_IRQ_LANCE_MERR] = -1, + [DEC_IRQ_SCC0A_RXERR] = -1, + [DEC_IRQ_SCC0A_RXDMA] = -1, + [DEC_IRQ_SCC0A_TXERR] = -1, + [DEC_IRQ_SCC0A_TXDMA] = -1, + [DEC_IRQ_AB_RXERR] = -1, + [DEC_IRQ_AB_RXDMA] = -1, + [DEC_IRQ_AB_TXERR] = -1, + [DEC_IRQ_AB_TXDMA] = -1, + [DEC_IRQ_SCC1A_RXERR] = -1, + [DEC_IRQ_SCC1A_RXDMA] = -1, + [DEC_IRQ_SCC1A_TXERR] = -1, + [DEC_IRQ_SCC1A_TXDMA] = -1, +}; + +static int_ptr kn01_cpu_mask_nr_tbl[][2] __initdata = { + { { .i = DEC_CPU_IRQ_MASK(KN01_CPU_INR_BUS) }, + { .i = DEC_CPU_IRQ_NR(KN01_CPU_INR_BUS) } }, + { { .i = DEC_CPU_IRQ_MASK(KN01_CPU_INR_RTC) }, + { .i = DEC_CPU_IRQ_NR(KN01_CPU_INR_RTC) } }, + { { .i = DEC_CPU_IRQ_MASK(KN01_CPU_INR_DZ11) }, + { .i = DEC_CPU_IRQ_NR(KN01_CPU_INR_DZ11) } }, + { { .i = DEC_CPU_IRQ_MASK(KN01_CPU_INR_SII) }, + { .i = DEC_CPU_IRQ_NR(KN01_CPU_INR_SII) } }, + { { .i = DEC_CPU_IRQ_MASK(KN01_CPU_INR_LANCE) }, + { .i = DEC_CPU_IRQ_NR(KN01_CPU_INR_LANCE) } }, + { { .i = DEC_CPU_IRQ_ALL }, + { .p = cpu_all_int } }, +}; + void __init dec_init_kn01(void) { - /* - * Setup some memory addresses. - */ - dec_rtc_base = (char *) KN01_RTC_BASE; - - /* - * Setup interrupt structure - */ - dec_interrupt[CLOCK].cpu_mask = IE_IRQ3; - dec_interrupt[CLOCK].iemask = 0; - cpu_mask_tbl[0] = IE_IRQ3; - cpu_irq_nr[0] = CLOCK; - - dec_interrupt[SCSI_INT].cpu_mask = IE_IRQ0; - dec_interrupt[SCSI_INT].iemask = 0; - cpu_mask_tbl[1] = IE_IRQ0; - cpu_irq_nr[1] = SCSI_INT; - - dec_interrupt[ETHER].cpu_mask = IE_IRQ1; - dec_interrupt[ETHER].iemask = 0; - cpu_mask_tbl[2] = IE_IRQ1; - cpu_irq_nr[2] = ETHER; - - dec_interrupt[SERIAL].cpu_mask = IE_IRQ2; - dec_interrupt[SERIAL].iemask = 0; - cpu_mask_tbl[3] = IE_IRQ2; - cpu_irq_nr[3] = SERIAL; - - dec_interrupt[MEMORY].cpu_mask = IE_IRQ4; - dec_interrupt[MEMORY].iemask = 0; - cpu_mask_tbl[4] = IE_IRQ4; - cpu_irq_nr[4] = MEMORY; - - dec_interrupt[FPU].cpu_mask = IE_IRQ5; - dec_interrupt[FPU].iemask = 0; - cpu_mask_tbl[5] = IE_IRQ5; - cpu_irq_nr[5] = FPU; + /* IRQ routing. */ + memcpy(&dec_interrupt, &kn01_interrupt, + sizeof(kn01_interrupt)); + + /* CPU IRQ priorities. */ + memcpy(&cpu_mask_nr_tbl, &kn01_cpu_mask_nr_tbl, + sizeof(kn01_cpu_mask_nr_tbl)); + + mips_cpu_irq_init(DEC_CPU_IRQ_BASE); + } /* dec_init_kn01 */ + /* - * Machine-specific initialisation for kn230, aka MIPSmate, aka DS5100 - * - * There are a lot of experiments to do, this is definitely incomplete. + * Machine-specific initialisation for KN230, aka DS5100, aka MIPSmate. */ +static int kn230_interrupt[DEC_NR_INTS] __initdata = { + [DEC_IRQ_CASCADE] = -1, + [DEC_IRQ_AB_RECV] = -1, + [DEC_IRQ_AB_XMIT] = -1, + [DEC_IRQ_DZ11] = DEC_CPU_IRQ_NR(KN230_CPU_INR_DZ11), + [DEC_IRQ_ASC] = -1, + [DEC_IRQ_FLOPPY] = -1, + [DEC_IRQ_FPU] = DEC_CPU_IRQ_NR(DEC_CPU_INR_FPU), + [DEC_IRQ_HALT] = DEC_CPU_IRQ_NR(KN230_CPU_INR_HALT), + [DEC_IRQ_ISDN] = -1, + [DEC_IRQ_LANCE] = DEC_CPU_IRQ_NR(KN230_CPU_INR_LANCE), + [DEC_IRQ_BUS] = DEC_CPU_IRQ_NR(KN230_CPU_INR_BUS), + [DEC_IRQ_PSU] = -1, + [DEC_IRQ_RTC] = DEC_CPU_IRQ_NR(KN230_CPU_INR_RTC), + [DEC_IRQ_SCC0] = -1, + [DEC_IRQ_SCC1] = -1, + [DEC_IRQ_SII] = DEC_CPU_IRQ_NR(KN230_CPU_INR_SII), + [DEC_IRQ_TC0] = -1, + [DEC_IRQ_TC1] = -1, + [DEC_IRQ_TC2] = -1, + [DEC_IRQ_TIMER] = -1, + [DEC_IRQ_VIDEO] = -1, + [DEC_IRQ_ASC_MERR] = -1, + [DEC_IRQ_ASC_ERR] = -1, + [DEC_IRQ_ASC_DMA] = -1, + [DEC_IRQ_FLOPPY_ERR] = -1, + [DEC_IRQ_ISDN_ERR] = -1, + [DEC_IRQ_ISDN_RXDMA] = -1, + [DEC_IRQ_ISDN_TXDMA] = -1, + [DEC_IRQ_LANCE_MERR] = -1, + [DEC_IRQ_SCC0A_RXERR] = -1, + [DEC_IRQ_SCC0A_RXDMA] = -1, + [DEC_IRQ_SCC0A_TXERR] = -1, + [DEC_IRQ_SCC0A_TXDMA] = -1, + [DEC_IRQ_AB_RXERR] = -1, + [DEC_IRQ_AB_RXDMA] = -1, + [DEC_IRQ_AB_TXERR] = -1, + [DEC_IRQ_AB_TXDMA] = -1, + [DEC_IRQ_SCC1A_RXERR] = -1, + [DEC_IRQ_SCC1A_RXDMA] = -1, + [DEC_IRQ_SCC1A_TXERR] = -1, + [DEC_IRQ_SCC1A_TXDMA] = -1, +}; + +static int_ptr kn230_cpu_mask_nr_tbl[][2] __initdata = { + { { .i = DEC_CPU_IRQ_MASK(KN230_CPU_INR_BUS) }, + { .i = DEC_CPU_IRQ_NR(KN230_CPU_INR_BUS) } }, + { { .i = DEC_CPU_IRQ_MASK(KN230_CPU_INR_RTC) }, + { .i = DEC_CPU_IRQ_NR(KN230_CPU_INR_RTC) } }, + { { .i = DEC_CPU_IRQ_MASK(KN230_CPU_INR_DZ11) }, + { .i = DEC_CPU_IRQ_NR(KN230_CPU_INR_DZ11) } }, + { { .i = DEC_CPU_IRQ_MASK(KN230_CPU_INR_SII) }, + { .i = DEC_CPU_IRQ_NR(KN230_CPU_INR_SII) } }, + { { .i = DEC_CPU_IRQ_ALL }, + { .p = cpu_all_int } }, +}; + void __init dec_init_kn230(void) { - /* - * Setup some memory addresses. - */ - dec_rtc_base = (char *) KN01_RTC_BASE; - - /* - * Setup interrupt structure - */ - dec_interrupt[CLOCK].cpu_mask = IE_IRQ2; - dec_interrupt[CLOCK].iemask = 0; - cpu_mask_tbl[0] = IE_IRQ2; - cpu_irq_nr[0] = CLOCK; - - dec_interrupt[FPU].cpu_mask = IE_IRQ5; - dec_interrupt[FPU].iemask = 0; - cpu_mask_tbl[5] = IE_IRQ5; - cpu_irq_nr[5] = FPU; + /* IRQ routing. */ + memcpy(&dec_interrupt, &kn230_interrupt, + sizeof(kn230_interrupt)); + + /* CPU IRQ priorities. */ + memcpy(&cpu_mask_nr_tbl, &kn230_cpu_mask_nr_tbl, + sizeof(kn230_cpu_mask_nr_tbl)); + + mips_cpu_irq_init(DEC_CPU_IRQ_BASE); + } /* dec_init_kn230 */ + /* - * Machine-specific initialisation for kn02, aka 3max, aka DS5000/2xx. + * Machine-specific initialisation for KN02, aka DS5000/200, aka 3max. */ +static int kn02_interrupt[DEC_NR_INTS] __initdata = { + [DEC_IRQ_CASCADE] = DEC_CPU_IRQ_NR(KN02_CPU_INR_CASCADE), + [DEC_IRQ_AB_RECV] = -1, + [DEC_IRQ_AB_XMIT] = -1, + [DEC_IRQ_DZ11] = KN02_IRQ_NR(KN02_CSR_INR_DZ11), + [DEC_IRQ_ASC] = KN02_IRQ_NR(KN02_CSR_INR_ASC), + [DEC_IRQ_FLOPPY] = -1, + [DEC_IRQ_FPU] = DEC_CPU_IRQ_NR(DEC_CPU_INR_FPU), + [DEC_IRQ_HALT] = -1, + [DEC_IRQ_ISDN] = -1, + [DEC_IRQ_LANCE] = KN02_IRQ_NR(KN02_CSR_INR_LANCE), + [DEC_IRQ_BUS] = DEC_CPU_IRQ_NR(KN02_CPU_INR_BUS), + [DEC_IRQ_PSU] = -1, + [DEC_IRQ_RTC] = DEC_CPU_IRQ_NR(KN02_CPU_INR_RTC), + [DEC_IRQ_SCC0] = -1, + [DEC_IRQ_SCC1] = -1, + [DEC_IRQ_SII] = -1, + [DEC_IRQ_TC0] = KN02_IRQ_NR(KN02_CSR_INR_TC0), + [DEC_IRQ_TC1] = KN02_IRQ_NR(KN02_CSR_INR_TC1), + [DEC_IRQ_TC2] = KN02_IRQ_NR(KN02_CSR_INR_TC2), + [DEC_IRQ_TIMER] = -1, + [DEC_IRQ_VIDEO] = -1, + [DEC_IRQ_ASC_MERR] = -1, + [DEC_IRQ_ASC_ERR] = -1, + [DEC_IRQ_ASC_DMA] = -1, + [DEC_IRQ_FLOPPY_ERR] = -1, + [DEC_IRQ_ISDN_ERR] = -1, + [DEC_IRQ_ISDN_RXDMA] = -1, + [DEC_IRQ_ISDN_TXDMA] = -1, + [DEC_IRQ_LANCE_MERR] = -1, + [DEC_IRQ_SCC0A_RXERR] = -1, + [DEC_IRQ_SCC0A_RXDMA] = -1, + [DEC_IRQ_SCC0A_TXERR] = -1, + [DEC_IRQ_SCC0A_TXDMA] = -1, + [DEC_IRQ_AB_RXERR] = -1, + [DEC_IRQ_AB_RXDMA] = -1, + [DEC_IRQ_AB_TXERR] = -1, + [DEC_IRQ_AB_TXDMA] = -1, + [DEC_IRQ_SCC1A_RXERR] = -1, + [DEC_IRQ_SCC1A_RXDMA] = -1, + [DEC_IRQ_SCC1A_TXERR] = -1, + [DEC_IRQ_SCC1A_TXDMA] = -1, +}; + +static int_ptr kn02_cpu_mask_nr_tbl[][2] __initdata = { + { { .i = DEC_CPU_IRQ_MASK(KN02_CPU_INR_BUS) }, + { .i = DEC_CPU_IRQ_NR(KN02_CPU_INR_BUS) } }, + { { .i = DEC_CPU_IRQ_MASK(KN02_CPU_INR_RTC) }, + { .i = DEC_CPU_IRQ_NR(KN02_CPU_INR_RTC) } }, + { { .i = DEC_CPU_IRQ_MASK(KN02_CPU_INR_CASCADE) }, + { .p = kn02_io_int } }, + { { .i = DEC_CPU_IRQ_ALL }, + { .p = cpu_all_int } }, +}; + +static int_ptr kn02_asic_mask_nr_tbl[][2] __initdata = { + { { .i = KN02_IRQ_MASK(KN02_CSR_INR_DZ11) }, + { .i = KN02_IRQ_NR(KN02_CSR_INR_DZ11) } }, + { { .i = KN02_IRQ_MASK(KN02_CSR_INR_ASC) }, + { .i = KN02_IRQ_NR(KN02_CSR_INR_ASC) } }, + { { .i = KN02_IRQ_MASK(KN02_CSR_INR_LANCE) }, + { .i = KN02_IRQ_NR(KN02_CSR_INR_LANCE) } }, + { { .i = KN02_IRQ_MASK(KN02_CSR_INR_TC2) }, + { .i = KN02_IRQ_NR(KN02_CSR_INR_TC2) } }, + { { .i = KN02_IRQ_MASK(KN02_CSR_INR_TC1) }, + { .i = KN02_IRQ_NR(KN02_CSR_INR_TC1) } }, + { { .i = KN02_IRQ_MASK(KN02_CSR_INR_TC0) }, + { .i = KN02_IRQ_NR(KN02_CSR_INR_TC0) } }, + { { .i = KN02_IRQ_ALL }, + { .p = kn02_all_int } }, +}; + void __init dec_init_kn02(void) { - /* - * Setup some memory addresses. FIXME: probably incomplete! - */ - dec_rtc_base = (char *) KN02_RTC_BASE; - isr = (void *) KN02_CSR_ADDR; - imr = (void *) KN02_CSR_ADDR; - - /* - * Setup IOASIC interrupt - */ - cpu_ivec_tbl[1] = kn02_io_int; - cpu_mask_tbl[1] = IE_IRQ0; - cpu_irq_nr[1] = -1; - *imr = *imr & 0xff00ff00; - - /* - * Setup interrupt structure - */ - dec_interrupt[CLOCK].cpu_mask = IE_IRQ1; - dec_interrupt[CLOCK].iemask = 0; - cpu_mask_tbl[0] = IE_IRQ1; - cpu_irq_nr[0] = CLOCK; - - dec_interrupt[SCSI_INT].cpu_mask = IE_IRQ0; - dec_interrupt[SCSI_INT].iemask = KN02_SLOT5; - asic_mask_tbl[0] = KN02_SLOT5; - asic_irq_nr[0] = SCSI_INT; - - dec_interrupt[ETHER].cpu_mask = IE_IRQ0; - dec_interrupt[ETHER].iemask = KN02_SLOT6; - asic_mask_tbl[1] = KN02_SLOT6; - asic_irq_nr[1] = ETHER; - - dec_interrupt[SERIAL].cpu_mask = IE_IRQ0; - dec_interrupt[SERIAL].iemask = KN02_SLOT7; - asic_mask_tbl[2] = KN02_SLOT7; - asic_irq_nr[2] = SERIAL; - - dec_interrupt[TC0].cpu_mask = IE_IRQ0; - dec_interrupt[TC0].iemask = KN02_SLOT0; - asic_mask_tbl[3] = KN02_SLOT0; - asic_irq_nr[3] = TC0; - - dec_interrupt[TC1].cpu_mask = IE_IRQ0; - dec_interrupt[TC1].iemask = KN02_SLOT1; - asic_mask_tbl[4] = KN02_SLOT1; - asic_irq_nr[4] = TC1; - - dec_interrupt[TC2].cpu_mask = IE_IRQ0; - dec_interrupt[TC2].iemask = KN02_SLOT2; - asic_mask_tbl[5] = KN02_SLOT2; - asic_irq_nr[5] = TC2; - - dec_interrupt[MEMORY].cpu_mask = IE_IRQ3; - dec_interrupt[MEMORY].iemask = 0; - cpu_mask_tbl[2] = IE_IRQ3; - cpu_irq_nr[2] = MEMORY; - - dec_interrupt[FPU].cpu_mask = IE_IRQ5; - dec_interrupt[FPU].iemask = 0; - cpu_mask_tbl[3] = IE_IRQ5; - cpu_irq_nr[3] = FPU; + /* IRQ routing. */ + memcpy(&dec_interrupt, &kn02_interrupt, + sizeof(kn02_interrupt)); + + /* CPU IRQ priorities. */ + memcpy(&cpu_mask_nr_tbl, &kn02_cpu_mask_nr_tbl, + sizeof(kn02_cpu_mask_nr_tbl)); + + /* KN02 CSR IRQ priorities. */ + memcpy(&asic_mask_nr_tbl, &kn02_asic_mask_nr_tbl, + sizeof(kn02_asic_mask_nr_tbl)); + + mips_cpu_irq_init(DEC_CPU_IRQ_BASE); + init_kn02_irqs(KN02_IRQ_BASE); } /* dec_init_kn02 */ + /* - * Machine-specific initialisation for kn02ba, aka 3min, aka DS5000/1xx. + * Machine-specific initialisation for KN02-BA, aka DS5000/1xx + * (xx = 20, 25, 33), aka 3min. Also applies to KN04(-BA), aka + * DS5000/150, aka 4min. */ +static int kn02ba_interrupt[DEC_NR_INTS] __initdata = { + [DEC_IRQ_CASCADE] = DEC_CPU_IRQ_NR(KN02BA_CPU_INR_CASCADE), + [DEC_IRQ_AB_RECV] = -1, + [DEC_IRQ_AB_XMIT] = -1, + [DEC_IRQ_DZ11] = -1, + [DEC_IRQ_ASC] = IO_IRQ_NR(KN02BA_IO_INR_ASC), + [DEC_IRQ_FLOPPY] = -1, + [DEC_IRQ_FPU] = DEC_CPU_IRQ_NR(DEC_CPU_INR_FPU), + [DEC_IRQ_HALT] = DEC_CPU_IRQ_NR(KN02BA_CPU_INR_HALT), + [DEC_IRQ_ISDN] = -1, + [DEC_IRQ_LANCE] = IO_IRQ_NR(KN02BA_IO_INR_LANCE), + [DEC_IRQ_BUS] = IO_IRQ_NR(KN02BA_IO_INR_BUS), + [DEC_IRQ_PSU] = IO_IRQ_NR(KN02BA_IO_INR_PSU), + [DEC_IRQ_RTC] = IO_IRQ_NR(KN02BA_IO_INR_RTC), + [DEC_IRQ_SCC0] = IO_IRQ_NR(KN02BA_IO_INR_SCC0), + [DEC_IRQ_SCC1] = IO_IRQ_NR(KN02BA_IO_INR_SCC1), + [DEC_IRQ_SII] = -1, + [DEC_IRQ_TC0] = DEC_CPU_IRQ_NR(KN02BA_CPU_INR_TC0), + [DEC_IRQ_TC1] = DEC_CPU_IRQ_NR(KN02BA_CPU_INR_TC1), + [DEC_IRQ_TC2] = DEC_CPU_IRQ_NR(KN02BA_CPU_INR_TC2), + [DEC_IRQ_TIMER] = -1, + [DEC_IRQ_VIDEO] = -1, + [DEC_IRQ_ASC_MERR] = IO_IRQ_NR(IO_INR_ASC_MERR), + [DEC_IRQ_ASC_ERR] = IO_IRQ_NR(IO_INR_ASC_ERR), + [DEC_IRQ_ASC_DMA] = IO_IRQ_NR(IO_INR_ASC_DMA), + [DEC_IRQ_FLOPPY_ERR] = -1, + [DEC_IRQ_ISDN_ERR] = -1, + [DEC_IRQ_ISDN_RXDMA] = -1, + [DEC_IRQ_ISDN_TXDMA] = -1, + [DEC_IRQ_LANCE_MERR] = IO_IRQ_NR(IO_INR_LANCE_MERR), + [DEC_IRQ_SCC0A_RXERR] = IO_IRQ_NR(IO_INR_SCC0A_RXERR), + [DEC_IRQ_SCC0A_RXDMA] = IO_IRQ_NR(IO_INR_SCC0A_RXDMA), + [DEC_IRQ_SCC0A_TXERR] = IO_IRQ_NR(IO_INR_SCC0A_TXERR), + [DEC_IRQ_SCC0A_TXDMA] = IO_IRQ_NR(IO_INR_SCC0A_TXDMA), + [DEC_IRQ_AB_RXERR] = -1, + [DEC_IRQ_AB_RXDMA] = -1, + [DEC_IRQ_AB_TXERR] = -1, + [DEC_IRQ_AB_TXDMA] = -1, + [DEC_IRQ_SCC1A_RXERR] = IO_IRQ_NR(IO_INR_SCC1A_RXERR), + [DEC_IRQ_SCC1A_RXDMA] = IO_IRQ_NR(IO_INR_SCC1A_RXDMA), + [DEC_IRQ_SCC1A_TXERR] = IO_IRQ_NR(IO_INR_SCC1A_TXERR), + [DEC_IRQ_SCC1A_TXDMA] = IO_IRQ_NR(IO_INR_SCC1A_TXDMA), +}; + +static int_ptr kn02ba_cpu_mask_nr_tbl[][2] __initdata = { + { { .i = DEC_CPU_IRQ_MASK(KN02BA_CPU_INR_CASCADE) }, + { .p = kn02xa_io_int } }, + { { .i = DEC_CPU_IRQ_MASK(KN02BA_CPU_INR_TC2) }, + { .i = DEC_CPU_IRQ_NR(KN02BA_CPU_INR_TC2) } }, + { { .i = DEC_CPU_IRQ_MASK(KN02BA_CPU_INR_TC1) }, + { .i = DEC_CPU_IRQ_NR(KN02BA_CPU_INR_TC1) } }, + { { .i = DEC_CPU_IRQ_MASK(KN02BA_CPU_INR_TC0) }, + { .i = DEC_CPU_IRQ_NR(KN02BA_CPU_INR_TC0) } }, + { { .i = DEC_CPU_IRQ_ALL }, + { .p = cpu_all_int } }, +}; + +static int_ptr kn02ba_asic_mask_nr_tbl[][2] __initdata = { + { { .i = IO_IRQ_MASK(KN02BA_IO_INR_BUS) }, + { .i = IO_IRQ_NR(KN02BA_IO_INR_BUS) } }, + { { .i = IO_IRQ_MASK(KN02BA_IO_INR_RTC) }, + { .i = IO_IRQ_NR(KN02BA_IO_INR_RTC) } }, + { { .i = IO_IRQ_DMA }, + { .p = asic_dma_int } }, + { { .i = IO_IRQ_MASK(KN02BA_IO_INR_SCC0) }, + { .i = IO_IRQ_NR(KN02BA_IO_INR_SCC0) } }, + { { .i = IO_IRQ_MASK(KN02BA_IO_INR_SCC1) }, + { .i = IO_IRQ_NR(KN02BA_IO_INR_SCC1) } }, + { { .i = IO_IRQ_MASK(KN02BA_IO_INR_ASC) }, + { .i = IO_IRQ_NR(KN02BA_IO_INR_ASC) } }, + { { .i = IO_IRQ_MASK(KN02BA_IO_INR_LANCE) }, + { .i = IO_IRQ_NR(KN02BA_IO_INR_LANCE) } }, + { { .i = IO_IRQ_ALL }, + { .p = asic_all_int } }, +}; + void __init dec_init_kn02ba(void) { - /* - * Setup some memory addresses. - */ - ioasic_base = (void *) KN02XA_IOASIC_BASE; - dec_rtc_base = (char *) KN02XA_RTC_BASE; - isr = (void *) KN02XA_IOASIC_REG(SIR); - imr = (void *) KN02XA_IOASIC_REG(SIMR); - - /* - * Setup IOASIC interrupt - */ - cpu_mask_tbl[0] = IE_IRQ3; - cpu_irq_nr[0] = -1; - cpu_ivec_tbl[0] = kn02xa_io_int; - *imr = 0; - - /* - * Setup interrupt structure - */ - dec_interrupt[CLOCK].cpu_mask = IE_IRQ3; - dec_interrupt[CLOCK].iemask = KMIN_CLOCK; - asic_mask_tbl[0] = KMIN_CLOCK; - asic_irq_nr[0] = CLOCK; - - dec_interrupt[SCSI_DMA_INT].cpu_mask = IE_IRQ3; - dec_interrupt[SCSI_DMA_INT].iemask = SCSI_DMA_INTS; - asic_mask_tbl[1] = SCSI_DMA_INTS; - asic_irq_nr[1] = SCSI_DMA_INT; - - dec_interrupt[SCSI_INT].cpu_mask = IE_IRQ3; - dec_interrupt[SCSI_INT].iemask = SCSI_CHIP; - asic_mask_tbl[2] = SCSI_CHIP; - asic_irq_nr[2] = SCSI_INT; - - dec_interrupt[ETHER].cpu_mask = IE_IRQ3; - dec_interrupt[ETHER].iemask = LANCE_INTS; - asic_mask_tbl[3] = LANCE_INTS; - asic_irq_nr[3] = ETHER; - - dec_interrupt[SERIAL].cpu_mask = IE_IRQ3; - dec_interrupt[SERIAL].iemask = SERIAL_INTS; - asic_mask_tbl[4] = SERIAL_INTS; - asic_irq_nr[4] = SERIAL; - - dec_interrupt[MEMORY].cpu_mask = IE_IRQ3; - dec_interrupt[MEMORY].iemask = KMIN_TIMEOUT; - asic_mask_tbl[5] = KMIN_TIMEOUT; - asic_irq_nr[5] = MEMORY; - - dec_interrupt[TC0].cpu_mask = IE_IRQ0; - dec_interrupt[TC0].iemask = 0; - cpu_mask_tbl[1] = IE_IRQ0; - cpu_irq_nr[1] = TC0; - - dec_interrupt[TC1].cpu_mask = IE_IRQ1; - dec_interrupt[TC1].iemask = 0; - cpu_mask_tbl[2] = IE_IRQ1; - cpu_irq_nr[2] = TC1; - - dec_interrupt[TC2].cpu_mask = IE_IRQ2; - dec_interrupt[TC2].iemask = 0; - cpu_mask_tbl[3] = IE_IRQ2; - cpu_irq_nr[3] = TC2; - - dec_interrupt[HALT].cpu_mask = IE_IRQ4; - dec_interrupt[HALT].iemask = 0; - cpu_mask_tbl[4] = IE_IRQ4; - cpu_irq_nr[4] = HALT; - - dec_interrupt[FPU].cpu_mask = IE_IRQ5; - dec_interrupt[FPU].iemask = 0; - cpu_mask_tbl[5] = IE_IRQ5; - cpu_irq_nr[5] = FPU; + /* IRQ routing. */ + memcpy(&dec_interrupt, &kn02ba_interrupt, + sizeof(kn02ba_interrupt)); + + /* CPU IRQ priorities. */ + memcpy(&cpu_mask_nr_tbl, &kn02ba_cpu_mask_nr_tbl, + sizeof(kn02ba_cpu_mask_nr_tbl)); + + /* I/O ASIC IRQ priorities. */ + memcpy(&asic_mask_nr_tbl, &kn02ba_asic_mask_nr_tbl, + sizeof(kn02ba_asic_mask_nr_tbl)); + + mips_cpu_irq_init(DEC_CPU_IRQ_BASE); + init_ioasic_irqs(IO_IRQ_BASE); - dec_halt_init(&irq10); } /* dec_init_kn02ba */ + /* - * Machine-specific initialisation for kn02ca, aka maxine, aka DS5000/2x. + * Machine-specific initialisation for KN02-CA, aka DS5000/xx, + * (xx = 20, 25, 33), aka MAXine. Also applies to KN04(-CA), aka + * DS5000/50, aka 4MAXine. */ +static int kn02ca_interrupt[DEC_NR_INTS] __initdata = { + [DEC_IRQ_CASCADE] = DEC_CPU_IRQ_NR(KN02CA_CPU_INR_CASCADE), + [DEC_IRQ_AB_RECV] = IO_IRQ_NR(KN02CA_IO_INR_AB_RECV), + [DEC_IRQ_AB_XMIT] = IO_IRQ_NR(KN02CA_IO_INR_AB_XMIT), + [DEC_IRQ_DZ11] = -1, + [DEC_IRQ_ASC] = IO_IRQ_NR(KN02CA_IO_INR_ASC), + [DEC_IRQ_FLOPPY] = IO_IRQ_NR(KN02CA_IO_INR_FLOPPY), + [DEC_IRQ_FPU] = DEC_CPU_IRQ_NR(DEC_CPU_INR_FPU), + [DEC_IRQ_HALT] = DEC_CPU_IRQ_NR(KN02CA_CPU_INR_HALT), + [DEC_IRQ_ISDN] = IO_IRQ_NR(KN02CA_IO_INR_ISDN), + [DEC_IRQ_LANCE] = IO_IRQ_NR(KN02CA_IO_INR_LANCE), + [DEC_IRQ_BUS] = DEC_CPU_IRQ_NR(KN02CA_CPU_INR_BUS), + [DEC_IRQ_PSU] = -1, + [DEC_IRQ_RTC] = DEC_CPU_IRQ_NR(KN02CA_CPU_INR_RTC), + [DEC_IRQ_SCC0] = IO_IRQ_NR(KN02CA_IO_INR_SCC0), + [DEC_IRQ_SCC1] = -1, + [DEC_IRQ_SII] = -1, + [DEC_IRQ_TC0] = IO_IRQ_NR(KN02CA_IO_INR_TC0), + [DEC_IRQ_TC1] = IO_IRQ_NR(KN02CA_IO_INR_TC1), + [DEC_IRQ_TC2] = -1, + [DEC_IRQ_TIMER] = DEC_CPU_IRQ_NR(KN02CA_CPU_INR_TIMER), + [DEC_IRQ_VIDEO] = IO_IRQ_NR(KN02CA_IO_INR_VIDEO), + [DEC_IRQ_ASC_MERR] = IO_IRQ_NR(IO_INR_ASC_MERR), + [DEC_IRQ_ASC_ERR] = IO_IRQ_NR(IO_INR_ASC_ERR), + [DEC_IRQ_ASC_DMA] = IO_IRQ_NR(IO_INR_ASC_DMA), + [DEC_IRQ_FLOPPY_ERR] = IO_IRQ_NR(IO_INR_FLOPPY_ERR), + [DEC_IRQ_ISDN_ERR] = IO_IRQ_NR(IO_INR_ISDN_ERR), + [DEC_IRQ_ISDN_RXDMA] = IO_IRQ_NR(IO_INR_ISDN_RXDMA), + [DEC_IRQ_ISDN_TXDMA] = IO_IRQ_NR(IO_INR_ISDN_TXDMA), + [DEC_IRQ_LANCE_MERR] = IO_IRQ_NR(IO_INR_LANCE_MERR), + [DEC_IRQ_SCC0A_RXERR] = IO_IRQ_NR(IO_INR_SCC0A_RXERR), + [DEC_IRQ_SCC0A_RXDMA] = IO_IRQ_NR(IO_INR_SCC0A_RXDMA), + [DEC_IRQ_SCC0A_TXERR] = IO_IRQ_NR(IO_INR_SCC0A_TXERR), + [DEC_IRQ_SCC0A_TXDMA] = IO_IRQ_NR(IO_INR_SCC0A_TXDMA), + [DEC_IRQ_AB_RXERR] = IO_IRQ_NR(IO_INR_AB_RXERR), + [DEC_IRQ_AB_RXDMA] = IO_IRQ_NR(IO_INR_AB_RXDMA), + [DEC_IRQ_AB_TXERR] = IO_IRQ_NR(IO_INR_AB_TXERR), + [DEC_IRQ_AB_TXDMA] = IO_IRQ_NR(IO_INR_AB_TXDMA), + [DEC_IRQ_SCC1A_RXERR] = -1, + [DEC_IRQ_SCC1A_RXDMA] = -1, + [DEC_IRQ_SCC1A_TXERR] = -1, + [DEC_IRQ_SCC1A_TXDMA] = -1, +}; + +static int_ptr kn02ca_cpu_mask_nr_tbl[][2] __initdata = { + { { .i = DEC_CPU_IRQ_MASK(KN02CA_CPU_INR_BUS) }, + { .i = DEC_CPU_IRQ_NR(KN02CA_CPU_INR_BUS) } }, + { { .i = DEC_CPU_IRQ_MASK(KN02CA_CPU_INR_RTC) }, + { .i = DEC_CPU_IRQ_NR(KN02CA_CPU_INR_RTC) } }, + { { .i = DEC_CPU_IRQ_MASK(KN02CA_CPU_INR_CASCADE) }, + { .p = kn02xa_io_int } }, + { { .i = DEC_CPU_IRQ_ALL }, + { .p = cpu_all_int } }, +}; + +static int_ptr kn02ca_asic_mask_nr_tbl[][2] __initdata = { + { { .i = IO_IRQ_DMA }, + { .p = asic_dma_int } }, + { { .i = IO_IRQ_MASK(KN02CA_IO_INR_SCC0) }, + { .i = IO_IRQ_NR(KN02CA_IO_INR_SCC0) } }, + { { .i = IO_IRQ_MASK(KN02CA_IO_INR_ASC) }, + { .i = IO_IRQ_NR(KN02CA_IO_INR_ASC) } }, + { { .i = IO_IRQ_MASK(KN02CA_IO_INR_LANCE) }, + { .i = IO_IRQ_NR(KN02CA_IO_INR_LANCE) } }, + { { .i = IO_IRQ_MASK(KN02CA_IO_INR_TC1) }, + { .i = IO_IRQ_NR(KN02CA_IO_INR_TC1) } }, + { { .i = IO_IRQ_MASK(KN02CA_IO_INR_TC0) }, + { .i = IO_IRQ_NR(KN02CA_IO_INR_TC0) } }, + { { .i = IO_IRQ_ALL }, + { .p = asic_all_int } }, +}; + void __init dec_init_kn02ca(void) { - /* - * Setup some memory addresses. FIXME: probably incomplete! - */ - ioasic_base = (void *) KN02XA_IOASIC_BASE; - dec_rtc_base = (char *) KN02XA_RTC_BASE; - isr = (void *) KN02XA_IOASIC_REG(SIR); - imr = (void *) KN02XA_IOASIC_REG(SIMR); - - /* - * Setup IOASIC interrupt - */ - cpu_ivec_tbl[1] = kn02xa_io_int; - cpu_irq_nr[1] = -1; - cpu_mask_tbl[1] = IE_IRQ3; - *imr = 0; - - /* - * Setup interrupt structure - */ - dec_interrupt[CLOCK].cpu_mask = IE_IRQ1; - dec_interrupt[CLOCK].iemask = 0; - cpu_mask_tbl[0] = IE_IRQ1; - cpu_irq_nr[0] = CLOCK; - - dec_interrupt[SCSI_DMA_INT].cpu_mask = IE_IRQ3; - dec_interrupt[SCSI_DMA_INT].iemask = SCSI_DMA_INTS; - asic_mask_tbl[0] = SCSI_DMA_INTS; - asic_irq_nr[0] = SCSI_DMA_INT; - - dec_interrupt[SCSI_INT].cpu_mask = IE_IRQ3; - dec_interrupt[SCSI_INT].iemask = SCSI_CHIP; - asic_mask_tbl[1] = SCSI_CHIP; - asic_irq_nr[1] = SCSI_INT; - - dec_interrupt[ETHER].cpu_mask = IE_IRQ3; - dec_interrupt[ETHER].iemask = LANCE_INTS; - asic_mask_tbl[2] = LANCE_INTS; - asic_irq_nr[2] = ETHER; - - dec_interrupt[SERIAL].cpu_mask = IE_IRQ3; - dec_interrupt[SERIAL].iemask = XINE_SERIAL_INTS; - asic_mask_tbl[3] = XINE_SERIAL_INTS; - asic_irq_nr[3] = SERIAL; - - dec_interrupt[TC0].cpu_mask = IE_IRQ3; - dec_interrupt[TC0].iemask = MAXINE_TC0; - asic_mask_tbl[4] = MAXINE_TC0; - asic_irq_nr[4] = TC0; - - dec_interrupt[TC1].cpu_mask = IE_IRQ3; - dec_interrupt[TC1].iemask = MAXINE_TC1; - asic_mask_tbl[5] = MAXINE_TC1; - asic_irq_nr[5] = TC1; - - dec_interrupt[MEMORY].cpu_mask = IE_IRQ2; - dec_interrupt[MEMORY].iemask = 0; - cpu_mask_tbl[2] = IE_IRQ2; - cpu_irq_nr[2] = MEMORY; - - dec_interrupt[HALT].cpu_mask = IE_IRQ4; - dec_interrupt[HALT].iemask = 0; - cpu_mask_tbl[3] = IE_IRQ4; - cpu_irq_nr[3] = HALT; - - dec_interrupt[FPU].cpu_mask = IE_IRQ5; - dec_interrupt[FPU].iemask = 0; - cpu_mask_tbl[4] = IE_IRQ5; - cpu_irq_nr[4] = FPU; + /* IRQ routing. */ + memcpy(&dec_interrupt, &kn02ca_interrupt, + sizeof(kn02ca_interrupt)); + + /* CPU IRQ priorities. */ + memcpy(&cpu_mask_nr_tbl, &kn02ca_cpu_mask_nr_tbl, + sizeof(kn02ca_cpu_mask_nr_tbl)); + + /* I/O ASIC IRQ priorities. */ + memcpy(&asic_mask_nr_tbl, &kn02ca_asic_mask_nr_tbl, + sizeof(kn02ca_asic_mask_nr_tbl)); + + mips_cpu_irq_init(DEC_CPU_IRQ_BASE); + init_ioasic_irqs(IO_IRQ_BASE); - dec_halt_init(&irq10); } /* dec_init_kn02ca */ + /* - * Machine-specific initialisation for kn03, aka 3max+, aka DS5000/240. + * Machine-specific initialisation for KN03, aka DS5000/240, + * aka 3max+ and DS5900, aka BIGmax. Also applies to KN05, aka + * DS5000/260, aka 4max+ and DS5900/260. */ +static int kn03_interrupt[DEC_NR_INTS] __initdata = { + [DEC_IRQ_CASCADE] = DEC_CPU_IRQ_NR(KN03_CPU_INR_CASCADE), + [DEC_IRQ_AB_RECV] = -1, + [DEC_IRQ_AB_XMIT] = -1, + [DEC_IRQ_DZ11] = -1, + [DEC_IRQ_ASC] = IO_IRQ_NR(KN03_IO_INR_ASC), + [DEC_IRQ_FLOPPY] = -1, + [DEC_IRQ_FPU] = DEC_CPU_IRQ_NR(DEC_CPU_INR_FPU), + [DEC_IRQ_HALT] = DEC_CPU_IRQ_NR(KN03_CPU_INR_HALT), + [DEC_IRQ_ISDN] = -1, + [DEC_IRQ_LANCE] = IO_IRQ_NR(KN03_IO_INR_LANCE), + [DEC_IRQ_BUS] = DEC_CPU_IRQ_NR(KN03_CPU_INR_BUS), + [DEC_IRQ_PSU] = IO_IRQ_NR(KN03_IO_INR_PSU), + [DEC_IRQ_RTC] = DEC_CPU_IRQ_NR(KN03_CPU_INR_RTC), + [DEC_IRQ_SCC0] = IO_IRQ_NR(KN03_IO_INR_SCC0), + [DEC_IRQ_SCC1] = IO_IRQ_NR(KN03_IO_INR_SCC1), + [DEC_IRQ_SII] = -1, + [DEC_IRQ_TC0] = IO_IRQ_NR(KN03_IO_INR_TC0), + [DEC_IRQ_TC1] = IO_IRQ_NR(KN03_IO_INR_TC1), + [DEC_IRQ_TC2] = IO_IRQ_NR(KN03_IO_INR_TC2), + [DEC_IRQ_TIMER] = -1, + [DEC_IRQ_VIDEO] = -1, + [DEC_IRQ_ASC_MERR] = IO_IRQ_NR(IO_INR_ASC_MERR), + [DEC_IRQ_ASC_ERR] = IO_IRQ_NR(IO_INR_ASC_ERR), + [DEC_IRQ_ASC_DMA] = IO_IRQ_NR(IO_INR_ASC_DMA), + [DEC_IRQ_FLOPPY_ERR] = -1, + [DEC_IRQ_ISDN_ERR] = -1, + [DEC_IRQ_ISDN_RXDMA] = -1, + [DEC_IRQ_ISDN_TXDMA] = -1, + [DEC_IRQ_LANCE_MERR] = IO_IRQ_NR(IO_INR_LANCE_MERR), + [DEC_IRQ_SCC0A_RXERR] = IO_IRQ_NR(IO_INR_SCC0A_RXERR), + [DEC_IRQ_SCC0A_RXDMA] = IO_IRQ_NR(IO_INR_SCC0A_RXDMA), + [DEC_IRQ_SCC0A_TXERR] = IO_IRQ_NR(IO_INR_SCC0A_TXERR), + [DEC_IRQ_SCC0A_TXDMA] = IO_IRQ_NR(IO_INR_SCC0A_TXDMA), + [DEC_IRQ_AB_RXERR] = -1, + [DEC_IRQ_AB_RXDMA] = -1, + [DEC_IRQ_AB_TXERR] = -1, + [DEC_IRQ_AB_TXDMA] = -1, + [DEC_IRQ_SCC1A_RXERR] = IO_IRQ_NR(IO_INR_SCC1A_RXERR), + [DEC_IRQ_SCC1A_RXDMA] = IO_IRQ_NR(IO_INR_SCC1A_RXDMA), + [DEC_IRQ_SCC1A_TXERR] = IO_IRQ_NR(IO_INR_SCC1A_TXERR), + [DEC_IRQ_SCC1A_TXDMA] = IO_IRQ_NR(IO_INR_SCC1A_TXDMA), +}; + +static int_ptr kn03_cpu_mask_nr_tbl[][2] __initdata = { + { { .i = DEC_CPU_IRQ_MASK(KN03_CPU_INR_BUS) }, + { .i = DEC_CPU_IRQ_NR(KN03_CPU_INR_BUS) } }, + { { .i = DEC_CPU_IRQ_MASK(KN03_CPU_INR_RTC) }, + { .i = DEC_CPU_IRQ_NR(KN03_CPU_INR_RTC) } }, + { { .i = DEC_CPU_IRQ_MASK(KN03_CPU_INR_CASCADE) }, + { .p = kn03_io_int } }, + { { .i = DEC_CPU_IRQ_ALL }, + { .p = cpu_all_int } }, +}; + +static int_ptr kn03_asic_mask_nr_tbl[][2] __initdata = { + { { .i = IO_IRQ_DMA }, + { .p = asic_dma_int } }, + { { .i = IO_IRQ_MASK(KN03_IO_INR_SCC0) }, + { .i = IO_IRQ_NR(KN03_IO_INR_SCC0) } }, + { { .i = IO_IRQ_MASK(KN03_IO_INR_SCC1) }, + { .i = IO_IRQ_NR(KN03_IO_INR_SCC1) } }, + { { .i = IO_IRQ_MASK(KN03_IO_INR_ASC) }, + { .i = IO_IRQ_NR(KN03_IO_INR_ASC) } }, + { { .i = IO_IRQ_MASK(KN03_IO_INR_LANCE) }, + { .i = IO_IRQ_NR(KN03_IO_INR_LANCE) } }, + { { .i = IO_IRQ_MASK(KN03_IO_INR_TC2) }, + { .i = IO_IRQ_NR(KN03_IO_INR_TC2) } }, + { { .i = IO_IRQ_MASK(KN03_IO_INR_TC1) }, + { .i = IO_IRQ_NR(KN03_IO_INR_TC1) } }, + { { .i = IO_IRQ_MASK(KN03_IO_INR_TC0) }, + { .i = IO_IRQ_NR(KN03_IO_INR_TC0) } }, + { { .i = IO_IRQ_ALL }, + { .p = asic_all_int } }, +}; + void __init dec_init_kn03(void) { - /* - * Setup some memory addresses. FIXME: probably incomplete! - */ - ioasic_base = (void *) KN03_IOASIC_BASE; - dec_rtc_base = (char *) KN03_RTC_BASE; - isr = (void *) KN03_IOASIC_REG(SIR); - imr = (void *) KN03_IOASIC_REG(SIMR); - - /* - * Setup IOASIC interrupt - */ - cpu_ivec_tbl[1] = kn03_io_int; - cpu_mask_tbl[1] = IE_IRQ0; - cpu_irq_nr[1] = -1; - *imr = 0; - - /* - * Setup interrupt structure - */ - dec_interrupt[CLOCK].cpu_mask = IE_IRQ1; - dec_interrupt[CLOCK].iemask = 0; - cpu_mask_tbl[0] = IE_IRQ1; - cpu_irq_nr[0] = CLOCK; - - dec_interrupt[SCSI_DMA_INT].cpu_mask = IE_IRQ0; - dec_interrupt[SCSI_DMA_INT].iemask = SCSI_DMA_INTS; - asic_mask_tbl[0] = SCSI_DMA_INTS; - asic_irq_nr[0] = SCSI_DMA_INT; - - dec_interrupt[SCSI_INT].cpu_mask = IE_IRQ0; - dec_interrupt[SCSI_INT].iemask = SCSI_CHIP; - asic_mask_tbl[1] = SCSI_CHIP; - asic_irq_nr[1] = SCSI_INT; - - dec_interrupt[ETHER].cpu_mask = IE_IRQ0; - dec_interrupt[ETHER].iemask = LANCE_INTS; - asic_mask_tbl[2] = LANCE_INTS; - asic_irq_nr[2] = ETHER; - - dec_interrupt[SERIAL].cpu_mask = IE_IRQ0; - dec_interrupt[SERIAL].iemask = SERIAL_INTS; - asic_mask_tbl[3] = SERIAL_INTS; - asic_irq_nr[3] = SERIAL; - - dec_interrupt[TC0].cpu_mask = IE_IRQ0; - dec_interrupt[TC0].iemask = KN03_TC0; - asic_mask_tbl[4] = KN03_TC0; - asic_irq_nr[4] = TC0; - - dec_interrupt[TC1].cpu_mask = IE_IRQ0; - dec_interrupt[TC1].iemask = KN03_TC1; - asic_mask_tbl[5] = KN03_TC1; - asic_irq_nr[5] = TC1; - - dec_interrupt[TC2].cpu_mask = IE_IRQ0; - dec_interrupt[TC2].iemask = KN03_TC2; - asic_mask_tbl[6] = KN03_TC2; - asic_irq_nr[6] = TC2; - - dec_interrupt[MEMORY].cpu_mask = IE_IRQ3; - dec_interrupt[MEMORY].iemask = 0; - cpu_mask_tbl[2] = IE_IRQ3; - cpu_irq_nr[2] = MEMORY; - - dec_interrupt[HALT].cpu_mask = IE_IRQ4; - dec_interrupt[HALT].iemask = 0; - cpu_mask_tbl[3] = IE_IRQ4; - cpu_irq_nr[3] = HALT; - - dec_interrupt[FPU].cpu_mask = IE_IRQ5; - dec_interrupt[FPU].iemask = 0; - cpu_mask_tbl[4] = IE_IRQ5; - cpu_irq_nr[4] = FPU; + /* IRQ routing. */ + memcpy(&dec_interrupt, &kn03_interrupt, + sizeof(kn03_interrupt)); + + /* CPU IRQ priorities. */ + memcpy(&cpu_mask_nr_tbl, &kn03_cpu_mask_nr_tbl, + sizeof(kn03_cpu_mask_nr_tbl)); + + /* I/O ASIC IRQ priorities. */ + memcpy(&asic_mask_nr_tbl, &kn03_asic_mask_nr_tbl, + sizeof(kn03_asic_mask_nr_tbl)); + + mips_cpu_irq_init(DEC_CPU_IRQ_BASE); + init_ioasic_irqs(IO_IRQ_BASE); - dec_halt_init(&irq10); } /* dec_init_kn03 */ + + +void __init init_IRQ(void) +{ + switch (mips_machtype) { + case MACH_DS23100: /* DS2100/DS3100 Pmin/Pmax */ + dec_init_kn01(); + break; + case MACH_DS5100: /* DS5100 MIPSmate */ + dec_init_kn230(); + break; + case MACH_DS5000_200: /* DS5000/200 3max */ + dec_init_kn02(); + break; + case MACH_DS5000_1XX: /* DS5000/1xx 3min */ + dec_init_kn02ba(); + break; + case MACH_DS5000_2X0: /* DS5000/240 3max+ */ + case MACH_DS5900: /* DS5900 bigmax */ + dec_init_kn03(); + break; + case MACH_DS5000_XX: /* Personal DS5000/xx */ + dec_init_kn02ca(); + break; + case MACH_DS5800: /* DS5800 Isis */ + panic("Don't know how to set this up!"); + break; + case MACH_DS5400: /* DS5400 MIPSfair */ + panic("Don't know how to set this up!"); + break; + case MACH_DS5500: /* DS5500 MIPSfair-2 */ + panic("Don't know how to set this up!"); + break; + } + set_except_vector(0, decstation_handle_int); + + /* Free the FPU interrupt if the exception is present. */ + if (!cpu_has_nofpuex) { + cpu_fpu_mask = 0; + dec_interrupt[DEC_IRQ_FPU] = -1; + } + + /* Register board interrupts: FPU and cascade. */ + if (dec_interrupt[DEC_IRQ_FPU] >= 0) + setup_irq(dec_interrupt[DEC_IRQ_FPU], &fpuirq); + if (dec_interrupt[DEC_IRQ_CASCADE] >= 0) + setup_irq(dec_interrupt[DEC_IRQ_CASCADE], &ioirq); + + /* Register the bus error interrupt. */ + if (dec_interrupt[DEC_IRQ_BUS] >= 0 && busirq.handler) + setup_irq(dec_interrupt[DEC_IRQ_BUS], &busirq); + + /* Register the HALT interrupt. */ + if (dec_interrupt[DEC_IRQ_HALT] >= 0) + setup_irq(dec_interrupt[DEC_IRQ_HALT], &haltirq); +} + +EXPORT_SYMBOL(ioasic_base); +EXPORT_SYMBOL(dec_kn_slot_size); +EXPORT_SYMBOL(dec_interrupt); diff -Nru a/arch/mips/dec/time.c b/arch/mips/dec/time.c --- a/arch/mips/dec/time.c Tue Jul 1 18:44:37 2003 +++ b/arch/mips/dec/time.c Tue Jul 1 18:44:37 2003 @@ -2,12 +2,14 @@ * linux/arch/mips/dec/time.c * * Copyright (C) 1991, 1992, 1995 Linus Torvalds - * Copyright (C) 2000 Maciej W. Rozycki + * Copyright (C) 2000, 2003 Maciej W. Rozycki * * This file contains the time handling details for PC-style clocks as * found in some MIPS systems. * */ +#include +#include #include #include #include @@ -45,7 +47,9 @@ /* This is for machines which generate the exact clock. */ #define USECS_PER_JIFFY (1000000/HZ) -#define USECS_PER_JIFFY_FRAC ((1000000ULL << 32) / HZ & 0xffffffff) +#define USECS_PER_JIFFY_FRAC ((u32)((1000000ULL << 32) / HZ)) + +#define TICK_SIZE (tick_nsec / 1000) /* Cycle counter value at the previous timer interrupt.. */ @@ -99,7 +103,7 @@ } } /* Get last timer tick in absolute kernel time */ - count = read_32bit_cp0_register(CP0_COUNT); + count = read_c0_count(); /* .. relative to previous jiffy (32 bits is enough) */ count -= timerlo; @@ -110,7 +114,7 @@ : "r" (count), "r" (quotient)); /* - * Due to possible jiffies inconsistencies, we need to check + * Due to possible jiffies inconsistencies, we need to check * the result so that we'll get a timer that is monotonic. */ if (res >= USECS_PER_JIFFY) @@ -140,7 +144,7 @@ } } /* Get last timer tick in absolute kernel time */ - count = ioasic_read(FCTR); + count = ioasic_read(IO_REG_FCTR); /* .. relative to previous jiffy (32 bits is enough) */ count -= timerlo; @@ -160,9 +164,9 @@ return res; } -/* This function must be called with interrupts disabled +/* This function must be called with interrupts disabled * It was inspired by Steve McCanne's microtime-i386 for BSD. -- jrs - * + * * However, the pc-audio speaker driver changes the divisor so that * it gets interrupted rather more often - it loads 64 into the * counter rather than 11932! This has an adverse impact on @@ -176,7 +180,7 @@ * using either the RTC or the 8253 timer. The decision would be * based on whether there was any other device around that needed * to trample on the 8253. I'd set up the RTC to interrupt at 1024 Hz, - * and then do some jiggery to have a version of do_timer that + * and then do some jiggery to have a version of do_timer that * advanced the clock by 1/1024 s. Every time that reached over 1/100 * of a second, then do all the old code. If the time was kept correct * then do_gettimeoffset could just return 0 - there is no low order @@ -187,13 +191,11 @@ * often than every 120 us or so. * * Anyway, this needs more thought.... pjsg (1993-08-28) - * + * * If you are really that interested, you should be reading * comp.protocols.time.ntp! */ -#define TICK_SIZE tick - static unsigned long do_slow_gettimeoffset(void) { /* @@ -206,57 +208,58 @@ static unsigned long (*do_gettimeoffset) (void) = do_slow_gettimeoffset; /* - * This version of gettimeofday has near microsecond resolution. + * This version of gettimeofday has microsecond resolution + * and better than microsecond precision on fast x86 machines with TSC. */ void do_gettimeofday(struct timeval *tv) { - unsigned long flags; unsigned long seq; + unsigned long usec, sec; do { - seq = read_seqbegin_irqsave(&xtime_lock, flags); - *tv = xtime; - tv->tv_usec += do_gettimeoffset(); - - /* - * xtime is atomically updated in timer_bh. jiffies - wall_jiffies - * is nonzero if the timer bottom half hasnt executed yet. - */ - if (jiffies - wall_jiffies) - tv->tv_usec += USECS_PER_JIFFY; - - } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); - + seq = read_seqbegin(&xtime_lock); + usec = do_gettimeoffset(); + { + unsigned long lost = jiffies - wall_jiffies; + if (lost) + usec += lost * (1000000 / HZ); + } + sec = xtime.tv_sec; + usec += (xtime.tv_nsec / 1000); + } while (read_seqretry(&xtime_lock, seq)); - if (tv->tv_usec >= 1000000) { - tv->tv_usec -= 1000000; - tv->tv_sec++; + while (usec >= 1000000) { + usec -= 1000000; + sec++; } + + tv->tv_sec = sec; + tv->tv_usec = usec; } void do_settimeofday(struct timeval *tv) { write_seqlock_irq(&xtime_lock); - - /* This is revolting. We need to set the xtime.tv_usec - * correctly. However, the value in this location is - * is value at the last tick. - * Discover what correction gettimeofday - * would have done, and then undo it! + /* + * This is revolting. We need to set "xtime" correctly. However, the + * value in this location is the value at the most recent update of + * wall time. Discover what correction gettimeofday() would have + * made, and then undo it! */ tv->tv_usec -= do_gettimeoffset(); + tv->tv_usec -= (jiffies - wall_jiffies) * (1000000 / HZ); - if (tv->tv_usec < 0) { + while (tv->tv_usec < 0) { tv->tv_usec += 1000000; tv->tv_sec--; } - xtime = *tv; + xtime.tv_sec = tv->tv_sec; + xtime.tv_nsec = (tv->tv_usec * 1000); time_adjust = 0; /* stop active adjtime() */ time_status |= STA_UNSYNC; time_maxerror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT; - write_sequnlock_irq(&xtime_lock); } @@ -281,7 +284,7 @@ cmos_minutes = CMOS_READ(RTC_MINUTES); if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) - BCD_TO_BIN(cmos_minutes); + cmos_minutes = BCD2BIN(cmos_minutes); /* * since we're only adjusting minutes and seconds, @@ -297,8 +300,8 @@ if (abs(real_minutes - cmos_minutes) < 30) { if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { - BIN_TO_BCD(real_seconds); - BIN_TO_BCD(real_minutes); + real_seconds = BIN2BCD(real_seconds); + real_minutes = BIN2BCD(real_minutes); } CMOS_WRITE(real_seconds, RTC_SECONDS); CMOS_WRITE(real_minutes, RTC_MINUTES); @@ -366,8 +369,8 @@ if ((time_status & STA_UNSYNC) == 0 && xtime.tv_sec > last_rtc_update + 660 - && xtime.tv_usec >= 500000 - tick / 2 - && xtime.tv_usec <= 500000 + tick / 2) { + && (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 + && (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) { if (set_rtc_mmss(xtime.tv_sec) == 0) last_rtc_update = xtime.tv_sec; else @@ -381,7 +384,7 @@ rigged to be safe on the 386 - basically it's a hack, so don't look closely for now.. */ /*smp_message_pass(MSG_ALL_BUT_SELF, MSG_RESCHEDULE, 0L, 0); */ - + write_sequnlock(&xtime_lock); } static void r4k_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) @@ -392,7 +395,7 @@ * The cycle counter is only 32 bit which is good for about * a minute at current count rates of upto 150MHz or so. */ - count = read_32bit_cp0_register(CP0_COUNT); + count = read_c0_count(); timerhi += (count < timerlo); /* Wrap around */ timerlo = count; @@ -402,7 +405,7 @@ * update the timer[hi]/[lo] to make do_fast_gettimeoffset() * quotient calc still valid. -arca */ - write_32bit_cp0_register(CP0_COUNT, 0); + write_c0_count(0); timerhi = timerlo = 0; } @@ -417,7 +420,7 @@ * The free-running counter is 32 bit which is good for about * 2 minutes, 50 seconds at possible count rates of upto 25MHz. */ - count = ioasic_read(FCTR); + count = ioasic_read(IO_REG_FCTR); timerhi += (count < timerlo); /* Wrap around */ timerlo = count; @@ -427,15 +430,18 @@ * update the timer[hi]/[lo] to make do_fast_gettimeoffset() * quotient calc still valid. -arca */ - ioasic_write(FCTR, 0); + ioasic_write(IO_REG_FCTR, 0); timerhi = timerlo = 0; } timer_interrupt(irq, dev_id, regs); } -struct irqaction irq0 = {timer_interrupt, SA_INTERRUPT, 0, - "timer", NULL, NULL}; +struct irqaction irq0 = { + .handler = timer_interrupt, + .flags = SA_INTERRUPT, + .name = "timer", +}; void __init time_init(void) { @@ -463,12 +469,12 @@ year = CMOS_READ(RTC_YEAR); } while (sec != CMOS_READ(RTC_SECONDS)); if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { - BCD_TO_BIN(sec); - BCD_TO_BIN(min); - BCD_TO_BIN(hour); - BCD_TO_BIN(day); - BCD_TO_BIN(mon); - BCD_TO_BIN(year); + sec = BCD2BIN(sec); + min = BCD2BIN(min); + hour = BCD2BIN(hour); + day = BCD2BIN(day); + mon = BCD2BIN(mon); + year = BCD2BIN(year); } /* * The PROM will reset the year to either '72 or '73. @@ -480,15 +486,15 @@ write_seqlock_irq(&xtime_lock); xtime.tv_sec = mktime(year, mon, day, hour, min, sec); - xtime.tv_usec = 0; + xtime.tv_nsec = 0; write_sequnlock_irq(&xtime_lock); - if (mips_cpu.options & MIPS_CPU_COUNTER) { - write_32bit_cp0_register(CP0_COUNT, 0); + if (cpu_has_counter) { + write_c0_count(0); do_gettimeoffset = do_fast_gettimeoffset; irq0.handler = r4k_timer_interrupt; } else if (IOASIC) { - ioasic_write(FCTR, 0); + ioasic_write(IO_REG_FCTR, 0); do_gettimeoffset = do_ioasic_gettimeoffset; irq0.handler = ioasic_timer_interrupt; } diff -Nru a/arch/mips/dec/wbflush.c b/arch/mips/dec/wbflush.c --- a/arch/mips/dec/wbflush.c Tue Jul 1 18:44:37 2003 +++ b/arch/mips/dec/wbflush.c Tue Jul 1 18:44:37 2003 @@ -11,15 +11,18 @@ * for more details. * * Copyright (C) 1998 Harald Koerfgen + * Copyright (C) 2002 Maciej W. Rozycki */ -#include #include +#include +#include +#include + static void wbflush_kn01(void); static void wbflush_kn210(void); -static void wbflush_kn02ba(void); -static void wbflush_kn03(void); +static void wbflush_mips(void); void (*__wbflush) (void); @@ -27,28 +30,24 @@ { switch (mips_machtype) { case MACH_DS23100: - __wbflush = wbflush_kn01; - break; - case MACH_DS5100: /* DS5100 MIPSMATE */ - __wbflush = wbflush_kn210; - break; case MACH_DS5000_200: /* DS5000 3max */ - __wbflush = wbflush_kn01; - break; + __wbflush = wbflush_kn01; + break; + case MACH_DS5100: /* DS5100 MIPSMATE */ + __wbflush = wbflush_kn210; + break; case MACH_DS5000_1XX: /* DS5000/100 3min */ - __wbflush = wbflush_kn02ba; - break; - case MACH_DS5000_2X0: /* DS5000/240 3max+ */ - __wbflush = wbflush_kn03; - break; case MACH_DS5000_XX: /* Personal DS5000/2x */ - __wbflush = wbflush_kn02ba; - break; + case MACH_DS5000_2X0: /* DS5000/240 3max+ */ + case MACH_DS5900: /* DS5900 bigmax */ + default: + __wbflush = wbflush_mips; + break; } } /* - * For the DS3100 and DS5000/200 the writeback buffer functions + * For the DS3100 and DS5000/200 the R2020/R3220 writeback buffer functions * as part of Coprocessor 0. */ static void wbflush_kn01(void) @@ -78,29 +77,16 @@ "mtc0\t$2,$12\n\t" "nop\n\t" ".set\tpop" - : : :"$2", "$3"); -} - -/* - * Looks like some magic with the System Interrupt Mask Register - * in the famous IOASIC for kmins and maxines. - */ -static void wbflush_kn02ba(void) -{ - asm(".set\tpush\n\t" - ".set\tnoreorder\n\t" - "lui\t$2,0xbc04\n\t" - "lw\t$3,0x120($2)\n\t" - "lw\t$3,0x120($2)\n\t" - ".set\tpop" - : : :"$2", "$3"); + : : : "$2", "$3"); } /* - * The DS500/2x0 doesn't need to write back the WB. + * I/O ASIC systems use a standard writeback buffer that gets flushed + * upon an uncached read. */ -static void wbflush_kn03(void) +static void wbflush_mips(void) { + __fast_iob(); } #include diff -Nru a/arch/mips/defconfig b/arch/mips/defconfig --- a/arch/mips/defconfig Tue Jul 1 18:44:32 2003 +++ b/arch/mips/defconfig Tue Jul 1 18:44:32 2003 @@ -2,7 +2,8 @@ # Automatically generated make config: don't edit # CONFIG_MIPS=y -# CONFIG_SMP is not set +CONFIG_MIPS32=y +# CONFIG_MIPS64 is not set # # Code maturity level options @@ -10,89 +11,123 @@ CONFIG_EXPERIMENTAL=y # +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_EMBEDDED is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# # Machine selection # # CONFIG_ACER_PICA_61 is not set -# CONFIG_ALGOR_P4032 is not set # CONFIG_BAGET_MIPS is not set +# CONFIG_CASIO_E55 is not set +# CONFIG_MIPS_COBALT is not set # CONFIG_DECSTATION is not set -# CONFIG_DDB5074 is not set -# CONFIG_MIPS_EV96100 is not set # CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_IBM_WORKPAD is not set +# CONFIG_MIPS_ITE8172 is not set # CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_NINO is not set # CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set # CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_DDB5074 is not set # CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_NEC_EAGLE is not set # CONFIG_OLIVETTI_M700 is not set CONFIG_SGI_IP22=y +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set # CONFIG_SNI_RM200_PCI is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_MIPS_PB1000 is not set +# CONFIG_TANBAC_TB0226 is not set +# CONFIG_TANBAC_TB0229 is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +# CONFIG_VICTOR_MPC30X is not set +# CONFIG_ZAO_CAPCELLA is not set CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set -# CONFIG_MCA is not set -# CONFIG_SBUS is not set +CONFIG_ARC=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_NONCOHERENT_IO=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_IRQ_CPU=y +CONFIG_SWAP_IO_SPACE=y +CONFIG_BOOT_ELF32=y +CONFIG_L1_CACHE_SHIFT=5 CONFIG_ARC32=y +# CONFIG_FB is not set +CONFIG_ARC_CONSOLE=y +CONFIG_ARC_PROMLIB=y CONFIG_BOARD_SCACHE=y -CONFIG_PC_KEYB=y -CONFIG_SGI=y -CONFIG_NEW_IRQ=y -CONFIG_OLD_TIME_C=y -# CONFIG_ISA is not set -# CONFIG_EISA is not set -# CONFIG_PCI is not set -# CONFIG_I8259 is not set - -# -# Loadable module support -# -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y # # CPU selection # +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set # CONFIG_CPU_R3000 is not set -# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_TX39XX is not set # CONFIG_CPU_VR41XX is not set # CONFIG_CPU_R4300 is not set # CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set CONFIG_CPU_R5000=y # CONFIG_CPU_R5432 is not set -# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_R6000 is not set # CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set # CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set # CONFIG_CPU_SB1 is not set -# CONFIG_CPU_MIPS32 is not set -# CONFIG_CPU_MIPS64 is not set +# CONFIG_64BIT_PHYS_ADDR is not set # CONFIG_CPU_ADVANCED is not set CONFIG_CPU_HAS_LLSC=y CONFIG_CPU_HAS_LLDSCD=y -# CONFIG_CPU_HAS_WB is not set +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +CONFIG_KALLSYMS=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # -# General setup +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +# CONFIG_ISA is not set +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats # -# CONFIG_CPU_LITTLE_ENDIAN is not set CONFIG_KCORE_ELF=y -CONFIG_ELF_KERNEL=y -CONFIG_BINFMT_IRIX=y -CONFIG_FORWARD_KEYBOARD=y -# CONFIG_ARC_CONSOLE is not set -# CONFIG_BINFMT_AOUT is not set CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set -CONFIG_NET=y -# CONFIG_HOTPLUG is not set -# CONFIG_PCMCIA is not set -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y +CONFIG_BINFMT_IRIX=y # # Memory Technology Devices (MTD) @@ -105,41 +140,90 @@ # CONFIG_PARPORT is not set # +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# # Block devices # # CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_RAM is not set # CONFIG_BLK_DEV_INITRD is not set # +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_SCSI=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_ST=y +# CONFIG_CHR_DEV_OSST is not set +CONFIG_BLK_DEV_SR=y +# CONFIG_BLK_DEV_SR_VENDOR is not set +# CONFIG_CHR_DEV_SG is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_REPORT_LUNS is not set +CONFIG_SCSI_CONSTANTS=y +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI low-level drivers +# +CONFIG_SGIWD93_SCSI=y +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_DEBUG is not set + +# # Multi-device support (RAID and LVM) # # CONFIG_MD is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_BLK_DEV_LVM is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# I2O device support +# + +# +# Networking support +# +CONFIG_NET=y # # Networking options # CONFIG_PACKET=y CONFIG_PACKET_MMAP=y -CONFIG_NETLINK=y -CONFIG_RTNETLINK=y CONFIG_NETLINK_DEV=y # CONFIG_NETFILTER is not set -# CONFIG_FILTER is not set CONFIG_UNIX=y +CONFIG_NET_KEY=y CONFIG_INET=y CONFIG_IP_MULTICAST=y # CONFIG_IP_ADVANCED_ROUTER is not set @@ -153,20 +237,24 @@ # CONFIG_ARPD is not set # CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_KHTTPD is not set -# CONFIG_ATM is not set +# CONFIG_XFRM_USER is not set # -# +# SCTP Configuration (EXPERIMENTAL) # -# CONFIG_IPX is not set -# CONFIG_ATALK is not set +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC is not set # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_LLC is not set # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -179,87 +267,10 @@ # CONFIG_NET_SCHED is not set # -# Telephony Support -# -# CONFIG_PHONE is not set -# CONFIG_PHONE_IXJ is not set -# CONFIG_PHONE_IXJ_PCMCIA is not set - -# -# SCSI support -# -CONFIG_SCSI=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=y -CONFIG_SD_EXTRA_DEVS=40 -CONFIG_CHR_DEV_ST=y -# CONFIG_CHR_DEV_OSST is not set -CONFIG_BLK_DEV_SR=y -# CONFIG_BLK_DEV_SR_VENDOR is not set -CONFIG_SR_EXTRA_DEVS=2 -# CONFIG_CHR_DEV_SG is not set - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -# CONFIG_SCSI_DEBUG_QUEUES is not set -# CONFIG_SCSI_MULTI_LUN is not set -CONFIG_SCSI_CONSTANTS=y -# CONFIG_SCSI_LOGGING is not set - -# -# SCSI low-level drivers -# -CONFIG_SGIWD93_SCSI=y -# CONFIG_SCSI_7000FASST is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AHA152X is not set -# CONFIG_SCSI_AHA1542 is not set -# CONFIG_SCSI_AHA1740 is not set -# CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_AM53C974 is not set -# CONFIG_SCSI_MEGARAID is not set -# CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_DTC3280 is not set -# CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_DMA is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -# CONFIG_SCSI_GDTH is not set -# CONFIG_SCSI_GENERIC_NCR5380 is not set -# CONFIG_SCSI_INITIO is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_NCR_D700 is not set -# CONFIG_SCSI_NCR53C7xx is not set -# CONFIG_SCSI_PAS16 is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set -# CONFIG_SCSI_PSI240I is not set -# CONFIG_SCSI_QLOGIC_FAS is not set -# CONFIG_SCSI_SIM710 is not set -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set -# CONFIG_SCSI_DEBUG is not set - -# -# Network device support +# Network testing # +# CONFIG_NET_PKTGEN is not set CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set @@ -270,33 +281,16 @@ # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y -# CONFIG_SUNLANCE is not set -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set -# CONFIG_SUNLANCE is not set -# CONFIG_SUNGEM is not set -# CONFIG_NET_VENDOR_3COM is not set -# CONFIG_LANCE is not set -# CONFIG_NET_VENDOR_SMC is not set -# CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_NET_ISA is not set -# CONFIG_NET_PCI is not set -# CONFIG_NET_POCKET is not set +# CONFIG_MII is not set CONFIG_SGISEEQ=y # # Ethernet (1000 Mbit) # -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_MYRI_SBUS is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_SK98LIN is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PLIP is not set + +# +# Ethernet (10000 Mbit) +# # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -306,11 +300,8 @@ # CONFIG_NET_RADIO is not set # -# Token Ring devices +# Token Ring devices (depends on LLC=y) # -# CONFIG_TR is not set -# CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set # CONFIG_SHAPER is not set # @@ -331,21 +322,69 @@ # # ISDN subsystem # -# CONFIG_ISDN is not set +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set # -# Old CD-ROM drivers (not SCSI, not IDE) +# Input device support +# +CONFIG_INPUT=y + # -# CONFIG_CD_NO_IDESCSI is not set +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set # # Character devices # CONFIG_VT=y CONFIG_VT_CONSOLE=y -# CONFIG_SERIAL is not set -# CONFIG_SERIAL_EXTENDED is not set +CONFIG_HW_CONSOLE=y # CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_IP22_ZILOG=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_UNIX98_PTY_COUNT=256 @@ -355,36 +394,58 @@ # CONFIG_I2C is not set # -# Mice +# I2C Hardware Sensors Mainboard support # -# CONFIG_BUSMOUSE is not set -# CONFIG_MOUSE is not set # -# Joysticks +# I2C Hardware Sensors Chip support # -# CONFIG_INPUT_GAMEPORT is not set +# CONFIG_I2C_SENSOR is not set # -# Input core support is needed for gameports +# Mice # +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set # -# Input core support is needed for joysticks +# IPMI # -# CONFIG_QIC02_TAPE is not set +# CONFIG_IPMI_HANDLER is not set # # Watchdog Cards # -# CONFIG_WATCHDOG is not set -# CONFIG_INTEL_RNG is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_WDT is not set +# CONFIG_WDTPCI is not set +# CONFIG_PCWATCHDOG is not set +# CONFIG_ACQUIRE_WDT is not set +# CONFIG_ADVANTECH_WDT is not set +# CONFIG_EUROTECH_WDT is not set +# CONFIG_IB700_WDT is not set +# CONFIG_I810_TCO is not set +# CONFIG_MIXCOMWD is not set +# CONFIG_SCx200_WDT is not set +# CONFIG_60XX_WDT is not set +# CONFIG_W83877F_WDT is not set +# CONFIG_MACHZ_WDT is not set +CONFIG_INDYDOG=y +# CONFIG_SC520_WDT is not set +# CONFIG_AMD7XX_TCO is not set +# CONFIG_ALIM7101_WDT is not set +# CONFIG_SC1200_WDT is not set +# CONFIG_WAFER_WDT is not set +# CONFIG_CPU5_WDT is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +CONFIG_SGI_DS1286=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set -# CONFIG_SONYPI is not set # # Ftape, the floppy tape device driver @@ -392,6 +453,8 @@ # CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HANGCHECK_TIMER is not set # # Multimedia devices @@ -399,89 +462,92 @@ # CONFIG_VIDEO_DEV is not set # -# SGI Character devices +# Digital Video Broadcasting Devices # -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_SGI_NEWPORT_CONSOLE=y -CONFIG_FONT_8x16=y -# CONFIG_PSMOUSE is not set -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 +# CONFIG_DVB is not set # # File systems # +# CONFIG_EXT2_FS is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set CONFIG_AUTOFS_FS=y CONFIG_AUTOFS4_FS=y -# CONFIG_REISERFS_FS is not set -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +# CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# # CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set -# CONFIG_CMS_FS is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_JBD_DEBUG is not set -# CONFIG_FAT_FS is not set -# CONFIG_MSDOS_FS is not set -# CONFIG_UMSDOS_FS is not set -# CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -# CONFIG_JFFS2_FS is not set # CONFIG_CRAMFS is not set -# CONFIG_TMPFS is not set -# CONFIG_RAMFS is not set -CONFIG_ISO9660_FS=y -# CONFIG_JOLIET is not set -# CONFIG_MINIX_FS is not set -# CONFIG_FREEVXFS_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_DEBUG is not set -# CONFIG_NTFS_RW is not set +# CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set # # Network File Systems # -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=y # CONFIG_NFS_V3 is not set -CONFIG_ROOT_NFS=y +# CONFIG_NFS_V4 is not set CONFIG_NFSD=y # CONFIG_NFSD_V3 is not set -CONFIG_SUNRPC=y +# CONFIG_NFSD_TCP is not set +CONFIG_ROOT_NFS=y CONFIG_LOCKD=y +CONFIG_EXPORTFS=y +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set # CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set # CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set # # Partition Types @@ -498,22 +564,33 @@ # CONFIG_SOLARIS_X86_PARTITION is not set # CONFIG_UNIXWARE_DISKLABEL is not set # CONFIG_LDM_PARTITION is not set +# CONFIG_NEC98_PARTITION is not set CONFIG_SGI_PARTITION=y # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set -# CONFIG_SMB_NLS is not set -# CONFIG_NLS is not set +# CONFIG_EFI_PARTITION is not set # -# Console drivers +# Graphics support +# + +# +# Console display driver support # # CONFIG_VGA_CONSOLE is not set # CONFIG_MDA_CONSOLE is not set +CONFIG_SGI_NEWPORT_CONSOLE=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_FONT_8x16=y # -# Frame-buffer support +# Logo configuration # -# CONFIG_FB is not set +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +# CONFIG_LOGO_LINUX_CLUT224 is not set +CONFIG_LOGO_SGI_CLUT224=y # # Sound @@ -521,124 +598,48 @@ # CONFIG_SOUND is not set # -# SGI devices -# -CONFIG_SGI_SERIAL=y -# CONFIG_SERIAL_CONSOLE is not set -CONFIG_SGI_DS1286=y -# CONFIG_SGI_NEWPORT_GFX is not set - -# # USB support # -# CONFIG_USB is not set - -# -# USB Controllers -# -# CONFIG_USB_UHCI is not set -# CONFIG_USB_UHCI_ALT is not set -# CONFIG_USB_OHCI is not set - -# -# USB Device Class drivers -# -# CONFIG_USB_AUDIO is not set -# CONFIG_USB_BLUETOOTH is not set -# CONFIG_USB_STORAGE is not set -# CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set -# CONFIG_USB_STORAGE_DPCM is not set -# CONFIG_USB_STORAGE_SDDR09 is not set -# CONFIG_USB_ACM is not set -# CONFIG_USB_PRINTER is not set - -# -# USB Human Interface Devices (HID) -# - -# -# Input core support is needed for USB HID -# - -# -# USB Imaging devices -# -# CONFIG_USB_DC2XX is not set -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_SCANNER is not set -# CONFIG_USB_MICROTEK is not set -# CONFIG_USB_HPUSBSCSI is not set +# CONFIG_USB_GADGET is not set # -# USB Multimedia devices +# Bluetooth support # +# CONFIG_BT is not set # -# Video4Linux support is needed for USB Multimedia device support -# -# CONFIG_USB_DABUSB is not set - -# -# USB Network adaptors -# -# CONFIG_USB_PLUSB is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_CATC is not set -# CONFIG_USB_CDCETHER is not set -# CONFIG_USB_USBNET is not set - -# -# USB port drivers -# -# CONFIG_USB_USS720 is not set - -# -# USB Serial Converter support +# Kernel hacking # -# CONFIG_USB_SERIAL is not set -# CONFIG_USB_SERIAL_GENERIC is not set -# CONFIG_USB_SERIAL_BELKIN is not set -# CONFIG_USB_SERIAL_WHITEHEAT is not set -# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set -# CONFIG_USB_SERIAL_EMPEG is not set -# CONFIG_USB_SERIAL_FTDI_SIO is not set -# CONFIG_USB_SERIAL_VISOR is not set -# CONFIG_USB_SERIAL_EDGEPORT is not set -# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set -# CONFIG_USB_SERIAL_KEYSPAN is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set -# CONFIG_USB_SERIAL_MCT_U232 is not set -# CONFIG_USB_SERIAL_PL2303 is not set -# CONFIG_USB_SERIAL_CYBERJACK is not set -# CONFIG_USB_SERIAL_OMNINET is not set +CONFIG_CROSSCOMPILE=y +# CONFIG_DEBUG_KERNEL is not set # -# Miscellaneous USB drivers +# Security options # -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_ID75 is not set +# CONFIG_SECURITY is not set # -# Input core support +# Cryptographic options # -# CONFIG_INPUT is not set -# CONFIG_INPUT_KEYBDEV is not set -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_EVDEV is not set +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_BLOWFISH=y +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_SERPENT=y +CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_TEST is not set # -# Kernel hacking +# Library routines # -CONFIG_CROSSCOMPILE=y -# CONFIG_MAGIC_SYSRQ is not set -# CONFIG_MIPS_UNCACHED is not set +# CONFIG_CRC32 is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff -Nru a/arch/mips/defconfig-atlas b/arch/mips/defconfig-atlas --- a/arch/mips/defconfig-atlas Tue Jul 1 18:44:34 2003 +++ b/arch/mips/defconfig-atlas Tue Jul 1 18:44:34 2003 @@ -2,7 +2,8 @@ # Automatically generated make config: don't edit # CONFIG_MIPS=y -# CONFIG_SMP is not set +CONFIG_MIPS32=y +# CONFIG_MIPS64 is not set # # Code maturity level options @@ -10,82 +11,116 @@ CONFIG_EXPERIMENTAL=y # +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_EMBEDDED is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# # Machine selection # # CONFIG_ACER_PICA_61 is not set -# CONFIG_ALGOR_P4032 is not set # CONFIG_BAGET_MIPS is not set +# CONFIG_CASIO_E55 is not set +# CONFIG_MIPS_COBALT is not set # CONFIG_DECSTATION is not set -# CONFIG_DDB5074 is not set -# CONFIG_MIPS_EV96100 is not set # CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_IBM_WORKPAD is not set +# CONFIG_MIPS_ITE8172 is not set CONFIG_MIPS_ATLAS=y -# CONFIG_MIPS_MALTA is not set -# CONFIG_NINO is not set # CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set # CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_DDB5074 is not set # CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_NEC_EAGLE is not set # CONFIG_OLIVETTI_M700 is not set # CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set # CONFIG_SNI_RM200_PCI is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_MIPS_PB1000 is not set +# CONFIG_TANBAC_TB0226 is not set +# CONFIG_TANBAC_TB0229 is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +# CONFIG_VICTOR_MPC30X is not set +# CONFIG_ZAO_CAPCELLA is not set CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set -# CONFIG_MCA is not set -# CONFIG_SBUS is not set -CONFIG_PCI=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_NONCOHERENT_IO=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_MIPS_BOARDS_GEN=y CONFIG_SWAP_IO_SPACE=y -# CONFIG_ISA is not set -# CONFIG_EISA is not set -# CONFIG_I8259 is not set - -# -# Loadable module support -# -# CONFIG_MODULES is not set +CONFIG_BOOT_ELF32=y +CONFIG_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set # # CPU selection # +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS64 is not set # CONFIG_CPU_R3000 is not set -# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_TX39XX is not set # CONFIG_CPU_VR41XX is not set # CONFIG_CPU_R4300 is not set # CONFIG_CPU_R4X00 is not set -CONFIG_CPU_R5000=y +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set # CONFIG_CPU_R5432 is not set -# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_R6000 is not set # CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set # CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set # CONFIG_CPU_SB1 is not set -# CONFIG_CPU_MIPS32 is not set -# CONFIG_CPU_MIPS64 is not set +CONFIG_CPU_HAS_PREFETCH=y +# CONFIG_VTAG_ICACHE is not set +# CONFIG_64BIT_PHYS_ADDR is not set # CONFIG_CPU_ADVANCED is not set CONFIG_CPU_HAS_LLSC=y -CONFIG_CPU_HAS_LLDSCD=y -# CONFIG_CPU_HAS_WB is not set +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +CONFIG_KALLSYMS=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # -# General setup +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats # -# CONFIG_CPU_LITTLE_ENDIAN is not set CONFIG_KCORE_ELF=y -CONFIG_ELF_KERNEL=y -CONFIG_BINFMT_IRIX=y -# CONFIG_FORWARD_KEYBOARD is not set -# CONFIG_BINFMT_AOUT is not set CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set -CONFIG_NET=y -# CONFIG_PCI_NAMES is not set -# CONFIG_HOTPLUG is not set -# CONFIG_PCMCIA is not set -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -# CONFIG_SYSCTL is not set +# CONFIG_BINFMT_IRIX is not set # # Memory Technology Devices (MTD) @@ -98,91 +133,36 @@ # CONFIG_PARPORT is not set # +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# # Block devices # # CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_UMEM is not set +CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_NBD is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 # CONFIG_BLK_DEV_INITRD is not set # -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_BLK_DEV_LVM is not set - -# -# Networking options -# -# CONFIG_PACKET is not set -# CONFIG_NETLINK is not set -# CONFIG_NETFILTER is not set -# CONFIG_FILTER is not set -CONFIG_UNIX=y -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -# CONFIG_IP_PNP_BOOTP is not set -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_IPV6 is not set -# CONFIG_KHTTPD is not set -# CONFIG_ATM is not set - -# -# -# -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_LLC is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set -# CONFIG_PHONE_IXJ is not set -# CONFIG_PHONE_IXJ_PCMCIA is not set - -# -# ATA/IDE/MFM/RLL support +# ATA/ATAPI/MFM/RLL support # # CONFIG_IDE is not set -# CONFIG_BLK_DEV_IDE_MODES is not set -# CONFIG_BLK_DEV_HD is not set # -# SCSI support +# SCSI device support # CONFIG_SCSI=y @@ -190,7 +170,6 @@ # SCSI support type (disk, tape, CD-ROM) # CONFIG_BLK_DEV_SD=y -CONFIG_SD_EXTRA_DEVS=40 # CONFIG_CHR_DEV_ST is not set # CONFIG_CHR_DEV_OSST is not set # CONFIG_BLK_DEV_SR is not set @@ -199,8 +178,8 @@ # # Some SCSI devices (e.g. CD jukebox) support multiple LUNs # -# CONFIG_SCSI_DEBUG_QUEUES is not set # CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_REPORT_LUNS is not set # CONFIG_SCSI_CONSTANTS is not set # CONFIG_SCSI_LOGGING is not set @@ -208,53 +187,115 @@ # SCSI low-level drivers # # CONFIG_BLK_DEV_3W_XXXX_RAID is not set -# CONFIG_SCSI_7000FASST is not set # CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AHA152X is not set -# CONFIG_SCSI_AHA1542 is not set -# CONFIG_SCSI_AHA1740 is not set +# CONFIG_SCSI_AACRAID is not set # CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set # CONFIG_SCSI_DPT_I2O is not set # CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_AM53C974 is not set # CONFIG_SCSI_MEGARAID is not set # CONFIG_SCSI_BUSLOGIC is not set # CONFIG_SCSI_CPQFCTS is not set # CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_DTC3280 is not set # CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_DMA is not set # CONFIG_SCSI_EATA_PIO is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_GDTH is not set -# CONFIG_SCSI_GENERIC_NCR5380 is not set # CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_NCR_D700 is not set -# CONFIG_SCSI_NCR53C7xx is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set # CONFIG_SCSI_NCR53C8XX is not set # CONFIG_SCSI_SYM53C8XX is not set -# CONFIG_SCSI_PAS16 is not set # CONFIG_SCSI_PCI2000 is not set # CONFIG_SCSI_PCI2220I is not set -# CONFIG_SCSI_PSI240I is not set -# CONFIG_SCSI_QLOGIC_FAS is not set # CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set -# CONFIG_SCSI_SIM710 is not set -# CONFIG_SCSI_SYM53C416 is not set +# CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set +# CONFIG_SCSI_NSP32 is not set # CONFIG_SCSI_DEBUG is not set # -# Network device support +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support # +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=y +# CONFIG_NETFILTER is not set +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set CONFIG_NETDEVICES=y # @@ -265,39 +306,43 @@ # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y -# CONFIG_SUNLANCE is not set +# CONFIG_MII is not set # CONFIG_HAPPYMEAL is not set -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set -# CONFIG_SUNLANCE is not set # CONFIG_SUNGEM is not set # CONFIG_NET_VENDOR_3COM is not set -# CONFIG_LANCE is not set -# CONFIG_NET_VENDOR_SMC is not set -# CONFIG_NET_VENDOR_RACAL is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set # CONFIG_HP100 is not set -# CONFIG_NET_ISA is not set # CONFIG_NET_PCI is not set -# CONFIG_NET_POCKET is not set # # Ethernet (1000 Mbit) # # CONFIG_ACENIC is not set # CONFIG_DL2K is not set -# CONFIG_MYRI_SBUS is not set +# CONFIG_E1000 is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set # CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set -# CONFIG_PLIP is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -307,9 +352,8 @@ # CONFIG_NET_RADIO is not set # -# Token Ring devices +# Token Ring devices (depends on LLC=y) # -# CONFIG_TR is not set # CONFIG_NET_FC is not set # CONFIG_RCPCI is not set # CONFIG_SHAPER is not set @@ -332,21 +376,65 @@ # # ISDN subsystem # -# CONFIG_ISDN is not set +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set # -# Old CD-ROM drivers (not SCSI, not IDE) +# Input Device Drivers # -# CONFIG_CD_NO_IDESCSI is not set +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set # # Character devices # # CONFIG_VT is not set -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y -# CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_UNIX98_PTY_COUNT=256 @@ -356,36 +444,35 @@ # CONFIG_I2C is not set # -# Mice +# I2C Hardware Sensors Mainboard support # -# CONFIG_BUSMOUSE is not set -# CONFIG_MOUSE is not set # -# Joysticks +# I2C Hardware Sensors Chip support # -# CONFIG_INPUT_GAMEPORT is not set +# CONFIG_I2C_SENSOR is not set # -# Input core support is needed for gameports +# Mice # +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set # -# Input core support is needed for joysticks +# IPMI # -# CONFIG_QIC02_TAPE is not set +# CONFIG_IPMI_HANDLER is not set # # Watchdog Cards # # CONFIG_WATCHDOG is not set -# CONFIG_INTEL_RNG is not set # CONFIG_NVRAM is not set -CONFIG_RTC=y +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set -# CONFIG_SONYPI is not set # # Ftape, the floppy tape device driver @@ -393,6 +480,8 @@ # CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HANGCHECK_TIMER is not set # # Multimedia devices @@ -400,86 +489,94 @@ # CONFIG_VIDEO_DEV is not set # +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# # File systems # +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set -CONFIG_AUTOFS_FS=y +# CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# # CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set -# CONFIG_CMS_FS is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_JBD_DEBUG is not set -# CONFIG_FAT_FS is not set -# CONFIG_MSDOS_FS is not set -# CONFIG_UMSDOS_FS is not set -# CONFIG_VFAT_FS is not set -CONFIG_EFS_FS=y -# CONFIG_JFFS_FS is not set -# CONFIG_JFFS2_FS is not set +# CONFIG_EFS_FS is not set # CONFIG_CRAMFS is not set -# CONFIG_TMPFS is not set -# CONFIG_RAMFS is not set -# CONFIG_ISO9660_FS is not set -# CONFIG_JOLIET is not set -# CONFIG_MINIX_FS is not set -# CONFIG_FREEVXFS_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_DEBUG is not set -# CONFIG_NTFS_RW is not set +# CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set # # Network File Systems # -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -CONFIG_ROOT_NFS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V4 is not set # CONFIG_NFSD is not set -# CONFIG_NFSD_V3 is not set -CONFIG_SUNRPC=y +CONFIG_ROOT_NFS=y CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set # CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set # CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set # # Partition Types # # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y -# CONFIG_SMB_NLS is not set -# CONFIG_NLS is not set + +# +# Graphics support +# # # Sound @@ -490,116 +587,30 @@ # USB support # # CONFIG_USB is not set +# CONFIG_USB_GADGET is not set # -# USB Controllers -# -# CONFIG_USB_UHCI is not set -# CONFIG_USB_UHCI_ALT is not set -# CONFIG_USB_OHCI is not set - -# -# USB Device Class drivers -# -# CONFIG_USB_AUDIO is not set -# CONFIG_USB_BLUETOOTH is not set -# CONFIG_USB_STORAGE is not set -# CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set -# CONFIG_USB_STORAGE_DPCM is not set -# CONFIG_USB_STORAGE_SDDR09 is not set -# CONFIG_USB_ACM is not set -# CONFIG_USB_PRINTER is not set - -# -# USB Human Interface Devices (HID) -# - -# -# Input core support is needed for USB HID -# - -# -# USB Imaging devices -# -# CONFIG_USB_DC2XX is not set -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_SCANNER is not set -# CONFIG_USB_MICROTEK is not set -# CONFIG_USB_HPUSBSCSI is not set - -# -# USB Multimedia devices +# Bluetooth support # +# CONFIG_BT is not set # -# Video4Linux support is needed for USB Multimedia device support -# -# CONFIG_USB_DABUSB is not set - -# -# USB Network adaptors -# -# CONFIG_USB_PLUSB is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_CATC is not set -# CONFIG_USB_CDCETHER is not set -# CONFIG_USB_USBNET is not set - -# -# USB port drivers -# -# CONFIG_USB_USS720 is not set - -# -# USB Serial Converter support +# Kernel hacking # -# CONFIG_USB_SERIAL is not set -# CONFIG_USB_SERIAL_GENERIC is not set -# CONFIG_USB_SERIAL_BELKIN is not set -# CONFIG_USB_SERIAL_WHITEHEAT is not set -# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set -# CONFIG_USB_SERIAL_EMPEG is not set -# CONFIG_USB_SERIAL_FTDI_SIO is not set -# CONFIG_USB_SERIAL_VISOR is not set -# CONFIG_USB_SERIAL_EDGEPORT is not set -# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set -# CONFIG_USB_SERIAL_KEYSPAN is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set -# CONFIG_USB_SERIAL_MCT_U232 is not set -# CONFIG_USB_SERIAL_PL2303 is not set -# CONFIG_USB_SERIAL_CYBERJACK is not set -# CONFIG_USB_SERIAL_OMNINET is not set +CONFIG_CROSSCOMPILE=y +# CONFIG_DEBUG_KERNEL is not set # -# Miscellaneous USB drivers +# Security options # -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_ID75 is not set +# CONFIG_SECURITY is not set # -# Input core support +# Cryptographic options # -# CONFIG_INPUT is not set -# CONFIG_INPUT_KEYBDEV is not set -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_EVDEV is not set +# CONFIG_CRYPTO is not set # -# Kernel hacking +# Library routines # -CONFIG_CROSSCOMPILE=y -# CONFIG_REMOTE_DEBUG is not set -# CONFIG_GDB_CONSOLE is not set -# CONFIG_LL_DEBUG is not set -# CONFIG_MAGIC_SYSRQ is not set -# CONFIG_MIPS_UNCACHED is not set +# CONFIG_CRC32 is not set diff -Nru a/arch/mips/defconfig-capcella b/arch/mips/defconfig-capcella --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/defconfig-capcella Tue Jul 1 18:44:40 2003 @@ -0,0 +1,612 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +CONFIG_MIPS32=y +# CONFIG_MIPS64 is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_EMBEDDED is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_ACER_PICA_61 is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_CASIO_E55 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_IBM_WORKPAD is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_NEC_EAGLE is not set +# CONFIG_OLIVETTI_M700 is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TANBAC_TB0226 is not set +# CONFIG_TANBAC_TB0229 is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +# CONFIG_VICTOR_MPC30X is not set +CONFIG_ZAO_CAPCELLA=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_NONCOHERENT_IO=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_VR41XX_TIME_C=y +CONFIG_DUMMY_KEYB=y +CONFIG_VR41XX_COMMON=y +CONFIG_NEW_PCI=y +# CONFIG_FB is not set + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +CONFIG_CPU_VR41XX=y +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_SB1 is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +CONFIG_KALLSYMS=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_KCORE_ELF=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y + +# +# IDE, ATA and ATAPI Block devices +# +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_IDEDISK_STROKE is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_IDE_TASK_IOCTL is not set +CONFIG_IDE_TASKFILE_IO=y + +# +# IDE chipset support/bugfixes +# +# CONFIG_BLK_DEV_IDEPCI is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_NETLINK_DEV=y +# CONFIG_NETFILTER is not set +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices (depends on LLC=y) +# +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +# CONFIG_SERIO is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +# CONFIG_VT_CONSOLE is not set +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# I2C Hardware Sensors Mainboard support +# + +# +# I2C Hardware Sensors Chip support +# +# CONFIG_I2C_SENSOR is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_WDT is not set +# CONFIG_WDTPCI is not set +# CONFIG_PCWATCHDOG is not set +# CONFIG_ACQUIRE_WDT is not set +# CONFIG_ADVANTECH_WDT is not set +# CONFIG_EUROTECH_WDT is not set +# CONFIG_IB700_WDT is not set +# CONFIG_I810_TCO is not set +# CONFIG_MIXCOMWD is not set +# CONFIG_SCx200_WDT is not set +# CONFIG_60XX_WDT is not set +# CONFIG_W83877F_WDT is not set +# CONFIG_MACHZ_WDT is not set +# CONFIG_SC520_WDT is not set +# CONFIG_AMD7XX_TCO is not set +# CONFIG_ALIM7101_WDT is not set +# CONFIG_SC1200_WDT is not set +# CONFIG_WAFER_WDT is not set +# CONFIG_CPU5_WDT is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HANGCHECK_TIMER is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=y +CONFIG_AUTOFS4_FS=y + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +CONFIG_NFSD=y +# CONFIG_NFSD_V3 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_EXPORTFS=y +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set +# CONFIG_USB_GADGET is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set diff -Nru a/arch/mips/defconfig-cobalt b/arch/mips/defconfig-cobalt --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/defconfig-cobalt Tue Jul 1 18:44:39 2003 @@ -0,0 +1,576 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +CONFIG_MIPS32=y +# CONFIG_MIPS64 is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_EMBEDDED is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# Machine selection +# +# CONFIG_ACER_PICA_61 is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_CASIO_E55 is not set +CONFIG_MIPS_COBALT=y +# CONFIG_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_IBM_WORKPAD is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_NEC_EAGLE is not set +# CONFIG_OLIVETTI_M700 is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TANBAC_TB0226 is not set +# CONFIG_TANBAC_TB0229 is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +# CONFIG_VICTOR_MPC30X is not set +# CONFIG_ZAO_CAPCELLA is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_I8259=y +CONFIG_NONCOHERENT_IO=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_COBALT_LCD=y +# CONFIG_FB is not set + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +CONFIG_CPU_NEVADA=y +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_SB1 is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +CONFIG_KALLSYMS=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_KCORE_ELF=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y + +# +# IDE, ATA and ATAPI Block devices +# +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_IDEDISK_STROKE is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_IDE_TASK_IOCTL is not set +CONFIG_IDE_TASKFILE_IO=y + +# +# IDE chipset support/bugfixes +# +# CONFIG_BLK_DEV_IDEPCI is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=y +# CONFIG_NETFILTER is not set +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices (depends on LLC=y) +# +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=16 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# I2C Hardware Sensors Mainboard support +# + +# +# I2C Hardware Sensors Chip support +# +# CONFIG_I2C_SENSOR is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +CONFIG_RTC=y +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set +CONFIG_HANGCHECK_TIMER=y + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Graphics support +# + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set +# CONFIG_USB_GADGET is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set diff -Nru a/arch/mips/defconfig-ddb5476 b/arch/mips/defconfig-ddb5476 --- a/arch/mips/defconfig-ddb5476 Tue Jul 1 18:44:39 2003 +++ b/arch/mips/defconfig-ddb5476 Tue Jul 1 18:44:39 2003 @@ -2,7 +2,8 @@ # Automatically generated make config: don't edit # CONFIG_MIPS=y -# CONFIG_SMP is not set +CONFIG_MIPS32=y +# CONFIG_MIPS64 is not set # # Code maturity level options @@ -10,90 +11,113 @@ CONFIG_EXPERIMENTAL=y # +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_EMBEDDED is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# # Machine selection # # CONFIG_ACER_PICA_61 is not set -# CONFIG_ALGOR_P4032 is not set # CONFIG_BAGET_MIPS is not set +# CONFIG_CASIO_E55 is not set +# CONFIG_MIPS_COBALT is not set # CONFIG_DECSTATION is not set -# CONFIG_DDB5074 is not set -# CONFIG_MIPS_EV96100 is not set # CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_IBM_WORKPAD is not set +# CONFIG_MIPS_ITE8172 is not set # CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_NINO is not set # CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set # CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_DDB5074 is not set CONFIG_DDB5476=y # CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_NEC_EAGLE is not set # CONFIG_OLIVETTI_M700 is not set # CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set # CONFIG_SNI_RM200_PCI is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_MIPS_PB1000 is not set +# CONFIG_TANBAC_TB0226 is not set +# CONFIG_TANBAC_TB0229 is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +# CONFIG_VICTOR_MPC30X is not set +# CONFIG_ZAO_CAPCELLA is not set CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set -# CONFIG_MCA is not set -# CONFIG_SBUS is not set -CONFIG_ISA=y -CONFIG_PCI=y -CONFIG_PC_KEYB=y -CONFIG_ROTTEN_IRQ=y +CONFIG_I8259=y +CONFIG_NONCOHERENT_IO=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_DDB5XXX_COMMON=y +CONFIG_NEW_PCI=y +CONFIG_FB=y CONFIG_HAVE_STD_PC_SERIAL_PORT=y -CONFIG_NEW_TIME_C=y -CONFIG_EISA=y -# CONFIG_I8259 is not set - -# -# Loadable module support -# -# CONFIG_MODULES is not set # # CPU selection # +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set # CONFIG_CPU_R3000 is not set -# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_TX39XX is not set # CONFIG_CPU_VR41XX is not set # CONFIG_CPU_R4300 is not set # CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set # CONFIG_CPU_R5000 is not set CONFIG_CPU_R5432=y -# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_R6000 is not set # CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set # CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set # CONFIG_CPU_SB1 is not set -# CONFIG_CPU_MIPS32 is not set -# CONFIG_CPU_MIPS64 is not set # CONFIG_CPU_ADVANCED is not set CONFIG_CPU_HAS_LLSC=y CONFIG_CPU_HAS_LLDSCD=y -# CONFIG_CPU_HAS_WB is not set +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +CONFIG_KALLSYMS=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # -# General setup +# Bus options (PCI, PCMCIA, EISA, ISA, TC) # -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_KCORE_ELF=y -CONFIG_ELF_KERNEL=y -# CONFIG_BINFMT_AOUT is not set -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -CONFIG_NET=y -# CONFIG_PCI_NAMES is not set +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y +CONFIG_MMU=y # CONFIG_HOTPLUG is not set -# CONFIG_PCMCIA is not set -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y # -# Plug and Play configuration +# Executable file formats # -# CONFIG_PNP is not set -# CONFIG_ISAPNP is not set -# CONFIG_PNPBIOS is not set +CONFIG_KCORE_ELF=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set # # Memory Technology Devices (MTD) @@ -106,39 +130,93 @@ # CONFIG_PARPORT is not set # +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# # Block devices # # CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_RAM is not set # CONFIG_BLK_DEV_INITRD is not set # +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y + +# +# IDE, ATA and ATAPI Block devices +# +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_IDEDISK_STROKE is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_IDE_TASK_IOCTL is not set +CONFIG_IDE_TASKFILE_IO=y + +# +# IDE chipset support/bugfixes +# +# CONFIG_BLK_DEV_IDEPCI is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# # Multi-device support (RAID and LVM) # # CONFIG_MD is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_BLK_DEV_LVM is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Networking support +# +CONFIG_NET=y # # Networking options # CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set -# CONFIG_NETLINK is not set +CONFIG_NETLINK_DEV=y # CONFIG_NETFILTER is not set -# CONFIG_FILTER is not set CONFIG_UNIX=y +CONFIG_NET_KEY=y CONFIG_INET=y # CONFIG_IP_MULTICAST is not set # CONFIG_IP_ADVANCED_ROUTER is not set @@ -148,22 +226,27 @@ # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set # CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_KHTTPD is not set -# CONFIG_ATM is not set +# CONFIG_XFRM_USER is not set # -# +# SCTP Configuration (EXPERIMENTAL) # -# CONFIG_IPX is not set -# CONFIG_ATALK is not set +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC is not set # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_LLC is not set # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -176,84 +259,9 @@ # CONFIG_NET_SCHED is not set # -# Telephony Support -# -# CONFIG_PHONE is not set -# CONFIG_PHONE_IXJ is not set -# CONFIG_PHONE_IXJ_PCMCIA is not set - -# -# ATA/IDE/MFM/RLL support -# -CONFIG_IDE=y - -# -# IDE, ATA and ATAPI Block devices -# -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD_IDE is not set -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=y -# CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_BLK_DEV_IDECS is not set -# 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 - -# -# IDE chipset support/bugfixes -# -# CONFIG_BLK_DEV_CMD640 is not set -# CONFIG_BLK_DEV_CMD640_ENHANCED is not set -# CONFIG_BLK_DEV_ISAPNP is not set -# CONFIG_BLK_DEV_RZ1000 is not set -# CONFIG_IDEPCI_SHARE_IRQ is not set -# CONFIG_BLK_DEV_IDEDMA_PCI is not set -# CONFIG_BLK_DEV_OFFBOARD is not set -# CONFIG_IDEDMA_PCI_AUTO is not set -# CONFIG_BLK_DEV_IDEDMA is not set -# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set -# CONFIG_BLK_DEV_AEC62XX is not set -# CONFIG_AEC62XX_TUNING is not set -# CONFIG_BLK_DEV_ALI15X3 is not set -# CONFIG_WDC_ALI15X3 is not set -# CONFIG_BLK_DEV_AMD74XX is not set -# CONFIG_AMD74XX_OVERRIDE is not set -# CONFIG_BLK_DEV_CMD64X is not set -# CONFIG_BLK_DEV_CY82C693 is not set -# CONFIG_BLK_DEV_CS5530 is not set -# CONFIG_BLK_DEV_HPT34X is not set -# CONFIG_HPT34X_AUTODMA is not set -# CONFIG_BLK_DEV_HPT366 is not set -# CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_OPTI621 is not set -# CONFIG_BLK_DEV_PDC202XX is not set -# CONFIG_PDC202XX_BURST is not set -# CONFIG_PDC202XX_FORCE is not set -# CONFIG_BLK_DEV_SVWKS is not set -# CONFIG_BLK_DEV_SIS5513 is not set -# CONFIG_BLK_DEV_TRM290 is not set -# CONFIG_BLK_DEV_VIA82CXXX is not set -# CONFIG_IDE_CHIPSETS is not set -# CONFIG_IDEDMA_AUTO is not set -# CONFIG_BLK_DEV_IDE_MODES is not set -# CONFIG_BLK_DEV_ATARAID is not set -# CONFIG_BLK_DEV_ATARAID_PDC is not set -# CONFIG_BLK_DEV_ATARAID_HPT is not set - -# -# SCSI support -# -# CONFIG_SCSI is not set - -# -# Network device support +# Network testing # +# CONFIG_NET_PKTGEN is not set CONFIG_NETDEVICES=y # @@ -264,70 +272,43 @@ # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y -# CONFIG_SUNLANCE is not set +# CONFIG_MII is not set # CONFIG_HAPPYMEAL is not set -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set -# CONFIG_SUNLANCE is not set # CONFIG_SUNGEM is not set # CONFIG_NET_VENDOR_3COM is not set -# CONFIG_LANCE is not set -# CONFIG_NET_VENDOR_SMC is not set -# CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_AT1700 is not set -# CONFIG_DEPCA is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set # CONFIG_HP100 is not set -# CONFIG_NET_ISA is not set -CONFIG_NET_PCI=y -# CONFIG_PCNET32 is not set -# CONFIG_ADAPTEC_STARFIRE is not set -# CONFIG_AC3200 is not set -# CONFIG_APRICOT is not set -# CONFIG_CS89x0 is not set -CONFIG_TULIP=y -# CONFIG_TULIP_MWI is not set -# CONFIG_TULIP_MMIO is not set -# CONFIG_DE4X5 is not set -# CONFIG_DGRS is not set -# CONFIG_DM9102 is not set -CONFIG_EEPRO100=y -# CONFIG_LNE390 is not set -# CONFIG_FEALNX is not set -# CONFIG_NATSEMI is not set -CONFIG_NE2K_PCI=y -# CONFIG_NE3210 is not set -# CONFIG_ES3210 is not set -# CONFIG_8139TOO is not set -# CONFIG_8139TOO_PIO is not set -# CONFIG_8139TOO_TUNE_TWISTER is not set -# CONFIG_8139TOO_8129 is not set -# CONFIG_SIS900 is not set -# CONFIG_EPIC100 is not set -# CONFIG_SUNDANCE is not set -# CONFIG_TLAN is not set -# CONFIG_VIA_RHINE is not set -# CONFIG_WINBOND_840 is not set -# CONFIG_LAN_SAA9730 is not set -# CONFIG_NET_POCKET is not set +# CONFIG_NET_PCI is not set # # Ethernet (1000 Mbit) # # CONFIG_ACENIC is not set # CONFIG_DL2K is not set -# CONFIG_MYRI_SBUS is not set +# CONFIG_E1000 is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set # CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set -# CONFIG_PLIP is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -337,10 +318,8 @@ # CONFIG_NET_RADIO is not set # -# Token Ring devices +# Token Ring devices (depends on LLC=y) # -# CONFIG_TR is not set -# CONFIG_NET_FC is not set # CONFIG_RCPCI is not set # CONFIG_SHAPER is not set @@ -362,22 +341,67 @@ # # ISDN subsystem # -# CONFIG_ISDN is not set +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set # -# Old CD-ROM drivers (not SCSI, not IDE) +# Input I/O drivers # -# CONFIG_CD_NO_IDESCSI is not set +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set # # Character devices # CONFIG_VT=y # CONFIG_VT_CONSOLE is not set -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y -# CONFIG_SERIAL_EXTENDED is not set +CONFIG_HW_CONSOLE=y # CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_UNIX98_PTY_COUNT=256 @@ -387,39 +411,35 @@ # CONFIG_I2C is not set # -# Mice +# I2C Hardware Sensors Mainboard support # -# CONFIG_BUSMOUSE is not set -CONFIG_MOUSE=y -CONFIG_PSMOUSE=y -# CONFIG_82C710_MOUSE is not set -# CONFIG_PC110_PAD is not set # -# Joysticks +# I2C Hardware Sensors Chip support # -# CONFIG_INPUT_GAMEPORT is not set +# CONFIG_I2C_SENSOR is not set # -# Input core support is needed for gameports +# Mice # +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set # -# Input core support is needed for joysticks +# IPMI # -# CONFIG_QIC02_TAPE is not set +# CONFIG_IPMI_HANDLER is not set # # Watchdog Cards # # CONFIG_WATCHDOG is not set -# CONFIG_INTEL_RNG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set -# CONFIG_SONYPI is not set # # Ftape, the floppy tape device driver @@ -427,6 +447,8 @@ # CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HANGCHECK_TIMER is not set # # Multimedia devices @@ -434,238 +456,157 @@ # CONFIG_VIDEO_DEV is not set # +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# # File systems # +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# # CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set -# CONFIG_CMS_FS is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_JBD_DEBUG is not set -# CONFIG_FAT_FS is not set -# CONFIG_MSDOS_FS is not set -# CONFIG_UMSDOS_FS is not set -# CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -# CONFIG_JFFS2_FS is not set # CONFIG_CRAMFS is not set -# CONFIG_TMPFS is not set -# CONFIG_RAMFS is not set -# CONFIG_ISO9660_FS is not set -# CONFIG_JOLIET is not set -# CONFIG_MINIX_FS is not set -# CONFIG_FREEVXFS_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_DEBUG is not set -# CONFIG_NTFS_RW is not set +# CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set # # Network File Systems # -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=y # CONFIG_NFS_V3 is not set -CONFIG_ROOT_NFS=y +# CONFIG_NFS_V4 is not set # CONFIG_NFSD is not set -# CONFIG_NFSD_V3 is not set -CONFIG_SUNRPC=y +CONFIG_ROOT_NFS=y CONFIG_LOCKD=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set # CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set # CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set # # Partition Types # # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y -# CONFIG_SMB_NLS is not set -# CONFIG_NLS is not set - -# -# Console drivers -# -# CONFIG_VGA_CONSOLE is not set -# CONFIG_MDA_CONSOLE is not set # -# Frame-buffer support +# Graphics support # -CONFIG_FB=y -CONFIG_DUMMY_CONSOLE=y -# CONFIG_FB_RIVA is not set -# CONFIG_FB_CLGEN is not set +# CONFIG_FB_CIRRUS is not set # CONFIG_FB_PM2 is not set # CONFIG_FB_CYBER2000 is not set -# CONFIG_FB_E1355 is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_RIVA is not set # CONFIG_FB_MATROX is not set -# CONFIG_FB_ATY is not set # CONFIG_FB_RADEON is not set # CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set # CONFIG_FB_SIS is not set -CONFIG_FB_3DFX=y +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_PM3 is not set +# CONFIG_FB_E1356 is not set # CONFIG_FB_VIRTUAL is not set -# CONFIG_FBCON_ADVANCED is not set -CONFIG_FBCON_CFB8=y -CONFIG_FBCON_CFB16=y -CONFIG_FBCON_CFB32=y -# CONFIG_FBCON_FONTWIDTH8_ONLY is not set -# CONFIG_FBCON_FONTS is not set -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y - -# -# Sound -# -# CONFIG_SOUND is not set # -# USB support -# -# CONFIG_USB is not set - -# -# USB Controllers -# -# CONFIG_USB_UHCI is not set -# CONFIG_USB_UHCI_ALT is not set -# CONFIG_USB_OHCI is not set - +# Console display driver support # -# USB Device Class drivers -# -# CONFIG_USB_AUDIO is not set -# CONFIG_USB_BLUETOOTH is not set -# CONFIG_USB_STORAGE is not set -# CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set -# CONFIG_USB_STORAGE_DPCM is not set -# CONFIG_USB_STORAGE_SDDR09 is not set -# CONFIG_USB_ACM is not set -# CONFIG_USB_PRINTER is not set - -# -# USB Human Interface Devices (HID) -# - -# -# Input core support is needed for USB HID -# - -# -# USB Imaging devices -# -# CONFIG_USB_DC2XX is not set -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_SCANNER is not set -# CONFIG_USB_MICROTEK is not set -# CONFIG_USB_HPUSBSCSI is not set +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE is not set # -# USB Multimedia devices +# Logo configuration # +# CONFIG_LOGO is not set # -# Video4Linux support is needed for USB Multimedia device support +# Sound # -# CONFIG_USB_DABUSB is not set +# CONFIG_SOUND is not set # -# USB Network adaptors +# USB support # -# CONFIG_USB_PLUSB is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_CATC is not set -# CONFIG_USB_CDCETHER is not set -# CONFIG_USB_USBNET is not set +# CONFIG_USB is not set +# CONFIG_USB_GADGET is not set # -# USB port drivers +# Bluetooth support # -# CONFIG_USB_USS720 is not set +# CONFIG_BT is not set # -# USB Serial Converter support +# Kernel hacking # -# CONFIG_USB_SERIAL is not set -# CONFIG_USB_SERIAL_GENERIC is not set -# CONFIG_USB_SERIAL_BELKIN is not set -# CONFIG_USB_SERIAL_WHITEHEAT is not set -# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set -# CONFIG_USB_SERIAL_EMPEG is not set -# CONFIG_USB_SERIAL_FTDI_SIO is not set -# CONFIG_USB_SERIAL_VISOR is not set -# CONFIG_USB_SERIAL_EDGEPORT is not set -# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set -# CONFIG_USB_SERIAL_KEYSPAN is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set -# CONFIG_USB_SERIAL_MCT_U232 is not set -# CONFIG_USB_SERIAL_PL2303 is not set -# CONFIG_USB_SERIAL_CYBERJACK is not set -# CONFIG_USB_SERIAL_OMNINET is not set +CONFIG_CROSSCOMPILE=y +# CONFIG_DEBUG_KERNEL is not set # -# Miscellaneous USB drivers +# Security options # -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_ID75 is not set +# CONFIG_SECURITY is not set # -# Input core support +# Cryptographic options # -# CONFIG_INPUT is not set -# CONFIG_INPUT_KEYBDEV is not set -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_EVDEV is not set +# CONFIG_CRYPTO is not set # -# Kernel hacking +# Library routines # -CONFIG_CROSSCOMPILE=y -# CONFIG_REMOTE_DEBUG is not set -# CONFIG_GDB_CONSOLE is not set -# CONFIG_LL_DEBUG is not set -# CONFIG_MAGIC_SYSRQ is not set -# CONFIG_MIPS_UNCACHED is not set +# CONFIG_CRC32 is not set diff -Nru a/arch/mips/defconfig-ddb5477 b/arch/mips/defconfig-ddb5477 --- a/arch/mips/defconfig-ddb5477 Tue Jul 1 18:44:33 2003 +++ b/arch/mips/defconfig-ddb5477 Tue Jul 1 18:44:33 2003 @@ -2,7 +2,8 @@ # Automatically generated make config: don't edit # CONFIG_MIPS=y -# CONFIG_SMP is not set +CONFIG_MIPS32=y +# CONFIG_MIPS64 is not set # # Code maturity level options @@ -10,82 +11,114 @@ CONFIG_EXPERIMENTAL=y # +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_EMBEDDED is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# # Machine selection # # CONFIG_ACER_PICA_61 is not set -# CONFIG_ALGOR_P4032 is not set # CONFIG_BAGET_MIPS is not set +# CONFIG_CASIO_E55 is not set +# CONFIG_MIPS_COBALT is not set # CONFIG_DECSTATION is not set -# CONFIG_DDB5074 is not set -# CONFIG_MIPS_EV96100 is not set # CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_IBM_WORKPAD is not set +# CONFIG_MIPS_ITE8172 is not set # CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_NINO is not set # CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set # CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_DDB5074 is not set # CONFIG_DDB5476 is not set CONFIG_DDB5477=y +CONFIG_DDB5477_BUS_FREQUENCY=0 +# CONFIG_NEC_OSPREY is not set +# CONFIG_NEC_EAGLE is not set # CONFIG_OLIVETTI_M700 is not set # CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set # CONFIG_SNI_RM200_PCI is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_MIPS_PB1000 is not set +# CONFIG_TANBAC_TB0226 is not set +# CONFIG_TANBAC_TB0229 is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +# CONFIG_VICTOR_MPC30X is not set +# CONFIG_ZAO_CAPCELLA is not set CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set -# CONFIG_MCA is not set -# CONFIG_SBUS is not set +CONFIG_I8259=y +CONFIG_NONCOHERENT_IO=y CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_PCI=y -CONFIG_NEW_TIME_C=y -CONFIG_NEW_IRQ=y -# CONFIG_ISA is not set -# CONFIG_EISA is not set -# CONFIG_I8259 is not set - -# -# Loadable module support -# -# CONFIG_MODULES is not set +CONFIG_IRQ_CPU=y +CONFIG_DUMMY_KEYB=y +CONFIG_DDB5XXX_COMMON=y +CONFIG_NEW_PCI=y +# CONFIG_FB is not set # # CPU selection # +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set # CONFIG_CPU_R3000 is not set -# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_TX39XX is not set # CONFIG_CPU_VR41XX is not set # CONFIG_CPU_R4300 is not set # CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set # CONFIG_CPU_R5000 is not set CONFIG_CPU_R5432=y -# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_R6000 is not set # CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set # CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set # CONFIG_CPU_SB1 is not set -# CONFIG_CPU_MIPS32 is not set -# CONFIG_CPU_MIPS64 is not set # CONFIG_CPU_ADVANCED is not set CONFIG_CPU_HAS_LLSC=y CONFIG_CPU_HAS_LLDSCD=y -# CONFIG_CPU_HAS_WB is not set +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +CONFIG_KALLSYMS=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # -# General setup +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats # -CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_KCORE_ELF=y -CONFIG_ELF_KERNEL=y -# CONFIG_BINFMT_AOUT is not set CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set -CONFIG_NET=y -# CONFIG_PCI_NAMES is not set -# CONFIG_HOTPLUG is not set -# CONFIG_PCMCIA is not set -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y # # Memory Technology Devices (MTD) @@ -98,39 +131,71 @@ # CONFIG_PARPORT is not set # +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# # Block devices # # CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_RAM is not set # CONFIG_BLK_DEV_INITRD is not set # +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# # Multi-device support (RAID and LVM) # # CONFIG_MD is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_BLK_DEV_LVM is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Networking support +# +CONFIG_NET=y # # Networking options # CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set -# CONFIG_NETLINK is not set +CONFIG_NETLINK_DEV=y # CONFIG_NETFILTER is not set -# CONFIG_FILTER is not set CONFIG_UNIX=y +CONFIG_NET_KEY=y CONFIG_INET=y # CONFIG_IP_MULTICAST is not set # CONFIG_IP_ADVANCED_ROUTER is not set @@ -140,22 +205,27 @@ # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set # CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_KHTTPD is not set -# CONFIG_ATM is not set +# CONFIG_XFRM_USER is not set # -# +# SCTP Configuration (EXPERIMENTAL) # -# CONFIG_IPX is not set -# CONFIG_ATALK is not set +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC is not set # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_LLC is not set # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -168,27 +238,9 @@ # CONFIG_NET_SCHED is not set # -# Telephony Support -# -# CONFIG_PHONE is not set -# CONFIG_PHONE_IXJ is not set -# CONFIG_PHONE_IXJ_PCMCIA is not set - -# -# ATA/IDE/MFM/RLL support -# -# CONFIG_IDE is not set -# CONFIG_BLK_DEV_IDE_MODES is not set -# CONFIG_BLK_DEV_HD is not set - -# -# SCSI support -# -# CONFIG_SCSI is not set - -# -# Network device support +# Network testing # +# CONFIG_NET_PKTGEN is not set CONFIG_NETDEVICES=y # @@ -199,67 +251,43 @@ # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y -# CONFIG_SUNLANCE is not set +# CONFIG_MII is not set # CONFIG_HAPPYMEAL is not set -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set -# CONFIG_SUNLANCE is not set # CONFIG_SUNGEM is not set # CONFIG_NET_VENDOR_3COM is not set -# CONFIG_LANCE is not set -# CONFIG_NET_VENDOR_SMC is not set -# CONFIG_NET_VENDOR_RACAL is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set # CONFIG_HP100 is not set -# CONFIG_NET_ISA is not set -CONFIG_NET_PCI=y -# CONFIG_PCNET32 is not set -# CONFIG_ADAPTEC_STARFIRE is not set -# CONFIG_APRICOT is not set -# CONFIG_CS89x0 is not set -CONFIG_TULIP=y -# CONFIG_TULIP_MWI is not set -# CONFIG_TULIP_MMIO is not set -# CONFIG_DE4X5 is not set -# CONFIG_DGRS is not set -# CONFIG_DM9102 is not set -# CONFIG_EEPRO100 is not set -# CONFIG_LNE390 is not set -# CONFIG_FEALNX is not set -# CONFIG_NATSEMI is not set -# CONFIG_NE2K_PCI is not set -# CONFIG_NE3210 is not set -# CONFIG_ES3210 is not set -# CONFIG_8139TOO is not set -# CONFIG_8139TOO_PIO is not set -# CONFIG_8139TOO_TUNE_TWISTER is not set -# CONFIG_8139TOO_8129 is not set -# CONFIG_SIS900 is not set -# CONFIG_EPIC100 is not set -# CONFIG_SUNDANCE is not set -# CONFIG_TLAN is not set -# CONFIG_VIA_RHINE is not set -# CONFIG_WINBOND_840 is not set -# CONFIG_LAN_SAA9730 is not set -# CONFIG_NET_POCKET is not set +# CONFIG_NET_PCI is not set # # Ethernet (1000 Mbit) # # CONFIG_ACENIC is not set # CONFIG_DL2K is not set -# CONFIG_MYRI_SBUS is not set +# CONFIG_E1000 is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set # CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set -# CONFIG_PLIP is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -269,10 +297,8 @@ # CONFIG_NET_RADIO is not set # -# Token Ring devices +# Token Ring devices (depends on LLC=y) # -# CONFIG_TR is not set -# CONFIG_NET_FC is not set # CONFIG_RCPCI is not set # CONFIG_SHAPER is not set @@ -294,22 +320,67 @@ # # ISDN subsystem # -# CONFIG_ISDN is not set +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set # -# Old CD-ROM drivers (not SCSI, not IDE) +# Input device support # -# CONFIG_CD_NO_IDESCSI is not set +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set # # Character devices # # CONFIG_VT is not set -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y -# CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_UNIX98_PTYS is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 # # I2C support @@ -317,36 +388,35 @@ # CONFIG_I2C is not set # -# Mice +# I2C Hardware Sensors Mainboard support # -# CONFIG_BUSMOUSE is not set -# CONFIG_MOUSE is not set # -# Joysticks +# I2C Hardware Sensors Chip support # -# CONFIG_INPUT_GAMEPORT is not set +# CONFIG_I2C_SENSOR is not set # -# Input core support is needed for gameports +# Mice # +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set # -# Input core support is needed for joysticks +# IPMI # -# CONFIG_QIC02_TAPE is not set +# CONFIG_IPMI_HANDLER is not set # # Watchdog Cards # # CONFIG_WATCHDOG is not set -# CONFIG_INTEL_RNG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set -# CONFIG_SONYPI is not set # # Ftape, the floppy tape device driver @@ -354,6 +424,8 @@ # CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HANGCHECK_TIMER is not set # # Multimedia devices @@ -361,206 +433,158 @@ # CONFIG_VIDEO_DEV is not set # +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# # File systems # +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set CONFIG_AUTOFS_FS=y CONFIG_AUTOFS4_FS=y -# CONFIG_REISERFS_FS is not set -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# # CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set -# CONFIG_CMS_FS is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_JBD_DEBUG is not set -# CONFIG_FAT_FS is not set -# CONFIG_MSDOS_FS is not set -# CONFIG_UMSDOS_FS is not set -# CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -# CONFIG_JFFS2_FS is not set # CONFIG_CRAMFS is not set -# CONFIG_TMPFS is not set -# CONFIG_RAMFS is not set -# CONFIG_ISO9660_FS is not set -# CONFIG_JOLIET is not set -# CONFIG_MINIX_FS is not set -# CONFIG_FREEVXFS_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_DEBUG is not set -# CONFIG_NTFS_RW is not set +# CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -# CONFIG_DEVPTS_FS is not set # CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set # # Network File Systems # -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=y # CONFIG_NFS_V3 is not set -CONFIG_ROOT_NFS=y +# CONFIG_NFS_V4 is not set CONFIG_NFSD=y # CONFIG_NFSD_V3 is not set -CONFIG_SUNRPC=y +# CONFIG_NFSD_TCP is not set +CONFIG_ROOT_NFS=y CONFIG_LOCKD=y +CONFIG_EXPORTFS=y +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set # CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set # CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set # # Partition Types # # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y -# CONFIG_SMB_NLS is not set -# CONFIG_NLS is not set # -# Sound +# Graphics support # -# CONFIG_SOUND is not set # -# USB support -# -# CONFIG_USB is not set - -# -# USB Controllers -# -# CONFIG_USB_UHCI is not set -# CONFIG_USB_UHCI_ALT is not set -# CONFIG_USB_OHCI is not set - -# -# USB Device Class drivers -# -# CONFIG_USB_AUDIO is not set -# CONFIG_USB_BLUETOOTH is not set -# CONFIG_USB_STORAGE is not set -# CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set -# CONFIG_USB_STORAGE_DPCM is not set -# CONFIG_USB_STORAGE_SDDR09 is not set -# CONFIG_USB_ACM is not set -# CONFIG_USB_PRINTER is not set - -# -# USB Human Interface Devices (HID) -# - -# -# Input core support is needed for USB HID -# - -# -# USB Imaging devices +# Sound # -# CONFIG_USB_DC2XX is not set -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_SCANNER is not set -# CONFIG_USB_MICROTEK is not set -# CONFIG_USB_HPUSBSCSI is not set +CONFIG_SOUND=y # -# USB Multimedia devices +# Advanced Linux Sound Architecture # +# CONFIG_SND is not set # -# Video4Linux support is needed for USB Multimedia device support -# -# CONFIG_USB_DABUSB is not set +# Open Sound System +# +CONFIG_SOUND_PRIME=y +# CONFIG_SOUND_BT878 is not set +# CONFIG_SOUND_CMPCI is not set +# CONFIG_SOUND_EMU10K1 is not set +# CONFIG_SOUND_FUSION is not set +# CONFIG_SOUND_CS4281 is not set +# CONFIG_SOUND_ES1370 is not set +# CONFIG_SOUND_ES1371 is not set +# CONFIG_SOUND_ESSSOLO1 is not set +# CONFIG_SOUND_MAESTRO is not set +# CONFIG_SOUND_MAESTRO3 is not set +# CONFIG_SOUND_ICH is not set +# CONFIG_SOUND_RME96XX is not set +# CONFIG_SOUND_SONICVIBES is not set +CONFIG_SOUND_VRC5477=y +# CONFIG_SOUND_TRIDENT is not set +# CONFIG_SOUND_MSNDCLAS is not set +# CONFIG_SOUND_MSNDPIN is not set +# CONFIG_SOUND_VIA82CXXX is not set +# CONFIG_SOUND_OSS is not set # -# USB Network adaptors +# USB support # -# CONFIG_USB_PLUSB is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_CATC is not set -# CONFIG_USB_CDCETHER is not set -# CONFIG_USB_USBNET is not set +# CONFIG_USB is not set +# CONFIG_USB_GADGET is not set # -# USB port drivers +# Bluetooth support # -# CONFIG_USB_USS720 is not set +# CONFIG_BT is not set # -# USB Serial Converter support +# Kernel hacking # -# CONFIG_USB_SERIAL is not set -# CONFIG_USB_SERIAL_GENERIC is not set -# CONFIG_USB_SERIAL_BELKIN is not set -# CONFIG_USB_SERIAL_WHITEHEAT is not set -# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set -# CONFIG_USB_SERIAL_EMPEG is not set -# CONFIG_USB_SERIAL_FTDI_SIO is not set -# CONFIG_USB_SERIAL_VISOR is not set -# CONFIG_USB_SERIAL_EDGEPORT is not set -# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set -# CONFIG_USB_SERIAL_KEYSPAN is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set -# CONFIG_USB_SERIAL_MCT_U232 is not set -# CONFIG_USB_SERIAL_PL2303 is not set -# CONFIG_USB_SERIAL_CYBERJACK is not set -# CONFIG_USB_SERIAL_OMNINET is not set +CONFIG_CROSSCOMPILE=y +# CONFIG_DEBUG_KERNEL is not set # -# Miscellaneous USB drivers +# Security options # -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_ID75 is not set +# CONFIG_SECURITY is not set # -# Input core support +# Cryptographic options # -# CONFIG_INPUT is not set -# CONFIG_INPUT_KEYBDEV is not set -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_EVDEV is not set +# CONFIG_CRYPTO is not set # -# Kernel hacking +# Library routines # -CONFIG_CROSSCOMPILE=y -# CONFIG_REMOTE_DEBUG is not set -# CONFIG_GDB_CONSOLE is not set -CONFIG_LL_DEBUG=y -# CONFIG_MAGIC_SYSRQ is not set -# CONFIG_MIPS_UNCACHED is not set +# CONFIG_CRC32 is not set diff -Nru a/arch/mips/defconfig-decstation b/arch/mips/defconfig-decstation --- a/arch/mips/defconfig-decstation Tue Jul 1 18:44:39 2003 +++ b/arch/mips/defconfig-decstation Tue Jul 1 18:44:39 2003 @@ -2,7 +2,8 @@ # Automatically generated make config: don't edit # CONFIG_MIPS=y -# CONFIG_SMP is not set +CONFIG_MIPS32=y +# CONFIG_MIPS64 is not set # # Code maturity level options @@ -10,81 +11,113 @@ CONFIG_EXPERIMENTAL=y # +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_EMBEDDED is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# # Machine selection # # CONFIG_ACER_PICA_61 is not set -# CONFIG_ALGOR_P4032 is not set # CONFIG_BAGET_MIPS is not set +# CONFIG_CASIO_E55 is not set +# CONFIG_MIPS_COBALT is not set CONFIG_DECSTATION=y -# CONFIG_DDB5074 is not set -# CONFIG_MIPS_EV96100 is not set # CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_IBM_WORKPAD is not set +# CONFIG_MIPS_ITE8172 is not set # CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_NINO is not set # CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set # CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_DDB5074 is not set # CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_NEC_EAGLE is not set # CONFIG_OLIVETTI_M700 is not set # CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set # CONFIG_SNI_RM200_PCI is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_MIPS_PB1000 is not set +# CONFIG_TANBAC_TB0226 is not set +# CONFIG_TANBAC_TB0229 is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +# CONFIG_VICTOR_MPC30X is not set +# CONFIG_ZAO_CAPCELLA is not set CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set -# CONFIG_MCA is not set -# CONFIG_SBUS is not set -# CONFIG_ISA is not set -# CONFIG_EISA is not set -# CONFIG_PCI is not set -# CONFIG_I8259 is not set - -# -# Loadable module support -# -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_NONCOHERENT_IO=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_BOOT_ELF32=y +CONFIG_L1_CACHE_SHIFT=4 +# CONFIG_FB is not set # # CPU selection # +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set CONFIG_CPU_R3000=y -# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_TX39XX is not set # CONFIG_CPU_VR41XX is not set # CONFIG_CPU_R4300 is not set # CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set # CONFIG_CPU_R5000 is not set # CONFIG_CPU_R5432 is not set -# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_R6000 is not set # CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set # CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set # CONFIG_CPU_SB1 is not set -# CONFIG_CPU_MIPS32 is not set -# CONFIG_CPU_MIPS64 is not set # CONFIG_CPU_ADVANCED is not set -# CONFIG_CPU_HAS_LLSC is not set -# CONFIG_CPU_HAS_LLDSCD is not set -# CONFIG_CPU_HAS_WB is not set +CONFIG_CPU_HAS_WB=y +# CONFIG_PREEMPT is not set +CONFIG_KALLSYMS=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # -# General setup +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_TC=y +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats # -CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_KCORE_ELF=y -CONFIG_ELF_KERNEL=y -# CONFIG_BINFMT_AOUT is not set CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set -CONFIG_NET=y -# CONFIG_HOTPLUG is not set -# CONFIG_PCMCIA is not set -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_TC=y # # Memory Technology Devices (MTD) @@ -97,39 +130,90 @@ # CONFIG_PARPORT is not set # +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# # Block devices # # CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_RAM is not set # CONFIG_BLK_DEV_INITRD is not set # +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_SCSI=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_REPORT_LUNS is not set +CONFIG_SCSI_CONSTANTS=y +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI low-level drivers +# +CONFIG_SCSI_DECNCR=y +# CONFIG_SCSI_DECSII is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_DEBUG is not set + +# # Multi-device support (RAID and LVM) # # CONFIG_MD is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_BLK_DEV_LVM is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# I2O device support +# + +# +# Networking support +# +CONFIG_NET=y # # Networking options # CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set -# CONFIG_NETLINK is not set +CONFIG_NETLINK_DEV=y # CONFIG_NETFILTER is not set -# CONFIG_FILTER is not set CONFIG_UNIX=y +CONFIG_NET_KEY=y CONFIG_INET=y # CONFIG_IP_MULTICAST is not set # CONFIG_IP_ADVANCED_ROUTER is not set @@ -139,22 +223,27 @@ # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set # CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_KHTTPD is not set -# CONFIG_ATM is not set +# CONFIG_XFRM_USER is not set # -# +# SCTP Configuration (EXPERIMENTAL) # -# CONFIG_IPX is not set -# CONFIG_ATALK is not set +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC is not set # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_LLC is not set # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -167,122 +256,30 @@ # CONFIG_NET_SCHED is not set # -# Telephony Support -# -# CONFIG_PHONE is not set -# CONFIG_PHONE_IXJ is not set -# CONFIG_PHONE_IXJ_PCMCIA is not set - -# -# SCSI support -# -CONFIG_SCSI=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=y -CONFIG_SD_EXTRA_DEVS=40 -# CONFIG_CHR_DEV_ST is not set -# CONFIG_CHR_DEV_OSST is not set -# CONFIG_BLK_DEV_SR is not set -# CONFIG_CHR_DEV_SG is not set - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -# CONFIG_SCSI_DEBUG_QUEUES is not set -# CONFIG_SCSI_MULTI_LUN is not set -CONFIG_SCSI_CONSTANTS=y -# CONFIG_SCSI_LOGGING is not set - -# -# SCSI low-level drivers -# -CONFIG_SCSI_DECNCR=y -# CONFIG_SCSI_DECSII is not set -# CONFIG_SCSI_7000FASST is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AHA152X is not set -# CONFIG_SCSI_AHA1542 is not set -# CONFIG_SCSI_AHA1740 is not set -# CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_AM53C974 is not set -# CONFIG_SCSI_MEGARAID is not set -# CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_DTC3280 is not set -# CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_DMA is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -# CONFIG_SCSI_GDTH is not set -# CONFIG_SCSI_GENERIC_NCR5380 is not set -# CONFIG_SCSI_INITIO is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_NCR_D700 is not set -# CONFIG_SCSI_NCR53C7xx is not set -# CONFIG_SCSI_PAS16 is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set -# CONFIG_SCSI_PSI240I is not set -# CONFIG_SCSI_QLOGIC_FAS is not set -# CONFIG_SCSI_SIM710 is not set -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set -# CONFIG_SCSI_DEBUG is not set - -# -# Network device support +# Network testing # +# CONFIG_NET_PKTGEN is not set CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y -# CONFIG_SUNLANCE is not set -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set -# CONFIG_SUNLANCE is not set -# CONFIG_SUNGEM is not set -# CONFIG_NET_VENDOR_3COM is not set -# CONFIG_LANCE is not set -# CONFIG_NET_VENDOR_SMC is not set -# CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_NET_ISA is not set -# CONFIG_NET_PCI is not set -# CONFIG_NET_POCKET is not set +# CONFIG_MII is not set CONFIG_DECLANCE=y # # Ethernet (1000 Mbit) # -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_MYRI_SBUS is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_SK98LIN is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PLIP is not set + +# +# Ethernet (10000 Mbit) +# # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -292,11 +289,8 @@ # CONFIG_NET_RADIO is not set # -# Token Ring devices +# Token Ring devices (depends on LLC=y) # -# CONFIG_TR is not set -# CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set # CONFIG_SHAPER is not set # @@ -317,21 +311,64 @@ # # ISDN subsystem # -# CONFIG_ISDN is not set +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y # -# Old CD-ROM drivers (not SCSI, not IDE) +# Userland interfaces # -# CONFIG_CD_NO_IDESCSI is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set # # Character devices # # CONFIG_VT is not set -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y -# CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_DZ=y +CONFIG_SERIAL_DZ_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_UNIX98_PTY_COUNT=256 @@ -341,36 +378,35 @@ # CONFIG_I2C is not set # -# Mice +# I2C Hardware Sensors Mainboard support # -# CONFIG_BUSMOUSE is not set -# CONFIG_MOUSE is not set # -# Joysticks +# I2C Hardware Sensors Chip support # -# CONFIG_INPUT_GAMEPORT is not set +# CONFIG_I2C_SENSOR is not set # -# Input core support is needed for gameports +# Mice # +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set # -# Input core support is needed for joysticks +# IPMI # -# CONFIG_QIC02_TAPE is not set +# CONFIG_IPMI_HANDLER is not set # # Watchdog Cards # # CONFIG_WATCHDOG is not set -# CONFIG_INTEL_RNG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set -# CONFIG_SONYPI is not set # # Ftape, the floppy tape device driver @@ -378,6 +414,8 @@ # CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HANGCHECK_TIMER is not set # # Multimedia devices @@ -385,90 +423,81 @@ # CONFIG_VIDEO_DEV is not set # -# DECStation Character devices +# Digital Video Broadcasting Devices # -# CONFIG_VT is not set -CONFIG_SERIAL=y -# CONFIG_DZ is not set -CONFIG_ZS=y -CONFIG_SERIAL_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 -# CONFIG_RTC is not set +# CONFIG_DVB is not set # # File systems # +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# # CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set -# CONFIG_CMS_FS is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_JBD_DEBUG is not set -# CONFIG_FAT_FS is not set -# CONFIG_MSDOS_FS is not set -# CONFIG_UMSDOS_FS is not set -# CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -# CONFIG_JFFS2_FS is not set # CONFIG_CRAMFS is not set -# CONFIG_TMPFS is not set -# CONFIG_RAMFS is not set -# CONFIG_ISO9660_FS is not set -# CONFIG_JOLIET is not set -# CONFIG_MINIX_FS is not set -# CONFIG_FREEVXFS_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_DEBUG is not set -# CONFIG_NTFS_RW is not set +# CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set # # Network File Systems # -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set # CONFIG_NFS_FS is not set -# CONFIG_NFS_V3 is not set -# CONFIG_ROOT_NFS is not set # CONFIG_NFSD is not set -# CONFIG_NFSD_V3 is not set -# CONFIG_SUNRPC is not set -# CONFIG_LOCKD is not set +# CONFIG_EXPORTFS is not set # CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set # CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set # # Partition Types @@ -485,126 +514,48 @@ # CONFIG_SOLARIS_X86_PARTITION is not set # CONFIG_UNIXWARE_DISKLABEL is not set # CONFIG_LDM_PARTITION is not set +# CONFIG_NEC98_PARTITION is not set # CONFIG_SGI_PARTITION is not set CONFIG_ULTRIX_PARTITION=y # CONFIG_SUN_PARTITION is not set -# CONFIG_SMB_NLS is not set -# CONFIG_NLS is not set - -# -# USB support -# -# CONFIG_USB is not set +# CONFIG_EFI_PARTITION is not set # -# USB Controllers +# Graphics support # -# CONFIG_USB_UHCI is not set -# CONFIG_USB_UHCI_ALT is not set -# CONFIG_USB_OHCI is not set # -# USB Device Class drivers +# Sound # -# CONFIG_USB_AUDIO is not set -# CONFIG_USB_BLUETOOTH is not set -# CONFIG_USB_STORAGE is not set -# CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set -# CONFIG_USB_STORAGE_DPCM is not set -# CONFIG_USB_STORAGE_SDDR09 is not set -# CONFIG_USB_ACM is not set -# CONFIG_USB_PRINTER is not set +# CONFIG_SOUND is not set # -# USB Human Interface Devices (HID) -# - -# -# Input core support is needed for USB HID -# - -# -# USB Imaging devices -# -# CONFIG_USB_DC2XX is not set -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_SCANNER is not set -# CONFIG_USB_MICROTEK is not set -# CONFIG_USB_HPUSBSCSI is not set - -# -# USB Multimedia devices -# - -# -# Video4Linux support is needed for USB Multimedia device support -# -# CONFIG_USB_DABUSB is not set - -# -# USB Network adaptors +# USB support # -# CONFIG_USB_PLUSB is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_CATC is not set -# CONFIG_USB_CDCETHER is not set -# CONFIG_USB_USBNET is not set +# CONFIG_USB_GADGET is not set # -# USB port drivers +# Bluetooth support # -# CONFIG_USB_USS720 is not set +# CONFIG_BT is not set # -# USB Serial Converter support +# Kernel hacking # -# CONFIG_USB_SERIAL is not set -# CONFIG_USB_SERIAL_GENERIC is not set -# CONFIG_USB_SERIAL_BELKIN is not set -# CONFIG_USB_SERIAL_WHITEHEAT is not set -# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set -# CONFIG_USB_SERIAL_EMPEG is not set -# CONFIG_USB_SERIAL_FTDI_SIO is not set -# CONFIG_USB_SERIAL_VISOR is not set -# CONFIG_USB_SERIAL_EDGEPORT is not set -# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set -# CONFIG_USB_SERIAL_KEYSPAN is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set -# CONFIG_USB_SERIAL_MCT_U232 is not set -# CONFIG_USB_SERIAL_PL2303 is not set -# CONFIG_USB_SERIAL_CYBERJACK is not set -# CONFIG_USB_SERIAL_OMNINET is not set +CONFIG_CROSSCOMPILE=y +# CONFIG_DEBUG_KERNEL is not set # -# Miscellaneous USB drivers +# Security options # -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_ID75 is not set +# CONFIG_SECURITY is not set # -# Input core support +# Cryptographic options # -# CONFIG_INPUT is not set -# CONFIG_INPUT_KEYBDEV is not set -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_EVDEV is not set +# CONFIG_CRYPTO is not set # -# Kernel hacking +# Library routines # -CONFIG_CROSSCOMPILE=y -# CONFIG_REMOTE_DEBUG is not set -# CONFIG_GDB_CONSOLE is not set -# CONFIG_LL_DEBUG is not set -# CONFIG_MAGIC_SYSRQ is not set -# CONFIG_MIPS_UNCACHED is not set +# CONFIG_CRC32 is not set diff -Nru a/arch/mips/defconfig-e55 b/arch/mips/defconfig-e55 --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/defconfig-e55 Tue Jul 1 18:44:40 2003 @@ -0,0 +1,564 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +CONFIG_MIPS32=y +# CONFIG_MIPS64 is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_EMBEDDED is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_ACER_PICA_61 is not set +# CONFIG_BAGET_MIPS is not set +CONFIG_CASIO_E55=y +# CONFIG_MIPS_COBALT is not set +# CONFIG_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_IBM_WORKPAD is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_NEC_EAGLE is not set +# CONFIG_OLIVETTI_M700 is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TANBAC_TB0226 is not set +# CONFIG_TANBAC_TB0229 is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +# CONFIG_VICTOR_MPC30X is not set +# CONFIG_ZAO_CAPCELLA is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_NONCOHERENT_IO=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_VR41XX_TIME_C=y +CONFIG_DUMMY_KEYB=y +CONFIG_VR41XX_COMMON=y +# CONFIG_FB is not set + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +CONFIG_CPU_VR41XX=y +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_SB1 is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +CONFIG_KALLSYMS=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_KCORE_ELF=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y + +# +# IDE, ATA and ATAPI Block devices +# +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_IDEDISK_STROKE is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_IDE_TASK_IOCTL is not set +CONFIG_IDE_TASKFILE_IO=y + +# +# IDE chipset support/bugfixes +# + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# I2O device support +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_NETLINK_DEV=y +# CONFIG_NETFILTER is not set +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices (depends on LLC=y) +# +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +# CONFIG_SERIO is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +# CONFIG_VT_CONSOLE is not set +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# I2C Hardware Sensors Mainboard support +# + +# +# I2C Hardware Sensors Chip support +# +# CONFIG_I2C_SENSOR is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_WDT is not set +# CONFIG_WDTPCI is not set +# CONFIG_PCWATCHDOG is not set +# CONFIG_ACQUIRE_WDT is not set +# CONFIG_ADVANTECH_WDT is not set +# CONFIG_EUROTECH_WDT is not set +# CONFIG_IB700_WDT is not set +# CONFIG_I810_TCO is not set +# CONFIG_MIXCOMWD is not set +# CONFIG_SCx200_WDT is not set +# CONFIG_60XX_WDT is not set +# CONFIG_W83877F_WDT is not set +# CONFIG_MACHZ_WDT is not set +# CONFIG_SC520_WDT is not set +# CONFIG_AMD7XX_TCO is not set +# CONFIG_ALIM7101_WDT is not set +# CONFIG_SC1200_WDT is not set +# CONFIG_WAFER_WDT is not set +# CONFIG_CPU5_WDT is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HANGCHECK_TIMER is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=y +CONFIG_AUTOFS4_FS=y + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +CONFIG_NFSD=y +# CONFIG_NFSD_V3 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_LOCKD=y +CONFIG_EXPORTFS=y +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB_GADGET is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set diff -Nru a/arch/mips/defconfig-eagle b/arch/mips/defconfig-eagle --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/defconfig-eagle Tue Jul 1 18:44:40 2003 @@ -0,0 +1,728 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +CONFIG_MIPS32=y +# CONFIG_MIPS64 is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_EMBEDDED is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_ACER_PICA_61 is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_CASIO_E55 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_IBM_WORKPAD is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +CONFIG_NEC_EAGLE=y +# CONFIG_OLIVETTI_M700 is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TANBAC_TB0226 is not set +# CONFIG_TANBAC_TB0229 is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +# CONFIG_VICTOR_MPC30X is not set +# CONFIG_ZAO_CAPCELLA is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_NONCOHERENT_IO=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_VR41XX_TIME_C=y +CONFIG_DUMMY_KEYB=y +CONFIG_VR41XX_COMMON=y +CONFIG_VRC4173=y +CONFIG_NEW_PCI=y +# CONFIG_FB is not set + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +CONFIG_CPU_VR41XX=y +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_SB1 is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +CONFIG_KALLSYMS=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y +CONFIG_MMU=y +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=y +# CONFIG_YENTA is not set +# CONFIG_I82092 is not set +# CONFIG_TCIC is not set +# CONFIG_PCMCIA_VRC4173 is not set + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set + +# +# Executable file formats +# +CONFIG_KCORE_ELF=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_PARTITIONS is not set +# CONFIG_MTD_CONCAT is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_CFI_ADV_OPTIONS=y +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set +# CONFIG_MTD_CFI_GEOMETRY is not set +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CFI_STAA is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_START=0x1c000000 +CONFIG_MTD_PHYSMAP_LEN=0x2000000 +CONFIG_MTD_PHYSMAP_BUSWIDTH=4 + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y + +# +# IDE, ATA and ATAPI Block devices +# +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +# CONFIG_IDEDISK_STROKE is not set +CONFIG_BLK_DEV_IDECS=y +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_IDE_TASK_IOCTL is not set +CONFIG_IDE_TASKFILE_IO=y + +# +# IDE chipset support/bugfixes +# +# CONFIG_BLK_DEV_IDEPCI is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_NETLINK_DEV=y +# CONFIG_NETFILTER is not set +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices (depends on LLC=y) +# +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +# CONFIG_PCMCIA_3C589 is not set +# CONFIG_PCMCIA_3C574 is not set +CONFIG_PCMCIA_FMVJ18X=y +CONFIG_PCMCIA_PCNET=m +# CONFIG_PCMCIA_NMCLAN is not set +# CONFIG_PCMCIA_SMC91C92 is not set +# CONFIG_PCMCIA_XIRC2PS is not set +# CONFIG_PCMCIA_AXNET is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +# CONFIG_SERIO is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +# CONFIG_VT_CONSOLE is not set +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_CS is not set +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# I2C Hardware Sensors Mainboard support +# + +# +# I2C Hardware Sensors Chip support +# +# CONFIG_I2C_SENSOR is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_WDT is not set +# CONFIG_WDTPCI is not set +# CONFIG_PCWATCHDOG is not set +# CONFIG_ACQUIRE_WDT is not set +# CONFIG_ADVANTECH_WDT is not set +# CONFIG_EUROTECH_WDT is not set +# CONFIG_IB700_WDT is not set +# CONFIG_I810_TCO is not set +# CONFIG_MIXCOMWD is not set +# CONFIG_SCx200_WDT is not set +# CONFIG_60XX_WDT is not set +# CONFIG_W83877F_WDT is not set +# CONFIG_MACHZ_WDT is not set +# CONFIG_SC520_WDT is not set +# CONFIG_AMD7XX_TCO is not set +# CONFIG_ALIM7101_WDT is not set +# CONFIG_SC1200_WDT is not set +# CONFIG_WAFER_WDT is not set +# CONFIG_CPU5_WDT is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HANGCHECK_TIMER is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=y +CONFIG_AUTOFS4_FS=y + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS_FS=y +CONFIG_JFFS_FS_VERBOSE=0 +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +# CONFIG_JFFS2_FS_NAND is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +CONFIG_NFSD=y +# CONFIG_NFSD_V3 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_EXPORTFS=y +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set +# CONFIG_USB_GADGET is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=y +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +CONFIG_CRYPTO_SHA512=y +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_BLOWFISH is not set +CONFIG_CRYPTO_TWOFISH=y +# CONFIG_CRYPTO_SERPENT is not set +CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_TEST is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff -Nru a/arch/mips/defconfig-ev64120 b/arch/mips/defconfig-ev64120 --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/defconfig-ev64120 Tue Jul 1 18:44:40 2003 @@ -0,0 +1,571 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +CONFIG_MIPS32=y +# CONFIG_MIPS64 is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_EMBEDDED is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +# CONFIG_KMOD is not set + +# +# Machine selection +# +# CONFIG_ACER_PICA_61 is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_CASIO_E55 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_DECSTATION is not set +CONFIG_MIPS_EV64120=y +# CONFIG_EVB_PCI1 is not set +CONFIG_SYSCLK_100=y +# CONFIG_SYSCLK_75 is not set +# CONFIG_SYSCLK_83 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_IBM_WORKPAD is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_NEC_EAGLE is not set +# CONFIG_OLIVETTI_M700 is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TANBAC_TB0226 is not set +# CONFIG_TANBAC_TB0229 is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +# CONFIG_VICTOR_MPC30X is not set +# CONFIG_ZAO_CAPCELLA is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_CONFIG_GT64120=y +CONFIG_NONCOHERENT_IO=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_MIPS_GT64120=y +# CONFIG_FB is not set + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +CONFIG_CPU_R5000=y +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_SB1 is not set +# CONFIG_64BIT_PHYS_ADDR is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +CONFIG_KALLSYMS=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_KCORE_ELF=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_BINFMT_IRIX is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_PACKET is not set +CONFIG_NETLINK_DEV=y +# CONFIG_NETFILTER is not set +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PPP=y +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=y +# CONFIG_PPP_SYNC_TTY is not set +# CONFIG_PPP_DEFLATE is not set +# CONFIG_PPP_BSDCOMP is not set +# CONFIG_PPPOE is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices (depends on LLC=y) +# +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +# CONFIG_SERIAL_8250_CONSOLE is not set +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# I2C Hardware Sensors Mainboard support +# + +# +# I2C Hardware Sensors Chip support +# +# CONFIG_I2C_SENSOR is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HANGCHECK_TIMER is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Graphics support +# + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set +# CONFIG_USB_GADGET is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set diff -Nru a/arch/mips/defconfig-ev96100 b/arch/mips/defconfig-ev96100 --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/defconfig-ev96100 Tue Jul 1 18:44:40 2003 @@ -0,0 +1,523 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +CONFIG_MIPS32=y +# CONFIG_MIPS64 is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_EMBEDDED is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +# CONFIG_KMOD is not set + +# +# Machine selection +# +# CONFIG_ACER_PICA_61 is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_CASIO_E55 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +CONFIG_MIPS_EV96100=y +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_IBM_WORKPAD is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_NEC_EAGLE is not set +# CONFIG_OLIVETTI_M700 is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TANBAC_TB0226 is not set +# CONFIG_TANBAC_TB0229 is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +# CONFIG_VICTOR_MPC30X is not set +# CONFIG_ZAO_CAPCELLA is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_NONCOHERENT_IO=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_NEW_PCI=y +CONFIG_SWAP_IO_SPACE=y +CONFIG_MIPS_GT96100=y +# CONFIG_FB is not set +CONFIG_BOARD_SCACHE=y + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +CONFIG_CPU_RM7000=y +# CONFIG_CPU_SB1 is not set +CONFIG_CPU_HAS_PREFETCH=y +# CONFIG_64BIT_PHYS_ADDR is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +CONFIG_KALLSYMS=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +# CONFIG_PCI is not set +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_KCORE_ELF=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_BINFMT_IRIX is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# I2O device support +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_PACKET is not set +CONFIG_NETLINK_DEV=y +# CONFIG_NETFILTER is not set +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +CONFIG_MIPS_GT96100ETH=y + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices (depends on LLC=y) +# +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# I2C Hardware Sensors Mainboard support +# + +# +# I2C Hardware Sensors Chip support +# +# CONFIG_I2C_SENSOR is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HANGCHECK_TIMER is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Graphics support +# + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB_GADGET is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set diff -Nru a/arch/mips/defconfig-ip22 b/arch/mips/defconfig-ip22 --- a/arch/mips/defconfig-ip22 Tue Jul 1 18:44:39 2003 +++ b/arch/mips/defconfig-ip22 Tue Jul 1 18:44:39 2003 @@ -2,7 +2,8 @@ # Automatically generated make config: don't edit # CONFIG_MIPS=y -# CONFIG_SMP is not set +CONFIG_MIPS32=y +# CONFIG_MIPS64 is not set # # Code maturity level options @@ -10,89 +11,123 @@ CONFIG_EXPERIMENTAL=y # +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_EMBEDDED is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# # Machine selection # # CONFIG_ACER_PICA_61 is not set -# CONFIG_ALGOR_P4032 is not set # CONFIG_BAGET_MIPS is not set +# CONFIG_CASIO_E55 is not set +# CONFIG_MIPS_COBALT is not set # CONFIG_DECSTATION is not set -# CONFIG_DDB5074 is not set -# CONFIG_MIPS_EV96100 is not set # CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_IBM_WORKPAD is not set +# CONFIG_MIPS_ITE8172 is not set # CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_NINO is not set # CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set # CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_DDB5074 is not set # CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_NEC_EAGLE is not set # CONFIG_OLIVETTI_M700 is not set CONFIG_SGI_IP22=y +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set # CONFIG_SNI_RM200_PCI is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_MIPS_PB1000 is not set +# CONFIG_TANBAC_TB0226 is not set +# CONFIG_TANBAC_TB0229 is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +# CONFIG_VICTOR_MPC30X is not set +# CONFIG_ZAO_CAPCELLA is not set CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set -# CONFIG_MCA is not set -# CONFIG_SBUS is not set +CONFIG_ARC=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_NONCOHERENT_IO=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_IRQ_CPU=y +CONFIG_SWAP_IO_SPACE=y +CONFIG_BOOT_ELF32=y +CONFIG_L1_CACHE_SHIFT=5 CONFIG_ARC32=y +# CONFIG_FB is not set +CONFIG_ARC_CONSOLE=y +CONFIG_ARC_PROMLIB=y CONFIG_BOARD_SCACHE=y -CONFIG_PC_KEYB=y -CONFIG_SGI=y -CONFIG_NEW_IRQ=y -CONFIG_OLD_TIME_C=y -# CONFIG_ISA is not set -# CONFIG_EISA is not set -# CONFIG_PCI is not set -# CONFIG_I8259 is not set - -# -# Loadable module support -# -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y # # CPU selection # +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set # CONFIG_CPU_R3000 is not set -# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_TX39XX is not set # CONFIG_CPU_VR41XX is not set # CONFIG_CPU_R4300 is not set # CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set CONFIG_CPU_R5000=y # CONFIG_CPU_R5432 is not set -# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_R6000 is not set # CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set # CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set # CONFIG_CPU_SB1 is not set -# CONFIG_CPU_MIPS32 is not set -# CONFIG_CPU_MIPS64 is not set +# CONFIG_64BIT_PHYS_ADDR is not set # CONFIG_CPU_ADVANCED is not set CONFIG_CPU_HAS_LLSC=y CONFIG_CPU_HAS_LLDSCD=y -# CONFIG_CPU_HAS_WB is not set +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +CONFIG_KALLSYMS=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # -# General setup +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +# CONFIG_ISA is not set +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats # -# CONFIG_CPU_LITTLE_ENDIAN is not set CONFIG_KCORE_ELF=y -CONFIG_ELF_KERNEL=y -CONFIG_BINFMT_IRIX=y -CONFIG_FORWARD_KEYBOARD=y -# CONFIG_ARC_CONSOLE is not set -# CONFIG_BINFMT_AOUT is not set CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set -CONFIG_NET=y -# CONFIG_HOTPLUG is not set -# CONFIG_PCMCIA is not set -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y +CONFIG_BINFMT_IRIX=y # # Memory Technology Devices (MTD) @@ -105,41 +140,90 @@ # CONFIG_PARPORT is not set # +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# # Block devices # # CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_RAM is not set # CONFIG_BLK_DEV_INITRD is not set # +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_SCSI=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_ST=y +# CONFIG_CHR_DEV_OSST is not set +CONFIG_BLK_DEV_SR=y +# CONFIG_BLK_DEV_SR_VENDOR is not set +# CONFIG_CHR_DEV_SG is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_REPORT_LUNS is not set +CONFIG_SCSI_CONSTANTS=y +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI low-level drivers +# +CONFIG_SGIWD93_SCSI=y +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_DEBUG is not set + +# # Multi-device support (RAID and LVM) # # CONFIG_MD is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_BLK_DEV_LVM is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# I2O device support +# + +# +# Networking support +# +CONFIG_NET=y # # Networking options # CONFIG_PACKET=y CONFIG_PACKET_MMAP=y -CONFIG_NETLINK=y -CONFIG_RTNETLINK=y CONFIG_NETLINK_DEV=y # CONFIG_NETFILTER is not set -# CONFIG_FILTER is not set CONFIG_UNIX=y +CONFIG_NET_KEY=y CONFIG_INET=y CONFIG_IP_MULTICAST=y # CONFIG_IP_ADVANCED_ROUTER is not set @@ -153,20 +237,24 @@ # CONFIG_ARPD is not set # CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_KHTTPD is not set -# CONFIG_ATM is not set +# CONFIG_XFRM_USER is not set # -# +# SCTP Configuration (EXPERIMENTAL) # -# CONFIG_IPX is not set -# CONFIG_ATALK is not set +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC is not set # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_LLC is not set # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -179,87 +267,10 @@ # CONFIG_NET_SCHED is not set # -# Telephony Support -# -# CONFIG_PHONE is not set -# CONFIG_PHONE_IXJ is not set -# CONFIG_PHONE_IXJ_PCMCIA is not set - -# -# SCSI support -# -CONFIG_SCSI=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=y -CONFIG_SD_EXTRA_DEVS=40 -CONFIG_CHR_DEV_ST=y -# CONFIG_CHR_DEV_OSST is not set -CONFIG_BLK_DEV_SR=y -# CONFIG_BLK_DEV_SR_VENDOR is not set -CONFIG_SR_EXTRA_DEVS=2 -# CONFIG_CHR_DEV_SG is not set - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -# CONFIG_SCSI_DEBUG_QUEUES is not set -# CONFIG_SCSI_MULTI_LUN is not set -CONFIG_SCSI_CONSTANTS=y -# CONFIG_SCSI_LOGGING is not set - -# -# SCSI low-level drivers -# -CONFIG_SGIWD93_SCSI=y -# CONFIG_SCSI_7000FASST is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AHA152X is not set -# CONFIG_SCSI_AHA1542 is not set -# CONFIG_SCSI_AHA1740 is not set -# CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_AM53C974 is not set -# CONFIG_SCSI_MEGARAID is not set -# CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_DTC3280 is not set -# CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_DMA is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -# CONFIG_SCSI_GDTH is not set -# CONFIG_SCSI_GENERIC_NCR5380 is not set -# CONFIG_SCSI_INITIO is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_NCR_D700 is not set -# CONFIG_SCSI_NCR53C7xx is not set -# CONFIG_SCSI_PAS16 is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set -# CONFIG_SCSI_PSI240I is not set -# CONFIG_SCSI_QLOGIC_FAS is not set -# CONFIG_SCSI_SIM710 is not set -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set -# CONFIG_SCSI_DEBUG is not set - -# -# Network device support +# Network testing # +# CONFIG_NET_PKTGEN is not set CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set @@ -270,33 +281,16 @@ # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y -# CONFIG_SUNLANCE is not set -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set -# CONFIG_SUNLANCE is not set -# CONFIG_SUNGEM is not set -# CONFIG_NET_VENDOR_3COM is not set -# CONFIG_LANCE is not set -# CONFIG_NET_VENDOR_SMC is not set -# CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_NET_ISA is not set -# CONFIG_NET_PCI is not set -# CONFIG_NET_POCKET is not set +# CONFIG_MII is not set CONFIG_SGISEEQ=y # # Ethernet (1000 Mbit) # -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_MYRI_SBUS is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_SK98LIN is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PLIP is not set + +# +# Ethernet (10000 Mbit) +# # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -306,11 +300,8 @@ # CONFIG_NET_RADIO is not set # -# Token Ring devices +# Token Ring devices (depends on LLC=y) # -# CONFIG_TR is not set -# CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set # CONFIG_SHAPER is not set # @@ -331,21 +322,69 @@ # # ISDN subsystem # -# CONFIG_ISDN is not set +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set # -# Old CD-ROM drivers (not SCSI, not IDE) +# Input device support +# +CONFIG_INPUT=y + # -# CONFIG_CD_NO_IDESCSI is not set +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set # # Character devices # CONFIG_VT=y CONFIG_VT_CONSOLE=y -# CONFIG_SERIAL is not set -# CONFIG_SERIAL_EXTENDED is not set +CONFIG_HW_CONSOLE=y # CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_IP22_ZILOG=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_UNIX98_PTY_COUNT=256 @@ -355,36 +394,58 @@ # CONFIG_I2C is not set # -# Mice +# I2C Hardware Sensors Mainboard support # -# CONFIG_BUSMOUSE is not set -# CONFIG_MOUSE is not set # -# Joysticks +# I2C Hardware Sensors Chip support # -# CONFIG_INPUT_GAMEPORT is not set +# CONFIG_I2C_SENSOR is not set # -# Input core support is needed for gameports +# Mice # +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set # -# Input core support is needed for joysticks +# IPMI # -# CONFIG_QIC02_TAPE is not set +# CONFIG_IPMI_HANDLER is not set # # Watchdog Cards # -# CONFIG_WATCHDOG is not set -# CONFIG_INTEL_RNG is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_WDT is not set +# CONFIG_WDTPCI is not set +# CONFIG_PCWATCHDOG is not set +# CONFIG_ACQUIRE_WDT is not set +# CONFIG_ADVANTECH_WDT is not set +# CONFIG_EUROTECH_WDT is not set +# CONFIG_IB700_WDT is not set +# CONFIG_I810_TCO is not set +# CONFIG_MIXCOMWD is not set +# CONFIG_SCx200_WDT is not set +# CONFIG_60XX_WDT is not set +# CONFIG_W83877F_WDT is not set +# CONFIG_MACHZ_WDT is not set +CONFIG_INDYDOG=y +# CONFIG_SC520_WDT is not set +# CONFIG_AMD7XX_TCO is not set +# CONFIG_ALIM7101_WDT is not set +# CONFIG_SC1200_WDT is not set +# CONFIG_WAFER_WDT is not set +# CONFIG_CPU5_WDT is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +CONFIG_SGI_DS1286=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set -# CONFIG_SONYPI is not set # # Ftape, the floppy tape device driver @@ -392,6 +453,8 @@ # CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HANGCHECK_TIMER is not set # # Multimedia devices @@ -399,89 +462,92 @@ # CONFIG_VIDEO_DEV is not set # -# SGI Character devices +# Digital Video Broadcasting Devices # -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_SGI_NEWPORT_CONSOLE=y -CONFIG_FONT_8x16=y -# CONFIG_PSMOUSE is not set -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 +# CONFIG_DVB is not set # # File systems # +# CONFIG_EXT2_FS is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set CONFIG_AUTOFS_FS=y CONFIG_AUTOFS4_FS=y -# CONFIG_REISERFS_FS is not set -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +# CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# # CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set -# CONFIG_CMS_FS is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_JBD_DEBUG is not set -# CONFIG_FAT_FS is not set -# CONFIG_MSDOS_FS is not set -# CONFIG_UMSDOS_FS is not set -# CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -# CONFIG_JFFS2_FS is not set # CONFIG_CRAMFS is not set -# CONFIG_TMPFS is not set -# CONFIG_RAMFS is not set -CONFIG_ISO9660_FS=y -# CONFIG_JOLIET is not set -# CONFIG_MINIX_FS is not set -# CONFIG_FREEVXFS_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_DEBUG is not set -# CONFIG_NTFS_RW is not set +# CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set # # Network File Systems # -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=y # CONFIG_NFS_V3 is not set -CONFIG_ROOT_NFS=y +# CONFIG_NFS_V4 is not set CONFIG_NFSD=y # CONFIG_NFSD_V3 is not set -CONFIG_SUNRPC=y +# CONFIG_NFSD_TCP is not set +CONFIG_ROOT_NFS=y CONFIG_LOCKD=y +CONFIG_EXPORTFS=y +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set # CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set # CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set # # Partition Types @@ -498,22 +564,33 @@ # CONFIG_SOLARIS_X86_PARTITION is not set # CONFIG_UNIXWARE_DISKLABEL is not set # CONFIG_LDM_PARTITION is not set +# CONFIG_NEC98_PARTITION is not set CONFIG_SGI_PARTITION=y # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set -# CONFIG_SMB_NLS is not set -# CONFIG_NLS is not set +# CONFIG_EFI_PARTITION is not set # -# Console drivers +# Graphics support +# + +# +# Console display driver support # # CONFIG_VGA_CONSOLE is not set # CONFIG_MDA_CONSOLE is not set +CONFIG_SGI_NEWPORT_CONSOLE=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_FONT_8x16=y # -# Frame-buffer support +# Logo configuration # -# CONFIG_FB is not set +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +# CONFIG_LOGO_LINUX_CLUT224 is not set +CONFIG_LOGO_SGI_CLUT224=y # # Sound @@ -521,124 +598,48 @@ # CONFIG_SOUND is not set # -# SGI devices -# -CONFIG_SGI_SERIAL=y -# CONFIG_SERIAL_CONSOLE is not set -CONFIG_SGI_DS1286=y -# CONFIG_SGI_NEWPORT_GFX is not set - -# # USB support # -# CONFIG_USB is not set - -# -# USB Controllers -# -# CONFIG_USB_UHCI is not set -# CONFIG_USB_UHCI_ALT is not set -# CONFIG_USB_OHCI is not set - -# -# USB Device Class drivers -# -# CONFIG_USB_AUDIO is not set -# CONFIG_USB_BLUETOOTH is not set -# CONFIG_USB_STORAGE is not set -# CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set -# CONFIG_USB_STORAGE_DPCM is not set -# CONFIG_USB_STORAGE_SDDR09 is not set -# CONFIG_USB_ACM is not set -# CONFIG_USB_PRINTER is not set - -# -# USB Human Interface Devices (HID) -# - -# -# Input core support is needed for USB HID -# - -# -# USB Imaging devices -# -# CONFIG_USB_DC2XX is not set -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_SCANNER is not set -# CONFIG_USB_MICROTEK is not set -# CONFIG_USB_HPUSBSCSI is not set +# CONFIG_USB_GADGET is not set # -# USB Multimedia devices +# Bluetooth support # +# CONFIG_BT is not set # -# Video4Linux support is needed for USB Multimedia device support -# -# CONFIG_USB_DABUSB is not set - -# -# USB Network adaptors -# -# CONFIG_USB_PLUSB is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_CATC is not set -# CONFIG_USB_CDCETHER is not set -# CONFIG_USB_USBNET is not set - -# -# USB port drivers -# -# CONFIG_USB_USS720 is not set - -# -# USB Serial Converter support +# Kernel hacking # -# CONFIG_USB_SERIAL is not set -# CONFIG_USB_SERIAL_GENERIC is not set -# CONFIG_USB_SERIAL_BELKIN is not set -# CONFIG_USB_SERIAL_WHITEHEAT is not set -# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set -# CONFIG_USB_SERIAL_EMPEG is not set -# CONFIG_USB_SERIAL_FTDI_SIO is not set -# CONFIG_USB_SERIAL_VISOR is not set -# CONFIG_USB_SERIAL_EDGEPORT is not set -# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set -# CONFIG_USB_SERIAL_KEYSPAN is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set -# CONFIG_USB_SERIAL_MCT_U232 is not set -# CONFIG_USB_SERIAL_PL2303 is not set -# CONFIG_USB_SERIAL_CYBERJACK is not set -# CONFIG_USB_SERIAL_OMNINET is not set +CONFIG_CROSSCOMPILE=y +# CONFIG_DEBUG_KERNEL is not set # -# Miscellaneous USB drivers +# Security options # -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_ID75 is not set +# CONFIG_SECURITY is not set # -# Input core support +# Cryptographic options # -# CONFIG_INPUT is not set -# CONFIG_INPUT_KEYBDEV is not set -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_EVDEV is not set +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_BLOWFISH=y +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_SERPENT=y +CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_TEST is not set # -# Kernel hacking +# Library routines # -CONFIG_CROSSCOMPILE=y -# CONFIG_MAGIC_SYSRQ is not set -# CONFIG_MIPS_UNCACHED is not set +# CONFIG_CRC32 is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff -Nru a/arch/mips/defconfig-jmr3927 b/arch/mips/defconfig-jmr3927 --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/defconfig-jmr3927 Tue Jul 1 18:44:39 2003 @@ -0,0 +1,598 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +CONFIG_MIPS32=y +# CONFIG_MIPS64 is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_EMBEDDED is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# Machine selection +# +# CONFIG_ACER_PICA_61 is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_CASIO_E55 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_IBM_WORKPAD is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_NEC_EAGLE is not set +# CONFIG_OLIVETTI_M700 is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TANBAC_TB0226 is not set +# CONFIG_TANBAC_TB0229 is not set +CONFIG_TOSHIBA_JMR3927=y +# CONFIG_TOSHIBA_RBTX4927 is not set +# CONFIG_VICTOR_MPC30X is not set +# CONFIG_ZAO_CAPCELLA is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_NONCOHERENT_IO=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_NEW_PCI=y +CONFIG_SWAP_IO_SPACE=y +CONFIG_FB=y +CONFIG_TOSHIBA_BOARDS=y + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +CONFIG_CPU_TX39XX=y +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_SB1 is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +CONFIG_KALLSYMS=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +CONFIG_RTC_DS1742=y + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_KCORE_ELF=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_BINFMT_IRIX is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=y +# CONFIG_NETFILTER is not set +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices (depends on LLC=y) +# +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +# CONFIG_VT_CONSOLE is not set +CONFIG_HW_CONSOLE=y +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_COMPUTONE is not set +# CONFIG_ROCKETPORT is not set +# CONFIG_CYCLADES is not set +# CONFIG_DIGIEPCA is not set +# CONFIG_DIGI is not set +# CONFIG_MOXA_INTELLIO is not set +# CONFIG_MOXA_SMARTIO is not set +# CONFIG_SYNCLINK is not set +# CONFIG_SYNCLINKMP is not set +# CONFIG_N_HDLC is not set +# CONFIG_RISCOM8 is not set +# CONFIG_SPECIALIX is not set +# CONFIG_SX is not set +# CONFIG_RIO is not set +# CONFIG_STALDRV is not set +# CONFIG_SERIAL_TX3912 is not set +CONFIG_TXX927_SERIAL=y +CONFIG_TXX927_SERIAL_CONSOLE=y +# CONFIG_SERIAL_TXX9 is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_UNIX98_PTYS is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# I2C Hardware Sensors Mainboard support +# + +# +# I2C Hardware Sensors Chip support +# +# CONFIG_I2C_SENSOR is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HANGCHECK_TIMER is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# File systems +# +# CONFIG_EXT2_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Graphics support +# +# CONFIG_FB_CIRRUS is not set +# CONFIG_FB_PM2 is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_RIVA is not set +# CONFIG_FB_MATROX is not set +# CONFIG_FB_RADEON is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_PM3 is not set +# CONFIG_FB_E1356 is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE is not set + +# +# Logo configuration +# +# CONFIG_LOGO is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set +# CONFIG_USB_GADGET is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set diff -Nru a/arch/mips/defconfig-lasat200 b/arch/mips/defconfig-lasat200 --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/defconfig-lasat200 Tue Jul 1 18:44:40 2003 @@ -0,0 +1,679 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +CONFIG_MIPS32=y +# CONFIG_MIPS64 is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_EMBEDDED is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_ACER_PICA_61 is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_CASIO_E55 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +CONFIG_LASAT=y +# CONFIG_LASAT_100 is not set +CONFIG_LASAT_200=y +CONFIG_PICVUE=y +CONFIG_PICVUE_PROC=y +CONFIG_DS1603=y +CONFIG_LASAT_SYSCTL=y +# CONFIG_HP_LASERJET is not set +# CONFIG_IBM_WORKPAD is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_NEC_EAGLE is not set +# CONFIG_OLIVETTI_M700 is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TANBAC_TB0226 is not set +# CONFIG_TANBAC_TB0229 is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +# CONFIG_VICTOR_MPC30X is not set +# CONFIG_ZAO_CAPCELLA is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_NONCOHERENT_IO=y +CONFIG_CPU_LITTLE_ENDIAN=y +# CONFIG_FB is not set +CONFIG_BOARD_SCACHE=y + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +CONFIG_CPU_R5000=y +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_R5000_CPU_SCACHE=y +# CONFIG_64BIT_PHYS_ADDR is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +CONFIG_KALLSYMS=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y +# CONFIG_PCI_NAMES is not set +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_KCORE_ELF=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_CONCAT is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PHYSMAP is not set +CONFIG_MTD_LASAT=y +# CONFIG_MTD_UCLINUX is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y + +# +# IDE, ATA and ATAPI Block devices +# +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +# CONFIG_IDEDISK_STROKE is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_IDE_TASK_IOCTL is not set +CONFIG_IDE_TASKFILE_IO=y + +# +# IDE chipset support/bugfixes +# +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_BLK_DEV_GENERIC=y +# CONFIG_IDEPCI_SHARE_IRQ is not set +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDE_TCQ is not set +# CONFIG_BLK_DEV_OFFBOARD is not set +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_PCI_WIP is not set +CONFIG_BLK_DEV_ADMA=y +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +CONFIG_BLK_DEV_CMD64X=y +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_HPT34X is not set +# CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_SC1200 is not set +# CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_OPTI621 is not set +# CONFIG_BLK_DEV_PDC202XX_OLD is not set +# CONFIG_BLK_DEV_PDC202XX_NEW is not set +# CONFIG_BLK_DEV_SVWKS is not set +# CONFIG_BLK_DEV_SIIMAGE is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_IDEDMA_IVB is not set +CONFIG_BLK_DEV_IDE_MODES=y + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_PACKET is not set +# CONFIG_NETLINK_DEV is not set +# CONFIG_NETFILTER is not set +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices (depends on LLC=y) +# +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +# CONFIG_SERIO is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# I2C Hardware Sensors Mainboard support +# + +# +# I2C Hardware Sensors Chip support +# +# CONFIG_I2C_SENSOR is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HANGCHECK_TIMER is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V4 is not set +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Graphics support +# + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set +# CONFIG_USB_GADGET is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +CONFIG_CRC32=y diff -Nru a/arch/mips/defconfig-malta b/arch/mips/defconfig-malta --- a/arch/mips/defconfig-malta Tue Jul 1 18:44:33 2003 +++ b/arch/mips/defconfig-malta Tue Jul 1 18:44:33 2003 @@ -2,7 +2,8 @@ # Automatically generated make config: don't edit # CONFIG_MIPS=y -# CONFIG_SMP is not set +CONFIG_MIPS32=y +# CONFIG_MIPS64 is not set # # Code maturity level options @@ -10,82 +11,120 @@ CONFIG_EXPERIMENTAL=y # +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_EMBEDDED is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# # Machine selection # # CONFIG_ACER_PICA_61 is not set -# CONFIG_ALGOR_P4032 is not set # CONFIG_BAGET_MIPS is not set +# CONFIG_CASIO_E55 is not set +# CONFIG_MIPS_COBALT is not set # CONFIG_DECSTATION is not set -# CONFIG_DDB5074 is not set -# CONFIG_MIPS_EV96100 is not set # CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_IBM_WORKPAD is not set +# CONFIG_MIPS_ITE8172 is not set # CONFIG_MIPS_ATLAS is not set -CONFIG_MIPS_MALTA=y -# CONFIG_NINO is not set # CONFIG_MIPS_MAGNUM_4000 is not set +CONFIG_MIPS_MALTA=y +# CONFIG_MIPS_SEAD is not set # CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_DDB5074 is not set # CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_NEC_EAGLE is not set # CONFIG_OLIVETTI_M700 is not set # CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set # CONFIG_SNI_RM200_PCI is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_MIPS_PB1000 is not set +# CONFIG_TANBAC_TB0226 is not set +# CONFIG_TANBAC_TB0229 is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +# CONFIG_VICTOR_MPC30X is not set +# CONFIG_ZAO_CAPCELLA is not set CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set -# CONFIG_MCA is not set -# CONFIG_SBUS is not set +CONFIG_GENERIC_ISA_DMA=y CONFIG_I8259=y -CONFIG_PCI=y -CONFIG_HAVE_STD_PC_SERIAL_PORT=y -CONFIG_NEW_IRQ=y +CONFIG_NONCOHERENT_IO=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_MIPS_BOARDS_GEN=y CONFIG_SWAP_IO_SPACE=y -# CONFIG_ISA is not set -# CONFIG_EISA is not set - -# -# Loadable module support -# -# CONFIG_MODULES is not set +CONFIG_BOOT_ELF32=y +CONFIG_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set +CONFIG_HAVE_STD_PC_SERIAL_PORT=y # # CPU selection # +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS64 is not set # CONFIG_CPU_R3000 is not set -# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_TX39XX is not set # CONFIG_CPU_VR41XX is not set # CONFIG_CPU_R4300 is not set # CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set # CONFIG_CPU_R5000 is not set # CONFIG_CPU_R5432 is not set -# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_R6000 is not set # CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set # CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set # CONFIG_CPU_SB1 is not set -CONFIG_CPU_MIPS32=y -# CONFIG_CPU_MIPS64 is not set +CONFIG_CPU_HAS_PREFETCH=y +# CONFIG_VTAG_ICACHE is not set +# CONFIG_64BIT_PHYS_ADDR is not set # CONFIG_CPU_ADVANCED is not set CONFIG_CPU_HAS_LLSC=y -# CONFIG_CPU_HAS_LLDSCD is not set -# CONFIG_CPU_HAS_WB is not set +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +CONFIG_KALLSYMS=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # -# General setup +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +# CONFIG_PCI is not set +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats # -CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_KCORE_ELF=y -CONFIG_ELF_KERNEL=y -# CONFIG_BINFMT_AOUT is not set CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set -CONFIG_NET=y -# CONFIG_PCI_NAMES is not set -# CONFIG_HOTPLUG is not set -# CONFIG_PCMCIA is not set -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -# CONFIG_SYSCTL is not set # # Memory Technology Devices (MTD) @@ -98,14 +137,19 @@ # CONFIG_PARPORT is not set # +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# # Block devices # CONFIG_BLK_DEV_FD=y -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set CONFIG_BLK_DEV_RAM=y @@ -113,49 +157,98 @@ # CONFIG_BLK_DEV_INITRD is not set # +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_SCSI=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_REPORT_LUNS is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI low-level drivers +# +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_DEBUG is not set + +# # Multi-device support (RAID and LVM) # # CONFIG_MD is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_BLK_DEV_LVM is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# I2O device support +# + +# +# Networking support +# +CONFIG_NET=y # # Networking options # # CONFIG_PACKET is not set -# CONFIG_NETLINK is not set +CONFIG_NETLINK_DEV=y # CONFIG_NETFILTER is not set -# CONFIG_FILTER is not set CONFIG_UNIX=y +CONFIG_NET_KEY=y CONFIG_INET=y # CONFIG_IP_MULTICAST is not set # CONFIG_IP_ADVANCED_ROUTER is not set CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -# CONFIG_IP_PNP_BOOTP is not set +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set # CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_KHTTPD is not set -# CONFIG_ATM is not set +# CONFIG_XFRM_USER is not set # -# +# SCTP Configuration (EXPERIMENTAL) # -# CONFIG_IPX is not set -# CONFIG_ATALK is not set +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC is not set # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_LLC is not set # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -168,162 +261,29 @@ # CONFIG_NET_SCHED is not set # -# Telephony Support -# -# CONFIG_PHONE is not set -# CONFIG_PHONE_IXJ is not set -# CONFIG_PHONE_IXJ_PCMCIA is not set - -# -# ATA/IDE/MFM/RLL support -# -# CONFIG_IDE is not set -# CONFIG_BLK_DEV_IDE_MODES is not set -# CONFIG_BLK_DEV_HD is not set - -# -# SCSI support -# -CONFIG_SCSI=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=y -CONFIG_SD_EXTRA_DEVS=40 -# CONFIG_CHR_DEV_ST is not set -# CONFIG_CHR_DEV_OSST is not set -# CONFIG_BLK_DEV_SR is not set -# CONFIG_CHR_DEV_SG is not set - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -# CONFIG_SCSI_DEBUG_QUEUES is not set -# CONFIG_SCSI_MULTI_LUN is not set -# CONFIG_SCSI_CONSTANTS is not set -# CONFIG_SCSI_LOGGING is not set - -# -# SCSI low-level drivers -# -# CONFIG_BLK_DEV_3W_XXXX_RAID is not set -# CONFIG_SCSI_7000FASST is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AHA152X is not set -# CONFIG_SCSI_AHA1542 is not set -# CONFIG_SCSI_AHA1740 is not set -# CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_AM53C974 is not set -# CONFIG_SCSI_MEGARAID is not set -# CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_CPQFCTS is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_DTC3280 is not set -# CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_DMA is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -# CONFIG_SCSI_GDTH is not set -# CONFIG_SCSI_GENERIC_NCR5380 is not set -# CONFIG_SCSI_INITIO is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_NCR_D700 is not set -# CONFIG_SCSI_NCR53C7xx is not set -# CONFIG_SCSI_NCR53C8XX is not set -# CONFIG_SCSI_SYM53C8XX is not set -# CONFIG_SCSI_PAS16 is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set -# CONFIG_SCSI_PSI240I is not set -# CONFIG_SCSI_QLOGIC_FAS is not set -# CONFIG_SCSI_QLOGIC_ISP is not set -# CONFIG_SCSI_QLOGIC_FC is not set -# CONFIG_SCSI_QLOGIC_1280 is not set -# CONFIG_SCSI_SIM710 is not set -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set -# CONFIG_SCSI_DEBUG is not set - -# -# Network device support +# Network testing # +# CONFIG_NET_PKTGEN is not set CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y -# CONFIG_SUNLANCE is not set -# CONFIG_HAPPYMEAL is not set -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set -# CONFIG_SUNLANCE is not set -# CONFIG_SUNGEM is not set -# CONFIG_NET_VENDOR_3COM is not set -# CONFIG_LANCE is not set -# CONFIG_NET_VENDOR_SMC is not set -# CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_HP100 is not set -# CONFIG_NET_ISA is not set -CONFIG_NET_PCI=y -CONFIG_PCNET32=y -# CONFIG_ADAPTEC_STARFIRE is not set -# CONFIG_APRICOT is not set -# CONFIG_CS89x0 is not set -# CONFIG_TULIP is not set -# CONFIG_DE4X5 is not set -# CONFIG_DGRS is not set -# CONFIG_DM9102 is not set -# CONFIG_EEPRO100 is not set -# CONFIG_LNE390 is not set -# CONFIG_FEALNX is not set -# CONFIG_NATSEMI is not set -# CONFIG_NE2K_PCI is not set -# CONFIG_NE3210 is not set -# CONFIG_ES3210 is not set -# CONFIG_8139TOO is not set -# CONFIG_8139TOO_PIO is not set -# CONFIG_8139TOO_TUNE_TWISTER is not set -# CONFIG_8139TOO_8129 is not set -# CONFIG_SIS900 is not set -# CONFIG_EPIC100 is not set -# CONFIG_SUNDANCE is not set -# CONFIG_TLAN is not set -# CONFIG_VIA_RHINE is not set -# CONFIG_WINBOND_840 is not set -# CONFIG_LAN_SAA9730 is not set -# CONFIG_NET_POCKET is not set +# CONFIG_MII is not set # # Ethernet (1000 Mbit) # -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_MYRI_SBUS is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_SK98LIN is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PLIP is not set + +# +# Ethernet (10000 Mbit) +# # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -333,11 +293,8 @@ # CONFIG_NET_RADIO is not set # -# Token Ring devices +# Token Ring devices (depends on LLC=y) # -# CONFIG_TR is not set -# CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set # CONFIG_SHAPER is not set # @@ -358,21 +315,64 @@ # # ISDN subsystem # -# CONFIG_ISDN is not set +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set # -# Old CD-ROM drivers (not SCSI, not IDE) +# Input Device Drivers # -# CONFIG_CD_NO_IDESCSI is not set +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set # # Character devices # # CONFIG_VT is not set -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y -# CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_UNIX98_PTY_COUNT=256 @@ -382,36 +382,34 @@ # CONFIG_I2C is not set # -# Mice +# I2C Hardware Sensors Mainboard support # -# CONFIG_BUSMOUSE is not set -# CONFIG_MOUSE is not set # -# Joysticks +# I2C Hardware Sensors Chip support # -# CONFIG_INPUT_GAMEPORT is not set +# CONFIG_I2C_SENSOR is not set # -# Input core support is needed for gameports +# Mice # +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set # -# Input core support is needed for joysticks +# IPMI # -# CONFIG_QIC02_TAPE is not set +# CONFIG_IPMI_HANDLER is not set # # Watchdog Cards # # CONFIG_WATCHDOG is not set -# CONFIG_INTEL_RNG is not set # CONFIG_NVRAM is not set CONFIG_RTC=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set -# CONFIG_SONYPI is not set # # Ftape, the floppy tape device driver @@ -419,6 +417,8 @@ # CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HANGCHECK_TIMER is not set # # Multimedia devices @@ -426,206 +426,130 @@ # CONFIG_VIDEO_DEV is not set # +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# # File systems # +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set CONFIG_AUTOFS_FS=y # CONFIG_AUTOFS4_FS is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# # CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set -# CONFIG_CMS_FS is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_JBD_DEBUG is not set -# CONFIG_FAT_FS is not set -# CONFIG_MSDOS_FS is not set -# CONFIG_UMSDOS_FS is not set -# CONFIG_VFAT_FS is not set CONFIG_EFS_FS=y -# CONFIG_JFFS_FS is not set -# CONFIG_JFFS2_FS is not set # CONFIG_CRAMFS is not set -# CONFIG_TMPFS is not set -# CONFIG_RAMFS is not set -# CONFIG_ISO9660_FS is not set -# CONFIG_JOLIET is not set -# CONFIG_MINIX_FS is not set -# CONFIG_FREEVXFS_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_DEBUG is not set -# CONFIG_NTFS_RW is not set +# CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set # # Network File Systems # -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set +CONFIG_NFS_V3=y +# CONFIG_NFS_V4 is not set +CONFIG_NFSD=y +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V4 is not set +# CONFIG_NFSD_TCP is not set CONFIG_ROOT_NFS=y -# CONFIG_NFSD is not set -# CONFIG_NFSD_V3 is not set -CONFIG_SUNRPC=y CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=y +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set # CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set # CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set # # Partition Types # # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y -# CONFIG_SMB_NLS is not set -# CONFIG_NLS is not set # -# Sound +# Graphics support # -# CONFIG_SOUND is not set # -# USB support -# -# CONFIG_USB is not set - -# -# USB Controllers -# -# CONFIG_USB_UHCI is not set -# CONFIG_USB_UHCI_ALT is not set -# CONFIG_USB_OHCI is not set - -# -# USB Device Class drivers -# -# CONFIG_USB_AUDIO is not set -# CONFIG_USB_BLUETOOTH is not set -# CONFIG_USB_STORAGE is not set -# CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set -# CONFIG_USB_STORAGE_DPCM is not set -# CONFIG_USB_STORAGE_SDDR09 is not set -# CONFIG_USB_ACM is not set -# CONFIG_USB_PRINTER is not set - -# -# USB Human Interface Devices (HID) -# - -# -# Input core support is needed for USB HID -# - -# -# USB Imaging devices -# -# CONFIG_USB_DC2XX is not set -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_SCANNER is not set -# CONFIG_USB_MICROTEK is not set -# CONFIG_USB_HPUSBSCSI is not set - -# -# USB Multimedia devices -# - -# -# Video4Linux support is needed for USB Multimedia device support +# Sound # -# CONFIG_USB_DABUSB is not set +# CONFIG_SOUND is not set # -# USB Network adaptors +# USB support # -# CONFIG_USB_PLUSB is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_CATC is not set -# CONFIG_USB_CDCETHER is not set -# CONFIG_USB_USBNET is not set +# CONFIG_USB_GADGET is not set # -# USB port drivers +# Bluetooth support # -# CONFIG_USB_USS720 is not set +# CONFIG_BT is not set # -# USB Serial Converter support +# Kernel hacking # -# CONFIG_USB_SERIAL is not set -# CONFIG_USB_SERIAL_GENERIC is not set -# CONFIG_USB_SERIAL_BELKIN is not set -# CONFIG_USB_SERIAL_WHITEHEAT is not set -# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set -# CONFIG_USB_SERIAL_EMPEG is not set -# CONFIG_USB_SERIAL_FTDI_SIO is not set -# CONFIG_USB_SERIAL_VISOR is not set -# CONFIG_USB_SERIAL_EDGEPORT is not set -# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set -# CONFIG_USB_SERIAL_KEYSPAN is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set -# CONFIG_USB_SERIAL_MCT_U232 is not set -# CONFIG_USB_SERIAL_PL2303 is not set -# CONFIG_USB_SERIAL_CYBERJACK is not set -# CONFIG_USB_SERIAL_OMNINET is not set +CONFIG_CROSSCOMPILE=y +# CONFIG_DEBUG_KERNEL is not set # -# Miscellaneous USB drivers +# Security options # -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_ID75 is not set +# CONFIG_SECURITY is not set # -# Input core support +# Cryptographic options # -# CONFIG_INPUT is not set -# CONFIG_INPUT_KEYBDEV is not set -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_EVDEV is not set +# CONFIG_CRYPTO is not set # -# Kernel hacking +# Library routines # -CONFIG_CROSSCOMPILE=y -# CONFIG_REMOTE_DEBUG is not set -# CONFIG_GDB_CONSOLE is not set -# CONFIG_LL_DEBUG is not set -# CONFIG_MAGIC_SYSRQ is not set -# CONFIG_MIPS_UNCACHED is not set +# CONFIG_CRC32 is not set diff -Nru a/arch/mips/defconfig-mpc30x b/arch/mips/defconfig-mpc30x --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/defconfig-mpc30x Tue Jul 1 18:44:40 2003 @@ -0,0 +1,543 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +CONFIG_MIPS32=y +# CONFIG_MIPS64 is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_EMBEDDED is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_ACER_PICA_61 is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_CASIO_E55 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_IBM_WORKPAD is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_NEC_EAGLE is not set +# CONFIG_OLIVETTI_M700 is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TANBAC_TB0226 is not set +# CONFIG_TANBAC_TB0229 is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +CONFIG_VICTOR_MPC30X=y +# CONFIG_ZAO_CAPCELLA is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_NONCOHERENT_IO=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_VR41XX_TIME_C=y +CONFIG_DUMMY_KEYB=y +CONFIG_VR41XX_COMMON=y +CONFIG_VRC4173=y +CONFIG_NEW_PCI=y +# CONFIG_FB is not set + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +CONFIG_CPU_VR41XX=y +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_SB1 is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +CONFIG_KALLSYMS=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +# CONFIG_PCI is not set +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_KCORE_ELF=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# I2O device support +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_NETLINK_DEV=y +# CONFIG_NETFILTER is not set +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices (depends on LLC=y) +# +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +# CONFIG_SERIO is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +# CONFIG_VT_CONSOLE is not set +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# I2C Hardware Sensors Mainboard support +# + +# +# I2C Hardware Sensors Chip support +# +# CONFIG_I2C_SENSOR is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HANGCHECK_TIMER is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=y +CONFIG_AUTOFS4_FS=y + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB_GADGET is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=y +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +CONFIG_CRYPTO_SHA512=y +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_BLOWFISH is not set +CONFIG_CRYPTO_TWOFISH=y +# CONFIG_CRYPTO_SERPENT is not set +CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_TEST is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff -Nru a/arch/mips/defconfig-nino b/arch/mips/defconfig-nino --- a/arch/mips/defconfig-nino Tue Jul 1 18:44:36 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,416 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_MIPS=y -# CONFIG_SMP is not set - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# Machine selection -# -# CONFIG_ACER_PICA_61 is not set -# CONFIG_ALGOR_P4032 is not set -# CONFIG_BAGET_MIPS is not set -# CONFIG_DECSTATION is not set -# CONFIG_DDB5074 is not set -# CONFIG_MIPS_EV96100 is not set -# CONFIG_MIPS_EV64120 is not set -# CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MALTA is not set -CONFIG_NINO=y -# CONFIG_NINO_4MB is not set -CONFIG_NINO_8MB=y -# CONFIG_NINO_16MB is not set -# CONFIG_MIPS_MAGNUM_4000 is not set -# CONFIG_MOMENCO_OCELOT is not set -# CONFIG_DDB5476 is not set -# CONFIG_DDB5477 is not set -# CONFIG_OLIVETTI_M700 is not set -# CONFIG_SGI_IP22 is not set -# CONFIG_SNI_RM200_PCI is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_IVR is not set -# CONFIG_MIPS_PB1000 is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set -# CONFIG_MCA is not set -# CONFIG_SBUS is not set -CONFIG_PC_KEYB=y -# CONFIG_ISA is not set -# CONFIG_EISA is not set -# CONFIG_PCI is not set -# CONFIG_I8259 is not set - -# -# Loadable module support -# -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y - -# -# CPU selection -# -CONFIG_CPU_R3000=y -# CONFIG_CPU_R6000 is not set -# CONFIG_CPU_VR41XX is not set -# CONFIG_CPU_R4300 is not set -# CONFIG_CPU_R4X00 is not set -# CONFIG_CPU_R5000 is not set -# CONFIG_CPU_R5432 is not set -# CONFIG_CPU_RM7000 is not set -# CONFIG_CPU_NEVADA is not set -# CONFIG_CPU_R10000 is not set -# CONFIG_CPU_SB1 is not set -# CONFIG_CPU_MIPS32 is not set -# CONFIG_CPU_MIPS64 is not set -# CONFIG_CPU_ADVANCED is not set -# CONFIG_CPU_HAS_LLSC is not set -# CONFIG_CPU_HAS_LLDSCD is not set -# CONFIG_CPU_HAS_WB is not set - -# -# General setup -# -CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_KCORE_ELF=y -CONFIG_ELF_KERNEL=y -# CONFIG_BINFMT_AOUT is not set -CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_MISC=y -# CONFIG_NET is not set -# CONFIG_HOTPLUG is not set -# CONFIG_PCMCIA is not set -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -# CONFIG_SYSCTL is not set - -# -# Memory Technology Devices (MTD) -# -# CONFIG_MTD is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_SIZE=2048 -CONFIG_BLK_DEV_INITRD=y - -# -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_BLK_DEV_LVM is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set -# CONFIG_PHONE_IXJ is not set -# CONFIG_PHONE_IXJ_PCMCIA is not set - -# -# ATA/IDE/MFM/RLL support -# -# CONFIG_IDE is not set -# CONFIG_BLK_DEV_IDE_MODES is not set -# CONFIG_BLK_DEV_HD is not set - -# -# SCSI support -# -# CONFIG_SCSI is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# ISDN subsystem -# - -# -# Old CD-ROM drivers (not SCSI, not IDE) -# -# CONFIG_CD_NO_IDESCSI is not set - -# -# Character devices -# -# CONFIG_VT is not set -# CONFIG_SERIAL is not set -# CONFIG_SERIAL_EXTENDED is not set -CONFIG_SERIAL_NONSTANDARD=y -# CONFIG_COMPUTONE is not set -# CONFIG_ROCKETPORT is not set -# CONFIG_CYCLADES is not set -# CONFIG_DIGIEPCA is not set -# CONFIG_DIGI is not set -# CONFIG_ESPSERIAL is not set -# CONFIG_MOXA_INTELLIO is not set -# CONFIG_MOXA_SMARTIO is not set -# CONFIG_ISI is not set -# CONFIG_SYNCLINK is not set -# CONFIG_N_HDLC is not set -# CONFIG_RISCOM8 is not set -# CONFIG_SPECIALIX is not set -# CONFIG_SX is not set -# CONFIG_RIO is not set -# CONFIG_STALDRV is not set -CONFIG_SERIAL_TX3912=y -CONFIG_SERIAL_TX3912_CONSOLE=y -# CONFIG_AU1000_UART is not set -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_MOUSE is not set - -# -# Joysticks -# -# CONFIG_INPUT_GAMEPORT is not set - -# -# Input core support is needed for gameports -# - -# -# Input core support is needed for joysticks -# -# CONFIG_QIC02_TAPE is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_INTEL_RNG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set -# CONFIG_SONYPI is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set -# CONFIG_AGP is not set -# CONFIG_DRM is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# File systems -# -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set -# CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_CMS_FS is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_JBD_DEBUG is not set -# CONFIG_FAT_FS is not set -# CONFIG_MSDOS_FS is not set -# CONFIG_UMSDOS_FS is not set -# CONFIG_VFAT_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -# CONFIG_JFFS2_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_TMPFS is not set -# CONFIG_RAMFS is not set -# CONFIG_ISO9660_FS is not set -# CONFIG_JOLIET is not set -# CONFIG_MINIX_FS is not set -# CONFIG_FREEVXFS_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_DEBUG is not set -# CONFIG_NTFS_RW is not set -# CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y -# CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=y -# CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set -# CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_SMB_FS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y -# CONFIG_SMB_NLS is not set -# CONFIG_NLS is not set - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support -# -# CONFIG_USB is not set - -# -# USB Controllers -# -# CONFIG_USB_UHCI is not set -# CONFIG_USB_UHCI_ALT is not set -# CONFIG_USB_OHCI is not set - -# -# USB Device Class drivers -# -# CONFIG_USB_AUDIO is not set -# CONFIG_USB_BLUETOOTH is not set -# CONFIG_USB_STORAGE is not set -# CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set -# CONFIG_USB_STORAGE_DPCM is not set -# CONFIG_USB_STORAGE_SDDR09 is not set -# CONFIG_USB_ACM is not set -# CONFIG_USB_PRINTER is not set - -# -# USB Human Interface Devices (HID) -# - -# -# Input core support is needed for USB HID -# - -# -# USB Imaging devices -# -# CONFIG_USB_DC2XX is not set -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_SCANNER is not set -# CONFIG_USB_MICROTEK is not set -# CONFIG_USB_HPUSBSCSI is not set - -# -# USB Multimedia devices -# - -# -# Video4Linux support is needed for USB Multimedia device support -# -# CONFIG_USB_DABUSB is not set - -# -# USB Network adaptors -# - -# -# Networking support is needed for USB Networking device support -# - -# -# USB port drivers -# -# CONFIG_USB_USS720 is not set - -# -# USB Serial Converter support -# -# CONFIG_USB_SERIAL is not set -# CONFIG_USB_SERIAL_GENERIC is not set -# CONFIG_USB_SERIAL_BELKIN is not set -# CONFIG_USB_SERIAL_WHITEHEAT is not set -# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set -# CONFIG_USB_SERIAL_EMPEG is not set -# CONFIG_USB_SERIAL_FTDI_SIO is not set -# CONFIG_USB_SERIAL_VISOR is not set -# CONFIG_USB_SERIAL_EDGEPORT is not set -# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set -# CONFIG_USB_SERIAL_KEYSPAN is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set -# CONFIG_USB_SERIAL_MCT_U232 is not set -# CONFIG_USB_SERIAL_PL2303 is not set -# CONFIG_USB_SERIAL_CYBERJACK is not set -# CONFIG_USB_SERIAL_OMNINET is not set - -# -# Miscellaneous USB drivers -# -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_ID75 is not set - -# -# Input core support -# -# CONFIG_INPUT is not set -# CONFIG_INPUT_KEYBDEV is not set -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_EVDEV is not set - -# -# Kernel hacking -# -CONFIG_CROSSCOMPILE=y -# CONFIG_MAGIC_SYSRQ is not set -# CONFIG_MIPS_UNCACHED is not set diff -Nru a/arch/mips/defconfig-pb1000 b/arch/mips/defconfig-pb1000 --- a/arch/mips/defconfig-pb1000 Tue Jul 1 18:44:34 2003 +++ b/arch/mips/defconfig-pb1000 Tue Jul 1 18:44:34 2003 @@ -2,7 +2,8 @@ # Automatically generated make config: don't edit # CONFIG_MIPS=y -# CONFIG_SMP is not set +CONFIG_MIPS32=y +# CONFIG_MIPS64 is not set # # Code maturity level options @@ -10,85 +11,183 @@ CONFIG_EXPERIMENTAL=y # +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_EMBEDDED is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# # Machine selection # # CONFIG_ACER_PICA_61 is not set -# CONFIG_ALGOR_P4032 is not set # CONFIG_BAGET_MIPS is not set +# CONFIG_CASIO_E55 is not set +# CONFIG_MIPS_COBALT is not set # CONFIG_DECSTATION is not set -# CONFIG_DDB5074 is not set -# CONFIG_MIPS_EV96100 is not set # CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_IBM_WORKPAD is not set +# CONFIG_MIPS_ITE8172 is not set # CONFIG_MIPS_ATLAS is not set -# CONFIG_MIPS_MALTA is not set -# CONFIG_NINO is not set # CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set # CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_DDB5074 is not set # CONFIG_DDB5476 is not set # CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_NEC_EAGLE is not set # CONFIG_OLIVETTI_M700 is not set # CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set # CONFIG_SNI_RM200_PCI is not set -# CONFIG_MIPS_ITE8172 is not set -# CONFIG_MIPS_IVR is not set -CONFIG_MIPS_PB1000=y +# CONFIG_TANBAC_TB0226 is not set +# CONFIG_TANBAC_TB0229 is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +# CONFIG_VICTOR_MPC30X is not set +# CONFIG_ZAO_CAPCELLA is not set CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set -# CONFIG_MCA is not set -# CONFIG_SBUS is not set -CONFIG_MIPS_AU1000=y -CONFIG_NEW_IRQ=y -# CONFIG_ISA is not set -# CONFIG_EISA is not set -# CONFIG_PCI is not set -# CONFIG_I8259 is not set - -# -# Loadable module support -# -# CONFIG_MODULES is not set +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_FB=y # # CPU selection # +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS64 is not set # CONFIG_CPU_R3000 is not set -# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_TX39XX is not set # CONFIG_CPU_VR41XX is not set # CONFIG_CPU_R4300 is not set # CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set # CONFIG_CPU_R5000 is not set # CONFIG_CPU_R5432 is not set -# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_R6000 is not set # CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set # CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set # CONFIG_CPU_SB1 is not set -CONFIG_CPU_MIPS32=y -# CONFIG_CPU_MIPS64 is not set +CONFIG_CPU_HAS_PREFETCH=y +# CONFIG_VTAG_ICACHE is not set +CONFIG_64BIT_PHYS_ADDR=y CONFIG_CPU_ADVANCED=y CONFIG_CPU_HAS_LLSC=y # CONFIG_CPU_HAS_LLDSCD is not set CONFIG_CPU_HAS_WB=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +CONFIG_KALLSYMS=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # -# General setup +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_MMU=y +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=m +# CONFIG_TCIC is not set + +# +# PCI Hotplug Support +# + +# +# Executable file formats # -CONFIG_CPU_LITTLE_ENDIAN=y CONFIG_KCORE_ELF=y -CONFIG_ELF_KERNEL=y -# CONFIG_BINFMT_AOUT is not set CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set -CONFIG_NET=y -# CONFIG_HOTPLUG is not set -# CONFIG_PCMCIA is not set -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y # # Memory Technology Devices (MTD) # -# CONFIG_MTD is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_CONCAT is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +# CONFIG_MTD_CFI_INTELEXT is not set +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_STAA is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_UCLINUX is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set # # Parallel port support @@ -96,39 +195,83 @@ # CONFIG_PARPORT is not set # +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# # Block devices # # CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_RAM is not set # CONFIG_BLK_DEV_INITRD is not set # +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y + +# +# IDE, ATA and ATAPI Block devices +# +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_IDEDISK_STROKE is not set +CONFIG_BLK_DEV_IDECS=m +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_IDE_TASK_IOCTL is not set +CONFIG_IDE_TASKFILE_IO=y + +# +# IDE chipset support/bugfixes +# + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# # Multi-device support (RAID and LVM) # # CONFIG_MD is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_BLK_DEV_LVM is not set + +# +# Fusion MPT device support +# + +# +# I2O device support +# + +# +# Networking support +# +CONFIG_NET=y # # Networking options # CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set -# CONFIG_NETLINK is not set +# CONFIG_NETLINK_DEV is not set # CONFIG_NETFILTER is not set -# CONFIG_FILTER is not set CONFIG_UNIX=y +CONFIG_NET_KEY=y CONFIG_INET=y # CONFIG_IP_MULTICAST is not set # CONFIG_IP_ADVANCED_ROUTER is not set @@ -138,22 +281,27 @@ # CONFIG_IP_PNP_RARP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set # CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_KHTTPD is not set -# CONFIG_ATM is not set +# CONFIG_XFRM_USER is not set # -# +# SCTP Configuration (EXPERIMENTAL) # -# CONFIG_IPX is not set -# CONFIG_ATALK is not set +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC is not set # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_LLC is not set # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -166,69 +314,29 @@ # CONFIG_NET_SCHED is not set # -# Telephony Support -# -# CONFIG_PHONE is not set -# CONFIG_PHONE_IXJ is not set -# CONFIG_PHONE_IXJ_PCMCIA is not set - -# -# ATA/IDE/MFM/RLL support -# -# CONFIG_IDE is not set -# CONFIG_BLK_DEV_IDE_MODES is not set -# CONFIG_BLK_DEV_HD is not set - -# -# SCSI support -# -# CONFIG_SCSI is not set - -# -# Network device support +# Network testing # +# CONFIG_NET_PKTGEN is not set CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y -CONFIG_MIPS_AU1000_ENET=y -# CONFIG_SUNLANCE is not set -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set -# CONFIG_SUNLANCE is not set -# CONFIG_SUNGEM is not set -# CONFIG_NET_VENDOR_3COM is not set -# CONFIG_LANCE is not set -# CONFIG_NET_VENDOR_SMC is not set -# CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_NET_ISA is not set -# CONFIG_NET_PCI is not set -# CONFIG_NET_POCKET is not set +# CONFIG_MII is not set # # Ethernet (1000 Mbit) # -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_MYRI_SBUS is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_SK98LIN is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PLIP is not set + +# +# Ethernet (10000 Mbit) +# # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -238,11 +346,8 @@ # CONFIG_NET_RADIO is not set # -# Token Ring devices +# Token Ring devices (depends on LLC=y) # -# CONFIG_TR is not set -# CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set # CONFIG_SHAPER is not set # @@ -251,6 +356,19 @@ # CONFIG_WAN is not set # +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +# CONFIG_PCMCIA_3C574 is not set +# CONFIG_PCMCIA_FMVJ18X is not set +# CONFIG_PCMCIA_PCNET is not set +# CONFIG_PCMCIA_NMCLAN is not set +# CONFIG_PCMCIA_SMC91C92 is not set +# CONFIG_PCMCIA_XIRC2PS is not set +# CONFIG_PCMCIA_AXNET is not set + +# # Amateur Radio support # # CONFIG_HAMRADIO is not set @@ -258,44 +376,131 @@ # # IrDA (infrared) support # -# CONFIG_IRDA is not set +CONFIG_IRDA=y + +# +# IrDA protocols +# +CONFIG_IRLAN=m +CONFIG_IRCOMM=m +# CONFIG_IRDA_ULTRA is not set + +# +# IrDA options +# +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +# CONFIG_IRTTY_SIR is not set + +# +# Dongle support +# +# CONFIG_DONGLE is not set + +# +# Old SIR device drivers +# +# CONFIG_IRTTY_OLD is not set +# CONFIG_IRPORT_SIR is not set + +# +# Old Serial dongle support +# +# CONFIG_DONGLE_OLD is not set + +# +# FIR device drivers +# +# CONFIG_NSC_FIR is not set +# CONFIG_WINBOND_FIR is not set +# CONFIG_TOSHIBA_OLD is not set +# CONFIG_TOSHIBA_FIR is not set +# CONFIG_SMC_IRCC_OLD is not set +# CONFIG_SMC_IRCC_FIR is not set +# CONFIG_ALI_FIR is not set +# CONFIG_VLSI_FIR is not set # # ISDN subsystem # -# CONFIG_ISDN is not set +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +# CONFIG_SERIO is not set # -# Old CD-ROM drivers (not SCSI, not IDE) +# Input Device Drivers # -# CONFIG_CD_NO_IDESCSI is not set +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set # # Character devices # -# CONFIG_VT is not set -# CONFIG_SERIAL is not set -# CONFIG_SERIAL_EXTENDED is not set +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y CONFIG_SERIAL_NONSTANDARD=y # CONFIG_COMPUTONE is not set # CONFIG_ROCKETPORT is not set # CONFIG_CYCLADES is not set # CONFIG_DIGIEPCA is not set # CONFIG_DIGI is not set -# CONFIG_ESPSERIAL is not set # CONFIG_MOXA_INTELLIO is not set # CONFIG_MOXA_SMARTIO is not set +# CONFIG_ISI is not set # CONFIG_SYNCLINK is not set +# CONFIG_SYNCLINKMP is not set # CONFIG_N_HDLC is not set # CONFIG_RISCOM8 is not set # CONFIG_SPECIALIX is not set # CONFIG_SX is not set # CONFIG_RIO is not set # CONFIG_STALDRV is not set -# CONFIG_SERIAL_TX3912 is not set -# CONFIG_SERIAL_TX3912_CONSOLE is not set -CONFIG_AU1000_UART=y -CONFIG_AU1000_SERIAL_CONSOLE=y + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# CONFIG_UNIX98_PTYS=y CONFIG_UNIX98_PTY_COUNT=256 @@ -305,36 +510,35 @@ # CONFIG_I2C is not set # -# Mice +# I2C Hardware Sensors Mainboard support # -# CONFIG_BUSMOUSE is not set -# CONFIG_MOUSE is not set # -# Joysticks +# I2C Hardware Sensors Chip support # -# CONFIG_INPUT_GAMEPORT is not set +# CONFIG_I2C_SENSOR is not set # -# Input core support is needed for gameports +# Mice # +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set # -# Input core support is needed for joysticks +# IPMI # -# CONFIG_QIC02_TAPE is not set +# CONFIG_IPMI_HANDLER is not set # # Watchdog Cards # # CONFIG_WATCHDOG is not set -# CONFIG_INTEL_RNG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set -# CONFIG_SONYPI is not set # # Ftape, the floppy tape device driver @@ -344,223 +548,168 @@ # CONFIG_DRM is not set # +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HANGCHECK_TIMER is not set + +# # Multimedia devices # # CONFIG_VIDEO_DEV is not set # +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# # File systems # +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set CONFIG_AUTOFS_FS=y CONFIG_AUTOFS4_FS=y -# CONFIG_REISERFS_FS is not set -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# # CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set -# CONFIG_CMS_FS is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_JBD_DEBUG is not set -# CONFIG_FAT_FS is not set -# CONFIG_MSDOS_FS is not set -# CONFIG_UMSDOS_FS is not set -# CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set # CONFIG_JFFS_FS is not set -# CONFIG_JFFS2_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +# CONFIG_JFFS2_FS_NAND is not set # CONFIG_CRAMFS is not set -# CONFIG_TMPFS is not set -# CONFIG_RAMFS is not set -CONFIG_ISO9660_FS=y -# CONFIG_JOLIET is not set -# CONFIG_MINIX_FS is not set -# CONFIG_FREEVXFS_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_DEBUG is not set -# CONFIG_NTFS_RW is not set +# CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -# CONFIG_DEVPTS_FS is not set # CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set # # Network File Systems # -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=y # CONFIG_NFS_V3 is not set -CONFIG_ROOT_NFS=y +# CONFIG_NFS_V4 is not set # CONFIG_NFSD is not set -# CONFIG_NFSD_V3 is not set -CONFIG_SUNRPC=y +CONFIG_ROOT_NFS=y CONFIG_LOCKD=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set # CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set # CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set # # Partition Types # -CONFIG_PARTITION_ADVANCED=y -# CONFIG_ACORN_PARTITION is not set -# CONFIG_OSF_PARTITION is not set -# CONFIG_AMIGA_PARTITION is not set -# CONFIG_ATARI_PARTITION is not set -# CONFIG_MAC_PARTITION is not set +# CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y -# CONFIG_BSD_DISKLABEL is not set -# CONFIG_MINIX_SUBPARTITION is not set -# CONFIG_SOLARIS_X86_PARTITION is not set -# CONFIG_UNIXWARE_DISKLABEL is not set -# CONFIG_LDM_PARTITION is not set -CONFIG_SGI_PARTITION=y -# CONFIG_ULTRIX_PARTITION is not set -# CONFIG_SUN_PARTITION is not set -# CONFIG_SMB_NLS is not set -# CONFIG_NLS is not set - -# -# Sound -# -# CONFIG_SOUND is not set # -# USB support +# Graphics support # -# CONFIG_USB is not set +# CONFIG_FB_VIRTUAL is not set # -# USB Controllers +# Console display driver support # -# CONFIG_USB_UHCI is not set -# CONFIG_USB_UHCI_ALT is not set -# CONFIG_USB_OHCI is not set +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE is not set # -# USB Device Class drivers +# Logo configuration # -# CONFIG_USB_AUDIO is not set -# CONFIG_USB_BLUETOOTH is not set -# CONFIG_USB_STORAGE is not set -# CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set -# CONFIG_USB_STORAGE_DPCM is not set -# CONFIG_USB_STORAGE_SDDR09 is not set -# CONFIG_USB_ACM is not set -# CONFIG_USB_PRINTER is not set +# CONFIG_LOGO is not set # -# USB Human Interface Devices (HID) -# - -# -# Input core support is needed for USB HID -# - -# -# USB Imaging devices +# Sound # -# CONFIG_USB_DC2XX is not set -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_SCANNER is not set -# CONFIG_USB_MICROTEK is not set -# CONFIG_USB_HPUSBSCSI is not set +CONFIG_SOUND=y # -# USB Multimedia devices +# Advanced Linux Sound Architecture # +# CONFIG_SND is not set # -# Video4Linux support is needed for USB Multimedia device support +# Open Sound System # -# CONFIG_USB_DABUSB is not set +# CONFIG_SOUND_PRIME is not set # -# USB Network adaptors +# USB support # -# CONFIG_USB_PLUSB is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_CATC is not set -# CONFIG_USB_CDCETHER is not set -# CONFIG_USB_USBNET is not set +# CONFIG_USB_GADGET is not set # -# USB port drivers +# Bluetooth support # -# CONFIG_USB_USS720 is not set +# CONFIG_BT is not set # -# USB Serial Converter support +# Kernel hacking # -# CONFIG_USB_SERIAL is not set -# CONFIG_USB_SERIAL_GENERIC is not set -# CONFIG_USB_SERIAL_BELKIN is not set -# CONFIG_USB_SERIAL_WHITEHEAT is not set -# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set -# CONFIG_USB_SERIAL_EMPEG is not set -# CONFIG_USB_SERIAL_FTDI_SIO is not set -# CONFIG_USB_SERIAL_VISOR is not set -# CONFIG_USB_SERIAL_EDGEPORT is not set -# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set -# CONFIG_USB_SERIAL_KEYSPAN is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set -# CONFIG_USB_SERIAL_MCT_U232 is not set -# CONFIG_USB_SERIAL_PL2303 is not set -# CONFIG_USB_SERIAL_CYBERJACK is not set -# CONFIG_USB_SERIAL_OMNINET is not set +CONFIG_CROSSCOMPILE=y +# CONFIG_DEBUG_KERNEL is not set # -# Miscellaneous USB drivers +# Security options # -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_ID75 is not set +# CONFIG_SECURITY is not set # -# Input core support +# Cryptographic options # -# CONFIG_INPUT is not set -# CONFIG_INPUT_KEYBDEV is not set -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_EVDEV is not set +# CONFIG_CRYPTO is not set # -# Kernel hacking +# Library routines # -CONFIG_CROSSCOMPILE=y -# CONFIG_REMOTE_DEBUG is not set -# CONFIG_GDB_CONSOLE is not set -# CONFIG_MAGIC_SYSRQ is not set -# CONFIG_MIPS_UNCACHED is not set +# CONFIG_CRC32 is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff -Nru a/arch/mips/defconfig-pb1100 b/arch/mips/defconfig-pb1100 --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/defconfig-pb1100 Tue Jul 1 18:44:40 2003 @@ -0,0 +1,789 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +CONFIG_MIPS32=y +# CONFIG_MIPS64 is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_EMBEDDED is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_ACER_PICA_61 is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_CASIO_E55 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_IBM_WORKPAD is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_NEC_EAGLE is not set +# CONFIG_OLIVETTI_M700 is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TANBAC_TB0226 is not set +# CONFIG_TANBAC_TB0229 is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +# CONFIG_VICTOR_MPC30X is not set +# CONFIG_ZAO_CAPCELLA is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_FB=y + +# +# CPU selection +# +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_CPU_HAS_PREFETCH=y +# CONFIG_VTAG_ICACHE is not set +CONFIG_64BIT_PHYS_ADDR=y +CONFIG_CPU_ADVANCED=y +CONFIG_CPU_HAS_LLSC=y +# CONFIG_CPU_HAS_LLDSCD is not set +CONFIG_CPU_HAS_WB=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +CONFIG_KALLSYMS=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_MMU=y +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=m +# CONFIG_TCIC is not set + +# +# PCI Hotplug Support +# + +# +# Executable file formats +# +CONFIG_KCORE_ELF=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_CONCAT is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_CMDLINE_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set + +# +# RAM/ROM/Flash chip drivers +# +CONFIG_MTD_CFI=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_CFI_STAA is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set +# CONFIG_MTD_OBSOLETE_CHIPS is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_UCLINUX is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLKMTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set + +# +# NAND Flash Device Drivers +# +# CONFIG_MTD_NAND is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y + +# +# IDE, ATA and ATAPI Block devices +# +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_IDEDISK_STROKE is not set +CONFIG_BLK_DEV_IDECS=m +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_IDE_TASK_IOCTL is not set +CONFIG_IDE_TASKFILE_IO=y + +# +# IDE chipset support/bugfixes +# + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# I2O device support +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +# CONFIG_NETLINK_DEV is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_IP_NF_CONNTRACK is not set +# CONFIG_IP_NF_QUEUE is not set +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_NF_ARPTABLES is not set +# CONFIG_IP_NF_COMPAT_IPCHAINS is not set +# CONFIG_IP_NF_COMPAT_IPFWADM is not set +# CONFIG_IPV6 is not set +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPPOE=m +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices (depends on LLC=y) +# +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +# CONFIG_PCMCIA_3C574 is not set +# CONFIG_PCMCIA_FMVJ18X is not set +# CONFIG_PCMCIA_PCNET is not set +# CONFIG_PCMCIA_NMCLAN is not set +# CONFIG_PCMCIA_SMC91C92 is not set +# CONFIG_PCMCIA_XIRC2PS is not set +# CONFIG_PCMCIA_AXNET is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +CONFIG_IRDA=y + +# +# IrDA protocols +# +CONFIG_IRLAN=m +# CONFIG_IRNET is not set +CONFIG_IRCOMM=m +# CONFIG_IRDA_ULTRA is not set + +# +# IrDA options +# +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +# CONFIG_IRDA_DEBUG is not set + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +# CONFIG_IRTTY_SIR is not set + +# +# Dongle support +# +# CONFIG_DONGLE is not set + +# +# Old SIR device drivers +# +# CONFIG_IRTTY_OLD is not set +# CONFIG_IRPORT_SIR is not set + +# +# Old Serial dongle support +# +# CONFIG_DONGLE_OLD is not set + +# +# FIR device drivers +# +# CONFIG_NSC_FIR is not set +# CONFIG_WINBOND_FIR is not set +# CONFIG_TOSHIBA_OLD is not set +# CONFIG_TOSHIBA_FIR is not set +# CONFIG_SMC_IRCC_OLD is not set +# CONFIG_SMC_IRCC_FIR is not set +# CONFIG_ALI_FIR is not set +# CONFIG_VLSI_FIR is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +# CONFIG_SERIO is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_COMPUTONE is not set +# CONFIG_ROCKETPORT is not set +# CONFIG_CYCLADES is not set +# CONFIG_DIGIEPCA is not set +# CONFIG_DIGI is not set +# CONFIG_MOXA_INTELLIO is not set +# CONFIG_MOXA_SMARTIO is not set +# CONFIG_ISI is not set +# CONFIG_SYNCLINK is not set +# CONFIG_SYNCLINKMP is not set +# CONFIG_N_HDLC is not set +# CONFIG_RISCOM8 is not set +# CONFIG_SPECIALIX is not set +# CONFIG_SX is not set +# CONFIG_RIO is not set +# CONFIG_STALDRV is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# I2C Hardware Sensors Mainboard support +# + +# +# I2C Hardware Sensors Chip support +# +# CONFIG_I2C_SENSOR is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +CONFIG_RTC=y +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HANGCHECK_TIMER is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +CONFIG_TMPFS=y +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS_FS=m +CONFIG_JFFS_FS_VERBOSE=0 +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_FS_DEBUG=0 +# CONFIG_JFFS2_FS_NAND is not set +CONFIG_CRAMFS=m +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +CONFIG_NFSD=m +# CONFIG_NFSD_V3 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_EXPORTFS=m +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +CONFIG_SMB_FS=m +# CONFIG_SMB_NLS_DEFAULT is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +CONFIG_SMB_NLS=y +CONFIG_NLS=y + +# +# Native Language Support +# +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Graphics support +# +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE is not set + +# +# Logo configuration +# +# CONFIG_LOGO is not set + +# +# Sound +# +CONFIG_SOUND=y + +# +# Advanced Linux Sound Architecture +# +# CONFIG_SND is not set + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set + +# +# USB support +# +# CONFIG_USB_GADGET is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set +CONFIG_ZLIB_INFLATE=m +CONFIG_ZLIB_DEFLATE=m diff -Nru a/arch/mips/defconfig-pb1500 b/arch/mips/defconfig-pb1500 --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/defconfig-pb1500 Tue Jul 1 18:44:40 2003 @@ -0,0 +1,664 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +CONFIG_MIPS32=y +# CONFIG_MIPS64 is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_EMBEDDED is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_ACER_PICA_61 is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_CASIO_E55 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_IBM_WORKPAD is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_NEC_EAGLE is not set +# CONFIG_OLIVETTI_M700 is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +CONFIG_SOC_AU1X00=y +# CONFIG_SOC_AU1000 is not set +# CONFIG_SOC_AU1100 is not set +CONFIG_SOC_AU1500=y +# CONFIG_MIPS_PB1000 is not set +# CONFIG_MIPS_PB1100 is not set +CONFIG_MIPS_PB1500=y +# CONFIG_MIPS_DB1000 is not set +# CONFIG_MIPS_DB1100 is not set +# CONFIG_MIPS_DB1500 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TANBAC_TB0226 is not set +# CONFIG_TANBAC_TB0229 is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +# CONFIG_VICTOR_MPC30X is not set +# CONFIG_ZAO_CAPCELLA is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_NONCOHERENT_IO=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_NEW_PCI=y +# CONFIG_AU1000_USB_DEVICE is not set +# CONFIG_FB is not set + +# +# CPU selection +# +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_CPU_HAS_PREFETCH=y +# CONFIG_VTAG_ICACHE is not set +# CONFIG_64BIT_PHYS_ADDR is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +CONFIG_KALLSYMS=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +# CONFIG_PCI is not set +CONFIG_MMU=y +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=m +# CONFIG_TCIC is not set + +# +# PCI Hotplug Support +# + +# +# Executable file formats +# +CONFIG_KCORE_ELF=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_PM is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# I2O device support +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=y +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set + +# +# IP: Netfilter Configuration +# +# CONFIG_IP_NF_CONNTRACK is not set +# CONFIG_IP_NF_QUEUE is not set +# CONFIG_IP_NF_IPTABLES is not set +# CONFIG_IP_NF_ARPTABLES is not set +# CONFIG_IP_NF_COMPAT_IPCHAINS is not set +# CONFIG_IP_NF_COMPAT_IPFWADM is not set +# CONFIG_IPV6 is not set +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +CONFIG_MIPS_AU1X00_ENET=y + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +# CONFIG_PPP_SYNC_TTY is not set +CONFIG_PPP_DEFLATE=m +# CONFIG_PPP_BSDCOMP is not set +CONFIG_PPPOE=m +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices (depends on LLC=y) +# +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +CONFIG_PCMCIA_3C589=m +# CONFIG_PCMCIA_3C574 is not set +# CONFIG_PCMCIA_FMVJ18X is not set +# CONFIG_PCMCIA_PCNET is not set +# CONFIG_PCMCIA_NMCLAN is not set +# CONFIG_PCMCIA_SMC91C92 is not set +# CONFIG_PCMCIA_XIRC2PS is not set +# CONFIG_PCMCIA_AXNET is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_AU1X00_GPIO is not set +# CONFIG_TS_AU1X00_ADS7846 is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_AU1X00=y +CONFIG_SERIAL_AU1X00_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# I2C Hardware Sensors Mainboard support +# + +# +# I2C Hardware Sensors Chip support +# +# CONFIG_I2C_SENSOR is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +CONFIG_RTC=y +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HANGCHECK_TIMER is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +# CONFIG_EXT2_FS_SECURITY is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=m +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=m +CONFIG_AUTOFS4_FS=m + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +CONFIG_TMPFS=y +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_CRAMFS=m +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +CONFIG_NFSD=m +# CONFIG_NFSD_V3 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_EXPORTFS=m +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +CONFIG_SMB_FS=m +# CONFIG_SMB_NLS_DEFAULT is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +CONFIG_SMB_NLS=y +CONFIG_NLS=y + +# +# Native Language Support +# +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB_GADGET is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=y +# CONFIG_CRYPTO_MD4 is not set +# CONFIG_CRYPTO_MD5 is not set +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +CONFIG_CRYPTO_SHA512=y +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_BLOWFISH is not set +CONFIG_CRYPTO_TWOFISH=y +# CONFIG_CRYPTO_SERPENT is not set +CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_TEST is not set + +# +# Library routines +# +CONFIG_CRC32=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff -Nru a/arch/mips/defconfig-sb1250-swarm b/arch/mips/defconfig-sb1250-swarm --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/defconfig-sb1250-swarm Tue Jul 1 18:44:40 2003 @@ -0,0 +1,613 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +CONFIG_MIPS32=y +# CONFIG_MIPS64 is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=15 +# CONFIG_EMBEDDED is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_ACER_PICA_61 is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_CASIO_E55 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_IBM_WORKPAD is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_NEC_EAGLE is not set +# CONFIG_OLIVETTI_M700 is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +CONFIG_SIBYTE_SB1xxx_SOC=y +CONFIG_SIBYTE_SB1250=y +# CONFIG_SIMULATION is not set +CONFIG_SIBYTE_CFE=y +# CONFIG_SIBYTE_CFE_CONSOLE is not set +# CONFIG_SIBYTE_BUS_WATCHER is not set +# CONFIG_SIBYTE_SB1250_PROF is not set +# CONFIG_SIBYTE_TBPROF is not set +CONFIG_SIBYTE_SWARM=y +CONFIG_SIBYTE_BOARD=y +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TANBAC_TB0226 is not set +# CONFIG_TANBAC_TB0229 is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +# CONFIG_VICTOR_MPC30X is not set +# CONFIG_ZAO_CAPCELLA is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_DUMMY_KEYB=y +CONFIG_SWAP_IO_SPACE=y +CONFIG_BOOT_ELF32=y +# CONFIG_FB is not set + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +CONFIG_CPU_SB1=y +CONFIG_CPU_HAS_PREFETCH=y +CONFIG_VTAG_ICACHE=y +CONFIG_CPU_SB1_PASS_1=y +# CONFIG_CPU_SB1_PASS_2 is not set +# CONFIG_CPU_SB1_PASS_2_2 is not set +CONFIG_SB1_PASS_1_WORKAROUNDS=y +CONFIG_SB1_CACHE_ERROR=y +CONFIG_SB1_CERR_IGNORE_RECOVERABLE=y +# CONFIG_SB1_CERR_SPIN is not set +# CONFIG_64BIT_PHYS_ADDR is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_HIGHMEM is not set +CONFIG_SMP=y +CONFIG_NR_CPUS=2 +# CONFIG_PREEMPT is not set +CONFIG_KALLSYMS=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_KCORE_ELF=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_BINFMT_IRIX is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=9220 +# CONFIG_BLK_DEV_INITRD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_NETLINK_DEV=y +# CONFIG_NETFILTER is not set +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +CONFIG_NET_SB1250_MAC=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices (depends on LLC=y) +# +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +# CONFIG_VT is not set +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_COMPUTONE is not set +# CONFIG_ROCKETPORT is not set +# CONFIG_CYCLADES is not set +# CONFIG_DIGIEPCA is not set +# CONFIG_DIGI is not set +# CONFIG_MOXA_INTELLIO is not set +# CONFIG_MOXA_SMARTIO is not set +# CONFIG_ISI is not set +# CONFIG_SYNCLINK is not set +# CONFIG_SYNCLINKMP is not set +# CONFIG_N_HDLC is not set +# CONFIG_RISCOM8 is not set +# CONFIG_SPECIALIX is not set +# CONFIG_SX is not set +# CONFIG_RIO is not set +# CONFIG_STALDRV is not set +CONFIG_SIBYTE_SB1250_DUART=y +CONFIG_SIBYTE_SB1250_DUART_CONSOLE=y +CONFIG_SERIAL_CONSOLE=y + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_UNIX98_PTYS is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# I2C Hardware Sensors Mainboard support +# + +# +# I2C Hardware Sensors Chip support +# +# CONFIG_I2C_SENSOR is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HANGCHECK_TIMER is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V4 is not set +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Graphics support +# + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set +# CONFIG_USB_GADGET is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_BLOWFISH=y +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_SERPENT=y +CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_TEST is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff -Nru a/arch/mips/defconfig-sead b/arch/mips/defconfig-sead --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/defconfig-sead Tue Jul 1 18:44:40 2003 @@ -0,0 +1,393 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +CONFIG_MIPS32=y +# CONFIG_MIPS64 is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# General setup +# +CONFIG_SWAP=y +# CONFIG_SYSVIPC is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_EMBEDDED is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# Machine selection +# +# CONFIG_ACER_PICA_61 is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_CASIO_E55 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_IBM_WORKPAD is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MIPS_MALTA is not set +CONFIG_MIPS_SEAD=y +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_NEC_EAGLE is not set +# CONFIG_OLIVETTI_M700 is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TANBAC_TB0226 is not set +# CONFIG_TANBAC_TB0229 is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +# CONFIG_VICTOR_MPC30X is not set +# CONFIG_ZAO_CAPCELLA is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_NONCOHERENT_IO=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_MIPS_BOARDS_GEN=y +CONFIG_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set + +# +# CPU selection +# +CONFIG_CPU_MIPS32=y +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_CPU_HAS_PREFETCH=y +# CONFIG_VTAG_ICACHE is not set +# CONFIG_64BIT_PHYS_ADDR is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +CONFIG_KALLSYMS=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_KCORE_ELF=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=18432 +CONFIG_BLK_DEV_INITRD=y + +# +# MIPS initrd options +# +CONFIG_EMBEDDED_RAMDISK=y +CONFIG_EMBEDDED_RAMDISK_IMAGE="ramdisk.gz" + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# I2O device support +# + +# +# Networking support +# +# CONFIG_NET is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# ISDN subsystem +# + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_UNIX98_PTYS is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# I2C Hardware Sensors Mainboard support +# + +# +# I2C Hardware Sensors Chip support +# +# CONFIG_I2C_SENSOR is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HANGCHECK_TIMER is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Graphics support +# + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB_GADGET is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set diff -Nru a/arch/mips/defconfig-tb0226 b/arch/mips/defconfig-tb0226 --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/defconfig-tb0226 Tue Jul 1 18:44:40 2003 @@ -0,0 +1,667 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +CONFIG_MIPS32=y +# CONFIG_MIPS64 is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_EMBEDDED is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_ACER_PICA_61 is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_CASIO_E55 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_IBM_WORKPAD is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_NEC_EAGLE is not set +# CONFIG_OLIVETTI_M700 is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +CONFIG_TANBAC_TB0226=y +# CONFIG_TANBAC_TB0229 is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +# CONFIG_VICTOR_MPC30X is not set +# CONFIG_ZAO_CAPCELLA is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_NONCOHERENT_IO=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_VR41XX_TIME_C=y +CONFIG_DUMMY_KEYB=y +CONFIG_VR41XX_COMMON=y +CONFIG_NEW_PCI=y +CONFIG_FB=y + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +CONFIG_CPU_VR41XX=y +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_SB1 is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +CONFIG_KALLSYMS=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +# CONFIG_PCI is not set +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_KCORE_ELF=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# +# Block devices +# +CONFIG_BLK_DEV_FD=y +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_RAM=m +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_INITRD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y + +# +# IDE, ATA and ATAPI Block devices +# +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +# CONFIG_IDEDISK_STROKE is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +CONFIG_BLK_DEV_IDESCSI=y +# CONFIG_IDE_TASK_IOCTL is not set +CONFIG_IDE_TASKFILE_IO=y + +# +# IDE chipset support/bugfixes +# + +# +# SCSI device support +# +CONFIG_SCSI=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +CONFIG_BLK_DEV_SR=y +# CONFIG_BLK_DEV_SR_VENDOR is not set +CONFIG_CHR_DEV_SG=y + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_REPORT_LUNS is not set +CONFIG_SCSI_CONSTANTS=y +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI low-level drivers +# +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# I2O device support +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=m +# CONFIG_NETFILTER is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_NAT=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_TOS=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPPOE=m +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices (depends on LLC=y) +# +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=m +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1280 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=1024 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +# CONFIG_SERIO is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +# CONFIG_VT_CONSOLE is not set +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# I2C Hardware Sensors Mainboard support +# + +# +# I2C Hardware Sensors Chip support +# +# CONFIG_I2C_SENSOR is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HANGCHECK_TIMER is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +CONFIG_ROMFS_FS=m +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +CONFIG_AUTOFS4_FS=y + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_ZISOFS_FS=y +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +CONFIG_TMPFS=y +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_CRAMFS=m +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V4 is not set +CONFIG_NFSD=m +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V4 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=m +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +CONFIG_SMB_FS=m +CONFIG_SMB_NLS_DEFAULT=y +CONFIG_SMB_NLS_REMOTE="cp932" +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +CONFIG_SMB_NLS=y +CONFIG_NLS=y + +# +# Native Language Support +# +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=m +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +CONFIG_NLS_CODEPAGE_932=m +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ISO8859_1=m +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Graphics support +# +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE is not set + +# +# Logo configuration +# +# CONFIG_LOGO is not set + +# +# Sound +# +CONFIG_SOUND=y + +# +# Advanced Linux Sound Architecture +# +# CONFIG_SND is not set + +# +# Open Sound System +# +# CONFIG_SOUND_PRIME is not set + +# +# USB support +# +# CONFIG_USB_GADGET is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m diff -Nru a/arch/mips/defconfig-tb0229 b/arch/mips/defconfig-tb0229 --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/defconfig-tb0229 Tue Jul 1 18:44:40 2003 @@ -0,0 +1,657 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +CONFIG_MIPS32=y +# CONFIG_MIPS64 is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_EMBEDDED is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_ACER_PICA_61 is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_CASIO_E55 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_IBM_WORKPAD is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_NEC_EAGLE is not set +# CONFIG_OLIVETTI_M700 is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TANBAC_TB0226 is not set +CONFIG_TANBAC_TB0229=y +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +# CONFIG_VICTOR_MPC30X is not set +# CONFIG_ZAO_CAPCELLA is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_NONCOHERENT_IO=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_VR41XX_TIME_C=y +CONFIG_DUMMY_KEYB=y +CONFIG_VR41XX_COMMON=y +CONFIG_NEW_PCI=y +# CONFIG_FB is not set +CONFIG_TANBAC_TB0219=y + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +CONFIG_CPU_VR41XX=y +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_SB1 is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +CONFIG_KALLSYMS=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_KCORE_ELF=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +CONFIG_BLK_DEV_LOOP=m +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_INITRD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=m +# CONFIG_NETFILTER is not set +CONFIG_UNIX=y +# CONFIG_NET_KEY is not set +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_NAT=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_TOS=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE=m +# CONFIG_NET_IPGRE_BROADCAST is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +CONFIG_SYN_COOKIES=y +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +CONFIG_DUMMY=m +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PPP=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPPOE=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +CONFIG_SLIP_MODE_SLIP6=y + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices (depends on LLC=y) +# +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=m +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1280 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=1024 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +# CONFIG_SERIO is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +# CONFIG_VT_CONSOLE is not set +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# I2C Hardware Sensors Mainboard support +# + +# +# I2C Hardware Sensors Chip support +# +# CONFIG_I2C_SENSOR is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HANGCHECK_TIMER is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +CONFIG_EXT3_FS=m +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=m +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +CONFIG_JFS_FS=m +# CONFIG_JFS_POSIX_ACL is not set +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_XFS_FS=y +# CONFIG_XFS_RT is not set +CONFIG_XFS_QUOTA=y +CONFIG_XFS_POSIX_ACL=y +# CONFIG_MINIX_FS is not set +CONFIG_ROMFS_FS=m +# CONFIG_QUOTA is not set +CONFIG_QUOTACTL=y +# CONFIG_AUTOFS_FS is not set +CONFIG_AUTOFS4_FS=y + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_ZISOFS_FS=y +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +CONFIG_TMPFS=y +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_CRAMFS=m +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V4 is not set +CONFIG_NFSD=y +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V4 is not set +CONFIG_NFSD_TCP=y +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=y +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +CONFIG_SMB_FS=m +CONFIG_SMB_NLS_DEFAULT=y +CONFIG_SMB_NLS_REMOTE="cp932" +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +CONFIG_SMB_NLS=y +CONFIG_NLS=y + +# +# Native Language Support +# +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=m +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +CONFIG_NLS_CODEPAGE_932=m +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +CONFIG_NLS_ISO8859_1=m +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set +# CONFIG_USB_GADGET is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m diff -Nru a/arch/mips/defconfig-workpad b/arch/mips/defconfig-workpad --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/defconfig-workpad Tue Jul 1 18:44:40 2003 @@ -0,0 +1,568 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +CONFIG_MIPS32=y +# CONFIG_MIPS64 is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_EMBEDDED is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_ACER_PICA_61 is not set +# CONFIG_BAGET_MIPS is not set +# CONFIG_CASIO_E55 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +CONFIG_IBM_WORKPAD=y +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_NEC_EAGLE is not set +# CONFIG_OLIVETTI_M700 is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SOC_AU1X00 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TANBAC_TB0226 is not set +# CONFIG_TANBAC_TB0229 is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +# CONFIG_VICTOR_MPC30X is not set +# CONFIG_ZAO_CAPCELLA is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_NONCOHERENT_IO=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_VR41XX_TIME_C=y +CONFIG_DUMMY_KEYB=y +CONFIG_VR41XX_COMMON=y +# CONFIG_FB is not set + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +CONFIG_CPU_VR41XX=y +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_SB1 is not set +# CONFIG_CPU_ADVANCED is not set +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +CONFIG_KALLSYMS=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_KCORE_ELF=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y + +# +# IDE, ATA and ATAPI Block devices +# +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_IDEDISK_STROKE is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_IDE_TASK_IOCTL is not set +CONFIG_IDE_TASKFILE_IO=y + +# +# IDE chipset support/bugfixes +# + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# I2O device support +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_NETLINK_DEV=y +# CONFIG_NETFILTER is not set +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices (depends on LLC=y) +# +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +# CONFIG_SERIO is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +# CONFIG_VT_CONSOLE is not set +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# I2C Hardware Sensors Mainboard support +# + +# +# I2C Hardware Sensors Chip support +# +# CONFIG_I2C_SENSOR is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_WDT is not set +# CONFIG_WDTPCI is not set +# CONFIG_PCWATCHDOG is not set +# CONFIG_ACQUIRE_WDT is not set +# CONFIG_ADVANTECH_WDT is not set +# CONFIG_EUROTECH_WDT is not set +# CONFIG_IB700_WDT is not set +# CONFIG_I810_TCO is not set +# CONFIG_MIXCOMWD is not set +# CONFIG_SCx200_WDT is not set +# CONFIG_60XX_WDT is not set +# CONFIG_W83877F_WDT is not set +# CONFIG_MACHZ_WDT is not set +# CONFIG_SC520_WDT is not set +# CONFIG_AMD7XX_TCO is not set +# CONFIG_ALIM7101_WDT is not set +# CONFIG_SC1200_WDT is not set +# CONFIG_WAFER_WDT is not set +# CONFIG_CPU5_WDT is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HANGCHECK_TIMER is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=y +CONFIG_AUTOFS4_FS=y + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +CONFIG_NFSD=y +# CONFIG_NFSD_V3 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_LOCKD=y +CONFIG_EXPORTFS=y +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Graphics support +# + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB_GADGET is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set diff -Nru a/arch/mips/galileo-boards/ev64120/Makefile b/arch/mips/galileo-boards/ev64120/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/galileo-boards/ev64120/Makefile Tue Jul 1 18:44:40 2003 @@ -0,0 +1,12 @@ +# +# Copyright 2000 RidgeRun, Inc. +# Author: RidgeRun, Inc. +# glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com +# +# Makefile for the Galileo EV64120 board. +# + +obj-y := serialGT.o int-handler.o promcon.o reset.o setup.o irq.o \ + irq-handler.o + +EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips/galileo-boards/ev64120/README b/arch/mips/galileo-boards/ev64120/README --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/galileo-boards/ev64120/README Tue Jul 1 18:44:40 2003 @@ -0,0 +1,2 @@ +The compressed boot code was such a mess I deleted it. Feel free to +reimplement it -- Ralf diff -Nru a/arch/mips/galileo-boards/ev64120/dma.c b/arch/mips/galileo-boards/ev64120/dma.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/galileo-boards/ev64120/dma.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,168 @@ +/* DMA.C - DMA functions and definitions */ + +/* Copyright Galileo Technology. */ + +/* +DESCRIPTION +This file gives the user a complete interface to the powerful DMA engines, +including functions for controling the priority mechanism. +To fully understand the capabilities of the DMA engines please spare some +time to go trough the spec. +*/ + +/* includes */ + +#ifdef __linux__ +#include +#include +#else +#include "Core.h" +#include "DMA.h" +#endif +/******************************************************************** +* dmaCommand - Write a command to a DMA channel +* +* Inputs: DMA_ENGINE channel - choosing one of the four engine. +* unsigned int command - The command to be written to the control register. +* Returns: false if one of the parameters is erroneous else returns true. +*********************************************************************/ + +bool dmaCommand(DMA_ENGINE channel, unsigned int command) +{ + if (channel > LAST_DMA_ENGINE) + return false; + GT_REG_WRITE(CHANNEL0CONTROL + channel * 4, command); + return true; +} + +/******************************************************************** +* dmaTransfer - transfer data from sourceAddr to destAddr on DMA channel +* Inputs: +* DMA_RECORED *nextRecoredPointer: If we are using chain mode DMA transfer, +* then this pointer should point to the next recored,otherwise it should be +* NULL. +* VERY IMPORTANT !!! When using chain mode, the records must be 16 Bytes +* aligned, the function will take care of that for you, but you need to +* allocate one more record for that, meaning: if you are having 3 records , +* declare 4 (see the example bellow) and start using the second one. +* Example: +* Performing a chain mode DMA transfer(Copy a 1/4 mega of data using +* chain mode DMA): +* DMA_RECORED dmaRecoredArray[4]; +* dmaRecoredArray[1].ByteCnt = _64KB; +* dmaRecoredArray[1].DestAdd = destAddress + _64KB; +* dmaRecoredArray[1].SrcAdd = sourceAddress + _64KB; +* dmaRecoredArray[1].NextRecPtr = &dmaRecoredArray[2]; +* dmaRecoredArray[2].ByteCnt = _64KB; +* dmaRecoredArray[2].DestAdd = destAddress + 2*_64KB; +* dmaRecoredArray[2].SrcAdd = sourceAddress + 2*_64KB; +* dmaRecoredArray[2].NextRecPtr = &dmaRecoredArray[3]; +* dmaRecoredArray[3].ByteCnt = _64KB; +* dmaRecoredArray[3].DestAdd = destAddress + 3*_64KB; +* dmaRecoredArray[3].SrcAdd = sourceAddress + 3*_64KB; +* dmaRecoredArray[3].NextRecPtr = NULL; +* performCmDma(0,sourceAddress,destAddress,_64KB,PLAIN,WAIT_TO_END, +* &dmaRecoredArray[1]); +* Returns: NO_SUCH_CHANNEL if channel does not exist, CHANNEL_BUSY if channel +* is active and true if the transfer ended successfully +*********************************************************************/ + +DMA_STATUS dmaTransfer(DMA_ENGINE channel, unsigned int sourceAddr, + unsigned int destAddr, unsigned int numOfBytes, + unsigned int command, + DMA_RECORED * nextRecoredPointer) +{ + unsigned int tempData, checkBits, alignmentOffset = 0; + DMA_RECORED *next = nextRecoredPointer; + + if (channel > LAST_DMA_ENGINE) + return NO_SUCH_CHANNEL; + if (numOfBytes > 0xffff) + return GENERAL_ERROR; + if (isDmaChannelActive(channel)) + return CHANNEL_BUSY; + if (next != NULL) { /* case of chain Mode */ + alignmentOffset = ((unsigned int) next % 16); + } + checkBits = command & 0x6000000; + if (checkBits == 0) { + while (next != NULL) { + WRITE_WORD((unsigned int) next - alignmentOffset, + next->ByteCnt); + tempData = (unsigned int) next->SrcAdd; + WRITE_WORD((unsigned int) next + 4 - + alignmentOffset, tempData & 0x5fffffff); + tempData = (unsigned int) next->DestAdd; + WRITE_WORD((unsigned int) next + 8 - + alignmentOffset, tempData & 0x5fffffff); + tempData = (unsigned int) next->NextRecPtr; + WRITE_WORD((unsigned int) next + 12 - + alignmentOffset, + tempData & 0x5fffffff - + alignmentOffset); + next = (DMA_RECORED *) tempData; + if (next == nextRecoredPointer) + next = NULL; + } + } + GT_REG_WRITE(CHANNEL0_DMA_BYTE_COUNT + channel * 4, numOfBytes); + tempData = sourceAddr; + GT_REG_WRITE(CHANNEL0_DMA_SOURCE_ADDRESS + channel * 4, + tempData & 0x5fffffff); + tempData = destAddr; + GT_REG_WRITE(CHANNEL0_DMA_DESTINATION_ADDRESS + channel * 4, + tempData & 0x5fffffff); + if (nextRecoredPointer != NULL) { + tempData = + (unsigned int) nextRecoredPointer - alignmentOffset; + GT_REG_WRITE(CHANNEL0NEXT_RECORD_POINTER + 4 * channel, + tempData & 0x5fffffff); + command = command | CHANNEL_ENABLE; + } else { + command = command | CHANNEL_ENABLE | NON_CHAIN_MOD; + } + /* Activate DMA engine By writting to dmaControlRegister */ + GT_REG_WRITE(CHANNEL0CONTROL + channel * 4, command); + + return DMA_OK; +} + +/******************************************************************** +* isDmaChannelActive - check if channel is busy +* +* Inputs: channel number +* RETURNS: True if the channel is busy, false otherwise. +*********************************************************************/ + +bool isDmaChannelActive(DMA_ENGINE channel) +{ + unsigned int data; + + if (channel > LAST_DMA_ENGINE) + return false; + GT_REG_READ(CHANNEL0CONTROL + 4 * channel, &data); + if (data & DMA_ACTIVITY_STATUS) + return true; + else + return false; +} + + +/******************************************************************** +* changeDmaPriority - update the arbiter`s priority for channels 0-3 +* +* Inputs: priority for channels 0-1, priority for channels 2-3, + priority for groups and other priority options +* RETURNS: false if one of the parameters is erroneous and true else +*********************************************************************/ + +bool changeDmaPriority(PRIO_CHAN_0_1 prio_01, PRIO_CHAN_2_3 prio_23, + PRIO_GROUP prioGrp, PRIO_OPT prioOpt) +{ + unsigned int prioReg = 0; + + prioReg = (prio_01 & 0x3) + ((prio_23 & 0x3) << 2) + + ((prioGrp & 0x3) << 4) + (prioOpt << 6); + GT_REG_WRITE(ARBITER_CONTROL, prioReg); + return true; +} diff -Nru a/arch/mips/galileo-boards/ev64120/i2o.c b/arch/mips/galileo-boards/ev64120/i2o.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/galileo-boards/ev64120/i2o.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,689 @@ +/* i2o.c - Drivers for the I2O */ + +/* Copyright - Galileo technology. */ + +/*includes*/ + +#include + +#ifdef __linux__ +#include +#include +#else +#include "Core.h" +#include "i2o.h" +#endif + +/******************************************************************** +* getInBoundMessage - When the GT is configured for I2O support +* it can receive a message from an agent on the pci bus. +* This message is a 32 bit wide and can be read by +* the CPU. +* The messaging unit contains two sets of registers +* so, actually it can receive a 64 bit message. +* +* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register. +* OUTPUT: N/A. +* RETURNS: Data received from the remote agent. +*********************************************************************/ +unsigned int getInBoundMessage(I2O_MESSAGE_REG messageRegNum) +{ + unsigned int regValue; + + GT_REG_READ(INBOUND_MESSAGE_REGISTER0_CPU_SIDE + 4 * messageRegNum, + ®Value); + return (regValue); +} + + +/******************************************************************** +* checkInboundIntAndClear - When a message is received an interrupt is +* generated, to enable polling instead the use of +* an interrupt handler the user can use this fuction. +* You will need to mask the incomming interrupt for +* proper use. +* +* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register. +* OUTPUT: N/A. +* RETURNS: true if the corresponding bit in the cause register is set otherwise +* false. +*********************************************************************/ +bool checkInBoundIntAndClear(I2O_MESSAGE_REG messageRegNum) +{ + unsigned int regValue; + + GT_REG_READ(INBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE, ®Value); + /* clears bit 0 for message register 0 or bit 1 for message register 1 */ + GT_REG_WRITE(INBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE, + BIT1 * messageRegNum); + switch (messageRegNum) { + case MESSAGE_REG_0: + if (regValue & BIT0) + return true; + break; + case MESSAGE_REG_1: + if (regValue & BIT1) + return true; + break; + } + return false; +} + +/******************************************************************** +* sendOutBoundMessage - When the GT is configured for I2O support +* it can send a message to an agent on the pci bus. +* This message is a 32 bit wide and can be read by +* the PCI agent. +* The messaging unit contains two sets of registers +* so, actually it can send a 64 bit message. +* +* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register. +* unsigned int message - Message to be sent. +* OUTPUT: N/A. +* RETURNS: true. +*********************************************************************/ +bool sendOutBoundMessage(I2O_MESSAGE_REG messageRegNum, + unsigned int message) +{ + GT_REG_WRITE(OUTBOUND_MESSAGE_REGISTER0_CPU_SIDE + + 4 * messageRegNum, message); + return true; +} + +/******************************************************************** +* checkOutboundInt - When the CPU sends a message to the Outbound +* register it generates an interrupt which is refelcted on +* the Outbound Interrupt cause register, the interrupt can +* be cleard only by the PCI agent which read the message. +* After sending the message you can acknowledge it by +* monitoring the corresponding bit in the cause register. +* +* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register. +* OUTPUT: N/A. +* RETURNS: true if the corresponding bit in the cause register is set otherwise +* false. +*********************************************************************/ +bool outBoundMessageAcknowledge(I2O_MESSAGE_REG messageRegNum) +{ + unsigned int regValue; + + GT_REG_READ(OUTBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE, ®Value); + switch (messageRegNum) { + case MESSAGE_REG_0: + if (regValue & BIT0) + return true; + break; + case MESSAGE_REG_1: + if (regValue & BIT1) + return true; + break; + } + return false; +} + +/******************************************************************** +* maskInBoundMessageInterrupt - Mask the inbound interrupt, when masking +* the interrupt you can work in polling mode +* using the checkInboundIntAndClear function. +* +* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register. +* OUTPUT: N/A. +* RETURNS: true. +*********************************************************************/ +bool maskInBoundMessageInterrupt(I2O_MESSAGE_REG messageRegNum) +{ + switch (messageRegNum) { + case MESSAGE_REG_0: + SET_REG_BITS(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, + BIT0); + break; + case MESSAGE_REG_1: + SET_REG_BITS(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, + BIT1); + break; + } + return true; +} + +/******************************************************************** +* enableInBoundMessageInterrupt - unMask the inbound interrupt. +* +* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register. +* OUTPUT: N/A. +* RETURNS: true. +*********************************************************************/ +bool enableInBoundMessageInterrupt(I2O_MESSAGE_REG messageRegNum) +{ + switch (messageRegNum) { + case MESSAGE_REG_0: + RESET_REG_BITS(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, + BIT0); + break; + case MESSAGE_REG_1: + RESET_REG_BITS(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, + BIT1); + break; + } + return true; +} + +/******************************************************************** +* maskOutboundMessageInterrupt - Mask the out bound interrupt, when doing so +* the PCI agent needs to poll on the interrupt +* cause register to monitor an incoming message. +* +* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register. +* OUTPUT: N/A. +* RETURNS: true. +*********************************************************************/ +bool maskOutBoundMessageInterrupt(I2O_MESSAGE_REG messageRegNum) +{ + switch (messageRegNum) { + case MESSAGE_REG_0: + SET_REG_BITS(OUTBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, + BIT0); + break; + case MESSAGE_REG_1: + SET_REG_BITS(OUTBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, + BIT1); + break; + } + return true; +} + +/******************************************************************** +* enableOutboundMessageInterrupt - Mask the out bound interrupt, when doing so +* the PCI agent needs to poll on the interrupt +* cause register to monitor an incoming message. +* +* INPUTS: I2O_MESSAGE_REG messageRegNum - Selected set (0 or 1) register. +* OUTPUT: N/A. +* RETURNS: true. +*********************************************************************/ +bool enableOutBoundMessageInterrupt(I2O_MESSAGE_REG messageRegNum) +{ + switch (messageRegNum) { + case MESSAGE_REG_0: + RESET_REG_BITS(OUTBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, + BIT0); + break; + case MESSAGE_REG_1: + RESET_REG_BITS(OUTBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, + BIT1); + break; + } + return true; +} + +/******************************************************************** +* initiateOutBoundDoorBellInt - Setting a bit in this register to '1' by the +* CPU generates a PCI interrupt (if it is not masked by +* the Outbound interrupt Mask register) +* Only the PCI agent which recieved the interrupt can +* clear it, only after clearing all the bits the +* interrupt will be de-asserted. +* +* INPUTS: unsigned int data - Requested interrupt bits. +* OUTPUT: N/A. +* RETURNS: true. +*********************************************************************/ +bool initiateOutBoundDoorBellInt(unsigned int data) +{ + GT_REG_WRITE(OUTBOUND_DOORBELL_REGISTER_CPU_SIDE, data); + return true; +} + +/******************************************************************** +* readInBoundDoorBellInt - Read the in bound door bell interrupt cause +* register. +* +* OUTPUT: N/A. +* RETURNS: The 32 bit interrupt cause register. +*********************************************************************/ +unsigned int readInBoundDoorBellInt() +{ + unsigned int regData; + GT_REG_READ(INBOUND_DOORBELL_REGISTER_CPU_SIDE, ®Data); + return regData; +} + +/******************************************************************** +* clearInBoundDoorBellInt - An interrupt generated by a PCI agent through +* the in bound door bell mechanisem can be cleared +* only by the CPU. The interrupt will be de-asserted +* only if all the bits which where set by the PCI +* agent are cleared. +* +* INPUTS: unsigned int data - Bits to be cleared. +* OUTPUT: N/A. +* RETURNS: true. +*********************************************************************/ +bool clearInBoundDoorBellInt(unsigned int data) +{ + GT_REG_WRITE(INBOUND_DOORBELL_REGISTER_CPU_SIDE, data); + return true; +} + +/******************************************************************** +* isInBoundDoorBellInterruptSet - Check if Inbound Doorbell Interrupt is set, +* can be used for polling mode. +* +* INPUTS: N/A. +* OUTPUT: N/A. +* RETURNS: true if the corresponding bit in the cause register is set otherwise +* false. +*********************************************************************/ +bool isInBoundDoorBellInterruptSet() +{ + unsigned int regData; + + GT_REG_READ(INBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE, ®Data); + return (regData & BIT2); +} + +/******************************************************************** +* isOutBoundDoorBellInterruptSet - Check if out bound Doorbell Interrupt is +* set, can be used for acknowledging interrupt +* handling by the agent who recieived the +* interrupt. +* +* INPUTS: N/A. +* OUTPUT: N/A. +* RETURNS: true if the corresponding bit in the cause register is set otherwise +* false. +*********************************************************************/ +bool isOutBoundDoorBellInterruptSet() +{ + unsigned int regData; + + GT_REG_READ(OUTBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE, ®Data); + return (regData & BIT2); +} + +/******************************************************************** +* maskInboundDoorBellInterrupt - Mask the Inbound Doorbell Interrupt. +* +* INPUTS: N/A. +* OUTPUT: N/A. +* RETURNS: true. +*********************************************************************/ +bool maskInBoundDoorBellInterrupt() +{ + SET_REG_BITS(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, BIT2); + return true; +} + +/******************************************************************** +* enableInboundDoorBellInterrupt - unMask the Inbound Doorbell Interrupt. +* +* INPUTS: N/A. +* OUTPUT: N/A. +* RETURNS: true. +*********************************************************************/ +bool enableInBoundDoorBellInterrupt() +{ + RESET_REG_BITS(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, BIT2); + return true; +} + +/******************************************************************** +* maskOutboundDoorBellInterrupt - Mask the Outbound Doorbell Interrupt. +* +* INPUTS: N/A. +* OUTPUT: N/A. +* RETURNS: true. +*********************************************************************/ +bool maskOutBoundDoorBellInterrupt() +{ + SET_REG_BITS(OUTBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, BIT2); + return true; +} + +/******************************************************************** +* enableOutboundDoorBellInterrupt - unMask the Outbound Doorbell Interrupt. +* +* INPUTS: N/A. +* OUTPUT: N/A. +* RETURNS: true. +*********************************************************************/ +bool enableOutBoundDoorBellInterrupt() +{ + RESET_REG_BITS(OUTBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, BIT2); + return true; +} + +/******************************************************************** +* circularQueueEnable - Initialize the I2O messaging mechanism. +* +* INPUTS: CIRCULE_QUEUE_SIZE cirQueSize - Bits 5:1 in the: +* Queue Control Register, Offset 0x50 (0x1c50). +* Defines the queues size (refer to the data sheet +* for more information) +* unsigned int queueBaseAddr - The base address for the first queue. +* The other queues base Address will be determined as follows: +* Inbound Free = queueBaseAddr +* Inbound Post = queueBaseAddr + cirQueSize +* Outbound Post = queueBaseAddr + cirQueSize +* +* OUTPUT: N/A. +* RETURNS: true. +* +* The Circular Queue Starting Addresses as written in the spec: +* ---------------------------------------- +* | Queue | Starting Address | +* |----------------|---------------------| +* | Inbound Free | QBAR | +* | Inbound Post | QBAR + Queue Size | +* | Outbound Post | QBAR + 2*Queue Size | +* | Outbound Free | QBAR + 3*Queue Size | +* ---------------------------------------- +*********************************************************************/ +bool circularQueueEnable(CIRCULAR_QUEUE_SIZE cirQueSize, + unsigned int queueBaseAddr) +{ + unsigned int regData; + + regData = BIT0 | (cirQueSize << 1); + /* Enable Queue Operation */ + GT_REG_WRITE(QUEUE_CONTROL_REGISTER_CPU_SIDE, regData); + /* Writing The base Address for the 4 Queues */ + GT_REG_WRITE(QUEUE_BASE_ADDRESS_REGISTER_CPU_SIDE, queueBaseAddr); + /* Update The Inbound Free Queue Base Address, offset=0 */ + GT_REG_WRITE(INBOUND_FREE_HEAD_POINTER_REGISTER_CPU_SIDE, 0); + GT_REG_WRITE(INBOUND_FREE_TAIL_POINTER_REGISTER_CPU_SIDE, 0); + /* Update The Inbound Post Queue Base Address, offset=_16K*cirQueSize */ + GT_REG_WRITE(INBOUND_POST_HEAD_POINTER_REGISTER_CPU_SIDE, + _16K * cirQueSize); + GT_REG_WRITE(INBOUND_POST_TAIL_POINTER_REGISTER_CPU_SIDE, + _16K * cirQueSize); + /* Update The Outbound Post Queue Base Address, offset=2*_16K*cirQueSize */ + GT_REG_WRITE(OUTBOUND_POST_HEAD_POINTER_REGISTER_CPU_SIDE, + 2 * _16K * cirQueSize); + GT_REG_WRITE(OUTBOUND_POST_TAIL_POINTER_REGISTER_CPU_SIDE, + 2 * _16K * cirQueSize); + /* Update The Outbound Free Queue Base Address, offset=3*_16K*cirQueSize */ + GT_REG_WRITE(OUTBOUND_FREE_HEAD_POINTER_REGISTER_CPU_SIDE, + 3 * _16K * cirQueSize); + GT_REG_WRITE(OUTBOUND_FREE_TAIL_POINTER_REGISTER_CPU_SIDE, + 3 * _16K * cirQueSize); + return true; +} + +/******************************************************************** +* inBoundPostQueuePop - Two actions are being taken upon pop: +* 1) Getting out the data from the Queue`s head. +* 2) Increment the tail pointer in a cyclic way (The HEAD is +* incremented automaticaly by the GT) +* +* INPUTS: N/A. +* OUTPUT: N/A. +* RETURNS: Data pointed by tail. +*********************************************************************/ +unsigned int inBoundPostQueuePop() +{ + unsigned int tailAddrPointer; + unsigned int data; + unsigned int cirQueSize; + unsigned int qBar; + unsigned int inBoundPostQbase; + + /* Gets the Inbound Post TAIL pointer */ + GT_REG_READ(INBOUND_POST_TAIL_POINTER_REGISTER_CPU_SIDE, + &tailAddrPointer); + /* Gets the Data From the pointer Address */ + READ_WORD(tailAddrPointer, &data); + /* incrementing head process: */ + /* Gets the fifo's base Address */ + GT_REG_READ(QUEUE_BASE_ADDRESS_REGISTER_CPU_SIDE, &qBar); + qBar = qBar & 0xfff00000; + /* Gets the fifo's size */ + GT_REG_READ(QUEUE_CONTROL_REGISTER_CPU_SIDE, &cirQueSize); + cirQueSize = 0x1f && (cirQueSize >> 1); + /* calculating The Inbound Post Queue Base Address */ + inBoundPostQbase = qBar + 1 * cirQueSize * _16K; + /* incrementing Inbound Post queue TAIL in a cyclic loop */ + tailAddrPointer = inBoundPostQbase + ((tailAddrPointer + 4) % + (_16K * cirQueSize)); + /* updating the pointer back to INBOUND_POST_TAIL_POINTER_REGISTER */ + GT_REG_WRITE(INBOUND_POST_TAIL_POINTER_REGISTER_CPU_SIDE, + tailAddrPointer); + return data; +} + +/******************************************************************** +* isInBoundPostQueueInterruptSet - Check if in bound interrupt is set. +* can be used for polling mode. +* +* INPUTS: N/A. +* OUTPUT: N/A. +* RETURNS: true if the corresponding bit in the cause register is set otherwise +* false. +*********************************************************************/ +bool isInBoundPostQueueInterruptSet() +{ + unsigned int regData; + + GT_REG_READ(INBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE, ®Data); + return (regData & BIT4); /* if set return '1' (true), else '0' (false) */ +} + +/******************************************************************** +* clearInBoundPostQueueInterrupt - Clears the Post queue interrupt. +* +* INPUTS: N/A. +* OUTPUT: N/A. +* RETURNS: true. +*********************************************************************/ +bool clearInBoundPostQueueInterrupt() +{ + GT_REG_WRITE(INBOUND_INTERRUPT_CAUSE_REGISTER_CPU_SIDE, BIT4); + return true; +} + +/******************************************************************** +* maskInBoundPostQueueInterrupt - Mask the inbound interrupt, when masking +* the interrupt you can work in polling mode. +* +* INPUTS: N/A. +* OUTPUT: N/A. +* RETURNS: +*********************************************************************/ +void maskInBoundPostQueueInterrupt() +{ + unsigned int regData; + + GT_REG_READ(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, ®Data); + GT_REG_WRITE(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, + regData | BIT4); + +} + +/******************************************************************** +* enableInBoundPostQueueInterrupt - Enable interrupt when ever there is a new +* message from the PCI agent. +* +* INPUTS: N/A. +* OUTPUT: N/A. +* RETURNS: +*********************************************************************/ +void enableInBoundPostQueueInterrupt() +{ + unsigned int regData; + + GT_REG_READ(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, ®Data); + GT_REG_WRITE(INBOUND_INTERRUPT_MASK_REGISTER_CPU_SIDE, + regData & 0xfffffffb); +} + +/******************************************************************** +* inBoundFreeQueuePush - Two actions are being taken upon push: +* 1) Place the user`s data on the Queue`s head. +* 2) Increment the haed pointer in a cyclic way (The tail is +* decremented automaticaly by the GT) +* +* INPUTS: unsigned int data - Data to be placed in the queue. +* OUTPUT: N/A. +* RETURNS: true. +*********************************************************************/ +bool inBoundFreeQueuePush(unsigned int data) +{ + unsigned int headPointer; + unsigned int cirQueSize; + unsigned int qBar; + unsigned int inBoundFreeQbase; + + GT_REG_READ(INBOUND_FREE_HEAD_POINTER_REGISTER_CPU_SIDE, + &headPointer); + /* placing the data in the queue */ + WRITE_WORD(headPointer, data); + /* incrementing head process: */ + /* Gets the fifo's base Address */ + GT_REG_READ(QUEUE_BASE_ADDRESS_REGISTER_CPU_SIDE, &qBar); + qBar = qBar & 0xfff00000; + /* Gets the fifo's size */ + GT_REG_READ(QUEUE_CONTROL_REGISTER_CPU_SIDE, &cirQueSize); + cirQueSize = 0x1f && (cirQueSize >> 1); + /* calculating The Inbound Free Queue Base Address */ + inBoundFreeQbase = qBar; + /* incrementing Inbound Free queue HEAD in a cyclic loop */ + headPointer = + inBoundFreeQbase + ((headPointer + 4) % (_16K * cirQueSize)); + /* updating the pointer back to OUTBOUND_POST_HEAD_POINTER_REGISTER */ + GT_REG_WRITE(INBOUND_FREE_HEAD_POINTER_REGISTER_CPU_SIDE, + headPointer); + return true; +} + +/******************************************************************** +* isInBoundFreeQueueEmpty - Check if Inbound Free Queue Empty. +* Can be used for acknowledging the messages +* being sent by us to the PCI agent. +* +* INPUTS: N/A. +* OUTPUT: N/A. +* RETURNS: true if the queue is empty , otherwise false. +*********************************************************************/ +bool isInBoundFreeQueueEmpty() +{ + unsigned int inBoundFreeQueHead; + unsigned int inBoundFreeQueTail; + + GT_REG_READ(INBOUND_FREE_HEAD_POINTER_REGISTER_CPU_SIDE, + &inBoundFreeQueHead); + GT_REG_READ(INBOUND_FREE_TAIL_POINTER_REGISTER_CPU_SIDE, + &inBoundFreeQueTail); + if (inBoundFreeQueHead == inBoundFreeQueTail) { + return true; + } else + return false; +} + +/******************************************************************** +* outBoundPostQueuePush - Two actions are being taken upon push: +* 1) Place the user`s data on the Queue`s head. +* 2) Increment the haed pointer in a cyclic way (The tail is +* decremented automaticaly by the GT when the Agent on the +* PCI have read data from the Outbound Port). +* +* INPUTS: unsigned int data - Data to be placed in the queue`s head. +* OUTPUT: N/A. +* RETURNS: true. +*********************************************************************/ +bool outBoundPostQueuePush(unsigned int data) +{ + unsigned int headPointer; + unsigned int cirQueSize; + unsigned int qBar; + unsigned int outBoundPostQbase; + + GT_REG_READ(OUTBOUND_POST_HEAD_POINTER_REGISTER_CPU_SIDE, + &headPointer); + /* placing the data in the queue (where the head point to..) */ + WRITE_WORD(headPointer, data); + /* incrementing head process: */ + /* Gets the fifo's base Address */ + GT_REG_READ(QUEUE_BASE_ADDRESS_REGISTER_CPU_SIDE, &qBar); + qBar = qBar & 0xfff00000; + /* Gets the fifo's size */ + GT_REG_READ(QUEUE_CONTROL_REGISTER_CPU_SIDE, &cirQueSize); + cirQueSize = 0x1f && (cirQueSize >> 1); + /* calculating The Outbound Post Queue Base Address */ + outBoundPostQbase = qBar + 2 * cirQueSize * _16K; + /* incrementing Outbound Post queue in a cyclic loop */ + headPointer = + outBoundPostQbase + ((headPointer + 4) % (_16K * cirQueSize)); + /* updating the pointer back to OUTBOUND_POST_HEAD_POINTER_REGISTER */ + GT_REG_WRITE(OUTBOUND_POST_HEAD_POINTER_REGISTER_CPU_SIDE, + headPointer); + return true; +} + +/******************************************************************** +* isOutBoundPostQueueEmpty - Check if Outbound Post Queue Empty. +* Can be used for acknowledging the messages +* being sent by us to the PCI agent. +* +* INPUTS: N/A. +* OUTPUT: N/A. +* RETURNS: true if the queue is empty , otherwise false. +*********************************************************************/ +bool isOutBoundPostQueueEmpty() +{ + unsigned int outBoundPostQueHead; + unsigned int outBoundPostQueTail; + + GT_REG_READ(INBOUND_FREE_HEAD_POINTER_REGISTER_CPU_SIDE, + &outBoundPostQueHead); + GT_REG_READ(INBOUND_FREE_TAIL_POINTER_REGISTER_CPU_SIDE, + &outBoundPostQueTail); + if (outBoundPostQueHead == outBoundPostQueTail) { + return true; + } else + return false; +} + +/******************************************************************** +* outBoundFreeQueuePop - Two actions are being taken upon pop: +* 1) Getting out the data from the Queue`s head. +* 2) Increment the tail pointer in a cyclic way (The HEAD is +* incremented automaticaly by the GT) +* +* INPUTS: N/A. +* OUTPUT: N/A. +* RETURNS: Data pointed by tail. +*********************************************************************/ +unsigned int outBoundFreeQueuePop() +{ + unsigned int tailAddrPointer; + unsigned int data; + unsigned int cirQueSize; + unsigned int qBar; + unsigned int outBoundFreeQbase; + + /* Gets the Inbound Post TAIL pointer */ + GT_REG_READ(OUTBOUND_FREE_TAIL_POINTER_REGISTER_CPU_SIDE, + &tailAddrPointer); + /* Gets the Data From the pointer Address */ + READ_WORD(tailAddrPointer, &data); + /* incrementing head process: */ + /* Gets the fifo's base Address */ + GT_REG_READ(QUEUE_BASE_ADDRESS_REGISTER_CPU_SIDE, &qBar); + qBar = qBar & 0xfff00000; + /* Gets the fifo's size */ + GT_REG_READ(QUEUE_CONTROL_REGISTER_CPU_SIDE, &cirQueSize); + cirQueSize = 0x1f && (cirQueSize >> 1); + /* calculating The Inbound Post Queue Base Address */ + outBoundFreeQbase = qBar + 3 * cirQueSize * _16K; + /* incrementing Outbound Free queue TAlL in a cyclic loop */ + tailAddrPointer = outBoundFreeQbase + ((tailAddrPointer + 4) % + (_16K * cirQueSize)); + /* updating the pointer back to OUTBOUND_FREE_TAIL_POINTER_REGISTER */ + GT_REG_WRITE(OUTBOUND_FREE_TAIL_POINTER_REGISTER_CPU_SIDE, + tailAddrPointer); + return data; +} + + +EXPORT_SYMBOL(isInBoundDoorBellInterruptSet); +EXPORT_SYMBOL(initiateOutBoundDoorBellInt); +EXPORT_SYMBOL(clearInBoundDoorBellInt); diff -Nru a/arch/mips/galileo-boards/ev64120/int-handler.S b/arch/mips/galileo-boards/ev64120/int-handler.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/galileo-boards/ev64120/int-handler.S Tue Jul 1 18:44:40 2003 @@ -0,0 +1,85 @@ +/* + * int-handler.S + * + * Based on the cobalt handler. + */ +#include +#include +#include +#include +#include + +/* + * We check for the timer first, then check PCI ints A and D. + * Then check for serial IRQ and fall through. + */ + .align 5 + .set reorder + .set noat + NESTED(galileo_handle_int, PT_SIZE, sp) + SAVE_ALL + CLI + .set at + + mfc0 t0, CP0_CAUSE + mfc0 t2, CP0_STATUS + + and t0, t2 + + .set noreorder + andi t1, t0, STATUSF_IP4 /* int2 hardware line (timer) */ + andi t2, t0, STATUSF_IP2 /* int0 hardware line */ + bnez t1, ll_galileo_irq + andi t1, t0, STATUSF_IP5 /* int3 hardware line */ + bnez t2, ll_pci_intA + andi t2, t0, STATUSF_IP6 /* int4 hardware line */ + bnez t1, ll_pci_intD + andi t1, t0, STATUSF_IP7 /* compare int */ + bnez t2, ll_serial_irq + nop + bnez t1, ll_compare_irq + nop + .set reorder + + j spurious_interrupt + END(galileo_handle_int) + + .align 5 +ll_galileo_irq: li a0, 4 + move a1, sp + jal do_IRQ + j ret_from_irq + + .align 5 +ll_compare_irq: li a0, 7 + move a1, sp + jal do_IRQ + j ret_from_irq + + .align 5 +ll_pci_intA: move a0, sp + jal pci_intA + j ret_from_irq + +#if 0 + .align 5 +ll_pci_intB: move a0, sp + jal pci_intB + j ret_from_irq + + .align 5 +ll_pci_intC: move a0, sp + jal pci_intC + j ret_from_irq +#endif + + .align 5 +ll_pci_intD: move a0, sp + jal pci_intD + j ret_from_irq + + .align 5 +ll_serial_irq: li a0, 6 + move a1, sp + jal do_IRQ + j ret_from_irq diff -Nru a/arch/mips/galileo-boards/ev64120/irq-handler.c b/arch/mips/galileo-boards/ev64120/irq-handler.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/galileo-boards/ev64120/irq-handler.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,270 @@ +/* + * Galileo Technology chip interrupt handler + * + * Modified by RidgeRun, Inc. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * These are interrupt handlers for the GT on-chip interrupts. They all come + * in to the MIPS on a single interrupt line, and have to be handled and ack'ed + * differently than other MIPS interrupts. + */ + +#if CURRENTLY_UNUSED + +struct tq_struct irq_handlers[MAX_CAUSE_REGS][MAX_CAUSE_REG_WIDTH]; +void hook_irq_handler(int int_cause, int bit_num, void *isr_ptr); + +/* + * hook_irq_handler + * + * Hooks IRQ handler to the system. When the system is interrupted + * the interrupt service routine is called. + * + * Inputs : + * int_cause - The interrupt cause number. In EVB64120 two parameters + * are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH. + * bit_num - Indicates which bit number in the cause register + * isr_ptr - Pointer to the interrupt service routine + * + * Outputs : + */ +void hook_irq_handler(int int_cause, int bit_num, void *isr_ptr) +{ + irq_handlers[int_cause][bit_num].routine = isr_ptr; +} + + +/* + * enable_galileo_irq + * + * Enables the IRQ on Galileo Chip + * + * Inputs : + * int_cause - The interrupt cause number. In EVB64120 two parameters + * are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH. + * bit_num - Indicates which bit number in the cause register + * + * Outputs : + * 1 if succesful, 0 if failure + */ +int enable_galileo_irq(int int_cause, int bit_num) +{ + if (int_cause == INT_CAUSE_MAIN) + SET_REG_BITS(CPU_INTERRUPT_MASK_REGISTER, (1 << bit_num)); + else if (int_cause == INT_CAUSE_HIGH) + SET_REG_BITS(CPU_HIGH_INTERRUPT_MASK_REGISTER, + (1 << bit_num)); + else + return 0; + return 1; +} + +/* + * disable_galileo_irq + * + * Disables the IRQ on Galileo Chip + * + * Inputs : + * int_cause - The interrupt cause number. In EVB64120 two parameters + * are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH. + * bit_num - Indicates which bit number in the cause register + * + * Outputs : + * 1 if succesful, 0 if failure + */ +int disable_galileo_irq(int int_cause, int bit_num) +{ + if (int_cause == INT_CAUSE_MAIN) + RESET_REG_BITS(CPU_INTERRUPT_MASK_REGISTER, + (1 << bit_num)); + else if (int_cause == INT_CAUSE_HIGH) + RESET_REG_BITS(CPU_HIGH_INTERRUPT_MASK_REGISTER, + (1 << bit_num)); + else + return 0; + return 1; +} + +#endif /* UNUSED */ + +/* + * galileo_irq - + * + * Interrupt handler for interrupts coming from the Galileo chip. + * It could be timer interrupt, built in ethernet ports etc... + * + * Inputs : + * + * Outputs : + * + */ +static void galileo_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned int irq_src, int_high_src, irq_src_mask, + int_high_src_mask; + int handled; + unsigned int count; + static int counter = 0; + + GT_READ(GT_INTRCAUSE_OFS, &irq_src); + GT_READ(GT_INTRMASK_OFS, &irq_src_mask); + GT_READ(GT_HINTRCAUSE_OFS, &int_high_src); + GT_READ(GT_HINTRMASK_OFS, &int_high_src_mask); + irq_src = irq_src & irq_src_mask; + int_high_src = int_high_src & int_high_src_mask; + + handled = 0; + + /* Execute all interrupt handlers */ + /* Check for timer interrupt */ + if (irq_src & 0x00000800) { + handled = 1; + irq_src &= ~0x00000800; + // RESET_REG_BITS (INTERRUPT_CAUSE_REGISTER,BIT8); + do_timer(regs); + } + + if (irq_src) { + printk(KERN_INFO + "Other Galileo interrupt received irq_src %x\n", + irq_src); +#if CURRENTLY_UNUSED + for (count = 0; count < MAX_CAUSE_REG_WIDTH; count++) { + if (irq_src & (1 << count)) { + if (irq_handlers[INT_CAUSE_MAIN][count]. + routine) { + queue_task(&irq_handlers + [INT_CAUSE_MAIN][count], + &tq_immediate); + mark_bh(IMMEDIATE_BH); + handled = 1; + } + } + } +#endif /* UNUSED */ + } + GT_WRITE(GT_INTRCAUSE_OFS, 0); + GT_WRITE(GT_HINTRCAUSE_OFS, 0); + +#undef GALILEO_I2O +#ifdef GALILEO_I2O + /* + Future I2O support. We currently attach I2O interrupt handlers to the + Galileo interrupt (int 4) and handle them in do_IRQ. + */ + if (isInBoundDoorBellInterruptSet()) { + printk(KERN_INFO "I2O doorbell interrupt received.\n"); + handled = 1; + } + + if (isInBoundPostQueueInterruptSet()) { + printk(KERN_INFO "I2O Queue interrupt received.\n"); + handled = 1; + } + + /* + This normally would be outside of the ifdef, but since + we're handling I2O outside of this handler, this + printk shows up every time we get a valid I2O + interrupt. So turn this off for now. + */ + if (handled == 0) { + if (counter < 50) { + printk("Spurious Galileo interrupt...\n"); + counter++; + } + } +#endif +} + +/* + * galileo_time_init - + * + * Initializes timer using galileo's built in timer. + * + * + * Inputs : + * irq - number of irq to be used by the timer + * + * Outpus : + * + */ +#ifdef CONFIG_SYSCLK_100 +#define Sys_clock (100 * 1000000) // 100 MHz +#endif +#ifdef CONFIG_SYSCLK_83 +#define Sys_clock (83.333 * 1000000) // 83.333 MHz +#endif +#ifdef CONFIG_SYSCLK_75 +#define Sys_clock (75 * 1000000) // 75 MHz +#endif + +/* + * This will ignore the standard MIPS timer interrupt handler that is passed + * in as *irq (=irq0 in ../kernel/time.c). We will do our own timer interrupt + * handling. + */ +void galileo_time_init(struct irqaction *irq) +{ + extern irq_desc_t irq_desc[NR_IRQS]; + static struct irqaction timer; + + /* Disable timer first */ + GT_WRITE(GT_TC_CONTROL_OFS, 0); + /* Load timer value for 100 Hz */ + GT_WRITE(GT_TC3_OFS, Sys_clock / 100); + + /* + * Create the IRQ structure entry for the timer. Since we're too early + * in the boot process to use the "request_irq()" call, we'll hard-code + * the values to the correct interrupt line. + */ + timer.handler = &galileo_irq; + timer.flags = SA_SHIRQ; + timer.name = "timer"; + timer.dev_id = NULL; + timer.next = NULL; + timer.mask = 0; + irq_desc[TIMER].action = &timer; + + /* Enable timer ints */ + GT_WRITE(GT_TC_CONTROL_OFS, 0xc0); + /* clear Cause register first */ + GT_WRITE(GT_INTRCAUSE_OFS, 0x0); + /* Unmask timer int */ + GT_WRITE(GT_INTRMASK_OFS, 0x800); + /* Clear High int register */ + GT_WRITE(GT_HINTRCAUSE_OFS, 0x0); + /* Mask All interrupts at High cause interrupt */ + GT_WRITE(GT_HINTRMASK_OFS, 0x0); + +} + +void galileo_irq_init(void) +{ +#if CURRENTLY_UNUSED + int i, j; + + /* Reset irq handlers pointers to NULL */ + for (i = 0; i < MAX_CAUSE_REGS; i++) { + for (j = 0; j < MAX_CAUSE_REG_WIDTH; j++) { + irq_handlers[i][j].next = NULL; + irq_handlers[i][j].sync = 0; + irq_handlers[i][j].routine = NULL; + irq_handlers[i][j].data = NULL; + } + } +#endif +} diff -Nru a/arch/mips/galileo-boards/ev64120/irq.c b/arch/mips/galileo-boards/ev64120/irq.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/galileo-boards/ev64120/irq.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,184 @@ +/* + * BRIEF MODULE DESCRIPTION + * Code to handle irqs on GT64120A boards + * Derived from mips/orion and Cort + * + * Copyright (C) 2000 RidgeRun, Inc. + * Author: RidgeRun, Inc. + * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_AGENTS_PER_INT 21 /* Random number */ +unsigned char pci_int_irq[MAX_AGENTS_PER_INT]; +static int max_interrupts = 0; + +asmlinkage void pci_intA(struct pt_regs *regs) +{ + unsigned int count = 0; + + /* This must be a joke - Ralf */ + for (count = 0; count < max_interrupts; count++) + do_IRQ(pci_int_irq[count], regs); +} + +asmlinkage void pci_intD(struct pt_regs *regs) +{ + unsigned int count = 0; + + /* Encore une fois - This must be a joke - Ralf */ + for (count = 0; count < max_interrupts; count++) + do_IRQ(pci_int_irq[count], regs); +} + +/* + * Now this is scarry. A disable_irq(2) or disable_irq(5) would just + * accidently disable a pci irq. It shouldn't happen but may just leaving + * these always enabled or use some reference counting wouldn't be such a + * bad thing. + */ +static void disable_ev64120_irq(unsigned int irq_nr) +{ + unsigned long flags; + + local_irq_save(flags); + if (irq_nr >= 8) { + /* All PCI interrupts are on line 5 or 2 */ + clear_c0_status(IE_IRQ0 | IE_IRQ3); + } else { + clear_c0_status(0x100 << irq_nr); + } + local_irq_restore(flags); +} + +#define mask_and_ack_ev64120_irq disable_ev64120_irq + +static inline void enable_ev64120_irq(unsigned int irq_nr) +{ + unsigned long flags; + + local_irq_save(flags); + if (irq_nr >= 8) { + /* All PCI interrupts are on line 5 or 2 */ + set_c0_status(IE_IRQ0 | IE_IRQ3); + } else { + set_c0_status(IE_SW0 << irq_nr); + } + local_irq_restore(flags); +} + +static unsigned int startup_ev64120_irq(unsigned int irq) +{ + if (irq >= 8) { + // NOTE: Add error-handling if > max + pci_int_irq[max_interrupts++] = irq; + } + enable_ev64120_irq(irq); + + return 0; +} + +static void shutdown_ev64120_irq(unsigned int irq) +{ + int count, tmp; + + /* + * Remove PCI interrupts from the pci_int_irq list. Make sure + * that some handler was removed before decrementing max_interrupts. + */ + if (irq >= 8) { + for (count = 0; count < max_interrupts; count++) { + if (pci_int_irq[count] == irq) { + for (tmp = count; tmp < max_interrupts; tmp++) { + pci_int_irq[tmp] = + pci_int_irq[tmp + 1]; + } + } + } + max_interrupts--; + } +} + +static void end_ev64120_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_ev64120_irq(irq); +} + +static struct hw_interrupt_type ev64120_irq_type = { + "EV64120", + startup_ev64120_irq, + shutdown_ev64120_irq, + enable_ev64120_irq, + disable_ev64120_irq, + mask_and_ack_ev64120_irq, + end_ev64120_irq +}; + +/* + * galileo_irq_setup - Initializes CPU interrupts + */ +void __init init_IRQ(void) +{ + extern asmlinkage void galileo_handle_int(void); + int i; + + init_generic_irq(); + + /* Yes, how many interrupts does this beast actually have? -- Ralf */ + for (i = 0; i < NR_IRQS; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = 1; + irq_desc[i].handler = &ev64120_irq_type; + } + + /* + * Clear all of the interrupts while we change the able around a bit. + * Enable timer. Other interrupts will be enabled as they are + * registered. + */ + change_c0_status(ST0_IM | IE_IRQ2, IE_IRQ2); + + /* Sets the exception_handler array. */ + set_except_vector(0, galileo_handle_int); +} diff -Nru a/arch/mips/galileo-boards/ev64120/promcon.c b/arch/mips/galileo-boards/ev64120/promcon.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/galileo-boards/ev64120/promcon.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,70 @@ +/* + * Wrap-around code for a console using the + * SGI PROM io-routines. + * + * Copyright (c) 1999 Ulf Carlsson + * + * Derived from DECstation promcon.c + * Copyright (c) 1998 Harald Koerfgen + * Copyright (c) 2002 Ralf Baechle + */ + +#include +#include +#include +#include +#include +#include +/* +#include +*/ + +static void prom_console_write(struct console *co, const char *s, + unsigned count) +{ + extern int CONSOLE_CHANNEL; // The default serial port + unsigned i; + /* + * Now, do each character + */ + for (i = 0; i < count; i++) { + if (*s == 10) + serial_putc(CONSOLE_CHANNEL, 13); + serial_putc(CONSOLE_CHANNEL, *s++); + } +} +int prom_getchar(void) +{ + return 0; +} +static int __init prom_console_setup(struct console *co, char *options) +{ + return 0; +} + +static kdev_t prom_console_device(struct console *c) +{ + return mk_kdev(TTY_MAJOR, 64 + c->index); +} + +static struct console sercons = { + .name = "ttyS", + .write = prom_console_write, + .device = prom_console_device, + .setup = prom_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, +}; + + +/* + * Register console. + */ + +void gal_serial_console_init(void) +{ + // serial_init(); + //serial_set(115200); + + register_console(&sercons); +} diff -Nru a/arch/mips/galileo-boards/ev64120/reset.c b/arch/mips/galileo-boards/ev64120/reset.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/galileo-boards/ev64120/reset.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,45 @@ +/* + * 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) 1997, 2002 Ralf Baechle + */ +#include +#include +#include +#include +#include +#include +#include + +void galileo_machine_restart(char *command) +{ + *(volatile char *) 0xbc000000 = 0x0f; + /* + * Ouch, we're still alive ... This time we take the silver bullet ... + * ... and find that we leave the hardware in a state in which the + * kernel in the flush locks up somewhen during of after the PCI + * detection stuff. + */ + set_c0_status(ST0_BEV | ST0_ERL); + change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); + flush_cache_all(); + write_c0_wired(0); + __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); +} + +void galileo_machine_halt(void) +{ + printk(KERN_NOTICE "You can safely turn off the power\n"); + while (1) + __asm__(".set\tmips3\n\t" + "wait\n\t" + ".set\tmips0"); + +} + +void galileo_machine_power_off(void) +{ + galileo_machine_halt(); +} diff -Nru a/arch/mips/galileo-boards/ev64120/serialGT.c b/arch/mips/galileo-boards/ev64120/serialGT.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/galileo-boards/ev64120/serialGT.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,212 @@ +/* + * serialGT.c + * + * BRIEF MODULE DESCRIPTION + * Low Level Serial Port control for use + * with the Galileo EVB64120A MIPS eval board and + * its on board two channel 16552 Uart. + * + * Copyright (C) 2000 RidgeRun, Inc. + * Author: RidgeRun, Inc. + * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +// Note: +// Serial CHANNELS - 0 is the bottom connector of evb64120A. +// (The one that maps to the "B" channel of the +// board's uart) +// 1 is the top connector of evb64120A. +// (The one that maps to the "A" channel of the +// board's uart) +int DEBUG_CHANNEL = 0; // See Note Above +int CONSOLE_CHANNEL = 1; // See Note Above + +#define DUART 0xBD000000 /* Base address of Uart. */ +#define CHANNELOFFSET 0x20 /* DUART+CHANNELOFFSET gets you to the ChanA + register set of the 16552 Uart device. + DUART+0 gets you to the ChanB register set. + */ +#define DUART_DELTA 0x4 +#define FIFO_ENABLE 0x07 +#define INT_ENABLE 0x04 /* default interrupt mask */ + +#define RBR 0x00 +#define THR 0x00 +#define DLL 0x00 +#define IER 0x01 +#define DLM 0x01 +#define IIR 0x02 +#define FCR 0x02 +#define LCR 0x03 +#define MCR 0x04 +#define LSR 0x05 +#define MSR 0x06 +#define SCR 0x07 + +#define LCR_DLAB 0x80 +#define XTAL 1843200 +#define LSR_THRE 0x20 +#define LSR_BI 0x10 +#define LSR_DR 0x01 +#define MCR_LOOP 0x10 +#define ACCESS_DELAY 0x10000 + +/****************************** + Routine: + Description: + ******************************/ +int inreg(int channel, int reg) +{ + int val; + val = + *((volatile unsigned char *) DUART + + (channel * CHANNELOFFSET) + (reg * DUART_DELTA)); + return val; +} + +/****************************** + Routine: + Description: + ******************************/ +void outreg(int channel, int reg, unsigned char val) +{ + *((volatile unsigned char *) DUART + (channel * CHANNELOFFSET) + + (reg * DUART_DELTA)) = val; +} + +/****************************** + Routine: + Description: + Initialize the device driver. + ******************************/ +void serial_init(int channel) +{ + /* + * Configure active port, (CHANNELOFFSET already set.) + * + * Set 8 bits, 1 stop bit, no parity. + * + * LCR<7> 0 divisor latch access bit + * LCR<6> 0 break control (1=send break) + * LCR<5> 0 stick parity (0=space, 1=mark) + * LCR<4> 0 parity even (0=odd, 1=even) + * LCR<3> 0 parity enable (1=enabled) + * LCR<2> 0 # stop bits (0=1, 1=1.5) + * LCR<1:0> 11 bits per character(00=5, 01=6, 10=7, 11=8) + */ + outreg(channel, LCR, 0x3); + + outreg(channel, FCR, FIFO_ENABLE); /* Enable the FIFO */ + + outreg(channel, IER, INT_ENABLE); /* Enable appropriate interrupts */ +} + +/****************************** + Routine: + Description: + Set the baud rate. + ******************************/ +void serial_set(int channel, unsigned long baud) +{ + unsigned char sav_lcr; + + /* + * Enable access to the divisor latches by setting DLAB in LCR. + * + */ + sav_lcr = inreg(channel, LCR); + +#if 0 + /* + * Set baud rate + */ + outreg(channel, LCR, LCR_DLAB | sav_lcr); + // outreg(DLL,(XTAL/(16*2*(baud))-2)); + outreg(channel, DLL, XTAL / (16 * baud)); + // outreg(DLM,(XTAL/(16*2*(baud))-2)>>8); + outreg(channel, DLM, (XTAL / (16 * baud)) >> 8); +#else + /* + * Note: Set baud rate, hardcoded here for rate of 115200 + * since became unsure of above "buad rate" algorithm (??). + */ + outreg(channel, LCR, 0x83); + outreg(channel, DLM, 0x00); // See note above + outreg(channel, DLL, 0x02); // See note above. + outreg(channel, LCR, 0x03); +#endif + + /* + * Restore line control register + */ + outreg(channel, LCR, sav_lcr); +} + + +/****************************** + Routine: + Description: + Transmit a character. + ******************************/ +void serial_putc(int channel, int c) +{ + while ((inreg(channel, LSR) & LSR_THRE) == 0); + outreg(channel, THR, c); +} + +/****************************** + Routine: + Description: + Read a received character if one is + available. Return -1 otherwise. + ******************************/ +int serial_getc(int channel) +{ + if (inreg(channel, LSR) & LSR_DR) { + return inreg(channel, RBR); + } + return -1; +} + +/****************************** + Routine: + Description: + Used by embedded gdb client. (example; gdb-stub.c) + ******************************/ +char getDebugChar() +{ + int val; + while ((val = serial_getc(DEBUG_CHANNEL)) == -1); // loop until we get a character in. + return (char) val; +} + +/****************************** + Routine: + Description: + Used by embedded gdb target. (example; gdb-stub.c) + ******************************/ +void putDebugChar(char c) +{ + serial_putc(DEBUG_CHANNEL, (int) c); +} diff -Nru a/arch/mips/galileo-boards/ev64120/setup.c b/arch/mips/galileo-boards/ev64120/setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/galileo-boards/ev64120/setup.c Tue Jul 1 18:44:39 2003 @@ -0,0 +1,176 @@ +/* + * BRIEF MODULE DESCRIPTION + * Galileo Evaluation Boards - board dependent boot routines + * + * Copyright (C) 2000 RidgeRun, Inc. + * Author: RidgeRun, Inc. + * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern struct rtc_ops no_rtc_ops; + +/* These functions are used for rebooting or halting the machine*/ +extern void galileo_machine_restart(char *command); +extern void galileo_machine_halt(void); +extern void galileo_machine_power_off(void); +/* + *This structure holds pointers to the pci configuration space accesses + *and interrupts allocating routine for device over the PCI + */ +extern struct pci_ops galileo_pci_ops; + +extern unsigned long mips_machgroup; + +char arcs_cmdline[CL_SIZE] = { "console=ttyS0,115200 " + "root=/dev/nfs rw nfsroot=192.168.1.1:/mnt/disk2/fs.gal " + "ip=192.168.1.211:192.168.1.1:::gt::" +}; + +//struct eeprom_parameters eeprom_param; + +/* + * This function is added because arch/mips/mm/init.c needs it + * basically it does nothing + */ +void prom_free_prom_memory(void) +{ +} + +extern void (*board_time_init) (struct irqaction * irq); + +static unsigned char galileo_rtc_read_data(unsigned long addr) +{ + return 0; +} + +static void galileo_rtc_write_data(unsigned char data, unsigned long addr) +{ +} + +static int galileo_rtc_bcd_mode(void) +{ + return 0; +} + +struct rtc_ops galileo_rtc_ops = { + &galileo_rtc_read_data, + &galileo_rtc_write_data, + &galileo_rtc_bcd_mode +}; + +/******************************************************************** + *ev64120_setup - + * + *Initializes basic routines and structures pointers, memory size (as + *given by the bios and saves the command line. + * + * + *Inputs : + * + *Outpus : + * + *********************************************************************/ +extern void galileo_time_init(); + +void __init ev64120_setup(void) +{ + _machine_restart = galileo_machine_restart; + _machine_halt = galileo_machine_halt; + _machine_power_off = galileo_machine_power_off; + + rtc_ops = &galileo_rtc_ops; + + board_time_init = galileo_time_init; + set_io_port_base(KSEG1); + +#ifdef CONFIG_L2_L3_CACHE +#error "external cache not implemented yet" + config_register = read_c0_config(); + printk("\n\n\nchecking second level cache cp0_config = %08lx\n", + config_register); + if (config_register & CONF_SC) { // second/third level cache available + config_register = config_register & (1 << 12); + write_c0_config(config_register); + printk + ("\n\n\nchecking second level cache c0_config = %08lx\n", + config_register); + } +#endif +} + +const char *get_system_type(void) +{ + return "Galileo EV64120A"; +} + +/* + * SetUpBootInfo - + * + * This function is called at very first stages of kernel startup. + * It specifies for the kernel the evaluation board that the linux + * is running on. Then it saves the eprom parameters that holds the + * command line, memory size etc... + * + * Inputs : + * argc - nothing + * argv - holds a pointer to the eprom parameters + * envp - nothing + */ + +void SetUpBootInfo(int argc, char **argv, char **envp) +{ + mips_machgroup = MACH_GROUP_GALILEO; + mips_machtype = MACH_EV64120A; +} + +void __init prom_init(int a, char **b, char **c, int *d) +{ + mips_machgroup = MACH_GROUP_GALILEO; + add_memory_region(0, 32 << 20, BOOT_MEM_RAM); +} diff -Nru a/arch/mips/galileo-boards/ev96100/Makefile b/arch/mips/galileo-boards/ev96100/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/galileo-boards/ev96100/Makefile Tue Jul 1 18:44:39 2003 @@ -0,0 +1,11 @@ +# +# Copyright 2000 MontaVista Software Inc. +# Author: MontaVista Software, Inc. +# ppopov@mvista.com or source@mvista.com +# +# Makefile for the Galileo EV96100 board. +# + +obj-y += init.o time.o irq.o int-handler.o setup.o puts.o + +EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips/galileo-boards/ev96100/init.c b/arch/mips/galileo-boards/ev96100/init.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/galileo-boards/ev96100/init.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,174 @@ +/* + * Copyright 2000 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This file was derived from Carsten Langgaard's + * arch/mips/mips-boards/generic/generic.c + * + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +/* Environment variable */ + +typedef struct { + char *name; + char *val; +} t_env_var; + +int prom_argc; +char **prom_argv, **prom_envp; +char arcs_cmdline[CL_SIZE]; + +int init_debug = 0; + +char * __init prom_getcmdline(void) +{ + return &(arcs_cmdline[0]); +} + +void prom_free_prom_memory (void) +{ +} + +void __init prom_init_cmdline(void) +{ + char *cp; + int actr; + + actr = 1; /* Always ignore argv[0] */ + + cp = &(arcs_cmdline[0]); + while(actr < prom_argc) { + strcpy(cp, prom_argv[actr]); + cp += strlen(prom_argv[actr]); + *cp++ = ' '; + actr++; + } + if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */ + --cp; + *cp = '\0'; +} + +char *prom_getenv(char *envname) +{ + /* + * Return a pointer to the given environment variable. + */ + + t_env_var *env = (t_env_var *) prom_envp; + int i; + + i = strlen(envname); + + while (env->name) { + if (strncmp(envname, env->name, i) == 0) { + return (env->val); + } + env++; + } + return (NULL); +} + +static inline unsigned char str2hexnum(unsigned char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + return 0; /* foo */ +} + +static inline void str2eaddr(unsigned char *ea, unsigned char *str) +{ + int i; + + for (i = 0; i < 6; i++) { + unsigned char num; + + if ((*str == '.') || (*str == ':')) + str++; + num = str2hexnum(*str++) << 4; + num |= (str2hexnum(*str++)); + ea[i] = num; + } +} + +int get_ethernet_addr(char *ethernet_addr) +{ + char *ethaddr_str; + + ethaddr_str = prom_getenv("ethaddr"); + if (!ethaddr_str) { + printk("ethaddr not set in boot prom\n"); + return -1; + } + str2eaddr(ethernet_addr, ethaddr_str); + + if (init_debug > 1) { + int i; + printk("get_ethernet_addr: "); + for (i = 0; i < 5; i++) + printk("%02x:", + (unsigned char) *(ethernet_addr + i)); + printk("%02x\n", *(ethernet_addr + i)); + } + + return 0; +} + +const char *get_system_type(void) +{ + return "Galileo EV96100"; +} + +void __init prom_init(int argc, char **argv, char **envp, int *prom_vec) +{ + volatile unsigned char *uart; + char ppbuf[8]; + + prom_argc = argc; + prom_argv = argv; + prom_envp = envp; + + mips_machgroup = MACH_GROUP_GALILEO; + mips_machtype = MACH_EV96100; + + prom_init_cmdline(); + + /* 32 MB upgradable */ + add_memory_region(0, 32 << 20, BOOT_MEM_RAM); +} diff -Nru a/arch/mips/galileo-boards/ev96100/int-handler.S b/arch/mips/galileo-boards/ev96100/int-handler.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/galileo-boards/ev96100/int-handler.S Tue Jul 1 18:44:40 2003 @@ -0,0 +1,32 @@ +#include +#include +#include +#include + + .set noat + .align 5 + +NESTED(ev96100IRQ, PT_SIZE, sp) + SAVE_ALL + CLI # Important: mark KERNEL mode ! + + mfc0 t0, CP0_CAUSE # get pending interrupts + mfc0 t1, CP0_STATUS # get enabled interrupts + and t0, t1 # isolate allowed ones + + # FIX ME add R7000 extensions + andi t0,0xff00 # isolate pending bits + andi a0, t0, CAUSEF_IP7 + beq a0, zero, 1f + move a0, sp + jal mips_timer_interrupt + j ret_from_irq + +1: beqz t0, 3f # spurious interrupt + move a0, t0 + move a1, sp # delay slot + jal ev96100_cpu_irq + j ret_from_irq + +3: j spurious_interrupt + END(ev96100IRQ) diff -Nru a/arch/mips/galileo-boards/ev96100/irq.c b/arch/mips/galileo-boards/ev96100/irq.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/galileo-boards/ev96100/irq.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,133 @@ +/* + * Copyright 2000 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This file was derived from Carsten Langgaard's + * arch/mips/mips-boards/atlas/atlas_int.c. + * + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +extern void mips_timer_interrupt(int irq, struct pt_regs *regs); +extern asmlinkage void ev96100IRQ(void); + +static void disable_ev96100_irq(unsigned int irq_nr) +{ + unsigned long flags; + + local_irq_save(flags); + clear_c0_status(0x100 << irq_nr); + local_irq_restore(flags); +} + +static inline void enable_ev96100_irq(unsigned int irq_nr) +{ + unsigned long flags; + + local_irq_save(flags); + set_c0_status(0x100 << irq_nr); + local_irq_restore(flags); +} + +static unsigned int startup_ev96100_irq(unsigned int irq) +{ + enable_ev96100_irq(irq); + + return 0; /* never anything pending */ +} + +#define shutdown_ev96100_irq disable_ev96100_irq +#define mask_and_ack_ev96100_irq disable_ev96100_irq + +static void end_ev96100_irq (unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_ev96100_irq(irq); +} + +static inline unsigned int ffz8(unsigned int word) +{ + unsigned long k; + + k = 7; + if (word & 0x0fUL) { k -= 4; word <<= 4; } + if (word & 0x30UL) { k -= 2; word <<= 2; } + if (word & 0x40UL) { k -= 1; } + + return k; +} + +asmlinkage void ev96100_cpu_irq(unsigned long cause, struct pt_regs * regs) +{ + if (!(cause & 0xff00)) + return; + + do_IRQ(ffz8((cause >> 8) & 0xff), regs); +} + +static struct hw_interrupt_type ev96100_irq_type = { + "EV96100", + startup_ev96100_irq, + shutdown_ev96100_irq, + enable_ev96100_irq, + disable_ev96100_irq, + mask_and_ack_ev96100_irq, + end_ev96100_irq +}; + +void __init init_IRQ(void) +{ + int i; + + set_except_vector(0, ev96100IRQ); + init_generic_irq(); + + for (i = 0; i < 8; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = 1; + irq_desc[i].handler = &ev96100_irq_type; + } +} diff -Nru a/arch/mips/galileo-boards/ev96100/puts.c b/arch/mips/galileo-boards/ev96100/puts.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/galileo-boards/ev96100/puts.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,144 @@ + +/* + * Debug routines which directly access the uart. + */ + +#include +#include + + +//#define SERIAL_BASE EV96100_UART0_REGS_BASE +#define SERIAL_BASE 0xBD000020 +#define NS16550_BASE SERIAL_BASE + +#define SERA_CMD 0x0D +#define SERA_DATA 0x08 +//#define SERB_CMD 0x05 +#define SERB_CMD 20 +#define SERB_DATA 0x00 +#define TX_BUSY 0x20 + +#define TIMEOUT 0xffff +#undef SLOW_DOWN + +static const char digits[16] = "0123456789abcdef"; +static volatile unsigned char * const com1 = (unsigned char *)SERIAL_BASE; + + +#ifdef SLOW_DOWN +static inline void slow_down() +{ + int k; + for (k=0; k<10000; k++); +} +#else +#define slow_down() +#endif + +void +putch(const unsigned char c) +{ + unsigned char ch; + int i = 0; + + do { + ch = com1[SERB_CMD]; + slow_down(); + i++; + if (i>TIMEOUT) { + break; + } + } while (0 == (ch & TX_BUSY)); + com1[SERB_DATA] = c; +} + +void +putchar(const unsigned char c) +{ + unsigned char ch; + int i = 0; + + do { + ch = com1[SERB_CMD]; + slow_down(); + i++; + if (i>TIMEOUT) { + break; + } + } while (0 == (ch & TX_BUSY)); + com1[SERB_DATA] = c; +} + +void +puts(unsigned char *cp) +{ + unsigned char ch; + int i = 0; + + while (*cp) { + do { + ch = com1[SERB_CMD]; + slow_down(); + i++; + if (i>TIMEOUT) { + break; + } + } while (0 == (ch & TX_BUSY)); + com1[SERB_DATA] = *cp++; + } + putch('\r'); + putch('\n'); +} + +void +fputs(unsigned char *cp) +{ + unsigned char ch; + int i = 0; + + while (*cp) { + + do { + ch = com1[SERB_CMD]; + slow_down(); + i++; + if (i>TIMEOUT) { + break; + } + } while (0 == (ch & TX_BUSY)); + com1[SERB_DATA] = *cp++; + } +} + + +void +put64(uint64_t ul) +{ + int cnt; + unsigned ch; + + cnt = 16; /* 16 nibbles in a 64 bit long */ + putch('0'); + putch('x'); + do { + cnt--; + ch = (unsigned char)(ul >> cnt * 4) & 0x0F; + putch(digits[ch]); + } while (cnt > 0); +} + +void +put32(unsigned u) +{ + int cnt; + unsigned ch; + + cnt = 8; /* 8 nibbles in a 32 bit long */ + putch('0'); + putch('x'); + do { + cnt--; + ch = (unsigned char)(u >> cnt * 4) & 0x0F; + putch(digits[ch]); + } while (cnt > 0); +} diff -Nru a/arch/mips/galileo-boards/ev96100/setup.c b/arch/mips/galileo-boards/ev96100/setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/galileo-boards/ev96100/setup.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,206 @@ +/* + * BRIEF MODULE DESCRIPTION + * Galileo EV96100 setup. + * + * Copyright 2000 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This file was derived from Carsten Langgaard's + * arch/mips/mips-boards/atlas/atlas_setup.c. + * + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_PROM_CONSOLE) +extern void console_setup(char *, int *); +char serial_console[20]; +#endif + +extern char * __init prom_getcmdline(void); + +extern void mips_reboot_setup(void); +extern struct rtc_ops no_rtc_ops; +extern struct resource ioport_resource; + +unsigned char mac_0_1[12]; + +void __init ev96100_setup(void) +{ + unsigned long config = read_c0_config(); + unsigned long status = read_c0_status(); + unsigned long info = read_c0_info(); + u32 tmp; + + char *argptr; + + clear_c0_status(ST0_FR); + + if (config & 0x8) { + printk("Secondary cache is enabled\n"); + } + else { + printk("Secondary cache is disabled\n"); + } + + if (status & (1<<27)) { + printk("User-mode cache ops enabled\n"); + } + else { + printk("User-mode cache ops disabled\n"); + } + + printk("CP0 info reg: %x\n", (unsigned)info); + if (info & (1<<28)) { + printk("burst mode Scache RAMS\n"); + } + else { + printk("pipelined Scache RAMS\n"); + } + + if ((info & (0x3<<26)) >> 26 == 0) { + printk("67 percent drive strength\n"); + } + else if ((info & (0x3<<26)) >> 26 == 1) { + printk("50 percent drive strength\n"); + } + else if ((info & (0x3<<26)) >> 26 == 2) { + printk("100 percent drive strength\n"); + } + else if ((info & (0x3<<26)) >> 26 == 3) { + printk("83 percent drive strength\n"); + } + + + if ((info & (0x3<<23)) >> 23 == 0) { + printk("Write Protocol: R4000 compatible\n"); + } + else if ((info & (0x3<<23)) >> 23 == 1) { + printk("Write Protocol: Reserved\n"); + } + else if ((info & (0x3<<23)) >> 23 == 2) { + printk("Write Protocol: Pipelined\n"); + } + else if ((info & (0x3<<23)) >> 23 == 3) { + printk("Write Protocol: Write re-issue\n"); + } + + if (info & 0x1) { + printk("Atomic Enable is set\n"); + } + + argptr = prom_getcmdline(); +#ifdef CONFIG_SERIAL_CONSOLE + if (strstr(argptr, "console=") == NULL) { + argptr = prom_getcmdline(); + strcat(argptr, " console=ttyS0,115200"); + } +#endif + + rtc_ops = &no_rtc_ops; + mips_reboot_setup(); + set_io_port_base(KSEG1); + ioport_resource.start = GT_PCI_IO_BASE; + ioport_resource.end = GT_PCI_IO_BASE + 0x01ffffff; + +#ifdef CONFIG_BLK_DEV_INITRD + ROOT_DEV = Root_RAM0; +#endif + + + /* + * setup gt controller master bit so we can do config cycles + */ + + /* Clear cause register bits */ + GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT | + GT_INTRCAUSE_TARABORT0_BIT)); + /* Setup address */ + GT_WRITE(GT_PCI0_CFGADDR_OFS, + (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) | + (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | + ((PCI_COMMAND / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) | + GT_PCI0_CFGADDR_CONFIGEN_BIT); + + udelay(2); + tmp = le32_to_cpu(*(volatile u32 *)(MIPS_GT_BASE+GT_PCI0_CFGDATA_OFS)); + + tmp |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER | PCI_COMMAND_SERR); + GT_WRITE(GT_PCI0_CFGADDR_OFS, + (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) | + (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | + ((PCI_COMMAND / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) | + GT_PCI0_CFGADDR_CONFIGEN_BIT); + udelay(2); + *(volatile u32 *)(MIPS_GT_BASE+GT_PCI0_CFGDATA_OFS) = cpu_to_le32(tmp); + + /* Setup address */ + GT_WRITE(GT_PCI0_CFGADDR_OFS, + (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) | + (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | + ((PCI_COMMAND / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) | + GT_PCI0_CFGADDR_CONFIGEN_BIT); + + udelay(2); + tmp = le32_to_cpu(*(volatile u32 *)(MIPS_GT_BASE+GT_PCI0_CFGDATA_OFS)); +} + +unsigned short get_gt_devid(void) +{ + u32 gt_devid; + + /* Figure out if this is a gt96100 or gt96100A */ + GT_WRITE(GT_PCI0_CFGADDR_OFS, + (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) | + (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | + ((PCI_VENDOR_ID / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) | + GT_PCI0_CFGADDR_CONFIGEN_BIT); + + udelay(4); + gt_devid = le32_to_cpu(*(volatile u32 *) + (MIPS_GT_BASE+GT_PCI0_CFGDATA_OFS)); + return (unsigned short)(gt_devid>>16); +} diff -Nru a/arch/mips/galileo-boards/ev96100/time.c b/arch/mips/galileo-boards/ev96100/time.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/galileo-boards/ev96100/time.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,276 @@ +/* + * BRIEF MODULE DESCRIPTION + * Galileo EV96100 rtc routines. + * + * Copyright 2000 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This file was derived from Carsten Langgaard's + * arch/mips/mips-boards/atlas/atlas_rtc.c. + * + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include + +#include +#include + +#include + + +#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5) + +extern volatile unsigned long wall_jiffies; +unsigned long missed_heart_beats = 0; + +static unsigned long r4k_offset; /* Amount to increment compare reg each time */ +static unsigned long r4k_cur; /* What counter should be at next timer irq */ + +static inline void ack_r4ktimer(unsigned long newval) +{ + write_c0_compare(newval); +} + +static int set_rtc_mmss(unsigned long nowtime) +{ + /* EV96100 does not have a real time clock */ + int retval = 0; + + return retval; +} + + + +/* + * Figure out the r4k offset, the amount to increment the compare + * register for each time tick. + * Use the RTC to calculate offset. + */ +static unsigned long __init cal_r4koff(void) +{ + unsigned long count; + count = 300000000/2; + return (count / HZ); +} + + +static unsigned long __init get_mips_time(void) +{ + unsigned int year, mon, day, hour, min, sec; + + year = 2000; + mon = 10; + day = 31; + hour = 0; + min = 0; + sec = 0; + return mktime(year, mon, day, hour, min, sec); +} + + +/* + * called from start_kernel() + */ +void __init time_init(void) +{ + + unsigned int est_freq; + + r4k_offset = cal_r4koff(); + + est_freq = 2*r4k_offset*HZ; + est_freq += 5000; /* round */ + est_freq -= est_freq%10000; + printk("CPU frequency %d.%02d MHz\n", est_freq/1000000, + (est_freq%1000000)*100/1000000); + r4k_cur = (read_c0_count() + r4k_offset); + + write_c0_compare(r4k_cur); + + change_c0_status(ST0_IM, IE_IRQ5); /* FIX ME */ +} + +/* This is for machines which generate the exact clock. */ +#define USECS_PER_JIFFY (1000000/HZ) + +/* Cycle counter value at the previous timer interrupt.. */ + +static unsigned int timerhi = 0, timerlo = 0; + +/* + * FIXME: Does playing with the RP bit in c0_status interfere with this code? + */ +static unsigned long do_fast_gettimeoffset(void) +{ + u32 count; + unsigned long res, tmp; + + /* Last jiffy when do_fast_gettimeoffset() was called. */ + static unsigned long last_jiffies=0; + unsigned long quotient; + + /* + * Cached "1/(clocks per usec)*2^32" value. + * It has to be recalculated once each jiffy. + */ + static unsigned long cached_quotient=0; + + tmp = jiffies; + + quotient = cached_quotient; + + if (tmp && last_jiffies != tmp) { + last_jiffies = tmp; + __asm__(".set\tnoreorder\n\t" + ".set\tnoat\n\t" + ".set\tmips3\n\t" + "lwu\t%0,%2\n\t" + "dsll32\t$1,%1,0\n\t" + "or\t$1,$1,%0\n\t" + "ddivu\t$0,$1,%3\n\t" + "mflo\t$1\n\t" + "dsll32\t%0,%4,0\n\t" + "nop\n\t" + "ddivu\t$0,%0,$1\n\t" + "mflo\t%0\n\t" + ".set\tmips0\n\t" + ".set\tat\n\t" + ".set\treorder" + :"=&r" (quotient) + :"r" (timerhi), + "m" (timerlo), + "r" (tmp), + "r" (USECS_PER_JIFFY)); + cached_quotient = quotient; + } + + /* Get last timer tick in absolute kernel time */ + count = read_c0_count(); + + /* .. relative to previous jiffy (32 bits is enough) */ + count -= timerlo; + + __asm__("multu\t%1,%2\n\t" + "mfhi\t%0" + :"=r" (res) + :"r" (count), + "r" (quotient)); + + /* + * Due to possible jiffies inconsistencies, we need to check + * the result so that we'll get a timer that is monotonic. + */ + if (res >= USECS_PER_JIFFY) + res = USECS_PER_JIFFY-1; + + return res; +} + +/* + * This version of gettimeofday has microsecond resolution + * and better than microsecond precision on fast x86 machines with TSC. + */ +void do_gettimeofday(struct timeval *tv) +{ + unsigned long seq; + unsigned long usec, sec; + + do { + seq = read_seqbegin(&xtime_lock); + + usec = do_gettimeoffset(); + { + unsigned long lost = jiffies - wall_jiffies; + if (lost) + usec += lost * (1000000 / HZ); + } + sec = xtime.tv_sec; + usec += (xtime.tv_nsec / 1000); + } while (read_seqretry(&xtime_lock, seq)); + + while (usec >= 1000000) { + usec -= 1000000; + sec++; + } + + tv->tv_sec = sec; + tv->tv_usec = usec; +} + +void do_settimeofday(struct timeval *tv) +{ + write_seqlock_irq(&xtime_lock); + /* + * This is revolting. We need to set "xtime" correctly. However, the + * value in this location is the value at the most recent update of + * wall time. Discover what correction gettimeofday() would have + * made, and then undo it! + */ + tv->tv_usec -= do_gettimeoffset(); + tv->tv_usec -= (jiffies - wall_jiffies) * (1000000 / HZ); + + while (tv->tv_usec < 0) { + tv->tv_usec += 1000000; + tv->tv_sec--; + } + + xtime.tv_sec = tv->tv_sec; + xtime.tv_nsec = (tv->tv_usec * 1000); + time_adjust = 0; /* stop active adjtime() */ + time_status |= STA_UNSYNC; + time_maxerror = NTP_PHASE_LIMIT; + time_esterror = NTP_PHASE_LIMIT; + write_sequnlock_irq(&xtime_lock); +} + +/* + * There are a lot of conceptually broken versions of the MIPS timer interrupt + * handler floating around. This one is rather different, but the algorithm + * is probably more robust. + */ +void mips_timer_interrupt(struct pt_regs *regs) +{ + int irq = 7; /* FIX ME */ + + if (r4k_offset == 0) { + goto null; + } + + do { + kstat_cpu(0).irqs[irq]++; + do_timer(regs); + r4k_cur += r4k_offset; + ack_r4ktimer(r4k_cur); + + } while (((unsigned long)read_c0_count() + - r4k_cur) < 0x7fffffff); + return; + +null: + ack_r4ktimer(0); +} diff -Nru a/arch/mips/galileo-boards/generic/Makefile b/arch/mips/galileo-boards/generic/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/galileo-boards/generic/Makefile Tue Jul 1 18:44:40 2003 @@ -0,0 +1,25 @@ +# +# Carsten Langgaard, carstenl@mips.com +# Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. +# +# ######################################################################## +# +# This program is free software; you can distribute it and/or modify it +# under the terms of the GNU General Public License (Version 2) as +# published by the Free Software Foundation. +# +# This program is distributed in the hope it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. +# +# ####################################################################### +# +# Makefile for the MIPS boards generic routines under Linux. +# + +obj-y := reset.o diff -Nru a/arch/mips/galileo-boards/generic/reset.c b/arch/mips/galileo-boards/generic/reset.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/galileo-boards/generic/reset.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,72 @@ +/* + * BRIEF MODULE DESCRIPTION + * Galileo EV96100 reset routines. + * + * Copyright 2000 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This file was derived from Carsten Langgaard's + * arch/mips/mips-boards/generic/reset.c + * + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static void mips_machine_restart(char *command); +static void mips_machine_halt(void); + +static void mips_machine_restart(char *command) +{ + set_c0_status(ST0_BEV | ST0_ERL); + change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); + flush_cache_all(); + write_c0_wired(0); + __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); + while (1); +} + +static void mips_machine_halt(void) +{ + printk(KERN_NOTICE "You can safely turn off the power\n"); + while (1) + __asm__(".set\tmips3\n\t" + "wait\n\t" + ".set\tmips0"); +} + +void mips_reboot_setup(void) +{ + _machine_restart = mips_machine_restart; + _machine_halt = mips_machine_halt; +} diff -Nru a/arch/mips/jmr3927/common/Makefile b/arch/mips/jmr3927/common/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/jmr3927/common/Makefile Tue Jul 1 18:44:40 2003 @@ -0,0 +1,5 @@ +# +# Makefile for the common code of TOSHIBA JMR-TX3927 board +# + +obj-y += prom.o puts.o rtc_ds1742.o diff -Nru a/arch/mips/jmr3927/common/prom.c b/arch/mips/jmr3927/common/prom.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/jmr3927/common/prom.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,88 @@ +/* + * BRIEF MODULE DESCRIPTION + * PROM library initialisation code, assuming a version of + * pmon is the boot code. + * + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ahennessy@mvista.com + * + * Based on arch/mips/au1000/common/prom.c + * + * This file was derived from Carsten Langgaard's + * arch/mips/mips-boards/xx files. + * + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include + +#include + +/* #define DEBUG_CMDLINE */ + +char arcs_cmdline[CL_SIZE]; +extern int prom_argc; +extern char **prom_argv, **prom_envp; + +typedef struct +{ + char *name; +/* char *val; */ +}t_env_var; + + +char * __init prom_getcmdline(void) +{ + return &(arcs_cmdline[0]); +} + +void __init prom_init_cmdline(void) +{ + char *cp; + int actr; + + actr = 1; /* Always ignore argv[0] */ + + cp = &(arcs_cmdline[0]); + while(actr < prom_argc) { + strcpy(cp, prom_argv[actr]); + cp += strlen(prom_argv[actr]); + *cp++ = ' '; + actr++; + } + if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */ + --cp; + *cp = '\0'; +} + +int __init page_is_ram(unsigned long pagenr) +{ + return 1; +} + +void prom_free_prom_memory (void) +{ +} diff -Nru a/arch/mips/jmr3927/common/puts.c b/arch/mips/jmr3927/common/puts.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/jmr3927/common/puts.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,168 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * Low level uart routines to directly access a TX[34]927 SIO. + * + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ahennessy@mvista.com or source@mvista.com + * + * Copyright (C) 2000-2001 Toshiba Corporation + * + * Based on arch/mips/au1000/common/puts.c + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include + +#define TIMEOUT 0xffffff +#define SLOW_DOWN + +static const char digits[16] = "0123456789abcdef"; + +#ifdef SLOW_DOWN +#define slow_down() { int k; for (k=0; k<10000; k++); } +#else +#define slow_down() +#endif + +void +putch(const unsigned char c) +{ + int i = 0; + + do { + slow_down(); + i++; + if (i>TIMEOUT) { + break; + } + } while (!(tx3927_sioptr(1)->cisr & TXx927_SICISR_TXALS)); + tx3927_sioptr(1)->tfifo = c; + return; +} + +unsigned char getch(void) +{ + int i = 0; + int dicr; + char c; + + /* diable RX int. */ + dicr = tx3927_sioptr(1)->dicr; + tx3927_sioptr(1)->dicr = 0; + + do { + slow_down(); + i++; + if (i>TIMEOUT) { + break; + } + } while (tx3927_sioptr(1)->disr & TXx927_SIDISR_UVALID) + ; + c = tx3927_sioptr(1)->rfifo; + + /* clear RX int. status */ + tx3927_sioptr(1)->disr &= ~TXx927_SIDISR_RDIS; + /* enable RX int. */ + tx3927_sioptr(1)->dicr = dicr; + + return c; +} +void +do_jmr3927_led_set(char n) +{ + /* and with current leds */ + jmr3927_led_and_set(n); +} + +void +puts(unsigned char *cp) +{ + int i = 0; + + while (*cp) { + do { + slow_down(); + i++; + if (i>TIMEOUT) { + break; + } + } while (!(tx3927_sioptr(1)->cisr & TXx927_SICISR_TXALS)); + tx3927_sioptr(1)->tfifo = *cp++; + } + putch('\r'); + putch('\n'); +} + +void +fputs(unsigned char *cp) +{ + int i = 0; + + while (*cp) { + do { + slow_down(); + i++; + if (i>TIMEOUT) { + break; + } + } while (!(tx3927_sioptr(1)->cisr & TXx927_SICISR_TXALS)); + tx3927_sioptr(1)->tfifo = *cp++; + } +} + + +void +put64(uint64_t ul) +{ + int cnt; + unsigned ch; + + cnt = 16; /* 16 nibbles in a 64 bit long */ + putch('0'); + putch('x'); + do { + cnt--; + ch = (unsigned char)(ul >> cnt * 4) & 0x0F; + putch(digits[ch]); + } while (cnt > 0); +} + +void +put32(unsigned u) +{ + int cnt; + unsigned ch; + + cnt = 8; /* 8 nibbles in a 32 bit long */ + putch('0'); + putch('x'); + do { + cnt--; + ch = (unsigned char)(u >> cnt * 4) & 0x0F; + putch(digits[ch]); + } while (cnt > 0); +} diff -Nru a/arch/mips/jmr3927/common/rtc_ds1742.c b/arch/mips/jmr3927/common/rtc_ds1742.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/jmr3927/common/rtc_ds1742.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,165 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ahennessy@mvista.com + * + * arch/mips/jmr3927/common/rtc_ds1742.c + * Based on arch/mips/ddb5xxx/common/rtc_ds1386.c + * low-level RTC hookups for s for Dallas 1742 chip. + * + * Copyright (C) 2000-2001 Toshiba Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +/* + * This file exports a function, rtc_ds1386_init(), which expects an + * uncached base address as the argument. It will set the two function + * pointers expected by the MIPS generic timer code. + */ + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#define EPOCH 2000 + +static unsigned long rtc_base; + +static unsigned long +rtc_ds1742_get_time(void) +{ + unsigned int year, month, day, hour, minute, second; + unsigned int century; + + CMOS_WRITE(RTC_READ, RTC_CONTROL); + second = BCD2BIN(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK); + minute = BCD2BIN(CMOS_READ(RTC_MINUTES)); + hour = BCD2BIN(CMOS_READ(RTC_HOURS)); + day = BCD2BIN(CMOS_READ(RTC_DATE)); + month = BCD2BIN(CMOS_READ(RTC_MONTH)); + year = BCD2BIN(CMOS_READ(RTC_YEAR)); + century = BCD2BIN(CMOS_READ(RTC_CENTURY) & RTC_CENTURY_MASK); + CMOS_WRITE(0, RTC_CONTROL); + + year += century * 100; + + return mktime(year, month, day, hour, minute, second); +} +extern void to_tm(unsigned long tim, struct rtc_time * tm); + +static int +rtc_ds1742_set_time(unsigned long t) +{ + struct rtc_time tm; + u8 year, month, day, hour, minute, second; + u8 cmos_year, cmos_month, cmos_day, cmos_hour, cmos_minute, cmos_second; + int cmos_century; + + CMOS_WRITE(RTC_READ, RTC_CONTROL); + cmos_second = (u8)(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK); + cmos_minute = (u8)CMOS_READ(RTC_MINUTES); + cmos_hour = (u8)CMOS_READ(RTC_HOURS); + cmos_day = (u8)CMOS_READ(RTC_DATE); + cmos_month = (u8)CMOS_READ(RTC_MONTH); + cmos_year = (u8)CMOS_READ(RTC_YEAR); + cmos_century = CMOS_READ(RTC_CENTURY) & RTC_CENTURY_MASK; + + CMOS_WRITE(RTC_WRITE, RTC_CONTROL); + + /* convert */ + to_tm(t, &tm); + + /* check each field one by one */ + year = BIN2BCD(tm.tm_year - EPOCH); + if (year != cmos_year) { + CMOS_WRITE(year,RTC_YEAR); + } + + month = BIN2BCD(tm.tm_mon); + if (month != (cmos_month & 0x1f)) { + CMOS_WRITE((month & 0x1f) | (cmos_month & ~0x1f),RTC_MONTH); + } + + day = BIN2BCD(tm.tm_mday); + if (day != cmos_day) { + + CMOS_WRITE(day, RTC_DATE); + } + + if (cmos_hour & 0x40) { + /* 12 hour format */ + hour = 0x40; + if (tm.tm_hour > 12) { + hour |= 0x20 | (BIN2BCD(hour-12) & 0x1f); + } else { + hour |= BIN2BCD(tm.tm_hour); + } + } else { + /* 24 hour format */ + hour = BIN2BCD(tm.tm_hour) & 0x3f; + } + if (hour != cmos_hour) CMOS_WRITE(hour, RTC_HOURS); + + minute = BIN2BCD(tm.tm_min); + if (minute != cmos_minute) { + CMOS_WRITE(minute, RTC_MINUTES); + } + + second = BIN2BCD(tm.tm_sec); + if (second != cmos_second) { + CMOS_WRITE(second & RTC_SECONDS_MASK,RTC_SECONDS); + } + + /* RTC_CENTURY and RTC_CONTROL share same address... */ + CMOS_WRITE(cmos_century, RTC_CONTROL); + + return 0; +} + +void +rtc_ds1742_init(unsigned long base) +{ + u8 cmos_second; + + /* remember the base */ + rtc_base = base; + db_assert((rtc_base & 0xe0000000) == KSEG1); + + /* set the function pointers */ + rtc_get_time = rtc_ds1742_get_time; + rtc_set_time = rtc_ds1742_set_time; + + /* clear oscillator stop bit */ + CMOS_WRITE(RTC_READ, RTC_CONTROL); + cmos_second = (u8)(CMOS_READ(RTC_SECONDS) & RTC_SECONDS_MASK); + CMOS_WRITE(RTC_WRITE, RTC_CONTROL); + CMOS_WRITE(cmos_second, RTC_SECONDS); /* clear msb */ + CMOS_WRITE(0, RTC_CONTROL); +} diff -Nru a/arch/mips/jmr3927/rbhma3100/Makefile b/arch/mips/jmr3927/rbhma3100/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/jmr3927/rbhma3100/Makefile Tue Jul 1 18:44:40 2003 @@ -0,0 +1,9 @@ +# +# Makefile for TOSHIBA JMR-TX3927 board +# + +obj-y += init.o int-handler.o irq.o setup.o rtc.o +obj-$(CONFIG_RUNTIME_DEBUG) += debug.o +obj-$(CONFIG_KGDB) += kgdb_io.o + +EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips/jmr3927/rbhma3100/init.c b/arch/mips/jmr3927/rbhma3100/init.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/jmr3927/rbhma3100/init.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,80 @@ +/*********************************************************************** + * + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ahennessy@mvista.com + * + * arch/mips/jmr3927/common/init.c + * + * Copyright (C) 2000-2001 Toshiba Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + *********************************************************************** + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +int prom_argc; +char **prom_argv, **prom_envp; +extern void __init prom_init_cmdline(void); +extern char *prom_getenv(char *envname); +unsigned long mips_nofpu = 0; + +const char *get_system_type(void) +{ + return "Toshiba" +#ifdef CONFIG_TOSHIBA_JMR3927 + " JMR_TX3927" +#endif + ; +} + +extern void puts(unsigned char *cp); +int __init prom_init(int argc, char **argv, char **envp, int *prom_vec) +{ +#ifdef CONFIG_TOSHIBA_JMR3927 + /* CCFG */ + if ((tx3927_ccfgptr->ccfg & TX3927_CCFG_TLBOFF) == 0) + puts("Warning: TX3927 TLB off\n"); +#endif + prom_argc = argc; + prom_argv = argv; + prom_envp = envp; + + mips_machgroup = MACH_GROUP_TOSHIBA; + +#ifdef CONFIG_TOSHIBA_JMR3927 + mips_machtype = MACH_TOSHIBA_JMR3927; +#endif + + prom_init_cmdline(); + add_memory_region(0, JMR3927_SDRAM_SIZE, BOOT_MEM_RAM); + return 0; +} diff -Nru a/arch/mips/jmr3927/rbhma3100/int-handler.S b/arch/mips/jmr3927/rbhma3100/int-handler.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/jmr3927/rbhma3100/int-handler.S Tue Jul 1 18:44:39 2003 @@ -0,0 +1,74 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ahennessy@mvista.com + * + * Based on arch/mips/tsdb/kernel/int-handler.S + * + * Copyright (C) 2000-2001 Toshiba Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include + + /* A lot of complication here is taken away because: + * + * 1) We handle one interrupt and return, sitting in a loop + * and moving across all the pending IRQ bits in the cause + * register is _NOT_ the answer, the common case is one + * pending IRQ so optimize in that direction. + * + * 2) We need not check against bits in the status register + * IRQ mask, that would make this routine slow as hell. + * + * 3) Linux only thinks in terms of all IRQs on or all IRQs + * off, nothing in between like BSD spl() brain-damage. + * + */ + +/* Flush write buffer (needed?) + * NOTE: TX39xx performs "non-blocking load", so explicitly use the target + * register of LBU to flush immediately. + */ +#define FLUSH_WB(tmp) \ + la tmp, JMR3927_IOC_REV_ADDR; \ + lbu tmp, (tmp); \ + move tmp, zero; + + .text + .set noreorder + .set noat + .align 5 + NESTED(jmr3927_IRQ, PT_SIZE, sp) + SAVE_ALL + CLI + .set at + jal jmr3927_irc_irqdispatch + move a0, sp + FLUSH_WB(t0) + j ret_from_irq + nop + END(jmr3927_IRQ) diff -Nru a/arch/mips/jmr3927/rbhma3100/irq.c b/arch/mips/jmr3927/rbhma3100/irq.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/jmr3927/rbhma3100/irq.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,514 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ahennessy@mvista.com + * + * 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) 2000-2001 Toshiba Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#if JMR3927_IRQ_END > NR_IRQS +#error JMR3927_IRQ_END > NR_IRQS +#endif + +struct tb_irq_space* tb_irq_spaces; + +unsigned int local_bh_count[NR_CPUS]; +unsigned int local_irq_count[NR_CPUS]; + +static int jmr3927_irq_base=-1; + +#ifdef CONFIG_PCI +static int jmr3927_gen_iack(void) +{ + /* generate ACK cycle */ +#ifdef __BIG_ENDIAN + return (tx3927_pcicptr->iiadp >> 24) & 0xff; +#else + return tx3927_pcicptr->iiadp & 0xff; +#endif +} +#endif + +extern asmlinkage void jmr3927_IRQ(void); + +#define irc_dlevel 0 +#define irc_elevel 1 +static unsigned char irc_level[TX3927_NUM_IR] = { + 5, 5, 5, 5, 5, 5, /* INT[5:0] */ + 7, 7, /* SIO */ + 5, 5, 5, 0, 0, /* DMA, PIO, PCI */ + 6, 6, 6 /* TMR */ +}; + +static inline void mask_irq(unsigned int irq_nr) +{ + struct tb_irq_space* sp; + for (sp = tb_irq_spaces; sp; sp = sp->next) { + if (sp->start_irqno <= irq_nr && + irq_nr < sp->start_irqno + sp->nr_irqs) { + if (sp->mask_func) + sp->mask_func(irq_nr - sp->start_irqno, + sp->space_id); + break; + } + } +} + +static inline void unmask_irq(unsigned int irq_nr) +{ + struct tb_irq_space* sp; + for (sp = tb_irq_spaces; sp; sp = sp->next) { + if (sp->start_irqno <= irq_nr && + irq_nr < sp->start_irqno + sp->nr_irqs) { + if (sp->unmask_func) + sp->unmask_func(irq_nr - sp->start_irqno, + sp->space_id); + break; + } + } +} + +static void jmr3927_irq_disable(unsigned int irq_nr); +static void jmr3927_irq_enable(unsigned int irq_nr); + +static unsigned int jmr3927_irq_startup(unsigned int irq) +{ + jmr3927_irq_enable(irq); + return 0; +} + +#define jmr3927_irq_shutdown jmr3927_irq_disable + +static void jmr3927_irq_ack(unsigned int irq) +{ + db_assert(jmr3927_irq_base != -1); + db_assert(irq >= jmr3927_irq_base); + db_assert(irq < jmr3927_irq_base + JMR3927_NR_IRQ_IRC + JMR3927_NR_IRQ_IOC); + + if (irq == JMR3927_IRQ_IRC_TMR0) { + jmr3927_tmrptr->tisr = 0; /* ack interrupt */ + } + + jmr3927_irq_disable(irq); +} + +static void jmr3927_irq_end(unsigned int irq) +{ + db_assert(jmr3927_irq_base != -1); + db_assert(irq >= jmr3927_irq_base); + db_assert(irq < jmr3927_irq_base + JMR3927_NR_IRQ_IRC + JMR3927_NR_IRQ_IOC); + + jmr3927_irq_enable(irq); +} + +static void jmr3927_irq_disable(unsigned int irq_nr) +{ + unsigned long flags; + + db_assert(jmr3927_irq_base != -1); + db_assert(irq >= jmr3927_irq_base); + db_assert(irq < jmr3927_irq_base + JMR3927_NR_IRQ_IRC + JMR3927_NR_IRQ_IOC); + + local_irq_save(flags); + mask_irq(irq_nr); + local_irq_restore(flags); +} + +static void jmr3927_irq_enable(unsigned int irq_nr) +{ + unsigned long flags; + + db_assert(jmr3927_irq_base != -1); + db_assert(irq >= jmr3927_irq_base); + db_assert(irq < jmr3927_irq_base + JMR3927_NR_IRQ_IRC + JMR3927_NR_IRQ_IOC); + + local_irq_save(flags); + unmask_irq(irq_nr); + local_irq_restore(flags); +} + +/* + * CP0_STATUS is a thread's resource (saved/restored on context switch). + * So disable_irq/enable_irq MUST handle IOC/ISAC/IRC registers. + */ +static void mask_irq_isac(int irq_nr, int space_id) +{ + /* 0: mask */ + unsigned char imask = + jmr3927_isac_reg_in(JMR3927_ISAC_INTM_ADDR); + unsigned int bit = 1 << irq_nr; + jmr3927_isac_reg_out(imask & ~bit, JMR3927_ISAC_INTM_ADDR); + /* flush write buffer */ + (void)jmr3927_ioc_reg_in(JMR3927_IOC_REV_ADDR); +} +static void unmask_irq_isac(int irq_nr, int space_id) +{ + /* 0: mask */ + unsigned char imask = + jmr3927_isac_reg_in(JMR3927_ISAC_INTM_ADDR); + unsigned int bit = 1 << irq_nr; + jmr3927_isac_reg_out(imask | bit, JMR3927_ISAC_INTM_ADDR); + /* flush write buffer */ + (void)jmr3927_ioc_reg_in(JMR3927_IOC_REV_ADDR); +} + +static void mask_irq_ioc(int irq_nr, int space_id) +{ + /* 0: mask */ + unsigned char imask = + jmr3927_ioc_reg_in(JMR3927_IOC_INTM_ADDR); + unsigned int bit = 1 << irq_nr; + jmr3927_ioc_reg_out(imask & ~bit, JMR3927_IOC_INTM_ADDR); + /* flush write buffer */ + (void)jmr3927_ioc_reg_in(JMR3927_IOC_REV_ADDR); +} +static void unmask_irq_ioc(int irq_nr, int space_id) +{ + /* 0: mask */ + unsigned char imask = + jmr3927_ioc_reg_in(JMR3927_IOC_INTM_ADDR); + unsigned int bit = 1 << irq_nr; + jmr3927_ioc_reg_out(imask | bit, JMR3927_IOC_INTM_ADDR); + /* flush write buffer */ + (void)jmr3927_ioc_reg_in(JMR3927_IOC_REV_ADDR); +} + +static void mask_irq_irc(int irq_nr, int space_id) +{ + volatile unsigned long *ilrp = &tx3927_ircptr->ilr[irq_nr / 2]; + if (irq_nr & 1) + *ilrp = (*ilrp & 0x00ff) | (irc_dlevel << 8); + else + *ilrp = (*ilrp & 0xff00) | irc_dlevel; + /* update IRCSR */ + tx3927_ircptr->imr = 0; + tx3927_ircptr->imr = irc_elevel; +} +static void unmask_irq_irc(int irq_nr, int space_id) +{ + volatile unsigned long *ilrp = &tx3927_ircptr->ilr[irq_nr / 2]; + if (irq_nr & 1) + *ilrp = (*ilrp & 0x00ff) | (irc_level[irq_nr] << 8); + else + *ilrp = (*ilrp & 0xff00) | irc_level[irq_nr]; + /* update IRCSR */ + tx3927_ircptr->imr = 0; + tx3927_ircptr->imr = irc_elevel; +} + +struct tb_irq_space jmr3927_isac_irqspace = { + .next = NULL, + .start_irqno = JMR3927_IRQ_ISAC, + nr_irqs : JMR3927_NR_IRQ_ISAC, + .mask_func = mask_irq_isac, + .unmask_func = unmask_irq_isac, + .name = "ISAC", + .space_id = 0, + can_share : 0 +}; +struct tb_irq_space jmr3927_ioc_irqspace = { + .next = NULL, + .start_irqno = JMR3927_IRQ_IOC, + nr_irqs : JMR3927_NR_IRQ_IOC, + .mask_func = mask_irq_ioc, + .unmask_func = unmask_irq_ioc, + .name = "IOC", + .space_id = 0, + can_share : 1 +}; +struct tb_irq_space jmr3927_irc_irqspace = { + .next = NULL, + .start_irqno = JMR3927_IRQ_IRC, + nr_irqs : JMR3927_NR_IRQ_IRC, + .mask_func = mask_irq_irc, + .unmask_func = unmask_irq_irc, + .name = "on-chip", + .space_id = 0, + can_share : 0 +}; + +void jmr3927_spurious(struct pt_regs *regs) +{ +#ifdef CONFIG_TX_BRANCH_LIKELY_BUG_WORKAROUND + tx_branch_likely_bug_fixup(regs); +#endif + printk(KERN_WARNING "spurious interrupt (cause 0x%lx, pc 0x%lx, ra 0x%lx).\n", + regs->cp0_cause, regs->cp0_epc, regs->regs[31]); +} + +void jmr3927_irc_irqdispatch(struct pt_regs *regs) +{ + int irq; + +#ifdef CONFIG_TX_BRANCH_LIKELY_BUG_WORKAROUND + tx_branch_likely_bug_fixup(regs); +#endif + if ((regs->cp0_cause & CAUSEF_IP7) == 0) { +#if 0 + jmr3927_spurious(regs); +#endif + return; + } + irq = (regs->cp0_cause >> CAUSEB_IP2) & 0x0f; + + do_IRQ(irq + JMR3927_IRQ_IRC, regs); +} + +static void jmr3927_ioc_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned char istat = jmr3927_ioc_reg_in(JMR3927_IOC_INTS2_ADDR); + int i; + + for (i = 0; i < JMR3927_NR_IRQ_IOC; i++) { + if (istat & (1 << i)) { + irq = JMR3927_IRQ_IOC + i; + do_IRQ(irq, regs); + } + } +} + +static struct irqaction ioc_action = { + jmr3927_ioc_interrupt, 0, 0, "IOC", NULL, NULL, +}; + +static void jmr3927_isac_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned char istat = jmr3927_isac_reg_in(JMR3927_ISAC_INTS2_ADDR); + int i; + + for (i = 0; i < JMR3927_NR_IRQ_ISAC; i++) { + if (istat & (1 << i)) { + irq = JMR3927_IRQ_ISAC + i; + do_IRQ(irq, regs); + } + } +} + +static struct irqaction isac_action = { + jmr3927_isac_interrupt, 0, 0, "ISAC", NULL, NULL, +}; + + +static void jmr3927_isaerr_interrupt(int irq, void * dev_id, struct pt_regs * regs) +{ + printk(KERN_WARNING "ISA error interrupt (irq 0x%x).\n", irq); +} +static struct irqaction isaerr_action = { + jmr3927_isaerr_interrupt, 0, 0, "ISA error", NULL, NULL, +}; + +static void jmr3927_pcierr_interrupt(int irq, void * dev_id, struct pt_regs * regs) +{ + printk(KERN_WARNING "PCI error interrupt (irq 0x%x).\n", irq); + printk(KERN_WARNING "pcistat:%02x, lbstat:%04lx\n", + tx3927_pcicptr->pcistat, tx3927_pcicptr->lbstat); +} +static struct irqaction pcierr_action = { + jmr3927_pcierr_interrupt, 0, 0, "PCI error", NULL, NULL, +}; + +int jmr3927_ether1_irq = 0; + +void jmr3927_irq_init(u32 irq_base); +void jmr3927_irq_setup(void) +{ + /* look for io board's presence */ + int have_isac = jmr3927_have_isac(); + + /* Now, interrupt control disabled, */ + /* all IRC interrupts are masked, */ + /* all IRC interrupt mode are Low Active. */ + + if (have_isac) { + + /* ETHER1 (NE2000 compatible 10M-Ether) parameter setup */ + /* temporary enable interrupt control */ + tx3927_ircptr->cer = 1; + /* ETHER1 Int. Is High-Active. */ + if (tx3927_ircptr->ssr & (1 << 0)) + jmr3927_ether1_irq = JMR3927_IRQ_IRC_INT0; +#if 0 /* INT3 may be asserted by ether0 (even after reboot...) */ + else if (tx3927_ircptr->ssr & (1 << 3)) + jmr3927_ether1_irq = JMR3927_IRQ_IRC_INT3; +#endif + /* disable interrupt control */ + tx3927_ircptr->cer = 0; + + /* Ether1: High Active */ + if (jmr3927_ether1_irq) { + int ether1_irc = jmr3927_ether1_irq - JMR3927_IRQ_IRC; + tx3927_ircptr->cr[ether1_irc / 8] |= + TX3927_IRCR_HIGH << ((ether1_irc % 8) * 2); + } + } + + /* mask all IOC interrupts */ + jmr3927_ioc_reg_out(0, JMR3927_IOC_INTM_ADDR); + /* setup IOC interrupt mode (SOFT:High Active, Others:Low Active) */ + jmr3927_ioc_reg_out(JMR3927_IOC_INTF_SOFT, JMR3927_IOC_INTP_ADDR); + + if (have_isac) { + /* mask all ISAC interrupts */ + jmr3927_isac_reg_out(0, JMR3927_ISAC_INTM_ADDR); + /* setup ISAC interrupt mode (ISAIRQ3,ISAIRQ5:Low Active ???) */ + jmr3927_isac_reg_out(JMR3927_ISAC_INTF_IRQ3|JMR3927_ISAC_INTF_IRQ5, JMR3927_ISAC_INTP_ADDR); + } + + /* clear PCI Soft interrupts */ + jmr3927_ioc_reg_out(0, JMR3927_IOC_INTS1_ADDR); + /* clear PCI Reset interrupts */ + jmr3927_ioc_reg_out(0, JMR3927_IOC_RESET_ADDR); + + /* enable interrupt control */ + tx3927_ircptr->cer = TX3927_IRCER_ICE; + tx3927_ircptr->imr = irc_elevel; + + jmr3927_irq_init(NR_ISA_IRQS); + + set_except_vector(0, jmr3927_IRQ); + + /* setup irq space */ + add_tb_irq_space(&jmr3927_isac_irqspace); + add_tb_irq_space(&jmr3927_ioc_irqspace); + add_tb_irq_space(&jmr3927_irc_irqspace); + + /* setup IOC interrupt 1 (PCI, MODEM) */ + setup_irq(JMR3927_IRQ_IOCINT, &ioc_action); + + if (have_isac) { + setup_irq(JMR3927_IRQ_ISACINT, &isac_action); + setup_irq(JMR3927_IRQ_ISAC_ISAER, &isaerr_action); + } + +#ifdef CONFIG_PCI + setup_irq(JMR3927_IRQ_IRC_PCI, &pcierr_action); +#endif + + /* enable all CPU interrupt bits. */ + set_c0_status(ST0_IM); /* IE bit is still 0. */ +} + +void (*irq_setup)(void); +void __init init_IRQ(void) +{ + +#ifdef CONFIG_KGDB + extern void breakpoint(void); + extern void set_debug_traps(void); + + puts("Wait for gdb client connection ...\n"); + set_debug_traps(); + breakpoint(); +#endif + + /* invoke board-specific irq setup */ + irq_setup(); +} + +hw_irq_controller jmr3927_irq_controller = { + "jmr3927_irq", + jmr3927_irq_startup, + jmr3927_irq_shutdown, + jmr3927_irq_enable, + jmr3927_irq_disable, + jmr3927_irq_ack, + jmr3927_irq_end, + NULL /* no affinity stuff for UP */ +}; + +void +jmr3927_irq_init(u32 irq_base) +{ + extern irq_desc_t irq_desc[]; + u32 i; + + for (i= irq_base; i< irq_base + JMR3927_NR_IRQ_IRC + JMR3927_NR_IRQ_IOC; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = NULL; + irq_desc[i].depth = 1; + irq_desc[i].handler = &jmr3927_irq_controller; + } + + jmr3927_irq_base = irq_base; +} + +#ifdef CONFIG_TX_BRANCH_LIKELY_BUG_WORKAROUND +static int tx_branch_likely_bug_count = 0; +static int have_tx_branch_likely_bug = 0; +void tx_branch_likely_bug_fixup(struct pt_regs *regs) +{ + /* TX39/49-BUG: Under this condition, the insn in delay slot + of the branch likely insn is executed (not nullified) even + the branch condition is false. */ + if (!have_tx_branch_likely_bug) + return; + if ((regs->cp0_epc & 0xfff) == 0xffc && + KSEGX(regs->cp0_epc) != KSEG0 && + KSEGX(regs->cp0_epc) != KSEG1) { + unsigned int insn = *(unsigned int*)(regs->cp0_epc - 4); + /* beql,bnel,blezl,bgtzl */ + /* bltzl,bgezl,blezall,bgezall */ + /* bczfl, bcztl */ + if ((insn & 0xf0000000) == 0x50000000 || + (insn & 0xfc0e0000) == 0x04020000 || + (insn & 0xf3fe0000) == 0x41020000) { + regs->cp0_epc -= 4; + tx_branch_likely_bug_count++; + printk(KERN_INFO + "fix branch-likery bug in %s (insn %08x)\n", + current->comm, insn); + } + } +} +#endif diff -Nru a/arch/mips/jmr3927/rbhma3100/kgdb_io.c b/arch/mips/jmr3927/rbhma3100/kgdb_io.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/jmr3927/rbhma3100/kgdb_io.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,155 @@ +/* + * BRIEF MODULE DESCRIPTION + * Low level uart routines to directly access a TX[34]927 SIO. + * + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ahennessy@mvista.com or source@mvista.com + * + * Based on arch/mips/ddb5xxx/ddb5477/kgdb_io.c + * + * Copyright (C) 2000-2001 Toshiba Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include + +#define TIMEOUT 0xffffff +#define SLOW_DOWN + +static const char digits[16] = "0123456789abcdef"; + +#ifdef SLOW_DOWN +#define slow_down() { int k; for (k=0; k<10000; k++); } +#else +#define slow_down() +#endif + +static int remoteDebugInitialized = 0; + +int putDebugChar(unsigned char c) +{ + int i = 0; + + if (!remoteDebugInitialized) { + remoteDebugInitialized = 1; + debugInit(38400); + } + + do { + slow_down(); + i++; + if (i>TIMEOUT) { + break; + } + } while (!(tx3927_sioptr(0)->cisr & TXx927_SICISR_TXALS)); + tx3927_sioptr(0)->tfifo = c; + + return 1; +} + +unsigned char getDebugChar(void) +{ + int i = 0; + int dicr; + char c; + + if (!remoteDebugInitialized) { + remoteDebugInitialized = 1; + debugInit(38400); + } + + /* diable RX int. */ + dicr = tx3927_sioptr(0)->dicr; + tx3927_sioptr(0)->dicr = 0; + + do { + slow_down(); + i++; + if (i>TIMEOUT) { + break; + } + } while (tx3927_sioptr(0)->disr & TXx927_SIDISR_UVALID) + ; + c = tx3927_sioptr(0)->rfifo; + + /* clear RX int. status */ + tx3927_sioptr(0)->disr &= ~TXx927_SIDISR_RDIS; + /* enable RX int. */ + tx3927_sioptr(0)->dicr = dicr; + + return c; +} + +void debugInit(int baud) +{ + /* + volatile unsigned long lcr; + volatile unsigned long dicr; + volatile unsigned long disr; + volatile unsigned long cisr; + volatile unsigned long fcr; + volatile unsigned long flcr; + volatile unsigned long bgr; + volatile unsigned long tfifo; + volatile unsigned long rfifo; + */ + + tx3927_sioptr(0)->lcr = 0x020; + tx3927_sioptr(0)->dicr = 0; + tx3927_sioptr(0)->disr = 0x4100; + tx3927_sioptr(0)->cisr = 0x014; + tx3927_sioptr(0)->fcr = 0; + tx3927_sioptr(0)->flcr = 0x02; + tx3927_sioptr(0)->bgr = ((JMR3927_BASE_BAUD + baud / 2) / baud) | + TXx927_SIBGR_BCLK_T0; +#if 0 + /* + * Reset the UART. + */ + tx3927_sioptr(0)->fcr = TXx927_SIFCR_SWRST; + while (tx3927_sioptr(0)->fcr & TXx927_SIFCR_SWRST) + ; + + /* + * and set the speed of the serial port + * (currently hardwired to 9600 8N1 + */ + + tx3927_sioptr(0)->lcr = TXx927_SILCR_UMODE_8BIT | + TXx927_SILCR_USBL_1BIT | + TXx927_SILCR_SCS_IMCLK_BG; + tx3927_sioptr(0)->bgr = + ((JMR3927_BASE_BAUD + baud / 2) / baud) | + TXx927_SIBGR_BCLK_T0; + + /* HW RTS/CTS control */ + if (ser->flags & ASYNC_HAVE_CTS_LINE) + tx3927_sioptr(0)->flcr = TXx927_SIFLCR_RCS | TXx927_SIFLCR_TES | + TXx927_SIFLCR_RTSTL_MAX /* 15 */; + /* Enable RX/TX */ + tx3927_sioptr(0)->flcr &= ~(TXx927_SIFLCR_RSDE | TXx927_SIFLCR_TSDE); +#endif +} diff -Nru a/arch/mips/jmr3927/rbhma3100/rtc.c b/arch/mips/jmr3927/rbhma3100/rtc.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/jmr3927/rbhma3100/rtc.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,56 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ahennessy@mvista.com + * + * RTC routines for Dallas chip. + * + * 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) 200-2001 Toshiba Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include /* bad name... */ +#include + +static unsigned char jmr3927_rtc_read_data(unsigned long addr) +{ + return jmr3927_nvram_in(addr); +} + +static void jmr3927_rtc_write_data(unsigned char data, unsigned long addr) +{ + jmr3927_nvram_out(data, addr); +} + +static int jmr3927_rtc_bcd_mode(void) +{ + return 1; +} + +struct rtc_ops jmr3927_rtc_ops = { + &jmr3927_rtc_read_data, + &jmr3927_rtc_write_data, + &jmr3927_rtc_bcd_mode +}; diff -Nru a/arch/mips/jmr3927/rbhma3100/setup.c b/arch/mips/jmr3927/rbhma3100/setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/jmr3927/rbhma3100/setup.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,528 @@ +/*********************************************************************** + * + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ahennessy@mvista.com + * + * Based on arch/mips/ddb5xxx/ddb5477/setup.c + * + * Setup file for JMR3927. + * + * Copyright (C) 2000-2001 Toshiba Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + *********************************************************************** + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for HZ */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Tick Timer divider */ +#define JMR3927_TIMER_CCD 0 /* 1/2 */ +#define JMR3927_TIMER_CLK (JMR3927_IMCLK / (2 << JMR3927_TIMER_CCD)) + +unsigned char led_state = 0xf; + +struct { + struct resource ram0; + struct resource ram1; + struct resource pcimem; + struct resource iob; + struct resource ioc; + struct resource pciio; + struct resource jmy1394; + struct resource rom1; + struct resource rom0; + struct resource sio0; + struct resource sio1; +} jmr3927_resources = { + { "RAM0", 0, 0x01FFFFFF, IORESOURCE_MEM }, + { "RAM1", 0x02000000, 0x03FFFFFF, IORESOURCE_MEM }, + { "PCIMEM", 0x08000000, 0x07FFFFFF, IORESOURCE_MEM }, + { "IOB", 0x10000000, 0x13FFFFFF }, + { "IOC", 0x14000000, 0x14FFFFFF }, + { "PCIIO", 0x15000000, 0x15FFFFFF }, + { "JMY1394", 0x1D000000, 0x1D3FFFFF }, + { "ROM1", 0x1E000000, 0x1E3FFFFF }, + { "ROM0", 0x1FC00000, 0x1FFFFFFF }, + { "SIO0", 0xFFFEF300, 0xFFFEF3FF }, + { "SIO1", 0xFFFEF400, 0xFFFEF4FF }, +}; + +/* don't enable - see errata */ +int jmr3927_ccfg_toeon = 0; + +static inline void do_reset(void) +{ +#ifdef CONFIG_TC35815 + extern void tc35815_killall(void); + tc35815_killall(); +#endif +#if 1 /* Resetting PCI bus */ + jmr3927_ioc_reg_out(0, JMR3927_IOC_RESET_ADDR); + jmr3927_ioc_reg_out(JMR3927_IOC_RESET_PCI, JMR3927_IOC_RESET_ADDR); + (void)jmr3927_ioc_reg_in(JMR3927_IOC_RESET_ADDR); /* flush WB */ + mdelay(1); + jmr3927_ioc_reg_out(0, JMR3927_IOC_RESET_ADDR); +#endif + jmr3927_ioc_reg_out(JMR3927_IOC_RESET_CPU, JMR3927_IOC_RESET_ADDR); +} + +static void jmr3927_machine_restart(char *command) +{ + cli(); + puts("Rebooting..."); + do_reset(); +} + +static void jmr3927_machine_halt(void) +{ + puts("JMR-TX3927 halted.\n"); + while (1); +} + +static void jmr3927_machine_power_off(void) +{ + puts("JMR-TX3927 halted. Please turn off the power.\n"); + while (1); +} + +#define USE_RTC_DS1742 +#ifdef USE_RTC_DS1742 +extern void rtc_ds1742_init(unsigned long base); +#endif +static void __init jmr3927_time_init(void) +{ +#ifdef USE_RTC_DS1742 + if (jmr3927_have_nvram()) { + rtc_ds1742_init(JMR3927_IOC_NVRAMB_ADDR); + } +#endif +} + +unsigned long jmr3927_do_gettimeoffset(void); +extern int setup_irq(unsigned int irq, struct irqaction *irqaction); + +static void __init jmr3927_timer_setup(struct irqaction *irq) +{ + do_gettimeoffset = jmr3927_do_gettimeoffset; + + jmr3927_tmrptr->cpra = JMR3927_TIMER_CLK / HZ; + jmr3927_tmrptr->itmr = TXx927_TMTITMR_TIIE | TXx927_TMTITMR_TZCE; + jmr3927_tmrptr->ccdr = JMR3927_TIMER_CCD; + jmr3927_tmrptr->tcr = + TXx927_TMTCR_TCE | TXx927_TMTCR_CCDE | TXx927_TMTCR_TMODE_ITVL; + + setup_irq(JMR3927_IRQ_TICK, irq); +} + +#define USECS_PER_JIFFY (1000000/HZ) + +unsigned long jmr3927_do_gettimeoffset(void) +{ + unsigned long count; + unsigned long res = 0; + + /* MUST read TRR before TISR. */ + count = jmr3927_tmrptr->trr; + + if (jmr3927_tmrptr->tisr & TXx927_TMTISR_TIIS) { + /* timer interrupt is pending. use Max value. */ + res = USECS_PER_JIFFY - 1; + } else { + /* convert to usec */ + /* res = count / (JMR3927_TIMER_CLK / 1000000); */ + res = (count << 7) / ((JMR3927_TIMER_CLK << 7) / 1000000); + + /* + * Due to possible jiffies inconsistencies, we need to check + * the result so that we'll get a timer that is monotonic. + */ + if (res >= USECS_PER_JIFFY) + res = USECS_PER_JIFFY-1; + } + + return res; +} + + +#if defined(CONFIG_BLK_DEV_INITRD) +extern unsigned long __rd_start, __rd_end, initrd_start, initrd_end; +#endif + +//#undef DO_WRITE_THROUGH +#define DO_WRITE_THROUGH +#define DO_ENABLE_CACHE + +extern char * __init prom_getcmdline(void); +static void jmr3927_board_init(void); +extern void jmr3927_irq_setup(void); +extern struct resource pci_io_resource; +extern struct resource pci_mem_resource; + +void __init jmr3927_setup(void) +{ + extern int panic_timeout; + char *argptr; + + irq_setup = jmr3927_irq_setup; + set_io_port_base(JMR3927_PORT_BASE + JMR3927_PCIIO); + + board_time_init = jmr3927_time_init; + board_timer_setup = jmr3927_timer_setup; + + _machine_restart = jmr3927_machine_restart; + _machine_halt = jmr3927_machine_halt; + _machine_power_off = jmr3927_machine_power_off; + + /* + * IO/MEM resources. + */ + ioport_resource.start = pci_io_resource.start; + ioport_resource.end = pci_io_resource.end; + iomem_resource.start = pci_mem_resource.start; + iomem_resource.end = pci_mem_resource.end; + + /* Reboot on panic */ + panic_timeout = 180; + + { + unsigned int conf; + conf = read_c0_conf(); + } + +#if 1 + /* cache setup */ + { + unsigned int conf; +#ifdef DO_ENABLE_CACHE + int mips_ic_disable = 0, mips_dc_disable = 0; +#else + int mips_ic_disable = 1, mips_dc_disable = 1; +#endif +#ifdef DO_WRITE_THROUGH + int mips_config_cwfon = 0; + int mips_config_wbon = 0; +#else + int mips_config_cwfon = 1; + int mips_config_wbon = 1; +#endif + + conf = read_c0_conf(); + conf &= ~(TX39_CONF_ICE | TX39_CONF_DCE | TX39_CONF_WBON | TX39_CONF_CWFON); + conf |= mips_ic_disable ? 0 : TX39_CONF_ICE; + conf |= mips_dc_disable ? 0 : TX39_CONF_DCE; + conf |= mips_config_wbon ? TX39_CONF_WBON : 0; + conf |= mips_config_cwfon ? TX39_CONF_CWFON : 0; + + write_c0_conf(conf); + write_c0_cache(0); + } +#endif + + /* initialize board */ + jmr3927_board_init(); + + argptr = prom_getcmdline(); + + if ((argptr = strstr(argptr, "toeon")) != NULL) { + jmr3927_ccfg_toeon = 1; + } + argptr = prom_getcmdline(); + if ((argptr = strstr(argptr, "ip=")) == NULL) { + argptr = prom_getcmdline(); + strcat(argptr, " ip=bootp"); + } + +#ifdef CONFIG_TXX927_SERIAL_CONSOLE + argptr = prom_getcmdline(); + if ((argptr = strstr(argptr, "console=")) == NULL) { + argptr = prom_getcmdline(); + strcat(argptr, " console=ttyS1,115200"); + } +#endif +} + + +static void tx3927_setup(void); + +#ifdef CONFIG_PCI +unsigned long mips_pci_io_base; +unsigned long mips_pci_io_size; +unsigned long mips_pci_mem_base; +unsigned long mips_pci_mem_size; +/* for legacy I/O, PCI I/O PCI Bus address must be 0 */ +unsigned long mips_pci_io_pciaddr = 0; +#endif + +extern struct rtc_ops *rtc_ops; +extern struct rtc_ops jmr3927_rtc_ops; + +static void __init jmr3927_board_init(void) +{ + char *argptr; + +#ifdef CONFIG_PCI + mips_pci_io_base = JMR3927_PCIIO; + mips_pci_io_size = JMR3927_PCIIO_SIZE; + mips_pci_mem_base = JMR3927_PCIMEM; + mips_pci_mem_size = JMR3927_PCIMEM_SIZE; +#endif + + tx3927_setup(); + +#ifdef CONFIG_VT + conswitchp = &dummy_con; +#endif + + if (jmr3927_have_isac()) { + +#ifdef CONFIG_FB_E1355 + argptr = prom_getcmdline(); + if ((argptr = strstr(argptr, "video=")) == NULL) { + argptr = prom_getcmdline(); + strcat(argptr, " video=e1355fb:crt16h"); + } +#endif + +#ifdef CONFIG_BLK_DEV_IDE + /* overrides PCI-IDE */ +#endif + } +#ifdef USE_RTC_DS1742 + if (jmr3927_have_nvram()) { + rtc_ops = &jmr3927_rtc_ops; + } +#endif + + /* SIO0 DTR on */ + jmr3927_ioc_reg_out(0, JMR3927_IOC_DTR_ADDR); + + jmr3927_led_set(0); + + + if (jmr3927_have_isac()) + jmr3927_io_led_set(0); + printk("JMR-TX3927 (Rev %d) --- IOC(Rev %d) DIPSW:%d,%d,%d,%d\n", + jmr3927_ioc_reg_in(JMR3927_IOC_BREV_ADDR) & JMR3927_REV_MASK, + jmr3927_ioc_reg_in(JMR3927_IOC_REV_ADDR) & JMR3927_REV_MASK, + jmr3927_dipsw1(), jmr3927_dipsw2(), + jmr3927_dipsw3(), jmr3927_dipsw4()); + if (jmr3927_have_isac()) + printk("JMI-3927IO2 --- ISAC(Rev %d) DIPSW:%01x\n", + jmr3927_isac_reg_in(JMR3927_ISAC_REV_ADDR) & JMR3927_REV_MASK, + jmr3927_io_dipsw()); +} + +static void __init tx3927_setup(void) +{ + int i; + + /* SDRAMC are configured by PROM */ + + /* ROMC */ + tx3927_romcptr->cr[1] = JMR3927_ROMCE1 | 0x00030048; + tx3927_romcptr->cr[2] = JMR3927_ROMCE2 | 0x000064c8; + tx3927_romcptr->cr[3] = JMR3927_ROMCE3 | 0x0003f698; + tx3927_romcptr->cr[5] = JMR3927_ROMCE5 | 0x0000f218; + + /* CCFG */ + /* enable Timeout BusError */ + if (jmr3927_ccfg_toeon) + tx3927_ccfgptr->ccfg |= TX3927_CCFG_TOE; + + /* clear BusErrorOnWrite flag */ + tx3927_ccfgptr->ccfg &= ~TX3927_CCFG_BEOW; + /* Disable PCI snoop */ + tx3927_ccfgptr->ccfg &= ~TX3927_CCFG_PSNP; + +#ifdef DO_WRITE_THROUGH + /* Enable PCI SNOOP - with write through only */ + tx3927_ccfgptr->ccfg |= TX3927_CCFG_PSNP; +#endif + + /* Pin selection */ + tx3927_ccfgptr->pcfg &= ~TX3927_PCFG_SELALL; + tx3927_ccfgptr->pcfg |= + TX3927_PCFG_SELSIOC(0) | TX3927_PCFG_SELSIO_ALL | + (TX3927_PCFG_SELDMA_ALL & ~TX3927_PCFG_SELDMA(1)); + + printk("TX3927 -- CRIR:%08lx CCFG:%08lx PCFG:%08lx\n", + tx3927_ccfgptr->crir, + tx3927_ccfgptr->ccfg, tx3927_ccfgptr->pcfg); + + /* IRC */ + /* disable interrupt control */ + tx3927_ircptr->cer = 0; + /* mask all IRC interrupts */ + tx3927_ircptr->imr = 0; + for (i = 0; i < TX3927_NUM_IR / 2; i++) { + tx3927_ircptr->ilr[i] = 0; + } + /* setup IRC interrupt mode (Low Active) */ + for (i = 0; i < TX3927_NUM_IR / 8; i++) { + tx3927_ircptr->cr[i] = 0; + } + + /* TMR */ + /* disable all timers */ + for (i = 0; i < TX3927_NR_TMR; i++) { + tx3927_tmrptr(i)->tcr = TXx927_TMTCR_CRE; + tx3927_tmrptr(i)->tisr = 0; + tx3927_tmrptr(i)->cpra = 0xffffffff; + tx3927_tmrptr(i)->itmr = 0; + tx3927_tmrptr(i)->ccdr = 0; + tx3927_tmrptr(i)->pgmr = 0; + } + + /* DMA */ + tx3927_dmaptr->mcr = 0; + for (i = 0; i < sizeof(tx3927_dmaptr->ch) / sizeof(tx3927_dmaptr->ch[0]); i++) { + /* reset channel */ + tx3927_dmaptr->ch[i].ccr = TX3927_DMA_CCR_CHRST; + tx3927_dmaptr->ch[i].ccr = 0; + } + /* enable DMA */ +#ifdef __BIG_ENDIAN + tx3927_dmaptr->mcr = TX3927_DMA_MCR_MSTEN; +#else + tx3927_dmaptr->mcr = TX3927_DMA_MCR_MSTEN | TX3927_DMA_MCR_LE; +#endif + +#ifdef CONFIG_PCI + /* PCIC */ + printk("TX3927 PCIC -- DID:%04x VID:%04x RID:%02x Arbiter:", + tx3927_pcicptr->did, tx3927_pcicptr->vid, + tx3927_pcicptr->rid); + if (!(tx3927_ccfgptr->ccfg & TX3927_CCFG_PCIXARB)) { + printk("External\n"); + /* XXX */ + } else { + printk("Internal\n"); + + /* Reset PCI Bus */ + jmr3927_ioc_reg_out(0, JMR3927_IOC_RESET_ADDR); + udelay(100); + jmr3927_ioc_reg_out(JMR3927_IOC_RESET_PCI, + JMR3927_IOC_RESET_ADDR); + udelay(100); + jmr3927_ioc_reg_out(0, JMR3927_IOC_RESET_ADDR); + + + /* Disable External PCI Config. Access */ + tx3927_pcicptr->lbc = TX3927_PCIC_LBC_EPCAD; +#ifdef __BIG_ENDIAN + tx3927_pcicptr->lbc |= TX3927_PCIC_LBC_IBSE | + TX3927_PCIC_LBC_TIBSE | + TX3927_PCIC_LBC_TMFBSE | TX3927_PCIC_LBC_MSDSE; +#endif + /* LB->PCI mappings */ + tx3927_pcicptr->iomas = ~(mips_pci_io_size - 1); + tx3927_pcicptr->ilbioma = mips_pci_io_base; + tx3927_pcicptr->ipbioma = mips_pci_io_pciaddr; + tx3927_pcicptr->mmas = ~(mips_pci_mem_size - 1); + tx3927_pcicptr->ilbmma = mips_pci_mem_base; + tx3927_pcicptr->ipbmma = mips_pci_mem_base; + /* PCI->LB mappings */ + tx3927_pcicptr->iobas = 0xffffffff; + tx3927_pcicptr->ioba = 0; + tx3927_pcicptr->tlbioma = 0; + tx3927_pcicptr->mbas = ~(mips_pci_mem_size - 1); + tx3927_pcicptr->mba = 0; + tx3927_pcicptr->tlbmma = 0; +#ifndef JMR3927_INIT_INDIRECT_PCI + /* Enable Direct mapping Address Space Decoder */ + tx3927_pcicptr->lbc |= TX3927_PCIC_LBC_ILMDE | TX3927_PCIC_LBC_ILIDE; +#endif + + /* Clear All Local Bus Status */ + tx3927_pcicptr->lbstat = TX3927_PCIC_LBIM_ALL; + /* Enable All Local Bus Interrupts */ + tx3927_pcicptr->lbim = TX3927_PCIC_LBIM_ALL; + /* Clear All PCI Status Error */ + tx3927_pcicptr->pcistat = TX3927_PCIC_PCISTATIM_ALL; + /* Enable All PCI Status Error Interrupts */ + tx3927_pcicptr->pcistatim = TX3927_PCIC_PCISTATIM_ALL; + + /* PCIC Int => IRC IRQ10 */ + tx3927_pcicptr->il = TX3927_IR_PCI; +#if 1 + /* Target Control (per errata) */ + tx3927_pcicptr->tc = TX3927_PCIC_TC_OF8E | TX3927_PCIC_TC_IF8E; +#endif + + /* Enable Bus Arbiter */ +#if 0 + tx3927_pcicptr->req_trace = 0x73737373; +#endif + tx3927_pcicptr->pbapmc = TX3927_PCIC_PBAPMC_PBAEN; + + tx3927_pcicptr->pcicmd = PCI_COMMAND_MASTER | + PCI_COMMAND_MEMORY | +#if 1 + PCI_COMMAND_IO | +#endif + PCI_COMMAND_PARITY | PCI_COMMAND_SERR; + } +#endif /* CONFIG_PCI */ + + /* PIO */ + /* PIO[15:12] connected to LEDs */ + tx3927_pioptr->dir = 0x0000f000; + tx3927_pioptr->maskcpu = 0; + tx3927_pioptr->maskext = 0; + { + unsigned int conf; + + conf = read_c0_conf(); + if (!(conf & TX39_CONF_ICE)) + printk("TX3927 I-Cache disabled.\n"); + if (!(conf & TX39_CONF_DCE)) + printk("TX3927 D-Cache disabled.\n"); + else if (!(conf & TX39_CONF_WBON)) + printk("TX3927 D-Cache WriteThrough.\n"); + else if (!(conf & TX39_CONF_CWFON)) + printk("TX3927 D-Cache WriteBack.\n"); + else + printk("TX3927 D-Cache WriteBack (CWF) .\n"); + } +} diff -Nru a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile --- a/arch/mips/kernel/Makefile Tue Jul 1 18:44:34 2003 +++ b/arch/mips/kernel/Makefile Tue Jul 1 18:44:34 2003 @@ -2,45 +2,45 @@ # Makefile for the Linux/MIPS kernel. # -# EXTRA_AFLAGS = -mips3 -mcpu=r4000 # not used? +extra-y := head.o init_task.o + +obj-y += branch.o cpu-probe.o process.o signal.o entry.o traps.o \ + ptrace.o irq.o reset.o semaphore.o setup.o syscall.o \ + sysmips.o ipc.o scall_o32.o time.o unaligned.o -extra-y := head.o init_task.o -obj-y += branch.o process.o signal.o entry.o \ - traps.o ptrace.o vm86.o ioport.o reset.o \ - semaphore.o setup.o syscall.o sysmips.o \ - ipc.o scall_o32.o unaligned.o obj-$(CONFIG_MODULES) += mips_ksyms.o -ifdef CONFIG_CPU_R3000 -obj-y += r2300_misc.o r2300_fpu.o r2300_switch.o -else -obj-y += r4k_misc.o r4k_switch.o -ifdef CONFIG_CPU_R6000 -obj-y += r6000_fpu.o -else -obj-y += r4k_fpu.o -endif -endif +obj-$(CONFIG_CPU_R3000) += r2300_fpu.o r2300_switch.o +obj-$(CONFIG_CPU_TX39XX) += r2300_fpu.o r2300_switch.o +obj-$(CONFIG_CPU_TX49XX) += r4k_fpu.o r4k_switch.o +obj-$(CONFIG_CPU_R4000) += r4k_fpu.o r4k_switch.o +obj-$(CONFIG_CPU_VR41XX) += r4k_fpu.o r4k_switch.o +obj-$(CONFIG_CPU_R4300) += r4k_fpu.o r4k_switch.o +obj-$(CONFIG_CPU_R4X00) += r4k_fpu.o r4k_switch.o +obj-$(CONFIG_CPU_R5000) += r4k_fpu.o r4k_switch.o +obj-$(CONFIG_CPU_R5432) += r4k_fpu.o r4k_switch.o +obj-$(CONFIG_CPU_RM7000) += r4k_fpu.o r4k_switch.o +obj-$(CONFIG_CPU_NEVADA) += r4k_fpu.o r4k_switch.o +obj-$(CONFIG_CPU_R10000) += r4k_fpu.o r4k_switch.o +obj-$(CONFIG_CPU_SB1) += r4k_fpu.o r4k_switch.o +obj-$(CONFIG_CPU_MIPS32) += r4k_fpu.o r4k_switch.o +obj-$(CONFIG_CPU_MIPS64) += r4k_fpu.o r4k_switch.o +obj-$(CONFIG_CPU_R6000) += r6000_fpu.o r4k_switch.o obj-$(CONFIG_SMP) += smp.o -# Old style irq support, going to die in 2.5. -obj-$(CONFIG_NEW_IRQ) += irq.o -obj-$(CONFIG_ROTTEN_IRQ) += old-irq.o obj-$(CONFIG_I8259) += i8259.o - -# transition from old time.c to new time.c -# some boards uses old-time.c, some use time.c, and some use their own ones -obj-$(CONFIG_OLD_TIME_C) += old-time.o -obj-$(CONFIG_NEW_TIME_C) += time.o +obj-$(CONFIG_IRQ_CPU) += irq_cpu.o obj-$(CONFIG_BINFMT_IRIX) += irixelf.o irixioctl.o irixsig.o sysirix.o \ irixinv.o -obj-$(CONFIG_REMOTE_DEBUG) += gdb-low.o gdb-stub.o -obj-$(CONFIG_PCI) += pci-dma.o +obj-$(CONFIG_KGDB) += gdb-low.o gdb-stub.o obj-$(CONFIG_PROC_FS) += proc.o -ifdef CONFIG_PCI -obj-$(CONFIG_NEW_PCI) += pci.o -obj-$(CONFIG_PCI_AUTO) += pci_auto.o +ifndef CONFIG_MAPPED_PCI_IO +obj-y += pci-dma.o endif + +obj-$(CONFIG_MODULES) += module.o + +EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c --- a/arch/mips/kernel/branch.c Tue Jul 1 18:44:35 2003 +++ b/arch/mips/kernel/branch.c Tue Jul 1 18:44:35 2003 @@ -16,7 +16,6 @@ #include #include #include -#include #include /* @@ -164,10 +163,10 @@ * And now the FPA/cp1 branch instructions. */ case cop1_op: - if(!(mips_cpu.options & MIPS_CPU_FPU)) + if (!cpu_has_fpu) fcr31 = current->thread.fpu.soft.sr; else - asm ("cfc1\t%0,$31":"=r" (fcr31)); + asm volatile("cfc1\t%0,$31" : "=r" (fcr31)); bit = (insn.i_format.rt >> 2); bit += (bit != 0); bit += 23; diff -Nru a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/kernel/cpu-probe.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,509 @@ +#include +#include +#include +#include +#include +#include +#include + +/* + * Not all of the MIPS CPUs have the "wait" instruction available. Moreover, + * the implementation of the "wait" feature differs between CPU families. This + * points to the function that implements CPU specific wait. + * The wait instruction stops the pipeline and reduces the power consumption of + * the CPU very much. + */ +void (*cpu_wait)(void) = NULL; + +static void r3081_wait(void) +{ + unsigned long cfg = read_c0_conf(); + write_c0_conf(cfg | R30XX_CONF_HALT); +} + +static void r39xx_wait(void) +{ + unsigned long cfg = read_c0_conf(); + write_c0_conf(cfg | TX39_CONF_HALT); +} + +static void r4k_wait(void) +{ + __asm__(".set\tmips3\n\t" + "wait\n\t" + ".set\tmips0"); +} + +void au1k_wait(void) +{ +#ifdef CONFIG_PM + /* using the wait instruction makes CP0 counter unusable */ + __asm__(".set\tmips3\n\t" + "wait\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + ".set\tmips0"); +#else + __asm__("nop\n\t" + "nop"); +#endif +} + +static inline void check_wait(void) +{ + struct cpuinfo_mips *c = ¤t_cpu_data; + + printk("Checking for 'wait' instruction... "); + switch (c->cputype) { + case CPU_R3081: + case CPU_R3081E: + cpu_wait = r3081_wait; + printk(" available.\n"); + break; + case CPU_TX3927: + cpu_wait = r39xx_wait; + printk(" available.\n"); + break; + case CPU_R4200: +/* case CPU_R4300: */ + case CPU_R4600: + case CPU_R4640: + case CPU_R4650: + case CPU_R4700: + case CPU_R5000: + case CPU_NEVADA: + case CPU_RM7000: + case CPU_TX49XX: + case CPU_4KC: + case CPU_4KEC: + case CPU_4KSC: + case CPU_5KC: +/* case CPU_20KC:*/ + cpu_wait = r4k_wait; + printk(" available.\n"); + break; + case CPU_AU1000: + case CPU_AU1100: + case CPU_AU1500: + cpu_wait = au1k_wait; + printk(" available.\n"); + break; + default: + printk(" unavailable.\n"); + break; + } +} + +void __init check_bugs(void) +{ + check_wait(); +} + +/* + * Probe whether cpu has config register by trying to play with + * alternate cache bit and see whether it matters. + * It's used by cpu_probe to distinguish between R3000A and R3081. + */ +static inline int cpu_has_confreg(void) +{ +#ifdef CONFIG_CPU_R3000 + extern unsigned long r3k_cache_size(unsigned long); + unsigned long size1, size2; + unsigned long cfg = read_c0_conf(); + + size1 = r3k_cache_size(ST0_ISC); + write_c0_conf(cfg ^ R30XX_CONF_AC); + size2 = r3k_cache_size(ST0_ISC); + write_c0_conf(cfg); + return size1 != size2; +#else + return 0; +#endif +} + +/* + * Get the FPU Implementation/Revision. + */ +static inline unsigned long cpu_get_fpu_id(void) +{ + unsigned long tmp, fpu_id; + + tmp = read_c0_status(); + __enable_fpu(); + fpu_id = read_32bit_cp1_register(CP1_REVISION); + write_c0_status(tmp); + return fpu_id; +} + +/* + * Check the CPU has an FPU the official way. + */ +static inline int __cpu_has_fpu(void) +{ + return ((cpu_get_fpu_id() & 0xff00) != FPIR_IMP_NONE); +} + +#define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4KTLB \ + | MIPS_CPU_COUNTER | MIPS_CPU_CACHE_CDEX) + +__init void cpu_probe(void) +{ + struct cpuinfo_mips *c = ¤t_cpu_data; + unsigned long config0 = read_c0_config(); + unsigned long config1; + + c->processor_id = PRID_IMP_UNKNOWN; + c->fpu_id = FPIR_IMP_NONE; + c->cputype = CPU_UNKNOWN; + + if (config0 & (1 << 31)) { + /* MIPS32 or MIPS64 compliant CPU. Read Config 1 register. */ + c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX | + MIPS_CPU_4KTLB | MIPS_CPU_COUNTER | MIPS_CPU_DIVEC | + MIPS_CPU_LLSC; + config1 = read_c0_config1(); + if (config1 & (1 << 3)) + c->options |= MIPS_CPU_WATCH; + if (config1 & (1 << 2)) + c->options |= MIPS_CPU_MIPS16; + if (config1 & (1 << 1)) + c->options |= MIPS_CPU_EJTAG; + if (config1 & 1) { + c->options |= MIPS_CPU_FPU; + c->options |= MIPS_CPU_32FPR; + } + c->scache.flags = MIPS_CACHE_NOT_PRESENT; + + c->tlbsize = ((config1 >> 25) & 0x3f) + 1; + } + + c->processor_id = read_c0_prid(); + switch (c->processor_id & 0xff0000) { + case PRID_COMP_LEGACY: + switch (c->processor_id & 0xff00) { + case PRID_IMP_R2000: + c->cputype = CPU_R2000; + c->isa_level = MIPS_CPU_ISA_I; + c->options = MIPS_CPU_TLB | MIPS_CPU_NOFPUEX | + MIPS_CPU_LLSC; + if (__cpu_has_fpu()) + c->options |= MIPS_CPU_FPU; + c->tlbsize = 64; + break; + case PRID_IMP_R3000: + if ((c->processor_id & 0xff) == PRID_REV_R3000A) + if (cpu_has_confreg()) + c->cputype = CPU_R3081E; + else + c->cputype = CPU_R3000A; + else + c->cputype = CPU_R3000; + c->isa_level = MIPS_CPU_ISA_I; + c->options = MIPS_CPU_TLB | MIPS_CPU_NOFPUEX | + MIPS_CPU_LLSC; + if (__cpu_has_fpu()) + c->options |= MIPS_CPU_FPU; + c->tlbsize = 64; + break; + case PRID_IMP_R4000: + if ((c->processor_id & 0xff) >= PRID_REV_R4400) + c->cputype = CPU_R4400SC; + else + c->cputype = CPU_R4000SC; + c->isa_level = MIPS_CPU_ISA_III; + c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_WATCH | MIPS_CPU_VCE | + MIPS_CPU_LLSC; + c->tlbsize = 48; + break; + case PRID_IMP_VR41XX: + switch (c->processor_id & 0xf0) { +#ifndef CONFIG_VR4181 + case PRID_REV_VR4111: + c->cputype = CPU_VR4111; + break; +#else + case PRID_REV_VR4181: + c->cputype = CPU_VR4181; + break; +#endif + case PRID_REV_VR4121: + c->cputype = CPU_VR4121; + break; + case PRID_REV_VR4122: + if ((c->processor_id & 0xf) < 0x3) + c->cputype = CPU_VR4122; + else + c->cputype = CPU_VR4181A; + break; + case PRID_REV_VR4131: + c->cputype = CPU_VR4131; + break; + default: + printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n"); + c->cputype = CPU_VR41XX; + break; + } + c->isa_level = MIPS_CPU_ISA_III; + c->options = R4K_OPTS; + c->tlbsize = 32; + break; + case PRID_IMP_R4300: + c->cputype = CPU_R4300; + c->isa_level = MIPS_CPU_ISA_III; + c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_LLSC; + c->tlbsize = 32; + break; + case PRID_IMP_R4600: + c->cputype = CPU_R4600; + c->isa_level = MIPS_CPU_ISA_III; + c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_LLSC; + c->tlbsize = 48; + break; + #if 0 + case PRID_IMP_R4650: + /* + * This processor doesn't have an MMU, so it's not + * "real easy" to run Linux on it. It is left purely + * for documentation. Commented out because it shares + * it's c0_prid id number with the TX3900. + */ + c->cputype = CPU_R4650; + c->isa_level = MIPS_CPU_ISA_III; + c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_LLSC; + c->tlbsize = 48; + break; + #endif + case PRID_IMP_TX39: + c->isa_level = MIPS_CPU_ISA_I; + c->options = MIPS_CPU_TLB; + + if ((c->processor_id & 0xf0) == + (PRID_REV_TX3927 & 0xf0)) { + c->cputype = CPU_TX3927; + c->tlbsize = 64; + } else { + switch (c->processor_id & 0xff) { + case PRID_REV_TX3912: + c->cputype = CPU_TX3912; + c->tlbsize = 32; + break; + case PRID_REV_TX3922: + c->cputype = CPU_TX3922; + c->tlbsize = 64; + break; + default: + c->cputype = CPU_UNKNOWN; + break; + } + } + break; + case PRID_IMP_R4700: + c->cputype = CPU_R4700; + c->isa_level = MIPS_CPU_ISA_III; + c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_LLSC; + c->tlbsize = 48; + break; + case PRID_IMP_TX49: + c->cputype = CPU_TX49XX; + c->isa_level = MIPS_CPU_ISA_III; + c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_LLSC; + c->tlbsize = 48; + break; + case PRID_IMP_R5000: + c->cputype = CPU_R5000; + c->isa_level = MIPS_CPU_ISA_IV; + c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_LLSC; + c->tlbsize = 48; + break; + case PRID_IMP_R5432: + c->cputype = CPU_R5432; + c->isa_level = MIPS_CPU_ISA_IV; + c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_WATCH | MIPS_CPU_LLSC; + c->tlbsize = 48; + break; + case PRID_IMP_R5500: + c->cputype = CPU_R5500; + c->isa_level = MIPS_CPU_ISA_IV; + c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_WATCH | MIPS_CPU_LLSC; + c->tlbsize = 48; + break; + case PRID_IMP_NEVADA: + c->cputype = CPU_NEVADA; + c->isa_level = MIPS_CPU_ISA_IV; + c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_DIVEC | MIPS_CPU_LLSC; + c->tlbsize = 48; + break; + case PRID_IMP_R6000: + c->cputype = CPU_R6000; + c->isa_level = MIPS_CPU_ISA_II; + c->options = MIPS_CPU_TLB | MIPS_CPU_FPU | + MIPS_CPU_LLSC; + c->tlbsize = 32; + break; + case PRID_IMP_R6000A: + c->cputype = CPU_R6000A; + c->isa_level = MIPS_CPU_ISA_II; + c->options = MIPS_CPU_TLB | MIPS_CPU_FPU | + MIPS_CPU_LLSC; + c->tlbsize = 32; + break; + case PRID_IMP_RM7000: + c->cputype = CPU_RM7000; + c->isa_level = MIPS_CPU_ISA_IV; + c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_LLSC; + /* + * Undocumented RM7000: Bit 29 in the info register of + * the RM7000 v2.0 indicates if the TLB has 48 or 64 + * entries. + * + * 29 1 => 64 entry JTLB + * 0 => 48 entry JTLB + */ + c->tlbsize = (read_c0_info() & (1 << 29)) ? 64 : 48; + break; + case PRID_IMP_R8000: + c->cputype = CPU_R8000; + c->isa_level = MIPS_CPU_ISA_IV; + c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX | + MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_LLSC; + c->tlbsize = 384; /* has weird TLB: 3-way x 128 */ + break; + case PRID_IMP_R10000: + c->cputype = CPU_R10000; + c->isa_level = MIPS_CPU_ISA_IV; + c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX | + MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_COUNTER | MIPS_CPU_WATCH | + MIPS_CPU_LLSC; + c->tlbsize = 64; + break; + case PRID_IMP_R12000: + c->cputype = CPU_R12000; + c->isa_level = MIPS_CPU_ISA_IV; + c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX | + MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_COUNTER | MIPS_CPU_WATCH | + MIPS_CPU_LLSC; + c->tlbsize = 64; + break; + default: + c->cputype = CPU_UNKNOWN; + break; + } + break; + case PRID_COMP_MIPS: + switch (c->processor_id & 0xff00) { + case PRID_IMP_4KC: + c->cputype = CPU_4KC; + c->isa_level = MIPS_CPU_ISA_M32; + break; + case PRID_IMP_4KEC: + c->cputype = CPU_4KEC; + c->isa_level = MIPS_CPU_ISA_M32; + break; + case PRID_IMP_4KSC: + c->cputype = CPU_4KSC; + c->isa_level = MIPS_CPU_ISA_M32; + break; + case PRID_IMP_5KC: + c->cputype = CPU_5KC; + c->isa_level = MIPS_CPU_ISA_M64; + break; + case PRID_IMP_20KC: + c->cputype = CPU_20KC; + c->isa_level = MIPS_CPU_ISA_M64; + break; + default: + c->cputype = CPU_UNKNOWN; + break; + } + break; + case PRID_COMP_ALCHEMY: + switch (c->processor_id & 0xff00) { + case PRID_IMP_AU1_REV1: + case PRID_IMP_AU1_REV2: + switch ((c->processor_id >> 24) & 0xff) { + case 0: + c->cputype = CPU_AU1000; + break; + case 1: + c->cputype = CPU_AU1500; + break; + case 2: + c->cputype = CPU_AU1100; + break; + default: + panic("Unknown Au Core!"); + break; + } + c->isa_level = MIPS_CPU_ISA_M32; + break; + default: + c->cputype = CPU_UNKNOWN; + break; + } + break; + case PRID_COMP_SIBYTE: + switch (c->processor_id & 0xff00) { + case PRID_IMP_SB1: + c->cputype = CPU_SB1; + c->isa_level = MIPS_CPU_ISA_M64; + c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX | + MIPS_CPU_COUNTER | MIPS_CPU_DIVEC | + MIPS_CPU_MCHECK | MIPS_CPU_EJTAG | + MIPS_CPU_WATCH | MIPS_CPU_LLSC; +#ifndef CONFIG_SB1_PASS_1_WORKAROUNDS + /* FPU in pass1 is known to have issues. */ + c->options |= MIPS_CPU_FPU | MIPS_CPU_32FPR; +#endif + break; + default: + c->cputype = CPU_UNKNOWN; + break; + } + break; + + case PRID_COMP_SANDCRAFT: + switch (c->processor_id & 0xff00) { + case PRID_IMP_SR71000: + c->cputype = CPU_SR71000; + c->isa_level = MIPS_CPU_ISA_M64; + c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX | + MIPS_CPU_4KTLB | MIPS_CPU_FPU | + MIPS_CPU_COUNTER | MIPS_CPU_MCHECK; + c->scache.ways = 8; + c->tlbsize = 64; + break; + default: + c->cputype = CPU_UNKNOWN; + break; + } + break; + default: + c->cputype = CPU_UNKNOWN; + c->tlbsize = ((config1 >> 25) & 0x3f) + 1; + } + if (c->options & MIPS_CPU_FPU) + c->fpu_id = cpu_get_fpu_id(); +} + +__init void cpu_report(void) +{ + struct cpuinfo_mips *c = ¤t_cpu_data; + + printk("CPU revision is: %08x\n", c->processor_id); + if (c->options & MIPS_CPU_FPU) + printk("FPU revision is: %08x\n", c->fpu_id); +} diff -Nru a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S --- a/arch/mips/kernel/entry.S Tue Jul 1 18:44:32 2003 +++ b/arch/mips/kernel/entry.S Tue Jul 1 18:44:32 2003 @@ -1,5 +1,4 @@ /* -/* * 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. @@ -9,79 +8,155 @@ * Copyright (C) 2001 MIPS Technologies, Inc. */ #include +#include #include #include #include -#include +#include #include #include #include -#include +#include +#include #include #include -#include #include #include #include +#include -/* This duplicates the definition from */ -#define PT_TRACESYS 0x00000002 /* tracing system calls */ +#ifdef CONFIG_PREEMPT + .macro preempt_stop + cli + .endm + .macro init_ret_intr temp + mfc0 t0, CP0_STATUS # cli + ori t0, t0, 1 + xori t0, t0, 1 + mtc0 t0, CP0_STATUS + SSNOP; SSNOP; SSNOP + + lw \temp, TI_PRE_COUNT($28) + subu \temp, \temp, 1 + sw \temp, TI_PRE_COUNT($28) + .endm +#else + .macro preempt_stop + .endm + + .macro init_ret_intr + .endm + +#define resume_kernel restore_all +#endif .text - .align 4 + .align 5 .set push .set reorder -EXPORT(ret_from_fork) - move a0, v0 # prev - jal schedule_tail -#error lw t0, TASK_PTRACE($28) # syscall tracing enabled? - andi t0, PT_TRACESYS - bnez t0, tracesys_exit - j ret_from_sys_call - -tracesys_exit: jal syscall_trace - b ret_from_sys_call - -EXPORT(ret_from_irq) -EXPORT(ret_from_exception) +FEXPORT(ret_from_irq) +FEXPORT(ret_from_exception) lw t0, PT_STATUS(sp) # returning to kernel mode? andi t0, t0, KU_USER - bnez t0, ret_from_sys_call + beqz t0, resume_kernel + +FEXPORT(resume_userspace) + mfc0 t0, CP0_STATUS # make sure we dont miss an + ori t0, t0, 1 # interrupt setting need_resched + xori t0, t0, 1 # between sampling and return + mtc0 t0, CP0_STATUS + SSNOP; SSNOP; SSNOP + + LONG_L a2, TI_FLAGS($28) + andi a2, _TIF_WORK_MASK # current->work (ignoring + # syscall_trace) + bnez a2, work_pending j restore_all -reschedule: jal schedule +#ifdef CONFIG_PREEMPT +ENTRY(resume_kernel) + lw t0, TI_PRE_COUNT($28) + bnez t0, restore_all + LONG_L t0, TI_FLAGS($28) + andi t1, t0, _TIF_NEED_RESCHED + beqz restore_all +#ifdef CONFIG_SMP + lw t0, TI_CPU($28) + la t1, irq_stat + sll t0, 5 # *sizeof(irq_cpustat_t) + addu t0, t1 + lw t1, local_bh_count(t0) + addl t0, local_irq_count(t0) +#else + lw t1, irq_stat+local_bh_count + addl t0, irq_stat+local_irq_count +#endif + addu t0, t1 + bnez t0, restore_all + lw t0, TI_PRE_COUNT($28) + addiu t0, 1 + sw t0, TI_PRE_COUNT($28) + sti + movl t0, TI_TASK($28) # ti->task + sw zero, TASK_STATE(t0) # current->state = TASK_RUNNING + jal schedule + j ret_from_intr +#endif -EXPORT(ret_from_sys_call) - .type ret_from_irq,@function +FEXPORT(ret_from_fork) + jal schedule_tail - mfc0 t0, CP0_STATUS # need_resched and signals atomic test - ori t0, t0, 1 - xori t0, t0, 1 +FEXPORT(syscall_exit) + mfc0 t0, CP0_STATUS # make sure need_resched and + ori t0, t0, 1 # signals dont change between + xori t0, t0, 1 # sampling and return mtc0 t0, CP0_STATUS - nop; nop; nop + SSNOP; SSNOP; SSNOP + + LONG_L a2, TI_FLAGS($28) # current->work + bnez a2, syscall_exit_work -#error lw v0, TASK_NEED_RESCHED($28) -#error lw v1, TASK_SIGPENDING($28) - bnez v0, reschedule - bnez v1, signal_return -restore_all: .set noat +FEXPORT(restore_all) + .set noat RESTORE_ALL_AND_RET .set at -/* Put this behind restore_all for the sake of the branch prediction. */ -signal_return: - .type signal_return, @function - - mfc0 t0, CP0_STATUS - ori t0, t0, 1 +FEXPORT(work_pending) + andi t0, a2, _TIF_NEED_RESCHED + bnez t0, work_notifysig +work_resched: + jal schedule + + mfc0 t0, CP0_STATUS # make sure need_resched and + ori t0, t0, 1 # signals dont change between + xori t0, t0, 1 # sampling and return mtc0 t0, CP0_STATUS + SSNOP; SSNOP; SSNOP - move a0, zero - move a1, sp -#error jal do_signal - b restore_all + LONG_L a2, TI_FLAGS($28) + andi a2, _TIF_WORK_MASK # is there any work to be done + # other than syscall tracing? + beqz a2, restore_all + andi t0, a2, _TIF_NEED_RESCHED + bnez t0, work_resched + +work_notifysig: # deal with pending signals and + # notify-resume requests + move a0, sp + li a1, 0 + jal do_notify_resume # a2 already loaded + j restore_all + +FEXPORT(syscall_exit_work) + LONG_L t0, TI_FLAGS($28) + bgez t0, work_pending # trace bit is set + mfc0 t0, CP0_STATUS # could let do_syscall_trace() + ori t0, t0, 1 # call schedule() instead + mtc0 t0, CP0_STATUS + jal do_syscall_trace + b resume_userspace /* * Common spurious interrupt handler. @@ -93,25 +168,105 @@ * Someone tried to fool us by sending an interrupt but we * couldn't find a cause for it. */ - lui t1,%hi(spurious_count) - .set reorder - lw t0,%lo(spurious_count)(t1) - .set noreorder + lui t1,%hi(irq_err_count) + lw t0,%lo(irq_err_count)(t1) addiu t0,1 - sw t0,%lo(spurious_count)(t1) + sw t0,%lo(irq_err_count)(t1) j ret_from_irq END(spurious_interrupt) + __INIT + + .set reorder + + NESTED(except_vec1_generic, 0, sp) + PANIC("Exception vector 1 called") + END(except_vec1_generic) + + /* + * General exception vector. Used for all CPUs except R4000 + * and R4400 SC and MC versions. + */ + NESTED(except_vec3_generic, 0, sp) +#if R5432_CP0_INTERRUPT_WAR + mfc0 k0, CP0_INDEX +#endif + mfc0 k1, CP0_CAUSE + la k0, exception_handlers + andi k1, k1, 0x7c + addu k0, k0, k1 + lw k0, (k0) + jr k0 + END(except_vec3_generic) + .set at + + /* General exception vector R4000 version. */ + NESTED(except_vec3_r4000, 0, sp) + .set push + .set mips3 + .set noat + mfc0 k1, CP0_CAUSE + li k0, 31<<2 + andi k1, k1, 0x7c + .set noreorder + beq k1, k0, handle_vced + li k0, 14<<2 + beq k1, k0, handle_vcei + lui k0, %hi(exception_handlers) + addiu k0, %lo(exception_handlers) + .set reorder + addu k0, k0, k1 + lw k0, (k0) + jr k0 + + /* + * Big shit, we now may have two dirty primary cache lines for + * the same physical address. We can savely invalidate the + * line pointed to by c0_badvaddr because after return from + * this exception handler the load / store will be re-executed. + */ +handle_vced: + mfc0 k0, CP0_BADVADDR + li k1, -4 + and k0, k1 + mtc0 zero, CP0_TAGLO + cache Index_Store_Tag_D,(k0) + cache Hit_Writeback_Inv_SD,(k0) +#ifdef CONFIG_PROC_FS + lui k0, %hi(vced_count) + lw k1, %lo(vced_count)(k0) + addiu k1, 1 + sw k1, %lo(vced_count)(k0) +#endif + eret + +handle_vcei: + mfc0 k0, CP0_BADVADDR + cache Hit_Writeback_Inv_SD, (k0) # also cleans pi +#ifdef CONFIG_PROC_FS + lui k0, %hi(vcei_count) + lw k1, %lo(vcei_count)(k0) + addiu k1, 1 + sw k1, %lo(vcei_count)(k0) +#endif + eret + .set pop + END(except_vec3_r4000) + + __FINIT + /* * Build a default exception handler for the exceptions that don't need * special handlers. If you didn't know yet - I *like* playing games with * the C preprocessor ... */ #define __BUILD_clear_none(exception) -#define __BUILD_clear_sti(exception) \ +#define __BUILD_clear_sti(exception) \ STI -#define __BUILD_clear_cli(exception) \ +#define __BUILD_clear_cli(exception) \ CLI +#define __BUILD_clear_kmode(exception) \ + KMODE #define __BUILD_clear_fpe(exception) \ cfc1 a1,fcr31; \ li a2,~(0x3f<<12); \ @@ -148,6 +303,7 @@ NESTED(handle_##exception, PT_SIZE, sp); \ .set noat; \ SAVE_ALL; \ + FEXPORT(handle_##exception##_int); \ __BUILD_clear_##clear(exception); \ .set at; \ __BUILD_##verbose(exception); \ @@ -159,16 +315,18 @@ BUILD_HANDLER(adel,ade,ade,silent) /* #4 */ BUILD_HANDLER(ades,ade,ade,silent) /* #5 */ - BUILD_HANDLER(ibe,ibe,cli,verbose) /* #6 */ - BUILD_HANDLER(dbe,dbe,cli,silent) /* #7 */ - BUILD_HANDLER(bp,bp,sti,silent) /* #9 */ - BUILD_HANDLER(ri,ri,sti,silent) /* #10 */ - BUILD_HANDLER(cpu,cpu,sti,silent) /* #11 */ - BUILD_HANDLER(ov,ov,sti,silent) /* #12 */ - BUILD_HANDLER(tr,tr,sti,silent) /* #13 */ + BUILD_HANDLER(ibe,be,cli,silent) /* #6 */ + BUILD_HANDLER(dbe,be,cli,silent) /* #7 */ + BUILD_HANDLER(bp,bp,kmode,silent) /* #9 */ + BUILD_HANDLER(ri,ri,kmode,silent) /* #10 */ + BUILD_HANDLER(cpu,cpu,kmode,silent) /* #11 */ + BUILD_HANDLER(ov,ov,kmode,silent) /* #12 */ + BUILD_HANDLER(tr,tr,kmode,silent) /* #13 */ BUILD_HANDLER(fpe,fpe,fpe,silent) /* #15 */ - BUILD_HANDLER(watch,watch,sti,verbose) /* #23 */ - BUILD_HANDLER(reserved,reserved,sti,verbose) /* others */ + BUILD_HANDLER(mdmx,mdmx,sti,silent) /* #22 */ + BUILD_HANDLER(watch,watch,sti,silent) /* #23 */ + BUILD_HANDLER(mcheck,mcheck,cli,silent) /* #24 */ + BUILD_HANDLER(reserved,reserved,kmode,silent) /* others */ .set pop diff -Nru a/arch/mips/kernel/gdb-low.S b/arch/mips/kernel/gdb-low.S --- a/arch/mips/kernel/gdb-low.S Tue Jul 1 18:44:33 2003 +++ b/arch/mips/kernel/gdb-low.S Tue Jul 1 18:44:33 2003 @@ -14,6 +14,16 @@ #include /* + * [jsun] We reserves about 2x GDB_FR_SIZE in stack. The lower (addressed) + * part is used to store registers and passed to exception handler. + * The upper part is reserved for "call func" feature where gdb client + * saves some of the regs, setups call frame and passes args. + * + * A trace shows about 200 bytes are used to store about half of all regs. + * The rest should be big enough for frame setup and passing args. + */ + +/* * The low level trap handler */ .align 5 @@ -38,7 +48,7 @@ nop 1: move k0,sp - subu sp,k1,GDB_FR_SIZE + subu sp,k1,GDB_FR_SIZE*2 # see comment above sw k0,GDB_FR_REG29(sp) sw v0,GDB_FR_REG2(sp) @@ -97,7 +107,7 @@ sw ra,GDB_FR_REG31(sp) CLI /* disable interrupts */ - + /* * Followed by the floating point registers */ @@ -145,9 +155,9 @@ * FPU control registers */ - mfc1 v0,CP1_STATUS + cfc1 v0,CP1_STATUS sw v0,GDB_FR_FSR(sp) - mfc1 v0,CP1_REVISION + cfc1 v0,CP1_REVISION sw v0,GDB_FR_FIR(sp) /* @@ -211,7 +221,7 @@ lw v0,GDB_FR_CP0_CONTEXT(sp) mtc0 v1,CP0_INDEX mtc0 v0,CP0_CONTEXT - + /* * Next, the floating point registers @@ -304,7 +314,7 @@ lw v1,GDB_FR_REG3(sp) lw v0,GDB_FR_REG2(sp) lw $1,GDB_FR_REG1(sp) -#ifdef CONFIG_CPU_R3000 +#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX) lw k0, GDB_FR_EPC(sp) lw sp, GDB_FR_REG29(sp) /* Deallocate stack */ jr k0 @@ -321,11 +331,7 @@ END(trap_low) LEAF(kgdb_read_byte) - .set push - .set noreorder - .set nomacro 4: lb t0, (a0) - .set pop sb t0, (a1) li v0, 0 jr ra @@ -335,11 +341,7 @@ END(kgdb_read_byte) LEAF(kgdb_write_byte) - .set push - .set noreorder - .set nomacro 5: sb a0, (a1) - .set pop li v0, 0 jr ra .section __ex_table,"a" @@ -349,6 +351,7 @@ .type kgdbfault@function .ent kgdbfault + kgdbfault: li v0, -EFAULT jr ra .end kgdbfault diff -Nru a/arch/mips/kernel/gdb-stub.c b/arch/mips/kernel/gdb-stub.c --- a/arch/mips/kernel/gdb-stub.c Tue Jul 1 18:44:39 2003 +++ b/arch/mips/kernel/gdb-stub.c Tue Jul 1 18:44:39 2003 @@ -11,8 +11,6 @@ * Send complaints, suggestions etc. to * * Copyright (C) 1995 Andreas Busse - * - * $Id: gdb-stub.c,v 1.6 1999/05/01 22:40:35 ralf Exp $ */ /* @@ -64,7 +62,7 @@ * Host: Reply: * $m0,10#2a +$00010203040506070809101112131415#42 * - * + * * ============== * MORE EXAMPLES: * ============== @@ -74,11 +72,11 @@ * going. In this scenario the host machine was a PC and the * target platform was a Galileo EVB64120A MIPS evaluation * board. - * + * * Step 1: * First download gdb-5.0.tar.gz from the internet. * and then build/install the package. - * + * * Example: * $ tar zxf gdb-5.0.tar.gz * $ cd gdb-5.0 @@ -87,40 +85,39 @@ * $ install * $ which mips-linux-elf-gdb * /usr/local/bin/mips-linux-elf-gdb - * + * * Step 2: * Configure linux for remote debugging and build it. - * + * * Example: * $ cd ~/linux * $ make menuconfig * $ make dep; make vmlinux - * + * * Step 3: * Download the kernel to the remote target and start - * the kernel running. It will promptly halt and wait + * the kernel running. It will promptly halt and wait * for the host gdb session to connect. It does this - * since the "Kernel Hacking" option has defined - * CONFIG_REMOTE_DEBUG which in turn enables your calls + * since the "Kernel Hacking" option has defined + * CONFIG_KGDB which in turn enables your calls * to: * set_debug_traps(); * breakpoint(); - * + * * Step 4: * Start the gdb session on the host. - * + * * Example: * $ mips-linux-elf-gdb vmlinux * (gdb) set remotebaud 115200 * (gdb) target remote /dev/ttyS1 - * ...at this point you are connected to + * ...at this point you are connected to * the remote target and can use gdb - * in the normal fasion. Setting + * in the normal fasion. Setting * breakpoints, single stepping, * printing variables, etc. - * */ - +#include #include #include #include @@ -128,6 +125,8 @@ #include #include #include +#include +#include #include #include @@ -176,8 +175,8 @@ /* Used to prevent crashes in memory access. Note that they'll crash anyway if we haven't set up fault handlers yet... */ -int kgdb_read_byte(unsigned *address, unsigned *dest); -int kgdb_write_byte(unsigned val, unsigned *dest); +int kgdb_read_byte(unsigned char *address, unsigned char *dest); +int kgdb_write_byte(unsigned char val, unsigned char *dest); /* * Convert ch from a hex digit to an int @@ -214,7 +213,7 @@ checksum = 0; xmitcsum = -1; count = 0; - + /* * now, read until a # or end of buffer is found */ @@ -376,10 +375,10 @@ unsigned long flags; unsigned char c; - save_and_cli(flags); + local_irq_save(flags); for (ht = hard_trap_info; ht->tt && ht->signo; ht++) saved_vectors[ht->tt] = set_except_vector(ht->tt, trap_low); - + putDebugChar('+'); /* 'hello world' */ /* * In case GDB is started before us, ack any packets @@ -392,7 +391,7 @@ putDebugChar('+'); /* ack it */ initialized = 1; - restore_flags(flags); + local_irq_restore(flags); } /* @@ -548,7 +547,7 @@ targ += 4 + (insn.i_format.simmediate << 2); break; } - + if (is_branch) { i = 0; if (is_cond && targ != (regs->cp0_epc + 8)) { @@ -568,7 +567,7 @@ /* * If asynchronously interrupted by gdb, then we need to set a breakpoint - * at the interrupted instruction so that we wind up stopped with a + * at the interrupted instruction so that we wind up stopped with a * reasonable stack frame. */ static struct gdb_bp_save async_bp; @@ -578,7 +577,7 @@ async_bp.addr = epc; async_bp.val = *(unsigned *)epc; *(unsigned *)epc = BP; - flush_cache_all(); + __flush_cache_all(); } @@ -596,31 +595,11 @@ char *ptr; unsigned long *stack; -#if 0 - printk("in handle_exception()\n"); - show_gdbregs(regs); -#endif - - /* - * First check trap type. If this is CPU_UNUSABLE and CPU_ID is 1, - * the simply switch the FPU on and return since this is no error - * condition. kernel/traps.c does the same. - * FIXME: This doesn't work yet, so we don't catch CPU_UNUSABLE - * traps for now. - */ - trap = (regs->cp0_cause & 0x7c) >> 2; -/* printk("trap=%d\n",trap); */ - if (trap == 11) { - if (((regs->cp0_cause >> CAUSEB_CE) & 3) == 1) { - regs->cp0_status |= ST0_CU1; - return; - } - } - /* * If we're in breakpoint() increment the PC */ - if (trap == 9 && regs->cp0_epc == (unsigned long)breakinst) + trap = (regs->cp0_cause & 0x7c) >> 2; + if (trap == 9 && regs->cp0_epc == (unsigned long)breakinst) regs->cp0_epc += 4; /* @@ -630,7 +609,7 @@ if (step_bp[0].addr) { *(unsigned *)step_bp[0].addr = step_bp[0].val; step_bp[0].addr = 0; - + if (step_bp[1].addr) { *(unsigned *)step_bp[1].addr = step_bp[1].val; step_bp[1].addr = 0; @@ -708,6 +687,11 @@ output_buffer[3] = 0; break; + case 'D': + /* detach; let CPU run */ + putpacket(output_buffer); + return; + case 'd': /* toggle debug flag */ break; @@ -724,29 +708,24 @@ ptr = mem2hex((char *)®s->frame_ptr, ptr, 2*4, 0); /* frp */ ptr = mem2hex((char *)®s->cp0_index, ptr, 16*4, 0); /* cp0 */ break; - + /* * set the value of the CPU registers - return OK - * FIXME: Needs to be written */ case 'G': { -#if 0 - unsigned long *newsp, psr; - ptr = &input_buffer[1]; - hex2mem(ptr, (char *)registers, 16 * 4, 0); /* G & O regs */ - - /* - * See if the stack pointer has moved. If so, then copy the - * saved locals and ins to the new location. - */ - - newsp = (unsigned long *)registers[SP]; - if (sp != newsp) - sp = memcpy(newsp, sp, 16 * 4); - -#endif + hex2mem(ptr, (char *)®s->reg0, 32*4, 0); + ptr += 32*8; + hex2mem(ptr, (char *)®s->cp0_status, 6*4, 0); + ptr += 6*8; + hex2mem(ptr, (char *)®s->fpr0, 32*4, 0); + ptr += 32*8; + hex2mem(ptr, (char *)®s->cp1_fsr, 2*4, 0); + ptr += 2*8; + hex2mem(ptr, (char *)®s->frame_ptr, 2*4, 0); + ptr += 2*8; + hex2mem(ptr, (char *)®s->cp0_index, 16*4, 0); strcpy(output_buffer,"OK"); } break; @@ -770,7 +749,7 @@ /* * MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */ - case 'M': + case 'M': ptr = &input_buffer[1]; if (hexToInt(&ptr, &addr) @@ -789,13 +768,13 @@ /* * cAA..AA Continue at address AA..AA(optional) */ - case 'c': + case 'c': /* try to read optional parameter, pc unchanged if no parm */ ptr = &input_buffer[1]; if (hexToInt(&ptr, &addr)) regs->cp0_epc = addr; - + /* * Need to flush the instruction cache here, as we may * have deposited a breakpoint, and the icache probably @@ -805,26 +784,21 @@ * NB: We flush both caches, just to be sure... */ - flush_cache_all(); + __flush_cache_all(); return; /* NOTREACHED */ break; /* - * kill the program - */ - case 'k' : - break; /* do nothing */ - - - /* - * Reset the whole machine (FIXME: system dependent) + * kill the program; let us try to restart the machine + * Reset the whole machine. */ + case 'k': case 'r': + machine_restart("kgdb restarts machine"); break; - /* * Step to next instruction */ @@ -834,7 +808,7 @@ * use breakpoints and continue, instead. */ single_step(regs); - flush_cache_all(); + __flush_cache_all(); return; /* NOTREACHED */ @@ -844,7 +818,7 @@ */ case 'b': { -#if 0 +#if 0 int baudrate; extern void set_timer_3(); @@ -904,30 +878,43 @@ if (!initialized) return; - __asm__ __volatile__(" - .globl breakinst - .set noreorder - nop -breakinst: break - nop - .set reorder - "); + __asm__ __volatile__( + ".globl breakinst\n\t" + ".set\tnoreorder\n\t" + "nop\n\t" + "breakinst:\tbreak\n\t" + "nop\n\t" + ".set\treorder" + ); } void adel(void) { - __asm__ __volatile__(" - .globl adel - la $8,0x80000001 - lw $9,0($8) - "); + __asm__ __volatile__( + ".globl\tadel\n\t" + "la\t$8,0x80000001\n\t" + "lw\t$9,0($8)\n\t" + ); +} + +/* + * malloc is needed by gdb client in "call func()", even a private one + * will make gdb happy + */ +static void *malloc(size_t size) +{ + return kmalloc(size, GFP_ATOMIC); +} + +static void free(void *where) +{ + kfree(where); } #ifdef CONFIG_GDB_CONSOLE -void gdb_puts(const char *str) +void gdb_putsn(const char *str, int l) { - int l = strlen(str); char outbuf[18]; outbuf[0]='O'; @@ -936,7 +923,7 @@ int i = (l>8)?8:l; mem2hex((char *)str, &outbuf[1], i, 0); outbuf[(i*2)+1]=0; - putpacket(outbuf); + putpacket(outbuf); str += i; l -= i; } @@ -944,7 +931,7 @@ static void gdb_console_write(struct console *con, const char *s, unsigned n) { - gdb_puts(s); + gdb_putsn(s, n); } static struct console gdb_console = { @@ -958,5 +945,5 @@ { register_console(&gdb_console); } - + #endif diff -Nru a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S --- a/arch/mips/kernel/head.S Tue Jul 1 18:44:36 2003 +++ b/arch/mips/kernel/head.S Tue Jul 1 18:44:36 2003 @@ -1,6 +1,4 @@ /* - * arch/mips/kernel/head.S - * * 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. @@ -13,550 +11,224 @@ * Further modifications by David S. Miller and Harald Koerfgen * Copyright (C) 1999 Silicon Graphics, Inc. * - * Head.S contains the MIPS exception handler and startup code. - * - ************************************************************************** - * 9 Nov, 2000. - * Added Cache Error exception handler and SBDDP EJTAG debug exception. - * - * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - ************************************************************************** + * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. */ #include +#include #include #include -#include -#include #include +#include #include #include #include #include #include -#include - - .text - /* - * Reserved space for exception handlers. - * Necessary for machines which link their kernels at KSEG0. - * FIXME: Use the initcode feature to get rid of unused handler - * variants. - */ - .fill 0x280 -/* - * This is space for the interrupt handlers. - * After trap_init() they are located at virtual address KSEG0. - * - * These handlers much be written in a relocatable manner - * because based upon the cpu type an arbitrary one of the - * following pieces of code will be copied to the KSEG0 - * vector location. - */ - /* TLB refill, EXL == 0, R4xx0, non-R4600 version */ - .set noreorder - .set noat - LEAF(except_vec0_r4000) - .set mips3 -#ifdef CONFIG_SMP - mfc0 k1, CP0_CONTEXT - la k0, current_pgd - srl k1, 23 - sll k1, 2 - addu k1, k0, k1 - lw k1, (k1) -#else - lw k1, current_pgd # get pgd pointer -#endif - mfc0 k0, CP0_BADVADDR # Get faulting address - srl k0, k0, 22 # get pgd only bits - - sll k0, k0, 2 - addu k1, k1, k0 # add in pgd offset - mfc0 k0, CP0_CONTEXT # get context reg - lw k1, (k1) -#if defined(CONFIG_CPU_VR41XX) - srl k0, k0, 3 # get pte offset -#else - srl k0, k0, 1 # get pte offset -#endif - and k0, k0, 0xff8 - addu k1, k1, k0 # add in offset - lw k0, 0(k1) # get even pte - lw k1, 4(k1) # get odd pte - srl k0, k0, 6 # convert to entrylo0 - mtc0 k0, CP0_ENTRYLO0 # load it - srl k1, k1, 6 # convert to entrylo1 - mtc0 k1, CP0_ENTRYLO1 # load it - b 1f - tlbwr # write random tlb entry -1: - nop - eret # return from trap - END(except_vec0_r4000) - - /* TLB refill, EXL == 0, R4600 version */ - LEAF(except_vec0_r4600) - .set mips3 - mfc0 k0, CP0_BADVADDR - srl k0, k0, 22 - lw k1, current_pgd # get pgd pointer - sll k0, k0, 2 - addu k1, k1, k0 - mfc0 k0, CP0_CONTEXT - lw k1, (k1) - srl k0, k0, 1 - and k0, k0, 0xff8 - addu k1, k1, k0 - lw k0, 0(k1) - lw k1, 4(k1) - srl k0, k0, 6 - mtc0 k0, CP0_ENTRYLO0 - srl k1, k1, 6 - mtc0 k1, CP0_ENTRYLO1 - nop - tlbwr - nop - eret - END(except_vec0_r4600) - - /* TLB refill, EXL == 0, R52x0 "Nevada" version */ - /* - * This version has a bug workaround for the Nevada. It seems - * as if under certain circumstances the move from cp0_context - * might produce a bogus result when the mfc0 instruction and - * it's consumer are in a different cacheline or a load instruction, - * probably any memory reference, is between them. This is - * potencially slower than the R4000 version, so we use this - * special version. - */ - .set noreorder - .set noat - LEAF(except_vec0_nevada) - .set mips3 - mfc0 k0, CP0_BADVADDR # Get faulting address - srl k0, k0, 22 # get pgd only bits - lw k1, current_pgd # get pgd pointer - sll k0, k0, 2 - addu k1, k1, k0 # add in pgd offset - lw k1, (k1) - mfc0 k0, CP0_CONTEXT # get context reg - srl k0, k0, 1 # get pte offset - and k0, k0, 0xff8 - addu k1, k1, k0 # add in offset - lw k0, 0(k1) # get even pte - lw k1, 4(k1) # get odd pte - srl k0, k0, 6 # convert to entrylo0 - mtc0 k0, CP0_ENTRYLO0 # load it - srl k1, k1, 6 # convert to entrylo1 - mtc0 k1, CP0_ENTRYLO1 # load it - nop # QED specified nops - nop - tlbwr # write random tlb entry - nop # traditional nop - eret # return from trap - END(except_vec0_nevada) - - /* TLB refill, EXL == 0, R4[40]00/R5000 badvaddr hwbug version */ - LEAF(except_vec0_r45k_bvahwbug) - .set mips3 - mfc0 k0, CP0_BADVADDR - srl k0, k0, 22 - lw k1, current_pgd # get pgd pointer - sll k0, k0, 2 - addu k1, k1, k0 - mfc0 k0, CP0_CONTEXT - lw k1, (k1) - srl k0, k0, 1 - and k0, k0, 0xff8 - addu k1, k1, k0 - lw k0, 0(k1) - lw k1, 4(k1) - nop /* XXX */ - tlbp - srl k0, k0, 6 - mtc0 k0, CP0_ENTRYLO0 - srl k1, k1, 6 - mfc0 k0, CP0_INDEX - mtc0 k1, CP0_ENTRYLO1 - bltzl k0, 1f - tlbwr -1: - nop - eret - END(except_vec0_r45k_bvahwbug) - -#ifdef CONFIG_SMP - /* TLB refill, EXL == 0, R4000 MP badvaddr hwbug version */ - LEAF(except_vec0_r4k_mphwbug) - .set mips3 - mfc0 k0, CP0_BADVADDR - srl k0, k0, 22 - lw k1, current_pgd # get pgd pointer - sll k0, k0, 2 - addu k1, k1, k0 - mfc0 k0, CP0_CONTEXT - lw k1, (k1) - srl k0, k0, 1 - and k0, k0, 0xff8 - addu k1, k1, k0 - lw k0, 0(k1) - lw k1, 4(k1) - nop /* XXX */ - tlbp - srl k0, k0, 6 - mtc0 k0, CP0_ENTRYLO0 - srl k1, k1, 6 - mfc0 k0, CP0_INDEX - mtc0 k1, CP0_ENTRYLO1 - bltzl k0, 1f - tlbwr -1: - nop - eret - END(except_vec0_r4k_mphwbug) -#endif - - /* TLB refill, EXL == 0, R4000 UP 250MHZ entrylo[01] hwbug version */ - LEAF(except_vec0_r4k_250MHZhwbug) - .set mips3 - mfc0 k0, CP0_BADVADDR - srl k0, k0, 22 - lw k1, current_pgd # get pgd pointer - sll k0, k0, 2 - addu k1, k1, k0 - mfc0 k0, CP0_CONTEXT - lw k1, (k1) - srl k0, k0, 1 - and k0, k0, 0xff8 - addu k1, k1, k0 - lw k0, 0(k1) - lw k1, 4(k1) - srl k0, k0, 6 - mtc0 zero, CP0_ENTRYLO0 - mtc0 k0, CP0_ENTRYLO0 - srl k1, k1, 6 - mtc0 zero, CP0_ENTRYLO1 - mtc0 k1, CP0_ENTRYLO1 - b 1f - tlbwr -1: - nop - eret - END(except_vec0_r4k_250MHZhwbug) - -#ifdef CONFIG_SMP - /* TLB refill, EXL == 0, R4000 MP 250MHZ entrylo[01]+badvaddr bug version */ - LEAF(except_vec0_r4k_MP250MHZhwbug) - .set mips3 - mfc0 k0, CP0_BADVADDR - srl k0, k0, 22 - lw k1, current_pgd # get pgd pointer - sll k0, k0, 2 - addu k1, k1, k0 - mfc0 k0, CP0_CONTEXT - lw k1, (k1) - srl k0, k0, 1 - and k0, k0, 0xff8 - addu k1, k1, k0 - lw k0, 0(k1) - lw k1, 4(k1) - nop /* XXX */ - tlbp - srl k0, k0, 6 - mtc0 zero, CP0_ENTRYLO0 - mtc0 k0, CP0_ENTRYLO0 - mfc0 k0, CP0_INDEX - srl k1, k1, 6 - mtc0 zero, CP0_ENTRYLO1 - mtc0 k1, CP0_ENTRYLO1 - bltzl k0, 1f - tlbwr -1: - nop - eret - END(except_vec0_r4k_MP250MHZhwbug) -#endif - - /* TLB refill, R[23]00 version */ - LEAF(except_vec0_r2300) - .set noat - .set mips1 - mfc0 k0, CP0_BADVADDR - lw k1, current_pgd # get pgd pointer - srl k0, k0, 22 - sll k0, k0, 2 - addu k1, k1, k0 - mfc0 k0, CP0_CONTEXT - lw k1, (k1) - and k0, k0, 0xffc - addu k1, k1, k0 - lw k0, (k1) - nop - mtc0 k0, CP0_ENTRYLO0 - mfc0 k1, CP0_EPC - tlbwr - jr k1 - rfe - END(except_vec0_r2300) - - - /* XTLB refill, EXL == 0, R4xx0 cpus only use this... */ - NESTED(except_vec1_generic, 0, sp) - .set noat - .set mips3 - /* Register saving is delayed as long as we don't know - * which registers really need to be saved. - */ - mfc0 k1, CP0_CONTEXT - dsra k1, 1 - lwu k0, (k1) # May cause another exception - lwu k1, 4(k1) - dsrl k0, 6 # Convert to EntryLo format - dsrl k1, 6 # Convert to EntryLo format - dmtc0 k0, CP0_ENTRYLO0 - dmtc0 k1, CP0_ENTRYLO1 - nop # Needed for R4[04]00 pipeline - tlbwr - nop # Needed for R4[04]00 pipeline - nop - nop - eret - nop /* Workaround for R4000 bug. */ - eret - END(except_vec1_generic) - - /* Cache Error */ - LEAF(except_vec2_generic) - .set noat - .set mips0 - /* - * This is a very bad place to be. Our cache error - * detection has triggered. If we have write-back data - * in the cache, we may not be able to recover. As a - * first-order desperate measure, turn off KSEG0 cacheing. - */ - mfc0 k0,CP0_CONFIG - li k1,~CONF_CM_CMASK - and k0,k0,k1 - ori k0,k0,CONF_CM_UNCACHED - mtc0 k0,CP0_CONFIG - /* Give it a few cycles to sink in... */ - nop - nop - nop - - j cache_parity_error - nop - END(except_vec2_generic) - - /* General exception vector R4000 version. */ - NESTED(except_vec3_r4000, 0, sp) - .set noat - mfc0 k1, CP0_CAUSE - andi k1, k1, 0x7c - li k0, 31<<2 - beq k1, k0, handle_vced - li k0, 14<<2 - beq k1, k0, handle_vcei - la k0, exception_handlers - addu k0, k0, k1 - lw k0, (k0) - nop - jr k0 - nop -/* - * Big shit, we now may have two dirty primary cache lines for the same - * physical address. We can savely invalidate the line pointed to by - * c0_badvaddr because after return from this exception handler the load / - * store will be re-executed. - */ - .set mips3 -handle_vced: - mfc0 k0, CP0_BADVADDR - li k1, -4 - and k0, k1 - mtc0 zero, CP0_TAGLO - cache Index_Store_Tag_D,(k0) - cache Hit_Writeback_Inv_SD,(k0) -#ifdef CONFIG_PROC_FS - lui k0, %hi(vced_count) - lw k1, %lo(vced_count)(k0) - addiu k1, 1 - sw k1, %lo(vced_count)(k0) -#endif - eret - -handle_vcei: - mfc0 k0, CP0_BADVADDR - cache Hit_Writeback_Inv_SD,(k0) # also cleans pi -#ifdef CONFIG_PROC_FS - lui k0, %hi(vcei_count) - lw k1, %lo(vcei_count)(k0) - addiu k1, 1 - sw k1, %lo(vcei_count)(k0) -#endif - eret - - END(except_vec3_r4000) - .set at - - /* General exception vector. */ - NESTED(except_vec3_generic, 0, sp) - .set noat - .set mips0 - mfc0 k1, CP0_CAUSE - la k0, exception_handlers - andi k1, k1, 0x7c - addu k0, k0, k1 - lw k0, (k0) - nop - jr k0 - nop - END(except_vec3_generic) - .set at - - /* - * Special interrupt vector for embedded MIPS. This is a - * dedicated interrupt vector which reduces interrupt processing - * overhead. The jump instruction will be inserted here at - * initialization time. This handler may only be 8 bytes in size! - */ - NESTED(except_vec4, 0, sp) -1: j 1b /* Dummy, will be replaced */ - nop - END(except_vec4) - - /* - * SBDDP EJTAG debug exception handler. - * The EJTAG debug exception entry point is 0xbfc00480, which - * normally is in the boot PROM, so the boot PROM must do a - * unconditional jump to this vector. - */ - NESTED(except_vec_ejtag_debug, 0, sp) - j ejtag_debug_handler - nop - END(except_vec_ejtag_debug) - - /* - * EJTAG debug exception handler. - */ - NESTED(ejtag_debug_handler, PT_SIZE, sp) - .set noat - .set noreorder - SAVE_ALL - PRINT("SDBBP EJTAG debug exception - not handled yet, just ignored!\n"); - mfc0 k0, $23 # Get EJTAG Debug register. - mfc0 k1, $24 # Get DEPC register. - bgez k0, 1f - addiu k1, k1, 4 # SBDDP inst. in delay slot. - addiu k1, k1, 4 -1: mtc0 k1, $24 - RESTORE_ALL - .word 0x4200001f # deret, return EJTAG debug exception. - nop - .set at - END(ejtag_debug_handler) - - -/* - * Kernel entry point - */ -NESTED(kernel_entry, 16, sp) - .set noreorder - /* The following two symbols are used for kernel profiling. */ - EXPORT(stext) - EXPORT(_stext) - - /* - * Stack for kernel and init, current variable - */ - la $28, init_task_union - addiu t0, $28, KERNEL_STACK_SIZE-32 - subu sp, t0, 4*SZREG - - sw t0, kernelsp - /* The firmware/bootloader passes argc/argp/envp - * to us as arguments. But clear bss first because - * the romvec and other important info is stored there - * by prom_init(). - */ - la t0, _edata - sw zero, (t0) - la t1, (_end - 4) -1: - addiu t0, 4 - bne t0, t1, 1b - sw zero, (t0) - - jal init_arch - nop - END(kernel_entry) + .text + /* + * Reserved space for exception handlers. + * Necessary for machines which link their kernels at KSEG0. + */ + .fill 0x400 + + /* The following two symbols are used for kernel profiling. */ + EXPORT(stext) + EXPORT(_stext) + + __INIT + + /* Cache Error */ + LEAF(except_vec2_generic) + .set noreorder + .set noat + .set mips0 + /* + * This is a very bad place to be. Our cache error + * detection has triggered. If we have write-back data + * in the cache, we may not be able to recover. As a + * first-order desperate measure, turn off KSEG0 cacheing. + */ + mfc0 k0,CP0_CONFIG + li k1,~CONF_CM_CMASK + and k0,k0,k1 + ori k0,k0,CONF_CM_UNCACHED + mtc0 k0,CP0_CONFIG + /* Give it a few cycles to sink in... */ + nop + nop + nop + + j cache_parity_error + nop + END(except_vec2_generic) + + .set at + + /* + * Special interrupt vector for embedded MIPS. This is a + * dedicated interrupt vector which reduces interrupt processing + * overhead. The jump instruction will be inserted here at + * initialization time. This handler may only be 8 bytes in + * size! + */ + NESTED(except_vec4, 0, sp) +1: j 1b /* Dummy, will be replaced */ + nop + END(except_vec4) + + /* + * EJTAG debug exception handler. + * The EJTAG debug exception entry point is 0xbfc00480, which + * normally is in the boot PROM, so the boot PROM must do a + * unconditional jump to this vector. + */ + NESTED(except_vec_ejtag_debug, 0, sp) + j ejtag_debug_handler + nop + END(except_vec_ejtag_debug) + + __FINIT + + /* + * EJTAG debug exception handler. + */ + NESTED(ejtag_debug_handler, PT_SIZE, sp) + .set noat + .set noreorder + mtc0 k0, CP0_DESAVE + mfc0 k0, CP0_DEBUG + + sll k0, k0, 30 # Check for SDBBP. + bgez k0, ejtag_return + + la k0, ejtag_debug_buffer + sw k1, 0(k0) + SAVE_ALL + jal ejtag_exception_handler + move a0, sp + RESTORE_ALL + la k0, ejtag_debug_buffer + lw k1, 0(k0) + +ejtag_return: + mfc0 k0, CP0_DESAVE + .set mips32 + deret + .set mips0 + nop + .set at + END(ejtag_debug_handler) + + __INIT + + /* + * NMI debug exception handler for MIPS reference boards. + * The NMI debug exception entry point is 0xbfc00000, which + * normally is in the boot PROM, so the boot PROM must do a + * unconditional jump to this vector. + */ + NESTED(except_vec_nmi, 0, sp) + j nmi_handler + nop + END(except_vec_nmi) + + __FINIT + + NESTED(nmi_handler, PT_SIZE, sp) + .set noat + .set noreorder + .set mips3 + SAVE_ALL + jal nmi_exception_handler + move a0, sp + RESTORE_ALL + eret + .set at + .set mips0 + END(nmi_handler) + + __INIT + + /* + * Kernel entry point + */ + NESTED(kernel_entry, 16, sp) + .set noreorder + + /* + * Stack for kernel and init, current variable + */ + la $28, init_thread_union + addiu t0, $28, KERNEL_STACK_SIZE-32 + subu sp, t0, 4*SZREG + sw t0, kernelsp + + /* The firmware/bootloader passes argc/argp/envp + * to us as arguments. But clear bss first because + * the romvec and other important info is stored there + * by prom_init(). + */ + la t0, __bss_start + sw zero, (t0) + la t1, __bss_stop - 4 +1: + addiu t0, 4 + bne t0, t1, 1b + sw zero, (t0) + + jal init_arch + nop + END(kernel_entry) #ifdef CONFIG_SMP /* - * SMP slave cpus entry point. Board specific code - * for bootstrap calls this function after setting up - * the stack and gp registers. - */ - LEAF(smp_bootstrap) - .set push - .set noreorder - mtc0 zero, CP0_WIRED - CLI - mfc0 t0, CP0_STATUS - li t1, ~(ST0_CU1|ST0_CU2|ST0_CU3|ST0_BEV); - and t0, t1 - or t0, (ST0_CU0|ST0_KX|ST0_SX|ST0_FR); - addiu a0, zero, 0 - jal start_secondary - mtc0 t0, CP0_STATUS - .set pop - END(smp_bootstrap) -#endif - -/* - * This buffer is reserved for the use of the cache error handler. + * SMP slave cpus entry point. Board specific code for bootstrap calls this + * function after setting up the stack and gp registers. */ + LEAF(smp_bootstrap) + .set push + .set noreorder + mtc0 zero, CP0_WIRED + CLI + mfc0 t0, CP0_STATUS + li t1, ~(ST0_CU1|ST0_CU2|ST0_CU3|ST0_KX|ST0_SX) + and t0, t1 + or t0, (ST0_CU0); + jal start_secondary + mtc0 t0, CP0_STATUS + .set pop + END(smp_bootstrap) +#endif + + __FINIT + + /* + * This buffer is reserved for the use of the EJTAG debug + * handler. + */ .data - EXPORT(cache_error_buffer) - .fill 32*4,1,0 - -#ifndef CONFIG_SMP -EXPORT(kernelsp) - PTR 0 -EXPORT(current_pgd) - PTR 0 -#else - /* There's almost certainly a better way to do this with the macros...*/ - .globl kernelsp - .comm kernelsp, NR_CPUS * 8, 8 - .globl current_pgd - .comm current_pgd, NR_CPUS * 8, 8 -#endif - .text - .org 0x1000 -EXPORT(swapper_pg_dir) - - .org 0x2000 -EXPORT(empty_bad_page) + EXPORT(ejtag_debug_buffer) + .fill 4 - .org 0x3000 -EXPORT(empty_bad_page_table) + .comm kernelsp, NR_CPUS * 8, 8 + .comm pgd_current, NR_CPUS * 8, 8 - .org 0x4000 -EXPORT(invalid_pte_table) - - .org 0x5000 -/* XXX This label is required to keep GAS trying to be too clever ... - Bug? */ -dummy: -/* - * Align to 8kb boundary for init_task_union which follows in the - * .text segment. - */ - .align 13 + .macro page name, order=0 + .globl \name +\name: .size \name, (_PAGE_SIZE << \order) + .org . + (_PAGE_SIZE << \order) + .type \name, @object + .endm + + .data + .align PAGE_SHIFT + + page swapper_pg_dir, _PGD_ORDER + page empty_bad_page, 0 + page empty_bad_page_table, 0 + page invalid_pte_table, 0 diff -Nru a/arch/mips/kernel/i8259.c b/arch/mips/kernel/i8259.c --- a/arch/mips/kernel/i8259.c Tue Jul 1 18:44:32 2003 +++ b/arch/mips/kernel/i8259.c Tue Jul 1 18:44:32 2003 @@ -11,11 +11,12 @@ #include #include #include -#include #include #include #include +#include +#include #include void enable_8259A_irq(unsigned int irq); @@ -30,11 +31,12 @@ * moves to arch independent land */ -spinlock_t i8259A_lock = SPIN_LOCK_UNLOCKED; +static spinlock_t i8259A_lock = SPIN_LOCK_UNLOCKED; static void end_8259A_irq (unsigned int irq) { - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)) && + irq_desc[irq].action) enable_8259A_irq(irq); } @@ -43,7 +45,7 @@ void mask_and_ack_8259A(unsigned int); static unsigned int startup_8259A_irq(unsigned int irq) -{ +{ enable_8259A_irq(irq); return 0; /* never anything pending */ @@ -69,9 +71,8 @@ */ static unsigned int cached_irq_mask = 0xffff; -#define __byte(x,y) (((unsigned char *)&(y))[x]) -#define cached_21 (__byte(0,cached_irq_mask)) -#define cached_A1 (__byte(1,cached_irq_mask)) +#define cached_21 (cached_irq_mask) +#define cached_A1 (cached_irq_mask >> 8) void disable_8259A_irq(unsigned int irq) { @@ -211,7 +212,7 @@ printk("spurious 8259A interrupt: IRQ%d.\n", irq); spurious_irq_mask |= irqmask; } - irq_err_count++; + atomic_inc(&irq_err_count); /* * Theoretically we do not have to handle this IRQ, * but in Linux this does not cause problems and is @@ -221,6 +222,32 @@ } } +static int i8259A_resume(struct sys_device *dev) +{ + init_8259A(0); + return 0; +} + +static struct sysdev_class i8259_sysdev_class = { + set_kset_name("i8259"), + .resume = i8259A_resume, +}; + +static struct sys_device device_i8259A = { + .id = 0, + .cls = &i8259_sysdev_class, +}; + +static int __init i8259A_init_sysfs(void) +{ + int error = sysdev_class_register(&i8259_sysdev_class); + if (!error) + error = sys_device_register(&device_i8259A); + return error; +} + +device_initcall(i8259A_init_sysfs); + void __init init_8259A(int auto_eoi) { unsigned long flags; @@ -234,7 +261,7 @@ * outb_p - this has to work on a wide range of PC hardware. */ outb_p(0x11, 0x20); /* ICW1: select 8259A-1 init */ - outb_p(0x20 + 0, 0x21); /* ICW2: 8259A-1 IR0-7 mapped to 0x20-0x27 */ + outb_p(0x00, 0x21); /* ICW2: 8259A-1 IR0-7 mapped to 0x00-0x07 */ outb_p(0x04, 0x21); /* 8259A-1 (the master) has a slave on IR2 */ if (auto_eoi) outb_p(0x03, 0x21); /* master does Auto EOI */ @@ -242,7 +269,7 @@ outb_p(0x01, 0x21); /* master expects normal EOI */ outb_p(0x11, 0xA0); /* ICW1: select 8259A-2 init */ - outb_p(0x20 + 8, 0xA1); /* ICW2: 8259A-2 IR0-7 mapped to 0x28-0x2f */ + outb_p(0x08, 0xA1); /* ICW2: 8259A-2 IR0-7 mapped to 0x08-0x0f */ outb_p(0x02, 0xA1); /* 8259A-2 is a slave on master's IR2 */ outb_p(0x01, 0xA1); /* (slave's support for AEOI in flat mode is to be investigated) */ diff -Nru a/arch/mips/kernel/init_task.c b/arch/mips/kernel/init_task.c --- a/arch/mips/kernel/init_task.c Tue Jul 1 18:44:33 2003 +++ b/arch/mips/kernel/init_task.c Tue Jul 1 18:44:33 2003 @@ -1,17 +1,19 @@ #include #include #include +#include #include #include static struct fs_struct init_fs = INIT_FS; static struct files_struct init_files = INIT_FILES; -static struct signal_struct init_signals = INIT_SIGNALS; +static struct signal_struct init_signals = INIT_SIGNALS(init_signals); +static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); struct mm_struct init_mm = INIT_MM(init_mm); /* - * Initial task structure. + * Initial thread structure. * * We need to make sure that this is 8192-byte aligned due to the * way process stacks are handled. This is done by making sure @@ -20,6 +22,13 @@ * * The things we do for performance.. */ -union task_union init_task_union - __attribute__((__section__(".text"))) = - { INIT_TASK(init_task_union.task) }; +union thread_union init_thread_union + __attribute__((__section__(".data.init_task"))) = + { INIT_THREAD_INFO(init_task) }; + +/* + * Initial task structure. + * + * All other task structs will be allocated on slabs in fork.c + */ +struct task_struct init_task = INIT_TASK(init_task); diff -Nru a/arch/mips/kernel/ioport.c b/arch/mips/kernel/ioport.c --- a/arch/mips/kernel/ioport.c Tue Jul 1 18:44:32 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,34 +0,0 @@ -/* - * linux/arch/mips/kernel/ioport.c - */ -#include -#include -#include -#include -#include - -/* - * This changes the io permissions bitmap in the current task. - */ -asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on) -{ - return -ENOSYS; -} - -/* - * sys_iopl has to be used when you want to access the IO ports - * beyond the 0x3ff range: to get the full 65536 ports bitmapped - * you'd need 8kB of bitmaps/process, which is a bit excessive. - * - * Here we just change the eflags value on the stack: we allow - * only the super-user to do it. This depends on the stack-layout - * on system-call entry - see also fork() and the signal handling - * code. - */ -asmlinkage int sys_iopl(long ebx,long ecx,long edx, - long esi, long edi, long ebp, long eax, long ds, - long es, long fs, long gs, long orig_eax, - long eip,long cs,long eflags,long esp,long ss) -{ - return -ENOSYS; -} diff -Nru a/arch/mips/kernel/ipc.c b/arch/mips/kernel/ipc.c --- a/arch/mips/kernel/ipc.c Tue Jul 1 18:44:32 2003 +++ b/arch/mips/kernel/ipc.c Tue Jul 1 18:44:32 2003 @@ -45,7 +45,7 @@ } case MSGSND: - return sys_msgsnd (first, (struct msgbuf *) ptr, + return sys_msgsnd (first, (struct msgbuf *) ptr, second, third); case MSGRCV: switch (version) { @@ -53,9 +53,9 @@ struct ipc_kludge tmp; if (!ptr) return -EINVAL; - + if (copy_from_user(&tmp, - (struct ipc_kludge *) ptr, + (struct ipc_kludge *) ptr, sizeof (tmp))) return -EFAULT; return sys_msgrcv (first, tmp.msgp, second, @@ -85,7 +85,7 @@ return -EINVAL; return sys_shmat (first, (char *) ptr, second, (ulong *) third); } - case SHMDT: + case SHMDT: return sys_shmdt ((char *)ptr); case SHMGET: return sys_shmget (first, second, third); @@ -93,6 +93,6 @@ return sys_shmctl (first, second, (struct shmid_ds *) ptr); default: - return -EINVAL; + return -ENOSYS; } } diff -Nru a/arch/mips/kernel/irix5sys.h b/arch/mips/kernel/irix5sys.h --- a/arch/mips/kernel/irix5sys.h Tue Jul 1 18:44:31 2003 +++ b/arch/mips/kernel/irix5sys.h Tue Jul 1 18:44:31 2003 @@ -1,5 +1,4 @@ -/* $Id: irix5sys.h,v 1.2 1998/08/17 10:16:25 ralf Exp $ - * +/* * irix5sys.h: 32-bit IRIX5 ABI system call table. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) diff -Nru a/arch/mips/kernel/irixelf.c b/arch/mips/kernel/irixelf.c --- a/arch/mips/kernel/irixelf.c Tue Jul 1 18:44:39 2003 +++ b/arch/mips/kernel/irixelf.c Tue Jul 1 18:44:39 2003 @@ -45,7 +45,6 @@ static int load_irix_library(struct file *); static int irix_core_dump(long signr, struct pt_regs * regs, struct file *file); -extern int dump_fpu (elf_fpregset_t *); static struct linux_binfmt irix_format = { NULL, THIS_MODULE, load_irix_binary, load_irix_library, @@ -127,7 +126,7 @@ { start = PAGE_ALIGN(start); end = PAGE_ALIGN(end); - if (end <= start) + if (end <= start) return; do_brk(start, end - start); } @@ -157,7 +156,7 @@ elf_addr_t *argv; elf_addr_t *envp; elf_addr_t *sp, *csp; - + #ifdef DEBUG_ELF printk("create_irix_tables: p[%p] argc[%d] envc[%d] " "load_addr[%08x] interp_load_addr[%08x]\n", @@ -246,7 +245,7 @@ elf_bss = 0; last_bss = 0; error = load_addr = 0; - + #ifdef DEBUG_ELF print_elfhdr(interp_elf_ex); #endif @@ -267,7 +266,7 @@ return 0xffffffff; } - elf_phdata = (struct elf_phdr *) + elf_phdata = (struct elf_phdr *) kmalloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum, GFP_KERNEL); @@ -393,7 +392,7 @@ return -ENOEXEC; /* First of all, some simple consistency checks */ - if((ehp->e_type != ET_EXEC && ehp->e_type != ET_DYN) || + if((ehp->e_type != ET_EXEC && ehp->e_type != ET_DYN) || !irix_elf_check_arch(ehp) || !bprm->file->f_op->mmap) { return -ENOEXEC; } @@ -557,7 +556,7 @@ } /* - * IRIX maps a page at 0x200000 that holds information about the + * IRIX maps a page at 0x200000 that holds information about the * process and the system, here we map the page and fill the * structure */ @@ -567,20 +566,20 @@ struct prda *pp; v = do_brk (PRDA_ADDRESS, PAGE_SIZE); - + if (v < 0) return; pp = (struct prda *) v; pp->prda_sys.t_pid = current->pid; - pp->prda_sys.t_prid = read_32bit_cp0_register (CP0_PRID); + pp->prda_sys.t_prid = read_c0_prid(); pp->prda_sys.t_rpid = current->pid; /* We leave the rest set to zero */ } - - + + /* These are the functions used to load ELF style executables and shared * libraries. There is no binary dependent code anywhere else. */ @@ -595,7 +594,7 @@ int retval, has_interp, has_ephdr, size, i; char *elf_interpreter; mm_segment_t old_fs; - + load_addr = 0; has_interp = has_ephdr = 0; elf_ihdr = elf_ephdr = 0; @@ -684,7 +683,7 @@ current->mm->mmap = NULL; current->flags &= ~PF_FORKNOEXEC; elf_entry = (unsigned int) elf_ex.e_entry; - + /* Do this so that we can load the interpreter, if need be. We will * change some of these later. */ @@ -723,7 +722,7 @@ set_binfmt(&irix_format); compute_creds(bprm); current->flags &= ~PF_FORKNOEXEC; - bprm->p = (unsigned long) + bprm->p = (unsigned long) create_irix_tables((char *)bprm->p, bprm->argc, bprm->envc, (elf_interpreter ? &elf_ex : NULL), load_addr, interp_load_addr, regs, elf_ephdr); @@ -811,30 +810,30 @@ if(elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 || !irix_elf_check_arch(&elf_ex) || !file->f_op->mmap) return -ENOEXEC; - + /* Now read in all of the header information. */ if(sizeof(struct elf_phdr) * elf_ex.e_phnum > PAGE_SIZE) return -ENOEXEC; - - elf_phdata = (struct elf_phdr *) + + elf_phdata = (struct elf_phdr *) kmalloc(sizeof(struct elf_phdr) * elf_ex.e_phnum, GFP_KERNEL); if (elf_phdata == NULL) return -ENOMEM; - + retval = kernel_read(file, elf_ex.e_phoff, (char *) elf_phdata, sizeof(struct elf_phdr) * elf_ex.e_phnum); - + j = 0; for(i=0; ip_type == PT_LOAD) j++; - + if(j != 1) { kfree(elf_phdata); return -ENOEXEC; } - + while(elf_phdata->p_type != PT_LOAD) elf_phdata++; - + /* Now use mmap to map the library into memory. */ down_write(¤t->mm->mmap_sem); error = do_mmap(file, @@ -862,7 +861,7 @@ kfree(elf_phdata); return 0; } - + /* Called through irix_syssgi() to map an elf image given an FD, * a phdr ptr USER_PHDRP in userspace, and a count CNT telling how many * phdrs there are in the USER_PHDRP array. We return the vaddr the @@ -1025,7 +1024,7 @@ DUMP_SEEK(roundup((unsigned long)file->f_pos, 4)); /* XXX */ DUMP_WRITE(men->data, men->datasz); DUMP_SEEK(roundup((unsigned long)file->f_pos, 4)); /* XXX */ - + return 1; end_coredump: @@ -1071,13 +1070,13 @@ if (maydump(vma)) { int sz = vma->vm_end-vma->vm_start; - + if (size+sz >= limit) break; else size += sz; } - + segs++; } #ifdef DEBUG @@ -1104,7 +1103,7 @@ elf.e_shentsize = 0; elf.e_shnum = 0; elf.e_shstrndx = 0; - + fs = get_fs(); set_fs(KERNEL_DS); @@ -1129,24 +1128,24 @@ prstatus.pr_sigpend = current->pending.signal.sig[0]; prstatus.pr_sighold = current->blocked.sig[0]; psinfo.pr_pid = prstatus.pr_pid = current->pid; - psinfo.pr_ppid = prstatus.pr_ppid = current->p_pptr->pid; + psinfo.pr_ppid = prstatus.pr_ppid = current->parent->pid; psinfo.pr_pgrp = prstatus.pr_pgrp = current->pgrp; psinfo.pr_sid = prstatus.pr_sid = current->session; - prstatus.pr_utime.tv_sec = CT_TO_SECS(current->times.tms_utime); - prstatus.pr_utime.tv_usec = CT_TO_USECS(current->times.tms_utime); - prstatus.pr_stime.tv_sec = CT_TO_SECS(current->times.tms_stime); - prstatus.pr_stime.tv_usec = CT_TO_USECS(current->times.tms_stime); - prstatus.pr_cutime.tv_sec = CT_TO_SECS(current->times.tms_cutime); - prstatus.pr_cutime.tv_usec = CT_TO_USECS(current->times.tms_cutime); - prstatus.pr_cstime.tv_sec = CT_TO_SECS(current->times.tms_cstime); - prstatus.pr_cstime.tv_usec = CT_TO_USECS(current->times.tms_cstime); + prstatus.pr_utime.tv_sec = CT_TO_SECS(current->utime); + prstatus.pr_utime.tv_usec = CT_TO_USECS(current->utime); + prstatus.pr_stime.tv_sec = CT_TO_SECS(current->stime); + prstatus.pr_stime.tv_usec = CT_TO_USECS(current->stime); + prstatus.pr_cutime.tv_sec = CT_TO_SECS(current->cutime); + prstatus.pr_cutime.tv_usec = CT_TO_USECS(current->cutime); + prstatus.pr_cstime.tv_sec = CT_TO_SECS(current->cstime); + prstatus.pr_cstime.tv_usec = CT_TO_USECS(current->cstime); if (sizeof(elf_gregset_t) != sizeof(struct pt_regs)) { printk("sizeof(elf_gregset_t) (%d) != sizeof(struct pt_regs) " "(%d)\n", sizeof(elf_gregset_t), sizeof(struct pt_regs)); } else { *(struct pt_regs *)&prstatus.pr_reg = *regs; } - + notes[1].name = "CORE"; notes[1].type = NT_PRPSINFO; notes[1].datasz = sizeof(psinfo); @@ -1155,7 +1154,7 @@ psinfo.pr_state = i; psinfo.pr_sname = (i < 0 || i > 5) ? '.' : "RSDZTD"[i]; psinfo.pr_zomb = psinfo.pr_sname == 'Z'; - psinfo.pr_nice = current->nice; + psinfo.pr_nice = task_nice(current); psinfo.pr_flag = current->flags; psinfo.pr_uid = current->uid; psinfo.pr_gid = current->gid; @@ -1163,7 +1162,7 @@ int i, len; set_fs(fs); - + len = current->mm->arg_end - current->mm->arg_start; len = len >= ELF_PRARGSZ ? ELF_PRARGSZ : len; copy_from_user(&psinfo.pr_psargs, @@ -1183,7 +1182,7 @@ notes[2].data = current; /* Try to dump the FPU. */ - prstatus.pr_fpvalid = dump_fpu (&fpu); + prstatus.pr_fpvalid = dump_fpu (regs, &fpu); if (!prstatus.pr_fpvalid) { numnote--; } else { @@ -1200,7 +1199,7 @@ for(i = 0; i < numnote; i++) sz += notesize(¬es[i]); - + phdr.p_type = PT_NOTE; phdr.p_offset = offset; phdr.p_vaddr = 0; @@ -1216,7 +1215,7 @@ /* Page-align dumped data. */ dataoff = offset = roundup(offset, PAGE_SIZE); - + /* Write program headers for segments dump. */ for(vma = current->mm->mmap, i = 0; i < segs && vma != NULL; vma = vma->vm_next) { @@ -1226,7 +1225,7 @@ i++; sz = vma->vm_end - vma->vm_start; - + phdr.p_type = PT_LOAD; phdr.p_offset = offset; phdr.p_vaddr = vma->vm_start; @@ -1245,17 +1244,17 @@ for(i = 0; i < numnote; i++) if (!writenote(¬es[i], file)) goto end_coredump; - + set_fs(fs); DUMP_SEEK(dataoff); - + for(i = 0, vma = current->mm->mmap; i < segs && vma != NULL; vma = vma->vm_next) { unsigned long addr = vma->vm_start; unsigned long len = vma->vm_end - vma->vm_start; - + if (!maydump(vma)) continue; i++; diff -Nru a/arch/mips/kernel/irixinv.c b/arch/mips/kernel/irixinv.c --- a/arch/mips/kernel/irixinv.c Tue Jul 1 18:44:31 2003 +++ b/arch/mips/kernel/irixinv.c Tue Jul 1 18:44:31 2003 @@ -1,11 +1,9 @@ /* * Support the inventory interface for IRIX binaries * This is invoked before the mm layer is working, so we do not - * use the linked lists for the inventory yet. + * use the linked lists for the inventory yet. * * Miguel de Icaza, 1997. - * - * $Id: irixinv.c,v 1.3 1998/04/05 11:23:51 ralf Exp $ */ #include #include @@ -18,14 +16,13 @@ static inventory_t inventory [MAX_INVENTORY]; -void -add_to_inventory (int class, int type, int controller, int unit, int state) +void add_to_inventory (int class, int type, int controller, int unit, int state) { inventory_t *ni = &inventory [inventory_items]; if (inventory_items == MAX_INVENTORY) return; - + ni->inv_class = class; ni->inv_type = type; ni->inv_controller = controller; @@ -35,8 +32,7 @@ inventory_items++; } -int -dump_inventory_to_user (void *userbuf, int size) +int dump_inventory_to_user (void *userbuf, int size) { inventory_t *inv = &inventory [0]; inventory_t *user = userbuf; @@ -53,13 +49,13 @@ return inventory_items * sizeof (inventory_t); } -void __init init_inventory (void) +static int __init init_inventory(void) { - /* gross hack while we put the right bits all over the kernel + /* + * gross hack while we put the right bits all over the kernel * most likely this will not let just anyone run the X server * until we put the right values all over the place */ - add_to_inventory (10, 3, 0, 0, 16400); add_to_inventory (1, 1, 150, -1, 12); add_to_inventory (1, 3, 0, 0, 8976); @@ -78,4 +74,8 @@ add_to_inventory (2, 2, 0, 2, 0); add_to_inventory (2, 2, 0, 1, 0); add_to_inventory (7, 14, 0, 0, 6); + + return 0; } + +module_init(init_inventory); diff -Nru a/arch/mips/kernel/irixioctl.c b/arch/mips/kernel/irixioctl.c --- a/arch/mips/kernel/irixioctl.c Tue Jul 1 18:44:36 2003 +++ b/arch/mips/kernel/irixioctl.c Tue Jul 1 18:44:36 2003 @@ -10,6 +10,7 @@ #include #include #include +#include #include #include diff -Nru a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c --- a/arch/mips/kernel/irixsig.c Tue Jul 1 18:44:37 2003 +++ b/arch/mips/kernel/irixsig.c Tue Jul 1 18:44:37 2003 @@ -17,7 +17,7 @@ #include #include -extern asmlinkage void syscall_trace(void); +extern asmlinkage void do_syscall_trace(void); #undef DEBUG_SIG @@ -117,7 +117,8 @@ regs->regs[5] = 0; /* XXX sigcode XXX */ regs->regs[6] = regs->regs[29] = sp; regs->regs[7] = (unsigned long) ka->sa.sa_handler; - regs->regs[25] = regs->cp0_epc = (unsigned long) ka->sa.sa_restorer; + regs->regs[25] = regs->cp0_epc = (unsigned long) ka->sa_restorer; + return; segv_and_exit: @@ -134,27 +135,11 @@ do_exit(SIGSEGV); } -static inline void handle_signal(unsigned long sig, struct k_sigaction *ka, - siginfo_t *info, sigset_t *oldset, struct pt_regs * regs) +static inline void handle_signal(unsigned long sig, siginfo_t *info, + sigset_t *oldset, struct pt_regs * regs) { - if (ka->sa.sa_flags & SA_SIGINFO) - setup_irix_rt_frame(ka, regs, sig, oldset, info); - else - setup_irix_frame(ka, regs, sig, oldset); + struct k_sigaction *ka = ¤t->sighand->action[sig-1]; - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; - if (!(ka->sa.sa_flags & SA_NODEFER)) { - spin_lock_irq(¤t->sigmask_lock); - sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); - sigaddset(¤t->blocked,sig); - recalc_sigpending(); - spin_unlock_irq(¤t->sigmask_lock); - } -} - -static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) -{ switch(regs->regs[0]) { case ERESTARTNOHAND: regs->regs[2] = EINTR; @@ -170,111 +155,34 @@ } regs->regs[0] = 0; /* Don't deal with this again. */ + + if (ka->sa.sa_flags & SA_SIGINFO) + setup_irix_rt_frame(ka, regs, sig, oldset, info); + else + setup_irix_frame(ka, regs, sig, oldset); + + if (ka->sa.sa_flags & SA_ONESHOT) + ka->sa.sa_handler = SIG_DFL; + if (!(ka->sa.sa_flags & SA_NODEFER)) { + spin_lock_irq(¤t->sighand->siglock); + sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + sigaddset(¤t->blocked,sig); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + } } asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs) { - struct k_sigaction *ka; siginfo_t info; + int signr; if (!oldset) oldset = ¤t->blocked; - for (;;) { - unsigned long signr; - - spin_lock_irq(¤t->sigmask_lock); - signr = dequeue_signal(current, ¤t->blocked, &info); - spin_unlock_irq(¤t->sigmask_lock); - - if (!signr) - break; - - if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) { - /* Let the debugger run. */ - current->exit_code = signr; - current->state = TASK_STOPPED; - notify_parent(current, SIGCHLD); - schedule(); - - /* We're back. Did the debugger cancel the sig? */ - if (!(signr = current->exit_code)) - continue; - current->exit_code = 0; - - /* The debugger continued. Ignore SIGSTOP. */ - if (signr == SIGSTOP) - continue; - - /* Update the siginfo structure. Is this good? */ - if (signr != info.si_signo) { - info.si_signo = signr; - info.si_errno = 0; - info.si_code = SI_USER; - info.si_pid = current->p_pptr->pid; - info.si_uid = current->p_pptr->uid; - } - - /* If the (new) signal is now blocked, requeue it. */ - if (sigismember(¤t->blocked, signr)) { - send_sig_info(signr, &info, current); - continue; - } - } - - ka = ¤t->sig->action[signr-1]; - if (ka->sa.sa_handler == SIG_IGN) { - if (signr != SIGCHLD) - continue; - /* Check for SIGCHLD: it's special. */ - while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0) - /* nothing */; - continue; - } - - if (ka->sa.sa_handler == SIG_DFL) { - int exit_code = signr; - - /* Init gets no signals it doesn't want. */ - if (current->pid == 1) - continue; - - switch (signr) { - case SIGCONT: case SIGCHLD: case SIGWINCH: - continue; - - case SIGTSTP: case SIGTTIN: case SIGTTOU: - if (is_orphaned_pgrp(current->pgrp)) - continue; - /* FALLTHRU */ - - case SIGSTOP: - current->state = TASK_STOPPED; - current->exit_code = signr; - if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) - notify_parent(current, SIGCHLD); - schedule(); - continue; - - case SIGQUIT: case SIGILL: case SIGTRAP: - case SIGABRT: case SIGFPE: case SIGSEGV: - if (do_coredump(signr, regs)) - exit_code |= 0x80; - /* FALLTHRU */ - - default: - sigaddset(¤t->pending.signal, signr); - recalc_sigpending(); - current->flags |= PF_SIGNALED; - do_exit(exit_code); - /* NOTREACHED */ - } - } - - if (regs->regs[0]) - syscall_restart(regs, ka); - /* Whee! Actually deliver the signal. */ - handle_signal(signr, ka, &info, oldset, regs); + signr = get_signal_to_deliver(&info, regs, NULL); + if (signr > 0) { + handle_signal(signr, &info, oldset, regs); return 1; } @@ -343,19 +251,19 @@ goto badframe; sigdelsetmask(&blocked, ~_BLOCKABLE); - spin_lock_irq(¤t->sigmask_lock); + spin_lock_irq(¤t->sighand->siglock); current->blocked = blocked; recalc_sigpending(); - spin_unlock_irq(¤t->sigmask_lock); + spin_unlock_irq(¤t->sighand->siglock); /* * Don't let your children do this ... */ - if (current->ptrace & PT_TRACESYS) - syscall_trace(); + if (current_thread_info()->flags & TIF_SYSCALL_TRACE) + do_syscall_trace(); __asm__ __volatile__( "move\t$29,%0\n\t" - "j\tret_from_sys_call" + "j\tsyscall_exit" :/* no outputs */ :"r" (®s)); /* Unreached */ @@ -380,7 +288,7 @@ } #endif -asmlinkage int +asmlinkage int irix_sigaction(int sig, const struct sigaction *act, struct sigaction *oact, void *trampoline) { @@ -408,7 +316,7 @@ * value for all invocations of sigaction. Will have to * investigate. POSIX POSIX, die die die... */ - new_ka.sa.sa_restorer = trampoline; + new_ka.sa_restorer = trampoline; } /* XXX Implement SIG_SETMASK32 for IRIX compatibility */ @@ -443,7 +351,7 @@ __copy_from_user(&newbits, new, sizeof(unsigned long)*4); sigdelsetmask(&newbits, ~_BLOCKABLE); - spin_lock_irq(¤t->sigmask_lock); + spin_lock_irq(¤t->sighand->siglock); oldbits = current->blocked; switch(how) { @@ -466,7 +374,7 @@ return -EINVAL; } recalc_sigpending(); - spin_unlock_irq(¤t->sigmask_lock); + spin_unlock_irq(¤t->sighand->siglock); } if(old) { error = verify_area(VERIFY_WRITE, old, sizeof(*old)); @@ -487,11 +395,11 @@ return -EFAULT; sigdelsetmask(&newset, ~_BLOCKABLE); - spin_lock_irq(¤t->sigmask_lock); + spin_lock_irq(¤t->sighand->siglock); saveset = current->blocked; current->blocked = newset; recalc_sigpending(); - spin_unlock_irq(¤t->sigmask_lock); + spin_unlock_irq(¤t->sighand->siglock); regs->regs[2] = -EINTR; while (1) { @@ -640,7 +548,9 @@ { int flag, retval; DECLARE_WAITQUEUE(wait, current); + struct task_struct *tsk; struct task_struct *p; + struct list_head *_p; if (!info) { retval = -EINVAL; @@ -667,7 +577,9 @@ flag = 0; current->state = TASK_INTERRUPTIBLE; read_lock(&tasklist_lock); - for (p = current->p_cptr; p; p = p->p_osptr) { + tsk = current; + list_for_each(_p,&tsk->children) { + p = list_entry(_p,struct task_struct,sibling); if ((type == P_PID) && p->pid != pid) continue; if ((type == P_PGID) && p->pgrp != pid) @@ -676,50 +588,63 @@ continue; flag = 1; switch (p->state) { - case TASK_STOPPED: - if (!p->exit_code) - continue; - if (!(options & (W_TRAPPED|W_STOPPED)) && - !(p->ptrace & PT_PTRACED)) - continue; - if (ru != NULL) - getrusage(p, RUSAGE_BOTH, ru); - __put_user(SIGCHLD, &info->sig); - __put_user(0, &info->code); - __put_user(p->pid, &info->stuff.procinfo.pid); - __put_user((p->exit_code >> 8) & 0xff, + case TASK_STOPPED: + if (!p->exit_code) + continue; + if (!(options & (W_TRAPPED|W_STOPPED)) && + !(p->ptrace & PT_PTRACED)) + continue; + read_unlock(&tasklist_lock); + + /* move to end of parent's list to avoid starvation */ + write_lock_irq(&tasklist_lock); + remove_parent(p); + add_parent(p, p->parent); + write_unlock_irq(&tasklist_lock); + retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0; + if (!retval && ru) { + retval |= __put_user(SIGCHLD, &info->sig); + retval |= __put_user(0, &info->code); + retval |= __put_user(p->pid, &info->stuff.procinfo.pid); + retval |= __put_user((p->exit_code >> 8) & 0xff, &info->stuff.procinfo.procdata.child.status); - __put_user(p->times.tms_utime, &info->stuff.procinfo.procdata.child.utime); - __put_user(p->times.tms_stime, &info->stuff.procinfo.procdata.child.stime); + retval |= __put_user(p->utime, &info->stuff.procinfo.procdata.child.utime); + retval |= __put_user(p->stime, &info->stuff.procinfo.procdata.child.stime); + } + if (!retval) { p->exit_code = 0; - retval = 0; - goto end_waitsys; - case TASK_ZOMBIE: - current->times.tms_cutime += p->times.tms_utime + p->times.tms_cutime; - current->times.tms_cstime += p->times.tms_stime + p->times.tms_cstime; - if (ru != NULL) - getrusage(p, RUSAGE_BOTH, ru); - __put_user(SIGCHLD, &info->sig); - __put_user(1, &info->code); /* CLD_EXITED */ - __put_user(p->pid, &info->stuff.procinfo.pid); - __put_user((p->exit_code >> 8) & 0xff, - &info->stuff.procinfo.procdata.child.status); - __put_user(p->times.tms_utime, - &info->stuff.procinfo.procdata.child.utime); - __put_user(p->times.tms_stime, - &info->stuff.procinfo.procdata.child.stime); - retval = 0; - if (p->p_opptr != p->p_pptr) { - REMOVE_LINKS(p); - p->p_pptr = p->p_opptr; - SET_LINKS(p); - notify_parent(p, SIGCHLD); - } else - release_task(p); - goto end_waitsys; - default: - continue; + } + goto end_waitsys; + + case TASK_ZOMBIE: + current->cutime += p->utime + p->cutime; + current->cstime += p->stime + p->cstime; + if (ru != NULL) + getrusage(p, RUSAGE_BOTH, ru); + __put_user(SIGCHLD, &info->sig); + __put_user(1, &info->code); /* CLD_EXITED */ + __put_user(p->pid, &info->stuff.procinfo.pid); + __put_user((p->exit_code >> 8) & 0xff, + &info->stuff.procinfo.procdata.child.status); + __put_user(p->utime, + &info->stuff.procinfo.procdata.child.utime); + __put_user(p->stime, + &info->stuff.procinfo.procdata.child.stime); + retval = 0; + if (p->real_parent != p->parent) { + write_lock_irq(&tasklist_lock); + remove_parent(p); + p->parent = p->real_parent; + add_parent(p, p->parent); + do_notify_parent(p, SIGCHLD); + write_unlock_irq(&tasklist_lock); + } else + release_task(p); + goto end_waitsys; + default: + continue; } + tsk = next_thread(tsk); } read_unlock(&tasklist_lock); if (flag) { diff -Nru a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c --- a/arch/mips/kernel/irq.c Tue Jul 1 18:44:32 2003 +++ b/arch/mips/kernel/irq.c Tue Jul 1 18:44:32 2003 @@ -8,18 +8,24 @@ * Copyright (C) 1992 Linus Torvalds * Copyright (C) 1994 - 2000 Ralf Baechle */ +#include #include -#include +#include #include #include #include +#include +#include #include #include #include #include #include +#include +#include #include +#include /* * Controller mappings for all interrupt sources: @@ -31,11 +37,14 @@ } }; +static void register_irq_proc (unsigned int irq); + /* * Special irq handlers. */ -void no_action(int cpl, void *dev_id, struct pt_regs *regs) { } +irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs) +{ return IRQ_NONE; } /* * Generic no controller code @@ -68,7 +77,7 @@ end_none }; -volatile unsigned long irq_err_count, spurious_count; +atomic_t irq_err_count; /* * Generic, controller-independent functions: @@ -76,35 +85,53 @@ int show_interrupts(struct seq_file *p, void *v) { + int i, j; struct irqaction * action; unsigned long flags; - int i; - - seq_puts(p, " "); - for (i=0; i < 1 /*smp_num_cpus*/; i++) - seq_printf(p, "CPU%d ", i); + + seq_printf(p, " "); + for (j=0; jtypename); seq_printf(p, " %s", action->name); for (action=action->next; action; action = action->next) seq_printf(p, ", %s", action->name); + seq_putc(p, '\n'); -unlock: +skip: spin_unlock_irqrestore(&irq_desc[i].lock, flags); } - seq_printf(p, "ERR: %10lu\n", irq_err_count); + seq_putc(p, '\n'); + seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); + return 0; } +#ifdef CONFIG_SMP +inline void synchronize_irq(unsigned int irq) +{ + while (irq_desc[irq].status & IRQ_INPROGRESS) + cpu_relax(); +} +#endif + /* * This should really return information about whether * we should do bottom half handling etc. Right now we @@ -114,37 +141,112 @@ */ int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action) { - int status; - int cpu = smp_processor_id(); - - irq_enter(cpu, irq); - - status = 1; /* Force the "do bottom halves" bit */ + int status = 1; /* Force the "do bottom halves" bit */ + int retval = 0; if (!(action->flags & SA_INTERRUPT)) local_irq_enable(); do { status |= action->flags; - action->handler(irq, action->dev_id, regs); + retval |= action->handler(irq, action->dev_id, regs); action = action->next; } while (action); if (status & SA_SAMPLE_RANDOM) add_interrupt_randomness(irq); local_irq_disable(); - irq_exit(cpu, irq); + return retval; +} + +static void __report_bad_irq(int irq, irq_desc_t *desc, irqreturn_t action_ret) +{ + struct irqaction *action; + + if (action_ret != IRQ_HANDLED && action_ret != IRQ_NONE) { + printk(KERN_ERR "irq event %d: bogus return value %x\n", + irq, action_ret); + } else { + printk(KERN_ERR "irq %d: nobody cared!\n", irq); + } + dump_stack(); + printk(KERN_ERR "handlers:\n"); + action = desc->action; + do { + printk(KERN_ERR "[<%p>]", action->handler); + print_symbol(" (%s)", + (unsigned long)action->handler); + printk("\n"); + action = action->next; + } while (action); +} + +static void report_bad_irq(int irq, irq_desc_t *desc, irqreturn_t action_ret) +{ + static int count = 100; + + if (count) { + count--; + __report_bad_irq(irq, desc, action_ret); + } +} + +static int noirqdebug; - return status; +static int __init noirqdebug_setup(char *str) +{ + noirqdebug = 1; + printk("IRQ lockup detection disabled\n"); + return 1; +} + +__setup("noirqdebug", noirqdebug_setup); + +/* + * If 99,900 of the previous 100,000 interrupts have not been handled then + * assume that the IRQ is stuck in some manner. Drop a diagnostic and try to + * turn the IRQ off. + * + * (The other 100-of-100,000 interrupts may have been a correctly-functioning + * device sharing an IRQ with the failing one) + * + * Called under desc->lock + */ +static void note_interrupt(int irq, irq_desc_t *desc, irqreturn_t action_ret) +{ + if (action_ret != IRQ_HANDLED) { + desc->irqs_unhandled++; + if (action_ret != IRQ_NONE) + report_bad_irq(irq, desc, action_ret); + } + + desc->irq_count++; + if (desc->irq_count < 100000) + return; + + desc->irq_count = 0; + if (desc->irqs_unhandled > 99900) { + /* + * The interrupt is stuck + */ + __report_bad_irq(irq, desc, action_ret); + /* + * Now kill the IRQ + */ + printk(KERN_EMERG "Disabling IRQ #%d\n", irq); + desc->status |= IRQ_DISABLED; + desc->handler->disable(irq); + } + desc->irqs_unhandled = 0; } /* * Generic enable/disable code: this just calls * down into the PIC-specific version for the actual * hardware disable after having gotten the irq - * controller lock. + * controller lock. */ - + /** * disable_irq_nosync - disable an irq without waiting * @irq: Interrupt to disable @@ -155,7 +257,7 @@ * * This function may be called from IRQ context. */ - + void inline disable_irq_nosync(unsigned int irq) { irq_desc_t *desc = irq_desc + irq; @@ -181,16 +283,11 @@ * * This function may be called - with care - from IRQ context. */ - + void disable_irq(unsigned int irq) { disable_irq_nosync(irq); - - if (!local_irq_count(smp_processor_id())) { - do { - barrier(); - } while (irq_desc[irq].status & IRQ_INPROGRESS); - } + synchronize_irq(irq); } /** @@ -202,7 +299,7 @@ * * This function may be called from IRQ context. */ - + void enable_irq(unsigned int irq) { irq_desc_t *desc = irq_desc + irq; @@ -237,7 +334,7 @@ */ asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs) { - /* + /* * We ack quickly, we don't want the irq controller * thinking we're snobs just because some other CPU has * disabled global interrupts (we have already done the @@ -252,6 +349,7 @@ struct irqaction * action; unsigned int status; + irq_enter(); kstat_cpu(cpu).irqs[irq]++; spin_lock(&desc->lock); desc->handler->ack(irq); @@ -267,7 +365,7 @@ * use the action we have. */ action = NULL; - if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) { + if (likely(!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))) { action = desc->action; status &= ~IRQ_PENDING; /* we commit to handling */ status |= IRQ_INPROGRESS; /* we are handling it */ @@ -280,7 +378,7 @@ a different instance of this same irq, the other processor will take care of it. */ - if (!action) + if (unlikely(!action)) goto out; /* @@ -294,15 +392,19 @@ * SMP environment. */ for (;;) { + irqreturn_t action_ret; + spin_unlock(&desc->lock); - handle_IRQ_event(irq, regs, action); + action_ret = handle_IRQ_event(irq, ®s, action); spin_lock(&desc->lock); - - if (!(desc->status & IRQ_PENDING)) + if (!noirqdebug) + note_interrupt(irq, desc, action_ret); + if (likely(!(desc->status & IRQ_PENDING))) break; desc->status &= ~IRQ_PENDING; } desc->status &= ~IRQ_INPROGRESS; + out: /* * The ->end() handler has to deal with interrupts which got @@ -311,8 +413,8 @@ desc->handler->end(irq); spin_unlock(&desc->lock); - if (softirq_pending(cpu)) - do_softirq(); + irq_exit(); + return 1; } @@ -327,7 +429,7 @@ * This call allocates interrupt resources and enables the * interrupt line and IRQ handling. From the point this * call is made your handler function may be invoked. Since - * your handler function must clear any interrupt the board + * your handler function must clear any interrupt the board * raises, you must take care both to initialise your hardware * and to set up the interrupt handler in the right order. * @@ -347,10 +449,10 @@ * SA_SAMPLE_RANDOM The interrupt can be used for entropy * */ - -int request_irq(unsigned int irq, - void (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, + +int request_irq(unsigned int irq, + irqreturn_t (*handler)(int, void *, struct pt_regs *), + unsigned long irqflags, const char * devname, void *dev_id) { @@ -376,7 +478,7 @@ return -EINVAL; action = (struct irqaction *) - kmalloc(sizeof(struct irqaction), GFP_KERNEL); + kmalloc(sizeof(struct irqaction), GFP_ATOMIC); if (!action) return -ENOMEM; @@ -405,12 +507,9 @@ * does not return until any executing interrupts for this IRQ * have completed. * - * This function may be called from interrupt context. - * - * Bugs: Attempting to free an irq in a handler for the same irq hangs - * the machine. + * This function must not be called from interrupt context. */ - + void free_irq(unsigned int irq, void *dev_id) { irq_desc_t *desc; @@ -439,11 +538,8 @@ } spin_unlock_irqrestore(&desc->lock,flags); -#ifdef CONFIG_SMP /* Wait to make sure it's not being used on another CPU */ - while (desc->status & IRQ_INPROGRESS) - barrier(); -#endif + synchronize_irq(irq); kfree(action); return; } @@ -471,7 +567,7 @@ * and a mask of potential interrupt lines is returned. * */ - + unsigned long probe_irq_on(void) { unsigned int i; @@ -480,22 +576,22 @@ unsigned long delay; down(&probe_sem); - /* + /* * something may have generated an irq long ago and we want to - * flush such a longstanding irq before considering it as spurious. + * flush such a longstanding irq before considering it as spurious. */ for (i = NR_IRQS-1; i > 0; i--) { desc = irq_desc + i; spin_lock_irq(&desc->lock); - if (!irq_desc[i].action) + if (!irq_desc[i].action) irq_desc[i].handler->startup(i); spin_unlock_irq(&desc->lock); } /* Wait for longstanding interrupts to trigger. */ for (delay = jiffies + HZ/50; time_after(delay, jiffies); ) - /* about 20ms delay */ synchronize_irq(); + /* about 20ms delay */ barrier(); /* * enable any unassigned irqs @@ -518,7 +614,7 @@ * Wait for spurious interrupts to trigger */ for (delay = jiffies + HZ/10; time_after(delay, jiffies); ) - /* about 100ms delay */ synchronize_irq(); + /* about 100ms delay */ barrier(); /* * Now filter out any obviously spurious interrupts @@ -550,7 +646,7 @@ * Return a mask of triggered interrupts (this * can handle only legacy ISA interrupts). */ - + /** * probe_irq_mask - scan a bitmap of interrupt lines * @val: mask of interrupts to consider @@ -612,7 +708,7 @@ * nothing prevents two IRQ probe callers from overlapping. The * results of this are non-optimal. */ - + int probe_irq_off(unsigned long val) { int i, irq_found, nr_irqs; @@ -693,12 +789,12 @@ if (!shared) { desc->depth = 0; - desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING); + desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS); desc->handler->startup(irq); } spin_unlock_irqrestore(&desc->lock,flags); - /* register_irq_proc(irq); */ + register_irq_proc(irq); return 0; } @@ -712,4 +808,177 @@ irq_desc[i].depth = 1; irq_desc[i].handler = &no_irq_type; } +} + +EXPORT_SYMBOL(disable_irq_nosync); +EXPORT_SYMBOL(disable_irq); +EXPORT_SYMBOL(enable_irq); +EXPORT_SYMBOL(probe_irq_mask); + +static struct proc_dir_entry * root_irq_dir; +static struct proc_dir_entry * irq_dir [NR_IRQS]; + +#define HEX_DIGITS 8 + +static unsigned int parse_hex_value (const char *buffer, + unsigned long count, unsigned long *ret) +{ + unsigned char hexnum [HEX_DIGITS]; + unsigned long value; + int i; + + if (!count) + return -EINVAL; + if (count > HEX_DIGITS) + count = HEX_DIGITS; + if (copy_from_user(hexnum, buffer, count)) + return -EFAULT; + + /* + * Parse the first 8 characters as a hex string, any non-hex char + * is end-of-string. '00e1', 'e1', '00E1', 'E1' are all the same. + */ + value = 0; + + for (i = 0; i < count; i++) { + unsigned int c = hexnum[i]; + + switch (c) { + case '0' ... '9': c -= '0'; break; + case 'a' ... 'f': c -= 'a'-10; break; + case 'A' ... 'F': c -= 'A'-10; break; + default: + goto out; + } + value = (value << 4) | c; + } +out: + *ret = value; + return 0; +} + +#ifdef CONFIG_SMP + +static struct proc_dir_entry * smp_affinity_entry [NR_IRQS]; + +static unsigned long irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL }; +static int irq_affinity_read_proc (char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + if (count < HEX_DIGITS+1) + return -EINVAL; + return sprintf (page, "%08lx\n", irq_affinity[(long)data]); +} + +static int irq_affinity_write_proc (struct file *file, const char *buffer, + unsigned long count, void *data) +{ + int irq = (long) data, full_count = count, err; + unsigned long new_value; + + if (!irq_desc[irq].handler->set_affinity) + return -EIO; + + err = parse_hex_value(buffer, count, &new_value); + + /* + * Do not allow disabling IRQs completely - it's a too easy + * way to make the system unusable accidentally :-) At least + * one online CPU still has to be targeted. + */ + if (!(new_value & cpu_online_map)) + return -EINVAL; + + irq_affinity[irq] = new_value; + irq_desc[irq].handler->set_affinity(irq, new_value); + + return full_count; +} + +#endif + +static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + unsigned long *mask = (unsigned long *) data; + if (count < HEX_DIGITS+1) + return -EINVAL; + return sprintf (page, "%08lx\n", *mask); +} + +static int prof_cpu_mask_write_proc (struct file *file, const char *buffer, + unsigned long count, void *data) +{ + unsigned long *mask = (unsigned long *) data, full_count = count, err; + unsigned long new_value; + + err = parse_hex_value(buffer, count, &new_value); + if (err) + return err; + + *mask = new_value; + return full_count; +} + +#define MAX_NAMELEN 10 + +static void register_irq_proc (unsigned int irq) +{ + char name [MAX_NAMELEN]; + + if (!root_irq_dir || (irq_desc[irq].handler == &no_irq_type) || + irq_dir[irq]) + return; + + memset(name, 0, MAX_NAMELEN); + sprintf(name, "%d", irq); + + /* create /proc/irq/1234 */ + irq_dir[irq] = proc_mkdir(name, root_irq_dir); + +#ifdef CONFIG_SMP + { + struct proc_dir_entry *entry; + + /* create /proc/irq/1234/smp_affinity */ + entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]); + + if (entry) { + entry->nlink = 1; + entry->data = (void *)(long)irq; + entry->read_proc = irq_affinity_read_proc; + entry->write_proc = irq_affinity_write_proc; + } + + smp_affinity_entry[irq] = entry; + } +#endif +} + +unsigned long prof_cpu_mask = -1; + +void init_irq_proc (void) +{ + struct proc_dir_entry *entry; + int i; + + /* create /proc/irq */ + root_irq_dir = proc_mkdir("irq", 0); + + /* create /proc/irq/prof_cpu_mask */ + entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir); + + if (!entry) + return; + + entry->nlink = 1; + entry->data = (void *)&prof_cpu_mask; + entry->read_proc = prof_cpu_mask_read_proc; + entry->write_proc = prof_cpu_mask_write_proc; + + /* + * Create entries for all existing IRQs. + */ + for (i = 0; i < NR_IRQS; i++) + register_irq_proc(i); } diff -Nru a/arch/mips/kernel/irq_cpu.c b/arch/mips/kernel/irq_cpu.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/kernel/irq_cpu.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,117 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * Copyright (C) 2001 Ralf Baechle + * + * This file define the irq handler for MIPS CPU interrupts. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +/* + * Almost all MIPS CPUs define 8 interrupt sources. They are typically + * level triggered (i.e., cannot be cleared from CPU; must be cleared from + * device). The first two are software interrupts which we don't really + * use or support. The last one is usually the CPU timer interrupt if + * counter register is present or, for CPUs with an external FPU, by + * convention it's the FPU exception interrupt. + * + * Don't even think about using this on SMP. You have been warned. + * + * This file exports one global function: + * void mips_cpu_irq_init(int irq_base); + */ +#include +#include +#include + +#include +#include +#include + +static int mips_cpu_irq_base; + +static inline void unmask_mips_irq(unsigned int irq) +{ + clear_c0_cause(0x100 << (irq - mips_cpu_irq_base)); + set_c0_status(0x100 << (irq - mips_cpu_irq_base)); +} + +static inline void mask_mips_irq(unsigned int irq) +{ + clear_c0_status(0x100 << (irq - mips_cpu_irq_base)); +} + +static inline void mips_cpu_irq_enable(unsigned int irq) +{ + unsigned long flags; + + local_irq_save(flags); + unmask_mips_irq(irq); + local_irq_restore(flags); +} + +static void mips_cpu_irq_disable(unsigned int irq) +{ + unsigned long flags; + + local_irq_save(flags); + mask_mips_irq(irq); + local_irq_restore(flags); +} + +static unsigned int mips_cpu_irq_startup(unsigned int irq) +{ + mips_cpu_irq_enable(irq); + + return 0; +} + +#define mips_cpu_irq_shutdown mips_cpu_irq_disable + +/* + * While we ack the interrupt interrupts are disabled and thus we don't need + * to deal with concurrency issues. Same for mips_cpu_irq_end. + */ +static void mips_cpu_irq_ack(unsigned int irq) +{ + /* Only necessary for soft interrupts */ + clear_c0_cause(1 << (irq - mips_cpu_irq_base + 8)); + + mask_mips_irq(irq); +} + +static void mips_cpu_irq_end(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + unmask_mips_irq(irq); +} + +static hw_irq_controller mips_cpu_irq_controller = { + "MIPS", + mips_cpu_irq_startup, + mips_cpu_irq_shutdown, + mips_cpu_irq_enable, + mips_cpu_irq_disable, + mips_cpu_irq_ack, + mips_cpu_irq_end, + NULL /* no affinity stuff for UP */ +}; + +void __init mips_cpu_irq_init(int irq_base) +{ + int i; + + for (i = irq_base; i < irq_base + 8; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = NULL; + irq_desc[i].depth = 1; + irq_desc[i].handler = &mips_cpu_irq_controller; + } + + mips_cpu_irq_base = irq_base; +} diff -Nru a/arch/mips/kernel/mips_ksyms.c b/arch/mips/kernel/mips_ksyms.c --- a/arch/mips/kernel/mips_ksyms.c Tue Jul 1 18:44:33 2003 +++ b/arch/mips/kernel/mips_ksyms.c Tue Jul 1 18:44:33 2003 @@ -12,9 +12,9 @@ #include #include #include -#include #include #include +#include #include #include @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #ifdef CONFIG_BLK_DEV_FD #include @@ -41,7 +41,9 @@ extern long __strnlen_user_asm(const char *s); EXPORT_SYMBOL(mips_machtype); +#ifdef CONFIG_EISA EXPORT_SYMBOL(EISA_bus); +#endif /* * String functions @@ -58,11 +60,8 @@ EXPORT_SYMBOL_NOVERS(strnlen); EXPORT_SYMBOL_NOVERS(strrchr); EXPORT_SYMBOL_NOVERS(strstr); -EXPORT_SYMBOL_NOVERS(strsep); EXPORT_SYMBOL(_clear_page); -EXPORT_SYMBOL(enable_irq); -EXPORT_SYMBOL(disable_irq); EXPORT_SYMBOL(kernel_thread); /* @@ -77,15 +76,6 @@ EXPORT_SYMBOL_NOVERS(__strnlen_user_nocheck_asm); EXPORT_SYMBOL_NOVERS(__strnlen_user_asm); - -/* - * Functions to control caches. - */ -EXPORT_SYMBOL(_flush_page_to_ram); -EXPORT_SYMBOL(_flush_cache_all); -EXPORT_SYMBOL(_dma_cache_wback_inv); -EXPORT_SYMBOL(_dma_cache_inv); - EXPORT_SYMBOL(invalid_pte_table); /* @@ -97,32 +87,11 @@ EXPORT_SYMBOL(__up); /* - * Base address of ports for Intel style I/O. - */ -EXPORT_SYMBOL(mips_io_port_base); - -/* - * Architecture specific stuff. - */ -#ifdef CONFIG_MIPS_JAZZ -EXPORT_SYMBOL(vdma_alloc); -EXPORT_SYMBOL(vdma_free); -EXPORT_SYMBOL(vdma_log2phys); -#endif - -#ifdef CONFIG_SGI_IP22 -EXPORT_SYMBOL(hpc3c0); -#endif - -/* * Kernel hacking ... */ #include #include -int register_fpe(void (*handler)(struct pt_regs *regs, unsigned int fcr31)); -int unregister_fpe(void (*handler)(struct pt_regs *regs, unsigned int fcr31)); - #ifdef CONFIG_VT EXPORT_SYMBOL(screen_info); #endif @@ -132,4 +101,3 @@ #endif EXPORT_SYMBOL(get_wchan); -EXPORT_SYMBOL(flush_tlb_page); diff -Nru a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/kernel/module.c Tue Jul 1 18:44:39 2003 @@ -0,0 +1,242 @@ +/* Kernel module help for MIPS. + Copyright (C) 2001 Rusty Russell. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include +#include +#include +#include +#include +#include +#include + +struct mips_hi16 { + struct mips_hi16 *next; + Elf32_Addr *addr; + Elf32_Addr value; +}; + +static struct mips_hi16 *mips_hi16_list; + +#if 0 +#define DEBUGP printk +#else +#define DEBUGP(fmt , ...) +#endif + +void *module_alloc(unsigned long size) +{ + if (size == 0) + return NULL; + return vmalloc(size); +} + + +/* Free memory returned from module_alloc */ +void module_free(struct module *mod, void *module_region) +{ + vfree(module_region); + /* FIXME: If module_region == mod->init_region, trim exception + table entries. */ +} + +/* We don't need anything special. */ +long module_core_size(const Elf32_Ehdr *hdr, + const Elf32_Shdr *sechdrs, + const char *secstrings, + struct module *module) +{ + return module->core_size; +} + +long module_init_size(const Elf32_Ehdr *hdr, + const Elf32_Shdr *sechdrs, + const char *secstrings, + struct module *module) +{ + return module->init_size; +} + +int module_frob_arch_sections(Elf_Ehdr *hdr, + Elf_Shdr *sechdrs, + char *secstrings, + struct module *mod) +{ + return 0; +} + +int apply_relocate(Elf32_Shdr *sechdrs, + const char *strtab, + unsigned int symindex, + unsigned int relsec, + struct module *me) +{ + unsigned int i; + Elf32_Rel *rel = (void *)sechdrs[relsec].sh_offset; + Elf32_Sym *sym; + uint32_t *location; + Elf32_Addr v; + + DEBUGP("Applying relocate section %u to %u\n", relsec, + sechdrs[relsec].sh_info); + for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { + /* This is where to make the change */ + location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_offset + + rel[i].r_offset; + /* This is the symbol it is referring to */ + sym = (Elf32_Sym *)sechdrs[symindex].sh_offset + + ELF32_R_SYM(rel[i].r_info); + if (!sym->st_value) { + printk(KERN_WARNING "%s: Unknown symbol %s\n", + me->name, strtab + sym->st_name); + return -ENOENT; + } + + v = sym->st_value; + + switch (ELF32_R_TYPE(rel[i].r_info)) { + case R_MIPS_NONE: + break; + + case R_MIPS_32: + *location += v; + break; + + case R_MIPS_26: + if (v % 4) + printk(KERN_ERR + "module %s: dangerous relocation\n", + me->name); + return -ENOEXEC; + if ((v & 0xf0000000) != + (((unsigned long)location + 4) & 0xf0000000)) + printk(KERN_ERR + "module %s: relocation overflow\n", + me->name); + return -ENOEXEC; + *location = (*location & ~0x03ffffff) | + ((*location + (v >> 2)) & 0x03ffffff); + break; + + case R_MIPS_HI16: { + struct mips_hi16 *n; + + /* + * We cannot relocate this one now because we don't + * know the value of the carry we need to add. Save + * the information, and let LO16 do the actual + * relocation. + */ + n = (struct mips_hi16 *) kmalloc(sizeof *n, GFP_KERNEL); + n->addr = location; + n->value = v; + n->next = mips_hi16_list; + mips_hi16_list = n; + break; + } + + case R_MIPS_LO16: { + unsigned long insnlo = *location; + Elf32_Addr val, vallo; + + /* Sign extend the addend we extract from the lo insn. */ + vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000; + + if (mips_hi16_list != NULL) { + struct mips_hi16 *l; + + l = mips_hi16_list; + while (l != NULL) { + struct mips_hi16 *next; + unsigned long insn; + + /* + * The value for the HI16 had best be + * the same. + */ + printk(KERN_ERR "module %s: dangerous " + "relocation\n", me->name); + return -ENOEXEC; + + /* + * Do the HI16 relocation. Note that + * we actually don't need to know + * anything about the LO16 itself, + * except where to find the low 16 bits + * of the addend needed by the LO16. + */ + insn = *l->addr; + val = ((insn & 0xffff) << 16) + vallo; + val += v; + + /* + * Account for the sign extension that + * will happen in the low bits. + */ + val = ((val >> 16) + ((val & 0x8000) != + 0)) & 0xffff; + + insn = (insn & ~0xffff) | val; + *l->addr = insn; + + next = l->next; + kfree(l); + l = next; + } + + mips_hi16_list = NULL; + } + + /* + * Ok, we're done with the HI16 relocs. Now deal with + * the LO16. + */ + val = v + vallo; + insnlo = (insnlo & ~0xffff) | (val & 0xffff); + *location = insnlo; + break; + } + + default: + printk(KERN_ERR "module %s: Unknown relocation: %u\n", + me->name, ELF32_R_TYPE(rel[i].r_info)); + return -ENOEXEC; + } + } + return 0; +} + +int apply_relocate_add(Elf32_Shdr *sechdrs, + const char *strtab, + unsigned int symindex, + unsigned int relsec, + struct module *me) +{ + printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n", + me->name); + return -ENOEXEC; +} + +int module_finalize(const Elf_Ehdr *hdr, + const Elf_Shdr *sechdrs, + struct module *me) +{ + return 0; +} + +void module_arch_cleanup(struct module *mod) +{ +} diff -Nru a/arch/mips/kernel/offset.c b/arch/mips/kernel/offset.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/kernel/offset.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,207 @@ +/* + * offset.c: Calculate pt_regs and task_struct offsets. + * + * Copyright (C) 1996 David S. Miller + * Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Ralf Baechle + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + * + * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. + */ +#include +#include +#include +#include + +#include +#include + +#define text(t) __asm__("\n@@@" t) +#define _offset(type, member) (&(((type *)NULL)->member)) + +#define offset(string, ptr, member) \ + __asm__("\n@@@" string "%0" : : "i" (_offset(ptr, member))) +#define constant(string, member) \ + __asm__("\n@@@" string "%x0" : : "i" (member)) +#define size(string, size) \ + __asm__("\n@@@" string "%0" : : "i" (sizeof(size))) +#define linefeed text("") + +void output_ptreg_defines(void) +{ + text("/* MIPS pt_regs offsets. */"); + offset("#define PT_R0 ", struct pt_regs, regs[0]); + offset("#define PT_R1 ", struct pt_regs, regs[1]); + offset("#define PT_R2 ", struct pt_regs, regs[2]); + offset("#define PT_R3 ", struct pt_regs, regs[3]); + offset("#define PT_R4 ", struct pt_regs, regs[4]); + offset("#define PT_R5 ", struct pt_regs, regs[5]); + offset("#define PT_R6 ", struct pt_regs, regs[6]); + offset("#define PT_R7 ", struct pt_regs, regs[7]); + offset("#define PT_R8 ", struct pt_regs, regs[8]); + offset("#define PT_R9 ", struct pt_regs, regs[9]); + offset("#define PT_R10 ", struct pt_regs, regs[10]); + offset("#define PT_R11 ", struct pt_regs, regs[11]); + offset("#define PT_R12 ", struct pt_regs, regs[12]); + offset("#define PT_R13 ", struct pt_regs, regs[13]); + offset("#define PT_R14 ", struct pt_regs, regs[14]); + offset("#define PT_R15 ", struct pt_regs, regs[15]); + offset("#define PT_R16 ", struct pt_regs, regs[16]); + offset("#define PT_R17 ", struct pt_regs, regs[17]); + offset("#define PT_R18 ", struct pt_regs, regs[18]); + offset("#define PT_R19 ", struct pt_regs, regs[19]); + offset("#define PT_R20 ", struct pt_regs, regs[20]); + offset("#define PT_R21 ", struct pt_regs, regs[21]); + offset("#define PT_R22 ", struct pt_regs, regs[22]); + offset("#define PT_R23 ", struct pt_regs, regs[23]); + offset("#define PT_R24 ", struct pt_regs, regs[24]); + offset("#define PT_R25 ", struct pt_regs, regs[25]); + offset("#define PT_R26 ", struct pt_regs, regs[26]); + offset("#define PT_R27 ", struct pt_regs, regs[27]); + offset("#define PT_R28 ", struct pt_regs, regs[28]); + offset("#define PT_R29 ", struct pt_regs, regs[29]); + offset("#define PT_R30 ", struct pt_regs, regs[30]); + offset("#define PT_R31 ", struct pt_regs, regs[31]); + offset("#define PT_LO ", struct pt_regs, lo); + offset("#define PT_HI ", struct pt_regs, hi); + offset("#define PT_EPC ", struct pt_regs, cp0_epc); + offset("#define PT_BVADDR ", struct pt_regs, cp0_badvaddr); + offset("#define PT_STATUS ", struct pt_regs, cp0_status); + offset("#define PT_CAUSE ", struct pt_regs, cp0_cause); + size("#define PT_SIZE ", struct pt_regs); + linefeed; +} + +void output_task_defines(void) +{ + text("/* MIPS task_struct offsets. */"); + offset("#define TASK_STATE ", struct task_struct, state); + offset("#define TASK_THREAD_INFO ", struct task_struct, thread_info); + offset("#define TASK_FLAGS ", struct task_struct, flags); + offset("#define TASK_MM ", struct task_struct, mm); + offset("#define TASK_PID ", struct task_struct, pid); + size( "#define TASK_STRUCT_SIZE ", struct task_struct); + linefeed; +} + +void output_thread_info_defines(void) +{ + text("/* MIPS thread_info offsets. */"); + offset("#define TI_TASK ", struct thread_info, task); + offset("#define TI_EXEC_DOMAIN ", struct thread_info, exec_domain); + offset("#define TI_FLAGS ", struct thread_info, flags); + offset("#define TI_CPU ", struct thread_info, cpu); + offset("#define TI_PRE_COUNT ", struct thread_info, preempt_count); + offset("#define TI_ADDR_LIMIT ", struct thread_info, addr_limit); + offset("#define TI_RESTART_BLOCK ", struct thread_info, restart_block); + linefeed; +} + +void output_thread_defines(void) +{ + text("/* MIPS specific thread_struct offsets. */"); + offset("#define THREAD_REG16 ", struct task_struct, thread.reg16); + offset("#define THREAD_REG17 ", struct task_struct, thread.reg17); + offset("#define THREAD_REG18 ", struct task_struct, thread.reg18); + offset("#define THREAD_REG19 ", struct task_struct, thread.reg19); + offset("#define THREAD_REG20 ", struct task_struct, thread.reg20); + offset("#define THREAD_REG21 ", struct task_struct, thread.reg21); + offset("#define THREAD_REG22 ", struct task_struct, thread.reg22); + offset("#define THREAD_REG23 ", struct task_struct, thread.reg23); + offset("#define THREAD_REG29 ", struct task_struct, thread.reg29); + offset("#define THREAD_REG30 ", struct task_struct, thread.reg30); + offset("#define THREAD_REG31 ", struct task_struct, thread.reg31); + offset("#define THREAD_STATUS ", struct task_struct, \ + thread.cp0_status); + offset("#define THREAD_FPU ", struct task_struct, thread.fpu); + offset("#define THREAD_BVADDR ", struct task_struct, \ + thread.cp0_badvaddr); + offset("#define THREAD_BUADDR ", struct task_struct, \ + thread.cp0_baduaddr); + offset("#define THREAD_ECODE ", struct task_struct, \ + thread.error_code); + offset("#define THREAD_TRAPNO ", struct task_struct, thread.trap_no); + offset("#define THREAD_MFLAGS ", struct task_struct, thread.mflags); + offset("#define THREAD_TRAMP ", struct task_struct, \ + thread.irix_trampoline); + offset("#define THREAD_OLDCTX ", struct task_struct, \ + thread.irix_oldctx); + linefeed; +} + +void output_mm_defines(void) +{ + text("/* Linux mm_struct offsets. */"); + offset("#define MM_USERS ", struct mm_struct, mm_users); + offset("#define MM_PGD ", struct mm_struct, pgd); + offset("#define MM_CONTEXT ", struct mm_struct, context); + linefeed; + constant("#define _PAGE_SIZE ", PAGE_SIZE); + constant("#define _PGD_ORDER ", PGD_ORDER); + constant("#define _PGDIR_SHIFT ", PGDIR_SHIFT); + linefeed; +} + +void output_sc_defines(void) +{ + text("/* Linux sigcontext offsets. */"); + offset("#define SC_REGS ", struct sigcontext, sc_regs); + offset("#define SC_FPREGS ", struct sigcontext, sc_fpregs); + offset("#define SC_MDHI ", struct sigcontext, sc_mdhi); + offset("#define SC_MDLO ", struct sigcontext, sc_mdlo); + offset("#define SC_PC ", struct sigcontext, sc_pc); + offset("#define SC_STATUS ", struct sigcontext, sc_status); + offset("#define SC_FPC_CSR ", struct sigcontext, sc_fpc_csr); + offset("#define SC_FPC_EIR ", struct sigcontext, sc_fpc_eir); + offset("#define SC_CAUSE ", struct sigcontext, sc_cause); + offset("#define SC_BADVADDR ", struct sigcontext, sc_badvaddr); + linefeed; +} + +void output_signal_defined(void) +{ + text("/* Linux signal numbers. */"); + constant("#define _SIGHUP ", SIGHUP); + constant("#define _SIGINT ", SIGINT); + constant("#define _SIGQUIT ", SIGQUIT); + constant("#define _SIGILL ", SIGILL); + constant("#define _SIGTRAP ", SIGTRAP); + constant("#define _SIGIOT ", SIGIOT); + constant("#define _SIGABRT ", SIGABRT); + constant("#define _SIGEMT ", SIGEMT); + constant("#define _SIGFPE ", SIGFPE); + constant("#define _SIGKILL ", SIGKILL); + constant("#define _SIGBUS ", SIGBUS); + constant("#define _SIGSEGV ", SIGSEGV); + constant("#define _SIGSYS ", SIGSYS); + constant("#define _SIGPIPE ", SIGPIPE); + constant("#define _SIGALRM ", SIGALRM); + constant("#define _SIGTERM ", SIGTERM); + constant("#define _SIGUSR1 ", SIGUSR1); + constant("#define _SIGUSR2 ", SIGUSR2); + constant("#define _SIGCHLD ", SIGCHLD); + constant("#define _SIGPWR ", SIGPWR); + constant("#define _SIGWINCH ", SIGWINCH); + constant("#define _SIGURG ", SIGURG); + constant("#define _SIGIO ", SIGIO); + constant("#define _SIGSTOP ", SIGSTOP); + constant("#define _SIGTSTP ", SIGTSTP); + constant("#define _SIGCONT ", SIGCONT); + constant("#define _SIGTTIN ", SIGTTIN); + constant("#define _SIGTTOU ", SIGTTOU); + constant("#define _SIGVTALRM ", SIGVTALRM); + constant("#define _SIGPROF ", SIGPROF); + constant("#define _SIGXCPU ", SIGXCPU); + constant("#define _SIGXFSZ ", SIGXFSZ); + linefeed; +} + +void output_irq_cpustat_t_defines(void) +{ + text("/* Linux irq_cpustat_t offsets. */"); + offset("#define IC_SOFTIRQ_PENDING ", irq_cpustat_t, __softirq_pending); + offset("#define IC_SYSCALL_COUNT ", irq_cpustat_t, __syscall_count); + offset("#define IC_KSOFTIRQD_TASK ", irq_cpustat_t, __ksoftirqd_task); + size("#define IC_IRQ_CPUSTAT_T ", irq_cpustat_t); + linefeed; +} diff -Nru a/arch/mips/kernel/old-irq.c b/arch/mips/kernel/old-irq.c --- a/arch/mips/kernel/old-irq.c Tue Jul 1 18:44:35 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,410 +0,0 @@ -/* - * 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. - * - * Code to handle x86 style IRQs plus some generic interrupt stuff. - * - * Copyright (C) 1992 Linus Torvalds - * Copyright (C) 1994 - 2001 Ralf Baechle - * - * Old rotten IRQ code. To be killed as soon as everybody had converted or - * in 2.5.0, whatever comes first. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -/* - * The board specific setup routine sets irq_setup to point to a board - * specific setup routine. - */ -void (*irq_setup)(void); - -/* - * Linux has a controller-independent x86 interrupt architecture. - * every controller has a 'controller-template', that is used - * by the main code to do the right thing. Each driver-visible - * interrupt source is transparently wired to the apropriate - * controller. Thus drivers need not be aware of the - * interrupt-controller. - * - * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC, - * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC. - * (IO-APICs assumed to be messaging to Pentium local-APICs) - * - * the code is designed to be easily extended with new/different - * interrupt controllers, without having to do assembly magic. - */ - -/* - * This contains the irq mask for both 8259A irq controllers, it's an - * int so we can deal with the third PIC in some systems like the RM300. - * (XXX This is broken for big endian.) - */ -static unsigned int cached_irq_mask = 0xffff; - -#define __byte(x,y) (((unsigned char *)&(y))[x]) -#define __word(x,y) (((unsigned short *)&(y))[x]) -#define __long(x,y) (((unsigned int *)&(y))[x]) - -#define cached_21 (__byte(0,cached_irq_mask)) -#define cached_A1 (__byte(1,cached_irq_mask)) - -unsigned long spurious_count = 0; - -/* - * (un)mask_irq, disable_irq() and enable_irq() only handle (E)ISA and - * PCI devices. Other onboard hardware needs specific routines. - */ -static inline void mask_irq(unsigned int irq) -{ - cached_irq_mask |= 1 << irq; - if (irq & 8) { - outb(cached_A1, 0xa1); - } else { - outb(cached_21, 0x21); - } -} - -static inline void unmask_irq(unsigned int irq) -{ - cached_irq_mask &= ~(1 << irq); - if (irq & 8) { - outb(cached_A1, 0xa1); - } else { - outb(cached_21, 0x21); - } -} - -void i8259_disable_irq(unsigned int irq_nr) -{ - unsigned long flags; - - save_and_cli(flags); - mask_irq(irq_nr); - restore_flags(flags); -} - -void i8259_enable_irq(unsigned int irq_nr) -{ - unsigned long flags; - save_and_cli(flags); - unmask_irq(irq_nr); - restore_flags(flags); -} - -static struct irqaction *irq_action[NR_IRQS] = { - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - -int show_interrupts(struct seq_file *p, void *v) -{ - int i; - struct irqaction * action; - unsigned long flags; - - for (i = 0 ; i < 32 ; i++) { - local_irq_save(flags); - action = irq_action[i]; - if (!action) - goto skip; - seq_printf(p, "%2d: %8d %c %s", - i, kstat_cpu(0).irqs[i], - (action->flags & SA_INTERRUPT) ? '+' : ' ', - action->name); - for (action=action->next; action; action = action->next) { - seq_printf(p, ",%s %s", - (action->flags & SA_INTERRUPT) ? " +" : "", - action->name); - } - seq_putc(p, '\n'); -skip: - local_irq_restore(flags); - } - return 0; -} - -static inline void i8259_mask_and_ack_irq(int irq) -{ - cached_irq_mask |= 1 << irq; - - if (irq & 8) { - inb(0xa1); - outb(cached_A1, 0xa1); - outb(0x62, 0x20); /* Specific EOI to cascade */ - outb(0x20, 0xa0); - } else { - inb(0x21); - outb(cached_21, 0x21); - outb(0x20, 0x20); - } -} - -asmlinkage void i8259_do_irq(int irq, struct pt_regs *regs) -{ - struct irqaction *action; - int do_random, cpu; - - cpu = smp_processor_id(); - irq_enter(cpu, irq); - - if (irq >= 16) - goto out; - - i8259_mask_and_ack_irq(irq); - - kstat_cpu(cpu).irqs[irq]++; - - action = *(irq + irq_action); - if (!action) - goto out; - - if (!(action->flags & SA_INTERRUPT)) - local_irq_enable(); - action = *(irq + irq_action); - do_random = 0; - do { - do_random |= action->flags; - action->handler(irq, action->dev_id, regs); - action = action->next; - } while (action); - if (do_random & SA_SAMPLE_RANDOM) - add_interrupt_randomness(irq); - local_irq_disable(); - unmask_irq (irq); - -out: - irq_exit(cpu, irq); -} - -/* - * do_IRQ handles IRQ's that have been installed without the - * SA_INTERRUPT flag: it uses the full signal-handling return - * and runs with other interrupts enabled. All relatively slow - * IRQ's should use this format: notably the keyboard/timer - * routines. - */ -asmlinkage void do_IRQ(int irq, struct pt_regs * regs) -{ - struct irqaction *action; - int do_random, cpu; - - cpu = smp_processor_id(); - irq_enter(cpu, irq); - kstat_cpu(cpu).irqs[irq]++; - - action = *(irq + irq_action); - if (action) { - if (!(action->flags & SA_INTERRUPT)) - local_irq_enable(); - action = *(irq + irq_action); - do_random = 0; - do { - do_random |= action->flags; - action->handler(irq, action->dev_id, regs); - action = action->next; - } while (action); - if (do_random & SA_SAMPLE_RANDOM) - add_interrupt_randomness(irq); - local_irq_disable(); - } - irq_exit(cpu, irq); - - if (softirq_pending(cpu)) - do_softirq(); - - /* unmasking and bottom half handling is done magically for us. */ -} - -int i8259_setup_irq(int irq, struct irqaction * new) -{ - int shared = 0; - struct irqaction *old, **p; - unsigned long flags; - - p = irq_action + irq; - if ((old = *p) != NULL) { - /* Can't share interrupts unless both agree to */ - if (!(old->flags & new->flags & SA_SHIRQ)) - return -EBUSY; - - /* Can't share interrupts unless both are same type */ - if ((old->flags ^ new->flags) & SA_INTERRUPT) - return -EBUSY; - - /* add new interrupt at end of irq queue */ - do { - p = &old->next; - old = *p; - } while (old); - shared = 1; - } - - if (new->flags & SA_SAMPLE_RANDOM) - rand_initialize_irq(irq); - - save_and_cli(flags); - *p = new; - - if (!shared) { - if (is_i8259_irq(irq)) - unmask_irq(irq); -#if (defined(CONFIG_DDB5074) || defined(CONFIG_DDB5476)) - else - nile4_enable_irq(irq_to_nile4(irq)); -#endif - } - restore_flags(flags); - return 0; -} - -/* - * Request_interrupt and free_interrupt ``sort of'' handle interrupts of - * non i8259 devices. They will have to be replaced by architecture - * specific variants. For now we still use this as broken as it is because - * it used to work ... - */ -int request_irq(unsigned int irq, - void (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, const char * devname, void *dev_id) -{ - int retval; - struct irqaction * action; - - if (irq >= 32) - return -EINVAL; - if (!handler) - return -EINVAL; - - action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL); - if (!action) - return -ENOMEM; - - action->handler = handler; - action->flags = irqflags; - action->mask = 0; - action->name = devname; - action->next = NULL; - action->dev_id = dev_id; - - retval = i8259_setup_irq(irq, action); - - if (retval) - kfree(action); - return retval; -} - -void free_irq(unsigned int irq, void *dev_id) -{ - struct irqaction * action, **p; - unsigned long flags; - - if (irq > 31) { - printk("Trying to free IRQ%d\n",irq); - return; - } - for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) { - if (action->dev_id != dev_id) - continue; - - /* Found it - now free it */ - save_and_cli(flags); - *p = action->next; - if (!irq[irq_action]) - mask_irq(irq); - restore_flags(flags); - kfree(action); - return; - } - printk("Trying to free free IRQ%d\n",irq); -} - -unsigned long probe_irq_on (void) -{ - unsigned int i, irqs = 0; - unsigned long delay; - - /* first, enable any unassigned (E)ISA irqs */ - for (i = 15; i > 0; i--) { - if (!irq_action[i]) { - i8259_enable_irq(i); - irqs |= (1 << i); - } - } - - /* wait for spurious interrupts to mask themselves out again */ - for (delay = jiffies + HZ/10; time_before(jiffies, delay); ) - /* about 100ms delay */; - - /* now filter out any obviously spurious interrupts */ - return irqs & ~cached_irq_mask; -} - -int probe_irq_off (unsigned long irqs) -{ - unsigned int i; - -#ifdef DEBUG - printk("probe_irq_off: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask); -#endif - irqs &= cached_irq_mask; - if (!irqs) - return 0; - i = ffz(~irqs); - if (irqs != (irqs & (1 << i))) - i = -i; - return i; -} - -void __init i8259_init(void) -{ - /* Init master interrupt controller */ - outb(0x11, 0x20); /* Start init sequence */ - outb(0x00, 0x21); /* Vector base */ - outb(0x04, 0x21); /* edge tiggered, Cascade (slave) on IRQ2 */ - outb(0x01, 0x21); /* Select 8086 mode */ - outb(0xff, 0x21); /* Mask all */ - - /* Init slave interrupt controller */ - outb(0x11, 0xa0); /* Start init sequence */ - outb(0x08, 0xa1); /* Vector base */ - outb(0x02, 0xa1); /* edge triggered, Cascade (slave) on IRQ2 */ - outb(0x01, 0xa1); /* Select 8086 mode */ - outb(0xff, 0xa1); /* Mask all */ - - outb(cached_A1, 0xa1); - outb(cached_21, 0x21); -} - -void __init init_IRQ(void) -{ - /* i8259_init(); */ - irq_setup(); -} diff -Nru a/arch/mips/kernel/old-time.c b/arch/mips/kernel/old-time.c --- a/arch/mips/kernel/old-time.c Tue Jul 1 18:44:36 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,518 +0,0 @@ -/* - * Copyright (C) 1991, 1992, 1995 Linus Torvalds - * Copyright (C) 1996 - 2000 Ralf Baechle - * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - * - * Don't use. Deprecated. Dead meat. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -extern volatile unsigned long wall_jiffies; -unsigned long r4k_interval; -extern rwlock_t xtime_lock; - -/* - * Change this if you have some constant time drift - */ -/* This is the value for the PC-style PICs. */ -/* #define USECS_PER_JIFFY (1000020/HZ) */ - -/* This is for machines which generate the exact clock. */ -#define USECS_PER_JIFFY (1000000/HZ) - -/* Cycle counter value at the previous timer interrupt.. */ - -static unsigned int timerhi, timerlo; - -/* - * On MIPS only R4000 and better have a cycle counter. - * - * FIXME: Does playing with the RP bit in c0_status interfere with this code? - */ -static unsigned long do_fast_gettimeoffset(void) -{ - u32 count; - unsigned long res, tmp; - - /* Last jiffy when do_fast_gettimeoffset() was called. */ - static unsigned long last_jiffies; - unsigned long quotient; - - /* - * Cached "1/(clocks per usec)*2^32" value. - * It has to be recalculated once each jiffy. - */ - static unsigned long cached_quotient; - - tmp = jiffies; - - quotient = cached_quotient; - - if (tmp && last_jiffies != tmp) { - last_jiffies = tmp; - __asm__(".set\tnoreorder\n\t" - ".set\tnoat\n\t" - ".set\tmips3\n\t" - "lwu\t%0,%2\n\t" - "dsll32\t$1,%1,0\n\t" - "or\t$1,$1,%0\n\t" - "ddivu\t$0,$1,%3\n\t" - "mflo\t$1\n\t" - "dsll32\t%0,%4,0\n\t" - "nop\n\t" - "ddivu\t$0,%0,$1\n\t" - "mflo\t%0\n\t" - ".set\tmips0\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=&r" (quotient) - :"r" (timerhi), - "m" (timerlo), - "r" (tmp), - "r" (USECS_PER_JIFFY) - :"$1"); - cached_quotient = quotient; - } - - /* Get last timer tick in absolute kernel time */ - count = read_32bit_cp0_register(CP0_COUNT); - - /* .. relative to previous jiffy (32 bits is enough) */ - count -= timerlo; - - __asm__("multu\t%1,%2\n\t" - "mfhi\t%0" - :"=r" (res) - :"r" (count), - "r" (quotient)); - - /* - * Due to possible jiffies inconsistencies, we need to check - * the result so that we'll get a timer that is monotonic. - */ - if (res >= USECS_PER_JIFFY) - res = USECS_PER_JIFFY-1; - - return res; -} - -/* This function must be called with interrupts disabled - * It was inspired by Steve McCanne's microtime-i386 for BSD. -- jrs - * - * However, the pc-audio speaker driver changes the divisor so that - * it gets interrupted rather more often - it loads 64 into the - * counter rather than 11932! This has an adverse impact on - * do_gettimeoffset() -- it stops working! What is also not - * good is that the interval that our timer function gets called - * is no longer 10.0002 ms, but 9.9767 ms. To get around this - * would require using a different timing source. Maybe someone - * could use the RTC - I know that this can interrupt at frequencies - * ranging from 8192Hz to 2Hz. If I had the energy, I'd somehow fix - * it so that at startup, the timer code in sched.c would select - * using either the RTC or the 8253 timer. The decision would be - * based on whether there was any other device around that needed - * to trample on the 8253. I'd set up the RTC to interrupt at 1024 Hz, - * and then do some jiggery to have a version of do_timer that - * advanced the clock by 1/1024 s. Every time that reached over 1/100 - * of a second, then do all the old code. If the time was kept correct - * then do_gettimeoffset could just return 0 - there is no low order - * divider that can be accessed. - * - * Ideally, you would be able to use the RTC for the speaker driver, - * but it appears that the speaker driver really needs interrupt more - * often than every 120 us or so. - * - * Anyway, this needs more thought.... pjsg (1993-08-28) - * - * If you are really that interested, you should be reading - * comp.protocols.time.ntp! - */ - -#define TICK_SIZE tick - -static unsigned long do_slow_gettimeoffset(void) -{ - int count; - - static int count_p = LATCH; /* for the first call after boot */ - static unsigned long jiffies_p; - - /* - * cache volatile jiffies temporarily; we have IRQs turned off. - */ - unsigned long jiffies_t; - - /* timer count may underflow right here */ - outb_p(0x00, 0x43); /* latch the count ASAP */ - - count = inb_p(0x40); /* read the latched count */ - - /* - * We do this guaranteed double memory access instead of a _p - * postfix in the previous port access. Wheee, hackady hack - */ - jiffies_t = jiffies; - - count |= inb_p(0x40) << 8; - - /* - * avoiding timer inconsistencies (they are rare, but they happen)... - * there are two kinds of problems that must be avoided here: - * 1. the timer counter underflows - * 2. hardware problem with the timer, not giving us continuous time, - * the counter does small "jumps" upwards on some Pentium systems, - * (see c't 95/10 page 335 for Neptun bug.) - */ - - if( jiffies_t == jiffies_p ) { - if( count > count_p ) { - /* the nutcase */ - - outb_p(0x0A, 0x20); - - /* assumption about timer being IRQ1 */ - if (inb(0x20) & 0x01) { - /* - * We cannot detect lost timer interrupts ... - * well, that's why we call them lost, don't we? :) - * [hmm, on the Pentium and Alpha we can ... sort of] - */ - count -= LATCH; - } else { - printk("do_slow_gettimeoffset(): hardware timer problem?\n"); - } - } - } else - jiffies_p = jiffies_t; - - count_p = count; - - count = ((LATCH-1) - count) * TICK_SIZE; - count = (count + LATCH/2) / LATCH; - - return count; -} - -static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset; - -/* - * This version of gettimeofday has near microsecond resolution. - */ -void do_gettimeofday(struct timeval *tv) -{ - unsigned long flags; - - read_lock_irqsave (&xtime_lock, flags); - *tv = xtime; - tv->tv_usec += do_gettimeoffset(); - - /* - * xtime is atomically updated in timer_bh. jiffies - wall_jiffies - * is nonzero if the timer bottom half hasnt executed yet. - */ - if (jiffies - wall_jiffies) - tv->tv_usec += USECS_PER_JIFFY; - - read_unlock_irqrestore (&xtime_lock, flags); - - if (tv->tv_usec >= 1000000) { - tv->tv_usec -= 1000000; - tv->tv_sec++; - } -} - -void do_settimeofday(struct timeval *tv) -{ - write_lock_irq (&xtime_lock); - - /* This is revolting. We need to set the xtime.tv_usec - * correctly. However, the value in this location is - * is value at the last tick. - * Discover what correction gettimeofday - * would have done, and then undo it! - */ - tv->tv_usec -= do_gettimeoffset(); - - if (tv->tv_usec < 0) { - tv->tv_usec += 1000000; - tv->tv_sec--; - } - - xtime = *tv; - time_adjust = 0; /* stop active adjtime() */ - time_status |= STA_UNSYNC; - time_maxerror = NTP_PHASE_LIMIT; - time_esterror = NTP_PHASE_LIMIT; - - write_unlock_irq (&xtime_lock); -} - -/* - * In order to set the CMOS clock precisely, set_rtc_mmss has to be - * called 500 ms after the second nowtime has started, because when - * nowtime is written into the registers of the CMOS clock, it will - * jump to the next second precisely 500 ms later. Check the Motorola - * MC146818A or Dallas DS12887 data sheet for details. - * - * BUG: This routine does not handle hour overflow properly; it just - * sets the minutes. Usually you won't notice until after reboot! - */ -static int set_rtc_mmss(unsigned long nowtime) -{ - int retval = 0; - int real_seconds, real_minutes, cmos_minutes; - unsigned char save_control, save_freq_select; - - save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ - CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); - - save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */ - CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); - - cmos_minutes = CMOS_READ(RTC_MINUTES); - if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) - BCD_TO_BIN(cmos_minutes); - - /* - * since we're only adjusting minutes and seconds, - * don't interfere with hour overflow. This avoids - * messing with unknown time zones but requires your - * RTC not to be off by more than 15 minutes - */ - real_seconds = nowtime % 60; - real_minutes = nowtime / 60; - if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) - real_minutes += 30; /* correct for half hour time zone */ - real_minutes %= 60; - - if (abs(real_minutes - cmos_minutes) < 30) { - if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { - BIN_TO_BCD(real_seconds); - BIN_TO_BCD(real_minutes); - } - CMOS_WRITE(real_seconds,RTC_SECONDS); - CMOS_WRITE(real_minutes,RTC_MINUTES); - } else { - printk(KERN_WARNING - "set_rtc_mmss: can't update from %d to %d\n", - cmos_minutes, real_minutes); - retval = -1; - } - - /* The following flags have to be released exactly in this order, - * otherwise the DS12887 (popular MC146818A clone with integrated - * battery and quartz) will not reset the oscillator and will not - * update precisely 500 ms later. You won't find this mentioned in - * the Dallas Semiconductor data sheets, but who believes data - * sheets anyway ... -- Markus Kuhn - */ - CMOS_WRITE(save_control, RTC_CONTROL); - CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); - - return retval; -} - -/* last time the cmos clock got updated */ -static long last_rtc_update; - -/* - * timer_interrupt() needs to keep up the real-time clock, - * as well as call the "do_timer()" routine every clocktick - */ -static void inline -timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) -{ -#ifdef CONFIG_DDB5074 - static unsigned cnt, period, dist; - - if (cnt == 0 || cnt == dist) - ddb5074_led_d2(1); - else if (cnt == 7 || cnt == dist+7) - ddb5074_led_d2(0); - - if (++cnt > period) { - cnt = 0; - /* The hyperbolic function below modifies the heartbeat period - * length in dependency of the current (5min) load. It goes - * through the points f(0)=126, f(1)=86, f(5)=51, - * f(inf)->30. */ - period = ((672<pid) { - extern int _stext; - unsigned long pc = regs->cp0_epc; - - pc -= (unsigned long) &_stext; - pc >>= prof_shift; - /* - * Dont ignore out-of-bounds pc values silently, - * put them into the last histogram slot, so if - * present, they will show up as a sharp peak. - */ - if (pc > prof_len-1) - pc = prof_len-1; - atomic_inc((atomic_t *)&prof_buffer[pc]); - } - } - do_timer(regs); - - /* - * If we have an externally synchronized Linux clock, then update - * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be - * called as close as possible to 500 ms before the new second starts. - */ - read_lock (&xtime_lock); - if ((time_status & STA_UNSYNC) == 0 && - xtime.tv_sec > last_rtc_update + 660 && - xtime.tv_usec >= 500000 - ((unsigned) tick) / 2 && - xtime.tv_usec <= 500000 + ((unsigned) tick) / 2) { - if (set_rtc_mmss(xtime.tv_sec) == 0) - last_rtc_update = xtime.tv_sec; - else - last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ - } - /* As we return to user mode fire off the other CPU schedulers.. this is - basically because we don't yet share IRQ's around. This message is - rigged to be safe on the 386 - basically it's a hack, so don't look - closely for now.. */ - /*smp_message_pass(MSG_ALL_BUT_SELF, MSG_RESCHEDULE, 0L, 0); */ - read_unlock (&xtime_lock); -} - -static inline void -r4k_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) -{ - unsigned int count; - - /* - * The cycle counter is only 32 bit which is good for about - * a minute at current count rates of upto 150MHz or so. - */ - count = read_32bit_cp0_register(CP0_COUNT); - timerhi += (count < timerlo); /* Wrap around */ - timerlo = count; - -#ifdef CONFIG_SGI_IP22 - /* Since we don't get anything but r4k timer interrupts, we need to - * set this up so that we'll get one next time. Fortunately since we - * have timerhi/timerlo, we don't care so much if we miss one. So - * we need only ask for the next in r4k_interval counts. On other - * archs we have a real timer, so we don't want this. - */ - write_32bit_cp0_register (CP0_COMPARE, - (unsigned long) (count + r4k_interval)); - kstat_cpu(0).irqs[irq]++; -#endif - - timer_interrupt(irq, dev_id, regs); - - if (!jiffies) - { - /* - * If jiffies has overflowed in this timer_interrupt we must - * update the timer[hi]/[lo] to make do_fast_gettimeoffset() - * quotient calc still valid. -arca - */ - timerhi = timerlo = 0; - } -} - -void indy_r4k_timer_interrupt (struct pt_regs *regs) -{ - static const int INDY_R4K_TIMER_IRQ = 7; - int cpu = smp_processor_id(); - - r4k_timer_interrupt (INDY_R4K_TIMER_IRQ, NULL, regs); - - if (softirq_pending(cpu)) - do_softirq(); -} - -struct irqaction irq0 = { timer_interrupt, SA_INTERRUPT, 0, - "timer", NULL, NULL}; - - -void (*board_time_init)(struct irqaction *irq); - -void __init time_init(void) -{ - unsigned int epoch = 0, year, mon, day, hour, min, sec; - int i; - - /* The Linux interpretation of the CMOS clock register contents: - * When the Update-In-Progress (UIP) flag goes from 1 to 0, the - * RTC registers show the second which has precisely just started. - * Let's hope other operating systems interpret the RTC the same way. - */ - /* read RTC exactly on falling edge of update flag */ - for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */ - if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) - break; - for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */ - if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) - break; - do { /* Isn't this overkill ? UIP above should guarantee consistency */ - sec = CMOS_READ(RTC_SECONDS); - min = CMOS_READ(RTC_MINUTES); - hour = CMOS_READ(RTC_HOURS); - day = CMOS_READ(RTC_DAY_OF_MONTH); - mon = CMOS_READ(RTC_MONTH); - year = CMOS_READ(RTC_YEAR); - } while (sec != CMOS_READ(RTC_SECONDS)); - if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) - { - BCD_TO_BIN(sec); - BCD_TO_BIN(min); - BCD_TO_BIN(hour); - BCD_TO_BIN(day); - BCD_TO_BIN(mon); - BCD_TO_BIN(year); - } - - /* Attempt to guess the epoch. This is the same heuristic as in rtc.c so - no stupid things will happen to timekeeping. Who knows, maybe Ultrix - also uses 1952 as epoch ... */ - if (year > 10 && year < 44) { - epoch = 1980; - } else if (year < 96) { - epoch = 1952; - } - year += epoch; - - write_lock_irq (&xtime_lock); - xtime.tv_sec = mktime(year, mon, day, hour, min, sec); - xtime.tv_usec = 0; - write_unlock_irq (&xtime_lock); - - if (mips_cpu.options & MIPS_CPU_COUNTER) { - write_32bit_cp0_register(CP0_COUNT, 0); - do_gettimeoffset = do_fast_gettimeoffset; - irq0.handler = r4k_timer_interrupt; - } - - board_time_init(&irq0); -} diff -Nru a/arch/mips/kernel/pci-dma.c b/arch/mips/kernel/pci-dma.c --- a/arch/mips/kernel/pci-dma.c Tue Jul 1 18:44:36 2003 +++ b/arch/mips/kernel/pci-dma.c Tue Jul 1 18:44:36 2003 @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -20,18 +21,23 @@ { void *ret; int gfp = GFP_ATOMIC; + struct pci_bus *bus = NULL; +#ifdef CONFIG_ISA if (hwdev == NULL || hwdev->dma_mask != 0xffffffff) gfp |= GFP_DMA; +#endif ret = (void *) __get_free_pages(gfp, get_order(size)); if (ret != NULL) { memset(ret, 0, size); -#ifndef CONFIG_COHERENT_IO + if (hwdev) + bus = hwdev->bus; + *dma_handle = bus_to_baddr(bus, __pa(ret)); +#ifdef CONFIG_NONCOHERENT_IO dma_cache_wback_inv((unsigned long) ret, size); - ret = KSEG1ADDR(ret); + ret = UNCAC_ADDR(ret); #endif - *dma_handle = virt_to_bus(ret); } return ret; @@ -42,8 +48,11 @@ { unsigned long addr = (unsigned long) vaddr; -#ifndef CONFIG_COHERENT_IO - addr = KSEG0ADDR(addr); +#ifdef CONFIG_NONCOHERENT_IO + addr = CAC_ADDR(addr); #endif free_pages(addr, get_order(size)); } + +EXPORT_SYMBOL(pci_alloc_consistent); +EXPORT_SYMBOL(pci_free_consistent); diff -Nru a/arch/mips/kernel/pci.c b/arch/mips/kernel/pci.c --- a/arch/mips/kernel/pci.c Tue Jul 1 18:44:36 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,168 +0,0 @@ -/* - * Copyright 2001 MontaVista Software Inc. - * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net - * - * Modified to be mips generic, ppopov@mvista.com - * arch/mips/kernel/pci.c - * Common MIPS PCI routines. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -/* - * This file contains common PCI routines meant to be shared for - * all MIPS machines. - * - * Strategies: - * - * . We rely on pci_auto.c file to assign PCI resources (MEM and IO) - * TODO: this should be optional for some machines where they do have - * a real "pcibios" that does resource assignment. - * - * . We then use pci_scan_bus() to "discover" all the resources for - * later use by Linux. - * - * . We finally reply on a board supplied function, pcibios_fixup_irq(), to - * to assign the interrupts. We may use setup-irq.c under drivers/pci - * later. - * - * . Specifically, we will *NOT* use pci_assign_unassigned_resources(), - * because we assume all PCI devices should have the resources correctly - * assigned and recorded. - * - * Limitations: - * - * . We "collapse" all IO and MEM spaces in sub-buses under a top-level bus - * into a contiguous range. - * - * . In the case of Memory space, the rnage is 1:1 mapping with CPU physical - * address space. - * - * . In the case of IO space, it starts from 0, and the beginning address - * is mapped to KSEG0ADDR(mips_io_port) in the CPU physical address. - * - * . These are the current MIPS limitations (by ioremap, etc). In the - * future, we may remove them. - * - * Credits: - * Most of the code are derived from the pci routines from PPC and Alpha, - * which were mostly writtne by - * Cort Dougan, cort@fsmlabs.com - * Matt Porter, mporter@mvista.com - * Dave Rusling david.rusling@reo.mts.dec.com - * David Mosberger davidm@cs.arizona.edu - */ -#include -#include -#include -#include - -#include - -extern void pcibios_fixup(void); -extern void pcibios_fixup_irqs(void); - -struct pci_fixup pcibios_fixups[] = { - { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources }, - { 0 } -}; - -extern int pciauto_assign_resources(int busno, struct pci_channel * hose); - -void __init pcibios_init(void) -{ - struct pci_channel *p; - struct pci_bus *bus; - int busno; - -#ifdef CONFIG_PCI_AUTO - /* assign resources */ - busno=0; - for (p= mips_pci_channels; p->pci_ops != NULL; p++) { - busno = pciauto_assign_resources(busno, p) + 1; - } -#endif - - /* scan the buses */ - busno = 0; - for (p= mips_pci_channels; p->pci_ops != NULL; p++) { - bus = pci_scan_bus(busno, p->pci_ops, p); - busno = bus->subordinate+1; - } - - /* machine dependent fixups */ - pcibios_fixup(); - /* fixup irqs (board specific routines) */ - pcibios_fixup_irqs(); -} - -int pcibios_enable_device(struct pci_dev *dev) -{ - /* pciauto_assign_resources() will enable all devices found */ - return 0; -} - -unsigned long __init pci_bridge_check_io(struct pci_dev *bridge) -{ - u16 io; - - pci_read_config_word(bridge, PCI_IO_BASE, &io); - if (!io) { - pci_write_config_word(bridge, PCI_IO_BASE, 0xf0f0); - pci_read_config_word(bridge, PCI_IO_BASE, &io); - pci_write_config_word(bridge, PCI_IO_BASE, 0x0); - } - if (io) - return IORESOURCE_IO; - printk(KERN_WARNING "PCI: bridge %s does not support I/O forwarding!\n", - bridge->name); - return 0; -} - -void __init pcibios_fixup_bus(struct pci_bus *bus) -{ - /* Propogate hose info into the subordinate devices. */ - - struct pci_channel *hose = bus->sysdata; - struct pci_dev *dev = bus->self; - - if (!dev) { - /* Root bus */ - bus->resource[0] = hose->io_resource; - bus->resource[1] = hose->mem_resource; - } else { - /* This is a bridge. Do not care how it's initialized, - just link its resources to the bus ones */ - int i; - - for(i=0; i<3; i++) { - bus->resource[i] = - &dev->resource[PCI_BRIDGE_RESOURCES+i]; - bus->resource[i]->name = bus->name; - } - bus->resource[0]->flags |= pci_bridge_check_io(dev); - bus->resource[1]->flags |= IORESOURCE_MEM; - /* For now, propagate hose limits to the bus; - we'll adjust them later. */ - bus->resource[0]->end = hose->io_resource->end; - bus->resource[1]->end = hose->mem_resource->end; - /* Turn off downstream PF memory address range by default */ - bus->resource[2]->start = 1024*1024; - bus->resource[2]->end = bus->resource[2]->start - 1; - } -} - -char *pcibios_setup(char *str) -{ - return str; -} - -void -pcibios_align_resource(void *data, struct resource *res, - unsigned long size, unsigned long align) -{ - /* this should not be called */ -} diff -Nru a/arch/mips/kernel/pci_auto.c b/arch/mips/kernel/pci_auto.c --- a/arch/mips/kernel/pci_auto.c Tue Jul 1 18:44:39 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,323 +0,0 @@ -/* - * PCI autoconfiguration library - * - * Author: Matt Porter - * - * Copyright 2000, 2001 MontaVista Software Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -/* - * Modified for MIPS by Jun Sun, jsun@mvista.com - * - * . Simplify the interface between pci_auto and the rest: a single function. - * . Assign resources from low address to upper address. - * . change most int to u32. - * - * Further modified to include it as mips generic code, ppopov@mvista.com. - */ - -#include -#include -#include -#include - -#include - -#define DEBUG -#ifdef DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - -/* These are used for config access before all the PCI probing has been done. */ -int early_read_config_byte(struct pci_channel *hose, int bus, int dev_fn, int where, u8 *val); -int early_read_config_word(struct pci_channel *hose, int bus, int dev_fn, int where, u16 *val); -int early_read_config_dword(struct pci_channel *hose, int bus, int dev_fn, int where, u32 *val); -int early_write_config_byte(struct pci_channel *hose, int bus, int dev_fn, int where, u8 val); -int early_write_config_word(struct pci_channel *hose, int bus, int dev_fn, int where, u16 val); -int early_write_config_dword(struct pci_channel *hose, int bus, int dev_fn, int where, u32 val); - -static u32 pciauto_lower_iospc; -static u32 pciauto_upper_iospc; - -static u32 pciauto_lower_memspc; -static u32 pciauto_upper_memspc; - -void __init -pciauto_setup_bars(struct pci_channel *hose, - int current_bus, - int pci_devfn) -{ - u32 bar_response, bar_size, bar_value; - u32 bar, addr_mask, bar_nr = 0; - u32 * upper_limit; - u32 * lower_limit; - int found_mem64 = 0; - - DBG("PCI Autoconfig: Found Bus %d, Device %d, Function %d\n", - current_bus, PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn) ); - - for (bar = PCI_BASE_ADDRESS_0; bar <= PCI_BASE_ADDRESS_5; bar+=4) { - /* Tickle the BAR and get the response */ - early_write_config_dword(hose, - current_bus, - pci_devfn, - bar, - 0xffffffff); - early_read_config_dword(hose, - current_bus, - pci_devfn, - bar, - &bar_response); - - /* If BAR is not implemented go to the next BAR */ - if (!bar_response) - continue; - - /* Check the BAR type and set our address mask */ - if (bar_response & PCI_BASE_ADDRESS_SPACE) { - addr_mask = PCI_BASE_ADDRESS_IO_MASK; - upper_limit = &pciauto_upper_iospc; - lower_limit = &pciauto_lower_iospc; - DBG("PCI Autoconfig: BAR %d, I/O, ", bar_nr); - } else { - if ((bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == - PCI_BASE_ADDRESS_MEM_TYPE_64) - found_mem64 = 1; - - addr_mask = PCI_BASE_ADDRESS_MEM_MASK; - upper_limit = &pciauto_upper_memspc; - lower_limit = &pciauto_lower_memspc; - DBG("PCI Autoconfig: BAR %d, Mem, ", bar_nr); - } - - /* Calculate requested size */ - bar_size = ~(bar_response & addr_mask) + 1; - - /* Allocate a base address */ - bar_value = ((*lower_limit - 1) & ~(bar_size - 1)) + bar_size; - - /* Write it out and update our limit */ - early_write_config_dword(hose, current_bus, pci_devfn, - bar, bar_value); - - *lower_limit = bar_value + bar_size; - - /* - * If we are a 64-bit decoder then increment to the - * upper 32 bits of the bar and force it to locate - * in the lower 4GB of memory. - */ - if (found_mem64) { - bar += 4; - early_write_config_dword(hose, - current_bus, - pci_devfn, - bar, - 0x00000000); - } - - bar_nr++; - - DBG("size=0x%x, address=0x%x\n", - bar_size, bar_value); - } - -} - -void __init -pciauto_prescan_setup_bridge(struct pci_channel *hose, - int current_bus, - int pci_devfn, - int sub_bus) -{ - int cmdstat; - - /* Configure bus number registers */ - early_write_config_byte(hose, current_bus, pci_devfn, - PCI_PRIMARY_BUS, current_bus); - early_write_config_byte(hose, current_bus, pci_devfn, - PCI_SECONDARY_BUS, sub_bus + 1); - early_write_config_byte(hose, current_bus, pci_devfn, - PCI_SUBORDINATE_BUS, 0xff); - - /* Round memory allocator to 1MB boundary */ - pciauto_upper_memspc &= ~(0x100000 - 1); - - /* Round I/O allocator to 4KB boundary */ - pciauto_upper_iospc &= ~(0x1000 - 1); - - /* Set up memory and I/O filter limits, assume 32-bit I/O space */ - early_write_config_word(hose, current_bus, pci_devfn, PCI_MEMORY_LIMIT, - ((pciauto_upper_memspc - 1) & 0xfff00000) >> 16); - early_write_config_byte(hose, current_bus, pci_devfn, PCI_IO_LIMIT, - ((pciauto_upper_iospc - 1) & 0x0000f000) >> 8); - early_write_config_word(hose, current_bus, pci_devfn, - PCI_IO_LIMIT_UPPER16, - ((pciauto_upper_iospc - 1) & 0xffff0000) >> 16); - - /* We don't support prefetchable memory for now, so disable */ - early_write_config_word(hose, current_bus, pci_devfn, - PCI_PREF_MEMORY_BASE, 0x1000); - early_write_config_word(hose, current_bus, pci_devfn, - PCI_PREF_MEMORY_LIMIT, 0x1000); - - /* Enable memory and I/O accesses, enable bus master */ - early_read_config_dword(hose, current_bus, pci_devfn, PCI_COMMAND, - &cmdstat); - early_write_config_dword(hose, current_bus, pci_devfn, PCI_COMMAND, - cmdstat | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | - PCI_COMMAND_MASTER); -} - -void __init -pciauto_postscan_setup_bridge(struct pci_channel *hose, - int current_bus, - int pci_devfn, - int sub_bus) -{ - /* Configure bus number registers */ - early_write_config_byte(hose, current_bus, pci_devfn, - PCI_SUBORDINATE_BUS, sub_bus); - - /* Round memory allocator to 1MB boundary */ - pciauto_upper_memspc &= ~(0x100000 - 1); - early_write_config_word(hose, current_bus, pci_devfn, PCI_MEMORY_BASE, - pciauto_upper_memspc >> 16); - - /* Round I/O allocator to 4KB boundary */ - pciauto_upper_iospc &= ~(0x1000 - 1); - early_write_config_byte(hose, current_bus, pci_devfn, PCI_IO_BASE, - (pciauto_upper_iospc & 0x0000f000) >> 8); - early_write_config_word(hose, current_bus, pci_devfn, - PCI_IO_BASE_UPPER16, pciauto_upper_iospc >> 16); -} - -#define PCIAUTO_IDE_MODE_MASK 0x05 - -int __init -pciauto_bus_scan(struct pci_channel *hose, int current_bus) -{ - int sub_bus; - u32 pci_devfn, pci_class, cmdstat, found_multi=0; - unsigned short vid; - unsigned char header_type; - int devfn_start = 0; - int devfn_stop = 0xff; - - sub_bus = current_bus; - - if (hose->first_devfn) - devfn_start = hose->first_devfn; - if (hose->last_devfn) - devfn_stop = hose->last_devfn; - - for (pci_devfn=devfn_start; pci_devfn> 16) == PCI_CLASS_BRIDGE_PCI) { - DBG("PCI Autoconfig: Found P2P bridge, device %d\n", PCI_SLOT(pci_devfn)); - pciauto_prescan_setup_bridge(hose, current_bus, - pci_devfn, sub_bus); - sub_bus = pciauto_bus_scan(hose, sub_bus+1); - pciauto_postscan_setup_bridge(hose, current_bus, - pci_devfn, sub_bus); - - } else if ((pci_class >> 16) == PCI_CLASS_STORAGE_IDE) { - - unsigned char prg_iface; - - early_read_config_byte(hose, current_bus, pci_devfn, - PCI_CLASS_PROG, &prg_iface); - if (!(prg_iface & PCIAUTO_IDE_MODE_MASK)) { - DBG("PCI Autoconfig: Skipping legacy mode IDE controller\n"); - continue; - } - } - - /* - * Found a peripheral, enable some standard - * settings - */ - early_read_config_dword(hose, current_bus, pci_devfn, - PCI_COMMAND, &cmdstat); - early_write_config_dword(hose, current_bus, pci_devfn, - PCI_COMMAND, cmdstat | PCI_COMMAND_IO | - PCI_COMMAND_MEMORY | - PCI_COMMAND_MASTER); - early_write_config_byte(hose, current_bus, pci_devfn, - PCI_LATENCY_TIMER, 0x80); - - /* Allocate PCI I/O and/or memory space */ - pciauto_setup_bars(hose, current_bus, pci_devfn); - } - return sub_bus; -} - -int __init -pciauto_assign_resources(int busno, struct pci_channel *hose) -{ - /* setup resource limits */ - pciauto_lower_iospc = hose->io_resource->start; - pciauto_upper_iospc = hose->io_resource->end + 1; - pciauto_lower_memspc = hose->mem_resource->start; - pciauto_upper_memspc = hose->mem_resource->end + 1; - - return pciauto_bus_scan(hose, busno); -} - - -/* - * These functions are used early on before PCI scanning is done - * and all of the pci_dev and pci_bus structures have been created. - */ -static struct pci_dev *fake_pci_dev(struct pci_channel *hose, int busnr, - int devfn) -{ - static struct pci_dev dev; - static struct pci_bus bus; - - dev.bus = &bus; - dev.sysdata = hose; - dev.devfn = devfn; - bus.number = busnr; - bus.ops = hose->pci_ops; - - return &dev; -} - -#define EARLY_PCI_OP(rw, size, type) \ -int early_##rw##_config_##size(struct pci_channel *hose, int bus, \ - int devfn, int offset, type value) \ -{ \ - return pci_##rw##_config_##size(fake_pci_dev(hose, bus, devfn), \ - offset, value); \ -} - -EARLY_PCI_OP(read, byte, u8 *) -EARLY_PCI_OP(read, word, u16 *) -EARLY_PCI_OP(read, dword, u32 *) -EARLY_PCI_OP(write, byte, u8) -EARLY_PCI_OP(write, word, u16) -EARLY_PCI_OP(write, dword, u32) diff -Nru a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c --- a/arch/mips/kernel/proc.c Tue Jul 1 18:44:33 2003 +++ b/arch/mips/kernel/proc.c Tue Jul 1 18:44:33 2003 @@ -8,102 +8,136 @@ #include #include #include +#include #include #include #include #include #include -extern unsigned long unaligned_instructions; unsigned int vced_count, vcei_count; -#ifndef CONFIG_CPU_HAS_LLSC -unsigned long ll_ops, sc_ops; -#endif -/* - * BUFFER is PAGE_SIZE bytes long. - * - * Currently /proc/cpuinfo is being abused to print data about the - * number of date/instruction cacheflushes. - */ -int get_cpuinfo(char *buffer) +static const char *cpu_name[] = { + [CPU_UNKNOWN] "unknown", + [CPU_R2000] "R2000", + [CPU_R3000] "R3000", + [CPU_R3000A] "R3000A", + [CPU_R3041] "R3041", + [CPU_R3051] "R3051", + [CPU_R3052] "R3052", + [CPU_R3081] "R3081", + [CPU_R3081E] "R3081E", + [CPU_R4000PC] "R4000PC", + [CPU_R4000SC] "R4000SC", + [CPU_R4000MC] "R4000MC", + [CPU_R4200] "R4200", + [CPU_R4400PC] "R4400PC", + [CPU_R4400SC] "R4400SC", + [CPU_R4400MC] "R4400MC", + [CPU_R4600] "R4600", + [CPU_R6000] "R6000", + [CPU_R6000A] "R6000A", + [CPU_R8000] "R8000", + [CPU_R10000] "R10000", + [CPU_R4300] "R4300", + [CPU_R4650] "R4650", + [CPU_R4700] "R4700", + [CPU_R5000] "R5000", + [CPU_R5000A] "R5000A", + [CPU_R4640] "R4640", + [CPU_NEVADA] "Nevada", + [CPU_RM7000] "RM7000", + [CPU_R5432] "R5432", + [CPU_4KC] "MIPS 4Kc", + [CPU_5KC] "MIPS 5Kc", + [CPU_R4310] "R4310", + [CPU_SB1] "SiByte SB1", + [CPU_TX3912] "TX3912", + [CPU_TX3922] "TX3922", + [CPU_TX3927] "TX3927", + [CPU_AU1000] "Au1000", + [CPU_AU1500] "Au1500", + [CPU_4KEC] "MIPS 4KEc", + [CPU_4KSC] "MIPS 4KSc", + [CPU_VR41XX] "NEC Vr41xx", + [CPU_R5500] "R5500", + [CPU_TX49XX] "TX49xx", + [CPU_20KC] "MIPS 20Kc", + [CPU_VR4111] "NEC VR4111", + [CPU_VR4121] "NEC VR4121", + [CPU_VR4122] "NEC VR4122", + [CPU_VR4131] "NEC VR4131", + [CPU_VR4181] "NEC VR4181", + [CPU_VR4181A] "NEC VR4181A", + [CPU_SR71000] "Sandcraft SR71000" +}; + + +static int show_cpuinfo(struct seq_file *m, void *v) { + unsigned int version = current_cpu_data.processor_id; + unsigned int fp_vers = current_cpu_data.fpu_id; + unsigned long n = (unsigned long) v - 1; char fmt [64]; - const char *cpu_name[] = CPU_NAMES; - const char *mach_group_names[] = GROUP_NAMES; - const char *mach_unknown_names[] = GROUP_UNKNOWN_NAMES; - const char *mach_jazz_names[] = GROUP_JAZZ_NAMES; - const char *mach_dec_names[] = GROUP_DEC_NAMES; - const char *mach_arc_names[] = GROUP_ARC_NAMES; - const char *mach_sni_rm_names[] = GROUP_SNI_RM_NAMES; - const char *mach_acn_names[] = GROUP_ACN_NAMES; - const char *mach_sgi_names[] = GROUP_SGI_NAMES; - const char *mach_cobalt_names[] = GROUP_COBALT_NAMES; - const char *mach_nec_ddb_names[] = GROUP_NEC_DDB_NAMES; - const char *mach_baget_names[] = GROUP_BAGET_NAMES; - const char *mach_cosine_names[] = GROUP_COSINE_NAMES; - const char *mach_galileo_names[] = GROUP_GALILEO_NAMES; - const char *mach_momenco_names[] = GROUP_MOMENCO_NAMES; - const char *mach_ite_names[] = GROUP_ITE_NAMES; - const char *mach_philips_names[] = GROUP_PHILIPS_NAMES; - const char *mach_globespan_names[] = GROUP_GLOBESPAN_NAMES; - const char *mach_sibyte_names[] = GROUP_SIBYTE_NAMES; - const char *mach_toshiba_names[] = GROUP_TOSHIBA_NAMES; - const char *mach_alchemy_names[] = GROUP_ALCHEMY_NAMES; - const char **mach_group_to_name[] = { mach_unknown_names, - mach_jazz_names, mach_dec_names, mach_arc_names, - mach_sni_rm_names, mach_acn_names, mach_sgi_names, - mach_cobalt_names, mach_nec_ddb_names, mach_baget_names, - mach_cosine_names, mach_galileo_names, mach_momenco_names, - mach_ite_names, mach_philips_names, mach_globespan_names, - mach_sibyte_names, mach_toshiba_names, mach_alchemy_names}; - unsigned int version = read_32bit_cp0_register(CP0_PRID); - int len; - - len = sprintf(buffer, "cpu\t\t\t: MIPS\n"); - len += sprintf(buffer + len, "cpu model\t\t: %s V%d.%d\n", - cpu_name[mips_cpu.cputype <= CPU_LAST ? - mips_cpu.cputype : CPU_UNKNOWN], - (version >> 4) & 0x0f, version & 0x0f); - len += sprintf(buffer + len, "system type\t\t: %s %s\n", - mach_group_names[mips_machgroup], - mach_group_to_name[mips_machgroup][mips_machtype]); - len += sprintf(buffer + len, "BogoMIPS\t\t: %lu.%02lu\n", - loops_per_jiffy/(500000/HZ), - (loops_per_jiffy/(5000/HZ)) % 100); -#if defined (__MIPSEB__) - len += sprintf(buffer + len, "byteorder\t\t: big endian\n"); -#endif -#if defined (__MIPSEL__) - len += sprintf(buffer + len, "byteorder\t\t: little endian\n"); +#ifdef CONFIG_SMP + if (!CPUMASK_TSTB(cpu_online_map, n)) + return 0; #endif - len += sprintf(buffer + len, "unaligned accesses\t: %lu\n", - unaligned_instructions); - len += sprintf(buffer + len, "wait instruction\t: %s\n", - cpu_wait ? "yes" : "no"); - len += sprintf(buffer + len, "microsecond timers\t: %s\n", - (mips_cpu.options & MIPS_CPU_COUNTER) ? "yes" : "no"); - len += sprintf(buffer + len, "extra interrupt vector\t: %s\n", - (mips_cpu.options & MIPS_CPU_DIVEC) ? "yes" : "no"); - len += sprintf(buffer + len, "hardware watchpoint\t: %s\n", - watch_available ? "yes" : "no"); + + /* + * For the first processor also print the system type + */ + if (n == 0) + seq_printf(m, "system type\t\t: %s\n", get_system_type()); + + seq_printf(m, "processor\t\t: %ld\n", n); + sprintf(fmt, "cpu model\t\t: %%s V%%d.%%d%s\n", + cpu_has_fpu ? " FPU V%d.%d" : ""); + seq_printf(m, fmt, cpu_name[current_cpu_data.cputype <= CPU_LAST ? + current_cpu_data.cputype : CPU_UNKNOWN], + (version >> 4) & 0x0f, version & 0x0f, + (fp_vers >> 4) & 0x0f, fp_vers & 0x0f); + seq_printf(m, "BogoMIPS\t\t: %lu.%02lu\n", + loops_per_jiffy / (500000/HZ), + (loops_per_jiffy / (5000/HZ)) % 100); + seq_printf(m, "wait instruction\t: %s\n", cpu_wait ? "yes" : "no"); + seq_printf(m, "microsecond timers\t: %s\n", + cpu_has_counter ? "yes" : "no"); + seq_printf(m, "tlb_entries\t\t: %d\n", current_cpu_data.tlbsize); + seq_printf(m, "extra interrupt vector\t: %s\n", + cpu_has_divec ? "yes" : "no"); + seq_printf(m, "hardware watchpoint\t: %s\n", + cpu_has_watch ? "yes" : "no"); sprintf(fmt, "VCE%%c exceptions\t\t: %s\n", - (mips_cpu.options & MIPS_CPU_VCE) ? "%d" : "not available"); - len += sprintf(buffer + len, fmt, 'D', vced_count); - len += sprintf(buffer + len, fmt, 'I', vcei_count); - -#ifndef CONFIG_CPU_HAS_LLSC - len += sprintf(buffer + len, "ll emulations\t\t: %lu\n", - ll_ops); - len += sprintf(buffer + len, "sc emulations\t\t: %lu\n", - sc_ops); -#endif - return len; + cpu_has_vce ? "%d" : "not available"); + seq_printf(m, fmt, 'D', vced_count); + seq_printf(m, fmt, 'I', vcei_count); + + return 0; } -void init_irq_proc(void) +static void *c_start(struct seq_file *m, loff_t *pos) { - /* Nothing, for now. */ + unsigned long i = *pos; + + return i < NR_CPUS ? (void *) (i + 1) : NULL; } + +static void *c_next(struct seq_file *m, void *v, loff_t *pos) +{ + ++*pos; + return c_start(m, pos); +} + +static void c_stop(struct seq_file *m, void *v) +{ +} + +struct seq_operations cpuinfo_op = { + .start = c_start, + .next = c_next, + .stop = c_stop, + .show = show_cpuinfo, +}; diff -Nru a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c --- a/arch/mips/kernel/process.c Tue Jul 1 18:44:34 2003 +++ b/arch/mips/kernel/process.c Tue Jul 1 18:44:34 2003 @@ -6,86 +6,95 @@ * Copyright (C) 1994 - 2000 by Ralf Baechle and others. * Copyright (C) 1999 Silicon Graphics, Inc. */ -#include #include #include #include #include #include #include -#include +#include #include #include #include #include #include +#include +#include #include #include +#include #include #include #include #include -#include +#include #include #include #include #include +#include -void cpu_idle(void) +/* + * We use this if we don't have any better idle routine.. + * (This to kill: kernel/platform.c. + */ +void default_idle (void) +{ +} + +/* + * The idle thread. There's no useful work to be done, so just try to conserve + * power and have a low exit latency (ie sit in a loop waiting for somebody to + * say that they'd like to reschedule) + */ +ATTRIB_NORET void cpu_idle(void) { /* endless idle loop with no priority at all */ - current->nice = 20; - init_idle(); while (1) { while (!need_resched()) if (cpu_wait) (*cpu_wait)(); schedule(); - check_pgt_cache(); } } -struct task_struct *last_task_used_math = NULL; - asmlinkage void ret_from_fork(void); +void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp) +{ + regs->cp0_status &= ~(ST0_CU0|ST0_KSU|ST0_CU1); + regs->cp0_status |= KU_USER; + current->used_math = 0; + loose_fpu(); + regs->cp0_epc = pc; + regs->regs[29] = sp; + current_thread_info()->addr_limit = USER_DS; +} + void exit_thread(void) { - /* Forget lazy fpu state */ - if (last_task_used_math == current) { - set_cp0_status(ST0_CU1); - __asm__ __volatile__("cfc1\t$0,$31"); - last_task_used_math = NULL; - } } void flush_thread(void) { - /* Forget lazy fpu state */ - if (last_task_used_math == current) { - set_cp0_status(ST0_CU1); - __asm__ __volatile__("cfc1\t$0,$31"); - last_task_used_math = NULL; - } } int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, unsigned long unused, struct task_struct * p, struct pt_regs * regs) { + struct thread_info *ti = p->thread_info; struct pt_regs * childregs; long childksp; - extern void save_fp(void*); - childksp = (unsigned long)p + KERNEL_STACK_SIZE - 32; + childksp = (unsigned long)ti + KERNEL_STACK_SIZE - 32; + + if (is_fpu_owner()) { + save_fp(p); + } - if (last_task_used_math == current) - if (mips_cpu.options & MIPS_CPU_FPU) { - set_cp0_status(ST0_CU1); - save_fp(p); - } /* set up new TSS. */ childregs = (struct pt_regs *) childksp - 1; *childregs = *regs; @@ -101,12 +110,12 @@ regs->regs[3] = 0; } if (childregs->cp0_status & ST0_CU0) { - childregs->regs[28] = (unsigned long) p; + childregs->regs[28] = (unsigned long) ti; childregs->regs[29] = childksp; - p->thread.current_ds = KERNEL_DS; + ti->addr_limit = KERNEL_DS; } else { childregs->regs[29] = usp; - p->thread.current_ds = USER_DS; + ti->addr_limit = USER_DS; } p->thread.reg29 = (unsigned long) childregs; p->thread.reg31 = (unsigned long) ret_from_fork; @@ -115,9 +124,10 @@ * New tasks lose permission to use the fpu. This accelerates context * switching for most programs since they don't use the fpu. */ - p->thread.cp0_status = read_32bit_cp0_register(CP0_STATUS) & + p->thread.cp0_status = read_c0_status() & ~(ST0_CU2|ST0_CU1|KU_MASK); childregs->cp0_status &= ~(ST0_CU2|ST0_CU1); + p->set_child_tid = p->clear_child_tid = NULL; return 0; } @@ -125,29 +135,8 @@ /* Fill in the fpu structure for a core dump.. */ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r) { - /* We actually store the FPU info in the task->thread - * area. - */ - if(regs->cp0_status & ST0_CU1) { - memcpy(r, ¤t->thread.fpu, sizeof(current->thread.fpu)); - return 1; - } - return 0; /* Task didn't use the fpu at all. */ -} - -/* Fill in the user structure for a core dump.. */ -void dump_thread(struct pt_regs *regs, struct user *dump) -{ - dump->magic = CMAGIC; - dump->start_code = current->mm->start_code; - dump->start_data = current->mm->start_data; - dump->start_stack = regs->regs[29] & ~(PAGE_SIZE - 1); - dump->u_tsize = (current->mm->end_code - dump->start_code) >> PAGE_SHIFT; - dump->u_dsize = (current->mm->brk + (PAGE_SIZE - 1) - dump->start_data) >> PAGE_SHIFT; - dump->u_ssize = - (current->mm->start_stack - dump->start_stack + PAGE_SIZE - 1) >> PAGE_SHIFT; - memcpy(&dump->regs[0], regs, sizeof(struct pt_regs)); - memcpy(&dump->regs[EF_SIZE/4], ¤t->thread.fpu, sizeof(current->thread.fpu)); + memcpy(r, ¤t->thread.fpu, sizeof(current->thread.fpu)); + return 1; } /* @@ -158,35 +147,107 @@ long retval; __asm__ __volatile__( - ".set noreorder \n" - " move $6,$sp \n" - " move $4,%5 \n" - " li $2,%1 \n" - " syscall \n" - " beq $6,$sp,1f \n" - " subu $sp,32 \n" /* delay slot */ - " jalr %4 \n" - " move $4,%3 \n" /* delay slot */ - " move $4,$2 \n" - " li $2,%2 \n" - " syscall \n" - "1: addiu $sp,32 \n" - " move %0,$2 \n" - ".set reorder" - :"=r" (retval) - :"i" (__NR_clone), "i" (__NR_exit), - "r" (arg), "r" (fn), - "r" (flags | CLONE_VM | CLONE_UNTRACED) + " .set noreorder \n" + " move $6, $sp \n" + " move $4, %5 \n" + " li $2, %1 \n" + " syscall \n" + " beq $6, $sp, 1f \n" + " subu $sp, 32 \n" + " jalr %4 \n" + " move $4, %3 \n" + " move $4, $2 \n" + " li $2, %2 \n" + " syscall \n" + "1: addiu $sp, 32 \n" + " move %0, $2 \n" + " .set reorder" + : "=r" (retval) + : "i" (__NR_clone), "i" (__NR_exit), "r" (arg), "r" (fn), + "r" (flags | CLONE_VM | CLONE_UNTRACED) /* * The called subroutine might have destroyed any of the * at, result, argument or temporary registers ... */ - :"$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", - "$9","$10","$11","$12","$13","$14","$15","$24","$25"); + : "$2", "$3", "$4", "$5", "$6", "$7", "$8", + "$9","$10","$11","$12","$13","$14","$15","$24","$25", "$31"); return retval; } +struct mips_frame_info { + int frame_offset; + int pc_offset; +}; +static struct mips_frame_info schedule_frame; +static struct mips_frame_info schedule_timeout_frame; +static struct mips_frame_info sleep_on_frame; +static struct mips_frame_info sleep_on_timeout_frame; +static struct mips_frame_info wait_for_completion_frame; +static int mips_frame_info_initialized; +static int __init get_frame_info(struct mips_frame_info *info, void *func) +{ + int i; + union mips_instruction *ip = (union mips_instruction *)func; + info->pc_offset = -1; + info->frame_offset = -1; + for (i = 0; i < 128; i++, ip++) { + /* if jal, jalr, jr, stop. */ + if (ip->j_format.opcode == jal_op || + (ip->r_format.opcode == spec_op && + (ip->r_format.func == jalr_op || + ip->r_format.func == jr_op))) + break; + if (ip->i_format.opcode == sw_op && + ip->i_format.rs == 29) { + /* sw $ra, offset($sp) */ + if (ip->i_format.rt == 31) { + if (info->pc_offset != -1) + break; + info->pc_offset = + ip->i_format.simmediate / sizeof(long); + } + /* sw $s8, offset($sp) */ + if (ip->i_format.rt == 30) { + if (info->frame_offset != -1) + break; + info->frame_offset = + ip->i_format.simmediate / sizeof(long); + } + } + } + if (info->pc_offset == -1 || info->frame_offset == -1) { + printk("Can't analyze prologue code at %p\n", func); + info->pc_offset = -1; + info->frame_offset = -1; + return -1; + } + + return 0; +} +void __init frame_info_init(void) +{ + mips_frame_info_initialized = + !get_frame_info(&schedule_frame, schedule) && + !get_frame_info(&schedule_timeout_frame, schedule_timeout) && + !get_frame_info(&sleep_on_frame, sleep_on) && + !get_frame_info(&sleep_on_timeout_frame, sleep_on_timeout) && + !get_frame_info(&wait_for_completion_frame, wait_for_completion); +} + +unsigned long thread_saved_pc(struct thread_struct *t) +{ + extern void ret_from_fork(void); + + /* New born processes are a special case */ + if (t->reg31 == (unsigned long) ret_from_fork) + return t->reg31; + + if (schedule_frame.pc_offset < 0) + return 0; + return ((unsigned long *)t->reg29)[schedule_frame.pc_offset]; +} + /* * These bracket the sleeping functions.. */ @@ -195,7 +256,7 @@ #define first_sched ((unsigned long) scheduling_functions_start_here) #define last_sched ((unsigned long) scheduling_functions_end_here) -/* get_wchan - a maintenance nightmare ... */ +/* get_wchan - a maintenance nightmare^W^Wpain in the ass ... */ unsigned long get_wchan(struct task_struct *p) { unsigned long frame, pc; @@ -203,6 +264,8 @@ if (!p || p == current || p->state == TASK_RUNNING) return 0; + if (!mips_frame_info_initialized) + return 0; pc = thread_saved_pc(&p->thread); if (pc < first_sched || pc >= last_sched) { return pc; @@ -216,26 +279,33 @@ goto schedule_timeout_caller; if (pc >= (unsigned long)interruptible_sleep_on) goto schedule_caller; + if (pc >= (unsigned long)wait_for_completion) + goto schedule_caller; goto schedule_timeout_caller; schedule_caller: - frame = ((unsigned long *)p->thread.reg30)[9]; - pc = ((unsigned long *)frame)[11]; + frame = ((unsigned long *)p->thread.reg30)[schedule_frame.frame_offset]; + if (pc >= (unsigned long) sleep_on) + pc = ((unsigned long *)frame)[sleep_on_frame.pc_offset]; + else + pc = ((unsigned long *)frame)[wait_for_completion_frame.pc_offset]; return pc; schedule_timeout_caller: - /* Must be schedule_timeout ... */ - pc = ((unsigned long *)p->thread.reg30)[10]; - frame = ((unsigned long *)p->thread.reg30)[9]; - - /* The schedule_timeout frame ... */ - pc = ((unsigned long *)frame)[14]; - frame = ((unsigned long *)frame)[13]; + /* + * The schedule_timeout frame + */ + frame = ((unsigned long *)p->thread.reg30)[schedule_frame.frame_offset]; + + /* + * frame now points to sleep_on_timeout's frame + */ + pc = ((unsigned long *)frame)[schedule_timeout_frame.pc_offset]; if (pc >= first_sched && pc < last_sched) { - /* schedule_timeout called by interruptible_sleep_on_timeout */ - pc = ((unsigned long *)frame)[11]; - frame = ((unsigned long *)frame)[10]; + /* schedule_timeout called by [interruptible_]sleep_on_timeout */ + frame = ((unsigned long *)frame)[schedule_timeout_frame.frame_offset]; + pc = ((unsigned long *)frame)[sleep_on_timeout_frame.pc_offset]; } return pc; diff -Nru a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c --- a/arch/mips/kernel/ptrace.c Tue Jul 1 18:44:39 2003 +++ b/arch/mips/kernel/ptrace.c Tue Jul 1 18:44:39 2003 @@ -11,6 +11,7 @@ * Copyright (C) 1999 MIPS Technologies, Inc. */ #include +#include #include #include #include @@ -19,8 +20,8 @@ #include #include #include +#include -#include #include #include #include @@ -28,6 +29,7 @@ #include #include #include +#include /* * Called by kernel/ptrace.c when detaching.. @@ -42,27 +44,27 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data) { struct task_struct *child; - int res; - extern void save_fp(struct task_struct *); + int ret; - lock_kernel(); #if 0 printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n", (int) request, (int) pid, (unsigned long) addr, (unsigned long) data); #endif + lock_kernel(); + ret = -EPERM; if (request == PTRACE_TRACEME) { /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) { - res = -EPERM; + if (current->ptrace & PT_PTRACED) + goto out; + if ((ret = security_ptrace(current->parent, current))) goto out; - } /* set the ptrace bit in the process flags. */ current->ptrace |= PT_PTRACED; - res = 0; + ret = 0; goto out; } - res = -ESRCH; + ret = -ESRCH; read_lock(&tasklist_lock); child = find_task_by_pid(pid); if (child) @@ -71,36 +73,31 @@ if (!child) goto out; - res = -EPERM; + ret = -EPERM; if (pid == 1) /* you may not mess with init */ - goto out; + goto out_tsk; if (request == PTRACE_ATTACH) { - res = ptrace_attach(child); - goto out_tsk; - } - res = -ESRCH; - if (!(child->ptrace & PT_PTRACED)) + ret = ptrace_attach(child); goto out_tsk; - if (child->state != TASK_STOPPED) { - if (request != PTRACE_KILL) - goto out_tsk; } - if (child->p_pptr != current) + + ret = ptrace_check_attach(child, request == PTRACE_KILL); + if (ret < 0) goto out_tsk; + switch (request) { - case PTRACE_PEEKTEXT: /* read word at location addr. */ + case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_PEEKDATA: { unsigned long tmp; int copied; copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); - res = -EIO; + ret = -EIO; if (copied != sizeof(tmp)) break; - res = put_user(tmp,(unsigned long *) data); - - goto out; + ret = put_user(tmp,(unsigned long *) data); + break; } /* Read the word at location addr in the USER area. */ @@ -108,7 +105,7 @@ struct pt_regs *regs; unsigned long tmp; - regs = (struct pt_regs *) ((unsigned long) child + + regs = (struct pt_regs *) ((unsigned long) child->thread_info + KERNEL_STACK_SIZE - 32 - sizeof(struct pt_regs)); tmp = 0; /* Default return value. */ @@ -118,30 +115,12 @@ break; case FPR_BASE ... FPR_BASE + 31: if (child->used_math) { - unsigned long long *fregs - = (unsigned long long *) - &child->thread.fpu.hard.fp_regs[0]; - if(!(mips_cpu.options & MIPS_CPU_FPU)) { - fregs = (unsigned long long *) - child->thread.fpu.soft.regs; - } else - if (last_task_used_math == child) { - enable_cp1(); - save_fp(child); - disable_cp1(); - last_task_used_math = NULL; - regs->cp0_status &= ~ST0_CU1; - } + unsigned long long *fregs = get_fpu_regs(child); /* * The odd registers are actually the high * order bits of the values stored in the even * registers - unless we're using r2k_switch.S. */ -#ifdef CONFIG_CPU_R3000 - if (mips_cpu.options & MIPS_CPU_FPU) - tmp = *(unsigned long *)(fregs + addr); - else -#endif if (addr & 1) tmp = (unsigned long) (fregs[((addr & ~1) - 32)] >> 32); else @@ -166,7 +145,7 @@ tmp = regs->lo; break; case FPC_CSR: - if (!(mips_cpu.options & MIPS_CPU_FPU)) + if (!cpu_has_fpu) tmp = child->thread.fpu.soft.sr; else tmp = child->thread.fpu.hard.control; @@ -174,34 +153,37 @@ case FPC_EIR: { /* implementation / version register */ unsigned int flags; - local_save_flags(flags); - enable_cp1(); + if (!cpu_has_fpu) + break; + + flags = read_c0_status(); + __enable_fpu(); __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp)); - local_irq_restore(flags); + write_c0_status(flags); break; } default: tmp = 0; - res = -EIO; - goto out; + ret = -EIO; + goto out_tsk; } - res = put_user(tmp, (unsigned long *) data); - goto out; + ret = put_user(tmp, (unsigned long *) data); + break; } case PTRACE_POKETEXT: /* write the word at location addr. */ case PTRACE_POKEDATA: - res = 0; + ret = 0; if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data)) break; - res = -EIO; - goto out; + ret = -EIO; + break; case PTRACE_POKEUSR: { struct pt_regs *regs; - res = 0; - regs = (struct pt_regs *) ((unsigned long) child + + ret = 0; + regs = (struct pt_regs *) ((unsigned long) child->thread_info + KERNEL_STACK_SIZE - 32 - sizeof(struct pt_regs)); switch (addr) { @@ -210,21 +192,8 @@ break; case FPR_BASE ... FPR_BASE + 31: { unsigned long long *fregs; - fregs = (unsigned long long *)&child->thread.fpu.hard.fp_regs[0]; - if (child->used_math) { - if (last_task_used_math == child) { - if(!(mips_cpu.options & MIPS_CPU_FPU)) { - fregs = (unsigned long long *) - child->thread.fpu.soft.regs; - } else { - enable_cp1(); - save_fp(child); - disable_cp1(); - last_task_used_math = NULL; - regs->cp0_status &= ~ST0_CU1; - } - } - } else { + fregs = (unsigned long long *)get_fpu_regs(child); + if (!child->used_math) { /* FP not yet used */ memset(&child->thread.fpu.hard, ~0, sizeof(child->thread.fpu.hard)); @@ -235,11 +204,6 @@ * of the values stored in the even registers - unless * we're using r2k_switch.S. */ -#ifdef CONFIG_CPU_R3000 - if (mips_cpu.options & MIPS_CPU_FPU) - *(unsigned long *)(fregs + addr) = data; - else -#endif if (addr & 1) { fregs[(addr & ~1) - FPR_BASE] &= 0xffffffff; fregs[(addr & ~1) - FPR_BASE] |= ((unsigned long long) data) << 32; @@ -259,14 +223,14 @@ regs->lo = data; break; case FPC_CSR: - if (!(mips_cpu.options & MIPS_CPU_FPU)) + if (!cpu_has_fpu) child->thread.fpu.soft.sr = data; else child->thread.fpu.hard.control = data; break; default: /* The rest are not allowed. */ - res = -EIO; + ret = -EIO; break; } break; @@ -274,26 +238,28 @@ case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ case PTRACE_CONT: { /* restart after signal. */ - res = -EIO; + ret = -EIO; if ((unsigned long) data > _NSIG) break; - if (request == PTRACE_SYSCALL) - child->ptrace |= PT_TRACESYS; - else - child->ptrace &= ~PT_TRACESYS; + if (request == PTRACE_SYSCALL) { + set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); + } + else { + clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); + } child->exit_code = data; wake_up_process(child); - res = 0; + ret = 0; break; } /* - * make the child exit. Best I can do is send it a sigkill. - * perhaps it should be put in the status that it wants to + * make the child exit. Best I can do is send it a sigkill. + * perhaps it should be put in the status that it wants to * exit. */ case PTRACE_KILL: - res = 0; + ret = 0; if (child->state == TASK_ZOMBIE) /* already dead */ break; child->exit_code = SIGKILL; @@ -301,32 +267,40 @@ break; case PTRACE_DETACH: /* detach a process that was attached. */ - res = ptrace_detach(child, data); + ret = ptrace_detach(child, data); break; default: - res = ptrace_request(child, request, addr, data); - goto out; + ret = ptrace_request(child, request, addr, data); + break; } out_tsk: - free_task_struct(child); + put_task_struct(child); out: unlock_kernel(); - return res; + return ret; } -asmlinkage void syscall_trace(void) +/* + * Notification of system call entry/exit + * - triggered by current->work.syscall_trace + */ +asmlinkage void do_syscall_trace(void) { - if ((current->ptrace & (PT_PTRACED|PT_TRACESYS)) - != (PT_PTRACED|PT_TRACESYS)) + if (!test_thread_flag(TIF_SYSCALL_TRACE)) return; + if (!(current->ptrace & PT_PTRACED)) + return; + /* The 0x80 provides a way for the tracing parent to distinguish between a syscall stop and SIGTRAP delivery */ current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) ? 0x80 : 0); + preempt_disable(); current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); schedule(); + preempt_enable(); /* * this isn't the same as continuing with a signal, but it will do * for normal use. strace only continues with a signal if the diff -Nru a/arch/mips/kernel/r2300_misc.S b/arch/mips/kernel/r2300_misc.S --- a/arch/mips/kernel/r2300_misc.S Tue Jul 1 18:44:37 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,199 +0,0 @@ -/* $Id: r2300_misc.S,v 1.8 1999/12/08 22:05:10 harald Exp $ - * misc.S: Misc. exception handling code for R3000/R2000. - * - * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse - * - * Multi-CPU abstraction reworking: - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * - * Further modifications to make this work: - * Copyright (c) 1998 Harald Koerfgen - * Copyright (c) 1998, 1999 Gleb Raiko & Vladimir Roganov - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - .text - .set mips1 - .set noreorder - -#undef NOTLB_OPTIMIZE /* If you are paranoid, define this. */ - - /* ABUSE of CPP macros 101. */ - - /* After this macro runs, the pte faulted on is - * in register PTE, a ptr into the table in which - * the pte belongs is in PTR. - */ -#define LOAD_PTE(pte, ptr) \ - mfc0 pte, CP0_BADVADDR; \ - lw ptr, current_pgd; \ - srl pte, pte, 22; \ - sll pte, pte, 2; \ - addu ptr, ptr, pte; \ - mfc0 pte, CP0_CONTEXT; \ - lw ptr, (ptr); \ - andi pte, pte, 0xffc; \ - addu ptr, ptr, pte; \ - lw pte, (ptr); \ - nop; - - /* This places the even/odd pte pair in the page - * table at PTR into ENTRYLO0 and ENTRYLO1 using - * TMP as a scratch register. - */ -#define PTE_RELOAD(ptr) \ - lw ptr, (ptr) ; \ - nop ; \ - mtc0 ptr, CP0_ENTRYLO0; \ - nop; - -#define DO_FAULT(write) \ - .set noat; \ - .set macro; \ - SAVE_ALL; \ - mfc0 a2, CP0_BADVADDR; \ - STI; \ - .set at; \ - move a0, sp; \ - jal do_page_fault; \ - li a1, write; \ - j ret_from_sys_call; \ - nop; \ - .set noat; \ - .set nomacro; - - /* Check is PTE is present, if not then jump to LABEL. - * PTR points to the page table where this PTE is located, - * when the macro is done executing PTE will be restored - * with its original value. - */ -#define PTE_PRESENT(pte, ptr, label) \ - andi pte, pte, (_PAGE_PRESENT | _PAGE_READ); \ - xori pte, pte, (_PAGE_PRESENT | _PAGE_READ); \ - bnez pte, label; \ - .set push; \ - .set reorder; \ - lw pte, (ptr); \ - .set pop; - - /* Make PTE valid, store result in PTR. */ -#define PTE_MAKEVALID(pte, ptr) \ - ori pte, pte, (_PAGE_VALID | _PAGE_ACCESSED); \ - sw pte, (ptr); - - /* Check if PTE can be written to, if not branch to LABEL. - * Regardless restore PTE with value from PTR when done. - */ -#define PTE_WRITABLE(pte, ptr, label) \ - andi pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \ - xori pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \ - bnez pte, label; \ - .set push; \ - .set reorder; \ - lw pte, (ptr); \ - .set pop; - - - /* Make PTE writable, update software status bits as well, - * then store at PTR. - */ -#define PTE_MAKEWRITE(pte, ptr) \ - ori pte, pte, (_PAGE_ACCESSED | _PAGE_MODIFIED | \ - _PAGE_VALID | _PAGE_DIRTY); \ - sw pte, (ptr); - -/* - * The index register may have the probe fail bit set, - * because we would trap on access kseg2, i.e. without refill. - */ -#define TLB_WRITE(reg) \ - mfc0 reg, CP0_INDEX; \ - nop; \ - bltz reg, 1f; \ - nop; \ - tlbwi; \ - j 2f; \ - nop; \ -1: tlbwr; \ -2: - -#define RET(reg) \ - mfc0 reg, CP0_EPC; \ - nop; \ - jr reg; \ - rfe - - .set noreorder - - .align 5 -NESTED(handle_tlbl, PT_SIZE, sp) - .set noat - -#ifndef NOTLB_OPTIMIZE - /* Test present bit in entry. */ - LOAD_PTE(k0, k1) - tlbp - PTE_PRESENT(k0, k1, nopage_tlbl) - PTE_MAKEVALID(k0, k1) - PTE_RELOAD(k1) - TLB_WRITE(k0) - RET(k0) -nopage_tlbl: -#endif - - DO_FAULT(0) -END(handle_tlbl) - -NESTED(handle_tlbs, PT_SIZE, sp) - .set noat - -#ifndef NOTLB_OPTIMIZE - LOAD_PTE(k0, k1) - tlbp # find faulting entry - PTE_WRITABLE(k0, k1, nopage_tlbs) - PTE_MAKEWRITE(k0, k1) - PTE_RELOAD(k1) - TLB_WRITE(k0) - RET(k0) -nopage_tlbs: -#endif - - DO_FAULT(1) -END(handle_tlbs) - - .align 5 -NESTED(handle_mod, PT_SIZE, sp) - .set noat -#ifndef NOTLB_OPTIMIZE - LOAD_PTE(k0, k1) - tlbp # find faulting entry - andi k0, k0, _PAGE_WRITE - beqz k0, nowrite_mod - .set push - .set reorder - lw k0, (k1) - .set pop - - /* Present and writable bits set, set accessed and dirty bits. */ - PTE_MAKEWRITE(k0, k1) - - /* Now reload the entry into the tlb. */ - PTE_RELOAD(k1) - tlbwi - RET(k0) -#endif - -nowrite_mod: - DO_FAULT(1) -END(handle_mod) diff -Nru a/arch/mips/kernel/r2300_switch.S b/arch/mips/kernel/r2300_switch.S --- a/arch/mips/kernel/r2300_switch.S Tue Jul 1 18:44:37 2003 +++ b/arch/mips/kernel/r2300_switch.S Tue Jul 1 18:44:37 2003 @@ -10,18 +10,17 @@ * Further modifications to make this work: * Copyright (c) 1998-2000 Harald Koerfgen */ +#include #include -#include #include -#include #include #include #include #include -#include #include #include #include +#include #include @@ -29,8 +28,24 @@ .align 5 /* - * task_struct *resume(task_struct *prev, - * task_struct *next) + * Offset to the current process status flags, the first 32 bytes of the + * stack are not used. + */ +#define ST_OFF (KERNEL_STACK_SIZE - 32 - PT_SIZE + PT_STATUS) + +/* + * FPU context is saved iff the process has used it's FPU in the current + * time slice as indicated by TIF_USEDFPU. In any case, the CU1 bit for user + * space STATUS register should be 0, so that a process *always* starts its + * userland with FPU disabled after each context switch. + * + * FPU will be enabled as soon as the process accesses FPU again, through + * do_cpu() trap. + */ + +/* + * task_struct *resume(task_struct *prev, task_struct *next, + * struct thread_info *next_ti) ) */ LEAF(resume) #ifndef CONFIG_CPU_HAS_LLSC @@ -41,84 +56,81 @@ CPU_SAVE_NONSCRATCH(a0) sw ra, THREAD_REG31(a0) + /* + * check if we need to save FPU registers + */ + lw t3, TASK_THREAD_INFO(a0) + lw t0, TI_FLAGS(t3) + li t1, TIF_USEDFPU + and t2, t0, t1 + beqz t2, 1f + nor t1, zero, t1 + + and t0, t0, t1 + sw t0, TI_FLAGS(t3) + + /* + * clear saved user stack CU1 bit + */ + lw t0, ST_OFF(t3) + li t1, ~ST0_CU1 + and t0, t0, t1 + sw t0, ST_OFF(t3) + + FPU_SAVE_SINGLE(a0, t0) # clobbers t0 + +1: /* * The order of restoring the registers takes care of the race * updating $28, $29 and kernelsp without disabling ints. */ - move $28, a1 - CPU_RESTORE_NONSCRATCH($28) - addiu t0, $28, KERNEL_STACK_SIZE-32 - sw t0, kernelsp + move $28, a2 + CPU_RESTORE_NONSCRATCH(a1) + + addiu t1, $28, KERNEL_STACK_SIZE-32 + sw t1, kernelsp + mfc0 t1, CP0_STATUS /* Do we really need this? */ li a3, 0xff00 and t1, a3 - lw a2, THREAD_STATUS($28) + lw a2, THREAD_STATUS(a1) nor a3, $0, a3 and a2, a3 or a2, t1 mtc0 a2, CP0_STATUS - .set noreorder + move v0, a0 jr ra - move v0, a0 - .set reorder END(resume) /* - * Do lazy fpu context switch. Saves FPU context to the process in a0 - * and loads the new context of the current process. - */ - -#define ST_OFF (KERNEL_STACK_SIZE - 32 - PT_SIZE + PT_STATUS) - -LEAF(lazy_fpu_switch) - mfc0 t0, CP0_STATUS # enable cp1 - li t3, 0x20000000 - or t0, t3 - mtc0 t0, CP0_STATUS - - .set noreorder - beqz a0, 2f # Save floating point state - nor t3, zero, t3 - .set reorder - lw t1, ST_OFF(a0) # last thread loses fpu - and t1, t3 - sw t1, ST_OFF(a0) - FPU_SAVE_SINGLE(a0, t1) # clobbers t1 - -2: - FPU_RESTORE_SINGLE($28, t0) # clobbers t0 - jr ra - END(lazy_fpu_switch) - -/* * Save a thread's fp context. */ -LEAF(save_fp) +LEAF(_save_fp) FPU_SAVE_SINGLE(a0, t1) # clobbers t1 jr ra - END(save_fp) + END(_save_fp) /* * Restore a thread's fp context. */ -LEAF(restore_fp) +LEAF(_restore_fp) FPU_RESTORE_SINGLE(a0, t1) # clobbers t1 jr ra - END(restore_fp) + END(_restore_fp) /* * Load the FPU with signalling NANS. This bit pattern we're using has * the property that no matter whether considered as single or as double - * precission represents signaling NANS. + * precision represents signaling NANS. * * We initialize fcr31 to rounding to nearest, no exceptions. */ #define FPU_DEFAULT 0x00000000 -LEAF(init_fpu) +LEAF(_init_fpu) mfc0 t0, CP0_STATUS - li t1, 0x20000000 + li t1, ST0_CU1 or t0, t1 mtc0 t0, CP0_STATUS @@ -158,8 +170,6 @@ mtc1 t0, $f28 mtc1 t0, $f29 mtc1 t0, $f30 - .set noreorder + mtc1 t0, $f31 jr ra - mtc1 t0, $f31 - .set reorder - END(init_fpu) + END(_init_fpu) diff -Nru a/arch/mips/kernel/r4k_misc.S b/arch/mips/kernel/r4k_misc.S --- a/arch/mips/kernel/r4k_misc.S Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,236 +0,0 @@ -/* $Id: r4k_misc.S,v 1.8 1999/10/09 00:00:58 ralf Exp $ - * - * r4k_misc.S: Misc. exception handling code for r4k. - * - * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse - * - * Multi-cpu abstraction and reworking: - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - */ -/************************************************************************** - * 14 Nov, 2000. - * Made support for MIPS32 CPUs. - * - * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - *************************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#undef NOTLB_OPTIMIZE /* If you are paranoid, define this. */ - - /* ABUSE of CPP macros 101. */ - - /* After this macro runs, the pte faulted on is - * in register PTE, a ptr into the table in which - * the pte belongs is in PTR. - */ - -#ifdef CONFIG_SMP -#define GET_PGD(scratch, ptr) \ - mfc0 ptr, CP0_CONTEXT; \ - la scratch, current_pgd;\ - srl ptr, 23; \ - sll ptr, 2; \ - addu ptr, scratch, ptr; \ - lw ptr, (ptr); -#else -#define GET_PGD(scratch, ptr) \ - lw ptr, current_pgd; -#endif - - -#define LOAD_PTE(pte, ptr) \ - GET_PGD(pte, ptr) \ - mfc0 pte, CP0_BADVADDR; \ - srl pte, pte, 22; \ - sll pte, pte, 2; \ - addu ptr, ptr, pte; \ - mfc0 pte, CP0_BADVADDR; \ - lw ptr, (ptr); \ - srl pte, pte, 10; \ - and pte, pte, 0xffc; \ - addu ptr, ptr, pte; \ - lw pte, (ptr); - - /* This places the even/odd pte pair in the page - * table at PTR into ENTRYLO0 and ENTRYLO1 using - * TMP as a scratch register. - */ -#define PTE_RELOAD(ptr, tmp) \ - ori ptr, ptr, 0x4; \ - xori ptr, ptr, 0x4; \ - lw tmp, 4(ptr); \ - lw ptr, 0(ptr); \ - srl tmp, tmp, 6; \ - mtc0 tmp, CP0_ENTRYLO1; \ - srl ptr, ptr, 6; \ - mtc0 ptr, CP0_ENTRYLO0; - -#define DO_FAULT(write) \ - .set noat; \ - SAVE_ALL; \ - mfc0 a2, CP0_BADVADDR; \ - STI; \ - .set at; \ - move a0, sp; \ - jal do_page_fault; \ - li a1, write; \ - j ret_from_sys_call; \ - nop; \ - .set noat; - - /* Check is PTE is present, if not then jump to LABEL. - * PTR points to the page table where this PTE is located, - * when the macro is done executing PTE will be restored - * with its original value. - */ -#define PTE_PRESENT(pte, ptr, label) \ - andi pte, pte, (_PAGE_PRESENT | _PAGE_READ); \ - xori pte, pte, (_PAGE_PRESENT | _PAGE_READ); \ - bnez pte, label; \ - lw pte, (ptr); - - /* Make PTE valid, store result in PTR. */ -#define PTE_MAKEVALID(pte, ptr) \ - ori pte, pte, (_PAGE_VALID | _PAGE_ACCESSED); \ - sw pte, (ptr); - - /* Check if PTE can be written to, if not branch to LABEL. - * Regardless restore PTE with value from PTR when done. - */ -#define PTE_WRITABLE(pte, ptr, label) \ - andi pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \ - xori pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \ - bnez pte, label; \ - lw pte, (ptr); - - /* Make PTE writable, update software status bits as well, - * then store at PTR. - */ -#define PTE_MAKEWRITE(pte, ptr) \ - ori pte, pte, (_PAGE_ACCESSED | _PAGE_MODIFIED | \ - _PAGE_VALID | _PAGE_DIRTY); \ - sw pte, (ptr); - - .set noreorder - -/* - * From the IDT errata for the QED RM5230 (Nevada), processor revision 1.0: - * 2. A timing hazard exists for the TLBP instruction. - * - * stalling_instruction - * TLBP - * - * The JTLB is being read for the TLBP throughout the stall generated by the - * previous instruction. This is not really correct as the stalling instruction - * can modify the address used to access the JTLB. The failure symptom is that - * the TLBP instruction will use an address created for the stalling instruction - * and not the address held in C0_ENHI and thus report the wrong results. - * - * The software work-around is to not allow the instruction preceding the TLBP - * to stall - make it an NOP or some other instruction guaranteed not to stall. - * - * Errata 2 will not be fixed. This errata is also on the R5000. - * - * As if we MIPS hackers wouldn't know how to nop pipelines happy ... - */ -#define R5K_HAZARD nop - - /* - * Note for many R4k variants tlb probes cannot be executed out - * of the instruction cache else you get bogus results. - */ - .align 5 - NESTED(handle_tlbl, PT_SIZE, sp) - .set noat -invalid_tlbl: -#ifndef NOTLB_OPTIMIZE - /* Test present bit in entry. */ - LOAD_PTE(k0, k1) - R5K_HAZARD - tlbp - PTE_PRESENT(k0, k1, nopage_tlbl) - PTE_MAKEVALID(k0, k1) - PTE_RELOAD(k1, k0) - nop - b 1f - tlbwi -1: - nop - .set mips3 - eret - .set mips0 -#endif - -nopage_tlbl: - DO_FAULT(0) - END(handle_tlbl) - - .align 5 - NESTED(handle_tlbs, PT_SIZE, sp) - .set noat -#ifndef NOTLB_OPTIMIZE - LOAD_PTE(k0, k1) - R5K_HAZARD - tlbp # find faulting entry - PTE_WRITABLE(k0, k1, nopage_tlbs) - PTE_MAKEWRITE(k0, k1) - PTE_RELOAD(k1, k0) - nop - b 1f - tlbwi -1: - nop - .set mips3 - eret - .set mips0 -#endif - -nopage_tlbs: - DO_FAULT(1) - END(handle_tlbs) - - .align 5 - NESTED(handle_mod, PT_SIZE, sp) - .set noat -#ifndef NOTLB_OPTIMIZE - LOAD_PTE(k0, k1) - R5K_HAZARD - tlbp # find faulting entry - andi k0, k0, _PAGE_WRITE - beqz k0, nowrite_mod - lw k0, (k1) - - /* Present and writable bits set, set accessed and dirty bits. */ - PTE_MAKEWRITE(k0, k1) -#if 0 - ori k0, k0, (_PAGE_ACCESSED | _PAGE_DIRTY) - sw k0, (k1) -#endif - - /* Now reload the entry into the tlb. */ - PTE_RELOAD(k1, k0) - nop - b 1f - tlbwi -1: - nop - .set mips3 - eret - .set mips0 -#endif - -nowrite_mod: - DO_FAULT(1) - END(handle_mod) diff -Nru a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S --- a/arch/mips/kernel/r4k_switch.S Tue Jul 1 18:44:38 2003 +++ b/arch/mips/kernel/r4k_switch.S Tue Jul 1 18:44:38 2003 @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1994, 1995, 1996, 1998, 1999 by Ralf Baechle + * Copyright (C) 1994, 1995, 1996, 1998, 1999, 2002 by Ralf Baechle * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * Copyright (C) 1994, 1995, 1996, by Andreas Busse * Copyright (C) 1999 Silicon Graphics, Inc. @@ -12,24 +12,35 @@ */ #include #include -#include #include -#include #include #include #include #include -#include +#include #include #include #include +#include #include +#define ST_OFF (KERNEL_STACK_SIZE - 32 - PT_SIZE + PT_STATUS) + +/* + * FPU context is saved iff the process has used it's FPU in the current + * time slice as indicated by TIF_USEDFPU. In any case, the CU1 bit for user + * space STATUS register should be 0, so that a process *always* starts its + * userland with FPU disabled after each context switch. + * + * FPU will be enabled as soon as the process accesses FPU again, through + * do_cpu() trap. + */ + /* - * task_struct *r4xx0_resume(task_struct *prev, task_struct *next) + * task_struct *r4xx0_resume(task_struct *prev, task_struct *next, + * struct thread_info *next_ti) */ - .set noreorder .align 5 LEAF(resume) #ifndef CONFIG_CPU_HAS_LLSC @@ -40,79 +51,76 @@ CPU_SAVE_NONSCRATCH(a0) sw ra, THREAD_REG31(a0) + /* + * check if we need to save FPU registers + */ + lw t3, TASK_THREAD_INFO(a0) + lw t0, TI_FLAGS(t3) + li t1, _TIF_USEDFPU + and t2, t0, t1 + beqz t2, 1f + nor t1, zero, t1 + + and t0, t0, t1 + sw t0, TI_FLAGS(t3) + + /* + * clear saved user stack CU1 bit + */ + lw t0, ST_OFF(t3) + li t1, ~ST0_CU1 + and t0, t0, t1 + sw t0, ST_OFF(t3) + + FPU_SAVE_DOUBLE(a0, t0) # clobbers t0 + +1: /* * The order of restoring the registers takes care of the race * updating $28, $29 and kernelsp without disabling ints. */ - move $28, a1 - CPU_RESTORE_NONSCRATCH($28) + move $28, a2 + CPU_RESTORE_NONSCRATCH(a1) + addiu t0, $28, KERNEL_STACK_SIZE-32 -#ifdef CONFIG_SMP +#ifdef CONFIG_SMP mfc0 a3, CP0_CONTEXT la t1, kernelsp srl a3, 23 sll a3, 2 addu t1, a3, t1 - sw t0, (t1) + sw t0, (t1) #else sw t0, kernelsp -#endif +#endif + mfc0 t1, CP0_STATUS /* Do we really need this? */ li a3, 0xff00 and t1, a3 - lw a2, THREAD_STATUS($28) + lw a2, THREAD_STATUS(a1) nor a3, $0, a3 and a2, a3 or a2, t1 mtc0 a2, CP0_STATUS + move v0, a0 jr ra - move v0, a0 END(resume) /* - * Do lazy fpu context switch. Saves FPU context to the process in a0 - * and loads the new context of the current process. - */ - -#define ST_OFF (KERNEL_STACK_SIZE - 32 - PT_SIZE + PT_STATUS) - -LEAF(lazy_fpu_switch) - mfc0 t0, CP0_STATUS # enable cp1 - li t3, 0x20000000 - or t0, t3 - mtc0 t0, CP0_STATUS - - beqz a0, 2f # Save floating point state - nor t3, zero, t3 - - lw t1, ST_OFF(a0) # last thread loses fpu - and t1, t3 - sw t1, ST_OFF(a0) - - - FPU_SAVE_DOUBLE(a0, t1) # clobbers t1 -2: - - .set reorder - FPU_RESTORE_DOUBLE($28, t0) # clobbers t0 - jr ra - END(lazy_fpu_switch) - -/* * Save a thread's fp context. */ -LEAF(save_fp) +LEAF(_save_fp) FPU_SAVE_DOUBLE(a0, t1) # clobbers t1 jr ra - END(save_fp) + END(_save_fp) /* * Restore a thread's fp context. */ -LEAF(restore_fp) +LEAF(_restore_fp) FPU_RESTORE_DOUBLE(a0, t1) # clobbers t1 jr ra - END(restore_fp) + END(_restore_fp) /* * Load the FPU with signalling NANS. This bit pattern we're using has @@ -124,12 +132,13 @@ #define FPU_DEFAULT 0x00000000 -LEAF(init_fpu) +LEAF(_init_fpu) .set mips3 mfc0 t0, CP0_STATUS - li t1, 0x20000000 + li t1, ST0_CU1 or t0, t1 mtc0 t0, CP0_STATUS + FPU_ENABLE_HAZARD li t1, FPU_DEFAULT ctc1 t1, fcr31 @@ -151,9 +160,6 @@ dmtc1 t0, $f24 dmtc1 t0, $f26 dmtc1 t0, $f28 - .set noreorder + dmtc1 t0, $f30 jr ra - dmtc1 t0, $f30 - .set reorder - END(init_fpu) - + END(_init_fpu) diff -Nru a/arch/mips/kernel/scall_o32.S b/arch/mips/kernel/scall_o32.S --- a/arch/mips/kernel/scall_o32.S Tue Jul 1 18:44:37 2003 +++ b/arch/mips/kernel/scall_o32.S Tue Jul 1 18:44:37 2003 @@ -3,124 +3,107 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1997, 1998, 1999, 2000 by Ralf Baechle + * Copyright (C) 1997, 1998, 1999, 2000, 2001 by Ralf Baechle + * Copyright (C) 2001 MIPS Technologies, Inc. */ -#include +#include #include -#include +#include #include #include #include #include +#include #include - -/* This duplicates the definition from */ -#define PT_TRACESYS 0x00000002 /* tracing system calls */ - -/* This duplicates the definition from */ -#define SIGILL 4 /* Illegal instruction (ANSI). */ +#include /* Highest syscall used of any syscall flavour */ #define MAX_SYSCALL_NO __NR_Linux + __NR_Linux_syscalls .align 5 NESTED(handle_sys, PT_SIZE, sp) - .set noat - SAVE_SOME - STI - .set at - - lw t1, PT_EPC(sp) # skip syscall on return - - sltiu t0, v0, MAX_SYSCALL_NO + 1 # check syscall number - addiu t1, 4 # skip to next instruction - beqz t0, illegal_syscall - sw t1, PT_EPC(sp) - - /* XXX Put both in one cacheline, should save a bit. */ - sll t0, v0, 2 - lw t2, sys_call_table(t0) # syscall routine - lbu t3, sys_narg_table(v0) # number of arguments - beqz t2, illegal_syscall; - - subu t0, t3, 5 # 5 or more arguments? - sw a3, PT_R26(sp) # save a3 for syscall restarting - bgez t0, stackargs + .set noat + SAVE_SOME + STI + .set at + + lw t1, PT_EPC(sp) # skip syscall on return + + sltiu t0, v0, MAX_SYSCALL_NO + 1 # check syscall number + addiu t1, 4 # skip to next instruction + beqz t0, illegal_syscall + sw t1, PT_EPC(sp) + + /* XXX Put both in one cacheline, should save a bit. */ + sll t0, v0, 2 + lw t2, sys_call_table(t0) # syscall routine + lbu t3, sys_narg_table(v0) # number of arguments + beqz t2, illegal_syscall; + + subu t0, t3, 5 # 5 or more arguments? + sw a3, PT_R26(sp) # save a3 for syscall restarting + bgez t0, stackargs stack_done: - sw a3, PT_R26(sp) # save for syscall restart -#error lw t0, TASK_PTRACE($28) # syscall tracing enabled? - andi t0, PT_TRACESYS - bnez t0, trace_a_syscall - - jalr t2 # Do The Real Thing (TM) - - li t0, -EMAXERRNO - 1 # error? - sltu t0, t0, v0 - sw t0, PT_R7(sp) # set error flag - beqz t0, 1f - - negu v0 # error - sw v0, PT_R0(sp) # set flag for syscall restarting -1: sw v0, PT_R2(sp) # result - -EXPORT(o32_ret_from_sys_call) - mfc0 t0, CP0_STATUS # need_resched and signals atomic test - ori t0, t0, 1 - xori t0, t0, 1 - mtc0 t0, CP0_STATUS - -#error lw t2, TASK_NEED_RESCHED($28) - bnez t2, o32_reschedule -#error lw v0, TASK_SIGPENDING($28) - bnez v0, signal_return -restore_all: - RESTORE_SOME - RESTORE_SP_AND_RET - -/* Put this behind restore_all for the sake of the branch prediction. */ -signal_return: - .type signal_return, @function - - mfc0 t0, CP0_STATUS - ori t0, t0, 1 - mtc0 t0, CP0_STATUS - - move a0, zero - move a1, sp -#error jal do_signal - b restore_all - -o32_reschedule: - SAVE_STATIC - jal schedule - b o32_ret_from_sys_call + sw a3, PT_R26(sp) # save for syscall restart + LONG_L t0, TI_FLAGS($28) # syscall tracing enabled? + bltz t0, syscall_trace_entry # -> yes + + jalr t2 # Do The Real Thing (TM) + + li t0, -EMAXERRNO - 1 # error? + sltu t0, t0, v0 + sw t0, PT_R7(sp) # set error flag + beqz t0, 1f + + negu v0 # error + sw v0, PT_R0(sp) # set flag for syscall + # restarting +1: sw v0, PT_R2(sp) # result + +EXPORT(o32_syscall_exit) + mfc0 t0, CP0_STATUS # make sure need_resched and + ori t0, t0, 1 # signals dont change between + xori t0, t0, 1 # sampling and return + mtc0 t0, CP0_STATUS + SSNOP; SSNOP; SSNOP + + LONG_L a2, TI_FLAGS($28) # current->work + bnez a2, o32_syscall_exit_work + +o32_restore_all: + RESTORE_SOME + RESTORE_SP_AND_RET + +o32_syscall_exit_work: + SAVE_STATIC + j syscall_exit_work /* ------------------------------------------------------------------------ */ -trace_a_syscall: - SAVE_STATIC - sw t2, PT_R1(sp) -#error jal syscall_trace - lw t2, PT_R1(sp) - - lw a0, PT_R4(sp) # Restore argument registers - lw a1, PT_R5(sp) - lw a2, PT_R6(sp) - lw a3, PT_R7(sp) - jalr t2 - - li t0, -EMAXERRNO - 1 # error? - sltu t0, t0, v0 - sw t0, PT_R7(sp) # set error flag - beqz t0, 1f - - negu v0 # error - sw v0, PT_R0(sp) # set flag for syscall restarting -1: sw v0, PT_R2(sp) # result +syscall_trace_entry: + SAVE_STATIC + sw t2, PT_R1(sp) + jal do_syscall_trace + lw t2, PT_R1(sp) + + lw a0, PT_R4(sp) # Restore argument registers + lw a1, PT_R5(sp) + lw a2, PT_R6(sp) + lw a3, PT_R7(sp) + jalr t2 + + li t0, -EMAXERRNO - 1 # error? + sltu t0, t0, v0 + sw t0, PT_R7(sp) # set error flag + beqz t0, 1f + + negu v0 # error + sw v0, PT_R0(sp) # set flag for syscall + # restarting +1: sw v0, PT_R2(sp) # result -#error jal syscall_trace - j ret_from_sys_call + j syscall_exit /* ------------------------------------------------------------------------ */ @@ -139,7 +122,7 @@ bltz t0, bad_stack # -> sp is bad lw t0, PT_R29(sp) # get old user stack pointer - la t1, 3f # copy 1 to 2 arguments + PTR_LA t1, 3f # copy 1 to 2 arguments sll t3, t3, 4 subu t1, t3 jr t1 @@ -153,6 +136,7 @@ */ .set push .set noreorder + .set nomacro 1: lw t1, 20(t0) # argument #6 from usp nop sw t1, 20(sp) @@ -161,9 +145,9 @@ nop sw t1, 16(sp) nop - .set pop +3: .set pop -3: j stack_done # go back + j stack_done # go back .section __ex_table,"a" PTR 1b,bad_stack @@ -180,7 +164,7 @@ sw v0, PT_R2(sp) li t0, 1 # set error flag sw t0, PT_R7(sp) - j ret_from_sys_call + j o32_syscall_exit /* * The system call does not exist in this kernel @@ -190,5 +174,147 @@ sw v0, PT_R2(sp) li t0, 1 # set error flag sw t0, PT_R7(sp) - j ret_from_sys_call + j o32_syscall_exit END(handle_sys) + + LEAF(mips_atomic_set) + andi v0, a1, 3 # must be word aligned + bnez v0, bad_alignment + + lw v1, TI_ADDR_LIMIT($28) # in legal address range? + addiu a0, a1, 4 + or a0, a0, a1 + and a0, a0, v1 + bltz a0, bad_address + +#ifdef CONFIG_CPU_HAS_LLSC + /* Ok, this is the ll/sc case. World is sane :-) */ +1: ll v0, (a1) + move a0, a2 +2: sc a0, (a1) + beqz a0, 1b + + .section __ex_table,"a" + PTR 1b, bad_stack + PTR 2b, bad_stack + .previous +#else + sw a1, 16(sp) + sw a2, 20(sp) + + move a0, sp + move a2, a1 + li a1, 1 + jal do_page_fault + + lw a1, 16(sp) + lw a2, 20(sp) + + /* + * At this point the page should be readable and writable unless + * there was no more memory available. + */ +1: lw v0, (a1) +2: sw a2, (a1) + + .section __ex_table,"a" + PTR 1b, no_mem + PTR 2b, no_mem + .previous +#endif + + sw v0, PT_R2(sp) # result +1: + + /* Success, so skip usual error handling garbage. */ + LONG_L t0, TI_FLAGS($28) # syscall tracing enabled? + bltz t0, 1f + b o32_syscall_exit + +1: SAVE_STATIC + jal do_syscall_trace + li a3, 0 # success + j syscall_exit + +no_mem: li v0, -ENOMEM + jr ra + +bad_address: + li v0, -EFAULT + jr ra + +bad_alignment: + li v0, -EINVAL + jr ra + END(mips_atomic_set) + + LEAF(sys_sysmips) + beq a0, MIPS_ATOMIC_SET, mips_atomic_set + j _sys_sysmips + END(sys_sysmips) + + LEAF(sys_syscall) + lw t0, PT_R29(sp) # user sp + + sltu v0, a0, __NR_Linux + __NR_Linux_syscalls + 1 + beqz v0, enosys + + sll v0, a0, 2 + la v1, sys_syscall + lw t2, sys_call_table(v0) # function pointer + lbu t4, sys_narg_table(a0) # number of arguments + + li v0, -EINVAL + beq t2, v1, out # do not recurse + + beqz t2, enosys # null function pointer? + + andi v0, t0, 0x3 # unaligned stack pointer? + bnez v0, sigsegv + + addu v0, t0, 16 # v0 = usp + 16 + addu t1, v0, 12 # 3 32-bit arguments + lw v1, TI_ADDR_LIMIT($28) + or v0, v0, t1 + and v1, v1, v0 + bltz v1, efault + + move a0, a1 # shift argument registers + move a1, a2 + move a2, a3 + +1: lw a3, 16(t0) +2: lw t3, 20(t0) +3: lw t4, 24(t0) + + .section __ex_table, "a" + .word 1b, efault + .word 2b, efault + .word 3b, efault + .previous + + sw t3, 16(sp) # put into new stackframe + sw t4, 20(sp) + + bnez t4, 1f # zero arguments? + addu a0, sp, 32 # then pass sp in a0 +1: + + sw t3, 16(sp) + sw v1, 20(sp) + jr t2 + /* Unreached */ + +enosys: li v0, -ENOSYS + b out + +sigsegv: + li a0, _SIGSEGV + move a1, $28 + jal force_sig + /* Fall through */ + +efault: li v0, -EFAULT + +out: jr ra + END(sys_syscall) diff -Nru a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c --- a/arch/mips/kernel/setup.c Tue Jul 1 18:44:32 2003 +++ b/arch/mips/kernel/setup.c Tue Jul 1 18:44:32 2003 @@ -4,9 +4,10 @@ * for more details. * * Copyright (C) 1995 Linus Torvalds - * Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000 Ralf Baechle + * Copyright (C) 1995 Waldorf Electronics + * Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001 Ralf Baechle * Copyright (C) 1996 Stoned Elipot - * Copyright (C) 2000 Maciej W. Rozycki + * Copyright (C) 2000, 2001, 2002 Maciej W. Rozycki */ #include #include @@ -16,10 +17,10 @@ #include #include #include +#include #include #include #include -#include #include #include #include @@ -29,6 +30,8 @@ #include #include #include +#include +#include #include #include @@ -36,23 +39,11 @@ #include #include #include -#include +#include +#include #include -#ifdef CONFIG_SGI_IP22 -#include -#endif - -struct mips_cpuinfo boot_cpu_data = { 0, NULL, NULL, 0 }; - -/* - * Not all of the MIPS CPUs have the "wait" instruction available. Moreover, - * the implementation of the "wait" feature differs between CPU families. This - * points to the function that implements CPU specific wait. - * The wait instruction stops the pipeline and reduces the power consumption of - * the CPU very much. - */ -void (*cpu_wait)(void) = NULL; +struct cpuinfo_mips cpu_data[NR_CPUS]; /* * There are several bus types available for MIPS machines. "RISC PC" @@ -61,7 +52,9 @@ * boxes ... * This flag is set if a EISA slots are available. */ +#ifdef CONFIG_EISA int EISA_bus = 0; +#endif struct screen_info screen_info; @@ -78,11 +71,6 @@ extern struct rtc_ops no_rtc_ops; struct rtc_ops *rtc_ops; -#ifdef CONFIG_PC_KEYB -extern struct kbd_ops no_kbd_ops; -struct kbd_ops *kbd_ops; -#endif - /* * Setup information * @@ -94,333 +82,59 @@ struct boot_mem_map boot_mem_map; unsigned char aux_device_present; -extern char _ftext, _etext, _fdata, _edata, _end; -static char command_line[COMMAND_LINE_SIZE]; - char saved_command_line[COMMAND_LINE_SIZE]; -extern char arcs_cmdline[COMMAND_LINE_SIZE]; +static char command_line[CL_SIZE]; + char saved_command_line[CL_SIZE]; +extern char arcs_cmdline[CL_SIZE]; /* * mips_io_port_base is the begin of the address space to which x86 style * I/O ports are mapped. */ -unsigned long mips_io_port_base; +const unsigned long mips_io_port_base = -1; +EXPORT_SYMBOL(mips_io_port_base); + /* - * isa_slot_offset is the address where E(ISA) busaddress 0 is is mapped + * isa_slot_offset is the address where E(ISA) busaddress 0 is mapped * for the processor. */ unsigned long isa_slot_offset; +EXPORT_SYMBOL(isa_slot_offset); -extern void sgi_sysinit(void); extern void SetUpBootInfo(void); -extern void loadmmu(void); +extern void load_mmu(void); extern asmlinkage void start_kernel(void); extern void prom_init(int, char **, char **, int *); static struct resource code_resource = { "Kernel code" }; static struct resource data_resource = { "Kernel data" }; -/* - * Probe whether cpu has config register by trying to play with - * alternate cache bit and see whether it matters. - * It's used by cpu_probe to distinguish between R3000A and R3081. - */ -static inline int cpu_has_confreg(void) -{ -#ifdef CONFIG_CPU_R3000 - extern unsigned long r3k_cache_size(unsigned long); - unsigned long size1, size2; - unsigned long cfg = read_32bit_cp0_register(CP0_CONF); - - size1 = r3k_cache_size(ST0_ISC); - write_32bit_cp0_register(CP0_CONF, cfg^CONF_AC); - size2 = r3k_cache_size(ST0_ISC); - write_32bit_cp0_register(CP0_CONF, cfg); - return size1 != size2; -#else - return 0; -#endif -} - -/* declaration of the global struct */ -struct mips_cpu mips_cpu = {PRID_IMP_UNKNOWN, CPU_UNKNOWN, 0, 0, 0, - {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}}; - -/* Shortcut for assembler access to mips_cpu.options */ -int *cpuoptions = &mips_cpu.options; - -#define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4KTLB \ - | MIPS_CPU_COUNTER | MIPS_CPU_CACHE_CDEX) - -static inline void cpu_probe(void) -{ - -#ifdef CONFIG_CPU_MIPS32 - unsigned long config1; -#endif - - mips_cpu.processor_id = read_32bit_cp0_register(CP0_PRID); - switch (mips_cpu.processor_id & 0xff0000) { - case PRID_COMP_LEGACY: - switch (mips_cpu.processor_id & 0xff00) { - case PRID_IMP_R2000: - mips_cpu.cputype = CPU_R2000; - mips_cpu.isa_level = MIPS_CPU_ISA_I; - mips_cpu.options = MIPS_CPU_TLB; - mips_cpu.tlbsize = 64; - break; - case PRID_IMP_R3000: - if ((mips_cpu.processor_id & 0xff) == PRID_REV_R3000A) - if (cpu_has_confreg()) - mips_cpu.cputype = CPU_R3081E; - else - mips_cpu.cputype = CPU_R3000A; - else - mips_cpu.cputype = CPU_R3000; - mips_cpu.isa_level = MIPS_CPU_ISA_I; - mips_cpu.options = MIPS_CPU_TLB; - mips_cpu.tlbsize = 64; - break; - case PRID_IMP_R4000: - if ((mips_cpu.processor_id & 0xff) == PRID_REV_R4400) - mips_cpu.cputype = CPU_R4400SC; - else - mips_cpu.cputype = CPU_R4000SC; - mips_cpu.isa_level = MIPS_CPU_ISA_III; - mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | - MIPS_CPU_WATCH | MIPS_CPU_VCE; - mips_cpu.tlbsize = 48; - break; - case PRID_IMP_VR41XX: - mips_cpu.cputype = CPU_VR41XX; - mips_cpu.isa_level = MIPS_CPU_ISA_III; - mips_cpu.options = R4K_OPTS; - mips_cpu.tlbsize = 32; - break; - case PRID_IMP_R4600: - mips_cpu.cputype = CPU_R4600; - mips_cpu.isa_level = MIPS_CPU_ISA_III; - mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU; - mips_cpu.tlbsize = 48; - break; -/* - * This processor doesn't have an MMU, so it's not "real easy" to - * run Linux on it. It is left purely for documentation. - * case PRID_IMP_R4650: - mips_cpu.cputype = CPU_R4650; - mips_cpu.isa_level = MIPS_CPU_ISA_III; - mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU; - mips_cpu.tlbsize = 48; - break; -*/ - case PRID_IMP_TX39: - mips_cpu.isa_level = MIPS_CPU_ISA_I; - mips_cpu.options = MIPS_CPU_TLB; - - switch (mips_cpu.processor_id & 0xff) { - case PRID_REV_TX3912: - mips_cpu.cputype = CPU_TX3912; - mips_cpu.tlbsize = 32; - break; - case PRID_REV_TX3922: - mips_cpu.cputype = CPU_TX3922; - mips_cpu.tlbsize = 64; - break; - case PRID_REV_TX3927: - mips_cpu.cputype = CPU_TX3927; - mips_cpu.tlbsize = 64; - break; - default: - mips_cpu.cputype = CPU_UNKNOWN; - break; - } - break; - case PRID_IMP_R4700: - mips_cpu.cputype = CPU_R4700; - mips_cpu.isa_level = MIPS_CPU_ISA_III; - mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR; - mips_cpu.tlbsize = 48; - break; - case PRID_IMP_R5000: - mips_cpu.cputype = CPU_R5000; - mips_cpu.isa_level = MIPS_CPU_ISA_IV; - mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR; - mips_cpu.tlbsize = 48; - break; - case PRID_IMP_R5432: - mips_cpu.cputype = CPU_R5432; - mips_cpu.isa_level = MIPS_CPU_ISA_IV; - mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR; - mips_cpu.tlbsize = 48; - break; - case PRID_IMP_NEVADA: - mips_cpu.cputype = CPU_NEVADA; - mips_cpu.isa_level = MIPS_CPU_ISA_IV; - mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | - MIPS_CPU_DIVEC; - mips_cpu.tlbsize = 48; - mips_cpu.icache.ways = 2; - mips_cpu.dcache.ways = 2; - break; - case PRID_IMP_R6000: - mips_cpu.cputype = CPU_R6000; - mips_cpu.isa_level = MIPS_CPU_ISA_II; - mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_FPU; - mips_cpu.tlbsize = 32; - break; - case PRID_IMP_R6000A: - mips_cpu.cputype = CPU_R6000A; - mips_cpu.isa_level = MIPS_CPU_ISA_II; - mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_FPU; - mips_cpu.tlbsize = 32; - break; - case PRID_IMP_RM7000: - mips_cpu.cputype = CPU_RM7000; - mips_cpu.isa_level = MIPS_CPU_ISA_IV; - mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR; - break; - case PRID_IMP_R8000: - mips_cpu.cputype = CPU_R8000; - mips_cpu.isa_level = MIPS_CPU_ISA_IV; - mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | - MIPS_CPU_FPU | MIPS_CPU_32FPR; - mips_cpu.tlbsize = 384; /* has weird TLB: 3-way x 128 */ - break; - case PRID_IMP_R10000: - mips_cpu.cputype = CPU_R10000; - mips_cpu.isa_level = MIPS_CPU_ISA_IV; - mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | - MIPS_CPU_FPU | MIPS_CPU_32FPR | - MIPS_CPU_COUNTER | MIPS_CPU_WATCH; - mips_cpu.tlbsize = 64; - break; - default: - mips_cpu.cputype = CPU_UNKNOWN; - break; - } - break; -#ifdef CONFIG_CPU_MIPS32 - case PRID_COMP_MIPS: - switch (mips_cpu.processor_id & 0xff00) { - case PRID_IMP_4KC: - mips_cpu.cputype = CPU_4KC; - goto cpu_4kc; - case PRID_IMP_4KEC: - mips_cpu.cputype = CPU_4KEC; - goto cpu_4kc; - case PRID_IMP_4KSC: - mips_cpu.cputype = CPU_4KSC; -cpu_4kc: - /* Why do we set all these options by default, THEN query them?? */ - mips_cpu.cputype = MIPS_CPU_ISA_M32; - mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | - MIPS_CPU_4KTLB | MIPS_CPU_COUNTER | - MIPS_CPU_DIVEC | MIPS_CPU_WATCH; - config1 = read_mips32_cp0_config1(); - if (config1 & (1 << 3)) - mips_cpu.options |= MIPS_CPU_WATCH; - if (config1 & (1 << 2)) - mips_cpu.options |= MIPS_CPU_MIPS16; - if (config1 & 1) - mips_cpu.options |= MIPS_CPU_FPU; - mips_cpu.scache.flags = MIPS_CACHE_NOT_PRESENT; - break; - case PRID_IMP_5KC: - mips_cpu.cputype = CPU_5KC; - mips_cpu.cputype = MIPS_CPU_ISA_M64; - /* See comment above about querying options */ - mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | - MIPS_CPU_4KTLB | MIPS_CPU_COUNTER | - MIPS_CPU_DIVEC | MIPS_CPU_WATCH; - config1 = read_mips32_cp0_config1(); - if (config1 & (1 << 3)) - mips_cpu.options |= MIPS_CPU_WATCH; - if (config1 & (1 << 2)) - mips_cpu.options |= MIPS_CPU_MIPS16; - if (config1 & 1) - mips_cpu.options |= MIPS_CPU_FPU; - break; - mips_cpu.scache.flags = MIPS_CACHE_NOT_PRESENT; - default: - mips_cpu.cputype = CPU_UNKNOWN; - break; - } - break; -#endif - case PRID_COMP_ALCHEMY: - switch (mips_cpu.processor_id & 0xff00) { -#ifdef CONFIG_CPU_MIPS32 - case PRID_IMP_AU1000: - mips_cpu.cputype = CPU_AU1000; - mips_cpu.isa_level = MIPS_CPU_ISA_M32; - mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | - MIPS_CPU_4KTLB | MIPS_CPU_COUNTER | - MIPS_CPU_DIVEC | MIPS_CPU_WATCH; - config1 = read_mips32_cp0_config1(); - if (config1 & (1 << 3)) - mips_cpu.options |= MIPS_CPU_WATCH; - if (config1 & (1 << 2)) - mips_cpu.options |= MIPS_CPU_MIPS16; - if (config1 & 1) - mips_cpu.options |= MIPS_CPU_FPU; - mips_cpu.scache.flags = MIPS_CACHE_NOT_PRESENT; - break; -#endif - default: - mips_cpu.cputype = CPU_UNKNOWN; - break; - } - break; - case PRID_COMP_SIBYTE: - switch (mips_cpu.processor_id & 0xff00) { - case PRID_IMP_SB1: - mips_cpu.cputype = CPU_SB1; - mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | - MIPS_CPU_COUNTER | MIPS_CPU_DIVEC | MIPS_CPU_FPU | - MIPS_CPU_VCE; - break; - default: - mips_cpu.cputype = CPU_UNKNOWN; - break; - } - break; - default: - mips_cpu.cputype = CPU_UNKNOWN; - } -} - asmlinkage void __init init_arch(int argc, char **argv, char **envp, int *prom_vec) { - unsigned int s; - /* Determine which MIPS variant we are running on. */ cpu_probe(); prom_init(argc, argv, envp, prom_vec); -#ifdef CONFIG_SGI_IP22 - sgi_sysinit(); -#endif + cpu_report(); /* * Determine the mmu/cache attached to this machine, * then flush the tlb and caches. On the r4xx0 * variants this also sets CP0_WIRED to zero. */ - loadmmu(); + load_mmu(); - /* Disable coprocessors and set FPU for 16 FPRs */ - s = read_32bit_cp0_register(CP0_STATUS); - s &= ~(ST0_CU1|ST0_CU2|ST0_CU3|ST0_KX|ST0_SX|ST0_FR); - s |= ST0_CU0; - write_32bit_cp0_register(CP0_STATUS, s); + /* Disable coprocessors and set FPU for 16/32 FPR register model */ + clear_c0_status(ST0_CU1|ST0_CU2|ST0_CU3|ST0_KX|ST0_SX|ST0_FR); + set_c0_status(ST0_CU0); start_kernel(); } -void __init add_memory_region(unsigned long start, unsigned long size, +void __init add_memory_region(phys_t start, phys_t size, long type) { int x = boot_mem_map.nr_map; @@ -441,8 +155,10 @@ int i; for (i = 0; i < boot_mem_map.nr_map; i++) { - printk(" memory: %08lx @ %08lx ", - boot_mem_map.map[i].size, boot_mem_map.map[i].addr); + printk(" memory: %08Lx @ %08Lx ", + (u64) boot_mem_map.map[i].size, + (u64) boot_mem_map.map[i].addr); + switch (boot_mem_map.map[i].type) { case BOOT_MEM_RAM: printk("(usable)\n"); @@ -460,7 +176,7 @@ } } -static inline void parse_mem_cmdline(void) +static inline void parse_cmdline_early(void) { char c = ' ', *to = command_line, *from = saved_command_line; unsigned long start_at, mem_size; @@ -499,7 +215,7 @@ c = *(from++); if (!c) break; - if (COMMAND_LINE_SIZE <= ++len) + if (CL_SIZE <= ++len) break; *(to++) = c; } @@ -511,143 +227,41 @@ } } -void __init setup_arch(char **cmdline_p) -{ - void atlas_setup(void); - void baget_setup(void); - void ddb_setup(void); - void decstation_setup(void); - void deskstation_setup(void); - void jazz_setup(void); - void sni_rm200_pci_setup(void); - void sgi_setup(void); - void ev96100_setup(void); - void malta_setup(void); - void momenco_ocelot_setup(void); - void nino_setup(void); - - unsigned long bootmap_size; - unsigned long start_pfn, max_pfn, first_usable_pfn; - int i; - -#ifdef CONFIG_BLK_DEV_FD - fd_ops = &no_fd_ops; -#endif +#define PFN_UP(x) (((x) + PAGE_SIZE - 1) >> PAGE_SHIFT) +#define PFN_DOWN(x) ((x) >> PAGE_SHIFT) +#define PFN_PHYS(x) ((x) << PAGE_SHIFT) -#ifdef CONFIG_BLK_DEV_IDE - ide_ops = &no_ide_ops; -#endif +#define MAXMEM HIGHMEM_START +#define MAXMEM_PFN PFN_DOWN(MAXMEM) -#ifdef CONFIG_PC_KEYB - kbd_ops = &no_kbd_ops; +static inline void bootmem_init(void) +{ +#ifdef CONFIG_BLK_DEV_INITRD + unsigned long tmp; + unsigned long *initrd_header; #endif - - rtc_ops = &no_rtc_ops; + unsigned long bootmap_size; + unsigned long start_pfn, max_low_pfn, first_usable_pfn; + int i; - switch(mips_machgroup) - { -#ifdef CONFIG_BAGET_MIPS - case MACH_GROUP_BAGET: - baget_setup(); - break; -#endif -#ifdef CONFIG_DECSTATION - case MACH_GROUP_DEC: - decstation_setup(); - break; -#endif -#ifdef CONFIG_MIPS_ATLAS - case MACH_GROUP_UNKNOWN: - atlas_setup(); - break; -#endif -#ifdef CONFIG_MIPS_JAZZ - case MACH_GROUP_JAZZ: - jazz_setup(); - break; -#endif -#ifdef CONFIG_MIPS_MALTA - case MACH_GROUP_UNKNOWN: - malta_setup(); - break; -#endif -#ifdef CONFIG_MOMENCO_OCELOT - case MACH_GROUP_MOMENCO: - momenco_ocelot_setup(); - break; -#endif -#ifdef CONFIG_SGI_IP22 - /* As of now this is only IP22. */ - case MACH_GROUP_SGI: - sgi_setup(); - break; -#endif -#ifdef CONFIG_SNI_RM200_PCI - case MACH_GROUP_SNI_RM: - sni_rm200_pci_setup(); - break; -#endif -#ifdef CONFIG_DDB5074 - case MACH_GROUP_NEC_DDB: - ddb_setup(); - break; -#endif -#ifdef CONFIG_DDB5476 - case MACH_GROUP_NEC_DDB: - ddb_setup(); - break; -#endif -#ifdef CONFIG_DDB5477 - case MACH_GROUP_NEC_DDB: - ddb_setup(); - break; -#endif -#ifdef CONFIG_MIPS_EV96100 - case MACH_GROUP_GALILEO: - ev96100_setup(); - break; -#endif -#ifdef CONFIG_MIPS_EV64120 - case MACH_GROUP_GALILEO: - ev64120_setup(); - break; -#endif -#if defined(CONFIG_MIPS_IVR) || defined(CONFIG_MIPS_ITE8172) - case MACH_GROUP_ITE: - case MACH_GROUP_GLOBESPAN: - it8172_setup(); - break; -#endif -#ifdef CONFIG_NINO - case MACH_GROUP_PHILIPS: - nino_setup(); - break; -#endif -#ifdef CONFIG_MIPS_PB1000 - case MACH_GROUP_ALCHEMY: - au1000_setup(); - break; -#endif - default: - panic("Unsupported architecture"); +#ifdef CONFIG_BLK_DEV_INITRD + tmp = (((unsigned long)&_end + PAGE_SIZE-1) & PAGE_MASK) - 8; + if (tmp < (unsigned long)&_end) + tmp += PAGE_SIZE; + initrd_header = (unsigned long *)tmp; + if (initrd_header[0] == 0x494E5244) { + initrd_start = (unsigned long)&initrd_header[2]; + initrd_end = initrd_start + initrd_header[1]; } - - strlcpy(command_line, arcs_cmdline, sizeof command_line); - strlcpy(saved_command_line, command_line, sizeof saved_command_line); - *cmdline_p = command_line; - - parse_mem_cmdline(); - -#define PFN_UP(x) (((x) + PAGE_SIZE - 1) >> PAGE_SHIFT) -#define PFN_DOWN(x) ((x) >> PAGE_SHIFT) -#define PFN_PHYS(x) ((x) << PAGE_SHIFT) - + start_pfn = PFN_UP(__pa((&_end)+(initrd_end - initrd_start) + PAGE_SIZE)); +#else /* * Partially used pages are not usable - thus * we are rounding upwards. */ start_pfn = PFN_UP(__pa(&_end)); +#endif /* CONFIG_BLK_DEV_INITRD */ /* Find the highest page frame number we have available. */ max_pfn = 0; @@ -674,9 +288,36 @@ } } } - - /* Initialize the boot-time allocator. */ - bootmap_size = init_bootmem(first_usable_pfn, max_pfn); + + /* + * Determine low and high memory ranges + */ + max_low_pfn = max_pfn; + if (max_low_pfn > MAXMEM_PFN) { + max_low_pfn = MAXMEM_PFN; +#ifndef CONFIG_HIGHMEM + /* Maximum memory usable is what is directly addressable */ + printk(KERN_WARNING "Warning only %dMB will be used.\n", + MAXMEM>>20); + printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n"); +#endif + } + +#ifdef CONFIG_HIGHMEM + /* + * Crude, we really should make a better attempt at detecting + * highstart_pfn + */ + highstart_pfn = highend_pfn = max_pfn; + if (max_pfn > MAXMEM_PFN) { + highstart_pfn = MAXMEM_PFN; + printk(KERN_NOTICE "%ldMB HIGHMEM available.\n", + (highend_pfn - highstart_pfn) >> (20 - PAGE_SHIFT)); + } +#endif + + /* Initialize the boot-time allocator with low memory only. */ + bootmap_size = init_bootmem(first_usable_pfn, max_low_pfn); /* * Register fully available low RAM pages with the bootmem allocator. @@ -694,7 +335,7 @@ * We are rounding up the start address of usable memory: */ curr_pfn = PFN_UP(boot_mem_map.map[i].addr); - if (curr_pfn >= max_pfn) + if (curr_pfn >= max_low_pfn) continue; if (curr_pfn < start_pfn) curr_pfn = start_pfn; @@ -705,8 +346,19 @@ last_pfn = PFN_DOWN(boot_mem_map.map[i].addr + boot_mem_map.map[i].size); - if (last_pfn > max_pfn) - last_pfn = max_pfn; + if (last_pfn > max_low_pfn) + last_pfn = max_low_pfn; + + /* + * Only register lowmem part of lowmem segment with bootmem. + */ + size = last_pfn - curr_pfn; + if (curr_pfn > PFN_DOWN(HIGHMEM_START)) + continue; + if (curr_pfn + size - 1 > PFN_DOWN(HIGHMEM_START)) + size = PFN_DOWN(HIGHMEM_START) - curr_pfn; + if (!size) + continue; /* * ... finally, did all the rounding and playing @@ -715,7 +367,7 @@ if (last_pfn <= curr_pfn) continue; - size = last_pfn - curr_pfn; + /* Register lowmem ranges */ free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size)); } @@ -725,38 +377,49 @@ #ifdef CONFIG_BLK_DEV_INITRD /* Board specific code should have set up initrd_start and initrd_end */ ROOT_DEV = Root_RAM0; - if( __rd_start != __rd_end ) { + if (&__rd_start != &__rd_end) { initrd_start = (unsigned long)&__rd_start; initrd_end = (unsigned long)&__rd_end; } initrd_below_start_ok = 1; if (initrd_start) { - unsigned long initrd_size = ((unsigned char *)initrd_end) - ((unsigned char *)initrd_start); + unsigned long initrd_size = ((unsigned char *)initrd_end) - ((unsigned char *)initrd_start); printk("Initial ramdisk at: 0x%p (%lu bytes)\n", - (void *)initrd_start, + (void *)initrd_start, initrd_size); - if ((void *)initrd_end > phys_to_virt(PFN_PHYS(max_low_pfn))) { + if (PHYSADDR(initrd_end) > PFN_PHYS(max_low_pfn)) { printk("initrd extends beyond end of memory " - "(0x%lx > 0x%p)\ndisabling initrd\n", - initrd_end, - phys_to_virt(PFN_PHYS(max_low_pfn))); + "(0x%08lx > 0x%08lx)\ndisabling initrd\n", + PHYSADDR(initrd_end), + PFN_PHYS(max_low_pfn)); initrd_start = initrd_end = 0; - } + } } #endif /* CONFIG_BLK_DEV_INITRD */ +} - paging_init(); +static inline void resource_init(void) +{ + int i; - code_resource.start = virt_to_bus(&_ftext); - code_resource.end = virt_to_bus(&_etext) - 1; - data_resource.start = virt_to_bus(&_fdata); - data_resource.end = virt_to_bus(&_edata) - 1; + code_resource.start = virt_to_phys(&_text); + code_resource.end = virt_to_phys(&_etext) - 1; + data_resource.start = virt_to_phys(&_etext); + data_resource.end = virt_to_phys(&_edata) - 1; /* * Request address space for all standard RAM. */ for (i = 0; i < boot_mem_map.nr_map; i++) { struct resource *res; + unsigned long start, end; + + start = boot_mem_map.map[i].addr; + end = boot_mem_map.map[i].addr + boot_mem_map.map[i].size - 1; + if (start >= MAXMEM) + continue; + if (end >= MAXMEM) + end = MAXMEM - 1; res = alloc_bootmem(sizeof(struct resource)); switch (boot_mem_map.map[i].type) { @@ -768,8 +431,10 @@ default: res->name = "reserved"; } - res->start = boot_mem_map.map[i].addr; - res->end = res->start + boot_mem_map.map[i].size - 1; + + res->start = start; + res->end = end; + res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; request_resource(&iomem_resource, res); @@ -783,15 +448,244 @@ } } -void r3081_wait(void) +#undef PFN_UP +#undef PFN_DOWN +#undef PFN_PHYS + +#undef MAXMEM +#undef MAXMEM_PFN + + +void __init setup_arch(char **cmdline_p) { - unsigned long cfg = read_32bit_cp0_register(CP0_CONF); - write_32bit_cp0_register(CP0_CONF, cfg|CONF_HALT); + void atlas_setup(void); + void baget_setup(void); + void cobalt_setup(void); + void lasat_setup(void); + void ddb_setup(void); + void decstation_setup(void); + void deskstation_setup(void); + void jazz_setup(void); + void sni_rm200_pci_setup(void); + void ip22_setup(void); + void ev96100_setup(void); + void malta_setup(void); + void sead_setup(void); + void ikos_setup(void); + void momenco_ocelot_setup(void); + void momenco_ocelot_g_setup(void); + void momenco_ocelot_c_setup(void); + void nec_osprey_setup(void); + void nec_eagle_setup(void); + void zao_capcella_setup(void); + void victor_mpc30x_setup(void); + void ibm_workpad_setup(void); + void casio_e55_setup(void); + void jmr3927_setup(void); + void it8172_setup(void); + void swarm_setup(void); + void hp_setup(void); + void au1x00_setup(void); + void frame_info_init(void); + + frame_info_init(); + +#ifdef CONFIG_BLK_DEV_FD + fd_ops = &no_fd_ops; +#endif + +#ifdef CONFIG_BLK_DEV_IDE + ide_ops = &no_ide_ops; +#endif + + rtc_ops = &no_rtc_ops; + + switch(mips_machgroup) + { +#ifdef CONFIG_BAGET_MIPS + case MACH_GROUP_BAGET: + baget_setup(); + break; +#endif +#ifdef CONFIG_MIPS_COBALT + case MACH_GROUP_COBALT: + cobalt_setup(); + break; +#endif +#ifdef CONFIG_DECSTATION + case MACH_GROUP_DEC: + decstation_setup(); + break; +#endif +#ifdef CONFIG_MIPS_ATLAS + case MACH_GROUP_UNKNOWN: + atlas_setup(); + break; +#endif +#ifdef CONFIG_MIPS_JAZZ + case MACH_GROUP_JAZZ: + jazz_setup(); + break; +#endif +#ifdef CONFIG_MIPS_MALTA + case MACH_GROUP_UNKNOWN: + malta_setup(); + break; +#endif +#ifdef CONFIG_MOMENCO_OCELOT + case MACH_GROUP_MOMENCO: + momenco_ocelot_setup(); + break; +#endif +#ifdef CONFIG_MOMENCO_OCELOT_G + case MACH_GROUP_MOMENCO: + momenco_ocelot_g_setup(); + break; +#endif +#ifdef CONFIG_MOMENCO_OCELOT_C + case MACH_GROUP_MOMENCO: + momenco_ocelot_c_setup(); + break; +#endif +#ifdef CONFIG_MIPS_SEAD + case MACH_GROUP_UNKNOWN: + sead_setup(); + break; +#endif +#ifdef CONFIG_SGI_IP22 + /* As of now this is only IP22. */ + case MACH_GROUP_SGI: + ip22_setup(); + break; +#endif +#ifdef CONFIG_SNI_RM200_PCI + case MACH_GROUP_SNI_RM: + sni_rm200_pci_setup(); + break; +#endif +#ifdef CONFIG_DDB5074 + case MACH_GROUP_NEC_DDB: + ddb_setup(); + break; +#endif +#ifdef CONFIG_DDB5476 + case MACH_GROUP_NEC_DDB: + ddb_setup(); + break; +#endif +#ifdef CONFIG_DDB5477 + case MACH_GROUP_NEC_DDB: + ddb_setup(); + break; +#endif +#ifdef CONFIG_CPU_VR41XX + case MACH_GROUP_NEC_VR41XX: + switch (mips_machtype) { +#ifdef CONFIG_NEC_OSPREY + case MACH_NEC_OSPREY: + nec_osprey_setup(); + break; +#endif +#ifdef CONFIG_NEC_EAGLE + case MACH_NEC_EAGLE: + nec_eagle_setup(); + break; +#endif +#ifdef CONFIG_ZAO_CAPCELLA + case MACH_ZAO_CAPCELLA: + zao_capcella_setup(); + break; +#endif +#ifdef CONFIG_VICTOR_MPC30X + case MACH_VICTOR_MPC30X: + victor_mpc30x_setup(); + break; +#endif +#ifdef CONFIG_IBM_WORKPAD + case MACH_IBM_WORKPAD: + ibm_workpad_setup(); + break; +#endif +#ifdef CONFIG_CASIO_E55 + case MACH_CASIO_E55: + casio_e55_setup(); + break; +#endif +#ifdef CONFIG_TANBAC_TB0229 + case MACH_TANBAC_TB0229: + tanbac_tb0229_setup(); + break; +#endif + } + break; +#endif +#ifdef CONFIG_MIPS_EV96100 + case MACH_GROUP_GALILEO: + ev96100_setup(); + break; +#endif +#ifdef CONFIG_MIPS_EV64120 + case MACH_GROUP_GALILEO: + ev64120_setup(); + break; +#endif +#if defined(CONFIG_MIPS_IVR) || defined(CONFIG_MIPS_ITE8172) + case MACH_GROUP_ITE: + case MACH_GROUP_GLOBESPAN: + it8172_setup(); + break; +#endif +#ifdef CONFIG_LASAT + case MACH_GROUP_LASAT: + lasat_setup(); + break; +#endif +#ifdef CONFIG_SOC_AU1X00 + case MACH_GROUP_ALCHEMY: + au1x00_setup(); + break; +#endif +#ifdef CONFIG_TOSHIBA_JMR3927 + case MACH_GROUP_TOSHIBA: + jmr3927_setup(); + break; +#endif +#ifdef CONFIG_TOSHIBA_RBTX4927 + case MACH_GROUP_TOSHIBA: + tx4927_setup(); + break; +#endif +#ifdef CONFIG_SIBYTE_BOARD + case MACH_GROUP_SIBYTE: + swarm_setup(); + break; +#endif +#ifdef CONFIG_HP_LASERJET + case MACH_GROUP_HP_LJ: + hp_setup(); + break; +#endif + default: + panic("Unsupported architecture"); + } + + strlcpy(command_line, arcs_cmdline, sizeof command_line); + strlcpy(saved_command_line, command_line, sizeof saved_command_line); + *cmdline_p = command_line; + + parse_cmdline_early(); + + bootmem_init(); + + paging_init(); + + resource_init(); } -void r4k_wait(void) +int __init fpu_disable(char *s) { - __asm__(".set\tmips3\n\t" - "wait\n\t" - ".set\tmips0"); + cpu_data[0].options &= ~MIPS_CPU_FPU; + + return 1; } +__setup("nofpu", fpu_disable); diff -Nru a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c --- a/arch/mips/kernel/signal.c Tue Jul 1 18:44:37 2003 +++ b/arch/mips/kernel/signal.c Tue Jul 1 18:44:37 2003 @@ -10,19 +10,22 @@ #include #include #include +#include #include #include #include #include #include #include -#include #include #include #include -#include -#include +#include +#include +#include +#include +#include #include #include @@ -32,17 +35,13 @@ extern asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs); -extern asmlinkage int (*save_fp_context)(struct sigcontext *sc); -extern asmlinkage int (*restore_fp_context)(struct sigcontext *sc); - -extern asmlinkage void syscall_trace(void); +extern asmlinkage void do_syscall_trace(void); /* * Atomically swap in the new signal mask, and wait for a signal. */ save_static_function(sys_sigsuspend); -static_unused int -_sys_sigsuspend(struct pt_regs regs) +static_unused int _sys_sigsuspend(struct pt_regs regs) { sigset_t *uset, saveset, newset; @@ -51,11 +50,11 @@ return -EFAULT; sigdelsetmask(&newset, ~_BLOCKABLE); - spin_lock_irq(¤t->sigmask_lock); + spin_lock_irq(¤t->sighand->siglock); saveset = current->blocked; current->blocked = newset; recalc_sigpending(); - spin_unlock_irq(¤t->sigmask_lock); + spin_unlock_irq(¤t->sighand->siglock); regs.regs[2] = EINTR; regs.regs[7] = 1; @@ -67,10 +66,8 @@ } } - save_static_function(sys_rt_sigsuspend); -static_unused int -_sys_rt_sigsuspend(struct pt_regs regs) +static_unused int _sys_rt_sigsuspend(struct pt_regs regs) { sigset_t *unewset, saveset, newset; size_t sigsetsize; @@ -85,11 +82,11 @@ return -EFAULT; sigdelsetmask(&newset, ~_BLOCKABLE); - spin_lock_irq(¤t->sigmask_lock); + spin_lock_irq(¤t->sighand->siglock); saveset = current->blocked; current->blocked = newset; recalc_sigpending(); - spin_unlock_irq(¤t->sigmask_lock); + spin_unlock_irq(¤t->sighand->siglock); regs.regs[2] = EINTR; regs.regs[7] = 1; @@ -101,8 +98,8 @@ } } -asmlinkage int -sys_sigaction(int sig, const struct sigaction *act, struct sigaction *oact) +asmlinkage int sys_sigaction(int sig, const struct sigaction *act, + struct sigaction *oact) { struct k_sigaction new_ka, old_ka; int ret; @@ -116,7 +113,6 @@ err |= __get_user(new_ka.sa.sa_handler, &act->sa_handler); err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags); err |= __get_user(mask, &act->sa_mask.sig[0]); - err |= __get_user(new_ka.sa.sa_restorer, &act->sa_restorer); if (err) return -EFAULT; @@ -134,7 +130,6 @@ err |= __put_user(0, &oact->sa_mask.sig[1]); err |= __put_user(0, &oact->sa_mask.sig[2]); err |= __put_user(0, &oact->sa_mask.sig[3]); - err |= __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer); if (err) return -EFAULT; } @@ -142,8 +137,7 @@ return ret; } -asmlinkage int -sys_sigaltstack(struct pt_regs regs) +asmlinkage int sys_sigaltstack(struct pt_regs regs) { const stack_t *uss = (const stack_t *) regs.regs[4]; stack_t *uoss = (stack_t *) regs.regs[5]; @@ -152,10 +146,8 @@ return do_sigaltstack(uss, uoss, usp); } -asmlinkage int -restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc) +static int restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc) { - int owned_fp; int err = 0; u64 reg; @@ -183,10 +175,15 @@ restore_gp_reg(31); #undef restore_gp_reg - err |= __get_user(owned_fp, &sc->sc_ownedfp); - if (owned_fp) { + err |= __get_user(current->used_math, &sc->sc_used_math); + + if (current->used_math) { + /* restore fpu context if we have used it before */ + own_fpu(); err |= restore_fp_context(sc); - last_task_used_math = current; + } else { + /* signal handler may have used FPU. Give it up. */ + loose_fpu(); } return err; @@ -206,8 +203,7 @@ struct ucontext rs_uc; }; -asmlinkage void -sys_sigreturn(struct pt_regs regs) +asmlinkage void sys_sigreturn(struct pt_regs regs) { struct sigframe *frame; sigset_t blocked; @@ -219,10 +215,10 @@ goto badframe; sigdelsetmask(&blocked, ~_BLOCKABLE); - spin_lock_irq(¤t->sigmask_lock); + spin_lock_irq(¤t->sighand->siglock); current->blocked = blocked; recalc_sigpending(); - spin_unlock_irq(¤t->sigmask_lock); + spin_unlock_irq(¤t->sighand->siglock); if (restore_sigcontext(®s, &frame->sf_sc)) goto badframe; @@ -230,11 +226,11 @@ /* * Don't let your children do this ... */ - if (current->ptrace & PT_TRACESYS) - syscall_trace(); + if (current_thread_info()->flags & TIF_SYSCALL_TRACE) + do_syscall_trace(); __asm__ __volatile__( "move\t$29, %0\n\t" - "j\tret_from_sys_call" + "j\tsyscall_exit" :/* no outputs */ :"r" (®s)); /* Unreached */ @@ -243,8 +239,7 @@ force_sig(SIGSEGV, current); } -asmlinkage void -sys_rt_sigreturn(struct pt_regs regs) +asmlinkage void sys_rt_sigreturn(struct pt_regs regs) { struct rt_sigframe *frame; sigset_t set; @@ -257,10 +252,10 @@ goto badframe; sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sigmask_lock); + spin_lock_irq(¤t->sighand->siglock); current->blocked = set; recalc_sigpending(); - spin_unlock_irq(¤t->sigmask_lock); + spin_unlock_irq(¤t->sighand->siglock); if (restore_sigcontext(®s, &frame->rs_uc.uc_mcontext)) goto badframe; @@ -276,7 +271,7 @@ */ __asm__ __volatile__( "move\t$29, %0\n\t" - "j\tret_from_sys_call" + "j\tsyscall_exit" :/* no outputs */ :"r" (®s)); /* Unreached */ @@ -285,21 +280,20 @@ force_sig(SIGSEGV, current); } -static inline int -setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc) +static inline int setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc) { - int owned_fp; int err = 0; u64 reg; - err |= __put_user(regs->cp0_epc, &sc->sc_pc); + reg = regs->cp0_epc; err |= __put_user(reg, &sc->sc_pc); err |= __put_user(regs->cp0_status, &sc->sc_status); #define save_gp_reg(i) { \ reg = regs->regs[i]; \ err |= __put_user(reg, &sc->sc_regs[i]); \ } while(0) - __put_user(0, &sc->sc_regs[0]); save_gp_reg(1); save_gp_reg(2); + reg = 0; err |= __put_user(reg, &sc->sc_regs[0]); + save_gp_reg(1); save_gp_reg(2); save_gp_reg(3); save_gp_reg(4); save_gp_reg(5); save_gp_reg(6); save_gp_reg(7); save_gp_reg(8); save_gp_reg(9); save_gp_reg(10); save_gp_reg(11); save_gp_reg(12); save_gp_reg(13); save_gp_reg(14); @@ -310,36 +304,48 @@ save_gp_reg(31); #undef save_gp_reg - err |= __put_user(regs->hi, &sc->sc_mdhi); - err |= __put_user(regs->lo, &sc->sc_mdlo); + reg = regs->hi; err |= __put_user(reg, &sc->sc_mdhi); + reg = regs->lo; err |= __put_user(reg, &sc->sc_mdlo); err |= __put_user(regs->cp0_cause, &sc->sc_cause); err |= __put_user(regs->cp0_badvaddr, &sc->sc_badvaddr); - owned_fp = (current == last_task_used_math); - err |= __put_user(owned_fp, &sc->sc_ownedfp); + err |= __put_user(current->used_math, &sc->sc_used_math); + + if (!current->used_math) + goto out; - if (current->used_math) { /* fp is active. */ - set_cp0_status(ST0_CU1); - err |= save_fp_context(sc); - last_task_used_math = NULL; - regs->cp0_status &= ~ST0_CU1; - current->used_math = 0; + /* + * Save FPU state to signal context. Signal handler will "inherit" + * current FPU state. + */ + if (!is_fpu_owner()) { + own_fpu(); + restore_fp(current); } + err |= save_fp_context(sc); +out: return err; } /* * Determine which stack to use.. */ -static inline void * -get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) +static inline void * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, + size_t frame_size) { unsigned long sp; /* Default to using normal stack */ sp = regs->regs[29]; + /* + * FPU emulator may have it's own trampoline active just + * above the user stack, 16-bytes before the next lowest + * 16 byte boundary. Try to avoid trashing it. + */ + sp -= 32; + /* This is the X/Open sanctioned signal stack switching. */ if ((ka->sa.sa_flags & SA_ONSTACK) && ! on_sig_stack(sp)) sp = current->sas_ss_sp + current->sas_ss_size; @@ -347,9 +353,8 @@ return (void *)((sp - frame_size) & ALMASK); } -static void inline -setup_frame(struct k_sigaction * ka, struct pt_regs *regs, - int signr, sigset_t *set) +static void inline setup_frame(struct k_sigaction * ka, struct pt_regs *regs, + int signr, sigset_t *set) { struct sigframe *frame; int err = 0; @@ -358,23 +363,15 @@ if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) goto give_sigsegv; - /* Set up to return from userspace. If provided, use a stub already - in userspace. */ - if (ka->sa.sa_flags & SA_RESTORER) - regs->regs[31] = (unsigned long) ka->sa.sa_restorer; - else { - /* - * Set up the return code ... - * - * li v0, __NR_sigreturn - * syscall - */ - err |= __put_user(0x24020000 + __NR_sigreturn, - frame->sf_code + 0); - err |= __put_user(0x0000000c , - frame->sf_code + 1); - flush_cache_sigtramp((unsigned long) frame->sf_code); - } + /* + * Set up the return code ... + * + * li v0, __NR_sigreturn + * syscall + */ + err |= __put_user(0x24020000 + __NR_sigreturn, frame->sf_code + 0); + err |= __put_user(0x0000000c , frame->sf_code + 1); + flush_cache_sigtramp((unsigned long) frame->sf_code); err |= setup_sigcontext(regs, &frame->sf_sc); err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set)); @@ -399,8 +396,9 @@ regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; #if DEBUG_SIG - printk("SIG deliver (%s:%d): sp=0x%p pc=0x%p ra=0x%p\n", - current->comm, current->pid, frame, regs->cp0_epc, frame->code); + printk("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%p\n", + current->comm, current->pid, + frame, regs->cp0_epc, frame->sf_code); #endif return; @@ -410,9 +408,8 @@ force_sig(SIGSEGV, current); } -static void inline -setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, - int signr, sigset_t *set, siginfo_t *info) +static void inline setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, + int signr, sigset_t *set, siginfo_t *info) { struct rt_sigframe *frame; int err = 0; @@ -421,23 +418,15 @@ if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) goto give_sigsegv; - /* Set up to return from userspace. If provided, use a stub already - in userspace. */ - if (ka->sa.sa_flags & SA_RESTORER) - regs->regs[31] = (unsigned long) ka->sa.sa_restorer; - else { - /* - * Set up the return code ... - * - * li v0, __NR_rt_sigreturn - * syscall - */ - err |= __put_user(0x24020000 + __NR_rt_sigreturn, - frame->rs_code + 0); - err |= __put_user(0x0000000c , - frame->rs_code + 1); - flush_cache_sigtramp((unsigned long) frame->rs_code); - } + /* + * Set up the return code ... + * + * li v0, __NR_rt_sigreturn + * syscall + */ + err |= __put_user(0x24020000 + __NR_rt_sigreturn, frame->rs_code + 0); + err |= __put_user(0x0000000c , frame->rs_code + 1); + flush_cache_sigtramp((unsigned long) frame->rs_code); /* Create siginfo. */ err |= copy_siginfo_to_user(&frame->rs_info, info); @@ -475,8 +464,9 @@ regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; #if DEBUG_SIG - printk("SIG deliver (%s:%d): sp=0x%p pc=0x%p ra=0x%p\n", - current->comm, current->pid, frame, regs->cp0_epc, frame->code); + printk("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%p\n", + current->comm, current->pid, + frame, regs->cp0_epc, frame->rs_code); #endif return; @@ -486,31 +476,11 @@ force_sig(SIGSEGV, current); } -static inline void -handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset, - struct pt_regs * regs) +static inline void handle_signal(unsigned long sig, siginfo_t *info, + sigset_t *oldset, struct pt_regs * regs) { - struct k_sigaction *ka = ¤t->sig->action[sig-1]; + struct k_sigaction *ka = ¤t->sighand->action[sig-1]; - if (ka->sa.sa_flags & SA_SIGINFO) - setup_rt_frame(ka, regs, sig, oldset, info); - else - setup_frame(ka, regs, sig, oldset); - - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; - if (!(ka->sa.sa_flags & SA_NODEFER)) { - spin_lock_irq(¤t->sigmask_lock); - sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); - sigaddset(¤t->blocked,sig); - recalc_sigpending(); - spin_unlock_irq(¤t->sigmask_lock); - } -} - -static inline void -syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) -{ switch(regs->regs[0]) { case ERESTARTNOHAND: regs->regs[2] = EINTR; @@ -527,27 +497,33 @@ } regs->regs[0] = 0; /* Don't deal with this again. */ -} -extern int do_irix_signal(sigset_t *oldset, struct pt_regs *regs); + if (ka->sa.sa_flags & SA_SIGINFO) + setup_rt_frame(ka, regs, sig, oldset, info); + else + setup_frame(ka, regs, sig, oldset); + + if (ka->sa.sa_flags & SA_ONESHOT) + ka->sa.sa_handler = SIG_DFL; + if (!(ka->sa.sa_flags & SA_NODEFER)) { + spin_lock_irq(¤t->sighand->siglock); + sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + sigaddset(¤t->blocked,sig); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + } +} asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) { siginfo_t info; - int sig_nr; - -#ifdef CONFIG_BINFMT_IRIX - if (current->personality != PER_LINUX) - return do_irix_signal(oldset, regs); -#endif + int signr; if (!oldset) oldset = ¤t->blocked; signr = get_signal_to_deliver(&info, regs, NULL); if (signr > 0) { - if (regs->regs[0]) - syscall_restart(regs, ka); /* Whee! Actually deliver the signal. */ handle_signal(signr, &info, oldset, regs); return 1; @@ -567,4 +543,25 @@ } } return 0; +} + +extern int do_irix_signal(sigset_t *oldset, struct pt_regs *regs); + +/* + * notification of userspace execution resumption + * - triggered by current->work.notify_resume + */ +asmlinkage void do_notify_resume(struct pt_regs *regs, sigset_t *oldset, + __u32 thread_info_flags) +{ + /* deal with pending signal delivery */ + if (thread_info_flags & _TIF_SIGPENDING) { +#ifdef CONFIG_BINFMT_IRIX + if (unlikely(current->personality != PER_LINUX)) { + do_irix_signal(oldset, regs); + return; + } +#endif + do_signal(oldset, regs); + } } diff -Nru a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c --- a/arch/mips/kernel/smp.c Tue Jul 1 18:44:32 2003 +++ b/arch/mips/kernel/smp.c Tue Jul 1 18:44:32 2003 @@ -1,11 +1,4 @@ /* - * - * arch/mips/kernel/smp.c - * - * Copyright (C) 2000 Sibyte - * - * Written by Justin Carlson (carlson@sibyte.com) - * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 @@ -15,229 +8,256 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - */ - - + * Copyright (C) 2000, 2001 Kanoj Sarcar + * Copyright (C) 2000, 2001 Ralf Baechle + * Copyright (C) 2000, 2001 Silicon Graphics, Inc. + * Copyright (C) 2000, 2001 Broadcom Corporation + */ #include +#include +#include #include +#include #include #include +#include #include #include #include -#include -#include #include +#include #include #include #include #include -#include #include -/* - * This was written with the BRCM12500 MP SOC in mind, but tries to - * be generic. It's modelled on the mips64 smp.c code, which is - * derived from Sparc, I'm guessing, which is derived from... - * - * It's probably horribly designed for very large ccNUMA systems - * as it doesn't take any node clustering into account. -*/ - - -/* Ze Big Kernel Lock! */ -int smp_threads_ready; /* Not used */ -int smp_num_cpus; -int global_irq_holder = NO_PROC_ID; -spinlock_t global_irq_lock = SPIN_LOCK_UNLOCKED; -struct mips_cpuinfo cpu_data[NR_CPUS]; - -struct smp_fn_call_struct smp_fn_call = -{ SPIN_LOCK_UNLOCKED, ATOMIC_INIT(0), NULL, NULL}; +int smp_threads_ready; /* Not used */ -static atomic_t cpus_booted = ATOMIC_INIT(0); +// static atomic_t cpus_booted = ATOMIC_INIT(0); +atomic_t cpus_booted = ATOMIC_INIT(0); +cpumask_t phys_cpu_present_map; /* Bitmask of physically CPUs */ +cpumask_t cpu_online_map; /* Bitmask of currently online CPUs */ +int __cpu_number_map[NR_CPUS]; +int __cpu_logical_map[NR_CPUS]; /* These are defined by the board-specific code. */ -/* Cause the function described by smp_fn_call - to be executed on the passed cpu. When the function - has finished, increment the finished field of - smp_fn_call. */ - -void core_call_function(int cpu); +/* + * Cause the function described by call_data to be executed on the passed + * cpu. When the function has finished, increment the finished field of + * call_data. + */ +void core_send_ipi(int cpu, unsigned int action); /* * Clear all undefined state in the cpu, set up sp and gp to the passed - * values, and kick the cpu into smp_bootstrap(); + * values, and kick the cpu into smp_bootstrap(); */ void prom_boot_secondary(int cpu, unsigned long sp, unsigned long gp); /* * After we've done initial boot, this function is called to allow the - * board code to clean up state, if needed + * board code to clean up state, if needed */ - void prom_init_secondary(void); +void prom_smp_finish(void); -void cpu_idle(void); - -/* Do whatever setup needs to be done for SMP at the board level. Return - the number of cpus in the system, including this one */ -int prom_setup_smp(void); - -int start_secondary(void *unused) -{ - prom_init_secondary(); - write_32bit_cp0_register(CP0_CONTEXT, smp_processor_id()<<23); - current_pgd[smp_processor_id()] = init_mm.pgd; - printk("Slave cpu booted successfully\n"); - atomic_inc(&cpus_booted); - cpu_idle(); - return 0; -} +cycles_t cacheflush_time; +unsigned long cache_decay_ticks; -void __init smp_boot_cpus(void) +void smp_tune_scheduling (void) { - int i; - - smp_num_cpus = prom_setup_smp(); - init_new_context(current, &init_mm); - current->processor = 0; - atomic_set(&cpus_booted, 1); /* Master CPU is already booted... */ - init_idle(); - for (i = 1; i < smp_num_cpus; i++) { - struct task_struct *p; - struct pt_regs regs; - printk("Starting CPU %d... ", i); - - /* Spawn a new process normally. Grab a pointer to - its task struct so we can mess with it */ - p = do_fork(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0); - - /* Schedule the first task manually */ - p->processor = i; - p->cpus_runnable = 1 << i; /* we schedule the first task manually */ - - /* Attach to the address space of init_task. */ - atomic_inc(&init_mm.mm_count); - p->active_mm = &init_mm; - init_tasks[i] = p; - - del_from_runqueue(p); - unhash_process(p); - - prom_boot_secondary(i, - (unsigned long)p + KERNEL_STACK_SIZE - 32, - (unsigned long)p); + struct cache_desc *cd = ¤t_cpu_data.scache; + unsigned long cachesize; /* kB */ + unsigned long bandwidth = 350; /* MB/s */ + unsigned long cpu_khz; -#if 0 - - /* This is copied from the ip-27 code in the mips64 tree */ - - struct task_struct *p; + /* + * Crude estimate until we actually meassure ... + */ + cpu_khz = loops_per_jiffy * 2 * HZ / 1000; + /* + * Rough estimation for SMP scheduling, this is the number of + * cycles it takes for a fully memory-limited process to flush + * the SMP-local cache. + * + * (For a P5 this pretty much means we will choose another idle + * CPU almost always at wakeup time (this is due to the small + * L1 cache), on PIIs it's around 50-100 usecs, depending on + * the cache size) + */ + if (!cpu_khz) { /* - * The following code is purely to make sure - * Linux can schedule processes on this slave. + * This basically disables processor-affinity scheduling on SMP + * without a cycle counter. Currently all SMP capable MIPS + * processors have a cycle counter. */ - kernel_thread(0, NULL, CLONE_IDLETASK); - p = prev_task(&init_task); - sprintf(p->comm, "%s%d", "Idle", i); - init_tasks[i] = p; - p->processor = i; - p->cpus_runnable = 1 << i; /* we schedule the first task manually */ - del_from_runqueue(p); - unhash_process(p); - /* Attach to the address space of init_task. */ - atomic_inc(&init_mm.mm_count); - p->active_mm = &init_mm; - prom_boot_secondary(i, - (unsigned long)p + KERNEL_STACK_SIZE - 32, - (unsigned long)p); -#endif + cacheflush_time = 0; + return; } - /* Wait for everyone to come up */ - while (atomic_read(&cpus_booted) != smp_num_cpus); + cachesize = cd->linesz * cd->sets * cd->ways; + cacheflush_time = (cpu_khz>>10) * (cachesize<<10) / bandwidth; + cache_decay_ticks = (long)cacheflush_time/cpu_khz * HZ / 1000; + + printk("per-CPU timeslice cutoff: %ld.%02ld usecs.\n", + (long)cacheflush_time/(cpu_khz/1000), + ((long)cacheflush_time*100/(cpu_khz/1000)) % 100); + printk("task migration cache decay timeout: %ld msecs.\n", + (cache_decay_ticks + 1) * 1000 / HZ); } -void __init smp_commence(void) +void __init smp_callin(void) { - /* Not sure what to do here yet */ +#if 0 + calibrate_delay(); + smp_store_cpu_info(cpuid); +#endif } -static void reschedule_this_cpu(void *dummy) +#ifndef CONFIG_SGI_IP27 +/* + * Hook for doing final board-specific setup after the generic smp setup + * is done + */ +asmlinkage void start_secondary(void) { - current->work.need_resched = 1; + unsigned int cpu = smp_processor_id(); + + cpu_probe(); + prom_init_secondary(); + per_cpu_trap_init(); + + /* + * XXX parity protection should be folded in here when it's converted + * to an option instead of something based on .cputype + */ + pgd_current[cpu] = init_mm.pgd; + cpu_data[cpu].udelay_val = loops_per_jiffy; + prom_smp_finish(); + printk("Slave cpu booted successfully\n"); + CPUMASK_SETB(cpu_online_map, cpu); + atomic_inc(&cpus_booted); + cpu_idle(); } +#endif /* CONFIG_SGI_IP27 */ -void FASTCALL(smp_send_reschedule(int cpu)) +/* + * this function sends a 'reschedule' IPI to another CPU. + * it goes straight through and wastes no time serializing + * anything. Worst case is that we lose a reschedule ... + */ +void smp_send_reschedule(int cpu) { - smp_call_function(reschedule_this_cpu, NULL, 0, 0); + core_send_ipi(cpu, SMP_RESCHEDULE_YOURSELF); } +static spinlock_t call_lock = SPIN_LOCK_UNLOCKED; + +struct call_data_struct *call_data; /* - * The caller of this wants the passed function to run on every cpu. If wait - * is set, wait until all cpus have finished the function before returning. - * The lock is here to protect the call structure. + * Run a function on all other CPUs. + * The function to run. This must be fast and non-blocking. + * An arbitrary pointer to pass to the function. + * If true, keep retrying until ready. + * If true, wait until function has completed on other CPUs. + * [RETURNS] 0 on success, else a negative status code. + * + * Does not return until remote CPUs are nearly ready to execute + * or are or have executed. + * * You must not call this function with disabled interrupts or from a * hardware interrupt handler or from a bottom half handler. */ -int smp_call_function (void (*func) (void *info), void *info, int retry, +int smp_call_function (void (*func) (void *info), void *info, int retry, int wait) { - int cpus = smp_num_cpus - 1; - int i; + struct call_data_struct data; + int i, cpus = num_online_cpus() - 1; + int cpu = smp_processor_id(); - if (smp_num_cpus < 2) { + if (!cpus) return 0; - } - - spin_lock(&smp_fn_call.lock); - atomic_set(&smp_fn_call.finished, 0); - smp_fn_call.fn = func; - smp_fn_call.data = info; - - for (i = 0; i < smp_num_cpus; i++) { - if (i != smp_processor_id()) { - /* Call the board specific routine */ - core_call_function(i); - } - } - - if (wait) { - while(atomic_read(&smp_fn_call.finished) != cpus) {} - } + data.func = func; + data.info = info; + atomic_set(&data.started, 0); + data.wait = wait; + if (wait) + atomic_set(&data.finished, 0); + + spin_lock(&call_lock); + call_data = &data; + + /* Send a message to all other CPUs and wait for them to respond */ + for (i = 0; i < NR_CPUS; i++) + if (cpu_online(cpu) && cpu != smp_processor_id()) + core_send_ipi(i, SMP_CALL_FUNCTION); + + /* Wait for response */ + /* FIXME: lock-up detection, backtrace on lock-up */ + while (atomic_read(&data.started) != cpus) + barrier(); + + if (wait) + while (atomic_read(&data.finished) != cpus) + barrier(); + spin_unlock(&call_lock); - spin_unlock(&smp_fn_call.lock); return 0; } -void synchronize_irq(void) +void smp_call_function_interrupt(void) { - panic("synchronize_irq"); + void (*func) (void *info) = call_data->func; + void *info = call_data->info; + int wait = call_data->wait; + + irq_enter(); + /* + * Notify initiating CPU that I've grabbed the data and am + * about to execute the function. + */ + mb(); + atomic_inc(&call_data->started); + + /* + * At this point the info structure may be out of scope unless wait==1. + */ + irq_enter(); + (*func)(info); + irq_exit(); + + if (wait) { + mb(); + atomic_inc(&call_data->finished); + } } static void stop_this_cpu(void *dummy) { - printk("Cpu stopping\n"); - for (;;); + /* + * Remove this CPU: + */ + clear_bit(smp_processor_id(), &cpu_online_map); + local_irq_enable(); /* May need to service _machine_restart IPI */ + for (;;); /* Wait if available. */ } void smp_send_stop(void) { smp_call_function(stop_this_cpu, NULL, 1, 0); - smp_num_cpus = 1; } /* Not really SMP stuff ... */ @@ -246,157 +266,142 @@ return 0; } +static void flush_tlb_all_ipi(void *info) +{ + local_flush_tlb_all(); +} + +void flush_tlb_all(void) +{ + on_each_cpu(flush_tlb_all_ipi, 0, 1, 1); +} + +static void flush_tlb_mm_ipi(void *mm) +{ + local_flush_tlb_mm((struct mm_struct *)mm); +} /* - * Most of this code is take from the mips64 tree (ip27-irq.c). It's virtually - * identical to the i386 implentation in arh/i386/irq.c, with translations for - * the interrupt enable bit + * The following tlb flush calls are invoked when old translations are + * being torn down, or pte attributes are changing. For single threaded + * address spaces, a new context is obtained on the current cpu, and tlb + * context on other cpus are invalidated to force a new context allocation + * at switch_mm time, should the mm ever be used on other cpus. For + * multithreaded address spaces, intercpu interrupts have to be sent. + * Another case where intercpu interrupts are required is when the target + * mm might be active on another cpu (eg debuggers doing the flushes on + * behalf of debugees, kswapd stealing pages from another process etc). + * Kanoj 07/00. */ -#define MAXCOUNT 100000000 -#define SYNC_OTHER_CORES(x) udelay(x+1) - -static inline void wait_on_irq(int cpu) +void flush_tlb_mm(struct mm_struct *mm) { - int count = MAXCOUNT; - - for (;;) { + preempt_disable(); - /* - * Wait until all interrupts are gone. Wait - * for bottom half handlers unless we're - * already executing in one.. - */ - if (!irqs_running()) - if (local_bh_count(cpu) || !spin_is_locked(&global_bh_lock)) - break; - - /* Duh, we have to loop. Release the lock to avoid deadlocks */ - spin_unlock(&global_irq_lock); - - for (;;) { - if (!--count) { - printk("Count spun out. Huh?\n"); - count = ~0; - } - local_irq_enable(); - SYNC_OTHER_CORES(cpu); - local_irq_disable(); - if (irqs_running()) - continue; - if (spin_is_locked(&global_irq_lock)) - continue; - if (!local_bh_count(cpu) && spin_is_locked(&global_bh_lock)) - continue; - if (spin_trylock(&global_irq_lock)) - break; - } + if ((atomic_read(&mm->mm_users) != 1) || (current->mm != mm)) { + smp_call_function(flush_tlb_mm_ipi, (void *)mm, 1, 1); + } else { + int i; + for (i = 0; i < num_online_cpus(); i++) + if (smp_processor_id() != i) + cpu_context(i, mm) = 0; } + local_flush_tlb_mm(mm); + + preempt_enable(); } +struct flush_tlb_data { + struct vm_area_struct *vma; + unsigned long addr1; + unsigned long addr2; +}; -static inline void get_irqlock(int cpu) +static void flush_tlb_range_ipi(void *info) { - if (!spin_trylock(&global_irq_lock)) { - /* do we already hold the lock? */ - if ((unsigned char) cpu == global_irq_holder) - return; - /* Uhhuh.. Somebody else got it. Wait.. */ - spin_lock(&global_irq_lock); - } - /* - * We also to make sure that nobody else is running - * in an interrupt context. - */ - wait_on_irq(cpu); + struct flush_tlb_data *fd = (struct flush_tlb_data *)info; - /* - * Ok, finally.. - */ - global_irq_holder = cpu; + local_flush_tlb_range(fd->vma, fd->addr1, fd->addr2); } - -/* - * A global "cli()" while in an interrupt context - * turns into just a local cli(). Interrupts - * should use spinlocks for the (very unlikely) - * case that they ever want to protect against - * each other. - * - * If we already have local interrupts disabled, - * this will not turn a local disable into a - * global one (problems with spinlocks: this makes - * save_flags+cli+sti usable inside a spinlock). - */ -void __global_cli(void) +void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) { - unsigned int flags; + struct mm_struct *mm = vma->vm_mm; - local_save_flags(flags); - if (flags & ST0_IE) { - int cpu = smp_processor_id(); - local_irq_disable(); - if (!local_irq_count(cpu)) - get_irqlock(cpu); + preempt_disable(); + if ((atomic_read(&mm->mm_users) != 1) || (current->mm != mm)) { + struct flush_tlb_data fd; + + fd.vma = vma; + fd.addr1 = start; + fd.addr2 = end; + smp_call_function(flush_tlb_range_ipi, (void *)&fd, 1, 1); + } else { + int i; + for (i = 0; i < num_online_cpus(); i++) + if (smp_processor_id() != i) + cpu_context(i, mm) = 0; } + local_flush_tlb_range(vma, start, end); + preempt_enable(); } -void __global_sti(void) +static void flush_tlb_kernel_range_ipi(void *info) { - int cpu = smp_processor_id(); + struct flush_tlb_data *fd = (struct flush_tlb_data *)info; - if (!local_irq_count(cpu)) - release_irqlock(cpu); - local_irq_enable(); + local_flush_tlb_kernel_range(fd->addr1, fd->addr2); } -/* - * SMP flags value to restore to: - * 0 - global cli - * 1 - global sti - * 2 - local cli - * 3 - local sti - */ -unsigned long __global_save_flags(void) +void flush_tlb_kernel_range(unsigned long start, unsigned long end) { - int retval; - int local_enabled; - unsigned long flags; - int cpu = smp_processor_id(); + struct flush_tlb_data fd; - local_save_flags(flags); - local_enabled = (flags & ST0_IE); - /* default to local */ - retval = 2 + local_enabled; - - /* check for global flags if we're not in an interrupt */ - if (!local_irq_count(cpu)) { - if (local_enabled) - retval = 1; - if (global_irq_holder == cpu) - retval = 0; - } + fd.addr1 = start; + fd.addr2 = end; + on_each_cpu(flush_tlb_kernel_range_ipi, (void *)&fd, 1, 1); +} + +static void flush_tlb_page_ipi(void *info) +{ + struct flush_tlb_data *fd = (struct flush_tlb_data *)info; - return retval; + local_flush_tlb_page(fd->vma, fd->addr1); } -void __global_restore_flags(unsigned long flags) +void flush_tlb_page(struct vm_area_struct *vma, unsigned long page) { - switch (flags) { - case 0: - __global_cli(); - break; - case 1: - __global_sti(); - break; - case 2: - local_irq_disable(); - break; - case 3: - local_irq_enable(); - break; - default: - printk("global_restore_flags: %08lx\n", flags); + preempt_disable(); + if ((atomic_read(&vma->vm_mm->mm_users) != 1) || (current->mm != vma->vm_mm)) { + struct flush_tlb_data fd; + + fd.vma = vma; + fd.addr1 = page; + smp_call_function(flush_tlb_page_ipi, (void *)&fd, 1, 1); + } else { + int i; + for (i = 0; i < num_online_cpus(); i++) + if (smp_processor_id() != i) + cpu_context(i, vma->vm_mm) = 0; } + local_flush_tlb_page(vma, page); + preempt_enable(); } + +static void flush_tlb_one_ipi(void *info) +{ + unsigned long vaddr = (unsigned long) info; + + local_flush_tlb_one(vaddr); +} + +void flush_tlb_one(unsigned long vaddr) +{ + smp_call_function(flush_tlb_one_ipi, (void *) vaddr, 1, 1); + local_flush_tlb_one(vaddr); +} + +EXPORT_SYMBOL(flush_tlb_page); +EXPORT_SYMBOL(flush_tlb_one); +EXPORT_SYMBOL(cpu_data); +EXPORT_SYMBOL(synchronize_irq); diff -Nru a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c --- a/arch/mips/kernel/syscall.c Tue Jul 1 18:44:37 2003 +++ b/arch/mips/kernel/syscall.c Tue Jul 1 18:44:37 2003 @@ -14,6 +14,7 @@ #undef CONF_DEBUG_IRIX #include +#include #include #include #include @@ -28,7 +29,7 @@ #include #include #include -#include +#include #include extern asmlinkage void syscall_trace(void); @@ -54,6 +55,61 @@ return res; } +unsigned long shm_align_mask = PAGE_SIZE - 1; /* Sane caches */ + +#define COLOUR_ALIGN(addr,pgoff) \ + ((((addr) + shm_align_mask) & ~shm_align_mask) + \ + (((pgoff) << PAGE_SHIFT) & shm_align_mask)) + +unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, + unsigned long len, unsigned long pgoff, unsigned long flags) +{ + struct vm_area_struct * vmm; + int do_color_align; + + if (flags & MAP_FIXED) { + /* + * We do not accept a shared mapping if it would violate + * cache aliasing constraints. + */ + if ((flags & MAP_SHARED) && (addr & shm_align_mask)) + return -EINVAL; + return addr; + } + + if (len > TASK_SIZE) + return -ENOMEM; + do_color_align = 0; + if (filp || (flags & MAP_SHARED)) + do_color_align = 1; + if (addr) { + if (do_color_align) + addr = COLOUR_ALIGN(addr, pgoff); + else + addr = PAGE_ALIGN(addr); + vmm = find_vma(current->mm, addr); + if (TASK_SIZE - len >= addr && + (!vmm || addr + len <= vmm->vm_start)) + return addr; + } + addr = TASK_UNMAPPED_BASE; + if (do_color_align) + addr = COLOUR_ALIGN(addr, pgoff); + else + addr = PAGE_ALIGN(addr); + + for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) { + /* At this point: (!vmm || addr < vmm->vm_end). */ + if (TASK_SIZE - len < addr) + return -ENOMEM; + if (!vmm || addr + len <= vmm->vm_start) + return addr; + addr = vmm->vm_end; + if (do_color_align) + addr = COLOUR_ALIGN(addr, pgoff); + } +} + /* common code for old and new mmaps */ static inline long do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, @@ -82,7 +138,16 @@ asmlinkage unsigned long old_mmap(unsigned long addr, size_t len, int prot, int flags, int fd, off_t offset) { - return do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); + int result; + + result = -EINVAL; + if (offset & ~PAGE_MASK) + goto out; + + result = do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); + +out: + return result; } asmlinkage long @@ -95,10 +160,7 @@ save_static_function(sys_fork); static_unused int _sys_fork(struct pt_regs regs) { - struct task_struct *p; - - p = do_fork(SIGCHLD, regs.regs[29], ®s, 0); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; + return do_fork(SIGCHLD, regs.regs[29], ®s, 0, NULL, NULL); } @@ -107,14 +169,16 @@ { unsigned long clone_flags; unsigned long newsp; - struct task_struct *p; + int *parent_tidptr, *child_tidptr; clone_flags = regs.regs[4]; newsp = regs.regs[5]; if (!newsp) newsp = regs.regs[29]; - p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; + parent_tidptr = (int *) regs.regs[6]; + child_tidptr = (int *) regs.regs[7]; + return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0, + parent_tidptr, child_tidptr); } /* @@ -158,7 +222,7 @@ return -EFAULT; if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname))) return -EFAULT; - + error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN); error -= __put_user(0,name->sysname+__OLD_UTS_LEN); error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN); @@ -172,76 +236,6 @@ error = error ? -EFAULT : 0; return error; -} - -/* - * Do the indirect syscall syscall. - * Don't care about kernel locking; the actual syscall will do it. - * - * XXX This is borken. - */ -asmlinkage int sys_syscall(struct pt_regs regs) -{ - syscall_t syscall; - unsigned long syscallnr = regs.regs[4]; - unsigned long a0, a1, a2, a3, a4, a5, a6; - int nargs, errno; - - if (syscallnr > __NR_Linux + __NR_Linux_syscalls) - return -ENOSYS; - - syscall = sys_call_table[syscallnr]; - nargs = sys_narg_table[syscallnr]; - /* - * Prevent stack overflow by recursive - * syscall(__NR_syscall, __NR_syscall,...); - */ - if (syscall == (syscall_t) sys_syscall) { - return -EINVAL; - } - - if (syscall == NULL) { - return -ENOSYS; - } - - if(nargs > 3) { - unsigned long usp = regs.regs[29]; - unsigned long *sp = (unsigned long *) usp; - if(usp & 3) { - printk("unaligned usp -EFAULT\n"); - force_sig(SIGSEGV, current); - return -EFAULT; - } - errno = verify_area(VERIFY_READ, (void *) (usp + 16), - (nargs - 3) * sizeof(unsigned long)); - if(errno) { - return -EFAULT; - } - switch(nargs) { - case 7: - a3 = sp[4]; a4 = sp[5]; a5 = sp[6]; a6 = sp[7]; - break; - case 6: - a3 = sp[4]; a4 = sp[5]; a5 = sp[6]; a6 = 0; - break; - case 5: - a3 = sp[4]; a4 = sp[5]; a5 = a6 = 0; - break; - case 4: - a3 = sp[4]; a4 = a5 = a6 = 0; - break; - - default: - a3 = a4 = a5 = a6 = 0; - break; - } - } else { - a3 = a4 = a5 = a6 = 0; - } - a0 = regs.regs[5]; a1 = regs.regs[6]; a2 = regs.regs[7]; - if(nargs == 0) - a0 = (unsigned long) ®s; - return syscall((void *)a0, a1, a2, a3, a4, a5, a6); } /* diff -Nru a/arch/mips/kernel/syscalls.h b/arch/mips/kernel/syscalls.h --- a/arch/mips/kernel/syscalls.h Tue Jul 1 18:44:31 2003 +++ b/arch/mips/kernel/syscalls.h Tue Jul 1 18:44:31 2003 @@ -3,7 +3,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1995, 96, 97, 98, 99, 2000 by Ralf Baechle + * Copyright (C) 1995, 96, 97, 98, 99, 2000, 2001, 2002 by Ralf Baechle */ /* @@ -20,7 +20,7 @@ SYS(sys_read, 3) SYS(sys_write, 3) SYS(sys_open, 3) /* 4005 */ -SYS(sys_close, 3) +SYS(sys_close, 1) SYS(sys_waitpid, 3) SYS(sys_creat, 2) SYS(sys_link, 2) @@ -32,7 +32,7 @@ SYS(sys_chmod, 2) /* 4015 */ SYS(sys_lchown, 3) SYS(sys_ni_syscall, 0) -SYS(sys_stat, 2) +SYS(sys_ni_syscall, 0) /* was sys_stat */ SYS(sys_lseek, 3) SYS(sys_getpid, 0) /* 4020 */ SYS(sys_mount, 5) @@ -42,7 +42,7 @@ SYS(sys_stime, 1) /* 4025 */ SYS(sys_ptrace, 4) SYS(sys_alarm, 1) -SYS(sys_fstat, 2) +SYS(sys_ni_syscall, 0) /* was sys_fstat */ SYS(sys_pause, 0) SYS(sys_utime, 2) /* 4030 */ SYS(sys_ni_syscall, 0) @@ -96,9 +96,9 @@ SYS(sys_settimeofday, 2) SYS(sys_getgroups, 2) /* 4080 */ SYS(sys_setgroups, 2) -SYS(sys_ni_syscall, 0) /* old_select */ +SYS(sys_ni_syscall, 0) /* old_select */ SYS(sys_symlink, 2) -SYS(sys_lstat, 2) +SYS(sys_ni_syscall, 0) /* was sys_lstat */ SYS(sys_readlink, 3) /* 4085 */ SYS(sys_uselib, 1) SYS(sys_swapon, 2) @@ -115,7 +115,7 @@ SYS(sys_ni_syscall, 0) SYS(sys_statfs, 2) SYS(sys_fstatfs, 2) /* 4100 */ -SYS(sys_ioperm, 3) +SYS(sys_ni_syscall, 0) /* was ioperm(2) */ SYS(sys_socketcall, 2) SYS(sys_syslog, 3) SYS(sys_setitimer, 3) @@ -124,10 +124,10 @@ SYS(sys_newlstat, 2) SYS(sys_newfstat, 2) SYS(sys_uname, 1) -SYS(sys_iopl, 0) /* Well, actually 17 args ... */ /* 4110 */ +SYS(sys_ni_syscall, 0) /* 4110 was iopl(2) */ SYS(sys_vhangup, 0) -SYS(sys_ni_syscall, 0) /* was sys_idle() */ -SYS(sys_vm86, 1) +SYS(sys_ni_syscall, 0) /* was sys_idle() */ +SYS(sys_ni_syscall, 0) /* was sys_vm86 */ SYS(sys_wait4, 4) SYS(sys_swapoff, 1) /* 4115 */ SYS(sys_sysinfo, 1) @@ -141,10 +141,10 @@ SYS(sys_adjtimex, 1) SYS(sys_mprotect, 3) /* 4125 */ SYS(sys_sigprocmask, 3) -SYS(sys_create_module, 2) +SYS(sys_ni_syscall, 0) /* was create_module */ SYS(sys_init_module, 5) SYS(sys_delete_module, 1) -SYS(sys_get_kernel_syms, 1) /* 4130 */ +SYS(sys_ni_syscall, 0) /* 4130, was get_kernel_syms */ SYS(sys_quotactl, 0) SYS(sys_getpgid, 1) SYS(sys_fchdir, 1) @@ -201,7 +201,7 @@ SYS(sys_socketpair, 4) SYS(sys_setresuid, 3) /* 4185 */ SYS(sys_getresuid, 3) -SYS(sys_query_module, 5) +SYS(sys_ni_syscall, 0) /* sys_query_module */ SYS(sys_poll, 3) SYS(sys_nfsservctl, 3) SYS(sys_setresgid, 3) /* 4190 */ @@ -214,19 +214,19 @@ SYS(sys_rt_sigtimedwait, 4) SYS(sys_rt_sigqueueinfo, 3) SYS(sys_rt_sigsuspend, 0) -SYS(sys_pread, 6) /* 4200 */ -SYS(sys_pwrite, 6) +SYS(sys_pread64, 6) /* 4200 */ +SYS(sys_pwrite64, 6) SYS(sys_chown, 3) SYS(sys_getcwd, 2) SYS(sys_capget, 2) SYS(sys_capset, 2) /* 4205 */ SYS(sys_sigaltstack, 0) -SYS(sys_sendfile, 3) +SYS(sys_sendfile, 4) SYS(sys_ni_syscall, 0) SYS(sys_ni_syscall, 0) SYS(sys_mmap2, 6) /* 4210 */ -SYS(sys_truncate64, 2) -SYS(sys_ftruncate64, 2) +SYS(sys_truncate64, 4) +SYS(sys_ftruncate64, 4) SYS(sys_stat64, 2) SYS(sys_lstat64, 2) SYS(sys_fstat64, 2) /* 4215 */ @@ -235,5 +235,39 @@ SYS(sys_madvise, 3) SYS(sys_getdents64, 3) SYS(sys_fcntl64, 3) /* 4220 */ +SYS(sys_ni_syscall, 0) SYS(sys_gettid, 0) +SYS(sys_readahead, 5) +SYS(sys_setxattr, 5) +SYS(sys_lsetxattr, 5) /* 4225 */ +SYS(sys_fsetxattr, 5) +SYS(sys_getxattr, 4) +SYS(sys_lgetxattr, 4) +SYS(sys_fgetxattr, 4) +SYS(sys_listxattr, 3) /* 4230 */ +SYS(sys_llistxattr, 3) +SYS(sys_flistxattr, 3) +SYS(sys_removexattr, 2) +SYS(sys_lremovexattr, 2) +SYS(sys_fremovexattr, 2) /* 4235 */ SYS(sys_tkill, 2) +SYS(sys_sendfile64, 5) +SYS(sys_futex, 2) +SYS(sys_sched_setaffinity, 3) +SYS(sys_sched_getaffinity, 3) /* 4240 */ +SYS(sys_io_setup, 2) +SYS(sys_io_destroy, 1) +SYS(sys_io_getevents, 5) +SYS(sys_io_submit, 3) +SYS(sys_io_cancel, 3) /* 4245 */ +SYS(sys_exit_group, 1) +SYS(sys_lookup_dcookie, 3) +SYS(sys_epoll_create, 1) +SYS(sys_epoll_ctl, 4) +SYS(sys_epoll_wait, 3) /* 4250 */ +SYS(sys_remap_file_pages, 5) +SYS(sys_set_tid_address, 1) +SYS(sys_restart_syscall, 0) /* XXX */ +SYS(sys_fadvise64, 6) +SYS(sys_statfs64, 3) /* 4255 */ +SYS(sys_fstatfs64, 2) diff -Nru a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c --- a/arch/mips/kernel/sysirix.c Tue Jul 1 18:44:38 2003 +++ b/arch/mips/kernel/sysirix.c Tue Jul 1 18:44:38 2003 @@ -7,6 +7,8 @@ */ #include #include +#include +#include #include #include #include @@ -24,6 +26,8 @@ #include #include #include +#include +#include #include #include @@ -55,7 +59,7 @@ break; case MP_NPROCS: case MP_NAPROCS: - error = smp_num_cpus; + error = num_online_cpus(); break; default: printk("SYSMP[%s:%d]: Unsupported opcode %d\n", @@ -111,7 +115,7 @@ if (error) error = (task->run_list.next != NULL); read_unlock(&tasklist_lock); - /* Can _your_ OS find this out that fast? */ + /* Can _your_ OS find this out that fast? */ break; } @@ -334,7 +338,7 @@ current->comm, current->pid, name, value, retval); /* if (retval == PROM_ENOENT) retval = -ENOENT; */ - break; + break; } #endif @@ -507,7 +511,7 @@ } break; } - + default: printk("irix_syssgi: Unsupported command %d\n", (int)cmd); retval = -EINVAL; @@ -600,7 +604,7 @@ asmlinkage int irix_getpid(struct pt_regs *regs) { - regs->regs[3] = current->p_opptr->pid; + regs->regs[3] = current->real_parent->pid; return current->pid; } @@ -623,9 +627,11 @@ write_seqlock_irq(&xtime_lock); xtime.tv_sec = value; - xtime.tv_usec = 0; - time_maxerror = MAXPHASE; - time_esterror = MAXPHASE; + xtime.tv_nsec = 0; + time_adjust = 0; /* stop active adjtime() */ + time_status |= STA_UNSYNC; + time_maxerror = NTP_PHASE_LIMIT; + time_esterror = NTP_PHASE_LIMIT; write_sequnlock_irq(&xtime_lock); return 0; @@ -819,10 +825,10 @@ err = verify_area(VERIFY_WRITE,tbuf,sizeof *tbuf); if (err) return err; - err |= __put_user(current->times.tms_utime,&tbuf->tms_utime); - err |= __put_user(current->times.tms_stime,&tbuf->tms_stime); - err |= __put_user(current->times.tms_cutime,&tbuf->tms_cutime); - err |= __put_user(current->times.tms_cstime,&tbuf->tms_cstime); + err |= __put_user(current->utime, &tbuf->tms_utime); + err |= __put_user(current->stime, &tbuf->tms_stime); + err |= __put_user(current->cutime, &tbuf->tms_cutime); + err |= __put_user(current->cstime, &tbuf->tms_cstime); } return err; @@ -1048,7 +1054,23 @@ asmlinkage int irix_gettimeofday(struct timeval *tv) { - return copy_to_user(tv, &xtime, sizeof(*tv)) ? -EFAULT : 0; + time_t sec; + long nsec, seq; + int err; + + if (verify_area(VERIFY_WRITE, tv, sizeof(struct timeval))) + return -EFAULT; + + do { + seq = read_seqbegin(&xtime_lock); + sec = xtime.tv_sec; + nsec = xtime.tv_nsec; + } while (read_seqretry(&xtime_lock, seq)); + + err = __put_user(sec, &tv->tv_sec); + err |= __put_user((nsec / 1000), &tv->tv_usec); + + return err; } #define IRIX_MAP_AUTOGROW 0x40 @@ -1068,7 +1090,7 @@ if (flags & IRIX_MAP_AUTOGROW) { unsigned long old_pos; long max_size = offset + len; - + if (max_size > file->f_dentry->d_inode->i_size) { old_pos = sys_lseek (fd, max_size - 1, 0); sys_write (fd, "", 1); @@ -1198,14 +1220,14 @@ #if BITS_PER_LONG == 32 if (stat->size > MAX_NON_LFS) return -EOVERFLOW; -#endif +#endif ub.st_size = stat->size; - ub.st_atime0 = stat->atime; - ub.st_atime1 = 0; - ub.st_mtime0 = stat->mtime; - ub.st_mtime1 = 0; - ub.st_ctime0 = stat->ctime; - ub.st_ctime1 = 0; + ub.st_atime0 = stat->atime.tv_sec; + ub.st_atime1 = stat->atime.tv_nsec; + ub.st_mtime0 = stat->mtime.tv_sec; + ub.st_mtime1 = stat->atime.tv_nsec; + ub.st_ctime0 = stat->ctime.tv_sec; + ub.st_ctime1 = stat->atime.tv_nsec; ub.st_blksize = stat->blksize; ub.st_blocks = stat->blocks; strcpy (ub.st_fstype, "efs"); @@ -1243,9 +1265,12 @@ ks.st_pad3 = 0; /* XXX hackety hack... */ - ks.st_atime.tv_sec = (s32) stat->atime; ks.st_atime.tv_nsec = 0; - ks.st_mtime.tv_sec = (s32) stat->atime; ks.st_mtime.tv_nsec = 0; - ks.st_ctime.tv_sec = (s32) stat->atime; ks.st_ctime.tv_nsec = 0; + ks.st_atime.tv_sec = (s32) stat->atime.tv_sec; + ks.st_atime.tv_nsec = stat->atime.tv_nsec; + ks.st_mtime.tv_sec = (s32) stat->mtime.tv_sec; + ks.st_mtime.tv_nsec = stat->mtime.tv_nsec;; + ks.st_ctime.tv_sec = (s32) stat->ctime.tv_sec; + ks.st_ctime.tv_nsec = stat->ctime.tv_nsec;; ks.st_blksize = (s32) stat->blksize; ks.st_blocks = (long long) stat->blocks; @@ -1812,7 +1837,8 @@ return 0; } -asmlinkage int irix_ngetdents(unsigned int fd, void * dirent, unsigned int count, int *eob) +asmlinkage int irix_ngetdents(unsigned int fd, void * dirent, + unsigned int count, int *eob) { struct file *file; struct irix_dirent32 *lastdirent; @@ -1836,6 +1862,7 @@ error = vfs_readdir(file, irix_filldir32, &buf); if (error < 0) goto out_putf; + error = buf.error; lastdirent = buf.previous; if (lastdirent) { @@ -1844,10 +1871,9 @@ } if (put_user(0, eob) < 0) { - error = EFAULT; + error = -EFAULT; goto out_putf; } - #ifdef DEBUG_GETDENTS printk("eob=%d returning %d\n", *eob, count - buf.count); diff -Nru a/arch/mips/kernel/sysmips.c b/arch/mips/kernel/sysmips.c --- a/arch/mips/kernel/sysmips.c Tue Jul 1 18:44:33 2003 +++ b/arch/mips/kernel/sysmips.c Tue Jul 1 18:44:33 2003 @@ -1,13 +1,11 @@ /* - * MIPS specific syscalls - * * 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) 1995, 1996, 1997, 2000 by Ralf Baechle + * Copyright (C) 1995, 1996, 1997, 2000, 2001 by Ralf Baechle + * Copyright (C) 2001 MIPS Technologies, Inc. */ -#include #include #include #include @@ -19,7 +17,7 @@ #include #include -#include +#include #include #include @@ -49,11 +47,10 @@ } asmlinkage int -sys_sysmips(int cmd, int arg1, int arg2, int arg3) +_sys_sysmips(int cmd, int arg1, int arg2, int arg3) { - int *p; char *name; - int tmp, len, retval, errno; + int tmp, len, retval; switch(cmd) { case SETNAME: { @@ -65,66 +62,22 @@ name = (char *) arg1; len = strncpy_from_user(nodename, name, __NEW_UTS_LEN); - if (len < 0) + if (len < 0) return -EFAULT; - nodename[__NEW_UTS_LEN] = '\0'; down_write(&uts_sem); + strncpy(system_utsname.nodename, nodename, len); + nodename[__NEW_UTS_LEN] = '\0'; strlcpy(system_utsname.nodename, nodename, - sizeof(system_utsname.nodename)); + sizeof(system_utsname.nodename)); up_write(&uts_sem); return 0; } - case MIPS_ATOMIC_SET: { -#ifdef CONFIG_CPU_HAS_LLSC - unsigned int tmp; - - p = (int *) arg1; - errno = verify_area(VERIFY_WRITE, p, sizeof(*p)); - if (errno) - return errno; - errno = 0; - - __asm__(".set\tpush\t\t\t# sysmips(MIPS_ATOMIC, ...)\n\t" - ".set\tmips2\n\t" - ".set\tnoat\n\t" - "1:\tll\t%0, %4\n\t" - "move\t$1, %3\n\t" - "2:\tsc\t$1, %1\n\t" - "beqz\t$1, 1b\n\t" - ".set\tpop\n\t" - ".section\t.fixup,\"ax\"\n" - "3:\tli\t%2, 1\t\t\t# error\n\t" - ".previous\n\t" - ".section\t__ex_table,\"a\"\n\t" - ".word\t1b, 3b\n\t" - ".word\t2b, 3b\n\t" - ".previous\n\t" - : "=&r" (tmp), "=o" (* (u32 *) p), "=r" (errno) - : "r" (arg2), "o" (* (u32 *) p), "2" (errno) - : "$1"); - - if (errno) - return -EFAULT; - - /* We're skipping error handling etc. */ - if (current->ptrace & PT_TRACESYS) - syscall_trace(); - - ((struct pt_regs *)&cmd)->regs[2] = tmp; - ((struct pt_regs *)&cmd)->regs[7] = 0; - - __asm__ __volatile__( - "move\t$29, %0\n\t" - "j\to32_ret_from_sys_call" - : /* No outputs */ - : "r" (&cmd)); - /* Unreached */ -#else - printk("sys_sysmips(MIPS_ATOMIC_SET, ...) not ready for !CONFIG_CPU_HAS_LLSC\n"); -#endif - } + case MIPS_ATOMIC_SET: + printk(KERN_CRIT "How did I get here?\n"); + retval = -EINVAL; + goto out; case MIPS_FIXADE: tmp = current->thread.mflags & ~3; @@ -133,7 +86,7 @@ goto out; case FLUSH_CACHE: - flush_cache_all(); + __flush_cache_all(); retval = 0; goto out; diff -Nru a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c --- a/arch/mips/kernel/time.c Tue Jul 1 18:44:34 2003 +++ b/arch/mips/kernel/time.c Tue Jul 1 18:44:34 2003 @@ -2,8 +2,8 @@ * Copyright 2001 MontaVista Software Inc. * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net * - * Common time service routines for MIPS machines. See - * Documentation/mips/time.README. + * Common time service routines for MIPS machines. See + * Documents/mips/README.txt. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -30,7 +31,9 @@ /* This is for machines which generate the exact clock. */ #define USECS_PER_JIFFY (1000000/HZ) -#define USECS_PER_JIFFY_FRAC ((1000000ULL << 32) / HZ & 0xffffffff) +#define USECS_PER_JIFFY_FRAC ((u32)((1000000ULL << 32) / HZ)) + +#define TICK_SIZE (tick_nsec / 1000) u64 jiffies_64 = INITIAL_JIFFIES; @@ -39,6 +42,13 @@ */ extern volatile unsigned long wall_jiffies; +spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED; + +/* + * whether we emulate local_timer_interrupts for SMP machines. + */ +int emulate_local_timer_interrupt; + /* * By default we provide the null RTC ops */ @@ -57,58 +67,64 @@ /* - * timeofday services, for syscalls. + * This version of gettimeofday has microsecond resolution and better than + * microsecond precision on fast machines with cycle counter. */ void do_gettimeofday(struct timeval *tv) { - unsigned long flags; unsigned long seq; + unsigned long usec, sec; do { - seq = read_seqbegin_irqsave(&xtime_lock, flags); - - *tv = xtime; - tv->tv_usec += do_gettimeoffset(); - - /* - * xtime is atomically updated in timer_bh. - * jiffies - wall_jiffies - * is nonzero if the timer bottom half hasnt executed yet. - */ - if (jiffies - wall_jiffies) - tv->tv_usec += USECS_PER_JIFFY; - } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); - + seq = read_seqbegin(&xtime_lock); + usec = do_gettimeoffset(); + { + unsigned long lost = jiffies - wall_jiffies; + if (lost) + usec += lost * (1000000 / HZ); + } + sec = xtime.tv_sec; + usec += (xtime.tv_nsec / 1000); + } while (read_seqretry(&xtime_lock, seq)); - if (tv->tv_usec >= 1000000) { - tv->tv_usec -= 1000000; - tv->tv_sec++; + while (usec >= 1000000) { + usec -= 1000000; + sec++; } + + tv->tv_sec = sec; + tv->tv_usec = usec; } -void do_settimeofday(struct timeval *tv) +int do_settimeofday(struct timespec *tv) { - write_seqlock_irq (&xtime_lock); + if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) + return -EINVAL; - /* This is revolting. We need to set the xtime.tv_usec - * correctly. However, the value in this location is - * is value at the last tick. - * Discover what correction gettimeofday - * would have done, and then undo it! + write_seqlock_irq(&xtime_lock); + /* + * This is revolting. We need to set "xtime" correctly. However, the + * value in this location is the value at the most recent update of + * wall time. Discover what correction gettimeofday() would have + * made, and then undo it! */ - tv->tv_usec -= do_gettimeoffset(); + tv->tv_nsec -= do_gettimeoffset() * NSEC_PER_USEC; + tv->tv_nsec -= (jiffies - wall_jiffies) * TICK_NSEC; - if (tv->tv_usec < 0) { - tv->tv_usec += 1000000; + while (tv->tv_nsec < 0) { + tv->tv_nsec += NSEC_PER_SEC; tv->tv_sec--; } - xtime = *tv; - time_adjust = 0; /* stop active adjtime() */ + + xtime.tv_sec = tv->tv_sec; + xtime.tv_nsec = tv->tv_nsec; + time_adjust = 0; /* stop active adjtime() */ time_status |= STA_UNSYNC; time_maxerror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT; + write_sequnlock_irq(&xtime_lock); - write_sequnlock_irq (&xtime_lock); + return 0; } @@ -137,6 +153,9 @@ /* Cycle counter value at the previous timer interrupt.. */ static unsigned int timerhi, timerlo; +/* expirelo is the count value for next CPU timer interrupt */ +static unsigned int expirelo; + /* last time when xtime and rtc are sync'ed up */ static long last_rtc_update; @@ -154,7 +173,7 @@ unsigned long res; /* Get last timer tick in absolute kernel time */ - count = read_32bit_cp0_register(CP0_COUNT); + count = read_c0_count(); /* .. relative to previous jiffy (32 bits is enough) */ count -= timerlo; @@ -210,7 +229,7 @@ } /* Get last timer tick in absolute kernel time */ - count = read_32bit_cp0_register(CP0_COUNT); + count = read_c0_count(); /* .. relative to previous jiffy (32 bits is enough) */ count -= timerlo; @@ -260,13 +279,12 @@ :"r" (timerhi), "m" (timerlo), "r" (tmp), - "r" (USECS_PER_JIFFY) - :"$1"); + "r" (USECS_PER_JIFFY)); cached_quotient = quotient; } /* Get last timer tick in absolute kernel time */ - count = read_32bit_cp0_register(CP0_COUNT); + count = read_c0_count(); /* .. relative to previous jiffy (32 bits is enough) */ count -= timerlo; @@ -289,35 +307,18 @@ /* - * high-level timer interrupt service routines. This function - * is set as irqaction->handler and is invoked through do_IRQ. + * local_timer_interrupt() does profiling and process accounting + * on a per-CPU basis. + * + * In UP mode, it is invoked from the (global) timer_interrupt. + * + * In SMP mode, it might invoked by per-CPU timer interrupt, or + * a broadcasted inter-processor interrupt which itself is triggered + * by the global timer interrupt. */ -void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +void local_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - unsigned long seq; - - if (mips_cpu.options & MIPS_CPU_COUNTER) { - unsigned int count; - - /* - * The cycle counter is only 32 bit which is good for about - * a minute at current count rates of upto 150MHz or so. - */ - count = read_32bit_cp0_register(CP0_COUNT); - timerhi += (count < timerlo); /* Wrap around */ - timerlo = count; - - /* - * set up for next timer interrupt - no harm if the machine - * is using another timer interrupt source. - * Note that writing to COMPARE register clears the interrupt - */ - write_32bit_cp0_register (CP0_COMPARE, - count + cycles_per_jiffy); - - } - - if(!user_mode(regs)) { + if (!user_mode(regs)) { if (prof_buffer && current->pid) { extern int _stext; unsigned long pc = regs->cp0_epc; @@ -335,6 +336,38 @@ } } +#ifdef CONFIG_SMP + /* in UP mode, update_process_times() is invoked by do_timer() */ + update_process_times(user_mode(regs)); +#endif +} + +/* + * high-level timer interrupt service routines. This function + * is set as irqaction->handler and is invoked through do_IRQ. + */ +irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + if (cpu_has_counter) { + unsigned int count; + + /* ack timer interrupt, and try to set next interrupt */ + expirelo += cycles_per_jiffy; + write_c0_compare(expirelo); + count = read_c0_count(); + + /* check to see if we have missed any timer interrupts */ + if ((count - expirelo) < 0x7fffffff) { + /* missed_timer_count ++; */ + expirelo = count + cycles_per_jiffy; + write_c0_compare(expirelo); + } + + /* Update timerhi/timerlo for intra-jiffy calibration. */ + timerhi += count < timerlo; /* Wrap around */ + timerlo = count; + } + /* * call the generic timer interrupt handling */ @@ -345,21 +378,19 @@ * CMOS clock accordingly every ~11 minutes. rtc_set_time() has to be * called as close as possible to 500 ms before the new second starts. */ - do { - seq = read_seqbegin(&xtime_lock); - - if ((time_status & STA_UNSYNC) == 0 && - xtime.tv_sec > last_rtc_update + 660 && - xtime.tv_usec >= 500000 - ((unsigned) tick) / 2 && - xtime.tv_usec <= 500000 + ((unsigned) tick) / 2) { - if (rtc_set_time(xtime.tv_sec) == 0) { - last_rtc_update = xtime.tv_sec; - } else { - last_rtc_update = xtime.tv_sec - 600; - /* do it again in 60 s */ - } + write_seqlock(&xtime_lock); + if ((time_status & STA_UNSYNC) == 0 && + xtime.tv_sec > last_rtc_update + 660 && + (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 && + (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) { + if (rtc_set_time(xtime.tv_sec) == 0) { + last_rtc_update = xtime.tv_sec; + } else { + last_rtc_update = xtime.tv_sec - 600; + /* do it again in 60 s */ } - } while (read_seqretry(&xtime_lock, seq)); + } + write_sequnlock(&xtime_lock); /* * If jiffies has overflowed in this timer_interrupt we must @@ -369,41 +400,83 @@ if (!jiffies) { timerhi = timerlo = 0; } + +#if !defined(CONFIG_SMP) + /* + * In UP mode, we call local_timer_interrupt() to do profiling + * and process accouting. + * + * In SMP mode, local_timer_interrupt() is invoked by appropriate + * low-level local timer interrupt handler. + */ + local_timer_interrupt(0, NULL, regs); + +#else /* CONFIG_SMP */ + + if (emulate_local_timer_interrupt) { + /* + * this is the place where we send out inter-process + * interrupts and let each CPU do its own profiling + * and process accouting. + * + * Obviously we need to call local_timer_interrupt() for + * the current CPU too. + */ + panic("Not implemented yet!!!"); + } +#endif /* CONFIG_SMP */ + + return IRQ_HANDLED; } asmlinkage void ll_timer_interrupt(int irq, struct pt_regs *regs) { int cpu = smp_processor_id(); - irq_enter(cpu, irq); + irq_enter(); kstat_cpu(cpu).irqs[irq]++; /* we keep interrupt disabled all the time */ timer_interrupt(irq, NULL, regs); - - irq_exit(cpu, irq); + + irq_exit(); if (softirq_pending(cpu)) do_softirq(); } +asmlinkage void ll_local_timer_interrupt(int irq, struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + + irq_enter(); + kstat_cpu(cpu).irqs[irq]++; + + /* we keep interrupt disabled all the time */ + local_timer_interrupt(irq, NULL, regs); + + irq_exit(); + + if (softirq_pending(cpu)) + do_softirq(); +} /* * time_init() - it does the following things. * - * 1) board_time_init() - - * a) (optional) set up RTC routines, + * 1) board_time_init() - + * a) (optional) set up RTC routines, * b) (optional) calibrate and set the mips_counter_frequency * (only needed if you intended to use fixed_rate_gettimeoffset * or use cpu counter as timer interrupt source) * 2) setup xtime based on rtc_get_time(). * 3) choose a appropriate gettimeoffset routine. * 4) calculate a couple of cached variables for later usage - * 5) board_timer_setup() - + * 5) board_timer_setup() - * a) (optional) over-write any choices made above by time_init(). * b) machine specific code should setup the timer irqaction. * c) enable the timer interrupt - */ + */ void (*board_time_init)(void) = NULL; void (*board_timer_setup)(struct irqaction *irq) = NULL; @@ -416,7 +489,8 @@ 0, "timer", NULL, - NULL}; + NULL +}; void __init time_init(void) { @@ -424,18 +498,18 @@ board_time_init(); xtime.tv_sec = rtc_get_time(); - xtime.tv_usec = 0; + xtime.tv_nsec = 0; /* choose appropriate gettimeoffset routine */ - if (!(mips_cpu.options & MIPS_CPU_COUNTER)) { + if (!cpu_has_counter) { /* no cpu counter - sorry */ do_gettimeoffset = null_gettimeoffset; } else if (mips_counter_frequency != 0) { /* we have cpu counter and know counter frequency! */ do_gettimeoffset = fixed_rate_gettimeoffset; - } else if ((mips_cpu.isa_level == MIPS_CPU_ISA_M32) || - (mips_cpu.isa_level == MIPS_CPU_ISA_I) || - (mips_cpu.isa_level == MIPS_CPU_ISA_II) ) { + } else if ((current_cpu_data.isa_level == MIPS_CPU_ISA_M32) || + (current_cpu_data.isa_level == MIPS_CPU_ISA_I) || + (current_cpu_data.isa_level == MIPS_CPU_ISA_II) ) { /* we need to calibrate the counter but we don't have * 64-bit division. */ do_gettimeoffset = calibrate_div32_gettimeoffset; @@ -443,7 +517,7 @@ /* we need to calibrate the counter but we *do* have * 64-bit division. */ do_gettimeoffset = calibrate_div64_gettimeoffset; - } + } /* caclulate cache parameters */ if (mips_counter_frequency) { @@ -454,16 +528,24 @@ sll32_usecs_per_cycle = mips_counter_frequency / 100000; sll32_usecs_per_cycle = 0xffffffff / sll32_usecs_per_cycle; sll32_usecs_per_cycle *= 10; + + /* + * For those using cpu counter as timer, this sets up the + * first interrupt + */ + write_c0_compare(cycles_per_jiffy); + write_c0_count(0); + expirelo = cycles_per_jiffy; } - /* + /* * Call board specific timer interrupt setup. * - * this pointer must be setup in machine setup routine. + * this pointer must be setup in machine setup routine. * * Even if the machine choose to use low-level timer interrupt, * it still needs to setup the timer_irqaction. - * In that case, it might be better to set timer_irqaction.handler + * In that case, it might be better to set timer_irqaction.handler * to be NULL function so that we are sure the high-level code * is not invoked accidentally. */ @@ -484,10 +566,10 @@ void to_tm(unsigned long tim, struct rtc_time * tm) { - long hms, day; + long hms, day, gday; int i; - day = tim / SECDAY; + gday = day = tim / SECDAY; hms = tim % SECDAY; /* Hours, minutes, seconds are easy */ @@ -506,7 +588,7 @@ for (i = 1; day >= days_in_month(i); i++) day -= days_in_month(i); days_in_month(FEBRUARY) = 28; - tm->tm_mon = i; + tm->tm_mon = i-1; /* tm_mon starts from 0 to 11 */ /* Days are what is left over (+1) from all that. */ tm->tm_mday = day + 1; @@ -514,5 +596,7 @@ /* * Determine the day of week */ - tm->tm_wday = (day + 3) % 7; + tm->tm_wday = (gday + 4) % 7; /* 1970/1/1 was Thursday */ } + +EXPORT_SYMBOL(rtc_lock); diff -Nru a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c --- a/arch/mips/kernel/traps.c Tue Jul 1 18:44:34 2003 +++ b/arch/mips/kernel/traps.c Tue Jul 1 18:44:34 2003 @@ -4,12 +4,12 @@ * for more details. * * Copyright (C) 1994 - 1999, 2000, 01 Ralf Baechle - * Modified for R3000 by Paul M. Antoine, 1995, 1996 - * Complete output from die() by Ulf Carlsson, 1998 + * Copyright (C) 1995, 1996 Paul M. Antoine + * Copyright (C) 1998 Ulf Carlsson * Copyright (C) 1999 Silicon Graphics, Inc. - * * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com * Copyright (C) 2000, 01 MIPS Technologies, Inc. + * Copyright (C) 2002, 2003 Maciej W. Rozycki */ #include #include @@ -19,30 +19,23 @@ #include #include #include +#include #include #include #include -#include -#include -#include +#include #include #include -#include -#include -#include +#include +#include #include +#include +#include #include #include - -/* - * Machine specific interrupt handlers - */ -extern asmlinkage void acer_pica_61_handle_int(void); -extern asmlinkage void decstation_handle_int(void); -extern asmlinkage void deskstation_rpc44_handle_int(void); -extern asmlinkage void deskstation_tyne_handle_int(void); -extern asmlinkage void mips_magnum_4000_handle_int(void); +#include +#include extern asmlinkage void handle_mod(void); extern asmlinkage void handle_tlbl(void); @@ -58,16 +51,16 @@ extern asmlinkage void handle_ov(void); extern asmlinkage void handle_tr(void); extern asmlinkage void handle_fpe(void); +extern asmlinkage void handle_mdmx(void); extern asmlinkage void handle_watch(void); extern asmlinkage void handle_mcheck(void); extern asmlinkage void handle_reserved(void); -extern int fpu_emulator_cop1Handler(struct pt_regs *); - -char watch_available = 0; +extern int fpu_emulator_cop1Handler(int xcptno, struct pt_regs *xcp, + struct mips_fpu_soft_struct *ctx); -void (*ibe_board_handler)(struct pt_regs *regs); -void (*dbe_board_handler)(struct pt_regs *regs); +void (*board_be_init)(void); +int (*board_be_handler)(struct pt_regs *regs, int is_fixup); /* * These constant is for searching for possible module text segments. @@ -75,99 +68,74 @@ */ #define MODULE_RANGE (8*1024*1024) -#ifndef CONFIG_CPU_HAS_LLSC -/* - * This stuff is needed for the userland ll-sc emulation for R2300 - */ -void simulate_ll(struct pt_regs *regs, unsigned int opcode); -void simulate_sc(struct pt_regs *regs, unsigned int opcode); - -#define OPCODE 0xfc000000 -#define BASE 0x03e00000 -#define RT 0x001f0000 -#define OFFSET 0x0000ffff -#define LL 0xc0000000 -#define SC 0xe0000000 -#endif - /* * This routine abuses get_user()/put_user() to reference pointers * with at least a bit of error checking ... */ -void show_stack(unsigned int *sp) +void show_stack(struct task_struct *task, unsigned long *sp) { + const int field = 2 * sizeof(unsigned long); + long stackdata; int i; - unsigned int *stack; - - stack = sp; - i = 0; - printk("Stack:"); - while ((unsigned long) stack & (PAGE_SIZE - 1)) { - unsigned long stackdata; + sp = sp ? sp : (unsigned long *) &sp; - if (__get_user(stackdata, stack++)) { - printk(" (Bad stack address)"); + printk("Stack: "); + i = 1; + while ((unsigned long) sp & (PAGE_SIZE - 1)) { + if (i && ((i % (64 / sizeof(unsigned long))) == 0)) + printk("\n "); + if (i > 40) { + printk(" ..."); break; } - printk(" %08lx", stackdata); - - if (++i > 40) { - printk(" ..."); + if (__get_user(stackdata, sp++)) { + printk(" (Bad stack address)"); break; } - if (i % 8 == 0) - printk("\n "); + printk(" %0*lx", field, stackdata); + i++; } + printk("\n"); } -void show_trace(unsigned int *sp) +void show_trace(struct task_struct *task, unsigned long *stack) { - int i; - unsigned int *stack; - unsigned long kernel_start, kernel_end; - unsigned long module_start, module_end; - extern char _stext, _etext; - - stack = sp; - i = 0; - - kernel_start = (unsigned long) &_stext; - kernel_end = (unsigned long) &_etext; - module_start = VMALLOC_START; - module_end = module_start + MODULE_RANGE; + const int field = 2 * sizeof(unsigned long); + unsigned long addr; - printk("\nCall Trace:"); + if (!stack) + stack = (unsigned long*)&stack; - while ((unsigned long) stack & (PAGE_SIZE -1)) { - unsigned long addr; - - if (__get_user(addr, stack++)) { - printk(" (Bad stack address)\n"); - break; + printk("Call Trace:"); +#ifdef CONFIG_KALLSYMS + printk("\n"); +#endif + while (((long) stack & (THREAD_SIZE-1)) != 0) { + addr = *stack++; + if (kernel_text_address(addr)) { + printk(" [<%0*lx>] ", field, addr); + print_symbol("%s\n", addr); } + } + printk("\n"); +} - /* - * If the address is either in the text segment of the - * kernel, or in the region which contains vmalloc'ed - * memory, it *may* be the address of a calling - * routine; if so, print it so that someone tracing - * down the cause of the crash will be able to figure - * out the call path that was taken. - */ +void show_trace_task(struct task_struct *tsk) +{ + show_trace(tsk, (long *)tsk->thread.reg29); +} - if ((addr >= kernel_start && addr < kernel_end) || - (addr >= module_start && addr < module_end)) { +/* + * The architecture-independent dump_stack generator + */ +void dump_stack(void) +{ + unsigned long stack; - printk(" [<%08lx>]", addr); - if (++i > 40) { - printk(" ..."); - break; - } - } - } + show_trace(current, &stack); } void show_code(unsigned int *pc) @@ -177,43 +145,114 @@ printk("\nCode:"); for(i = -3 ; i < 6 ; i++) { - unsigned long insn; + unsigned int insn; if (__get_user(insn, pc + i)) { printk(" (Bad address in epc)\n"); break; } - printk("%c%08lx%c",(i?' ':'<'),insn,(i?' ':'>')); + printk("%c%08x%c", (i?' ':'<'), insn, (i?' ':'>')); + } +} + +void show_regs(struct pt_regs *regs) +{ + const int field = 2 * sizeof(unsigned long); + int i; + + printk("Cpu %d\n", smp_processor_id()); + + /* + * Saved main processor registers + */ + for (i = 0; i < 32; i++) { + if ((i % 4) == 0) + printk("$%2d :", i); + if (i == 0) + printk(" %0*lx", field, 0UL); + else if (i == 26 || i == 27) + printk(" %*s", field, ""); + else + printk(" %0*lx", field, regs->regs[i]); + + i++; + if ((i % 4) == 0) + printk("\n"); } + + printk("Hi : %0*lx\n", field, regs->hi); + printk("Lo : %0*lx\n", field, regs->lo); + + /* + * Saved cp0 registers + */ + printk("epc : %0*lx %s\n", field, regs->cp0_epc, print_tainted()); + printk("Status: %0*lx\n", field, regs->cp0_status); + printk("Cause : %0*lx\n", field, regs->cp0_cause); + + if (regs->cp0_status & ST0_KX) + printk("KX "); + if (regs->cp0_status & ST0_SX) + printk("SX "); + if (regs->cp0_status & ST0_UX) + printk("UX "); + switch (regs->cp0_status & ST0_KSU) { + case KSU_USER: + printk("USER "); + break; + case KSU_SUPERVISOR: + printk("SUPERVISOR "); + break; + case KSU_KERNEL: + printk("KERNEL "); + break; + default: + printk("BAD_MODE "); + break; + } + if (regs->cp0_status & ST0_ERL) + printk("ERL "); + if (regs->cp0_status & ST0_EXL) + printk("EXL "); + if (regs->cp0_status & ST0_IE) + printk("IE "); +} + +void show_registers(struct pt_regs *regs) +{ + const int field = 2 * sizeof(unsigned long); + + show_regs(regs); + printk("Process %s (pid: %d, stackpage=%0*lx)\n", + current->comm, current->pid, field, (unsigned long) current); + show_stack(current, (long *) regs->regs[29]); + show_trace(current, (long *) regs->regs[29]); + show_code((unsigned int *) regs->cp0_epc); + printk("\n"); } -spinlock_t die_lock; +static spinlock_t die_lock = SPIN_LOCK_UNLOCKED; -extern void __die(const char * str, struct pt_regs * regs, const char *where, - unsigned long line) +void __die(const char * str, struct pt_regs * regs, const char * file, + const char * func, unsigned long line) { static int die_counter; + console_verbose(); spin_lock_irq(&die_lock); printk("%s", str); - if (where) - printk(" in %s, line %ld", where, line); + if (file && func) + printk(" in %s:%s, line %ld", file, func, line); printk("[#%d]:\n", ++die_counter); - show_regs(regs); - printk("Process %s (pid: %d, stackpage=%08lx)\n", - current->comm, current->pid, (unsigned long) current); - show_stack((unsigned int *) regs->regs[29]); - show_trace((unsigned int *) regs->regs[29]); - show_code((unsigned int *) regs->cp0_epc); - printk("\n"); + show_registers(regs); spin_unlock_irq(&die_lock); do_exit(SIGSEGV); } -void __die_if_kernel(const char * str, struct pt_regs * regs, const char *where, - unsigned long line) +void __die_if_kernel(const char * str, struct pt_regs * regs, + const char * file, const char * func, unsigned long line) { if (!user_mode(regs)) - __die(str, regs, where, line); + __die(str, regs, file, func, line); } extern const struct exception_table_entry __start___dbe_table[]; @@ -227,106 +266,199 @@ ); } -static inline unsigned long -search_one_table(const struct exception_table_entry *first, - const struct exception_table_entry *last, - unsigned long value) -{ - const struct exception_table_entry *mid; - long diff; - - while (first < last) { - mid = (last - first) / 2 + first; - diff = mid->insn - value; - if (diff < 0) - first = mid + 1; - else - last = mid; - } - return (first == last && first->insn == value) ? first->nextinsn : 0; -} +asmlinkage void do_be(struct pt_regs *regs) +{ + const int field = 2 * sizeof(unsigned long); + const struct exception_table_entry *fixup = NULL; + int data = regs->cp0_cause & 4; + int action = MIPS_BE_FATAL; -extern spinlock_t modlist_lock; + /* XXX For now. Fixme, this searches the wrong table ... */ + if (data && !user_mode(regs)) + fixup = search_exception_tables(regs->cp0_epc); -static inline unsigned long -search_dbe_table(unsigned long addr) -{ - unsigned long ret = 0; - -#ifndef CONFIG_MODULES - /* There is only the kernel to search. */ - ret = search_one_table(__start___dbe_table, __stop___dbe_table-1, addr); - return ret; -#else - unsigned long flags; - - /* The kernel is the last "module" -- no need to treat it special. */ - struct module *mp; - struct archdata *ap; - - spin_lock_irqsave(&modlist_lock, flags); - for (mp = module_list; mp != NULL; mp = mp->next) { - if (!mod_member_present(mp, archdata_end) || - !mod_archdata_member_present(mp, struct archdata, - dbe_table_end)) - continue; - ap = (struct archdata *)(mp->archdata_start); - - if (ap->dbe_table_start == NULL || - !(mp->flags & (MOD_RUNNING | MOD_INITIALIZING))) - continue; - ret = search_one_table(ap->dbe_table_start, - ap->dbe_table_end - 1, addr); - if (ret) - break; - } - spin_unlock_irqrestore(&modlist_lock, flags); - return ret; -#endif -} + if (fixup) + action = MIPS_BE_FIXUP; -static void default_be_board_handler(struct pt_regs *regs) -{ - unsigned long new_epc; - unsigned long fixup; - int data = regs->cp0_cause & 4; + if (board_be_handler) + action = board_be_handler(regs, fixup != 0); - if (data && !user_mode(regs)) { - fixup = search_dbe_table(regs->cp0_epc); + switch (action) { + case MIPS_BE_DISCARD: + return; + case MIPS_BE_FIXUP: if (fixup) { - new_epc = fixup_exception(dpf_reg, fixup, - regs->cp0_epc); - regs->cp0_epc = new_epc; + regs->cp0_epc = fixup->nextinsn; return; } + break; + default: + break; } /* * Assume it would be too dangerous to continue ... */ - printk(KERN_ALERT "%s bus error, epc == %08lx, ra == %08lx\n", + printk(KERN_ALERT "%s bus error, epc == %0*lx, ra == %0*lx\n", data ? "Data" : "Instruction", - regs->cp0_epc, regs->regs[31]); + field, regs->cp0_epc, field, regs->regs[31]); die_if_kernel("Oops", regs); force_sig(SIGBUS, current); } -asmlinkage void do_ibe(struct pt_regs *regs) +static inline int get_insn_opcode(struct pt_regs *regs, unsigned int *opcode) +{ + unsigned int *epc; + + epc = (unsigned int *) regs->cp0_epc + + ((regs->cp0_cause & CAUSEF_BD) != 0); + if (!get_user(*opcode, epc)) + return 0; + + force_sig(SIGSEGV, current); + return 1; +} + +/* + * ll/sc emulation + */ + +#define OPCODE 0xfc000000 +#define BASE 0x03e00000 +#define RT 0x001f0000 +#define OFFSET 0x0000ffff +#define LL 0xc0000000 +#define SC 0xe0000000 + +/* + * The ll_bit is cleared by r*_switch.S + */ + +unsigned long ll_bit; + +static struct task_struct *ll_task = NULL; + +static inline void simulate_ll(struct pt_regs *regs, unsigned int opcode) +{ + unsigned long value, *vaddr; + long offset; + int signal = 0; + + /* + * analyse the ll instruction that just caused a ri exception + * and put the referenced address to addr. + */ + + /* sign extend offset */ + offset = opcode & OFFSET; + offset <<= 16; + offset >>= 16; + + vaddr = (unsigned long *)((long)(regs->regs[(opcode & BASE) >> 21]) + offset); + + if ((unsigned long)vaddr & 3) { + signal = SIGBUS; + goto sig; + } + if (get_user(value, vaddr)) { + signal = SIGSEGV; + goto sig; + } + + if (ll_task == NULL || ll_task == current) { + ll_bit = 1; + } else { + ll_bit = 0; + } + ll_task = current; + + regs->regs[(opcode & RT) >> 16] = value; + + compute_return_epc(regs); + return; + +sig: + force_sig(signal, current); +} + +static inline void simulate_sc(struct pt_regs *regs, unsigned int opcode) { - ibe_board_handler(regs); + unsigned long *vaddr, reg; + long offset; + int signal = 0; + + /* + * analyse the sc instruction that just caused a ri exception + * and put the referenced address to addr. + */ + + /* sign extend offset */ + offset = opcode & OFFSET; + offset <<= 16; + offset >>= 16; + + vaddr = (unsigned long *)((long)(regs->regs[(opcode & BASE) >> 21]) + offset); + reg = (opcode & RT) >> 16; + + if ((unsigned long)vaddr & 3) { + signal = SIGBUS; + goto sig; + } + if (ll_bit == 0 || ll_task != current) { + regs->regs[reg] = 0; + compute_return_epc(regs); + return; + } + + if (put_user(regs->regs[reg], vaddr)) { + signal = SIGSEGV; + goto sig; + } + + regs->regs[reg] = 1; + + compute_return_epc(regs); + return; + +sig: + force_sig(signal, current); } -asmlinkage void do_dbe(struct pt_regs *regs) +/* + * ll uses the opcode of lwc0 and sc uses the opcode of swc0. That is both + * opcodes are supposed to result in coprocessor unusable exceptions if + * executed on ll/sc-less processors. That's the theory. In practice a + * few processors such as NEC's VR4100 throw reserved instruction exceptions + * instead, so we're doing the emulation thing in both exception handlers. + */ +static inline int simulate_llsc(struct pt_regs *regs) { - dbe_board_handler(regs); + unsigned int opcode; + + if (unlikely(get_insn_opcode(regs, &opcode))) + return -EFAULT; + + if ((opcode & OPCODE) == LL) { + simulate_ll(regs, opcode); + return 0; + } + if ((opcode & OPCODE) == SC) { + simulate_sc(regs, opcode); + return 0; + } + + return -EFAULT; /* Strange things going on ... */ } asmlinkage void do_ov(struct pt_regs *regs) { - if (compute_return_epc(regs)) - return; + siginfo_t info; - force_sig(SIGFPE, current); + info.si_code = FPE_INTOVF; + info.si_signo = SIGFPE; + info.si_errno = 0; + info.si_addr = (void *)regs->cp0_epc; + force_sig_info(SIGFPE, &info, current); } /* @@ -335,30 +467,29 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) { if (fcr31 & FPU_CSR_UNI_X) { - extern void save_fp(struct task_struct *); - extern void restore_fp(struct task_struct *); int sig; + /* - * Unimplemented operation exception. If we've got the - * full software emulator on-board, let's use it... + * Unimplemented operation exception. If we've got the full + * software emulator on-board, let's use it... * - * Force FPU to dump state into task/thread context. - * We're moving a lot of data here for what is probably - * a single instruction, but the alternative is to - * pre-decode the FP register operands before invoking - * the emulator, which seems a bit extreme for what - * should be an infrequent event. + * Force FPU to dump state into task/thread context. We're + * moving a lot of data here for what is probably a single + * instruction, but the alternative is to pre-decode the FP + * register operands before invoking the emulator, which seems + * a bit extreme for what should be an infrequent event. */ save_fp(current); - + /* Run the emulator */ - sig = fpu_emulator_cop1Handler(regs); + sig = fpu_emulator_cop1Handler (0, regs, + ¤t->thread.fpu.soft); - /* - * We can't allow the emulated instruction to leave the - * Unimplemented Operation bit set in $fcr31. + /* + * We can't allow the emulated instruction to leave any of + * the cause bit set in $fcr31. */ - current->thread.fpu.soft.sr &= ~FPU_CSR_UNI_X; + current->thread.fpu.soft.sr &= ~FPU_CSR_ALL_X; /* Restore the hardware register state */ restore_fp(current); @@ -370,36 +501,18 @@ return; } - if (compute_return_epc(regs)) - return; - force_sig(SIGFPE, current); - printk(KERN_DEBUG "Sent send SIGFPE to %s\n", current->comm); -} - -static inline int get_insn_opcode(struct pt_regs *regs, unsigned int *opcode) -{ - unsigned int *epc; - - epc = (unsigned int *) regs->cp0_epc + - ((regs->cp0_cause & CAUSEF_BD) != 0); - if (!get_user(*opcode, epc)) - return 0; - - force_sig(SIGSEGV, current); - return 1; } asmlinkage void do_bp(struct pt_regs *regs) { - siginfo_t info; unsigned int opcode, bcode; - unsigned int *epc; + siginfo_t info; - epc = (unsigned int *) regs->cp0_epc + - ((regs->cp0_cause & CAUSEF_BD) != 0); - if (get_user(opcode, epc)) - goto sigsegv; + die_if_kernel("Break instruction in kernel code", regs); + + if (get_insn_opcode(regs, &opcode)) + return; /* * There is the ancient bug in the MIPS assemblers that the break @@ -423,241 +536,107 @@ info.si_code = FPE_INTOVF; info.si_signo = SIGFPE; info.si_errno = 0; - info.si_addr = (void *)compute_return_epc(regs); + info.si_addr = (void *)regs->cp0_epc; force_sig_info(SIGFPE, &info, current); break; default: force_sig(SIGTRAP, current); } - return; - -sigsegv: - force_sig(SIGSEGV, current); } asmlinkage void do_tr(struct pt_regs *regs) { + unsigned int opcode, tcode = 0; siginfo_t info; - unsigned int opcode, bcode; - unsigned *epc; - epc = (unsigned int *) regs->cp0_epc + - ((regs->cp0_cause & CAUSEF_BD) != 0); - if (get_user(opcode, epc)) - goto sigsegv; + die_if_kernel("Trap instruction in kernel code", regs); + + if (get_insn_opcode(regs, &opcode)) + return; - bcode = ((opcode >> 6) & ((1 << 20) - 1)); + /* Immediate versions don't provide a code. */ + if (!(opcode & OPCODE)) + tcode = ((opcode >> 6) & ((1 << 20) - 1)); /* - * (A short test says that IRIX 5.3 sends SIGTRAP for all break - * insns, even for break codes that indicate arithmetic failures. + * (A short test says that IRIX 5.3 sends SIGTRAP for all trap + * insns, even for trap codes that indicate arithmetic failures. * Weird ...) * But should we continue the brokenness??? --macro */ - switch (bcode) { + switch (tcode) { case 6: case 7: - if (bcode == 7) + if (tcode == 7) info.si_code = FPE_INTDIV; else info.si_code = FPE_INTOVF; info.si_signo = SIGFPE; info.si_errno = 0; - info.si_addr = (void *)compute_return_epc(regs); + info.si_addr = (void *)regs->cp0_epc; force_sig_info(SIGFPE, &info, current); break; default: force_sig(SIGTRAP, current); } - return; - -sigsegv: - force_sig(SIGSEGV, current); } -#ifndef CONFIG_CPU_HAS_LLSC - -#ifdef CONFIG_SMP -#error "ll/sc emulation is not SMP safe" -#endif - -/* - * userland emulation for R2300 CPUs - * needed for the multithreading part of glibc - * - * this implementation can handle only sychronization between 2 or more - * user contexts and is not SMP safe. - */ asmlinkage void do_ri(struct pt_regs *regs) { - unsigned int opcode; - - if (!user_mode(regs)) - BUG(); + die_if_kernel("Reserved instruction in kernel code", regs); - if (!get_insn_opcode(regs, &opcode)) { - if ((opcode & OPCODE) == LL) { - simulate_ll(regs, opcode); + if (!cpu_has_llsc) + if (!simulate_llsc(regs)) return; - } - if ((opcode & OPCODE) == SC) { - simulate_sc(regs, opcode); - return; - } - } - if (compute_return_epc(regs)) - return; force_sig(SIGILL, current); } -/* - * The ll_bit is cleared by r*_switch.S - */ - -unsigned long ll_bit; -#ifdef CONFIG_PROC_FS -extern unsigned long ll_ops; -extern unsigned long sc_ops; -#endif - -static struct task_struct *ll_task = NULL; - -void simulate_ll(struct pt_regs *regp, unsigned int opcode) +asmlinkage void do_cpu(struct pt_regs *regs) { - unsigned long value, *vaddr; - long offset; - int signal = 0; + unsigned int cpid; - /* - * analyse the ll instruction that just caused a ri exception - * and put the referenced address to addr. - */ + die_if_kernel("do_cpu invoked from kernel context!", regs); - /* sign extend offset */ - offset = opcode & OFFSET; - offset <<= 16; - offset >>= 16; + cpid = (regs->cp0_cause >> CAUSEB_CE) & 3; - vaddr = (unsigned long *)((long)(regp->regs[(opcode & BASE) >> 21]) + offset); + switch (cpid) { + case 0: + if (cpu_has_llsc) + break; -#ifdef CONFIG_PROC_FS - ll_ops++; -#endif + if (!simulate_llsc(regs)) + return; + break; - if ((unsigned long)vaddr & 3) - signal = SIGBUS; - else if (get_user(value, vaddr)) - signal = SIGSEGV; - else { - if (ll_task == NULL || ll_task == current) { - ll_bit = 1; - } else { - ll_bit = 0; + case 1: + own_fpu(); + if (current->used_math) { /* Using the FPU again. */ + restore_fp(current); + } else { /* First time FPU user. */ + init_fpu(); + current->used_math = 1; } - ll_task = current; - regp->regs[(opcode & RT) >> 16] = value; - } - if (compute_return_epc(regp)) - return; - if (signal) - send_sig(signal, current, 1); -} - -void simulate_sc(struct pt_regs *regp, unsigned int opcode) -{ - unsigned long *vaddr, reg; - long offset; - int signal = 0; - - /* - * analyse the sc instruction that just caused a ri exception - * and put the referenced address to addr. - */ - - /* sign extend offset */ - offset = opcode & OFFSET; - offset <<= 16; - offset >>= 16; - - vaddr = (unsigned long *)((long)(regp->regs[(opcode & BASE) >> 21]) + offset); - reg = (opcode & RT) >> 16; -#ifdef CONFIG_PROC_FS - sc_ops++; -#endif + if (!cpu_has_fpu) { + int sig = fpu_emulator_cop1Handler(0, regs, + ¤t->thread.fpu.soft); + if (sig) + force_sig(sig, current); + } - if ((unsigned long)vaddr & 3) - signal = SIGBUS; - else if (ll_bit == 0 || ll_task != current) - regp->regs[reg] = 0; - else if (put_user(regp->regs[reg], vaddr)) - signal = SIGSEGV; - else - regp->regs[reg] = 1; - if (compute_return_epc(regp)) return; - if (signal) - send_sig(signal, current, 1); -} - -#else /* MIPS 2 or higher */ -asmlinkage void do_ri(struct pt_regs *regs) -{ - unsigned int opcode; - - get_insn_opcode(regs, &opcode); - if (compute_return_epc(regs)) - return; + case 2: + case 3: + break; + } force_sig(SIGILL, current); } -#endif - -asmlinkage void do_cpu(struct pt_regs *regs) +asmlinkage void do_mdmx(struct pt_regs *regs) { - unsigned int cpid; - extern void lazy_fpu_switch(void *); - extern void init_fpu(void); - void fpu_emulator_init_fpu(void); - int sig; - - cpid = (regs->cp0_cause >> CAUSEB_CE) & 3; - if (cpid != 1) - goto bad_cid; - - if (!(mips_cpu.options & MIPS_CPU_FPU)) - goto fp_emul; - - regs->cp0_status |= ST0_CU1; - if (last_task_used_math == current) - return; - - if (current->used_math) { /* Using the FPU again. */ - lazy_fpu_switch(last_task_used_math); - } else { /* First time FPU user. */ - init_fpu(); - current->used_math = 1; - } - last_task_used_math = current; - return; - -fp_emul: - if (last_task_used_math != current) { - if (!current->used_math) { - fpu_emulator_init_fpu(); - current->used_math = 1; - } - } - sig = fpu_emulator_cop1Handler(regs); - last_task_used_math = current; - if (sig) - force_sig(sig, current); - return; - -bad_cid: force_sig(SIGILL, current); } @@ -667,6 +646,7 @@ * We use the watch exception where available to detect stack * overflows. */ + dump_tlb_all(); show_regs(regs); panic("Caught WATCH exception - probably caused by stack overflow."); } @@ -674,8 +654,14 @@ asmlinkage void do_mcheck(struct pt_regs *regs) { show_regs(regs); - panic("Caught Machine Check exception - probably caused by multiple " - "matching entries in the TLB."); + dump_tlb_all(); + /* + * Some chips may have other causes of machine check (e.g. SB1 + * graduation timer) + */ + panic("Caught Machine Check exception - %scaused by multiple " + "matching entries in the TLB.", + (regs->cp0_status & ST0_TS) ? "" : "not "); } asmlinkage void do_reserved(struct pt_regs *regs) @@ -686,15 +672,8 @@ * hard/software error. */ show_regs(regs); - panic("Caught reserved exception - should not happen."); -} - -static inline void watch_init(void) -{ - if (mips_cpu.options & MIPS_CPU_WATCH ) { - set_except_vector(23, handle_watch); - watch_available = 1; - } + panic("Caught reserved exception %ld - should not happen.", + (regs->cp0_cause & 0x7f) >> 2); } /* @@ -703,14 +682,12 @@ */ static inline void parity_protection_init(void) { - switch (mips_cpu.cputype) { + switch (current_cpu_data.cputype) { case CPU_5KC: - /* Set the PE bit (bit 31) in the CP0_ECC register. */ + /* Set the PE bit (bit 31) in the c0_ecc register. */ printk(KERN_INFO "Enable the cache parity protection for " "MIPS 5KC CPUs.\n"); - write_32bit_cp0_register(CP0_ECC, - read_32bit_cp0_register(CP0_ECC) - | 0x80000000); + write_c0_ecc(read_c0_ecc() | 0x80000000); break; default: break; @@ -719,16 +696,16 @@ asmlinkage void cache_parity_error(void) { + const int field = 2 * sizeof(unsigned long); unsigned int reg_val; /* For the moment, report the problem and hang. */ - reg_val = read_32bit_cp0_register(CP0_ERROREPC); printk("Cache error exception:\n"); - printk("cp0_errorepc == %08x\n", reg_val); - reg_val = read_32bit_cp0_register(CP0_CACHEERR); - printk("cp0_cacheerr == %08x\n", reg_val); + printk("cp0_errorepc == %0*lx\n", field, read_c0_errorepc()); + reg_val = read_c0_cacheerr(); + printk("c0_cacheerr == %08x\n", reg_val); - printk("Decoded CP0_CACHEERR: %s cache fault in %s reference.\n", + printk("Decoded c0_cacheerr: %s cache fault in %s reference.\n", reg_val & (1<<30) ? "secondary" : "primary", reg_val & (1<<31) ? "data" : "insn"); printk("Error bits: %s%s%s%s%s%s%s\n", @@ -741,17 +718,63 @@ reg_val & (1<<22) ? "E0 " : ""); printk("IDX: 0x%08x\n", reg_val & ((1<<22)-1)); - if (reg_val&(1<<22)) - printk("DErrAddr0: 0x%08x\n", - read_32bit_cp0_set1_register(CP0_S1_DERRADDR0)); - - if (reg_val&(1<<23)) - printk("DErrAddr1: 0x%08x\n", - read_32bit_cp0_set1_register(CP0_S1_DERRADDR1)); +#if defined(CONFIG_CPU_MIPS32) || defined (CONFIG_CPU_MIPS64) + if (reg_val & (1<<22)) + printk("DErrAddr0: 0x%08x\n", read_c0_derraddr0()); + + if (reg_val & (1<<23)) + printk("DErrAddr1: 0x%08x\n", read_c0_derraddr1()); +#endif panic("Can't handle the cache error!"); } +/* + * SDBBP EJTAG debug exception handler. + * We skip the instruction and return to the next instruction. + */ +void ejtag_exception_handler(struct pt_regs *regs) +{ + const int field = 2 * sizeof(unsigned long); + unsigned long depc, old_epc; + unsigned int debug; + + printk("SDBBP EJTAG debug exception - not handled yet, just ignored!\n"); + depc = read_c0_depc(); + debug = read_c0_debug(); + printk("c0_depc = %0*lx, DEBUG = %08x\n", field, depc, debug); + if (debug & 0x80000000) { + /* + * In branch delay slot. + * We cheat a little bit here and use EPC to calculate the + * debug return address (DEPC). EPC is restored after the + * calculation. + */ + old_epc = regs->cp0_epc; + regs->cp0_epc = depc; + __compute_return_epc(regs); + depc = regs->cp0_epc; + regs->cp0_epc = old_epc; + } else + depc += 4; + write_c0_depc(depc); + +#if 0 + printk("\n\n----- Enable EJTAG single stepping ----\n\n"); + write_c0_debug(debug | 0x100); +#endif +} + +/* + * NMI exception handler. + */ +void nmi_exception_handler(struct pt_regs *regs) +{ + printk("NMI taken!!!!\n"); + die("NMI", regs); + while(1) ; +} + unsigned long exception_handlers[32]; /* @@ -761,11 +784,11 @@ */ void *set_except_vector(int n, void *addr) { - unsigned handler = (unsigned long) addr; - unsigned old_handler = exception_handlers[n]; - exception_handlers[n] = handler; + unsigned long handler = (unsigned long) addr; + unsigned long old_handler = exception_handlers[n]; - if (n == 0 && mips_cpu.options & MIPS_CPU_DIVEC) { + exception_handlers[n] = handler; + if (n == 0 && cpu_has_divec) { *(volatile u32 *)(KSEG0+0x200) = 0x08000000 | (0x03ffffff & (handler >> 2)); flush_icache_range(KSEG0+0x200, KSEG0 + 0x204); @@ -775,56 +798,70 @@ asmlinkage int (*save_fp_context)(struct sigcontext *sc); asmlinkage int (*restore_fp_context)(struct sigcontext *sc); + extern asmlinkage int _save_fp_context(struct sigcontext *sc); extern asmlinkage int _restore_fp_context(struct sigcontext *sc); extern asmlinkage int fpu_emulator_save_context(struct sigcontext *sc); extern asmlinkage int fpu_emulator_restore_context(struct sigcontext *sc); +void __init per_cpu_trap_init(void) +{ + unsigned int cpu = smp_processor_id(); + + /* Some firmware leaves the BEV flag set, clear it. */ + clear_c0_status(ST0_CU1|ST0_CU2|ST0_CU3|ST0_BEV); + + /* + * Some MIPS CPUs have a dedicated interrupt vector which reduces the + * interrupt processing overhead. Use it where available. + */ + if (cpu_has_divec) + set_c0_cause(CAUSEF_IV); + + cpu_data[cpu].asid_cache = ASID_FIRST_VERSION; + write_c0_context(cpu << 23); +} + void __init trap_init(void) { - extern char except_vec0_nevada, except_vec0_r4000; - extern char except_vec0_r4600, except_vec0_r2300; - extern char except_vec1_generic, except_vec2_generic; + extern char except_vec1_generic; extern char except_vec3_generic, except_vec3_r4000; - extern char except_vec4; extern char except_vec_ejtag_debug; + extern char except_vec4; unsigned long i; - /* Some firmware leaves the BEV flag set, clear it. */ - clear_cp0_status(ST0_BEV); + per_cpu_trap_init(); /* Copy the generic exception handler code to its final destination. */ memcpy((void *)(KSEG0 + 0x80), &except_vec1_generic, 0x80); - memcpy((void *)(KSEG0 + 0x100), &except_vec2_generic, 0x80); - memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, 0x80); - flush_icache_range(KSEG0 + 0x80, KSEG0 + 0x200); + /* * Setup default vectors */ for (i = 0; i <= 31; i++) set_except_vector(i, handle_reserved); - /* - * Copy the EJTAG debug exception vector handler code to its final + /* + * Copy the EJTAG debug exception vector handler code to it's final * destination. */ - memcpy((void *)(KSEG0 + 0x300), &except_vec_ejtag_debug, 0x80); + if (cpu_has_ejtag) + memcpy((void *)(KSEG0 + 0x300), &except_vec_ejtag_debug, 0x80); /* * Only some CPUs have the watch exceptions or a dedicated * interrupt vector. */ - watch_init(); + if (cpu_has_watch) + set_except_vector(23, handle_watch); /* * Some MIPS CPUs have a dedicated interrupt vector which reduces the * interrupt processing overhead. Use it where available. */ - if (mips_cpu.options & MIPS_CPU_DIVEC) { - memcpy((void *)(KSEG0 + 0x200), &except_vec4, 8); - set_cp0_cause(CAUSEF_IV); - } + if (cpu_has_divec) + memcpy((void *)(KSEG0 + 0x200), &except_vec4, 0x8); /* * Some CPUs can enable/disable for cache parity detection, but does @@ -832,21 +869,22 @@ */ parity_protection_init(); + /* + * The Data Bus Errors / Instruction Bus Errors are signaled + * by external hardware. Therefore these two exceptions + * may have board specific handlers. + */ + if (board_be_init) + board_be_init(); + set_except_vector(1, handle_mod); set_except_vector(2, handle_tlbl); set_except_vector(3, handle_tlbs); set_except_vector(4, handle_adel); set_except_vector(5, handle_ades); - /* - * The Data Bus Error/ Instruction Bus Errors are signaled - * by external hardware. Therefore these two expection have - * board specific handlers. - */ set_except_vector(6, handle_ibe); set_except_vector(7, handle_dbe); - ibe_board_handler = default_be_board_handler; - dbe_board_handler = default_be_board_handler; set_except_vector(8, handle_sys); set_except_vector(9, handle_bp); @@ -854,59 +892,23 @@ set_except_vector(11, handle_cpu); set_except_vector(12, handle_ov); set_except_vector(13, handle_tr); + set_except_vector(22, handle_mdmx); - if (mips_cpu.options & MIPS_CPU_FPU) + if (cpu_has_fpu && !cpu_has_nofpuex) set_except_vector(15, handle_fpe); - /* - * Handling the following exceptions depends mostly of the cpu type - */ - if ((mips_cpu.options & MIPS_CPU_4KEX) - && (mips_cpu.options & MIPS_CPU_4KTLB)) { - if (mips_cpu.cputype == CPU_NEVADA) { - memcpy((void *)KSEG0, &except_vec0_nevada, 0x80); - } else if (mips_cpu.cputype == CPU_R4600) - memcpy((void *)KSEG0, &except_vec0_r4600, 0x80); - else - memcpy((void *)KSEG0, &except_vec0_r4000, 0x80); - - /* Cache error vector already set above. */ - - if (mips_cpu.options & MIPS_CPU_VCE) { - memcpy((void *)(KSEG0 + 0x180), &except_vec3_r4000, - 0x80); - } else { - memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, - 0x80); - } + if (cpu_has_mcheck) + set_except_vector(24, handle_mcheck); - if (mips_cpu.options & MIPS_CPU_FPU) { - save_fp_context = _save_fp_context; - restore_fp_context = _restore_fp_context; - } else { - save_fp_context = fpu_emulator_save_context; - restore_fp_context = fpu_emulator_restore_context; - } - } else switch (mips_cpu.cputype) { - case CPU_SB1: - /* - * XXX - This should be folded in to the "cleaner" handling, - * above - */ - memcpy((void *)KSEG0, &except_vec0_r4000, 0x80); + if (cpu_has_vce) memcpy((void *)(KSEG0 + 0x180), &except_vec3_r4000, 0x80); - save_fp_context = _save_fp_context; - restore_fp_context = _restore_fp_context; + else if (cpu_has_4kex) + memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, 0x80); + else + memcpy((void *)(KSEG0 + 0x080), &except_vec3_generic, 0x80); - /* Enable timer interrupt and scd mapped interrupt */ - clear_cp0_status(0xf000); - set_cp0_status(0xc00); - break; - case CPU_R6000: - case CPU_R6000A: - save_fp_context = _save_fp_context; - restore_fp_context = _restore_fp_context; - + if (current_cpu_data.cputype == CPU_R6000 || + current_cpu_data.cputype == CPU_R6000A) { /* * The R6000 is the only R-series CPU that features a machine * check exception (similar to the R4000 cache error) and @@ -917,34 +919,24 @@ */ //set_except_vector(14, handle_mc); //set_except_vector(15, handle_ndc); - case CPU_R2000: - case CPU_R3000: - case CPU_R3000A: - case CPU_R3041: - case CPU_R3051: - case CPU_R3052: - case CPU_R3081: - case CPU_R3081E: - case CPU_TX3912: - case CPU_TX3922: - case CPU_TX3927: + } + + if (cpu_has_fpu) { save_fp_context = _save_fp_context; restore_fp_context = _restore_fp_context; - memcpy((void *)KSEG0, &except_vec0_r2300, 0x80); - memcpy((void *)(KSEG0 + 0x80), &except_vec3_generic, 0x80); - break; - - case CPU_UNKNOWN: - default: - panic("Unknown CPU type"); + } else { + save_fp_context = fpu_emulator_save_context; + restore_fp_context = fpu_emulator_restore_context; } - flush_icache_range(KSEG0, KSEG0 + 0x200); - if (mips_cpu.isa_level == MIPS_CPU_ISA_IV) - set_cp0_status(ST0_XX); + flush_icache_range(KSEG0, KSEG0 + 0x400); + + if (current_cpu_data.isa_level == MIPS_CPU_ISA_IV) + set_c0_status(ST0_XX); - atomic_inc(&init_mm.mm_count); /* XXX UP? */ + atomic_inc(&init_mm.mm_count); /* XXX UP? */ current->active_mm = &init_mm; - write_32bit_cp0_register(CP0_CONTEXT, smp_processor_id()<<23); - current_pgd[0] = init_mm.pgd; + + /* XXX Must be done for all CPUs */ + TLBMISS_HANDLER_SETUP(); } diff -Nru a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c --- a/arch/mips/kernel/unaligned.c Tue Jul 1 18:44:35 2003 +++ b/arch/mips/kernel/unaligned.c Tue Jul 1 18:44:35 2003 @@ -5,7 +5,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1996, 1998 by Ralf Baechle + * Copyright (C) 1996, 1998, 1999, 2002 by Ralf Baechle * Copyright (C) 1999 Silicon Graphics, Inc. * * This file contains exception handler for address error exception with the @@ -41,7 +41,7 @@ * * #include * #include - * + * * struct foo { * unsigned char bar[8]; * }; @@ -74,6 +74,7 @@ */ #include #include +#include #include #include #include @@ -88,23 +89,22 @@ #define STR(x) __STR(x) #define __STR(x) #x -/* - * User code may only access USEG; kernel code may access the - * entire address space. - */ -#define check_axs(pc,a,s) \ - if ((long)(~(pc) & ((a) | ((a)+(s)))) < 0) \ - goto sigbus; +#ifdef CONFIG_PROC_FS +unsigned long unaligned_instructions; +#endif -static inline void -emulate_load_store_insn(struct pt_regs *regs, - unsigned long addr, - unsigned long pc) +static inline int emulate_load_store_insn(struct pt_regs *regs, + void *addr, unsigned long pc, + unsigned long **regptr, unsigned long *newvalue) { union mips_instruction insn; - unsigned long value, fixup; + unsigned long value; + const struct exception_table_entry *fixup; + unsigned int res; regs->regs[0] = 0; + *regptr=NULL; + /* * This load never faults. */ @@ -144,186 +144,295 @@ * The remaining opcodes are the ones that are really of interest. */ case lh_op: - check_axs(pc, addr, 2); - __asm__( - ".set\tnoat\n" + if (verify_area(VERIFY_READ, addr, 2)) + goto sigbus; + + __asm__ __volatile__ (".set\tnoat\n" #ifdef __BIG_ENDIAN - "1:\tlb\t%0,0(%1)\n" - "2:\tlbu\t$1,1(%1)\n\t" + "1:\tlb\t%0, 0(%2)\n" + "2:\tlbu\t$1, 1(%2)\n\t" #endif #ifdef __LITTLE_ENDIAN - "1:\tlb\t%0,1(%1)\n" - "2:\tlbu\t$1,0(%1)\n\t" + "1:\tlb\t%0, 1(%2)\n" + "2:\tlbu\t$1, 0(%2)\n\t" #endif - "sll\t%0,0x8\n\t" - "or\t%0,$1\n\t" - ".set\tat\n\t" + "sll\t%0, 0x8\n\t" + "or\t%0, $1\n\t" + "li\t%1, 0\n" + "3:\t.set\tat\n\t" + ".section\t.fixup,\"ax\"\n\t" + "4:\tli\t%1, %3\n\t" + "j\t3b\n\t" + ".previous\n\t" ".section\t__ex_table,\"a\"\n\t" - STR(PTR)"\t1b,%2\n\t" - STR(PTR)"\t2b,%2\n\t" + STR(PTR)"\t1b, 4b\n\t" + STR(PTR)"\t2b, 4b\n\t" ".previous" - :"=&r" (value) - :"r" (addr), "i" (&&fault) - :"$1"); - regs->regs[insn.i_format.rt] = value; - return; + : "=&r" (value), "=r" (res) + : "r" (addr), "i" (-EFAULT)); + if (res) + goto fault; + *newvalue = value; + *regptr = ®s->regs[insn.i_format.rt]; + break; case lw_op: - check_axs(pc, addr, 4); - __asm__( + if (verify_area(VERIFY_READ, addr, 4)) + goto sigbus; + + __asm__ __volatile__ ( #ifdef __BIG_ENDIAN - "1:\tlwl\t%0,(%1)\n" - "2:\tlwr\t%0,3(%1)\n\t" + "1:\tlwl\t%0, (%2)\n" + "2:\tlwr\t%0, 3(%2)\n\t" #endif #ifdef __LITTLE_ENDIAN - "1:\tlwl\t%0,3(%1)\n" - "2:\tlwr\t%0,(%1)\n\t" + "1:\tlwl\t%0, 3(%2)\n" + "2:\tlwr\t%0, (%2)\n\t" #endif + "li\t%1, 0\n" + "3:\t.section\t.fixup,\"ax\"\n\t" + "4:\tli\t%1, %3\n\t" + "j\t3b\n\t" + ".previous\n\t" ".section\t__ex_table,\"a\"\n\t" - STR(PTR)"\t1b,%2\n\t" - STR(PTR)"\t2b,%2\n\t" + STR(PTR)"\t1b, 4b\n\t" + STR(PTR)"\t2b, 4b\n\t" ".previous" - :"=&r" (value) - :"r" (addr), "i" (&&fault)); - regs->regs[insn.i_format.rt] = value; - return; + : "=&r" (value), "=r" (res) + : "r" (addr), "i" (-EFAULT)); + if (res) + goto fault; + *newvalue = value; + *regptr = ®s->regs[insn.i_format.rt]; + break; case lhu_op: - check_axs(pc, addr, 2); - __asm__( + if (verify_area(VERIFY_READ, addr, 2)) + goto sigbus; + + __asm__ __volatile__ ( ".set\tnoat\n" #ifdef __BIG_ENDIAN - "1:\tlbu\t%0,0(%1)\n" - "2:\tlbu\t$1,1(%1)\n\t" + "1:\tlbu\t%0, 0(%2)\n" + "2:\tlbu\t$1, 1(%2)\n\t" #endif #ifdef __LITTLE_ENDIAN - "1:\tlbu\t%0,1(%1)\n" - "2:\tlbu\t$1,0(%1)\n\t" + "1:\tlbu\t%0, 1(%2)\n" + "2:\tlbu\t$1, 0(%2)\n\t" #endif - "sll\t%0,0x8\n\t" - "or\t%0,$1\n\t" - ".set\tat\n\t" + "sll\t%0, 0x8\n\t" + "or\t%0, $1\n\t" + "li\t%1, 0\n" + "3:\t.set\tat\n\t" + ".section\t.fixup,\"ax\"\n\t" + "4:\tli\t%1, %3\n\t" + "j\t3b\n\t" + ".previous\n\t" ".section\t__ex_table,\"a\"\n\t" - STR(PTR)"\t1b,%2\n\t" - STR(PTR)"\t2b,%2\n\t" + STR(PTR)"\t1b, 4b\n\t" + STR(PTR)"\t2b, 4b\n\t" ".previous" - :"=&r" (value) - :"r" (addr), "i" (&&fault) - :"$1"); - regs->regs[insn.i_format.rt] = value; - return; + : "=&r" (value), "=r" (res) + : "r" (addr), "i" (-EFAULT)); + if (res) + goto fault; + *newvalue = value; + *regptr = ®s->regs[insn.i_format.rt]; + break; case lwu_op: - check_axs(pc, addr, 4); - __asm__( +#ifdef CONFIG_MIPS64 + /* + * A 32-bit kernel might be running on a 64-bit processor. But + * if we're on a 32-bit processor and an i-cache incoherency + * or race makes us see a 64-bit instruction here the sdl/sdr + * would blow up, so for now we don't handle unaligned 64-bit + * instructions on 32-bit kernels. + */ + if (verify_area(VERIFY_READ, addr, 4)) + goto sigbus; + + __asm__ __volatile__ ( #ifdef __BIG_ENDIAN - "1:\tlwl\t%0,(%1)\n" - "2:\tlwr\t%0,3(%1)\n\t" + "1:\tlwl\t%0, (%2)\n" + "2:\tlwr\t%0, 3(%2)\n\t" #endif #ifdef __LITTLE_ENDIAN - "1:\tlwl\t%0,3(%1)\n" - "2:\tlwr\t%0,(%1)\n\t" + "1:\tlwl\t%0, 3(%2)\n" + "2:\tlwr\t%0, (%2)\n\t" #endif + "dsll\t%0, %0, 32\n\t" + "dsrl\t%0, %0, 32\n\t" + "li\t%1, 0\n" + "3:\t.section\t.fixup,\"ax\"\n\t" + "4:\tli\t%1, %3\n\t" + "j\t3b\n\t" + ".previous\n\t" ".section\t__ex_table,\"a\"\n\t" - STR(PTR)"\t1b,%2\n\t" - STR(PTR)"\t2b,%2\n\t" + STR(PTR)"\t1b, 4b\n\t" + STR(PTR)"\t2b, 4b\n\t" ".previous" - :"=&r" (value) - :"r" (addr), "i" (&&fault)); - value &= 0xffffffff; - regs->regs[insn.i_format.rt] = value; - return; + : "=&r" (value), "=r" (res) + : "r" (addr), "i" (-EFAULT)); + if (res) + goto fault; + *newvalue = value; + *regptr = ®s->regs[insn.i_format.rt]; + break; +#endif /* CONFIG_MIPS64 */ + + /* Cannot handle 64-bit instructions in 32-bit kernel */ + goto sigill; case ld_op: - check_axs(pc, addr, 8); - __asm__( - ".set\tmips3\n" +#ifdef CONFIG_MIPS64 + /* + * A 32-bit kernel might be running on a 64-bit processor. But + * if we're on a 32-bit processor and an i-cache incoherency + * or race makes us see a 64-bit instruction here the sdl/sdr + * would blow up, so for now we don't handle unaligned 64-bit + * instructions on 32-bit kernels. + */ + if (verify_area(VERIFY_READ, addr, 8)) + goto sigbus; + + __asm__ __volatile__ ( #ifdef __BIG_ENDIAN - "1:\tldl\t%0,(%1)\n" - "2:\tldr\t%0,7(%1)\n\t" + "1:\tldl\t%0, (%2)\n" + "2:\tldr\t%0, 7(%2)\n\t" #endif #ifdef __LITTLE_ENDIAN - "1:\tldl\t%0,7(%1)\n" - "2:\tldr\t%0,(%1)\n\t" + "1:\tldl\t%0, 7(%2)\n" + "2:\tldr\t%0, (%2)\n\t" #endif - ".set\tmips0\n\t" + "li\t%1, 0\n" + "3:\t.section\t.fixup,\"ax\"\n\t" + "4:\tli\t%1, %3\n\t" + "j\t3b\n\t" + ".previous\n\t" ".section\t__ex_table,\"a\"\n\t" - STR(PTR)"\t1b,%2\n\t" - STR(PTR)"\t2b,%2\n\t" + STR(PTR)"\t1b, 4b\n\t" + STR(PTR)"\t2b, 4b\n\t" ".previous" - :"=&r" (value) - :"r" (addr), "i" (&&fault)); - regs->regs[insn.i_format.rt] = value; - return; + : "=&r" (value), "=r" (res) + : "r" (addr), "i" (-EFAULT)); + if (res) + goto fault; + *newvalue = value; + *regptr = ®s->regs[insn.i_format.rt]; + break; +#endif /* CONFIG_MIPS64 */ + + /* Cannot handle 64-bit instructions in 32-bit kernel */ + goto sigill; case sh_op: - check_axs(pc, addr, 2); + if (verify_area(VERIFY_WRITE, addr, 2)) + goto sigbus; + value = regs->regs[insn.i_format.rt]; - __asm__( + __asm__ __volatile__ ( #ifdef __BIG_ENDIAN ".set\tnoat\n" - "1:\tsb\t%0,1(%1)\n\t" - "srl\t$1,%0,0x8\n" - "2:\tsb\t$1,0(%1)\n\t" + "1:\tsb\t%1, 1(%2)\n\t" + "srl\t$1, %1, 0x8\n" + "2:\tsb\t$1, 0(%2)\n\t" ".set\tat\n\t" #endif #ifdef __LITTLE_ENDIAN ".set\tnoat\n" - "1:\tsb\t%0,0(%1)\n\t" - "srl\t$1,%0,0x8\n" - "2:\tsb\t$1,1(%1)\n\t" + "1:\tsb\t%1, 0(%2)\n\t" + "srl\t$1,%1, 0x8\n" + "2:\tsb\t$1, 1(%2)\n\t" ".set\tat\n\t" #endif + "li\t%0, 0\n" + "3:\n\t" + ".section\t.fixup,\"ax\"\n\t" + "4:\tli\t%0, %3\n\t" + "j\t3b\n\t" + ".previous\n\t" ".section\t__ex_table,\"a\"\n\t" - STR(PTR)"\t1b,%2\n\t" - STR(PTR)"\t2b,%2\n\t" + STR(PTR)"\t1b, 4b\n\t" + STR(PTR)"\t2b, 4b\n\t" ".previous" - : /* no outputs */ - :"r" (value), "r" (addr), "i" (&&fault) - :"$1"); - return; + : "=r" (res) + : "r" (value), "r" (addr), "i" (-EFAULT)); + if (res) + goto fault; + break; case sw_op: - check_axs(pc, addr, 4); + if (verify_area(VERIFY_WRITE, addr, 4)) + goto sigbus; + value = regs->regs[insn.i_format.rt]; - __asm__( + __asm__ __volatile__ ( #ifdef __BIG_ENDIAN - "1:\tswl\t%0,(%1)\n" - "2:\tswr\t%0,3(%1)\n\t" + "1:\tswl\t%1,(%2)\n" + "2:\tswr\t%1, 3(%2)\n\t" #endif #ifdef __LITTLE_ENDIAN - "1:\tswl\t%0,3(%1)\n" - "2:\tswr\t%0,(%1)\n\t" + "1:\tswl\t%1, 3(%2)\n" + "2:\tswr\t%1, (%2)\n\t" #endif + "li\t%0, 0\n" + "3:\n\t" + ".section\t.fixup,\"ax\"\n\t" + "4:\tli\t%0, %3\n\t" + "j\t3b\n\t" + ".previous\n\t" ".section\t__ex_table,\"a\"\n\t" - STR(PTR)"\t1b,%2\n\t" - STR(PTR)"\t2b,%2\n\t" + STR(PTR)"\t1b, 4b\n\t" + STR(PTR)"\t2b, 4b\n\t" ".previous" - : /* no outputs */ - :"r" (value), "r" (addr), "i" (&&fault)); - return; + : "=r" (res) + : "r" (value), "r" (addr), "i" (-EFAULT)); + if (res) + goto fault; + break; case sd_op: - check_axs(pc, addr, 8); +#ifdef CONFIG_MIPS64 + /* + * A 32-bit kernel might be running on a 64-bit processor. But + * if we're on a 32-bit processor and an i-cache incoherency + * or race makes us see a 64-bit instruction here the sdl/sdr + * would blow up, so for now we don't handle unaligned 64-bit + * instructions on 32-bit kernels. + */ + if (verify_area(VERIFY_WRITE, addr, 8)) + goto sigbus; + value = regs->regs[insn.i_format.rt]; - __asm__( - ".set\tmips3\n" + __asm__ __volatile__ ( #ifdef __BIG_ENDIAN - "1:\tsdl\t%0,(%1)\n" - "2:\tsdr\t%0,7(%1)\n\t" + "1:\tsdl\t%1,(%2)\n" + "2:\tsdr\t%1, 7(%2)\n\t" #endif #ifdef __LITTLE_ENDIAN - "1:\tsdl\t%0,7(%1)\n" - "2:\tsdr\t%0,(%1)\n\t" + "1:\tsdl\t%1, 7(%2)\n" + "2:\tsdr\t%1, (%2)\n\t" #endif - ".set\tmips0\n\t" + "li\t%0, 0\n" + "3:\n\t" + ".section\t.fixup,\"ax\"\n\t" + "4:\tli\t%0, %3\n\t" + "j\t3b\n\t" + ".previous\n\t" ".section\t__ex_table,\"a\"\n\t" - STR(PTR)"\t1b,%2\n\t" - STR(PTR)"\t2b,%2\n\t" + STR(PTR)"\t1b, 4b\n\t" + STR(PTR)"\t2b, 4b\n\t" ".previous" - : /* no outputs */ - :"r" (value), "r" (addr), "i" (&&fault)); - return; + : "=r" (res) + : "r" (value), "r" (addr), "i" (-EFAULT)); + if (res) + goto fault; + break; +#endif /* CONFIG_MIPS64 */ + + /* Cannot handle 64-bit instructions in 32-bit kernel */ + goto sigill; case lwc1_op: case ldc1_op: @@ -352,78 +461,97 @@ */ goto sigill; } - return; + +#ifdef CONFIG_PROC_FS + unaligned_instructions++; +#endif + + return 0; fault: /* Did we have an exception handler installed? */ - fixup = search_exception_table(regs->cp0_epc); + fixup = search_exception_tables(exception_epc(regs)); if (fixup) { - long new_epc; - new_epc = fixup_exception(dpf_reg, fixup, regs->cp0_epc); + unsigned long new_epc = fixup->nextinsn; printk(KERN_DEBUG "%s: Forwarding exception at [<%lx>] (%lx)\n", current->comm, regs->cp0_epc, new_epc); regs->cp0_epc = new_epc; - return; + return 1; } die_if_kernel ("Unhandled kernel unaligned access", regs); send_sig(SIGSEGV, current, 1); - return; + + return 0; + sigbus: - die_if_kernel ("Unhandled kernel unaligned access", regs); + die_if_kernel("Unhandled kernel unaligned access", regs); send_sig(SIGBUS, current, 1); - return; + + return 0; + sigill: - die_if_kernel ("Unhandled kernel unaligned access or invalid instruction", regs); + die_if_kernel("Unhandled kernel unaligned access or invalid instruction", regs); send_sig(SIGILL, current, 1); - return; -} -#ifdef CONFIG_PROC_FS -unsigned long unaligned_instructions; -#endif + return 0; +} asmlinkage void do_ade(struct pt_regs *regs) { - unsigned long pc; + unsigned long *regptr, newval; extern int do_dsemulret(struct pt_regs *); + mm_segment_t seg; + unsigned long pc; - /* - * Address errors may be deliberately induced - * by the FPU emulator to take retake control - * of the CPU after executing the instruction - * in the delay slot of an emulated branch. + /* + * Address errors may be deliberately induced by the FPU emulator to + * retake control of the CPU after executing the instruction in the + * delay slot of an emulated branch. */ - - if ((unsigned long)regs->cp0_epc == current->thread.dsemul_aerpc) { - do_dsemulret(regs); + /* Terminate if exception was recognized as a delay slot return */ + if (do_dsemulret(regs)) return; - } + + /* Otherwise handle as normal */ /* * Did we catch a fault trying to load an instruction? - * This also catches attempts to activate MIPS16 code on - * CPUs which don't support it. + * Or are we running in MIPS16 mode? */ - if (regs->cp0_badvaddr == regs->cp0_epc) + if ((regs->cp0_badvaddr == regs->cp0_epc) || (regs->cp0_epc & 0x1)) goto sigbus; - pc = regs->cp0_epc + ((regs->cp0_cause & CAUSEF_BD) ? 4 : 0); - if (compute_return_epc(regs)) - return; + pc = exception_epc(regs); if ((current->thread.mflags & MF_FIXADE) == 0) goto sigbus; - emulate_load_store_insn(regs, regs->cp0_badvaddr, pc); -#ifdef CONFIG_PROC_FS - unaligned_instructions++; -#endif + /* + * Do branch emulation only if we didn't forward the exception. + * This is all so but ugly ... + */ + seg = get_fs(); + if (!user_mode(regs)) + set_fs(KERNEL_DS); + if (!emulate_load_store_insn(regs, (void *)regs->cp0_badvaddr, pc, + ®ptr, &newval)) { + compute_return_epc(regs); + /* + * Now that branch is evaluated, update the dest + * register if necessary + */ + if (regptr) + *regptr = newval; + } + set_fs(seg); return; sigbus: - die_if_kernel ("Kernel unaligned instruction access", regs); + die_if_kernel("Kernel unaligned instruction access", regs); force_sig(SIGBUS, current); - return; + /* + * XXX On return from the signal handler we should advance the epc + */ } diff -Nru a/arch/mips/kernel/vm86.c b/arch/mips/kernel/vm86.c --- a/arch/mips/kernel/vm86.c Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,13 +0,0 @@ -/* - * arch/mips/vm86.c - * - * Copyright (C) 1994 Waldorf GMBH, - * written by Ralf Baechle - */ -#include -#include - -asmlinkage int sys_vm86(void *v86) -{ - return -ENOSYS; -} diff -Nru a/arch/mips/lasat/Makefile b/arch/mips/lasat/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/lasat/Makefile Tue Jul 1 18:44:40 2003 @@ -0,0 +1,14 @@ +# +# Makefile for the LASAT specific kernel interface routines under Linux. +# + +obj-y += reset.o setup.o prom.o lasat_board.o \ + at93c.o interrupt.o lasatIRQ.o + +obj-$(CONFIG_LASAT_SYSCTL) += sysctl.o +obj-$(CONFIG_DS1603) += ds1603.o +obj-$(CONFIG_PICVUE) += picvue.o +obj-$(CONFIG_PICVUE_PROC) += picvue_proc.o + +clean: + make -C image clean diff -Nru a/arch/mips/lasat/at93c.c b/arch/mips/lasat/at93c.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/lasat/at93c.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,148 @@ +/* + * Atmel AT93C46 serial eeprom driver + * + * Brian Murphy + * + */ +#include +#include +#include +#include +#include + +#include "at93c.h" + +#define AT93C_ADDR_SHIFT 7 +#define AT93C_ADDR_MAX ((1 << AT93C_ADDR_SHIFT) - 1) +#define AT93C_RCMD (0x6 << AT93C_ADDR_SHIFT) +#define AT93C_WCMD (0x5 << AT93C_ADDR_SHIFT) +#define AT93C_WENCMD 0x260 +#define AT93C_WDSCMD 0x200 + +struct at93c_defs *at93c; + +static void at93c_reg_write(u32 val) +{ + *at93c->reg = val; +} + +static u32 at93c_reg_read(void) +{ + u32 tmp = *at93c->reg; + return tmp; +} + +static u32 at93c_datareg_read(void) +{ + u32 tmp = *at93c->rdata_reg; + return tmp; +} + +static void at93c_cycle_clk(u32 data) +{ + at93c_reg_write(data | at93c->clk); + ndelay(250); + at93c_reg_write(data & ~at93c->clk); + ndelay(250); +} + +static void at93c_write_databit(u8 bit) +{ + u32 data = at93c_reg_read(); + if (bit) + data |= 1 << at93c->wdata_shift; + else + data &= ~(1 << at93c->wdata_shift); + + at93c_reg_write(data); + ndelay(100); + at93c_cycle_clk(data); +} + +static unsigned int at93c_read_databit(void) +{ + u32 data; + + at93c_cycle_clk(at93c_reg_read()); + data = (at93c_datareg_read() >> at93c->rdata_shift) & 1; + return data; +} + +static u8 at93c_read_byte(void) +{ + int i; + u8 data = 0; + + for (i = 0; i<=7; i++) { + data <<= 1; + data |= at93c_read_databit(); + } + return data; +} + +static void at93c_write_bits(u32 data, int size) +{ + int i; + int shift = size - 1; + u32 mask = (1 << shift); + + for (i = 0; i < size; i++) { + at93c_write_databit((data & mask) >> shift); + data <<= 1; + } +} + +static void at93c_init_op(void) +{ + at93c_reg_write((at93c_reg_read() | at93c->cs) & ~at93c->clk & ~(1 << at93c->rdata_shift)); + ndelay(50); +} + +static void at93c_end_op(void) +{ + at93c_reg_write(at93c_reg_read() & ~at93c->cs); + ndelay(250); +} + +static void at93c_wait(void) +{ + at93c_init_op(); + while (!at93c_read_databit()) + ; + at93c_end_op(); +}; + +static void at93c_disable_wp(void) +{ + at93c_init_op(); + at93c_write_bits(AT93C_WENCMD, 10); + at93c_end_op(); +} + +static void at93c_enable_wp(void) +{ + at93c_init_op(); + at93c_write_bits(AT93C_WDSCMD, 10); + at93c_end_op(); +} + +u8 at93c_read(u8 addr) +{ + u8 byte; + at93c_init_op(); + at93c_write_bits((addr & AT93C_ADDR_MAX)|AT93C_RCMD, 10); + byte = at93c_read_byte(); + at93c_end_op(); + return byte; +} + +void at93c_write(u8 addr, u8 data) +{ + at93c_disable_wp(); + at93c_init_op(); + at93c_write_bits((addr & AT93C_ADDR_MAX)|AT93C_WCMD, 10); + at93c_write_bits(data, 8); + at93c_end_op(); + at93c_wait(); + at93c_enable_wp(); +} diff -Nru a/arch/mips/lasat/at93c.h b/arch/mips/lasat/at93c.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/lasat/at93c.h Tue Jul 1 18:44:40 2003 @@ -0,0 +1,18 @@ +/* + * Atmel AT93C46 serial eeprom driver + * + * Brian Murphy + * + */ + +extern struct at93c_defs { + volatile u32 *reg; + volatile u32 *rdata_reg; + int rdata_shift; + int wdata_shift; + u32 cs; + u32 clk; +} *at93c; + +u8 at93c_read(u8 addr); +void at93c_write(u8 addr, u8 data); diff -Nru a/arch/mips/lasat/ds1603.c b/arch/mips/lasat/ds1603.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/lasat/ds1603.c Tue Jul 1 18:44:39 2003 @@ -0,0 +1,174 @@ +/* + * Dallas Semiconductors 1603 RTC driver + * + * Brian Murphy + * + */ +#include +#include +#include +#include + +#include "ds1603.h" + +#define READ_TIME_CMD 0x81 +#define SET_TIME_CMD 0x80 +#define TRIMMER_SET_CMD 0xC0 +#define TRIMMER_VALUE_MASK 0x38 +#define TRIMMER_SHIFT 3 + +struct ds_defs *ds1603 = NULL; + +/* HW specific register functions */ +static void rtc_reg_write(unsigned long val) +{ + *ds1603->reg = val; +} + +static unsigned long rtc_reg_read(void) +{ + unsigned long tmp = *ds1603->reg; + return tmp; +} + +static unsigned long rtc_datareg_read(void) +{ + unsigned long tmp = *ds1603->data_reg; + return tmp; +} + +static void rtc_nrst_high(void) +{ + rtc_reg_write(rtc_reg_read() | ds1603->rst); +} + +static void rtc_nrst_low(void) +{ + rtc_reg_write(rtc_reg_read() & ~ds1603->rst); +} + +static void rtc_cycle_clock(unsigned long data) +{ + data |= ds1603->clk; + rtc_reg_write(data); + ndelay(250); + if (ds1603->data_reversed) + data &= ~ds1603->data; + else + data |= ds1603->data; + data &= ~ds1603->clk; + rtc_reg_write(data); + ndelay(250 + ds1603->huge_delay); +} + +static void rtc_write_databit(unsigned int bit) +{ + unsigned long data = rtc_reg_read(); + if (ds1603->data_reversed) + bit = !bit; + if (bit) + data |= ds1603->data; + else + data &= ~ds1603->data; + + rtc_reg_write(data); + ndelay(50 + ds1603->huge_delay); + rtc_cycle_clock(data); +} + +static unsigned int rtc_read_databit(void) +{ + unsigned int data; + + data = (rtc_datareg_read() & (1 << ds1603->data_read_shift)) + >> ds1603->data_read_shift; + rtc_cycle_clock(rtc_reg_read()); + return data; +} + +static void rtc_write_byte(unsigned int byte) +{ + int i; + + for (i = 0; i<=7; i++) { + rtc_write_databit(byte & 1L); + byte >>= 1; + } +} + +static void rtc_write_word(unsigned long word) +{ + int i; + + for (i = 0; i<=31; i++) { + rtc_write_databit(word & 1L); + word >>= 1; + } +} + +static unsigned long rtc_read_word(void) +{ + int i; + unsigned long word = 0; + unsigned long shift = 0; + + for (i = 0; i<=31; i++) { + word |= rtc_read_databit() << shift; + shift++; + } + return word; +} + +static void rtc_init_op(void) +{ + rtc_nrst_high(); + + rtc_reg_write(rtc_reg_read() & ~ds1603->clk); + + ndelay(50); +} + +static void rtc_end_op(void) +{ + rtc_nrst_low(); + ndelay(1000); +} + +/* interface */ +unsigned long ds1603_read(void) +{ + unsigned long word; + rtc_init_op(); + rtc_write_byte(READ_TIME_CMD); + word = rtc_read_word(); + rtc_end_op(); + return word; +} + +int ds1603_set(unsigned long time) +{ + rtc_init_op(); + rtc_write_byte(SET_TIME_CMD); + rtc_write_word(time); + rtc_end_op(); + + return 0; +} + +void ds1603_set_trimmer(unsigned int trimval) +{ + rtc_init_op(); + rtc_write_byte(((trimval << TRIMMER_SHIFT) & TRIMMER_VALUE_MASK) + | (TRIMMER_SET_CMD)); + rtc_end_op(); +} + +void ds1603_disable(void) +{ + ds1603_set_trimmer(TRIMMER_DISABLE_RTC); +} + +void ds1603_enable(void) +{ + ds1603_set_trimmer(TRIMMER_DEFAULT); +} diff -Nru a/arch/mips/lasat/ds1603.h b/arch/mips/lasat/ds1603.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/lasat/ds1603.h Tue Jul 1 18:44:40 2003 @@ -0,0 +1,33 @@ +/* + * Dallas Semiconductors 1603 RTC driver + * + * Brian Murphy + * + */ +#ifndef __DS1603_H +#define __DS1603_H + +struct ds_defs { + volatile u32 *reg; + volatile u32 *data_reg; + u32 rst; + u32 clk; + u32 data; + u32 data_read_shift; + char data_reversed; + u32 huge_delay; +}; + +extern struct ds_defs *ds1603; + +unsigned long ds1603_read(void); +int ds1603_set(unsigned long); +void ds1603_set_trimmer(unsigned int); +void ds1603_enable(void); +void ds1603_disable(void); +void ds1603_init(struct ds_defs *); + +#define TRIMMER_DEFAULT 3 +#define TRIMMER_DISABLE_RTC 0 + +#endif diff -Nru a/arch/mips/lasat/image/Makefile b/arch/mips/lasat/image/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/lasat/image/Makefile Tue Jul 1 18:44:40 2003 @@ -0,0 +1,52 @@ +# +# MAKEFILE FOR THE MIPS LINUX BOOTLOADER AND ROM DEBUGGER +# +# i-data Networks +# +# Author: Thomas Horsten +# + +ifndef Version + Version = "$(USER)-test" +endif + +MKLASATIMG = mklasatimg +MKLASATIMG_ARCH = mq2,mqpro,sp100,sp200 +KERNEL_IMAGE = $(TOPDIR)/vmlinux +KERNEL_START = $(shell $(NM) $(KERNEL_IMAGE) | grep " _text" | cut -f1 -d\ ) +KERNEL_ENTRY = $(shell $(NM) $(KERNEL_IMAGE) | grep kernel_entry | cut -f1 -d\ ) + +LDSCRIPT= -L$(obj) -Tromscript.normal + +AFLAGS_head.o += -D_kernel_start=0x$(KERNEL_START) \ + -D_kernel_entry=0x$(KERNEL_ENTRY) \ + -D VERSION="\"$(Version)\"" \ + -D TIMESTAMP=$(shell date +%s) + +head.o: $(KERNEL_IMAGE) + +obj-y = head.o kImage.o + +rom.sw: $(obj)/rom.sw + +$(obj)/rom.sw: $(obj)/rom.bin + $(MKLASATIMG) -o $@ -k $^ -m $(MKLASATIMG_ARCH) + +$(obj)/rom.bin: $(obj)/rom + $(OBJCOPY) -O binary -S $^ $@ + +# Rule to make the bootloader +$(obj)/rom: $(addprefix $(obj)/,$(obj-y)) + $(LD) $(LDFLAGS) $(LDSCRIPT) -o $@ $^ + +$(obj)/%.o: $(obj)/%.gz + $(LD) -r -o $@ -b binary $< + +$(obj)/%.gz: $(obj)/%.bin + gzip -cf -9 $< > $@ + +$(obj)/kImage.bin: $(KERNEL_IMAGE) + $(OBJCOPY) -O binary -S $^ $@ + +clean: + rm -f rom rom.bin rom.sw kImage.bin kImage.o diff -Nru a/arch/mips/lasat/image/head.S b/arch/mips/lasat/image/head.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/lasat/image/head.S Tue Jul 1 18:44:40 2003 @@ -0,0 +1,31 @@ +#include + + .text + .section .text.start, "ax" + .set noreorder + .set mips3 + + /* Magic words identifying a software image */ + .word LASAT_K_MAGIC0_VAL + .word LASAT_K_MAGIC1_VAL + + /* Image header version */ + .word 0x00000002 + + /* image start and size */ + .word _image_start + .word _image_size + + /* start of kernel and entrypoint in uncompressed image */ + .word _kernel_start + .word _kernel_entry + + /* Here we have room for future flags */ + + .org 0x40 +reldate: + .word TIMESTAMP + + .org 0x50 +release: + .string VERSION diff -Nru a/arch/mips/lasat/image/romscript.normal b/arch/mips/lasat/image/romscript.normal --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/lasat/image/romscript.normal Tue Jul 1 18:44:40 2003 @@ -0,0 +1,22 @@ +OUTPUT_ARCH(mips) + +SECTIONS +{ + .text : + { + *(.text.start) + } + + /* Data in ROM */ + + .data ALIGN(0x10) : + { + *(.data) + } + _image_start = ADDR(.data); + _image_size = SIZEOF(.data); + + .other : { + *(.*) + } +} diff -Nru a/arch/mips/lasat/interrupt.c b/arch/mips/lasat/interrupt.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/lasat/interrupt.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,194 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * ######################################################################## + * + * Routines for generic manipulation of the interrupts found on the + * Lasat boards. + * + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static volatile int *lasat_int_status = NULL; +static volatile int *lasat_int_mask = NULL; +static volatile int lasat_int_mask_shift; + +extern asmlinkage void mipsIRQ(void); + +#if 0 +#define DEBUG_INT(x...) printk(x) +#else +#define DEBUG_INT(x...) +#endif + +void disable_lasat_irq(unsigned int irq_nr) +{ + unsigned long flags; + DEBUG_INT("disable_lasat_irq: %d", irq_nr); + + local_irq_save(flags); + *lasat_int_mask &= ~(1 << irq_nr) << lasat_int_mask_shift; + local_irq_restore(flags); +} + +void enable_lasat_irq(unsigned int irq_nr) +{ + unsigned long flags; + DEBUG_INT("enable_lasat_irq: %d", irq_nr); + + local_irq_save(flags); + *lasat_int_mask |= (1 << irq_nr) << lasat_int_mask_shift; + local_irq_restore(flags); +} + +static unsigned int startup_lasat_irq(unsigned int irq) +{ + enable_lasat_irq(irq); + return 0; /* never anything pending */ +} + +#define shutdown_lasat_irq disable_lasat_irq + +#define mask_and_ack_lasat_irq disable_lasat_irq + +static void end_lasat_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_lasat_irq(irq); +} + +static struct hw_interrupt_type lasat_irq_type = { + "Lasat", + startup_lasat_irq, + shutdown_lasat_irq, + enable_lasat_irq, + disable_lasat_irq, + mask_and_ack_lasat_irq, + end_lasat_irq, + NULL +}; + +static inline int ls1bit32(unsigned int x) +{ + int b = 31, s; + + s = 16; if (x << 16 == 0) s = 0; b -= s; x <<= s; + s = 8; if (x << 8 == 0) s = 0; b -= s; x <<= s; + s = 4; if (x << 4 == 0) s = 0; b -= s; x <<= s; + s = 2; if (x << 2 == 0) s = 0; b -= s; x <<= s; + s = 1; if (x << 1 == 0) s = 0; b -= s; + + return b; +} + +static unsigned long (* get_int_status)(void); + +static unsigned long get_int_status_100(void) +{ + return (*lasat_int_status & *lasat_int_mask); +} + +static unsigned long get_int_status_200(void) +{ + unsigned long int_status; + + int_status = *lasat_int_status; + int_status &= (int_status >> LASATINT_MASK_SHIFT_200) & 0xffff; + return int_status; +} + +void lasat_hw0_irqdispatch(struct pt_regs *regs) +{ + struct irqaction *action; + unsigned long int_status; + int irq; + + int_status = get_int_status(); + + /* if int_status == 0, then the interrupt has already been cleared */ + if (int_status == 0) + return; + + irq = ls1bit32(int_status); + action = irq_desc[irq].action; + + DEBUG_INT("lasat_hw0_irqdispatch: irq=%d\n", irq); + + /* if action == NULL, then we don't have a handler for the irq */ + if (action == NULL) { + printk("No handler for hw0 irq: %i\n", irq); + atomic_inc(&irq_err_count); + disable_lasat_irq(irq); + return; + } + + irq_enter(); + kstat_cpu(0).irqs[irq]++; + action->handler(irq, action->dev_id, regs); + irq_exit(); + + return; +} + +void __init init_IRQ(void) +{ + int i; + + init_generic_irq(); + + switch (mips_machtype) { + case MACH_LASAT_100: + lasat_int_status = (void *)LASAT_INT_STATUS_REG_100; + lasat_int_mask = (void *)LASAT_INT_MASK_REG_100; + lasat_int_mask_shift = LASATINT_MASK_SHIFT_100; + get_int_status = get_int_status_100; + *lasat_int_mask = 0; + break; + case MACH_LASAT_200: + printk("**** MACH_LASAT_200 interrupt routines\n"); + lasat_int_status = (void *)LASAT_INT_STATUS_REG_200; + lasat_int_mask = (void *)LASAT_INT_MASK_REG_200; + lasat_int_mask_shift = LASATINT_MASK_SHIFT_200; + get_int_status = get_int_status_200; + *lasat_int_mask &= 0xffff; + break; + default: + panic("init_IRQ: mips_machtype incorrect"); + } + + /* Now safe to set the exception vector. */ + set_except_vector(0, mipsIRQ); + + for (i = 0; i <= LASATINT_END; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = 1; + irq_desc[i].handler = &lasat_irq_type; + } +} diff -Nru a/arch/mips/lasat/lasatIRQ.S b/arch/mips/lasat/lasatIRQ.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/lasat/lasatIRQ.S Tue Jul 1 18:44:40 2003 @@ -0,0 +1,75 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999, 2000 MIPS Technologies, Inc. All rights reserved. + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * ######################################################################## + * + * Interrupt exception dispatch code. + * + */ +#include + +#include +#include +#include +#include + + .text + .set noreorder + .set noat + .align 5 + NESTED(mipsIRQ, PT_SIZE, sp) + SAVE_ALL + CLI + .set at + + mfc0 s0, CP0_CAUSE # get irq mask + + /* First we check for r4k counter/timer IRQ. */ + andi a0, s0, CAUSEF_IP7 + beq a0, zero, 1f + andi a0, s0, CAUSEF_IP2 # delay slot, check hw0 interrupt + + /* Wheee, a timer interrupt. */ + move a0, sp + jal lasat_timer_interrupt + nop + + j ret_from_irq + nop + +1: + /* Wheee, combined hardware level zero interrupt. */ + jal lasat_hw0_irqdispatch + move a0, sp # delay slot + + j ret_from_irq + nop # delay slot + +1: + /* + * Here by mistake? This is possible, what can happen is that by the + * time we take the exception the IRQ pin goes low, so just leave if + * this is the case. + */ + move a1,s0 + mfc0 a1, CP0_EPC + + j ret_from_irq + nop + END(mipsIRQ) diff -Nru a/arch/mips/lasat/lasat_board.c b/arch/mips/lasat/lasat_board.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/lasat/lasat_board.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,282 @@ +/* + * lasat_board.c + * + * Thomas Horsten + * Copyright (C) 2000 LASAT Networks A/S. + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * ######################################################################## + * + * Routines specific to the LASAT boards + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "at93c.h" +/* New model description table */ +#include "lasat_models.h" + +#define EEPROM_CRC(data, len) (~0 ^ crc32(~0, data, len)) + +struct lasat_info lasat_board_info; + +void update_bcastaddr(void); + +int EEPROMRead(unsigned int pos, unsigned char *data, int len) +{ + int i; + + for (i=0; i 0x200000) { + ls[LASAT_MTD_CONFIG] = 0x100000; + ls[LASAT_MTD_FS] = 0x500000; + } + } else { + lasat_board_info.li_flash_base = KSEG1ADDR(0x10000000); + + if (lasat_board_info.li_flash_size < 0x1000000) { + lb[LASAT_MTD_BOOTLOADER] = KSEG1ADDR(0x10000000); + ls[LASAT_MTD_CONFIG] = 0x100000; + if (lasat_board_info.li_flash_size >= 0x400000) { + ls[LASAT_MTD_FS] = lasat_board_info.li_flash_size - 0x300000; + } + } + } + + for (i = 1; i < LASAT_MTD_LAST; i++) + lb[i] = lb[i-1] + ls[i-1]; +} + +int lasat_init_board_info(void) +{ + int c; + unsigned long crc; + unsigned long cfg0, cfg1; + const product_info_t *ppi; + int i_n_base_models = N_BASE_MODELS; + const char * const * i_txt_base_models = txt_base_models; + int i_n_prids = N_PRIDS; + + memset(&lasat_board_info, 0, sizeof(lasat_board_info)); + + /* First read the EEPROM info */ + EEPROMRead(0, (unsigned char *)&lasat_board_info.li_eeprom_info, + sizeof(struct lasat_eeprom_struct)); + + /* Check the CRC */ + crc = EEPROM_CRC((unsigned char *)(&lasat_board_info.li_eeprom_info), + sizeof(struct lasat_eeprom_struct) - 4); + + if (crc != lasat_board_info.li_eeprom_info.crc32) { + prom_printf("WARNING...\nWARNING...\nEEPROM CRC does not match calculated, attempting to soldier on...\n"); + } + + if (lasat_board_info.li_eeprom_info.version != LASAT_EEPROM_VERSION) + { + prom_printf("WARNING...\nWARNING...\nEEPROM version %d, wanted version %d, attempting to soldier on...\n", + (unsigned int)lasat_board_info.li_eeprom_info.version, + LASAT_EEPROM_VERSION); + } + + cfg0 = lasat_board_info.li_eeprom_info.cfg[0]; + cfg1 = lasat_board_info.li_eeprom_info.cfg[1]; + + if ( LASAT_W0_DSCTYPE(cfg0) != 1) { + prom_printf("WARNING...\nWARNING...\nInvalid configuration read from EEPROM, attempting to soldier on..."); + } + /* We have a valid configuration */ + + switch (LASAT_W0_SDRAMBANKSZ(cfg0)) { + case 0: + lasat_board_info.li_memsize = 0x0800000; + break; + case 1: + lasat_board_info.li_memsize = 0x1000000; + break; + case 2: + lasat_board_info.li_memsize = 0x2000000; + break; + case 3: + lasat_board_info.li_memsize = 0x4000000; + break; + case 4: + lasat_board_info.li_memsize = 0x8000000; + break; + default: + lasat_board_info.li_memsize = 0; + } + + switch (LASAT_W0_SDRAMBANKS(cfg0)) { + case 0: + break; + case 1: + lasat_board_info.li_memsize *= 2; + break; + default: + break; + } + + switch (LASAT_W0_BUSSPEED(cfg0)) { + case 0x0: + lasat_board_info.li_bus_hz = 60000000; + break; + case 0x1: + lasat_board_info.li_bus_hz = 66000000; + break; + case 0x2: + lasat_board_info.li_bus_hz = 66666667; + break; + case 0x3: + lasat_board_info.li_bus_hz = 80000000; + break; + case 0x4: + lasat_board_info.li_bus_hz = 83333333; + break; + case 0x5: + lasat_board_info.li_bus_hz = 100000000; + break; + } + + switch (LASAT_W0_CPUCLK(cfg0)) { + case 0x0: + lasat_board_info.li_cpu_hz = + lasat_board_info.li_bus_hz; + break; + case 0x1: + lasat_board_info.li_cpu_hz = + lasat_board_info.li_bus_hz + + (lasat_board_info.li_bus_hz >> 1); + break; + case 0x2: + lasat_board_info.li_cpu_hz = + lasat_board_info.li_bus_hz + + lasat_board_info.li_bus_hz; + break; + case 0x3: + lasat_board_info.li_cpu_hz = + lasat_board_info.li_bus_hz + + lasat_board_info.li_bus_hz + + (lasat_board_info.li_bus_hz >> 1); + break; + case 0x4: + lasat_board_info.li_cpu_hz = + lasat_board_info.li_bus_hz + + lasat_board_info.li_bus_hz + + lasat_board_info.li_bus_hz; + break; + } + + /* Flash size */ + switch (LASAT_W1_FLASHSIZE(cfg1)) { + case 0: + lasat_board_info.li_flash_size = 0x200000; + break; + case 1: + lasat_board_info.li_flash_size = 0x400000; + break; + case 2: + lasat_board_info.li_flash_size = 0x800000; + break; + case 3: + lasat_board_info.li_flash_size = 0x1000000; + break; + case 4: + lasat_board_info.li_flash_size = 0x2000000; + break; + } + + init_flash_sizes(); + + lasat_board_info.li_bmid = LASAT_W0_BMID(cfg0); + lasat_board_info.li_prid = lasat_board_info.li_eeprom_info.prid; + if (lasat_board_info.li_prid == 0xffff || lasat_board_info.li_prid == 0) + lasat_board_info.li_prid = lasat_board_info.li_bmid; + + /* Base model stuff */ + if (lasat_board_info.li_bmid > i_n_base_models) + lasat_board_info.li_bmid = i_n_base_models; + strcpy(lasat_board_info.li_bmstr, i_txt_base_models[lasat_board_info.li_bmid]); + + /* Product ID dependent values */ + c = lasat_board_info.li_prid; + if (c >= i_n_prids) { + strcpy(lasat_board_info.li_namestr, "Unknown Model"); + strcpy(lasat_board_info.li_typestr, "Unknown Type"); + } else { + ppi = &vendor_info_table[0].vi_product_info[c]; + strcpy(lasat_board_info.li_namestr, ppi->pi_name); + if (ppi->pi_type) + strcpy(lasat_board_info.li_typestr, ppi->pi_type); + else + sprintf(lasat_board_info.li_typestr, "%d",10*c); + } + +#if defined(CONFIG_INET) && defined(CONFIG_SYSCTL) + update_bcastaddr(); +#endif + + return 0; +} + +void lasat_write_eeprom_info(void) +{ + unsigned long crc; + + /* Generate the CRC */ + crc = EEPROM_CRC((unsigned char *)(&lasat_board_info.li_eeprom_info), + sizeof(struct lasat_eeprom_struct) - 4); + lasat_board_info.li_eeprom_info.crc32 = crc; + + /* Write the EEPROM info */ + EEPROMWrite(0, (unsigned char *)&lasat_board_info.li_eeprom_info, + sizeof(struct lasat_eeprom_struct)); +} + diff -Nru a/arch/mips/lasat/lasat_models.h b/arch/mips/lasat/lasat_models.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/lasat/lasat_models.h Tue Jul 1 18:44:40 2003 @@ -0,0 +1,63 @@ +/* + * Model description tables + */ + +typedef struct product_info_t { + const char *pi_name; + const char *pi_type; +} product_info_t; + +typedef struct vendor_info_t { + const char *vi_name; + const product_info_t *vi_product_info; +} vendor_info_t; + +/* + * Base models + */ +static const char * const txt_base_models[] = { + "MQ 2", "MQ Pro", "SP 25", "SP 50", "SP 100", "SP 5000", "SP 7000", "SP 1000", "Unknown" +}; +#define N_BASE_MODELS (sizeof(txt_base_models)/sizeof(char*)-1) + +/* + * Eicon Networks + */ +static const char txt_en_mq[] = "Masquerade"; +static const char txt_en_sp[] = "Safepipe"; + +static const product_info_t product_info_eicon[] = { + { txt_en_mq, "II" }, /* 0 */ + { txt_en_mq, "Pro" }, /* 1 */ + { txt_en_sp, "25" }, /* 2 */ + { txt_en_sp, "50" }, /* 3 */ + { txt_en_sp, "100" }, /* 4 */ + { txt_en_sp, "5000" }, /* 5 */ + { txt_en_sp, "7000" }, /* 6 */ + { txt_en_sp, "30" }, /* 7 */ + { txt_en_sp, "5100" }, /* 8 */ + { txt_en_sp, "7100" }, /* 9 */ + { txt_en_sp, "1110" }, /* 10 */ + { txt_en_sp, "3020" }, /* 11 */ + { txt_en_sp, "3030" }, /* 12 */ + { txt_en_sp, "5020" }, /* 13 */ + { txt_en_sp, "5030" }, /* 14 */ + { txt_en_sp, "1120" }, /* 15 */ + { txt_en_sp, "1130" }, /* 16 */ + { txt_en_sp, "6010" }, /* 17 */ + { txt_en_sp, "6110" }, /* 18 */ + { txt_en_sp, "6210" }, /* 19 */ + { txt_en_sp, "1020" }, /* 20 */ + { txt_en_sp, "1040" }, /* 21 */ + { txt_en_sp, "1050" }, /* 22 */ + { txt_en_sp, "1060" }, /* 23 */ +}; +#define N_PRIDS (sizeof(product_info_eicon)/sizeof(product_info_t)) + +/* + * The vendor table + */ +static vendor_info_t const vendor_info_table[] = { + { "Eicon Networks", product_info_eicon }, +}; +#define N_VENDORS (sizeof(vendor_info_table)/sizeof(vendor_info_t)) diff -Nru a/arch/mips/lasat/picvue.c b/arch/mips/lasat/picvue.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/lasat/picvue.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,240 @@ +/* + * Picvue PVC160206 display driver + * + * Brian Murphy + * + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "picvue.h" + +#define PVC_BUSY 0x80 +#define PVC_NLINES 2 +#define PVC_DISPMEM 80 +#define PVC_LINELEN PVC_DISPMEM / PVC_NLINES + +struct pvc_defs *picvue = NULL; + +DECLARE_MUTEX(pvc_sem); + +static void pvc_reg_write(u32 val) +{ + *picvue->reg = val; +} + +static u32 pvc_reg_read(void) +{ + u32 tmp = *picvue->reg; + return tmp; +} + +static void pvc_write_byte(u32 data, u8 byte) +{ + data |= picvue->e; + pvc_reg_write(data); + data &= ~picvue->data_mask; + data |= byte << picvue->data_shift; + pvc_reg_write(data); + ndelay(220); + pvc_reg_write(data & ~picvue->e); + ndelay(220); +} + +static u8 pvc_read_byte(u32 data) +{ + u8 byte; + + data |= picvue->e; + pvc_reg_write(data); + ndelay(220); + byte = (pvc_reg_read() & picvue->data_mask) >> picvue->data_shift; + data &= ~picvue->e; + pvc_reg_write(data); + ndelay(220); + return byte; +} + +static u8 pvc_read_data(void) +{ + u32 data = pvc_reg_read(); + u8 byte; + data |= picvue->rw; + data &= ~picvue->rs; + pvc_reg_write(data); + ndelay(40); + byte = pvc_read_byte(data); + data |= picvue->rs; + pvc_reg_write(data); + return byte; +} + +#define TIMEOUT 1000 +static int pvc_wait(void) +{ + int i = TIMEOUT; + int err = 0; + + while ((pvc_read_data() & PVC_BUSY) && i) + i--; + if (i == 0) + err = -ETIME; + + return err; +} + +#define MODE_INST 0 +#define MODE_DATA 1 +static void pvc_write(u8 byte, int mode) +{ + u32 data = pvc_reg_read(); + data &= ~picvue->rw; + if (mode == MODE_DATA) + data |= picvue->rs; + else + data &= ~picvue->rs; + pvc_reg_write(data); + ndelay(40); + pvc_write_byte(data, byte); + if (mode == MODE_DATA) + data &= ~picvue->rs; + else + data |= picvue->rs; + pvc_reg_write(data); + pvc_wait(); +} + +void pvc_write_string(const unsigned char *str, u8 addr, int line) +{ + int i = 0; + + if (line > 0 && (PVC_NLINES > 1)) + addr += 0x40 * line; + pvc_write(0x80 | addr, MODE_INST); + + while (*str != 0 && i < PVC_LINELEN) { + pvc_write(*str++, MODE_DATA); + i++; + } +} + +void pvc_write_string_centered(const unsigned char *str, int line) +{ + int len = strlen(str); + u8 addr; + + if (len > PVC_VISIBLE_CHARS) + addr = 0; + else + addr = (PVC_VISIBLE_CHARS - strlen(str))/2; + + pvc_write_string(str, addr, line); +} + +void pvc_dump_string(const unsigned char *str) +{ + int len = strlen(str); + + pvc_write_string(str, 0, 0); + if (len > PVC_VISIBLE_CHARS) + pvc_write_string(&str[PVC_VISIBLE_CHARS], 0, 1); +} + +#define BM_SIZE 8 +#define MAX_PROGRAMMABLE_CHARS 8 +int pvc_program_cg(int charnum, u8 bitmap[BM_SIZE]) +{ + int i; + int addr; + + if (charnum > MAX_PROGRAMMABLE_CHARS) + return -ENOENT; + + addr = charnum * 8; + pvc_write(0x40 | addr, MODE_INST); + + for (i=0; i + * + */ +#include + +struct pvc_defs { + volatile u32 *reg; + u32 data_shift; + u32 data_mask; + u32 e; + u32 rw; + u32 rs; +}; + +extern struct pvc_defs *picvue; + +#define PVC_NLINES 2 +#define PVC_DISPMEM 80 +#define PVC_LINELEN PVC_DISPMEM / PVC_NLINES +#define PVC_VISIBLE_CHARS 16 + +void pvc_write_string(const unsigned char *str, u8 addr, int line); +void pvc_write_string_centered(const unsigned char *str, int line); +void pvc_dump_string(const unsigned char *str); + +#define BM_SIZE 8 +#define MAX_PROGRAMMABLE_CHARS 8 +int pvc_program_cg(int charnum, u8 bitmap[BM_SIZE]); + +void pvc_dispcnt(u8 cmd); +#define DISP_OFF 0 +#define DISP_ON (1 << 2) +#define CUR_ON (1 << 1) +#define CUR_BLINK (1 << 0) + +void pvc_move(u8 cmd); +#define DISPLAY (1 << 3) +#define CURSOR 0 +#define RIGHT (1 << 2) +#define LEFT 0 + +void pvc_clear(void); +void pvc_home(void); + +extern struct semaphore pvc_sem; diff -Nru a/arch/mips/lasat/picvue_proc.c b/arch/mips/lasat/picvue_proc.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/lasat/picvue_proc.c Tue Jul 1 18:44:39 2003 @@ -0,0 +1,186 @@ +/* + * Picvue PVC160206 display driver + * + * Brian Murphy + * + */ +#include +#include +#include +#include + +#include +#include + +#include + +#include "picvue.h" + +static char pvc_lines[PVC_NLINES][PVC_LINELEN+1]; +static int pvc_linedata[PVC_NLINES]; +static struct proc_dir_entry *pvc_display_dir; +static char *pvc_linename[PVC_NLINES] = {"line1", "line2"}; +#define DISPLAY_DIR_NAME "display" +static int scroll_dir = 0, scroll_interval = 0; + +static struct timer_list timer; + +static void pvc_display(unsigned long data) { + int i; + + pvc_clear(); + for (i=0; i PVC_NLINES) { + printk("proc_read_line: invalid lineno %d\n", lineno); + return 0; + } + + down(&pvc_sem); + page += sprintf(page, "%s\n", pvc_lines[lineno]); + up(&pvc_sem); + + return page - origpage; +} + +static int pvc_proc_write_line(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + int origcount = count; + int lineno = *(int *)data; + + if (lineno < 0 || lineno > PVC_NLINES) { + printk("proc_write_line: invalid lineno %d\n", lineno); + return origcount; + } + + if (count > PVC_LINELEN) + count = PVC_LINELEN; + + if (buffer[count-1] == '\n') + count--; + + down(&pvc_sem); + strncpy(pvc_lines[lineno], buffer, count); + pvc_lines[lineno][count] = '\0'; + up(&pvc_sem); + + tasklet_schedule(&pvc_display_tasklet); + + return origcount; +} + +static int pvc_proc_write_scroll(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + int origcount = count; + int cmd = simple_strtol(buffer, NULL, 10); + + down(&pvc_sem); + if (scroll_interval != 0) + del_timer(&timer); + + if (cmd == 0) { + scroll_dir = 0; + scroll_interval = 0; + } else { + if (cmd < 0) { + scroll_dir = -1; + scroll_interval = -cmd; + } else { + scroll_dir = 1; + scroll_interval = cmd; + } + add_timer(&timer); + } + up(&pvc_sem); + + return origcount; +} + +static int pvc_proc_read_scroll(char *page, char **start, + off_t off, int count, + int *eof, void *data) +{ + char *origpage = page; + + down(&pvc_sem); + page += sprintf(page, "%d\n", scroll_dir * scroll_interval); + up(&pvc_sem); + + return page - origpage; +} + + +void pvc_proc_timerfunc(unsigned long data) +{ + if (scroll_dir < 0) + pvc_move(DISPLAY|RIGHT); + else if (scroll_dir > 0) + pvc_move(DISPLAY|LEFT); + + timer.expires = jiffies + scroll_interval; + add_timer(&timer); +} + +static void pvc_proc_cleanup(void) +{ + int i; + for (i=0; iread_proc = pvc_proc_read_line; + proc_entry->write_proc = pvc_proc_write_line; + proc_entry->data = &pvc_linedata[i]; + } + proc_entry = create_proc_entry("scroll", 0644, pvc_display_dir); + if (proc_entry == NULL) + goto error; + proc_entry->write_proc = pvc_proc_write_scroll; + proc_entry->read_proc = pvc_proc_read_scroll; + + init_timer(&timer); + timer.function = pvc_proc_timerfunc; + + return 0; +error: + pvc_proc_cleanup(); + return -ENOMEM; +} + +module_init(pvc_proc_init); +module_exit(pvc_proc_cleanup); +MODULE_LICENSE("GPL"); diff -Nru a/arch/mips/lasat/prom.c b/arch/mips/lasat/prom.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/lasat/prom.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,135 @@ +/* + * PROM interface routines. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "at93c.h" +#include +#include "prom.h" + +#define RESET_VECTOR 0xbfc00000 +#define PROM_JUMP_TABLE_ENTRY(n) (*((u32 *)(RESET_VECTOR + 0x20) + n)) +#define PROM_DISPLAY_ADDR PROM_JUMP_TABLE_ENTRY(0) +#define PROM_PUTC_ADDR PROM_JUMP_TABLE_ENTRY(1) +#define PROM_MONITOR_ADDR PROM_JUMP_TABLE_ENTRY(2) + +static void null_prom_printf(const char * fmt, ...) +{ +} + +static void null_prom_display(const char *string, int pos, int clear) +{ +} + +static void null_prom_monitor(void) +{ +} + +static void null_prom_putc(char c) +{ +} + +/* these are functions provided by the bootloader */ +static void (* prom_putc)(char c) = null_prom_putc; +void (* prom_printf)(const char * fmt, ...) = null_prom_printf; +void (* prom_display)(const char *string, int pos, int clear) = + null_prom_display; +void (* prom_monitor)(void) = null_prom_monitor; + +#define PROM_PRINTFBUF_SIZE 256 +static char prom_printfbuf[PROM_PRINTFBUF_SIZE]; + +static void real_prom_printf(const char * fmt, ...) +{ + va_list ap; + int len; + char *c = prom_printfbuf; + int i; + + va_start(ap, fmt); + len = vsnprintf(prom_printfbuf, PROM_PRINTFBUF_SIZE, fmt, ap); + va_end(ap); + + /* output overflowed the buffer */ + if (len < 0 || len > PROM_PRINTFBUF_SIZE) + len = PROM_PRINTFBUF_SIZE; + + for (i=0; i < len; i++) { + if (*c == '\n') + prom_putc('\r'); + prom_putc(*c++); + } +} + +static void setup_prom_vectors(void) +{ + u32 version = *(u32 *)(RESET_VECTOR + 0x90); + + if (version == 306) { + prom_display = (void *)PROM_DISPLAY_ADDR; + prom_putc = (void *)PROM_PUTC_ADDR; + prom_printf = real_prom_printf; + prom_monitor = (void *)PROM_MONITOR_ADDR; + } + prom_printf("prom vectors set up\n"); +} + +char arcs_cmdline[CL_SIZE]; + +static struct at93c_defs at93c_defs[N_MACHTYPES] = { + {(void *)AT93C_REG_100, (void *)AT93C_RDATA_REG_100, AT93C_RDATA_SHIFT_100, + AT93C_WDATA_SHIFT_100, AT93C_CS_M_100, AT93C_CLK_M_100}, + {(void *)AT93C_REG_200, (void *)AT93C_RDATA_REG_200, AT93C_RDATA_SHIFT_200, + AT93C_WDATA_SHIFT_200, AT93C_CS_M_200, AT93C_CLK_M_200}, +}; + +void __init prom_init(int argc, char **argv, char **envp, int *prom_vec) +{ + setup_prom_vectors(); + + if (current_cpu_data.cputype == CPU_R5000) + mips_machtype = MACH_LASAT_200; + else + mips_machtype = MACH_LASAT_100; + + at93c = &at93c_defs[mips_machtype]; + + lasat_init_board_info(); /* Read info from EEPROM */ + + mips_machgroup = MACH_GROUP_LASAT; + + /* Get the command line */ + if (argc>0) { + strncpy(arcs_cmdline, argv[0], CL_SIZE-1); + arcs_cmdline[CL_SIZE-1] = '\0'; + } + + /* Set the I/O base address */ + set_io_port_base(KSEG1); + + /* Set memory regions */ + ioport_resource.start = 0; /* Should be KSEGx ??? */ + ioport_resource.end = 0xffffffff; /* Should be ??? */ + + add_memory_region(0, lasat_board_info.li_memsize, BOOT_MEM_RAM); +} + +void prom_free_prom_memory(void) +{ +} + +const char *get_system_type(void) +{ + return lasat_board_info.li_bmstr; +} diff -Nru a/arch/mips/lasat/prom.h b/arch/mips/lasat/prom.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/lasat/prom.h Tue Jul 1 18:44:40 2003 @@ -0,0 +1,6 @@ +#ifndef PROM_H +#define PROM_H +extern void (* prom_display)(const char *string, int pos, int clear); +extern void (* prom_monitor)(void); +extern void (* prom_printf)(const char * fmt, ...); +#endif diff -Nru a/arch/mips/lasat/reset.c b/arch/mips/lasat/reset.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/lasat/reset.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,73 @@ +/* + * + * Thomas Horsten + * Copyright (C) 2000 LASAT Networks A/S. + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * ######################################################################## + * + * Reset the LASAT board. + * + */ + +#include +#include +#include +#include +#include "picvue.h" +#include "prom.h" + +static void lasat_machine_restart(char *command); +static void lasat_machine_halt(void); + +/* Used to set machine to boot in service mode via /proc interface */ +int lasat_boot_to_service = 0; + +static void lasat_machine_restart(char *command) +{ + local_irq_disable(); + + if (lasat_boot_to_service) { + printk("machine_restart: Rebooting to service mode\n"); + *(volatile unsigned int *)0xa0000024 = 0xdeadbeef; + *(volatile unsigned int *)0xa00000fc = 0xfedeabba; + } + *lasat_misc->reset_reg = 0xbedead; + for (;;) ; +} + +#define MESSAGE "System halted" +static void lasat_machine_halt(void) +{ + local_irq_disable(); + + /* Disable interrupts and loop forever */ + printk(KERN_NOTICE MESSAGE "\n"); +#ifdef CONFIG_PICVUE + pvc_clear(); + pvc_write_string(MESSAGE, 0, 0); +#endif + prom_monitor(); + for (;;) ; +} + +void lasat_reboot_setup(void) +{ + _machine_restart = lasat_machine_restart; + _machine_halt = lasat_machine_halt; + _machine_power_off = lasat_machine_halt; +} diff -Nru a/arch/mips/lasat/setup.c b/arch/mips/lasat/setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/lasat/setup.c Tue Jul 1 18:44:39 2003 @@ -0,0 +1,221 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999 MIPS Technologies, Inc. All rights reserved. + * + * Thomas Horsten + * Copyright (C) 2000 LASAT Networks A/S. + * + * Brian Murphy + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Lasat specific setup. + */ +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#ifdef CONFIG_PICVUE +#include +#endif + +#include "ds1603.h" +#include "at93c.h" +#include +#include +#include + +#include "prom.h" + +int lasat_command_line = 0; +void lasatint_init(void); + +#ifdef CONFIG_BLK_DEV_IDE +extern struct ide_ops std_ide_ops; +extern struct ide_ops *ide_ops; +#endif + +extern char arcs_cmdline[CL_SIZE]; + +extern void lasat_reboot_setup(void); +extern void pcisetup(void); +extern void edhac_init(void *, void *, void *); +extern void addrflt_init(void); + +struct lasat_misc lasat_misc_info[N_MACHTYPES] = { + {(void *)KSEG1ADDR(0x1c840000), (void *)KSEG1ADDR(0x1c800000), 2}, + {(void *)KSEG1ADDR(0x11080000), (void *)KSEG1ADDR(0x11000000), 6} +}; + +struct lasat_misc *lasat_misc = NULL; + +#ifdef CONFIG_DS1603 +static struct ds_defs ds_defs[N_MACHTYPES] = { + { (void *)DS1603_REG_100, (void *)DS1603_REG_100, + DS1603_RST_100, DS1603_CLK_100, DS1603_DATA_100, + DS1603_DATA_SHIFT_100, 0, 0 }, + { (void *)DS1603_REG_200, (void *)DS1603_DATA_REG_200, + DS1603_RST_200, DS1603_CLK_200, DS1603_DATA_200, + DS1603_DATA_READ_SHIFT_200, 1, 2000 } +}; +#endif + +#ifdef CONFIG_PICVUE +#include "picvue.h" +static struct pvc_defs pvc_defs[N_MACHTYPES] = { + { (void *)PVC_REG_100, PVC_DATA_SHIFT_100, PVC_DATA_M_100, + PVC_E_100, PVC_RW_100, PVC_RS_100 }, + { (void *)PVC_REG_200, PVC_DATA_SHIFT_200, PVC_DATA_M_200, + PVC_E_200, PVC_RW_200, PVC_RS_200 } +}; +#endif + +static int lasat_panic_display(struct notifier_block *this, + unsigned long event, void *ptr) +{ +#ifdef CONFIG_PICVUE + unsigned char *string = ptr; + if (string == NULL) + string = "Kernel Panic"; + pvc_dump_string(string); +#endif + return NOTIFY_DONE; +} + +static int lasat_panic_prom_monitor(struct notifier_block *this, + unsigned long event, void *ptr) +{ + prom_monitor(); + return NOTIFY_DONE; +} + +static struct notifier_block lasat_panic_block[] = +{ + { lasat_panic_display, NULL, INT_MAX }, + { lasat_panic_prom_monitor, NULL, INT_MIN } +}; + +#ifdef CONFIG_BLK_DEV_IDE +static int lasat_ide_default_irq(ide_ioreg_t base) { + return 0; +} + +static ide_ioreg_t lasat_ide_default_io_base(int index) { + return 0; +} +#endif + +static void lasat_time_init(void) +{ + mips_counter_frequency = lasat_board_info.li_cpu_hz / 2; +} + +static void lasat_timer_setup(struct irqaction *irq) +{ + + write_c0_compare( + read_c0_count() + + mips_counter_frequency / HZ); + change_c0_status(ST0_IM, IE_IRQ0 | IE_IRQ5); +} + +#define MIPS_CPU_TIMER_IRQ 7 +asmlinkage void lasat_timer_interrupt(struct pt_regs *regs) +{ + ll_timer_interrupt(MIPS_CPU_TIMER_IRQ, regs); +} + +//#define DYNAMIC_SERIAL_INIT +#ifdef DYNAMIC_SERIAL_INIT +void __init serial_init(void) +{ +#ifdef CONFIG_SERIAL + struct serial_struct s; + + memset(&s, 0, sizeof(s)); + + s.flags = STD_COM_FLAGS; + s.io_type = SERIAL_IO_MEM; + + if (mips_machtype == MACH_LASAT_100) { + s.baud_base = LASAT_BASE_BAUD_100; + s.irq = LASATINT_UART_100; + s.iomem_reg_shift = LASAT_UART_REGS_SHIFT_100; + s.iomem_base = (u8 *)KSEG1ADDR(LASAT_UART_REGS_BASE_100); + } else { + s.baud_base = LASAT_BASE_BAUD_200; + s.irq = LASATINT_UART_200; + s.iomem_reg_shift = LASAT_UART_REGS_SHIFT_200; + s.iomem_base = (u8 *)KSEG1ADDR(LASAT_UART_REGS_BASE_200); + } + + if (early_serial_setup(&s) != 0) + printk(KERN_ERR "Serial setup failed!\n"); +#endif +} +#endif + +void __init lasat_setup(void) +{ + int i; + lasat_misc = &lasat_misc_info[mips_machtype]; +#ifdef CONFIG_PICVUE + picvue = &pvc_defs[mips_machtype]; +#endif + + /* Set up panic notifier */ + for (i = 0; i < sizeof(lasat_panic_block) / sizeof(struct notifier_block); i++) + notifier_chain_register(&panic_notifier_list, &lasat_panic_block[i]); + +#ifdef CONFIG_BLK_DEV_IDE + ide_ops = &std_ide_ops; + ide_ops->ide_default_irq = &lasat_ide_default_irq; + ide_ops->ide_default_io_base = &lasat_ide_default_io_base; +#endif + + lasat_reboot_setup(); + + board_time_init = lasat_time_init; + board_timer_setup = lasat_timer_setup; + +#ifdef CONFIG_DS1603 + ds1603 = &ds_defs[mips_machtype]; + rtc_get_time = ds1603_read; + rtc_set_time = ds1603_set; +#endif + +#ifdef DYNAMIC_SERIAL_INIT + serial_init(); +#endif + /* Switch from prom exception handler to normal mode */ + change_c0_status(ST0_BEV,0); + + prom_printf("Lasat specific initialization complete\n"); +} + + diff -Nru a/arch/mips/lasat/sysctl.c b/arch/mips/lasat/sysctl.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/lasat/sysctl.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,355 @@ +/* + * Thomas Horsten + * Copyright (C) 2000 LASAT Networks A/S. + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Routines specific to the LASAT boards + */ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sysctl.h" +#include "ds1603.h" + +static DECLARE_MUTEX(lasat_info_sem); + +/* Strategy function to write EEPROM after changing string entry */ +int sysctl_lasatstring(ctl_table *table, int *name, int nlen, + void *oldval, size_t *oldlenp, + void *newval, size_t newlen, void **context) +{ + int r; + down(&lasat_info_sem); + r = sysctl_string(table, name, + nlen, oldval, oldlenp, newval, newlen, context); + if (r < 0) { + up(&lasat_info_sem); + return r; + } + if (newval && newlen) { + lasat_write_eeprom_info(); + } + up(&lasat_info_sem); + return 1; +} + + +/* And the same for proc */ +int proc_dolasatstring(ctl_table *table, int write, struct file *filp, + void *buffer, size_t *lenp) +{ + int r; + down(&lasat_info_sem); + r = proc_dostring(table, write, filp, buffer, lenp); + if ( (!write) || r) { + up(&lasat_info_sem); + return r; + } + lasat_write_eeprom_info(); + up(&lasat_info_sem); + return 0; +} + +/* proc function to write EEPROM after changing int entry */ +int proc_dolasatint(ctl_table *table, int write, struct file *filp, + void *buffer, size_t *lenp) +{ + int r; + down(&lasat_info_sem); + r = proc_dointvec(table, write, filp, buffer, lenp); + if ( (!write) || r) { + up(&lasat_info_sem); + return r; + } + lasat_write_eeprom_info(); + up(&lasat_info_sem); + return 0; +} + +static int rtctmp; + +#ifdef CONFIG_DS1603 +/* proc function to read/write RealTime Clock */ +int proc_dolasatrtc(ctl_table *table, int write, struct file *filp, + void *buffer, size_t *lenp) +{ + int r; + down(&lasat_info_sem); + if (!write) { + rtctmp = ds1603_read(); + /* check for time < 0 and set to 0 */ + if (rtctmp < 0) + rtctmp = 0; + } + r = proc_dointvec(table, write, filp, buffer, lenp); + if ( (!write) || r) { + up(&lasat_info_sem); + return r; + } + ds1603_set(rtctmp); + up(&lasat_info_sem); + return 0; +} +#endif + +/* Sysctl for setting the IP addresses */ +int sysctl_lasat_intvec(ctl_table *table, int *name, int nlen, + void *oldval, size_t *oldlenp, + void *newval, size_t newlen, void **context) +{ + int r; + down(&lasat_info_sem); + r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen, context); + if (r < 0) { + up(&lasat_info_sem); + return r; + } + if (newval && newlen) { + lasat_write_eeprom_info(); + } + up(&lasat_info_sem); + return 1; +} + +#ifdef CONFIG_DS1603 +/* Same for RTC */ +int sysctl_lasat_rtc(ctl_table *table, int *name, int nlen, + void *oldval, size_t *oldlenp, + void *newval, size_t newlen, void **context) +{ + int r; + down(&lasat_info_sem); + rtctmp = ds1603_read(); + if (rtctmp < 0) + rtctmp = 0; + r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen, context); + if (r < 0) { + up(&lasat_info_sem); + return r; + } + if (newval && newlen) { + ds1603_set(rtctmp); + } + up(&lasat_info_sem); + return 1; +} +#endif + +#ifdef CONFIG_INET +static char lasat_bcastaddr[16]; + +void update_bcastaddr(void) +{ + unsigned int ip; + + ip = (lasat_board_info.li_eeprom_info.ipaddr & + lasat_board_info.li_eeprom_info.netmask) | + ~lasat_board_info.li_eeprom_info.netmask; + + sprintf(lasat_bcastaddr, "%d.%d.%d.%d", + (ip ) & 0xff, + (ip >> 8) & 0xff, + (ip >> 16) & 0xff, + (ip >> 24) & 0xff); +} + +static char proc_lasat_ipbuf[32]; +/* Parsing of IP address */ +int proc_lasat_ip(ctl_table *table, int write, struct file *filp, + void *buffer, size_t *lenp) +{ + int len; + unsigned int ip; + char *p, c; + + if (!table->data || !table->maxlen || !*lenp || + (filp->f_pos && !write)) { + *lenp = 0; + return 0; + } + + down(&lasat_info_sem); + if (write) { + len = 0; + p = buffer; + while (len < *lenp) { + if(get_user(c, p++)) { + up(&lasat_info_sem); + return -EFAULT; + } + if (c == 0 || c == '\n') + break; + len++; + } + if (len >= sizeof(proc_lasat_ipbuf)-1) + len = sizeof(proc_lasat_ipbuf) - 1; + if (copy_from_user(proc_lasat_ipbuf, buffer, len)) + { + up(&lasat_info_sem); + return -EFAULT; + } + proc_lasat_ipbuf[len] = 0; + filp->f_pos += *lenp; + /* Now see if we can convert it to a valid IP */ + ip = in_aton(proc_lasat_ipbuf); + *(unsigned int *)(table->data) = ip; + lasat_write_eeprom_info(); + } else { + ip = *(unsigned int *)(table->data); + sprintf(proc_lasat_ipbuf, "%d.%d.%d.%d", + (ip ) & 0xff, + (ip >> 8) & 0xff, + (ip >> 16) & 0xff, + (ip >> 24) & 0xff); + len = strlen(proc_lasat_ipbuf); + if (len > *lenp) + len = *lenp; + if (len) + if(copy_to_user(buffer, proc_lasat_ipbuf, len)) { + up(&lasat_info_sem); + return -EFAULT; + } + if (len < *lenp) { + if(put_user('\n', ((char *) buffer) + len)) { + up(&lasat_info_sem); + return -EFAULT; + } + len++; + } + *lenp = len; + filp->f_pos += len; + } + update_bcastaddr(); + up(&lasat_info_sem); + return 0; +} +#endif /* defined(CONFIG_INET) */ + +static int sysctl_lasat_eeprom_value(ctl_table *table, int *name, int nlen, + void *oldval, size_t *oldlenp, + void *newval, size_t newlen, + void **context) +{ + int r; + + down(&lasat_info_sem); + r = sysctl_intvec(table, name, nlen, oldval, oldlenp, newval, newlen, context); + if (r < 0) { + up(&lasat_info_sem); + return r; + } + + if (newval && newlen) + { + if (name && *name == LASAT_PRID) + lasat_board_info.li_eeprom_info.prid = *(int*)newval; + + lasat_write_eeprom_info(); + lasat_init_board_info(); + } + up(&lasat_info_sem); + + return 0; +} + +int proc_lasat_eeprom_value(ctl_table *table, int write, struct file *filp, + void *buffer, size_t *lenp) +{ + int r; + down(&lasat_info_sem); + r = proc_dointvec(table, write, filp, buffer, lenp); + if ( (!write) || r) { + up(&lasat_info_sem); + return r; + } + if (filp && filp->f_dentry) + { + if (!strcmp(filp->f_dentry->d_name.name, "prid")) + lasat_board_info.li_eeprom_info.prid = lasat_board_info.li_prid; + if (!strcmp(filp->f_dentry->d_name.name, "debugaccess")) + lasat_board_info.li_eeprom_info.debugaccess = lasat_board_info.li_debugaccess; + } + lasat_write_eeprom_info(); + up(&lasat_info_sem); + return 0; +} + +extern int lasat_boot_to_service; + +#ifdef CONFIG_SYSCTL + +static ctl_table lasat_table[] = { + {LASAT_CPU_HZ, "cpu-hz", &lasat_board_info.li_cpu_hz, sizeof(int), + 0444, NULL, &proc_dointvec, &sysctl_intvec}, + {LASAT_BUS_HZ, "bus-hz", &lasat_board_info.li_bus_hz, sizeof(int), + 0444, NULL, &proc_dointvec, &sysctl_intvec}, + {LASAT_MODEL, "bmid", &lasat_board_info.li_bmid, sizeof(int), + 0444, NULL, &proc_dointvec, &sysctl_intvec}, + {LASAT_PRID, "prid", &lasat_board_info.li_prid, sizeof(int), + 0644, NULL, &proc_lasat_eeprom_value, &sysctl_lasat_eeprom_value}, +#ifdef CONFIG_INET + {LASAT_IPADDR, "ipaddr", &lasat_board_info.li_eeprom_info.ipaddr, sizeof(int), + 0644, NULL, &proc_lasat_ip, &sysctl_lasat_intvec}, + {LASAT_NETMASK, "netmask", &lasat_board_info.li_eeprom_info.netmask, sizeof(int), + 0644, NULL, &proc_lasat_ip, &sysctl_lasat_intvec}, + {LASAT_BCAST, "bcastaddr", &lasat_bcastaddr, + sizeof(lasat_bcastaddr), 0600, NULL, + &proc_dostring, &sysctl_string}, +#endif + {LASAT_PASSWORD, "passwd_hash", &lasat_board_info.li_eeprom_info.passwd_hash, sizeof(lasat_board_info.li_eeprom_info.passwd_hash), + 0600, NULL, &proc_dolasatstring, &sysctl_lasatstring}, + {LASAT_SBOOT, "boot-service", &lasat_boot_to_service, sizeof(int), + 0644, NULL, &proc_dointvec, &sysctl_intvec}, +#ifdef CONFIG_DS1603 + {LASAT_RTC, "rtc", &rtctmp, sizeof(int), + 0644, NULL, &proc_dolasatrtc, &sysctl_lasat_rtc}, +#endif + {LASAT_NAMESTR, "namestr", &lasat_board_info.li_namestr, sizeof(lasat_board_info.li_namestr), + 0444, NULL, &proc_dostring, &sysctl_string}, + {LASAT_TYPESTR, "typestr", &lasat_board_info.li_typestr, sizeof(lasat_board_info.li_typestr), + 0444, NULL, &proc_dostring, &sysctl_string}, + {0} +}; + +#define CTL_LASAT 1 // CTL_ANY ??? +static ctl_table lasat_root_table[] = { + { CTL_LASAT, "lasat", NULL, 0, 0555, lasat_table }, + { 0 } +}; + +static int __init lasat_register_sysctl(void) +{ + struct ctl_table_header *lasat_table_header; + + lasat_table_header = + register_sysctl_table(lasat_root_table, 0); + + return 0; +} + +__initcall(lasat_register_sysctl); +#endif /* CONFIG_SYSCTL */ diff -Nru a/arch/mips/lasat/sysctl.h b/arch/mips/lasat/sysctl.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/lasat/sysctl.h Tue Jul 1 18:44:40 2003 @@ -0,0 +1,24 @@ +/* + * LASAT sysctl values + */ + +#ifndef _LASAT_SYSCTL_H +#define _LASAT_SYSCTL_H + +/* /proc/sys/lasat */ +enum { + LASAT_CPU_HZ=1, + LASAT_BUS_HZ, + LASAT_MODEL, + LASAT_PRID, + LASAT_IPADDR, + LASAT_NETMASK, + LASAT_BCAST, + LASAT_PASSWORD, + LASAT_SBOOT, + LASAT_RTC, + LASAT_NAMESTR, + LASAT_TYPESTR, +}; + +#endif /* _LASAT_SYSCTL_H */ diff -Nru a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile --- a/arch/mips/lib/Makefile Tue Jul 1 18:44:31 2003 +++ b/arch/mips/lib/Makefile Tue Jul 1 18:44:31 2003 @@ -2,19 +2,17 @@ # Makefile for MIPS-specific library files.. # -EXTRA_AFLAGS := $(CFLAGS) - -lib-y += csum_partial.o csum_partial_copy.o \ - rtc-std.o rtc-no.o memcpy.o memset.o \ - watch.o strlen_user.o strncpy_user.o \ - strnlen_user.o +lib-y += csum_partial.o csum_partial_copy.o memcpy.o \ + memset.o promlib.o rtc-std.o rtc-no.o strlen_user.o \ + strncpy_user.o strnlen_user.o watch.o -ifdef CONFIG_CPU_R3000 - lib-y += r3k_dump_tlb.o +ifeq ($(CONFIG_CPU_R3000)$(CONFIG_CPU_TX39XX),y) + lib-y += r3k_dump_tlb.o else - lib-y += dump_tlb.o + lib-y += dump_tlb.o endif lib-$(CONFIG_BLK_DEV_FD) += floppy-no.o floppy-std.o -lib-$(CONFIG_IDE) += ide-std.o ide-no.o -lib-$(CONFIG_PC_KEYB) += kbd-std.o kbd-no.o +lib-$(subst m,y,$(CONFIG_IDE)) += ide-std.o ide-no.o # needed for ide module + +EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips/lib/csum_partial.S b/arch/mips/lib/csum_partial.S --- a/arch/mips/lib/csum_partial.S Tue Jul 1 18:44:38 2003 +++ b/arch/mips/lib/csum_partial.S Tue Jul 1 18:44:38 2003 @@ -1,5 +1,4 @@ -/* $Id: csum_partial.S,v 1.1 1998/05/04 09:12:52 ralf Exp $ - * +/* * 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. diff -Nru a/arch/mips/lib/csum_partial_copy.c b/arch/mips/lib/csum_partial_copy.c --- a/arch/mips/lib/csum_partial_copy.c Tue Jul 1 18:44:39 2003 +++ b/arch/mips/lib/csum_partial_copy.c Tue Jul 1 18:44:39 2003 @@ -13,8 +13,6 @@ * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. - * - * $Id: csum_partial_copy.c,v 1.2 1998/09/19 19:16:17 ralf Exp $ */ #include #include @@ -25,8 +23,8 @@ /* * copy while checksumming, otherwise like csum_partial */ -unsigned int csum_partial_copy_nocheck(const char *src, char *dst, - int len, unsigned int sum) +unsigned int csum_partial_copy_nocheck(const char *src, char *dst, + int len, unsigned int sum) { /* * It's 2:30 am and I don't feel like doing it real ... @@ -43,8 +41,7 @@ * then zero the rest of the buffer. */ unsigned int csum_partial_copy_from_user (const char *src, char *dst, - int len, unsigned int sum, - int *err_ptr) + int len, unsigned int sum, int *err_ptr) { int missing; @@ -53,6 +50,6 @@ memset(dst + len - missing, 0, missing); *err_ptr = -EFAULT; } - + return csum_partial(dst, len, sum); } diff -Nru a/arch/mips/lib/dump_tlb.c b/arch/mips/lib/dump_tlb.c --- a/arch/mips/lib/dump_tlb.c Tue Jul 1 18:44:35 2003 +++ b/arch/mips/lib/dump_tlb.c Tue Jul 1 18:44:35 2003 @@ -4,31 +4,48 @@ * Copyright (C) 1994, 1995 by Waldorf Electronics, written by Ralf Baechle. * Copyright (C) 1999 by Silicon Graphics, Inc. */ +#include #include #include #include #include #include +#include #include #include #include #include -#define mips_tlb_entries 48 +static inline const char *msg2str(unsigned int mask) +{ + switch (mask) { + case PM_4K: return "4kb"; + case PM_16K: return "16kb"; + case PM_64K: return "64kb"; + case PM_256K: return "256kb"; +#ifndef CONFIG_CPU_VR41XX + case PM_1M: return "1Mb"; + case PM_4M: return "4Mb"; + case PM_16M: return "16Mb"; + case PM_64M: return "64Mb"; + case PM_256M: return "256Mb"; +#endif + } +} -void -dump_tlb(int first, int last) +void dump_tlb(int first, int last) { int i; unsigned int pagemask, c0, c1, asid; - unsigned long entryhi, entrylo0, entrylo1; + unsigned long long entrylo0, entrylo1; + unsigned long entryhi; - asid = get_entryhi() & 0xff; + asid = read_c0_entryhi() & 0xff; - for(i=first;i<=last;i++) - { - write_32bit_cp0_register(CP0_INDEX, i); + printk("\n"); + for(i=first;i<=last;i++) { + write_c0_index(i); __asm__ __volatile__( ".set\tmips3\n\t" ".set\tnoreorder\n\t" @@ -37,57 +54,53 @@ "nop;nop;nop;nop\n\t" ".set\treorder\n\t" ".set\tmips0\n\t"); - pagemask = read_32bit_cp0_register(CP0_PAGEMASK); - entryhi = read_32bit_cp0_register(CP0_ENTRYHI); - entrylo0 = read_32bit_cp0_register(CP0_ENTRYLO0); - entrylo1 = read_32bit_cp0_register(CP0_ENTRYLO1); + pagemask = read_c0_pagemask(); + entryhi = read_c0_entryhi(); + entrylo0 = read_c0_entrylo0(); + entrylo1 = read_c0_entrylo1(); - /* Unused entries have a virtual address of KSEG0. */ - if ((entryhi & 0xffffe000) != 0x80000000 + /* Unused entries have a virtual address in KSEG0. */ + if ((entryhi & 0xf0000000) != 0x80000000 && (entryhi & 0xff) == asid) { /* * Only print entries in use */ - printk("Index: %2d pgmask=%08x ", i, pagemask); + printk("Index: %2d pgmask=%s ", i, msg2str(pagemask)); c0 = (entrylo0 >> 3) & 7; c1 = (entrylo1 >> 3) & 7; - printk("va=%08lx asid=%08lx" - " [pa=%06lx c=%d d=%d v=%d g=%ld]" - " [pa=%06lx c=%d d=%d v=%d g=%ld]", - (entryhi & 0xffffe000), - entryhi & 0xff, - entrylo0 & PAGE_MASK, c0, + printk("va=%08lx asid=%02lx\n", + (entryhi & 0xffffe000), (entryhi & 0xff)); + printk("\t\t\t[pa=%08Lx c=%d d=%d v=%d g=%Ld]\n", + (entrylo0 << 6) & PAGE_MASK, c0, (entrylo0 & 4) ? 1 : 0, (entrylo0 & 2) ? 1 : 0, - (entrylo0 & 1), - entrylo1 & PAGE_MASK, c1, + (entrylo0 & 1)); + printk("\t\t\t[pa=%08Lx c=%d d=%d v=%d g=%Ld]\n", + (entrylo1 << 6) & PAGE_MASK, c1, (entrylo1 & 4) ? 1 : 0, (entrylo1 & 2) ? 1 : 0, (entrylo1 & 1)); - + printk("\n"); } } - printk("\n"); - set_entryhi(asid); + write_c0_entryhi(asid); } -void -dump_tlb_all(void) +void dump_tlb_all(void) { - dump_tlb(0, mips_tlb_entries - 1); + dump_tlb(0, current_cpu_data.tlbsize - 1); } -void -dump_tlb_wired(void) +void dump_tlb_wired(void) { int wired; - wired = read_32bit_cp0_register(CP0_WIRED); + wired = read_c0_wired(); printk("Wired: %d", wired); - dump_tlb(0, read_32bit_cp0_register(CP0_WIRED)); + dump_tlb(0, read_c0_wired()); } #define BARRIER \ @@ -103,14 +116,14 @@ int index; local_irq_save(flags); - oldpid = get_entryhi() & 0xff; + oldpid = read_c0_entryhi() & 0xff; BARRIER; - set_entryhi((addr & PAGE_MASK) | oldpid); + write_c0_entryhi((addr & PAGE_MASK) | oldpid); BARRIER; tlb_probe(); BARRIER; - index = get_index(); - set_entryhi(oldpid); + index = read_c0_index(); + write_c0_entryhi(oldpid); local_irq_restore(flags); if (index < 0) { @@ -125,7 +138,7 @@ void dump_tlb_nonwired(void) { - dump_tlb(read_32bit_cp0_register(CP0_WIRED), mips_tlb_entries - 1); + dump_tlb(read_c0_wired(), current_cpu_data.tlbsize - 1); } void @@ -140,12 +153,20 @@ addr = (unsigned int) address; printk("Addr == %08x\n", addr); - printk("tasks->mm.pgd == %08x\n", (unsigned int) t->mm->pgd); - - page_dir = pgd_offset(t->mm, 0); + printk("task == %8p\n", t); + printk("task->mm == %8p\n", t->mm); + //printk("tasks->mm.pgd == %08x\n", (unsigned int) t->mm->pgd); + + if (addr > KSEG0) + page_dir = pgd_offset_k(0); + else + page_dir = pgd_offset(t->mm, 0); printk("page_dir == %08x\n", (unsigned int) page_dir); - pgd = pgd_offset(t->mm, addr); + if (addr > KSEG0) + pgd = pgd_offset_k(addr); + else + pgd = pgd_offset(t->mm, addr); printk("pgd == %08x, ", (unsigned int) pgd); pmd = pmd_offset(pgd, addr); @@ -155,7 +176,11 @@ printk("pte == %08x, ", (unsigned int) pte); page = *pte; - printk("page == %08x\n", (unsigned int) pte_val(page)); +#ifdef CONFIG_64BIT_PHYS_ADDR + printk("page == %08Lx\n", pte_val(page)); +#else + printk("page == %08lx\n", pte_val(page)); +#endif val = pte_val(page); if (val & _PAGE_PRESENT) printk("present "); @@ -200,9 +225,7 @@ for(i=0;i<8;i++) { - printk("*%08lx == %08lx, ", - (unsigned long)p, (unsigned long)*p++); - printk("*%08lx == %08lx\n", - (unsigned long)p, (unsigned long)*p++); + printk("*%8p = %08lx, ", p, *p); p++; + printk("*%8p = %08lx\n", p, *p); p++; } } diff -Nru a/arch/mips/lib/floppy-no.c b/arch/mips/lib/floppy-no.c --- a/arch/mips/lib/floppy-no.c Tue Jul 1 18:44:37 2003 +++ b/arch/mips/lib/floppy-no.c Tue Jul 1 18:44:37 2003 @@ -1,5 +1,4 @@ -/* $Id: floppy-no.c,v 1.1 1998/05/07 18:38:32 ralf Exp $ - * +/* * 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. diff -Nru a/arch/mips/lib/floppy-std.c b/arch/mips/lib/floppy-std.c --- a/arch/mips/lib/floppy-std.c Tue Jul 1 18:44:36 2003 +++ b/arch/mips/lib/floppy-std.c Tue Jul 1 18:44:36 2003 @@ -1,5 +1,4 @@ -/* $Id: floppy-std.c,v 1.2 1999/01/04 16:03:51 ralf Exp $ - * +/* * 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. @@ -20,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -112,8 +110,8 @@ } static void std_fd_dma_mem_free(unsigned long addr, unsigned long size) -{ - free_pages(addr, get_order(size)); +{ + free_pages(addr, get_order(size)); } static unsigned long std_fd_drive_type(unsigned long n) diff -Nru a/arch/mips/lib/ide-no.c b/arch/mips/lib/ide-no.c --- a/arch/mips/lib/ide-no.c Tue Jul 1 18:44:34 2003 +++ b/arch/mips/lib/ide-no.c Tue Jul 1 18:44:34 2003 @@ -1,5 +1,4 @@ -/* $Id: ide-no.c,v 1.2 1998/06/30 00:21:54 ralf Exp $ - * +/* * 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. @@ -13,7 +12,6 @@ #include #include #include -#include static int no_ide_default_irq(ide_ioreg_t base) { diff -Nru a/arch/mips/lib/ide-std.c b/arch/mips/lib/ide-std.c --- a/arch/mips/lib/ide-std.c Tue Jul 1 18:44:35 2003 +++ b/arch/mips/lib/ide-std.c Tue Jul 1 18:44:35 2003 @@ -11,7 +11,6 @@ #include #include #include -#include #include static int std_ide_default_irq(ide_ioreg_t base) @@ -30,16 +29,11 @@ static ide_ioreg_t std_ide_default_io_base(int index) { - switch (index) { - case 0: return 0x1f0; - case 1: return 0x170; - case 2: return 0x1e8; - case 3: return 0x168; - case 4: return 0x1e0; - case 5: return 0x160; - default: - return 0; - } + static unsigned long ata_io_base[MAX_HWIFS] = { + 0x1f0, 0x170, 0x1e8, 0x168, 0x1e0, 0x160 + }; + + return ata_io_base[index]; } static void std_ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, diff -Nru a/arch/mips/lib/kbd-no.c b/arch/mips/lib/kbd-no.c --- a/arch/mips/lib/kbd-no.c Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,63 +0,0 @@ -/* $Id: kbd-no.c,v 1.1 1998/10/28 12:38:14 ralf Exp $ - * - * 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. - * - * Stub keyboard and psaux routines to keep Linux from crashing on machines - * without a keyboard. - * - * Copyright (C) 1998 by Ralf Baechle - */ -#include -#include - -static void no_kbd_request_region(void) -{ - /* No I/O ports are being used on the Indy. */ -} - -static int no_kbd_request_irq(void (*handler)(int, void *, struct pt_regs *)) -{ - return -ENODEV; -} - -static int no_aux_request_irq(void (*handler)(int, void *, struct pt_regs *)) -{ - return -ENODEV; -} - -static void no_aux_free_irq(void) -{ -} - -static unsigned char no_kbd_read_input(void) -{ - return 0; -} - -static void no_kbd_write_output(unsigned char val) -{ -} - -static void no_kbd_write_command(unsigned char val) -{ -} - -static unsigned char no_kbd_read_status(void) -{ - return 0; -} - -struct kbd_ops no_kbd_ops = { - no_kbd_request_region, - no_kbd_request_irq, - - no_aux_request_irq, - no_aux_free_irq, - - no_kbd_read_input, - no_kbd_write_output, - no_kbd_write_command, - no_kbd_read_status -}; diff -Nru a/arch/mips/lib/kbd-std.c b/arch/mips/lib/kbd-std.c --- a/arch/mips/lib/kbd-std.c Tue Jul 1 18:44:31 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,85 +0,0 @@ -/* $Id: kbd-std.c,v 1.2 1999/06/11 14:29:45 ralf Exp $ - * - * 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. - * - * Routines for standard PC style keyboards accessible via I/O ports. - * - * Copyright (C) 1998, 1999 by Ralf Baechle - */ -#include -#include -#include -#include -#include - -#define KEYBOARD_IRQ 1 -#define AUX_IRQ 12 - -static void std_kbd_request_region(void) -{ -#ifdef CONFIG_MIPS_ITE8172 - request_region(0x14000060, 16, "keyboard"); -#else - request_region(0x60, 16, "keyboard"); -#endif -} - -static int std_kbd_request_irq(void (*handler)(int, void *, struct pt_regs *)) -{ - return request_irq(KEYBOARD_IRQ, handler, 0, "keyboard", NULL); -} - -static int std_aux_request_irq(void (*handler)(int, void *, struct pt_regs *)) -{ - return request_irq(AUX_IRQ, handler, 0, "PS/2 Mouse", NULL); -} - -static void std_aux_free_irq(void) -{ - free_irq(AUX_IRQ, NULL); -} - -static unsigned char std_kbd_read_input(void) -{ - return inb(KBD_DATA_REG); -} - -static void std_kbd_write_output(unsigned char val) -{ - int status; - - do { - status = inb(KBD_CNTL_REG); - } while (status & KBD_STAT_IBF); - outb(val, KBD_DATA_REG); -} - -static void std_kbd_write_command(unsigned char val) -{ - int status; - - do { - status = inb(KBD_CNTL_REG); - } while (status & KBD_STAT_IBF); - outb(val, KBD_CNTL_REG); -} - -static unsigned char std_kbd_read_status(void) -{ - return inb(KBD_STATUS_REG); -} - -struct kbd_ops std_kbd_ops = { - std_kbd_request_region, - std_kbd_request_irq, - - std_aux_request_irq, - std_aux_free_irq, - - std_kbd_read_input, - std_kbd_write_output, - std_kbd_write_command, - std_kbd_read_status -}; diff -Nru a/arch/mips/lib/memcpy.S b/arch/mips/lib/memcpy.S --- a/arch/mips/lib/memcpy.S Tue Jul 1 18:44:35 2003 +++ b/arch/mips/lib/memcpy.S Tue Jul 1 18:44:35 2003 @@ -4,407 +4,468 @@ * for more details. * * Unified implementation of memcpy, memmove and the __copy_user backend. - * For __rmemcpy and memmove an exception is always a kernel bug, therefore - * they're not protected. In order to keep the exception fixup routine - * simple all memory accesses in __copy_user to src rsp. dst are stricly - * incremental. The fixup routine depends on $at not being changed. + * + * Copyright (C) 1998, 99, 2000, 01, 2002 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 1999, 2000, 01, 2002 Silicon Graphics, Inc. + * Copyright (C) 2002 Broadcom, Inc. + * memcpy/copy_user author: Mark Vandevoorde + * + * Mnemonic names for arguments to memcpy/__copy_user */ +#include #include #include #include +#define dst a0 +#define src a1 +#define len a2 + /* - * The fixup routine for copy_to_user depends on copying strictly in - * increasing order. Gas expands the ulw/usw macros in the wrong order for - * little endian machines, so we cannot depend on them. + * Spec + * + * memcpy copies len bytes from src to dst and sets v0 to dst. + * It assumes that + * - src and dst don't overlap + * - src is readable + * - dst is writable + * memcpy uses the standard calling convention + * + * __copy_user copies up to len bytes from src to dst and sets a2 (len) to + * the number of uncopied bytes due to an exception caused by a read or write. + * __copy_user assumes that src and dst don't overlap, and that the call is + * implementing one of the following: + * copy_to_user + * - src is readable (no exceptions when reading src) + * copy_from_user + * - dst is writable (no exceptions when writing dst) + * __copy_user uses a non-standard calling convention; see + * include/asm-mips/uaccess.h + * + * When an exception happens on a load, the handler must + # ensure that all of the destination buffer is overwritten to prevent + * leaking information to user mode programs. */ -#ifdef __MIPSEB__ -#define uswL swl -#define uswU swr -#define ulwL lwl -#define ulwU lwr -#endif -#ifdef __MIPSEL__ -#define uswL swr -#define uswU swl -#define ulwL lwr -#define ulwU lwl -#endif -#define EX(insn,reg,addr,handler) \ -9: insn reg, addr; \ - .section __ex_table,"a"; \ - PTR 9b, handler; \ - .previous +/* + * Implementation + */ + +/* + * The exception handler for loads requires that: + * 1- AT contain the address of the byte just past the end of the source + * of the copy, + * 2- src_entry <= src < AT, and + * 3- (dst - src) == (dst_entry - src_entry), + * The _entry suffix denotes values when __copy_user was called. + * + * (1) is set up up by uaccess.h and maintained by not writing AT in copy_user + * (2) is met by incrementing src by the number of bytes copied + * (3) is met by not doing loads between a pair of increments of dst and src + * + * The exception handlers for stores adjust len (if necessary) and return. + * These handlers do not need to overwrite any data. + * + * For __rmemcpy and memmove an exception is always a kernel bug, therefore + * they're not protected. + */ -#define UEX(insn,reg,addr,handler) \ -9: insn ## L reg, addr; \ -10: insn ## U reg, 3 + addr; \ - .section __ex_table,"a"; \ - PTR 9b, handler; \ - PTR 10b, handler; \ +#define EXC(inst_reg,addr,handler) \ +9: inst_reg, addr; \ + .section __ex_table,"a"; \ + PTR 9b, handler; \ .previous -/* ascending order, destination aligned */ -#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3) \ - EX(lw, t0, (offset + 0x00)(src), l_fixup); \ - EX(lw, t1, (offset + 0x04)(src), l_fixup); \ - EX(lw, t2, (offset + 0x08)(src), l_fixup); \ - EX(lw, t3, (offset + 0x0c)(src), l_fixup); \ - EX(sw, t0, (offset + 0x00)(dst), s_fixup); \ - EX(sw, t1, (offset + 0x04)(dst), s_fixup); \ - EX(sw, t2, (offset + 0x08)(dst), s_fixup); \ - EX(sw, t3, (offset + 0x0c)(dst), s_fixup); \ - EX(lw, t0, (offset + 0x10)(src), l_fixup); \ - EX(lw, t1, (offset + 0x14)(src), l_fixup); \ - EX(lw, t2, (offset + 0x18)(src), l_fixup); \ - EX(lw, t3, (offset + 0x1c)(src), l_fixup); \ - EX(sw, t0, (offset + 0x10)(dst), s_fixup); \ - EX(sw, t1, (offset + 0x14)(dst), s_fixup); \ - EX(sw, t2, (offset + 0x18)(dst), s_fixup); \ - EX(sw, t3, (offset + 0x1c)(dst), s_fixup) - -/* ascending order, destination unaligned */ -#define UMOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3) \ - EX(lw, t0, (offset + 0x00)(src), l_fixup); \ - EX(lw, t1, (offset + 0x04)(src), l_fixup); \ - EX(lw, t2, (offset + 0x08)(src), l_fixup); \ - EX(lw, t3, (offset + 0x0c)(src), l_fixup); \ - UEX(usw, t0, (offset + 0x00)(dst), s_fixup); \ - UEX(usw, t1, (offset + 0x04)(dst), s_fixup); \ - UEX(usw, t2, (offset + 0x08)(dst), s_fixup); \ - UEX(usw, t3, (offset + 0x0c)(dst), s_fixup); \ - EX(lw, t0, (offset + 0x10)(src), l_fixup); \ - EX(lw, t1, (offset + 0x14)(src), l_fixup); \ - EX(lw, t2, (offset + 0x18)(src), l_fixup); \ - EX(lw, t3, (offset + 0x1c)(src), l_fixup); \ - UEX(usw, t0, (offset + 0x10)(dst), s_fixup); \ - UEX(usw, t1, (offset + 0x14)(dst), s_fixup); \ - UEX(usw, t2, (offset + 0x18)(dst), s_fixup); \ - UEX(usw, t3, (offset + 0x1c)(dst), s_fixup) +/* + * Only on the 64-bit kernel we can made use of 64-bit registers. + */ +#ifdef CONFIG_MIPS64 +#define USE_DOUBLE +#endif + +#ifdef USE_DOUBLE + +#define LOAD ld +#define LOADL ldl +#define LOADR ldr +#define STOREL sdl +#define STORER sdr +#define STORE sd +#define ADD daddu +#define SUB dsubu +#define SRL dsrl +#define SRA dsra +#define SLL dsll +#define SLLV dsllv +#define SRLV dsrlv +#define NBYTES 8 +#define LOG_NBYTES 3 + +/* + * As we are sharing code base with the mips32 tree (which use the o32 ABI + * register definitions). We need to redefine the register definitions from + * the n64 ABI register naming to the o32 ABI register naming. + */ +#undef t0 +#undef t1 +#undef t2 +#undef t3 +#define t0 $8 +#define t1 $9 +#define t2 $10 +#define t3 $11 +#define t4 $12 +#define t5 $13 +#define t6 $14 +#define t7 $15 + +#else + +#define LOAD lw +#define LOADL lwl +#define LOADR lwr +#define STOREL swl +#define STORER swr +#define STORE sw +#define ADD addu +#define SUB subu +#define SRL srl +#define SLL sll +#define SRA sra +#define SLLV sllv +#define SRLV srlv +#define NBYTES 4 +#define LOG_NBYTES 2 + +#endif /* USE_DOUBLE */ + +#ifdef CONFIG_CPU_LITTLE_ENDIAN +#define LDFIRST LOADR +#define LDREST LOADL +#define STFIRST STORER +#define STREST STOREL +#define SHIFT_DISCARD SLLV +#else +#define LDFIRST LOADL +#define LDREST LOADR +#define STFIRST STOREL +#define STREST STORER +#define SHIFT_DISCARD SRLV +#endif + +#define FIRST(unit) ((unit)*NBYTES) +#define REST(unit) (FIRST(unit)+NBYTES-1) +#define UNIT(unit) FIRST(unit) + +#define ADDRMASK (NBYTES-1) .text .set noreorder .set noat +/* + * A combined memcpy/__copy_user + * __copy_user sets len to 0 for success; else to an upper bound of + * the number of uncopied bytes. + * memcpy sets v0 to dst. + */ .align 5 LEAF(memcpy) /* a0=dst a1=src a2=len */ - move v0, a0 /* return value */ + move v0, dst /* return value */ __memcpy: -EXPORT(__copy_user) - xor t0, a0, a1 - andi t0, t0, 0x3 - move t7, a0 - beqz t0, can_align - sltiu t8, a2, 0x8 - - b memcpy_u_src # bad alignment - move t2, a2 - -can_align: - bnez t8, small_memcpy # < 8 bytes to copy - move t2, a2 - - beqz a2, out - andi t8, a1, 0x1 - -hword_align: - beqz t8, word_align - andi t8, a1, 0x2 - - EX(lb, t0, (a1), l_fixup) - subu a2, a2, 0x1 - EX(sb, t0, (a0), s_fixup) - addu a1, a1, 0x1 - addu a0, a0, 0x1 - andi t8, a1, 0x2 - -word_align: - beqz t8, dword_align - sltiu t8, a2, 56 - - EX(lh, t0, (a1), l_fixup) - subu a2, a2, 0x2 - EX(sh, t0, (a0), s_fixup) - sltiu t8, a2, 56 - addu a0, a0, 0x2 - addu a1, a1, 0x2 - -dword_align: - bnez t8, do_end_words - move t8, a2 - - andi t8, a1, 0x4 - beqz t8, qword_align - andi t8, a1, 0x8 - - EX(lw, t0, 0x00(a1), l_fixup) - subu a2, a2, 0x4 - EX(sw, t0, 0x00(a0), s_fixup) - addu a1, a1, 0x4 - addu a0, a0, 0x4 - andi t8, a1, 0x8 - -qword_align: - beqz t8, oword_align - andi t8, a1, 0x10 - - EX(lw, t0, 0x00(a1), l_fixup) - EX(lw, t1, 0x04(a1), l_fixup) - subu a2, a2, 0x8 - EX(sw, t0, 0x00(a0), s_fixup) - EX(sw, t1, 0x04(a0), s_fixup) - addu a1, a1, 0x8 - andi t8, a1, 0x10 - addu a0, a0, 0x8 - -oword_align: - beqz t8, begin_movement - srl t8, a2, 0x7 - - EX(lw, t3, 0x00(a1), l_fixup) - EX(lw, t4, 0x04(a1), l_fixup) - EX(lw, t0, 0x08(a1), l_fixup) - EX(lw, t1, 0x0c(a1), l_fixup) - EX(sw, t3, 0x00(a0), s_fixup) - EX(sw, t4, 0x04(a0), s_fixup) - EX(sw, t0, 0x08(a0), s_fixup) - EX(sw, t1, 0x0c(a0), s_fixup) - subu a2, a2, 0x10 - addu a1, a1, 0x10 - srl t8, a2, 0x7 - addu a0, a0, 0x10 - -begin_movement: - beqz t8, 0f - andi t2, a2, 0x40 - -move_128bytes: - MOVE_BIGCHUNK(a1, a0, 0x00, t0, t1, t3, t4) - MOVE_BIGCHUNK(a1, a0, 0x20, t0, t1, t3, t4) - MOVE_BIGCHUNK(a1, a0, 0x40, t0, t1, t3, t4) - MOVE_BIGCHUNK(a1, a0, 0x60, t0, t1, t3, t4) - subu t8, t8, 0x01 - addu a1, a1, 0x80 - bnez t8, move_128bytes - addu a0, a0, 0x80 - -0: - beqz t2, 1f - andi t2, a2, 0x20 - -move_64bytes: - MOVE_BIGCHUNK(a1, a0, 0x00, t0, t1, t3, t4) - MOVE_BIGCHUNK(a1, a0, 0x20, t0, t1, t3, t4) - addu a1, a1, 0x40 - addu a0, a0, 0x40 - +FEXPORT(__copy_user) + /* + * Note: dst & src may be unaligned, len may be 0 + * Temps + */ +#define rem t8 + + /* + * The "issue break"s below are very approximate. + * Issue delays for dcache fills will perturb the schedule, as will + * load queue full replay traps, etc. + * + * If len < NBYTES use byte operations. + */ + PREF( 0, 0(src) ) + PREF( 1, 0(dst) ) + sltu t2, len, NBYTES + and t1, dst, ADDRMASK + PREF( 0, 1*32(src) ) + PREF( 1, 1*32(dst) ) + bnez t2, copy_bytes_checklen + and t0, src, ADDRMASK + PREF( 0, 2*32(src) ) + PREF( 1, 2*32(dst) ) + bnez t1, dst_unaligned + nop + bnez t0, src_unaligned_dst_aligned + /* + * use delay slot for fall-through + * src and dst are aligned; need to compute rem + */ +both_aligned: + SRL t0, len, LOG_NBYTES+3 # +3 for 8 units/iter + beqz t0, cleanup_both_aligned # len < 8*NBYTES + and rem, len, (8*NBYTES-1) # rem = len % (8*NBYTES) + PREF( 0, 3*32(src) ) + PREF( 1, 3*32(dst) ) + .align 4 1: - beqz t2, do_end_words - andi t8, a2, 0x1c - -move_32bytes: - MOVE_BIGCHUNK(a1, a0, 0x00, t0, t1, t3, t4) - andi t8, a2, 0x1c - addu a1, a1, 0x20 - addu a0, a0, 0x20 - -do_end_words: - beqz t8, maybe_end_cruft - srl t8, t8, 0x2 - -end_words: - EX(lw, t0, (a1), l_fixup) - subu t8, t8, 0x1 - EX(sw, t0, (a0), s_fixup) - addu a1, a1, 0x4 - bnez t8, end_words - addu a0, a0, 0x4 - -maybe_end_cruft: - andi t2, a2, 0x3 - -small_memcpy: - beqz t2, out - move a2, t2 - -end_bytes: - EX(lb, t0, (a1), l_fixup) - subu a2, a2, 0x1 - EX(sb, t0, (a0), s_fixup) - addu a1, a1, 0x1 - bnez a2, end_bytes - addu a0, a0, 0x1 - -out: jr ra - move a2, zero - -/* ------------------------------------------------------------------------- */ +EXC( LOAD t0, UNIT(0)(src), l_exc) +EXC( LOAD t1, UNIT(1)(src), l_exc_copy) +EXC( LOAD t2, UNIT(2)(src), l_exc_copy) +EXC( LOAD t3, UNIT(3)(src), l_exc_copy) + SUB len, len, 8*NBYTES +EXC( LOAD t4, UNIT(4)(src), l_exc_copy) +EXC( LOAD t7, UNIT(5)(src), l_exc_copy) +EXC( STORE t0, UNIT(0)(dst), s_exc_p8u) +EXC( STORE t1, UNIT(1)(dst), s_exc_p7u) +EXC( LOAD t0, UNIT(6)(src), l_exc_copy) +EXC( LOAD t1, UNIT(7)(src), l_exc_copy) + ADD src, src, 8*NBYTES + ADD dst, dst, 8*NBYTES +EXC( STORE t2, UNIT(-6)(dst), s_exc_p6u) +EXC( STORE t3, UNIT(-5)(dst), s_exc_p5u) +EXC( STORE t4, UNIT(-4)(dst), s_exc_p4u) +EXC( STORE t7, UNIT(-3)(dst), s_exc_p3u) +EXC( STORE t0, UNIT(-2)(dst), s_exc_p2u) +EXC( STORE t1, UNIT(-1)(dst), s_exc_p1u) + PREF( 0, 8*32(src) ) + PREF( 1, 8*32(dst) ) + bne len, rem, 1b + nop -/* Bad, bad. At least try to align the source */ + /* + * len == rem == the number of bytes left to copy < 8*NBYTES + */ +cleanup_both_aligned: + beqz len, done + sltu t0, len, 4*NBYTES + bnez t0, less_than_4units + and rem, len, (NBYTES-1) # rem = len % NBYTES + /* + * len >= 4*NBYTES + */ +EXC( LOAD t0, UNIT(0)(src), l_exc) +EXC( LOAD t1, UNIT(1)(src), l_exc_copy) +EXC( LOAD t2, UNIT(2)(src), l_exc_copy) +EXC( LOAD t3, UNIT(3)(src), l_exc_copy) + SUB len, len, 4*NBYTES + ADD src, src, 4*NBYTES +EXC( STORE t0, UNIT(0)(dst), s_exc_p4u) +EXC( STORE t1, UNIT(1)(dst), s_exc_p3u) +EXC( STORE t2, UNIT(2)(dst), s_exc_p2u) +EXC( STORE t3, UNIT(3)(dst), s_exc_p1u) + beqz len, done + ADD dst, dst, 4*NBYTES +less_than_4units: + /* + * rem = len % NBYTES + */ + beq rem, len, copy_bytes + nop +1: +EXC( LOAD t0, 0(src), l_exc) + ADD src, src, NBYTES + SUB len, len, NBYTES +EXC( STORE t0, 0(dst), s_exc_p1u) + bne rem, len, 1b + ADD dst, dst, NBYTES + + /* + * src and dst are aligned, need to copy rem bytes (rem < NBYTES) + * A loop would do only a byte at a time with possible branch + * mispredicts. Can't do an explicit LOAD dst,mask,or,STORE + * because can't assume read-access to dst. Instead, use + * STREST dst, which doesn't require read access to dst. + * + * This code should perform better than a simple loop on modern, + * wide-issue mips processors because the code has fewer branches and + * more instruction-level parallelism. + */ +#define bits t2 + beqz len, done + ADD t1, dst, len # t1 is just past last byte of dst + li bits, 8*NBYTES + SLL rem, len, 3 # rem = number of bits to keep +EXC( LOAD t0, 0(src), l_exc) + SUB bits, bits, rem # bits = number of bits to discard + SHIFT_DISCARD t0, t0, bits +EXC( STREST t0, -1(t1), s_exc) + jr ra + move len, zero +dst_unaligned: + /* + * dst is unaligned + * t0 = src & ADDRMASK + * t1 = dst & ADDRMASK; T1 > 0 + * len >= NBYTES + * + * Copy enough bytes to align dst + * Set match = (src and dst have same alignment) + */ +#define match rem +EXC( LDFIRST t3, FIRST(0)(src), l_exc) + ADD t2, zero, NBYTES +EXC( LDREST t3, REST(0)(src), l_exc_copy) + SUB t2, t2, t1 # t2 = number of bytes copied + xor match, t0, t1 +EXC( STFIRST t3, FIRST(0)(dst), s_exc) + beq len, t2, done + SUB len, len, t2 + ADD dst, dst, t2 + beqz match, both_aligned + ADD src, src, t2 + +src_unaligned_dst_aligned: + SRL t0, len, LOG_NBYTES+2 # +2 for 4 units/iter + PREF( 0, 3*32(src) ) + beqz t0, cleanup_src_unaligned + and rem, len, (4*NBYTES-1) # rem = len % 4*NBYTES + PREF( 1, 3*32(dst) ) +1: +/* + * Avoid consecutive LD*'s to the same register since some mips + * implementations can't issue them in the same cycle. + * It's OK to load FIRST(N+1) before REST(N) because the two addresses + * are to the same unit (unless src is aligned, but it's not). + */ +EXC( LDFIRST t0, FIRST(0)(src), l_exc) +EXC( LDFIRST t1, FIRST(1)(src), l_exc_copy) + SUB len, len, 4*NBYTES +EXC( LDREST t0, REST(0)(src), l_exc_copy) +EXC( LDREST t1, REST(1)(src), l_exc_copy) +EXC( LDFIRST t2, FIRST(2)(src), l_exc_copy) +EXC( LDFIRST t3, FIRST(3)(src), l_exc_copy) +EXC( LDREST t2, REST(2)(src), l_exc_copy) +EXC( LDREST t3, REST(3)(src), l_exc_copy) + PREF( 0, 9*32(src) ) # 0 is PREF_LOAD (not streamed) + ADD src, src, 4*NBYTES +#ifdef CONFIG_CPU_SB1 + nop # improves slotting +#endif +EXC( STORE t0, UNIT(0)(dst), s_exc_p4u) +EXC( STORE t1, UNIT(1)(dst), s_exc_p3u) +EXC( STORE t2, UNIT(2)(dst), s_exc_p2u) +EXC( STORE t3, UNIT(3)(dst), s_exc_p1u) + PREF( 1, 9*32(dst) ) # 1 is PREF_STORE (not streamed) + bne len, rem, 1b + ADD dst, dst, 4*NBYTES + +cleanup_src_unaligned: + beqz len, done + and rem, len, NBYTES-1 # rem = len % NBYTES + beq rem, len, copy_bytes + nop +1: +EXC( LDFIRST t0, FIRST(0)(src), l_exc) +EXC( LDREST t0, REST(0)(src), l_exc_copy) + ADD src, src, NBYTES + SUB len, len, NBYTES +EXC( STORE t0, 0(dst), s_exc_p1u) + bne len, rem, 1b + ADD dst, dst, NBYTES -memcpy_u_src: - bnez t8, small_memcpy # < 8 bytes? - move t2, a2 - - addiu t0, a1, 7 # t0: how much to align - ori t0, 7 - xori t0, 7 - subu t0, a1 - - UEX(ulw, t1, 0(a1), l_fixup) # dword alignment - UEX(ulw, t2, 4(a1), l_fixup) - UEX(usw, t1, 0(a0), s_fixup) - UEX(usw, t2, 4(a0), s_fixup) - - addu a1, t0 # src - addu a0, t0 # dst - subu a2, t0 # len - - sltiu t8, a2, 56 - bnez t8, u_do_end_words - andi t8, a2, 0x3c - - andi t8, a1, 8 # now qword aligned? - -u_qword_align: - beqz t8, u_oword_align - andi t8, a1, 0x10 - - EX(lw, t0, 0x00(a1), l_fixup) - EX(lw, t1, 0x04(a1), l_fixup) - subu a2, a2, 0x8 - UEX(usw, t0, 0x00(a0), s_fixup) - UEX(usw, t1, 0x04(a0), s_fixup) - addu a1, a1, 0x8 - andi t8, a1, 0x10 - addu a0, a0, 0x8 - -u_oword_align: - beqz t8, u_begin_movement - srl t8, a2, 0x7 - - EX(lw, t3, 0x08(a1), l_fixup) - EX(lw, t4, 0x0c(a1), l_fixup) - EX(lw, t0, 0x00(a1), l_fixup) - EX(lw, t1, 0x04(a1), l_fixup) - UEX(usw, t3, 0x08(a0), s_fixup) - UEX(usw, t4, 0x0c(a0), s_fixup) - UEX(usw, t0, 0x00(a0), s_fixup) - UEX(usw, t1, 0x04(a0), s_fixup) - subu a2, a2, 0x10 - addu a1, a1, 0x10 - srl t8, a2, 0x7 - addu a0, a0, 0x10 - -u_begin_movement: - beqz t8, 0f - andi t2, a2, 0x40 - -u_move_128bytes: - UMOVE_BIGCHUNK(a1, a0, 0x00, t0, t1, t3, t4) - UMOVE_BIGCHUNK(a1, a0, 0x20, t0, t1, t3, t4) - UMOVE_BIGCHUNK(a1, a0, 0x40, t0, t1, t3, t4) - UMOVE_BIGCHUNK(a1, a0, 0x60, t0, t1, t3, t4) - subu t8, t8, 0x01 - addu a1, a1, 0x80 - bnez t8, u_move_128bytes - addu a0, a0, 0x80 - -0: - beqz t2, 1f - andi t2, a2, 0x20 - -u_move_64bytes: - UMOVE_BIGCHUNK(a1, a0, 0x00, t0, t1, t3, t4) - UMOVE_BIGCHUNK(a1, a0, 0x20, t0, t1, t3, t4) - addu a1, a1, 0x40 - addu a0, a0, 0x40 +copy_bytes_checklen: + beqz len, done + nop +copy_bytes: + /* 0 < len < NBYTES */ +#define COPY_BYTE(N) \ +EXC( lb t0, N(src), l_exc); \ + SUB len, len, 1; \ + beqz len, done; \ +EXC( sb t0, N(dst), s_exc_p1) + + COPY_BYTE(0) + COPY_BYTE(1) +#ifdef USE_DOUBLE + COPY_BYTE(2) + COPY_BYTE(3) + COPY_BYTE(4) + COPY_BYTE(5) +#endif +EXC( lb t0, NBYTES-2(src), l_exc) + SUB len, len, 1 + jr ra +EXC( sb t0, NBYTES-2(dst), s_exc_p1) +done: + jr ra + nop + END(memcpy) +l_exc_copy: + /* + * Copy bytes from src until faulting load address (or until a + * lb faults) + * + * When reached by a faulting LDFIRST/LDREST, THREAD_BUADDR($28) + * may be more than a byte beyond the last address. + * Hence, the lb below may get an exception. + * + * Assumes src < THREAD_BUADDR($28) + */ + LOAD t0, TI_TASK($28) + LOAD t0, THREAD_BUADDR(t0) 1: - beqz t2, u_do_end_words - andi t8, a2, 0x1c +EXC( lb t1, 0(src), l_exc) + ADD src, src, 1 + sb t1, 0(dst) # can't fault -- we're copy_from_user + bne src, t0, 1b + ADD dst, dst, 1 +l_exc: + LOAD t0, THREAD_BUADDR($28) # t0 is just past last good address + LOAD t0, THREAD_BUADDR(t0) + nop + SUB len, AT, t0 # len number of uncopied bytes + /* + * Here's where we rely on src and dst being incremented in tandem, + * See (3) above. + * dst += (fault addr - src) to put dst at first byte to clear + */ + ADD dst, t0 # compute start address in a1 + SUB dst, src + /* + * Clear len bytes starting at dst. Can't call __bzero because it + * might modify len. An inefficient loop for these rare times... + */ + beqz len, done + SUB src, len, 1 +1: sb zero, 0(dst) + ADD dst, dst, 1 + bnez src, 1b + SUB src, src, 1 + jr ra + nop -u_move_32bytes: - UMOVE_BIGCHUNK(a1, a0, 0x00, t0, t1, t3, t4) - andi t8, a2, 0x1c - addu a1, a1, 0x20 - addu a0, a0, 0x20 - -u_do_end_words: - beqz t8, u_maybe_end_cruft - srl t8, t8, 0x2 - -u_end_words: - EX(lw, t0, 0x00(a1), l_fixup) - subu t8, t8, 0x1 - UEX(usw, t0, 0x00(a0), s_fixup) - addu a1, a1, 0x4 - bnez t8, u_end_words - addu a0, a0, 0x4 - -u_maybe_end_cruft: - andi t2, a2, 0x3 - -u_cannot_optimize: - beqz t2, out - move a2, t2 - -u_end_bytes: - EX(lb, t0, (a1), l_fixup) - subu a2, a2, 0x1 - EX(sb, t0, (a0), s_fixup) - addu a1, a1, 0x1 - bnez a2, u_end_bytes - addu a0, a0, 0x1 - jr ra - move a2, zero - END(memcpy) +#define SEXC(n) \ +s_exc_p ## n ## u: \ + jr ra; \ + ADD len, len, n*NBYTES + +SEXC(8) +SEXC(7) +SEXC(6) +SEXC(5) +SEXC(4) +SEXC(3) +SEXC(2) +SEXC(1) -/* descending order, destination aligned */ -#define RMOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3) \ - lw t0, (offset + 0x10)(src); \ - lw t1, (offset + 0x14)(src); \ - lw t2, (offset + 0x18)(src); \ - lw t3, (offset + 0x1c)(src); \ - sw t0, (offset + 0x10)(dst); \ - sw t1, (offset + 0x14)(dst); \ - sw t2, (offset + 0x18)(dst); \ - sw t3, (offset + 0x1c)(dst); \ - lw t0, (offset + 0x00)(src); \ - lw t1, (offset + 0x04)(src); \ - lw t2, (offset + 0x08)(src); \ - lw t3, (offset + 0x0c)(src); \ - sw t0, (offset + 0x00)(dst); \ - sw t1, (offset + 0x04)(dst); \ - sw t2, (offset + 0x08)(dst); \ - sw t3, (offset + 0x0c)(dst) - -/* descending order, destination ununaligned */ -#define RUMOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3) \ - lw t0, (offset + 0x10)(src); \ - lw t1, (offset + 0x14)(src); \ - lw t2, (offset + 0x18)(src); \ - lw t3, (offset + 0x1c)(src); \ - usw t0, (offset + 0x10)(dst); \ - usw t1, (offset + 0x14)(dst); \ - usw t2, (offset + 0x18)(dst); \ - usw t3, (offset + 0x1c)(dst); \ - lw t0, (offset + 0x00)(src); \ - lw t1, (offset + 0x04)(src); \ - lw t2, (offset + 0x08)(src); \ - lw t3, (offset + 0x0c)(src); \ - usw t0, (offset + 0x00)(dst); \ - usw t1, (offset + 0x04)(dst); \ - usw t2, (offset + 0x08)(dst); \ - usw t3, (offset + 0x0c)(dst) +s_exc_p1: + jr ra + ADD len, len, 1 +s_exc: + jr ra + nop .align 5 LEAF(memmove) - addu t0, a0, a2 + ADD t0, a0, a2 + ADD t1, a1, a2 sltu t0, a1, t0 # dst + len <= src -> memcpy - addu t1, a1, a2 sltu t1, a0, t1 # dst >= src + len -> memcpy and t0, t1 beqz t0, __memcpy @@ -412,159 +473,21 @@ beqz a2, r_out END(memmove) + /* fall through to __rmemcpy */ LEAF(__rmemcpy) /* a0=dst a1=src a2=len */ - sltu t0, a1, a0 + sltu t0, a1, a0 beqz t0, r_end_bytes_up # src >= dst nop - addu a0, a2 # dst = dst + len - addu a1, a2 # src = src + len - -#if 0 /* Horror fix */ - xor t0, a0, a1 - andi t0, t0, 0x3 - move t7, a0 - beqz t0, r_can_align - sltiu t8, a2, 0x8 - - b r_memcpy_u_src # bad alignment - move t2, a2 - -r_can_align: - bnez t8, r_small_memcpy # < 8 bytes to copy - move t2, a2 - - beqz a2, r_out - andi t8, a1, 0x1 - -r_hword_align: - beqz t8, r_word_align - andi t8, a1, 0x2 - - lb t0, -1(a1) - subu a2, a2, 0x1 - sb t0, -1(a0) - subu a1, a1, 0x1 - subu a0, a0, 0x1 - andi t8, a1, 0x2 - -r_word_align: - beqz t8, r_dword_align - sltiu t8, a2, 56 - - lh t0, -2(a1) - subu a2, a2, 0x2 - sh t0, -2(a0) - sltiu t8, a2, 56 - subu a0, a0, 0x2 - subu a1, a1, 0x2 - -r_dword_align: - bnez t8, r_do_end_words - move t8, a2 - - andi t8, a1, 0x4 - beqz t8, r_qword_align - andi t8, a1, 0x8 - - lw t0, -4(a1) - subu a2, a2, 0x4 - sw t0, -4(a0) - subu a1, a1, 0x4 - subu a0, a0, 0x4 - andi t8, a1, 0x8 - -r_qword_align: - beqz t8, r_oword_align - andi t8, a1, 0x10 - - subu a1, a1, 0x8 - lw t0, 0x04(a1) - lw t1, 0x00(a1) - subu a0, a0, 0x8 - sw t0, 0x04(a0) - sw t1, 0x00(a0) - subu a2, a2, 0x8 - - andi t8, a1, 0x10 - -r_oword_align: - beqz t8, r_begin_movement - srl t8, a2, 0x7 - - subu a1, a1, 0x10 - lw t3, 0x08(a1) # assumes subblock ordering - lw t4, 0x0c(a1) - lw t0, 0x00(a1) - lw t1, 0x04(a1) - subu a0, a0, 0x10 - sw t3, 0x08(a0) - sw t4, 0x0c(a0) - sw t0, 0x00(a0) - sw t1, 0x04(a0) - subu a2, a2, 0x10 - srl t8, a2, 0x7 - -r_begin_movement: - beqz t8, 0f - andi t2, a2, 0x40 - -r_move_128bytes: - RMOVE_BIGCHUNK(a1, a0, -0x80, t0, t1, t3, t4) - RMOVE_BIGCHUNK(a1, a0, -0x60, t0, t1, t3, t4) - RMOVE_BIGCHUNK(a1, a0, -0x40, t0, t1, t3, t4) - RMOVE_BIGCHUNK(a1, a0, -0x20, t0, t1, t3, t4) - subu t8, t8, 0x01 - subu a1, a1, 0x80 - bnez t8, r_move_128bytes - subu a0, a0, 0x80 - -0: - beqz t2, 1f - andi t2, a2, 0x20 - -r_move_64bytes: - subu a1, a1, 0x40 - subu a0, a0, 0x40 - RMOVE_BIGCHUNK(a1, a0, 0x20, t0, t1, t3, t4) - RMOVE_BIGCHUNK(a1, a0, 0x00, t0, t1, t3, t4) - -1: - beqz t2, r_do_end_words - andi t8, a2, 0x1c - -r_move_32bytes: - subu a1, a1, 0x20 - subu a0, a0, 0x20 - RMOVE_BIGCHUNK(a1, a0, 0x00, t0, t1, t3, t4) - andi t8, a2, 0x1c - -r_do_end_words: - beqz t8, r_maybe_end_cruft - srl t8, t8, 0x2 - -r_end_words: - lw t0, -4(a1) - subu t8, t8, 0x1 - sw t0, -4(a0) - subu a1, a1, 0x4 - bnez t8, r_end_words - subu a0, a0, 0x4 - -r_maybe_end_cruft: - andi t2, a2, 0x3 - -r_small_memcpy: - beqz t2, r_out - move a2, t2 -#endif /* Horror fix */ + ADD a0, a2 # dst = dst + len + ADD a1, a2 # src = src + len r_end_bytes: lb t0, -1(a1) - subu a2, a2, 0x1 + SUB a2, a2, 0x1 sb t0, -1(a0) - subu a1, a1, 0x1 + SUB a1, a1, 0x1 bnez a2, r_end_bytes - subu a0, a0, 0x1 + SUB a0, a0, 0x1 r_out: jr ra @@ -572,148 +495,12 @@ r_end_bytes_up: lb t0, (a1) - subu a2, a2, 0x1 + SUB a2, a2, 0x1 sb t0, (a0) - addu a1, a1, 0x1 + ADD a1, a1, 0x1 bnez a2, r_end_bytes_up - addu a0, a0, 0x1 + ADD a0, a0, 0x1 jr ra move a2, zero - -#if 0 /* Horror fix */ -/* ------------------------------------------------------------------------- */ - -/* Bad, bad. At least try to align the source */ - -r_memcpy_u_src: - bnez t8, r_small_memcpy # < 8 bytes? - move t2, a2 - - andi t0, a1, 7 # t0: how much to align - - ulw t1, -8(a1) # dword alignment - ulw t2, -4(a1) - usw t1, -8(a0) - usw t2, -4(a0) - - subu a1, t0 # src - subu a0, t0 # dst - subu a2, t0 # len - - sltiu t8, a2, 56 - bnez t8, ru_do_end_words - andi t8, a2, 0x3c - - andi t8, a1, 8 # now qword aligned? - -ru_qword_align: - beqz t8, ru_oword_align - andi t8, a1, 0x10 - - subu a1, a1, 0x8 - lw t0, 0x00(a1) - lw t1, 0x04(a1) - subu a0, a0, 0x8 - usw t0, 0x00(a0) - usw t1, 0x04(a0) - subu a2, a2, 0x8 - - andi t8, a1, 0x10 - -ru_oword_align: - beqz t8, ru_begin_movement - srl t8, a2, 0x7 - - subu a1, a1, 0x10 - lw t3, 0x08(a1) # assumes subblock ordering - lw t4, 0x0c(a1) - lw t0, 0x00(a1) - lw t1, 0x04(a1) - subu a0, a0, 0x10 - usw t3, 0x08(a0) - usw t4, 0x0c(a0) - usw t0, 0x00(a0) - usw t1, 0x04(a0) - subu a2, a2, 0x10 - - srl t8, a2, 0x7 - -ru_begin_movement: - beqz t8, 0f - andi t2, a2, 0x40 - -ru_move_128bytes: - RUMOVE_BIGCHUNK(a1, a0, -0x80, t0, t1, t3, t4) - RUMOVE_BIGCHUNK(a1, a0, -0x60, t0, t1, t3, t4) - RUMOVE_BIGCHUNK(a1, a0, -0x40, t0, t1, t3, t4) - RUMOVE_BIGCHUNK(a1, a0, -0x20, t0, t1, t3, t4) - subu t8, t8, 0x01 - subu a1, a1, 0x80 - bnez t8, ru_move_128bytes - subu a0, a0, 0x80 - -0: - beqz t2, 1f - andi t2, a2, 0x20 - -ru_move_64bytes: - subu a1, a1, 0x40 - subu a0, a0, 0x40 - RUMOVE_BIGCHUNK(a1, a0, 0x20, t0, t1, t3, t4) - RUMOVE_BIGCHUNK(a1, a0, 0x00, t0, t1, t3, t4) - -1: - beqz t2, ru_do_end_words - andi t8, a2, 0x1c - -ru_move_32bytes: - subu a1, a1, 0x20 - subu a0, a0, 0x20 - RUMOVE_BIGCHUNK(a1, a0, 0x00, t0, t1, t3, t4) - andi t8, a2, 0x1c - -ru_do_end_words: - beqz t8, ru_maybe_end_cruft - srl t8, t8, 0x2 - -ru_end_words: - lw t0, -4(a1) - usw t0, -4(a0) - subu t8, t8, 0x1 - subu a1, a1, 0x4 - bnez t8, ru_end_words - subu a0, a0, 0x4 - -ru_maybe_end_cruft: - andi t2, a2, 0x3 - -ru_cannot_optimize: - beqz t2, r_out - move a2, t2 - -ru_end_bytes: - lb t0, -1(a1) - subu a2, a2, 0x1 - sb t0, -1(a0) - subu a1, a1, 0x1 - bnez a2, ru_end_bytes - subu a0, a0, 0x1 - - jr ra - move a2, zero -#endif /* Horror fix */ END(__rmemcpy) - -l_fixup: # clear the rest of the buffer - lw t0, THREAD_BUADDR($28) - nop - subu a2, AT, t0 # a2 bytes to go - addu a0, t0 # compute start address in a1 - subu a0, a1 - j __bzero - move a1, zero - -s_fixup: - jr ra - nop diff -Nru a/arch/mips/lib/memset.S b/arch/mips/lib/memset.S --- a/arch/mips/lib/memset.S Tue Jul 1 18:44:39 2003 +++ b/arch/mips/lib/memset.S Tue Jul 1 18:44:39 2003 @@ -54,7 +54,6 @@ 1: EXPORT(__bzero) - .type __bzero, @function sltiu t0, a2, 4 /* very small region? */ bnez t0, small_memset andi t0, a0, 3 /* aligned? */ @@ -84,13 +83,17 @@ .set noreorder memset_partial: - la t1, 2f /* where to start */ + PTR_LA t1, 2f /* where to start */ subu t1, t0 jr t1 addu a0, t0 /* dest ptr */ + .set push + .set noreorder + .set nomacro F_FILL64(a0, -64, a1, partial_fixup) /* ... but first do wrds ... */ -2: andi a2, 3 /* 0 <= n <= 3 to go */ +2: .set pop + andi a2, 3 /* 0 <= n <= 3 to go */ beqz a2, 1f addu a0, a2 /* What's left */ @@ -120,14 +123,16 @@ nop fwd_fixup: - lw t0, THREAD_BUADDR($28) + lw t0, TI_TASK($28) + lw t0, THREAD_BUADDR(t0) andi a2, 0x3f addu a2, t1 jr ra subu a2, t0 partial_fixup: - lw t0, THREAD_BUADDR($28) + lw t0, TI_TASK($28) + lw t0, THREAD_BUADDR(t0) andi a2, 3 addu a2, t1 jr ra diff -Nru a/arch/mips/lib/promlib.c b/arch/mips/lib/promlib.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/lib/promlib.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,24 @@ +#include +#include + +extern void prom_putchar(char); + +void prom_printf(char *fmt, ...) +{ + va_list args; + char ppbuf[1024]; + char *bptr; + + va_start(args, fmt); + vsprintf(ppbuf, fmt, args); + + bptr = ppbuf; + + while (*bptr != 0) { + if (*bptr == '\n') + prom_putchar('\r'); + + prom_putchar(*bptr++); + } + va_end(args); +} diff -Nru a/arch/mips/lib/r3k_dump_tlb.c b/arch/mips/lib/r3k_dump_tlb.c --- a/arch/mips/lib/r3k_dump_tlb.c Tue Jul 1 18:44:32 2003 +++ b/arch/mips/lib/r3k_dump_tlb.c Tue Jul 1 18:44:32 2003 @@ -12,11 +12,12 @@ #include #include +#include #include #include #include -#define mips_tlb_entries 64 +extern int r3k_have_wired_reg; /* defined in tlb-r3k.c */ void dump_tlb(int first, int last) @@ -25,18 +26,18 @@ unsigned int asid; unsigned long entryhi, entrylo0; - asid = get_entryhi() & 0xfc0; + asid = read_c0_entryhi() & 0xfc0; for(i=first;i<=last;i++) { - write_32bit_cp0_register(CP0_INDEX, i<<8); + write_c0_index(i<<8); __asm__ __volatile__( ".set\tnoreorder\n\t" "tlbr\n\t" "nop\n\t" ".set\treorder"); - entryhi = read_32bit_cp0_register(CP0_ENTRYHI); - entrylo0 = read_32bit_cp0_register(CP0_ENTRYLO0); + entryhi = read_c0_entryhi(); + entrylo0 = read_c0_entrylo0(); /* Unused entries have a virtual address of KSEG0. */ if ((entryhi & 0xffffe000) != 0x80000000 @@ -59,22 +60,22 @@ } printk("\n"); - set_entryhi(asid); + write_c0_entryhi(asid); } void dump_tlb_all(void) { - dump_tlb(0, mips_tlb_entries - 1); + dump_tlb(0, current_cpu_data.tlbsize - 1); } void dump_tlb_wired(void) { - int wired = 7; + int wired = r3k_have_wired_reg ? read_c0_wired() : 8; printk("Wired: %d", wired); - dump_tlb(0, read_32bit_cp0_register(CP0_WIRED)); + dump_tlb(0, wired - 1); } void @@ -84,11 +85,11 @@ int index; local_irq_save(flags); - oldpid = get_entryhi() & 0xff; - set_entryhi((addr & PAGE_MASK) | oldpid); + oldpid = read_c0_entryhi() & 0xff; + write_c0_entryhi((addr & PAGE_MASK) | oldpid); tlb_probe(); - index = get_index(); - set_entryhi(oldpid); + index = read_c0_index(); + write_c0_entryhi(oldpid); local_irq_restore(flags); if (index < 0) { @@ -103,7 +104,8 @@ void dump_tlb_nonwired(void) { - dump_tlb(8, mips_tlb_entries - 1); + int wired = r3k_have_wired_reg ? read_c0_wired() : 8; + dump_tlb(wired, current_cpu_data.tlbsize - 1); } void diff -Nru a/arch/mips/lib/strlen_user.S b/arch/mips/lib/strlen_user.S --- a/arch/mips/lib/strlen_user.S Tue Jul 1 18:44:38 2003 +++ b/arch/mips/lib/strlen_user.S Tue Jul 1 18:44:38 2003 @@ -1,5 +1,4 @@ -/* $Id: strlen_user.S,v 1.3 1999/08/21 22:19:11 ralf Exp $ - * +/* * 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. @@ -24,22 +23,18 @@ * Return 0 for error */ LEAF(__strlen_user_asm) - lw v0, THREAD_CURDS($28) # pointer ok? + lw v0, TI_ADDR_LIMIT($28) # pointer ok? and v0, a0 bltz v0, fault -EXPORT(__strlen_user_nocheck_asm) +FEXPORT(__strlen_user_nocheck_asm) move v0, a0 1: EX(lb, t0, (v0), fault) addiu v0, 1 bnez t0, 1b subu v0, a0 jr ra - END(__strlen_user_nocheck_asm) - - .section __ex_table,"a" - PTR 1b, fault - .previous + END(__strlen_user_asm) fault: move v0, zero jr ra diff -Nru a/arch/mips/lib/strncpy_user.S b/arch/mips/lib/strncpy_user.S --- a/arch/mips/lib/strncpy_user.S Tue Jul 1 18:44:36 2003 +++ b/arch/mips/lib/strncpy_user.S Tue Jul 1 18:44:36 2003 @@ -1,5 +1,4 @@ -/* $Id: strncpy_user.S,v 1.3 1999/08/21 22:19:11 ralf Exp $ - * +/* * 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. @@ -29,7 +28,7 @@ */ LEAF(__strncpy_from_user_asm) - lw v0, THREAD_CURDS($28) # pointer ok? + lw v0, TI_ADDR_LIMIT($28) # pointer ok? and v0, a1 bltz v0, fault diff -Nru a/arch/mips/lib/strnlen_user.S b/arch/mips/lib/strnlen_user.S --- a/arch/mips/lib/strnlen_user.S Tue Jul 1 18:44:37 2003 +++ b/arch/mips/lib/strnlen_user.S Tue Jul 1 18:44:37 2003 @@ -1,5 +1,4 @@ -/* $Id: strnlen_user.S,v 1.2 1999/11/19 20:35:21 ralf Exp $ - * +/* * 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. @@ -28,11 +27,11 @@ * bytes. There's nothing secret there ... */ LEAF(__strnlen_user_asm) - lw v0, THREAD_CURDS($28) # pointer ok? + lw v0, TI_ADDR_LIMIT($28) # pointer ok? and v0, a0 bltz v0, fault -EXPORT(__strnlen_user_nocheck_asm) +FEXPORT(__strnlen_user_nocheck_asm) .type __strnlen_user_nocheck_asm,@function move v0, a0 addu a1, a0 # stop pointer @@ -45,10 +44,6 @@ 1: subu v0, a0 jr ra END(__strnlen_user_asm) - - .section __ex_table,"a" - PTR 1b, fault - .previous fault: move v0, zero jr ra diff -Nru a/arch/mips/lib/tinycon.c b/arch/mips/lib/tinycon.c --- a/arch/mips/lib/tinycon.c Tue Jul 1 18:44:35 2003 +++ b/arch/mips/lib/tinycon.c Tue Jul 1 18:44:35 2003 @@ -38,7 +38,7 @@ cursor_y = 0; vram_addr = (unsigned short *)0xb00b8000; - + console_needs_init = 0; } @@ -87,7 +87,7 @@ *(caddr++) = *(caddr + size_x); /* blank last line */ - + caddr = vram_addr + (size_x * (size_y-1)); for(i=0; i -#include -#include -#include +#include -#include -#include +#include #include -#include #include -#include -#include #include +#include +#include #include -#include -#include - #include +#include +#include #include "ieee754.h" +#include "dsemul.h" /* Strap kernel emulator for full MIPS IV emulation */ @@ -62,20 +57,14 @@ #endif #define __mips 4 -typedef void *vaddr_t; - -/* Function which emulates the instruction in a branch delay slot. */ - -static int mips_dsemul(struct pt_regs *, mips_instruction, vaddr_t); - /* Function which emulates a floating point instruction. */ static int fpu_emu(struct pt_regs *, struct mips_fpu_soft_struct *, - mips_instruction); + mips_instruction); #if __mips >= 4 && __mips != 32 static int fpux_emu(struct pt_regs *, - struct mips_fpu_soft_struct *, mips_instruction); + struct mips_fpu_soft_struct *, mips_instruction); #endif /* Further private data for which no space exists in mips_fpu_soft_struct */ @@ -107,8 +96,7 @@ #endif - -/* +/* * Redundant with logic already in kernel/branch.c, * embedded in compute_return_epc. At some point, * a single subroutine should be used across both @@ -164,67 +152,45 @@ return 0; } -#define REG_TO_VA (vaddr_t) -#define VA_TO_REG (unsigned long) - -static unsigned long mips_get_word(struct pt_regs *xcp, void *va, int *perr) -{ - unsigned long temp; - - if (!user_mode(xcp)) { - *perr = 0; - return (*(unsigned long *) va); - } - - *perr = (int) get_user(temp, (unsigned long *) va); - return temp; -} - -static unsigned long long -mips_get_dword(struct pt_regs *xcp, void *va, int *perr) -{ - unsigned long long temp; - - if (!user_mode(xcp)) { - *perr = 0; - return (*(unsigned long long *) va); - } - - *perr = (int) get_user(temp, (unsigned long long *) va); - return temp; -} - -static int mips_put_word(struct pt_regs *xcp, void *va, unsigned long val) -{ - if (!user_mode(xcp)) { - *(unsigned long *) va = val; - return 0; - } - - return put_user(val, (unsigned long *) va); -} - -static int mips_put_dword(struct pt_regs *xcp, void *va, long long val) -{ - if (!user_mode(xcp)) { - *(unsigned long long *) va = val; - return 0; - } - - return put_user(val, (unsigned long long *) va); -} - - /* * In the Linux kernel, we support selection of FPR format on the * basis of the Status.FR bit. This does imply that, if a full 32 * FPRs are desired, there needs to be a flip-flop that can be written - * to one at that bit position. In any case, normal MIPS ABI uses + * to one at that bit position. In any case, O32 MIPS ABI uses * only the even FPRs (Status.FR = 0). */ #define CP0_STATUS_FR_SUPPORT +#ifdef CP0_STATUS_FR_SUPPORT +#define FR_BIT ST0_FR +#else +#define FR_BIT 0 +#endif + +#define SIFROMREG(si,x) ((si) = \ + (xcp->cp0_status & FR_BIT) || !(x & 1) ? \ + (int)ctx->regs[x] : \ + (int)(ctx->regs[x & ~1] >> 32 )) +#define SITOREG(si,x) (ctx->regs[x & ~((xcp->cp0_status & FR_BIT) == 0)] = \ + (xcp->cp0_status & FR_BIT) || !(x & 1) ? \ + ctx->regs[x & ~1] >> 32 << 32 | (u32)(si) : \ + ctx->regs[x & ~1] << 32 >> 32 | (u64)(si) << 32) + +#define DIFROMREG(di,x) ((di) = \ + ctx->regs[x & ~((xcp->cp0_status & FR_BIT) == 0)]) +#define DITOREG(di,x) (ctx->regs[x & ~((xcp->cp0_status & FR_BIT) == 0)] \ + = (di)) +#define DIFROMREG(di,x) ((di) = \ + ctx->regs[x & ~((xcp->cp0_status & FR_BIT) == 0)]) +#define DITOREG(di,x) (ctx->regs[x & ~((xcp->cp0_status & FR_BIT) == 0)] \ + = (di)) + +#define SPFROMREG(sp,x) SIFROMREG((sp).bits,x) +#define SPTOREG(sp,x) SITOREG((sp).bits,x) +#define DPFROMREG(dp,x) DIFROMREG((dp).bits,x) +#define DPTOREG(dp,x) DITOREG((dp).bits,x) + /* * Emulate the single floating point instruction pointed at by EPC. * Two instructions if the instruction is in a branch delay slot. @@ -233,13 +199,10 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx) { mips_instruction ir; - vaddr_t emulpc; - vaddr_t contpc; + vaddr_t emulpc, contpc; unsigned int cond; - int err = 0; - ir = mips_get_word(xcp, REG_TO_VA xcp->cp0_epc, &err); - if (err) { + if (get_user(ir, (mips_instruction *) xcp->cp0_epc)) { fpuemuprivate.stats.errors++; return SIGBUS; } @@ -252,7 +215,7 @@ /* * The instruction to be emulated is in a branch delay slot * which means that we have to emulate the branch instruction - * BEFORE we do the cop1 instruction. + * BEFORE we do the cop1 instruction. * * This branch could be a COP1 branch, but in that case we * would have had a trap for that instruction, and would not @@ -266,363 +229,201 @@ if (__compute_return_epc(xcp)) { #ifdef CP1DBG printk("failed to emulate branch at %p\n", - REG_TO_VA(xcp->cp0_epc)); + REG_TO_VA(xcp->cp0_epc)); #endif - return SIGILL;; + return SIGILL; } - ir = mips_get_word(xcp, emulpc, &err); - if (err) { + if (get_user(ir, (mips_instruction *) emulpc)) { fpuemuprivate.stats.errors++; return SIGBUS; } + /* __computer_return_epc() will have updated cp0_epc */ contpc = REG_TO_VA xcp->cp0_epc; - } else { + /* In order not to confuse ptrace() et al, tweak context */ + xcp->cp0_epc = VA_TO_REG emulpc - 4; + } + else { emulpc = REG_TO_VA xcp->cp0_epc; - contpc = REG_TO_VA xcp->cp0_epc + 4; + contpc = REG_TO_VA(xcp->cp0_epc + 4); } -emul: + emul: fpuemuprivate.stats.emulated++; switch (MIPSInst_OPCODE(ir)) { -#ifdef CP0_STATUS_FR_SUPPORT - /* R4000+ 64-bit fpu registers */ #ifndef SINGLE_ONLY_FPU - case ldc1_op: - { - void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)]) - + MIPSInst_SIMM(ir); - int ft = MIPSInst_RT(ir); - if (!(xcp->cp0_status & ST0_FR)) - ft &= ~1; - ctx->regs[ft] = mips_get_dword(xcp, va, &err); - fpuemuprivate.stats.loads++; - if (err) { - fpuemuprivate.stats.errors++; - return SIGBUS; - } + case ldc1_op:{ + u64 *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)] + + MIPSInst_SIMM(ir)); + u64 val; + + fpuemuprivate.stats.loads++; + if (get_user(val, va)) { + fpuemuprivate.stats.errors++; + return SIGBUS; } + DITOREG(val, MIPSInst_RT(ir)); break; + } - case sdc1_op: - { - void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)]) - + MIPSInst_SIMM(ir); - int ft = MIPSInst_RT(ir); - if (!(xcp->cp0_status & ST0_FR)) - ft &= ~1; - fpuemuprivate.stats.stores++; - if (mips_put_dword(xcp, va, ctx->regs[ft])) { - fpuemuprivate.stats.errors++; - return SIGBUS; - } + case sdc1_op:{ + u64 *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)] + + MIPSInst_SIMM(ir)); + u64 val; + + fpuemuprivate.stats.stores++; + DIFROMREG(val, MIPSInst_RT(ir)); + if (put_user(val, va)) { + fpuemuprivate.stats.errors++; + return SIGBUS; } break; + } #endif - case lwc1_op: - { - void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)]) - + MIPSInst_SIMM(ir); - fpureg_t val; - int ft = MIPSInst_RT(ir); - fpuemuprivate.stats.loads++; - val = mips_get_word(xcp, va, &err); - if (err) { - fpuemuprivate.stats.errors++; - return SIGBUS; - } - if (xcp->cp0_status & ST0_FR) { - /* load whole register */ - ctx->regs[ft] = val; - } else if (ft & 1) { - /* load to m.s. 32 bits */ -#ifdef SINGLE_ONLY_FPU - /* illegal register in single-float mode */ - return SIGILL; -#else - ctx->regs[(ft & ~1)] &= 0xffffffff; - ctx->regs[(ft & ~1)] |= val << 32; -#endif - } else { - /* load to l.s. 32 bits */ - ctx->regs[ft] &= ~0xffffffffLL; - ctx->regs[ft] |= val; - } - } - break; + case lwc1_op:{ + u32 *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)] + + MIPSInst_SIMM(ir)); + u32 val; - case swc1_op: - { - void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)]) - + MIPSInst_SIMM(ir); - unsigned int val; - int ft = MIPSInst_RT(ir); - fpuemuprivate.stats.stores++; - if (xcp->cp0_status & ST0_FR) { - /* store whole register */ - val = ctx->regs[ft]; - } else if (ft & 1) { -#ifdef SINGLE_ONLY_FPU - /* illegal register in single-float mode */ - return SIGILL; -#else - /* store from m.s. 32 bits */ - val = ctx->regs[(ft & ~1)] >> 32; -#endif - } else { - /* store from l.s. 32 bits */ - val = ctx->regs[ft]; - } - if (mips_put_word(xcp, va, val)) { - fpuemuprivate.stats.errors++; - return SIGBUS; - } - } - break; -#else /* old 32-bit fpu registers */ - case lwc1_op: - { - void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)]) - + MIPSInst_SIMM(ir); - ctx->regs[MIPSInst_RT(ir)] = - mips_get_word(xcp, va, &err); - fpuemuprivate.stats.loads++; - if (err) { - fpuemuprivate.stats.errors++; - return SIGBUS; - } + fpuemuprivate.stats.loads++; + if (get_user(val, va)) { + fpuemuprivate.stats.errors++; + return SIGBUS; } - break; - - case swc1_op: - { - void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)]) - + MIPSInst_SIMM(ir); - fpuemuprivate.stats.stores++; - if (mips_put_word - (xcp, va, ctx->regs[MIPSInst_RT(ir)])) { - fpuemuprivate.stats.errors++; - return SIGBUS; - } +#ifdef SINGLE_ONLY_FPU + if (MIPSInst_RT(ir) & 1) { + /* illegal register in single-float mode */ + return SIGILL; } - break; - case ldc1_op: - { - void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)]) - + MIPSInst_SIMM(ir); - unsigned int rt = MIPSInst_RT(ir) & ~1; - int errs = 0; - fpuemuprivate.stats.loads++; -#if (defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) || defined(__MIPSEB__) - ctx->regs[rt + 1] = - mips_get_word(xcp, va + 0, &err); - errs += err; - ctx->regs[rt + 0] = - mips_get_word(xcp, va + 4, &err); - errs += err; -#else - ctx->regs[rt + 0] = - mips_get_word(xcp, va + 0, &err); - errs += err; - ctx->regs[rt + 1] = - mips_get_word(xcp, va + 4, &err); - errs += err; #endif - if (err) - return SIGBUS; - } + SITOREG(val, MIPSInst_RT(ir)); break; + } - case sdc1_op: - { - void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)]) - + MIPSInst_SIMM(ir); - unsigned int rt = MIPSInst_RT(ir) & ~1; - fpuemuprivate.stats.stores++; -#if (defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) || defined(__MIPSEB__) - if (mips_put_word(xcp, va + 0, ctx->regs[rt + 1])) - return SIGBUS; - if (mips_put_word(xcp, va + 4, ctx->regs[rt + 0])) - return SIGBUS; -#else - if (mips_put_word(xcp, va + 0, ctx->regs[rt + 0])) - return SIGBUS; - if (mips_put_word(xcp, va + 4, ctx->regs[rt + 1])) - return SIGBUS; + case swc1_op:{ + u32 *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)] + + MIPSInst_SIMM(ir)); + u32 val; + + fpuemuprivate.stats.stores++; +#ifdef SINGLE_ONLY_FPU + if (MIPSInst_RT(ir) & 1) { + /* illegal register in single-float mode */ + return SIGILL; + } #endif + SIFROMREG(val, MIPSInst_RT(ir)); + if (put_user(val, va)) { + fpuemuprivate.stats.errors++; + return SIGBUS; } break; -#endif + } case cop1_op: switch (MIPSInst_RS(ir)) { -#ifdef CP0_STATUS_FR_SUPPORT #if __mips64 && !defined(SINGLE_ONLY_FPU) case dmfc_op: /* copregister fs -> gpr[rt] */ if (MIPSInst_RT(ir) != 0) { - int fs = MIPSInst_RD(ir); - if (!(xcp->cp0_status & ST0_FR)) - fs &= ~1; - xcp->regs[MIPSInst_RT(ir)] = ctx->regs[fs]; + DIFROMREG(xcp->regs[MIPSInst_RT(ir)], + MIPSInst_RD(ir)); } break; - case dmtc_op: { + case dmtc_op: /* copregister fs <- rt */ - fpureg_t value; - int fs = MIPSInst_RD(ir); - if (!(xcp->cp0_status & ST0_FR)) - fs &= ~1; - value = - (MIPSInst_RT(ir) == - 0) ? 0 : xcp->regs[MIPSInst_RT(ir)]; - ctx->regs[fs] = value; + DITOREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir)); break; - } #endif case mfc_op: /* copregister rd -> gpr[rt] */ - if (MIPSInst_RT(ir) != 0) { - /* default value from l.s. 32 bits */ - int value = ctx->regs[MIPSInst_RD(ir)]; - if (MIPSInst_RD(ir) & 1) { #ifdef SINGLE_ONLY_FPU - /* illegal register in single-float mode */ - return SIGILL; -#else - if (!(xcp->cp0_status & ST0_FR)) { - /* move from m.s. 32 bits */ - value = - ctx-> - regs[MIPSInst_RD(ir) & - ~1] >> 32; - } -#endif - } - xcp->regs[MIPSInst_RT(ir)] = value; + if (MIPSInst_RD(ir) & 1) { + /* illegal register in single-float mode */ + return SIGILL; } - break; - - case mtc_op: - /* copregister rd <- rt */ - { - fpureg_t value; - if (MIPSInst_RT(ir) == 0) - value = 0; - else - value = - (unsigned int) xcp-> - regs[MIPSInst_RT(ir)]; - if (MIPSInst_RD(ir) & 1) { -#ifdef SINGLE_ONLY_FPU - /* illegal register in single-float mode */ - return SIGILL; -#else - if (!(xcp->cp0_status & ST0_FR)) { - /* move to m.s. 32 bits */ - ctx-> - regs[ - (MIPSInst_RD(ir) & - ~1)] &= - 0xffffffff; - ctx-> - regs[ - (MIPSInst_RD(ir) & - ~1)] |= - value << 32; - break; - } #endif - } - /* move to l.s. 32 bits */ - ctx->regs[MIPSInst_RD(ir)] &= - ~0xffffffffLL; - ctx->regs[MIPSInst_RD(ir)] |= value; - } - break; -#else - - case mfc_op: - /* copregister rd -> gpr[rt] */ if (MIPSInst_RT(ir) != 0) { - unsigned value = - ctx->regs[MIPSInst_RD(ir)]; - xcp->regs[MIPSInst_RT(ir)] = value; + SIFROMREG(xcp->regs[MIPSInst_RT(ir)], + MIPSInst_RD(ir)); } break; case mtc_op: /* copregister rd <- rt */ - { - unsigned value; - value = - (MIPSInst_RT(ir) == - 0) ? 0 : xcp->regs[MIPSInst_RT(ir)]; - ctx->regs[MIPSInst_RD(ir)] = value; +#ifdef SINGLE_ONLY_FPU + if (MIPSInst_RD(ir) & 1) { + /* illegal register in single-float mode */ + return SIGILL; } - break; #endif + SITOREG(xcp->regs[MIPSInst_RT(ir)], MIPSInst_RD(ir)); + break; - case cfc_op: + case cfc_op:{ /* cop control register rd -> gpr[rt] */ - { - unsigned value; + u32 value; - if (MIPSInst_RD(ir) == FPCREG_CSR) { - value = ctx->sr; + if (ir == CP1UNDEF) { + return do_dsemulret(xcp); + } + if (MIPSInst_RD(ir) == FPCREG_CSR) { + value = ctx->sr; #ifdef CSRTRACE - printk - ("%p gpr[%d]<-csr=%08x\n", - REG_TO_VA(xcp->cp0_epc), - MIPSInst_RT(ir), value); + printk("%p gpr[%d]<-csr=%08x\n", + REG_TO_VA(xcp->cp0_epc), + MIPSInst_RT(ir), value); #endif - } else if (MIPSInst_RD(ir) == FPCREG_RID) - value = 0; - else - value = 0; - if (MIPSInst_RT(ir)) - xcp->regs[MIPSInst_RT(ir)] = value; } + else if (MIPSInst_RD(ir) == FPCREG_RID) + value = 0; + else + value = 0; + if (MIPSInst_RT(ir)) + xcp->regs[MIPSInst_RT(ir)] = value; break; + } - case ctc_op: + case ctc_op:{ /* copregister rd <- rt */ - { - unsigned value; - - if (MIPSInst_RT(ir) == 0) - value = 0; - else - value = xcp->regs[MIPSInst_RT(ir)]; + u32 value; - /* we only have one writable control reg - */ - if (MIPSInst_RD(ir) == FPCREG_CSR) { + if (MIPSInst_RT(ir) == 0) + value = 0; + else + value = xcp->regs[MIPSInst_RT(ir)]; + + /* we only have one writable control reg + */ + if (MIPSInst_RD(ir) == FPCREG_CSR) { #ifdef CSRTRACE - printk - ("%p gpr[%d]->csr=%08x\n", - REG_TO_VA(xcp->cp0_epc), - MIPSInst_RT(ir), value); -#endif - ctx->sr = value; - /* copy new rounding mode to ieee library state! */ - ieee754_csr.rm = - ieee_rm[value & 0x3]; - } + printk("%p gpr[%d]->csr=%08x\n", + REG_TO_VA(xcp->cp0_epc), + MIPSInst_RT(ir), value); +#endif + ctx->sr = value; + /* copy new rounding mode and + flush bit to ieee library state! */ + ieee754_csr.nod = (ctx->sr & 0x1000000) != 0; + ieee754_csr.rm = ieee_rm[value & 0x3]; + } + if ((ctx->sr >> 5) & ctx->sr & FPU_CSR_ALL_E) { + return SIGFPE; } break; + } - case bc_op: { + case bc_op:{ int likely = 0; if (xcp->cp0_cause & CAUSEF_BD) return SIGILL; #if __mips >= 4 - cond = ctx-> sr & fpucondbit[MIPSInst_RT(ir) >> 2]; + cond = ctx->sr & fpucondbit[MIPSInst_RT(ir) >> 2]; #else cond = ctx->sr & FPU_CSR_COND; #endif @@ -643,14 +444,16 @@ xcp->cp0_cause |= CAUSEF_BD; if (cond) { - /* branch taken: emulate dslot instruction */ + /* branch taken: emulate dslot + * instruction + */ xcp->cp0_epc += 4; - contpc = REG_TO_VA xcp->cp0_epc + - (MIPSInst_SIMM(ir) << 2); + contpc = REG_TO_VA + (xcp->cp0_epc + + (MIPSInst_SIMM(ir) << 2)); - ir = mips_get_word(xcp, REG_TO_VA(xcp->cp0_epc), - &err); - if (err) { + if (get_user(ir, (mips_instruction *) + REG_TO_VA xcp->cp0_epc)) { fpuemuprivate.stats.errors++; return SIGBUS; } @@ -677,30 +480,36 @@ } /* - * Single step the non-cp1 instruction in the - * dslot + * Single step the non-cp1 + * instruction in the dslot */ - return mips_dsemul(xcp, ir, contpc); - } else { + return mips_dsemul(xcp, ir, VA_TO_REG contpc); + } + else { /* branch not taken */ - if (likely) + if (likely) { /* - * branch likely nullifies dslot if not - * taken + * branch likely nullifies + * dslot if not taken */ xcp->cp0_epc += 4; - /* else continue & execute dslot as normal insn */ + contpc += 4; + /* + * else continue & execute + * dslot as normal insn + */ + } } break; } - default: { - int sig; - + default: if (!(MIPSInst_RS(ir) & 0x10)) return SIGILL; + { + int sig; - /* a real fpu computation instruction */ + /* a real fpu computation instruction */ if ((sig = fpu_emu(xcp, ctx, ir))) return sig; } @@ -708,13 +517,13 @@ break; #if __mips >= 4 && __mips != 32 - case cop1x_op: - { - int sig; - if ((sig = fpux_emu(xcp, ctx, ir))) - return sig; - } + case cop1x_op:{ + int sig; + + if ((sig = fpux_emu(xcp, ctx, ir))) + return sig; break; + } #endif #if __mips >= 4 @@ -722,8 +531,8 @@ if (MIPSInst_FUNC(ir) != movc_op) return SIGILL; cond = fpucondbit[MIPSInst_RT(ir) >> 2]; - if (((ctx->sr & cond) != 0) != - ((MIPSInst_RT(ir) & 1) != 0)) return 0; + if (((ctx->sr & cond) != 0) != ((MIPSInst_RT(ir) & 1) != 0)) + return 0; xcp->regs[MIPSInst_RD(ir)] = xcp->regs[MIPSInst_RS(ir)]; break; #endif @@ -739,141 +548,20 @@ } /* - * Emulate the arbritrary instruction ir at xcp->cp0_epc. Required when - * we have to emulate the instruction in a COP1 branch delay slot. Do - * not change cp0_epc due to the instruction - * - * According to the spec: - * 1) it shouldnt be a branch :-) - * 2) it can be a COP instruction :-( - * 3) if we are tring to run a protected memory space we must take - * special care on memory access instructions :-( - */ - -/* - * "Trampoline" return routine to catch exception following - * execution of delay-slot instruction execution. - */ - -int do_dsemulret(struct pt_regs *xcp) -{ -#ifdef DSEMUL_TRACE - printk("desemulret\n"); -#endif - /* Set EPC to return to post-branch instruction */ - xcp->cp0_epc = current->thread.dsemul_epc; - /* - * Clear the state that got us here. - */ - current->thread.dsemul_aerpc = (unsigned long) 0; - - return 0; -} - - -#define AdELOAD 0x8c000001 /* lw $0,1($0) */ - -static int -mips_dsemul(struct pt_regs *xcp, mips_instruction ir, vaddr_t cpc) -{ - mips_instruction *dsemul_insns; - mips_instruction forcetrap; - extern asmlinkage void handle_dsemulret(void); - - if (ir == 0) { /* a nop is easy */ - xcp->cp0_epc = VA_TO_REG(cpc); - return 0; - } -#ifdef DSEMUL_TRACE - printk("desemul %p %p\n", REG_TO_VA(xcp->cp0_epc), cpc); -#endif - - /* - * The strategy is to push the instruction onto the user stack - * and put a trap after it which we can catch and jump to - * the required address any alternative apart from full - * instruction emulation!!. - */ - dsemul_insns = (mips_instruction *) (xcp->regs[29] & ~3); - dsemul_insns -= 3; /* Two instructions, plus one for luck ;-) */ - - /* Verify that the stack pointer is not competely insane */ - if (verify_area(VERIFY_WRITE, dsemul_insns, - sizeof(mips_instruction) * 2)) - return SIGBUS; - - if (mips_put_word(xcp, &dsemul_insns[0], ir)) { - fpuemuprivate.stats.errors++; - return SIGBUS; - } - - /* - * Algorithmics used a system call instruction, and - * borrowed that vector. MIPS/Linux version is a bit - * more heavyweight in the interests of portability and - * multiprocessor support. We flag the thread for special - * handling in the unaligned access handler and force an - * address error excpetion. - */ - - /* If one is *really* paranoid, one tests for a bad stack pointer */ - if ((xcp->regs[29] & 0x3) == 0x3) - forcetrap = AdELOAD - 1; - else - forcetrap = AdELOAD; - - if (mips_put_word(xcp, &dsemul_insns[1], forcetrap)) { - fpuemuprivate.stats.errors++; - return (SIGBUS); - } - - /* Set thread state to catch and handle the exception */ - current->thread.dsemul_epc = (unsigned long) cpc; - current->thread.dsemul_aerpc = (unsigned long) &dsemul_insns[1]; - xcp->cp0_epc = VA_TO_REG & dsemul_insns[0]; - flush_cache_sigtramp((unsigned long) dsemul_insns); - - return SIGILL; /* force out of emulation loop */ -} - -/* * Conversion table from MIPS compare ops 48-63 - * cond = ieee754dp_cmp(x,y,IEEE754_UN); + * cond = ieee754dp_cmp(x,y,IEEE754_UN,sig); */ static const unsigned char cmptab[8] = { - 0, /* cmp_0 (sig) cmp_sf */ - IEEE754_CUN, /* cmp_un (sig) cmp_ngle */ - IEEE754_CEQ, /* cmp_eq (sig) cmp_seq */ - IEEE754_CEQ | IEEE754_CUN, /* cmp_ueq (sig) cmp_ngl */ - IEEE754_CLT, /* cmp_olt (sig) cmp_lt */ - IEEE754_CLT | IEEE754_CUN, /* cmp_ult (sig) cmp_nge */ - IEEE754_CLT | IEEE754_CEQ, /* cmp_ole (sig) cmp_le */ - IEEE754_CLT | IEEE754_CEQ | IEEE754_CUN, /* cmp_ule (sig) cmp_ngt */ + 0, /* cmp_0 (sig) cmp_sf */ + IEEE754_CUN, /* cmp_un (sig) cmp_ngle */ + IEEE754_CEQ, /* cmp_eq (sig) cmp_seq */ + IEEE754_CEQ | IEEE754_CUN, /* cmp_ueq (sig) cmp_ngl */ + IEEE754_CLT, /* cmp_olt (sig) cmp_lt */ + IEEE754_CLT | IEEE754_CUN, /* cmp_ult (sig) cmp_nge */ + IEEE754_CLT | IEEE754_CEQ, /* cmp_ole (sig) cmp_le */ + IEEE754_CLT | IEEE754_CEQ | IEEE754_CUN, /* cmp_ule (sig) cmp_ngt */ }; -#define SIFROMREG(si,x) ((si) = ctx->regs[x]) -#define SITOREG(si,x) (ctx->regs[x] = (int)(si)) - -#if __mips64 && !defined(SINGLE_ONLY_FPU) -#define DIFROMREG(di,x) ((di) = ctx->regs[x]) -#define DITOREG(di,x) (ctx->regs[x] = (di)) -#endif - -#define SPFROMREG(sp,x) ((sp).bits = ctx->regs[x]) -#define SPTOREG(sp,x) (ctx->regs[x] = (sp).bits) - -#ifdef CP0_STATUS_FR_SUPPORT -#define DPFROMREG(dp,x) ((dp).bits = \ - ctx->regs[(xcp->cp0_status & ST0_FR) ? x : (x & ~1)]) -#define DPTOREG(dp,x) (ctx->regs[(xcp->cp0_status & ST0_FR) ? x : (x & ~1)]\ - = (dp).bits) -#else -/* Beware: MIPS COP1 doubles are always little_word endian in registers */ -#define DPFROMREG(dp,x) \ - ((dp).bits = ((unsigned long long)ctx->regs[(x)+1] << 32) | ctx->regs[x]) -#define DPTOREG(dp,x) \ - (ctx->regs[x] = (dp).bits, ctx->regs[(x)+1] = (dp).bits >> 32) -#endif #if __mips >= 4 && __mips != 32 @@ -881,6 +569,22 @@ * Additional MIPS4 instructions */ +#define DEF3OP(name, p, f1, f2, f3) \ +static ieee754##p fpemu_##p##_##name (ieee754##p r, ieee754##p s, \ + ieee754##p t) \ +{ \ + struct ieee754_csr ieee754_csr_save; \ + s = f1 (s, t); \ + ieee754_csr_save = ieee754_csr; \ + s = f2 (s, r); \ + ieee754_csr_save.cx |= ieee754_csr.cx; \ + ieee754_csr_save.sx |= ieee754_csr.sx; \ + s = f3 (s); \ + ieee754_csr.cx |= ieee754_csr_save.cx; \ + ieee754_csr.sx |= ieee754_csr_save.sx; \ + return s; \ +} + static ieee754dp fpemu_dp_recip(ieee754dp d) { return ieee754dp_div(ieee754dp_one(0), d); @@ -901,287 +605,184 @@ return ieee754sp_div(ieee754sp_one(0), ieee754sp_sqrt(s)); } +DEF3OP(madd, sp, ieee754sp_mul, ieee754sp_add,); +DEF3OP(msub, sp, ieee754sp_mul, ieee754sp_sub,); +DEF3OP(nmadd, sp, ieee754sp_mul, ieee754sp_add, ieee754sp_neg); +DEF3OP(nmsub, sp, ieee754sp_mul, ieee754sp_sub, ieee754sp_neg); +DEF3OP(madd, dp, ieee754dp_mul, ieee754dp_add,); +DEF3OP(msub, dp, ieee754dp_mul, ieee754dp_sub,); +DEF3OP(nmadd, dp, ieee754dp_mul, ieee754dp_add, ieee754dp_neg); +DEF3OP(nmsub, dp, ieee754dp_mul, ieee754dp_sub, ieee754dp_neg); -static ieee754dp fpemu_dp_madd(ieee754dp r, ieee754dp s, ieee754dp t) +static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx, + mips_instruction ir) { - return ieee754dp_add(ieee754dp_mul(s, t), r); -} + unsigned rcsr = 0; /* resulting csr */ -static ieee754dp fpemu_dp_msub(ieee754dp r, ieee754dp s, ieee754dp t) -{ - return ieee754dp_sub(ieee754dp_mul(s, t), r); -} + fpuemuprivate.stats.cp1xops++; -static ieee754dp fpemu_dp_nmadd(ieee754dp r, ieee754dp s, ieee754dp t) -{ - return ieee754dp_neg(ieee754dp_add(ieee754dp_mul(s, t), r)); -} + switch (MIPSInst_FMA_FFMT(ir)) { + case s_fmt:{ /* 0 */ -static ieee754dp fpemu_dp_nmsub(ieee754dp r, ieee754dp s, ieee754dp t) -{ - return ieee754dp_neg(ieee754dp_sub(ieee754dp_mul(s, t), r)); -} + ieee754sp(*handler) (ieee754sp, ieee754sp, ieee754sp); + ieee754sp fd, fr, fs, ft; + u32 *va; + u32 val; + switch (MIPSInst_FUNC(ir)) { + case lwxc1_op: + va = REG_TO_VA(xcp->regs[MIPSInst_FR(ir)] + + xcp->regs[MIPSInst_FT(ir)]); -static ieee754sp fpemu_sp_madd(ieee754sp r, ieee754sp s, ieee754sp t) -{ - return ieee754sp_add(ieee754sp_mul(s, t), r); -} + fpuemuprivate.stats.loads++; + if (get_user(val, va)) { + fpuemuprivate.stats.errors++; + return SIGBUS; + } +#ifdef SINGLE_ONLY_FPU + if (MIPSInst_FD(ir) & 1) { + /* illegal register in single-float + * mode + */ + return SIGILL; + } +#endif + SITOREG(val, MIPSInst_FD(ir)); + break; -static ieee754sp fpemu_sp_msub(ieee754sp r, ieee754sp s, ieee754sp t) -{ - return ieee754sp_sub(ieee754sp_mul(s, t), r); -} + case swxc1_op: + va = REG_TO_VA(xcp->regs[MIPSInst_FR(ir)] + + xcp->regs[MIPSInst_FT(ir)]); -static ieee754sp fpemu_sp_nmadd(ieee754sp r, ieee754sp s, ieee754sp t) -{ - return ieee754sp_neg(ieee754sp_add(ieee754sp_mul(s, t), r)); -} + fpuemuprivate.stats.stores++; +#ifdef SINGLE_ONLY_FPU + if (MIPSInst_FS(ir) & 1) { + /* illegal register in single-float + * mode + */ + return SIGILL; + } +#endif -static ieee754sp fpemu_sp_nmsub(ieee754sp r, ieee754sp s, ieee754sp t) -{ - return ieee754sp_neg(ieee754sp_sub(ieee754sp_mul(s, t), r)); -} + SIFROMREG(val, MIPSInst_FS(ir)); + if (put_user(val, va)) { + fpuemuprivate.stats.errors++; + return SIGBUS; + } + break; -static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx, - mips_instruction ir) -{ - unsigned rcsr = 0; /* resulting csr */ + case madd_s_op: + handler = fpemu_sp_madd; + goto scoptop; + case msub_s_op: + handler = fpemu_sp_msub; + goto scoptop; + case nmadd_s_op: + handler = fpemu_sp_nmadd; + goto scoptop; + case nmsub_s_op: + handler = fpemu_sp_nmsub; + goto scoptop; - fpuemuprivate.stats.cp1xops++; + scoptop: + SPFROMREG(fr, MIPSInst_FR(ir)); + SPFROMREG(fs, MIPSInst_FS(ir)); + SPFROMREG(ft, MIPSInst_FT(ir)); + fd = (*handler) (fr, fs, ft); + SPTOREG(fd, MIPSInst_FD(ir)); - switch (MIPSInst_FMA_FFMT(ir)) { - case s_fmt: /* 0 */ - { - ieee754sp(*handler) (ieee754sp, ieee754sp, - ieee754sp); - ieee754sp fd, fr, fs, ft; - - switch (MIPSInst_FUNC(ir)) { - case lwxc1_op: - { - void *va = - REG_TO_VA(xcp-> - regs[MIPSInst_FR(ir)] - + - xcp-> - regs[MIPSInst_FT - (ir)]); - fpureg_t val; - int err = 0; - val = mips_get_word(xcp, va, &err); - if (err) { - fpuemuprivate.stats. - errors++; - return SIGBUS; - } - if (xcp->cp0_status & ST0_FR) { - /* load whole register */ - ctx-> - regs[MIPSInst_FD(ir)] = - val; - } else if (MIPSInst_FD(ir) & 1) { - /* load to m.s. 32 bits */ -#if defined(SINGLE_ONLY_FPU) - /* illegal register in single-float mode */ - return SIGILL; -#else - ctx-> - regs[ - (MIPSInst_FD(ir) & - ~1)] &= - 0xffffffff; - ctx-> - regs[ - (MIPSInst_FD(ir) & - ~1)] |= - val << 32; -#endif - } else { - /* load to l.s. 32 bits */ - ctx-> - regs[MIPSInst_FD(ir)] - &= ~0xffffffffLL; - ctx-> - regs[MIPSInst_FD(ir)] - |= val; - } - } - break; + copcsr: + if (ieee754_cxtest(IEEE754_INEXACT)) + rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S; + if (ieee754_cxtest(IEEE754_UNDERFLOW)) + rcsr |= FPU_CSR_UDF_X | FPU_CSR_UDF_S; + if (ieee754_cxtest(IEEE754_OVERFLOW)) + rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S; + if (ieee754_cxtest(IEEE754_INVALID_OPERATION)) + rcsr |= FPU_CSR_INV_X | FPU_CSR_INV_S; - case swxc1_op: - { - void *va = - REG_TO_VA(xcp-> - regs[MIPSInst_FR(ir)] - + - xcp-> - regs[MIPSInst_FT - (ir)]); - unsigned int val; - if (xcp->cp0_status & ST0_FR) { - /* store whole register */ - val = - ctx-> - regs[MIPSInst_FS(ir)]; - } else if (MIPSInst_FS(ir) & 1) { -#if defined(SINGLE_ONLY_FPU) - /* illegal register in single-float mode */ - return SIGILL; -#else - /* store from m.s. 32 bits */ - val = - ctx-> - regs[ - (MIPSInst_FS(ir) & - ~1)] >> 32; -#endif - } else { - /* store from l.s. 32 bits */ - val = - ctx-> - regs[MIPSInst_FS(ir)]; - } - if (mips_put_word(xcp, va, val)) { - fpuemuprivate.stats. - errors++; - return SIGBUS; - } - } - break; + ctx->sr = (ctx->sr & ~FPU_CSR_ALL_X) | rcsr; + if (ieee754_csr.nod) + ctx->sr |= 0x1000000; + if ((ctx->sr >> 5) & ctx->sr & FPU_CSR_ALL_E) { + /*printk ("SIGFPE: fpu csr = %08x\n", + ctx->sr); */ + return SIGFPE; + } - case madd_s_op: - handler = fpemu_sp_madd; - goto scoptop; - case msub_s_op: - handler = fpemu_sp_msub; - goto scoptop; - case nmadd_s_op: - handler = fpemu_sp_nmadd; - goto scoptop; - case nmsub_s_op: - handler = fpemu_sp_nmsub; - goto scoptop; + break; - scoptop: - SPFROMREG(fr, MIPSInst_FR(ir)); - SPFROMREG(fs, MIPSInst_FS(ir)); - SPFROMREG(ft, MIPSInst_FT(ir)); - fd = (*handler) (fr, fs, ft); - SPTOREG(fd, MIPSInst_FD(ir)); + default: + return SIGILL; + } + break; + } - copcsr: - if (ieee754_cxtest(IEEE754_INEXACT)) - rcsr |= - FPU_CSR_INE_X | FPU_CSR_INE_S; - if (ieee754_cxtest(IEEE754_UNDERFLOW)) - rcsr |= - FPU_CSR_UDF_X | FPU_CSR_UDF_S; - if (ieee754_cxtest(IEEE754_OVERFLOW)) - rcsr |= - FPU_CSR_OVF_X | FPU_CSR_OVF_S; - if (ieee754_cxtest - (IEEE754_INVALID_OPERATION)) rcsr |= - FPU_CSR_INV_X | FPU_CSR_INV_S; - - ctx->sr = - (ctx->sr & ~FPU_CSR_ALL_X) | rcsr; - if ((ctx->sr >> 5) & ctx-> - sr & FPU_CSR_ALL_E) { - /*printk ("SIGFPE: fpu csr = %08x\n",ctx->sr); */ - return SIGFPE; - } +#ifndef SINGLE_ONLY_FPU + case d_fmt:{ /* 1 */ + ieee754dp(*handler) (ieee754dp, ieee754dp, ieee754dp); + ieee754dp fd, fr, fs, ft; + u64 *va; + u64 val; - break; + switch (MIPSInst_FUNC(ir)) { + case ldxc1_op: + va = REG_TO_VA(xcp->regs[MIPSInst_FR(ir)] + + xcp->regs[MIPSInst_FT(ir)]); - default: - return SIGILL; + fpuemuprivate.stats.loads++; + if (get_user(val, va)) { + fpuemuprivate.stats.errors++; + return SIGBUS; } - } - break; + DITOREG(val, MIPSInst_FD(ir)); + break; -#if !defined(SINGLE_ONLY_FPU) - case d_fmt: /* 1 */ - { - ieee754dp(*handler) (ieee754dp, ieee754dp, - ieee754dp); - ieee754dp fd, fr, fs, ft; - - switch (MIPSInst_FUNC(ir)) { - case ldxc1_op: - { - void *va = - REG_TO_VA(xcp-> - regs[MIPSInst_FR(ir)] - + - xcp-> - regs[MIPSInst_FT - (ir)]); - int err = 0; - ctx->regs[MIPSInst_FD(ir)] = - mips_get_dword(xcp, va, &err); - if (err) { - fpuemuprivate.stats. - errors++; - return SIGBUS; - } - } - break; + case sdxc1_op: + va = REG_TO_VA(xcp->regs[MIPSInst_FR(ir)] + + xcp->regs[MIPSInst_FT(ir)]); - case sdxc1_op: - { - void *va = - REG_TO_VA(xcp-> - regs[MIPSInst_FR(ir)] - + - xcp-> - regs[MIPSInst_FT - (ir)]); - if (mips_put_dword - (xcp, va, - ctx->regs[MIPSInst_FS(ir)])) { - fpuemuprivate.stats. - errors++; - return SIGBUS; - } - } - break; + fpuemuprivate.stats.stores++; + DIFROMREG(val, MIPSInst_FS(ir)); + if (put_user(val, va)) { + fpuemuprivate.stats.errors++; + return SIGBUS; + } + break; - case madd_d_op: - handler = fpemu_dp_madd; - goto dcoptop; - case msub_d_op: - handler = fpemu_dp_msub; - goto dcoptop; - case nmadd_d_op: - handler = fpemu_dp_nmadd; - goto dcoptop; - case nmsub_d_op: - handler = fpemu_dp_nmsub; - goto dcoptop; + case madd_d_op: + handler = fpemu_dp_madd; + goto dcoptop; + case msub_d_op: + handler = fpemu_dp_msub; + goto dcoptop; + case nmadd_d_op: + handler = fpemu_dp_nmadd; + goto dcoptop; + case nmsub_d_op: + handler = fpemu_dp_nmsub; + goto dcoptop; - dcoptop: - DPFROMREG(fr, MIPSInst_FR(ir)); - DPFROMREG(fs, MIPSInst_FS(ir)); - DPFROMREG(ft, MIPSInst_FT(ir)); - fd = (*handler) (fr, fs, ft); - DPTOREG(fd, MIPSInst_FD(ir)); - goto copcsr; + dcoptop: + DPFROMREG(fr, MIPSInst_FR(ir)); + DPFROMREG(fs, MIPSInst_FS(ir)); + DPFROMREG(ft, MIPSInst_FT(ir)); + fd = (*handler) (fr, fs, ft); + DPTOREG(fd, MIPSInst_FD(ir)); + goto copcsr; - default: - return SIGILL; - } + default: + return SIGILL; } break; + } #endif case 0x7: /* 7 */ - { - if (MIPSInst_FUNC(ir) != pfetch_op) { - return SIGILL; - } - /* ignore prefx operation */ + if (MIPSInst_FUNC(ir) != pfetch_op) { + return SIGILL; } + /* ignore prefx operation */ break; default: @@ -1198,7 +799,7 @@ * Emulate a single COP1 arithmetic instruction. */ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx, - mips_instruction ir) + mips_instruction ir) { int rfmt; /* resulting format */ unsigned rcsr = 0; /* resulting csr */ @@ -1208,49 +809,52 @@ ieee754sp s; int w; #if __mips64 - long long l; + s64 l; #endif } rv; /* resulting value */ fpuemuprivate.stats.cp1ops++; switch (rfmt = (MIPSInst_FFMT(ir) & 0xf)) { - case s_fmt: { /* 0 */ - ieee754sp(*handler) (); + case s_fmt:{ /* 0 */ + union { + ieee754sp(*b) (ieee754sp, ieee754sp); + ieee754sp(*u) (ieee754sp); + } handler; switch (MIPSInst_FUNC(ir)) { /* binary ops */ case fadd_op: - handler = ieee754sp_add; + handler.b = ieee754sp_add; goto scopbop; case fsub_op: - handler = ieee754sp_sub; + handler.b = ieee754sp_sub; goto scopbop; case fmul_op: - handler = ieee754sp_mul; + handler.b = ieee754sp_mul; goto scopbop; case fdiv_op: - handler = ieee754sp_div; + handler.b = ieee754sp_div; goto scopbop; /* unary ops */ #if __mips >= 2 || __mips64 case fsqrt_op: - handler = ieee754sp_sqrt; + handler.u = ieee754sp_sqrt; goto scopuop; #endif #if __mips >= 4 && __mips != 32 case frsqrt_op: - handler = fpemu_sp_rsqrt; + handler.u = fpemu_sp_rsqrt; goto scopuop; case frecip_op: - handler = fpemu_sp_recip; + handler.u = fpemu_sp_recip; goto scopuop; #endif #if __mips >= 4 case fmovc_op: cond = fpucondbit[MIPSInst_FT(ir) >> 2]; if (((ctx->sr & cond) != 0) != - ((MIPSInst_FT(ir) & 1) != 0)) + ((MIPSInst_FT(ir) & 1) != 0)) return 0; SPFROMREG(rv.s, MIPSInst_FS(ir)); break; @@ -1266,35 +870,36 @@ break; #endif case fabs_op: - handler = ieee754sp_abs; + handler.u = ieee754sp_abs; goto scopuop; case fneg_op: - handler = ieee754sp_neg; + handler.u = ieee754sp_neg; goto scopuop; case fmov_op: /* an easy one */ SPFROMREG(rv.s, MIPSInst_FS(ir)); - break; + goto copcsr; + /* binary op on handler */ -scopbop: + scopbop: { ieee754sp fs, ft; SPFROMREG(fs, MIPSInst_FS(ir)); SPFROMREG(ft, MIPSInst_FT(ir)); - rv.s = (*handler) (fs, ft); + rv.s = (*handler.b) (fs, ft); goto copcsr; } -scopuop: + scopuop: { ieee754sp fs; SPFROMREG(fs, MIPSInst_FS(ir)); - rv.s = (*handler) (fs); + rv.s = (*handler.u) (fs); goto copcsr; } -copcsr: + copcsr: if (ieee754_cxtest(IEEE754_INEXACT)) rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S; if (ieee754_cxtest(IEEE754_UNDERFLOW)) @@ -1303,15 +908,14 @@ rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S; if (ieee754_cxtest(IEEE754_ZERO_DIVIDE)) rcsr |= FPU_CSR_DIV_X | FPU_CSR_DIV_S; - if (ieee754_cxtest - (IEEE754_INVALID_OPERATION)) rcsr |= - FPU_CSR_INV_X | FPU_CSR_INV_S; - break; + if (ieee754_cxtest(IEEE754_INVALID_OPERATION)) + rcsr |= FPU_CSR_INV_X | FPU_CSR_INV_S; + break; - /* unary conv ops */ + /* unary conv ops */ case fcvts_op: return SIGILL; /* not defined */ - case fcvtd_op: { + case fcvtd_op:{ #ifdef SINGLE_ONLY_FPU return SIGILL; /* not defined */ #else @@ -1323,7 +927,7 @@ goto copcsr; } #endif - case fcvtw_op: { + case fcvtw_op:{ ieee754sp fs; SPFROMREG(fs, MIPSInst_FS(ir)); @@ -1336,7 +940,7 @@ case fround_op: case ftrunc_op: case fceil_op: - case ffloor_op: { + case ffloor_op:{ unsigned int oldrm = ieee754_csr.rm; ieee754sp fs; @@ -1350,7 +954,7 @@ #endif /* __mips >= 2 */ #if __mips64 && !defined(SINGLE_ONLY_FPU) - case fcvtl_op: { + case fcvtl_op:{ ieee754sp fs; SPFROMREG(fs, MIPSInst_FS(ir)); @@ -1362,7 +966,7 @@ case froundl_op: case ftruncl_op: case fceill_op: - case ffloorl_op: { + case ffloorl_op:{ unsigned int oldrm = ieee754_csr.rm; ieee754sp fs; @@ -1382,55 +986,65 @@ SPFROMREG(fs, MIPSInst_FS(ir)); SPFROMREG(ft, MIPSInst_FT(ir)); - rv.w = ieee754sp_cmp(fs, ft, cmptab[cmpop & 0x7]); + rv.w = ieee754sp_cmp(fs, ft, + cmptab[cmpop & 0x7], cmpop & 0x8); rfmt = -1; - if ((cmpop & 0x8) && ieee754_cxtest(IEEE754_INVALID_OPERATION)) + if ((cmpop & 0x8) && ieee754_cxtest + (IEEE754_INVALID_OPERATION)) rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S; - } else { - return SIGILL; - } - break; + else + goto copcsr; + + } + else { + return SIGILL; } break; } + break; + } -#if !defined(SINGLE_ONLY_FPU) - case d_fmt: { - ieee754dp(*handler) (); +#ifndef SINGLE_ONLY_FPU + case d_fmt:{ + union { + ieee754dp(*b) (ieee754dp, ieee754dp); + ieee754dp(*u) (ieee754dp); + } handler; switch (MIPSInst_FUNC(ir)) { /* binary ops */ case fadd_op: - handler = ieee754dp_add; + handler.b = ieee754dp_add; goto dcopbop; case fsub_op: - handler = ieee754dp_sub; + handler.b = ieee754dp_sub; goto dcopbop; case fmul_op: - handler = ieee754dp_mul; + handler.b = ieee754dp_mul; goto dcopbop; case fdiv_op: - handler = ieee754dp_div; + handler.b = ieee754dp_div; goto dcopbop; /* unary ops */ #if __mips >= 2 || __mips64 case fsqrt_op: - handler = ieee754dp_sqrt; + handler.u = ieee754dp_sqrt; goto dcopuop; #endif #if __mips >= 4 && __mips != 32 case frsqrt_op: - handler = fpemu_dp_rsqrt; + handler.u = fpemu_dp_rsqrt; goto dcopuop; case frecip_op: - handler = fpemu_dp_recip; + handler.u = fpemu_dp_recip; goto dcopuop; #endif #if __mips >= 4 case fmovc_op: cond = fpucondbit[MIPSInst_FT(ir) >> 2]; - if (((ctx->sr & cond) != 0) != ((MIPSInst_FT(ir) & 1) != 0)) + if (((ctx->sr & cond) != 0) != + ((MIPSInst_FT(ir) & 1) != 0)) return 0; DPFROMREG(rv.d, MIPSInst_FS(ir)); break; @@ -1446,40 +1060,38 @@ break; #endif case fabs_op: - handler = ieee754dp_abs; + handler.u = ieee754dp_abs; goto dcopuop; case fneg_op: - handler = ieee754dp_neg; + handler.u = ieee754dp_neg; goto dcopuop; case fmov_op: /* an easy one */ DPFROMREG(rv.d, MIPSInst_FS(ir)); - break; + goto copcsr; /* binary op on handler */ -dcopbop: - { + dcopbop:{ ieee754dp fs, ft; DPFROMREG(fs, MIPSInst_FS(ir)); DPFROMREG(ft, MIPSInst_FT(ir)); - rv.d = (*handler) (fs, ft); + rv.d = (*handler.b) (fs, ft); goto copcsr; } -dcopuop: - { + dcopuop:{ ieee754dp fs; DPFROMREG(fs, MIPSInst_FS(ir)); - rv.d = (*handler) (fs); + rv.d = (*handler.u) (fs); goto copcsr; } - /* unary conv ops */ - case fcvts_op: { + /* unary conv ops */ + case fcvts_op:{ ieee754dp fs; DPFROMREG(fs, MIPSInst_FS(ir)); @@ -1490,7 +1102,7 @@ case fcvtd_op: return SIGILL; /* not defined */ - case fcvtw_op: { + case fcvtw_op:{ ieee754dp fs; DPFROMREG(fs, MIPSInst_FS(ir)); @@ -1503,7 +1115,7 @@ case fround_op: case ftrunc_op: case fceil_op: - case ffloor_op: { + case ffloor_op:{ unsigned int oldrm = ieee754_csr.rm; ieee754dp fs; @@ -1517,7 +1129,7 @@ #endif #if __mips64 && !defined(SINGLE_ONLY_FPU) - case fcvtl_op: { + case fcvtl_op:{ ieee754dp fs; DPFROMREG(fs, MIPSInst_FS(ir)); @@ -1529,7 +1141,7 @@ case froundl_op: case ftruncl_op: case fceill_op: - case ffloorl_op: { + case ffloorl_op:{ unsigned int oldrm = ieee754_csr.rm; ieee754dp fs; @@ -1549,30 +1161,42 @@ DPFROMREG(fs, MIPSInst_FS(ir)); DPFROMREG(ft, MIPSInst_FT(ir)); - rv.w = ieee754dp_cmp(fs, ft, cmptab[cmpop & 0x7]); + rv.w = ieee754dp_cmp(fs, ft, + cmptab[cmpop & 0x7], cmpop & 0x8); rfmt = -1; - if ((cmpop & 0x8) && ieee754_cxtest (IEEE754_INVALID_OPERATION)) + if ((cmpop & 0x8) + && + ieee754_cxtest + (IEEE754_INVALID_OPERATION)) rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S; - } else { + else + goto copcsr; + + } + else { return SIGILL; } break; } break; } -#endif /* !defined(SINGLE_ONLY_FPU) */ +#endif /* ifndef SINGLE_ONLY_FPU */ + + case w_fmt:{ + ieee754sp fs; - case w_fmt: { switch (MIPSInst_FUNC(ir)) { case fcvts_op: /* convert word to single precision real */ - rv.s = ieee754sp_fint(ctx-> regs[MIPSInst_FS(ir)]); + SPFROMREG(fs, MIPSInst_FS(ir)); + rv.s = ieee754sp_fint(fs.bits); rfmt = s_fmt; goto copcsr; -#if !defined(SINGLE_ONLY_FPU) +#ifndef SINGLE_ONLY_FPU case fcvtd_op: /* convert word to double precision real */ - rv.d = ieee754dp_fint(ctx-> regs[MIPSInst_FS(ir)]); + SPFROMREG(fs, MIPSInst_FS(ir)); + rv.d = ieee754dp_fint(fs.bits); rfmt = d_fmt; goto copcsr; #endif @@ -1583,16 +1207,16 @@ } #if __mips64 && !defined(SINGLE_ONLY_FPU) - case l_fmt: { + case l_fmt:{ switch (MIPSInst_FUNC(ir)) { case fcvts_op: /* convert long to single precision real */ - rv.s = ieee754sp_flong(ctx-> regs[MIPSInst_FS(ir)]); + rv.s = ieee754sp_flong(ctx->regs[MIPSInst_FS(ir)]); rfmt = s_fmt; goto copcsr; case fcvtd_op: /* convert long to double precision real */ - rv.d = ieee754dp_flong(ctx-> regs[MIPSInst_FS(ir)]); + rv.d = ieee754dp_flong(ctx->regs[MIPSInst_FS(ir)]); rfmt = d_fmt; goto copcsr; default: @@ -1619,11 +1243,11 @@ return SIGFPE; } - /* + /* * Now we can safely write the result back to the register file. */ switch (rfmt) { - case -1: { + case -1:{ #if __mips >= 4 cond = fpucondbit[MIPSInst_FD(ir) >> 2]; #else @@ -1635,7 +1259,7 @@ ctx->sr &= ~cond; break; } -#if !defined(SINGLE_ONLY_FPU) +#ifndef SINGLE_ONLY_FPU case d_fmt: DPTOREG(rv.d, MIPSInst_FD(ir)); break; @@ -1658,38 +1282,39 @@ return 0; } - -/* - * Emulate the floating point instruction at EPC, and continue to run until we - * hit a non-fp instruction, or a backward branch. This cuts down dramatically - * on the per instruction exception overhead. - */ -int fpu_emulator_cop1Handler(struct pt_regs *xcp) +int fpu_emulator_cop1Handler(int xcptno, struct pt_regs *xcp, + struct mips_fpu_soft_struct *ctx) { - struct mips_fpu_soft_struct *ctx = ¤t->thread.fpu.soft; - unsigned long oldepc, prevepc; - unsigned int insn; + gpreg_t oldepc, prevepc; + mips_instruction insn; int sig = 0; - int err = 0; oldepc = xcp->cp0_epc; do { - cond_resched(); - prevepc = xcp->cp0_epc; - insn = mips_get_word(xcp, REG_TO_VA(xcp->cp0_epc), &err); - if (err) { + + if (get_user(insn, (mips_instruction *) xcp->cp0_epc)) { fpuemuprivate.stats.errors++; return SIGBUS; } - if (insn != 0) - sig = cop1Emulate(xcp, ctx); - else + if (insn == 0) xcp->cp0_epc += 4; /* skip nops */ + else { + /* Update ieee754_csr. Only relevant if we have a + h/w FPU */ + ieee754_csr.nod = (ctx->sr & 0x1000000) != 0; + ieee754_csr.rm = ieee_rm[ctx->sr & 0x3]; + ieee754_csr.cx = (ctx->sr >> 12) & 0x1f; + sig = cop1Emulate(xcp, ctx); + } - if (mips_cpu.options & MIPS_CPU_FPU) + if (cpu_has_fpu) + break; + if (sig) break; - } while (xcp->cp0_epc > prevepc && sig == 0); + + cond_resched(); + } while (xcp->cp0_epc > prevepc); /* SIGILL indicates a non-fpu instruction */ if (sig == SIGILL && xcp->cp0_epc != oldepc) @@ -1698,80 +1323,3 @@ return sig; } - - -#ifdef NOTDEF -/* - * Patch up the hardware fpu state when an f.p. exception occurs. - */ -static int cop1Patcher(int xcptno, struct pt_regs *xcp) -{ - struct mips_fpu_soft_struct *ctx = ¤t->thread.fpu.soft; - unsigned sr; - int sig; - - /* reenable Cp1, else fpe_save() will get nested exception */ - sr = mips_bissr(ST0_CU1); - - /* get fpu registers and status, then clear pending exceptions */ - fpe_save(ctx); - fpe_setsr(ctx->sr &= ~FPU_CSR_ALL_X); - - /* get current rounding mode for IEEE library, and emulate insn */ - ieee754_csr.rm = ieee_rm[ctx->sr & 0x3]; - sig = cop1Emulate(xcp, ctx); - - /* don't return with f.p. exceptions pending */ - ctx->sr &= ~FPU_CSR_ALL_X; - fpe_restore(ctx); - - mips_setsr(sr); - return sig; -} - -void _cop1_init(int emulate) -{ - extern int _nofpu; - - if (emulate) { - /* - * Install cop1 emulator to handle "coprocessor unusable" exception - */ - xcption(XCPTCPU, cop1Handler); - fpuemuactive = 1; /* tell dbg.c that we are in charge */ - _nofpu = 0; /* tell setjmp() it "has" an fpu */ - } else { - /* - * Install cop1 emulator for floating point exceptions only, - * i.e. denormalised results, underflow, overflow etc, which - * must be emulated in s/w. - */ -#ifdef 1 - /* r4000 or above use dedicate exception */ - xcption(XCPTFPE, cop1Patcher); -#else - /* r3000 et al use interrupt */ - extern int _sbd_getfpuintr(void); - int intno = _sbd_getfpuintr(); - intrupt(intno, cop1Patcher, 0); - mips_bissr(SR_IM0 << intno); -#endif - -#if (#cpu(r4640) || #cpu(r4650)) && !defined(SINGLE_ONLY_FPU) - /* For R4640/R4650 compiled *without* the -msingle-float flag, - then we share responsibility: the h/w handles the single - precision operations, and the trap emulator handles the - double precision. We set fpuemuactive so that dbg.c first - fetches the s/w state before saving the h/w state. */ - fpuemuactive = 1; - { - int i; - /* initialise the unused d.p high order words to be NaN */ - for (i = 0; i < 32; i++) - current->thread.fpu.soft.regs[i] = - 0x7ff80bad00000000LL; - } -#endif /* (r4640 || r4650) && !fpu(single) */ - } -} -#endif diff -Nru a/arch/mips/math-emu/dp_add.c b/arch/mips/math-emu/dp_add.c --- a/arch/mips/math-emu/dp_add.c Tue Jul 1 18:44:34 2003 +++ b/arch/mips/math-emu/dp_add.c Tue Jul 1 18:44:34 2003 @@ -38,27 +38,23 @@ CLEARCX; - switch (CLPAIR(xc, yc)) { - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): - return ieee754dp_nanxcpt(ieee754dp_bestnan(x, y), "add", x, - y); + FLUSHXDP; + FLUSHYDP; + switch (CLPAIR(xc, yc)) { + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): - return ieee754dp_nanxcpt(y, "add", x, y); - - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - return ieee754dp_nanxcpt(x, "add", x, y); - - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): - return ieee754dp_bestnan(x, y); + SETCX(IEEE754_INVALID_OPERATION); + return ieee754dp_nanxcpt(ieee754dp_indef(), "add", x, y); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): @@ -66,6 +62,7 @@ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): return y; + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): @@ -73,7 +70,7 @@ return x; - /* Inifity handling + /* Infinity handling */ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): diff -Nru a/arch/mips/math-emu/dp_cmp.c b/arch/mips/math-emu/dp_cmp.c --- a/arch/mips/math-emu/dp_cmp.c Tue Jul 1 18:44:37 2003 +++ b/arch/mips/math-emu/dp_cmp.c Tue Jul 1 18:44:37 2003 @@ -27,21 +27,30 @@ #include "ieee754dp.h" -int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cmp) +int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cmp, int sig) { - CLEARCX; + COMPXDP; + COMPYDP; + + EXPLODEXDP; + EXPLODEYDP; + FLUSHXDP; + FLUSHYDP; + CLEARCX; /* Even clear inexact flag here */ if (ieee754dp_isnan(x) || ieee754dp_isnan(y)) { + if (sig || xc == IEEE754_CLASS_SNAN || yc == IEEE754_CLASS_SNAN) + SETCX(IEEE754_INVALID_OPERATION); if (cmp & IEEE754_CUN) return 1; if (cmp & (IEEE754_CLT | IEEE754_CGT)) { - if (SETCX(IEEE754_INVALID_OPERATION)) + if (sig && SETANDTESTCX(IEEE754_INVALID_OPERATION)) return ieee754si_xcpt(0, "fcmpf", x); } return 0; } else { - long long int vx = x.bits; - long long int vy = y.bits; + s64 vx = x.bits; + s64 vy = y.bits; if (vx < 0) vx = -vx ^ DP_SIGN_BIT; diff -Nru a/arch/mips/math-emu/dp_div.c b/arch/mips/math-emu/dp_div.c --- a/arch/mips/math-emu/dp_div.c Tue Jul 1 18:44:31 2003 +++ b/arch/mips/math-emu/dp_div.c Tue Jul 1 18:44:31 2003 @@ -32,32 +32,28 @@ COMPXDP; COMPYDP; - CLEARCX; - EXPLODEXDP; EXPLODEYDP; - switch (CLPAIR(xc, yc)) { - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): - return ieee754dp_nanxcpt(ieee754dp_bestnan(x, y), "div", x, - y); + CLEARCX; + + FLUSHXDP; + FLUSHYDP; + switch (CLPAIR(xc, yc)) { + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): - return ieee754dp_nanxcpt(y, "div", x, y); - - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - return ieee754dp_nanxcpt(x, "div", x, y); - - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): - return ieee754dp_bestnan(x, y); + SETCX(IEEE754_INVALID_OPERATION); + return ieee754dp_nanxcpt(ieee754dp_indef(), "div", x, y); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): @@ -65,6 +61,7 @@ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): return y; + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): @@ -129,9 +126,9 @@ { /* now the dirty work */ - unsigned long long rm = 0; + u64 rm = 0; int re = xe - ye; - unsigned long long bm; + u64 bm; for (bm = DP_MBIT(DP_MBITS + 2); bm; bm >>= 1) { if (xm >= ym) { diff -Nru a/arch/mips/math-emu/dp_flong.c b/arch/mips/math-emu/dp_flong.c --- a/arch/mips/math-emu/dp_flong.c Tue Jul 1 18:44:36 2003 +++ b/arch/mips/math-emu/dp_flong.c Tue Jul 1 18:44:36 2003 @@ -27,7 +27,7 @@ #include "ieee754dp.h" -ieee754dp ieee754dp_flong(long long x) +ieee754dp ieee754dp_flong(s64 x) { COMPXDP; @@ -67,9 +67,9 @@ DPNORMRET1(xs, xe, xm, "dp_flong", x); } -ieee754dp ieee754dp_fulong(unsigned long long u) +ieee754dp ieee754dp_fulong(u64 u) { - if ((long long) u < 0) + if ((s64) u < 0) return ieee754dp_add(ieee754dp_1e63(), ieee754dp_flong(u & ~(1ULL << 63))); return ieee754dp_flong(u); diff -Nru a/arch/mips/math-emu/dp_frexp.c b/arch/mips/math-emu/dp_frexp.c --- a/arch/mips/math-emu/dp_frexp.c Tue Jul 1 18:44:33 2003 +++ b/arch/mips/math-emu/dp_frexp.c Tue Jul 1 18:44:33 2003 @@ -27,7 +27,7 @@ #include "ieee754dp.h" -/* close to ieeep754dp_logb +/* close to ieeep754dp_logb */ ieee754dp ieee754dp_frexp(ieee754dp x, int *eptr) { diff -Nru a/arch/mips/math-emu/dp_fsp.c b/arch/mips/math-emu/dp_fsp.c --- a/arch/mips/math-emu/dp_fsp.c Tue Jul 1 18:44:32 2003 +++ b/arch/mips/math-emu/dp_fsp.c Tue Jul 1 18:44:32 2003 @@ -31,16 +31,20 @@ { COMPXSP; + EXPLODEXSP; + CLEARCX; - EXPLODEXSP; + FLUSHXSP; switch (xc) { - case IEEE754_CLASS_QNAN: case IEEE754_CLASS_SNAN: + SETCX(IEEE754_INVALID_OPERATION); + return ieee754dp_nanxcpt(ieee754dp_indef(), "fsp"); + case IEEE754_CLASS_QNAN: return ieee754dp_nanxcpt(builddp(xs, DP_EMAX + 1 + DP_EBIAS, - ((unsigned long long) xm + ((u64) xm << (DP_MBITS - SP_MBITS))), "fsp", x); @@ -66,5 +70,5 @@ xm &= ~SP_HIDDEN_BIT; return builddp(xs, xe + DP_EBIAS, - (unsigned long long) xm << (DP_MBITS - SP_MBITS)); + (u64) xm << (DP_MBITS - SP_MBITS)); } diff -Nru a/arch/mips/math-emu/dp_modf.c b/arch/mips/math-emu/dp_modf.c --- a/arch/mips/math-emu/dp_modf.c Tue Jul 1 18:44:36 2003 +++ b/arch/mips/math-emu/dp_modf.c Tue Jul 1 18:44:36 2003 @@ -59,7 +59,7 @@ *ip = x; return ieee754dp_zero(xs); } - /* generate ipart mantissa by clearing bottom bits + /* generate ipart mantissa by clearing bottom bits */ *ip = builddp(xs, xe + DP_EBIAS, ((xm >> (DP_MBITS - xe)) << (DP_MBITS - xe)) & diff -Nru a/arch/mips/math-emu/dp_mul.c b/arch/mips/math-emu/dp_mul.c --- a/arch/mips/math-emu/dp_mul.c Tue Jul 1 18:44:34 2003 +++ b/arch/mips/math-emu/dp_mul.c Tue Jul 1 18:44:34 2003 @@ -32,32 +32,28 @@ COMPXDP; COMPYDP; - CLEARCX; - EXPLODEXDP; EXPLODEYDP; - switch (CLPAIR(xc, yc)) { - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): - return ieee754dp_nanxcpt(ieee754dp_bestnan(x, y), "mul", x, - y); + CLEARCX; + + FLUSHXDP; + FLUSHYDP; + switch (CLPAIR(xc, yc)) { + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): - return ieee754dp_nanxcpt(y, "mul", x, y); - - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - return ieee754dp_nanxcpt(x, "mul", x, y); - - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): - return ieee754dp_bestnan(x, y); + SETCX(IEEE754_INVALID_OPERATION); + return ieee754dp_nanxcpt(ieee754dp_indef(), "mul", x, y); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): @@ -65,6 +61,7 @@ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): return y; + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): @@ -114,7 +111,7 @@ { int re = xe + ye; int rs = xs ^ ys; - unsigned long long rm; + u64 rm; /* shunt to top of word */ xm <<= 64 - (DP_MBITS + 1); @@ -124,23 +121,23 @@ */ /* 32 * 32 => 64 */ -#define DPXMULT(x,y) ((unsigned long long)(x) * (unsigned long long)y) +#define DPXMULT(x,y) ((u64)(x) * (u64)y) { unsigned lxm = xm; unsigned hxm = xm >> 32; unsigned lym = ym; unsigned hym = ym >> 32; - unsigned long long lrm; - unsigned long long hrm; + u64 lrm; + u64 hrm; lrm = DPXMULT(lxm, lym); hrm = DPXMULT(hxm, hym); { - unsigned long long t = DPXMULT(lxm, hym); + u64 t = DPXMULT(lxm, hym); { - unsigned long long at = + u64 at = lrm + (t << 32); hrm += at < lrm; lrm = at; @@ -149,9 +146,9 @@ } { - unsigned long long t = DPXMULT(hxm, lym); + u64 t = DPXMULT(hxm, lym); { - unsigned long long at = + u64 at = lrm + (t << 32); hrm += at < lrm; lrm = at; @@ -164,7 +161,7 @@ /* * sticky shift down to normal rounding precision */ - if ((signed long long) rm < 0) { + if ((s64) rm < 0) { rm = (rm >> (64 - (DP_MBITS + 1 + 3))) | ((rm << (DP_MBITS + 1 + 3)) != 0); diff -Nru a/arch/mips/math-emu/dp_simple.c b/arch/mips/math-emu/dp_simple.c --- a/arch/mips/math-emu/dp_simple.c Tue Jul 1 18:44:37 2003 +++ b/arch/mips/math-emu/dp_simple.c Tue Jul 1 18:44:37 2003 @@ -42,7 +42,16 @@ ieee754dp ieee754dp_neg(ieee754dp x) { + COMPXDP; + + EXPLODEXDP; CLEARCX; + FLUSHXDP; + + if (xc == IEEE754_CLASS_SNAN) { + SETCX(IEEE754_INVALID_OPERATION); + return ieee754dp_nanxcpt(ieee754dp_indef(), "neg"); + } if (ieee754dp_isnan(x)) /* but not infinity */ return ieee754dp_nanxcpt(x, "neg", x); @@ -55,7 +64,16 @@ ieee754dp ieee754dp_abs(ieee754dp x) { + COMPXDP; + + EXPLODEXDP; CLEARCX; + FLUSHXDP; + + if (xc == IEEE754_CLASS_SNAN) { + SETCX(IEEE754_INVALID_OPERATION); + return ieee754dp_nanxcpt(ieee754dp_indef(), "neg"); + } if (ieee754dp_isnan(x)) /* but not infinity */ return ieee754dp_nanxcpt(x, "abs", x); diff -Nru a/arch/mips/math-emu/dp_sqrt.c b/arch/mips/math-emu/dp_sqrt.c --- a/arch/mips/math-emu/dp_sqrt.c Tue Jul 1 18:44:37 2003 +++ b/arch/mips/math-emu/dp_sqrt.c Tue Jul 1 18:44:37 2003 @@ -27,16 +27,6 @@ #include "ieee754dp.h" -static const struct ieee754dp_konst knan = { -#if (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) || defined(__MIPSEL__) - 0, 0, DP_EBIAS + DP_EMAX + 1, 0 -#else - 0, DP_EBIAS + DP_EMAX + 1, 0, 0 -#endif -}; - -#define nan ((ieee754dp)knan) - static const unsigned table[] = { 0, 1204, 3062, 5746, 9193, 13348, 18162, 23592, 29598, 36145, 43202, 50740, 58733, 67158, 75992, @@ -53,29 +43,37 @@ COMPXDP; EXPLODEXDP; + CLEARCX; + FLUSHXDP; /* x == INF or NAN? */ switch (xc) { case IEEE754_CLASS_QNAN: - case IEEE754_CLASS_SNAN: /* sqrt(Nan) = Nan */ return ieee754dp_nanxcpt(x, "sqrt"); + case IEEE754_CLASS_SNAN: + SETCX(IEEE754_INVALID_OPERATION); + return ieee754dp_nanxcpt(ieee754dp_indef(), "sqrt"); case IEEE754_CLASS_ZERO: /* sqrt(0) = 0 */ return x; case IEEE754_CLASS_INF: - if (xs) + if (xs) { /* sqrt(-Inf) = Nan */ - return ieee754dp_nanxcpt(nan, "sqrt"); + SETCX(IEEE754_INVALID_OPERATION); + return ieee754dp_nanxcpt(ieee754dp_indef(), "sqrt"); + } /* sqrt(+Inf) = Inf */ return x; case IEEE754_CLASS_DNORM: DPDNORMX; /* fall through */ case IEEE754_CLASS_NORM: - if (xs) + if (xs) { /* sqrt(-x) = Nan */ - return ieee754dp_nanxcpt(nan, "sqrt"); + SETCX(IEEE754_INVALID_OPERATION); + return ieee754dp_nanxcpt(ieee754dp_indef(), "sqrt"); + } break; } @@ -101,7 +99,7 @@ yh = y.bits >> 32; yh = (yh >> 1) + 0x1ff80000; yh = yh - table[(yh >> 15) & 31]; - y.bits = ((unsigned long long) yh << 32) | (y.bits & 0xffffffff); + y.bits = ((u64) yh << 32) | (y.bits & 0xffffffff); /* Heron's rule once with correction to improve to ~18 sig. bits */ /* t=x/y; y=y+t; py[n0]=py[n0]-0x00100006; py[n1]=0; */ diff -Nru a/arch/mips/math-emu/dp_sub.c b/arch/mips/math-emu/dp_sub.c --- a/arch/mips/math-emu/dp_sub.c Tue Jul 1 18:44:36 2003 +++ b/arch/mips/math-emu/dp_sub.c Tue Jul 1 18:44:36 2003 @@ -32,32 +32,28 @@ COMPXDP; COMPYDP; - CLEARCX; - EXPLODEXDP; EXPLODEYDP; - switch (CLPAIR(xc, yc)) { - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): - return ieee754dp_nanxcpt(ieee754dp_bestnan(x, y), "sub", x, - y); + CLEARCX; + + FLUSHXDP; + FLUSHYDP; + switch (CLPAIR(xc, yc)) { + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): - return ieee754dp_nanxcpt(y, "sub", x, y); - - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - return ieee754dp_nanxcpt(x, "sub", x, y); - - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): - return ieee754dp_bestnan(x, y); + SETCX(IEEE754_INVALID_OPERATION); + return ieee754dp_nanxcpt(ieee754dp_indef(), "sub", x, y); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): @@ -65,6 +61,7 @@ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): return y; + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): @@ -72,7 +69,7 @@ return x; - /* Inifity handling + /* Infinity handling */ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): @@ -183,7 +180,7 @@ return ieee754dp_zero(0); /* other round modes => sign = 1 */ } - /* normalize to rounding precision + /* normalize to rounding precision */ while ((xm >> (DP_MBITS + 3)) == 0) { xm <<= 1; diff -Nru a/arch/mips/math-emu/dp_tint.c b/arch/mips/math-emu/dp_tint.c --- a/arch/mips/math-emu/dp_tint.c Tue Jul 1 18:44:31 2003 +++ b/arch/mips/math-emu/dp_tint.c Tue Jul 1 18:44:31 2003 @@ -35,38 +35,74 @@ CLEARCX; EXPLODEXDP; + FLUSHXDP; switch (xc) { case IEEE754_CLASS_SNAN: case IEEE754_CLASS_QNAN: - SETCX(IEEE754_INVALID_OPERATION); - return ieee754si_xcpt(ieee754si_indef(), "fixdp", x); case IEEE754_CLASS_INF: - SETCX(IEEE754_OVERFLOW); - return ieee754si_xcpt(ieee754si_indef(), "fixdp", x); + SETCX(IEEE754_INVALID_OPERATION); + return ieee754si_xcpt(ieee754si_indef(), "dp_tint", x); case IEEE754_CLASS_ZERO: return 0; - case IEEE754_CLASS_DNORM: /* much to small */ - SETCX(IEEE754_UNDERFLOW); - return ieee754si_xcpt(0, "fixdp", x); + case IEEE754_CLASS_DNORM: case IEEE754_CLASS_NORM: break; } - if (xe >= 31) { - SETCX(IEEE754_OVERFLOW); - return ieee754si_xcpt(ieee754si_indef(), "fix", x); - } - if (xe < 0) { - SETCX(IEEE754_UNDERFLOW); - return ieee754si_xcpt(0, "fix", x); + if (xe > 31) { + /* Set invalid. We will only use overflow for floating + point overflow */ + SETCX(IEEE754_INVALID_OPERATION); + return ieee754si_xcpt(ieee754si_indef(), "dp_tint", x); } /* oh gawd */ if (xe > DP_MBITS) { xm <<= xe - DP_MBITS; } else if (xe < DP_MBITS) { - /* XXX no rounding - */ - xm >>= DP_MBITS - xe; + u64 residue; + int round; + int sticky; + int odd; + + if (xe < -1) { + residue = xm; + round = 0; + sticky = residue != 0; + xm = 0; + } + else { + residue = xm << (64 - DP_MBITS + xe); + round = (residue >> 63) != 0; + sticky = (residue << 1) != 0; + xm >>= DP_MBITS - xe; + } + /* Note: At this point upper 32 bits of xm are guaranteed + to be zero */ + odd = (xm & 0x1) != 0x0; + switch (ieee754_csr.rm) { + case IEEE754_RN: + if (round && (sticky || odd)) + xm++; + break; + case IEEE754_RZ: + break; + case IEEE754_RU: /* toward +Infinity */ + if ((round || sticky) && !xs) + xm++; + break; + case IEEE754_RD: /* toward -Infinity */ + if ((round || sticky) && xs) + xm++; + break; + } + /* look for valid corner case 0x80000000 */ + if ((xm >> 31) != 0 && (xs == 0 || xm != 0x80000000)) { + /* This can happen after rounding */ + SETCX(IEEE754_INVALID_OPERATION); + return ieee754si_xcpt(ieee754si_indef(), "dp_tint", x); + } + if (round || sticky) + SETCX(IEEE754_INEXACT); } if (xs) return -xm; diff -Nru a/arch/mips/math-emu/dp_tlong.c b/arch/mips/math-emu/dp_tlong.c --- a/arch/mips/math-emu/dp_tlong.c Tue Jul 1 18:44:34 2003 +++ b/arch/mips/math-emu/dp_tlong.c Tue Jul 1 18:44:34 2003 @@ -27,99 +27,85 @@ #include "ieee754dp.h" -long long ieee754dp_tlong(ieee754dp x) +s64 ieee754dp_tlong(ieee754dp x) { COMPXDP; CLEARCX; EXPLODEXDP; + FLUSHXDP; switch (xc) { case IEEE754_CLASS_SNAN: case IEEE754_CLASS_QNAN: - SETCX(IEEE754_INVALID_OPERATION); - return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x); case IEEE754_CLASS_INF: - SETCX(IEEE754_OVERFLOW); + SETCX(IEEE754_INVALID_OPERATION); return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x); case IEEE754_CLASS_ZERO: return 0; - case IEEE754_CLASS_DNORM: /* much too small */ - SETCX(IEEE754_UNDERFLOW); - return ieee754di_xcpt(0, "dp_tlong", x); + case IEEE754_CLASS_DNORM: case IEEE754_CLASS_NORM: break; } if (xe >= 63) { - SETCX(IEEE754_OVERFLOW); + /* look for valid corner case */ + if (xe == 63 && xs && xm == DP_HIDDEN_BIT) + return -0x8000000000000000LL; + /* Set invalid. We will only use overflow for floating + point overflow */ + SETCX(IEEE754_INVALID_OPERATION); return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x); } - if (xe < 0) { - if (ieee754_csr.rm == IEEE754_RU) { - if (xs) { /* Negative */ - return 0x0000000000000000LL; - } else { /* Positive */ - return 0x0000000000000001LL; - } - } else if (ieee754_csr.rm == IEEE754_RD) { - if (xs) { /* Negative , return -1 */ - return 0xffffffffffffffffLL; - } else { /* Positive */ - return 0x0000000000000000LL; - } - } else { - SETCX(IEEE754_UNDERFLOW); - return ieee754di_xcpt(0, "dp_tlong", x); - } - } /* oh gawd */ if (xe > DP_MBITS) { xm <<= xe - DP_MBITS; } else if (xe < DP_MBITS) { - unsigned long long residue; - unsigned long long mask = 0; - int i; + u64 residue; int round; int sticky; int odd; - /* compute mask */ - for (i = 0; i < DP_MBITS - xe; i++) { - mask = mask << 1; - mask = mask | 0x1; + if (xe < -1) { + residue = xm; + round = 0; + sticky = residue != 0; + xm = 0; } - residue = (xm & mask) << (64 - (DP_MBITS - xe)); - round = - ((0x8000000000000000LL & residue) != - 0x0000000000000000LL); - sticky = - ((0x7fffffffffffffffLL & residue) != - 0x0000000000000000LL); - - xm >>= DP_MBITS - xe; - - odd = ((xm & 0x1) != 0x0000000000000000LL); - - /* Do the rounding */ - if (!round && sticky) { - if ((ieee754_csr.rm == IEEE754_RU && !xs) - || (ieee754_csr.rm == IEEE754_RD && xs)) { + else { + /* Shifting a u64 64 times does not work, + * so we do it in two steps. Be aware that xe + * may be -1 */ + residue = xm << (xe + 1); + residue <<= 63 - DP_MBITS; + round = (residue >> 63) != 0; + sticky = (residue << 1) != 0; + xm >>= DP_MBITS - xe; + } + odd = (xm & 0x1) != 0x0; + switch (ieee754_csr.rm) { + case IEEE754_RN: + if (round && (sticky || odd)) xm++; - } - } else if (round && !sticky) { - if ((ieee754_csr.rm == IEEE754_RU && !xs) - || (ieee754_csr.rm == IEEE754_RD && xs) - || (ieee754_csr.rm == IEEE754_RN && odd)) { + break; + case IEEE754_RZ: + break; + case IEEE754_RU: /* toward +Infinity */ + if ((round || sticky) && !xs) xm++; - } - } else if (round && sticky) { - if ((ieee754_csr.rm == IEEE754_RU && !xs) - || (ieee754_csr.rm == IEEE754_RD && xs) - || (ieee754_csr.rm == IEEE754_RN)) { + break; + case IEEE754_RD: /* toward -Infinity */ + if ((round || sticky) && xs) xm++; - } + break; + } + if ((xm >> 63) != 0) { + /* This can happen after rounding */ + SETCX(IEEE754_INVALID_OPERATION); + return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x); } + if (round || sticky) + SETCX(IEEE754_INEXACT); } if (xs) return -xm; @@ -128,14 +114,14 @@ } -unsigned long long ieee754dp_tulong(ieee754dp x) +u64 ieee754dp_tulong(ieee754dp x) { ieee754dp hb = ieee754dp_1e63(); /* what if x < 0 ?? */ if (ieee754dp_lt(x, hb)) - return (unsigned long long) ieee754dp_tlong(x); + return (u64) ieee754dp_tlong(x); - return (unsigned long long) ieee754dp_tlong(ieee754dp_sub(x, hb)) | + return (u64) ieee754dp_tlong(ieee754dp_sub(x, hb)) | (1ULL << 63); } diff -Nru a/arch/mips/math-emu/dsemul.c b/arch/mips/math-emu/dsemul.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/math-emu/dsemul.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,173 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ieee754.h" +#include "dsemul.h" + +/* Strap kernel emulator for full MIPS IV emulation */ + +#ifdef __mips +#undef __mips +#endif +#define __mips 4 + +extern struct mips_fpu_emulator_private fpuemuprivate; + + +/* + * Emulate the arbritrary instruction ir at xcp->cp0_epc. Required when + * we have to emulate the instruction in a COP1 branch delay slot. Do + * not change cp0_epc due to the instruction + * + * According to the spec: + * 1) it shouldnt be a branch :-) + * 2) it can be a COP instruction :-( + * 3) if we are tring to run a protected memory space we must take + * special care on memory access instructions :-( + */ + +/* + * "Trampoline" return routine to catch exception following + * execution of delay-slot instruction execution. + */ + +struct emuframe { + mips_instruction emul; + mips_instruction badinst; + mips_instruction cookie; + gpreg_t epc; +}; + +int mips_dsemul(struct pt_regs *regs, mips_instruction ir, gpreg_t cpc) +{ + extern asmlinkage void handle_dsemulret(void); + mips_instruction *dsemul_insns; + struct emuframe *fr; + int err; + + if (ir == 0) { /* a nop is easy */ + regs->cp0_epc = cpc; + regs->cp0_cause &= ~CAUSEF_BD; + return 0; + } +#ifdef DSEMUL_TRACE + printk("dsemul %lx %lx\n", regs->cp0_epc, cpc); + +#endif + + /* + * The strategy is to push the instruction onto the user stack + * and put a trap after it which we can catch and jump to + * the required address any alternative apart from full + * instruction emulation!!. + * + * Algorithmics used a system call instruction, and + * borrowed that vector. MIPS/Linux version is a bit + * more heavyweight in the interests of portability and + * multiprocessor support. For Linux we generate a + * an unaligned access and force an address error exception. + * + * For embedded systems (stand-alone) we prefer to use a + * non-existing CP1 instruction. This prevents us from emulating + * branches, but gives us a cleaner interface to the exception + * handler (single entry point). + */ + + /* Ensure that the two instructions are in the same cache line */ + dsemul_insns = (mips_instruction *) REG_TO_VA ((regs->regs[29] - sizeof(struct emuframe)) & ~0x7); + fr = (struct emuframe *) dsemul_insns; + + /* Verify that the stack pointer is not competely insane */ + if (unlikely(verify_area(VERIFY_WRITE, fr, sizeof(struct emuframe)))) + return SIGBUS; + + err = __put_user(ir, &fr->emul); + err |= __put_user((mips_instruction)BADINST, &fr->badinst); + err |= __put_user((mips_instruction)BD_COOKIE, &fr->cookie); + err |= __put_user(cpc, &fr->epc); + + if (unlikely(err)) { + fpuemuprivate.stats.errors++; + return SIGBUS; + } + + regs->cp0_epc = VA_TO_REG & fr->emul; + + flush_cache_sigtramp((unsigned long)&fr->badinst); + + return SIGILL; /* force out of emulation loop */ +} + +int do_dsemulret(struct pt_regs *xcp) +{ + struct emuframe *fr; + gpreg_t epc; + u32 insn, cookie; + int err = 0; + + fr = (struct emuframe *) (xcp->cp0_epc - sizeof(mips_instruction)); + + /* + * If we can't even access the area, something is very wrong, but we'll + * leave that to the default handling + */ + if (verify_area(VERIFY_READ, fr, sizeof(struct emuframe))) + return 0; + + /* + * Do some sanity checking on the stackframe: + * + * - Is the instruction pointed to by the EPC an BADINST? + * - Is the following memory word the BD_COOKIE? + */ + err = __get_user(insn, &fr->badinst); + err |= __get_user(cookie, &fr->cookie); + + if (unlikely(err || (insn != BADINST) || (cookie != BD_COOKIE))) { + fpuemuprivate.stats.errors++; + + return 0; + } + + /* + * At this point, we are satisfied that it's a BD emulation trap. Yes, + * a user might have deliberately put two malformed and useless + * instructions in a row in his program, in which case he's in for a + * nasty surprise - the next instruction will be treated as a + * continuation address! Alas, this seems to be the only way that we + * can handle signals, recursion, and longjmps() in the context of + * emulating the branch delay instruction. + */ + +#ifdef DSEMUL_TRACE + printk("dsemulret\n"); +#endif + if (__get_user(epc, &fr->epc)) { /* Saved EPC */ + /* This is not a good situation to be in */ + force_sig(SIGBUS, current); + + return 0; + } + + /* Set EPC to return to post-branch instruction */ + xcp->cp0_epc = epc; + + return 1; +} diff -Nru a/arch/mips/math-emu/dsemul.h b/arch/mips/math-emu/dsemul.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/math-emu/dsemul.h Tue Jul 1 18:44:40 2003 @@ -0,0 +1,23 @@ +typedef long gpreg_t; +typedef void *vaddr_t; + +#define REG_TO_VA (vaddr_t) +#define VA_TO_REG (gpreg_t) + +int mips_dsemul(struct pt_regs *regs, mips_instruction ir, gpreg_t cpc); +int do_dsemulret(struct pt_regs *xcp); + +/* Instruction which will always cause an address error */ +#define AdELOAD 0x8c000001 /* lw $0,1($0) */ +/* Instruction which will plainly cause a CP1 exception when FPU is disabled */ +#define CP1UNDEF 0x44400001 /* cfc1 $0,$0 undef */ + +/* Instruction inserted following the badinst to further tag the sequence */ +#define BD_COOKIE 0x0000bd36 /* tne $0,$0 with baggage */ + +/* Setup which instruction to use for trampoline */ +#ifdef STANDALONE_EMULATOR +#define BADINST CP1UNDEF +#else +#define BADINST AdELOAD +#endif diff -Nru a/arch/mips/math-emu/ieee754.c b/arch/mips/math-emu/ieee754.c --- a/arch/mips/math-emu/ieee754.c Tue Jul 1 18:44:31 2003 +++ b/arch/mips/math-emu/ieee754.c Tue Jul 1 18:44:31 2003 @@ -50,7 +50,7 @@ "SNaN", }; -/* the control status register +/* the control status register */ struct ieee754_csr ieee754_csr; @@ -77,7 +77,7 @@ DPSTR(1, 3 + DP_EBIAS, 0x40000, 0), /* - 10.0 */ DPSTR(0, DP_EMAX + 1 + DP_EBIAS, 0, 0), /* + infinity */ DPSTR(1, DP_EMAX + 1 + DP_EBIAS, 0, 0), /* - infinity */ - DPSTR(0, DP_EMAX + 1 + DP_EBIAS, 0x40000, 0), /* + indef quiet Nan */ + DPSTR(0,DP_EMAX+1+DP_EBIAS,0x7FFFF,0xFFFFFFFF), /* + indef quiet Nan */ DPSTR(0, DP_EMAX + DP_EBIAS, 0xFFFFF, 0xFFFFFFFF), /* + max */ DPSTR(1, DP_EMAX + DP_EBIAS, 0xFFFFF, 0xFFFFFFFF), /* - max */ DPSTR(0, DP_EMIN + DP_EBIAS, 0, 0), /* + min normal */ @@ -97,7 +97,7 @@ SPSTR(1, 3 + SP_EBIAS, 0x200000), /* - 10.0 */ SPSTR(0, SP_EMAX + 1 + SP_EBIAS, 0), /* + infinity */ SPSTR(1, SP_EMAX + 1 + SP_EBIAS, 0), /* - infinity */ - SPSTR(0, SP_EMAX + 1 + SP_EBIAS, 0x200000), /* + indef quiet Nan */ + SPSTR(0,SP_EMAX+1+SP_EBIAS,0x3FFFFF), /* + indef quiet Nan */ SPSTR(0, SP_EMAX + SP_EBIAS, 0x7FFFFF), /* + max normal */ SPSTR(1, SP_EMAX + SP_EBIAS, 0x7FFFFF), /* - max normal */ SPSTR(0, SP_EMIN + SP_EBIAS, 0), /* + min normal */ @@ -123,7 +123,7 @@ return ax.rv.si; } -long long ieee754di_xcpt(long long r, const char *op, ...) +s64 ieee754di_xcpt(s64 r, const char *op, ...) { struct ieee754xctx ax; diff -Nru a/arch/mips/math-emu/ieee754.h b/arch/mips/math-emu/ieee754.h --- a/arch/mips/math-emu/ieee754.h Tue Jul 1 18:44:32 2003 +++ b/arch/mips/math-emu/ieee754.h Tue Jul 1 18:44:32 2003 @@ -26,7 +26,7 @@ /************************************************************************** * Nov 7, 2000 - * Modification to allow integration with Linux kernel + * Modification to allow integration with Linux kernel * * Kevin D. Kissell, kevink@mips.com and Carsten Langgard, carstenl@mips.com * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. @@ -36,8 +36,8 @@ /* Going from Algorithmics to Linux native environment, add this */ #include -/* - * Not very pretty, but the Linux kernel's normal va_list definition +/* + * Not very pretty, but the Linux kernel's normal va_list definition * does not allow it to be used as a structure element, as it is here. */ #ifndef _STDARG_H @@ -71,18 +71,18 @@ typedef union _ieee754dp { struct ieee754dp_konst oparts; struct { - unsigned long long mant:52; + u64 mant:52; unsigned int bexp:11; unsigned int sign:1; } parts; - unsigned long long bits; + u64 bits; double d; } ieee754dp; typedef union _ieee754sp { struct ieee754sp_konst parts; float f; - unsigned long bits; + u32 bits; } ieee754sp; #endif @@ -98,10 +98,10 @@ struct { unsigned int sign:1; unsigned int bexp:11; - unsigned long long mant:52; + u64 mant:52; } parts; double d; - unsigned long long bits; + u64 bits; } ieee754dp; struct ieee754sp_konst { @@ -113,7 +113,7 @@ typedef union _ieee754sp { struct ieee754sp_konst parts; float f; - unsigned long bits; + u32 bits; } ieee754sp; #endif @@ -138,16 +138,16 @@ ieee754sp ieee754sp_fint(int x); ieee754sp ieee754sp_funs(unsigned x); -ieee754sp ieee754sp_flong(long long x); -ieee754sp ieee754sp_fulong(unsigned long long x); +ieee754sp ieee754sp_flong(s64 x); +ieee754sp ieee754sp_fulong(u64 x); ieee754sp ieee754sp_fdp(ieee754dp x); int ieee754sp_tint(ieee754sp x); unsigned int ieee754sp_tuns(ieee754sp x); -long long ieee754sp_tlong(ieee754sp x); -unsigned long long ieee754sp_tulong(ieee754sp x); +s64 ieee754sp_tlong(ieee754sp x); +u64 ieee754sp_tulong(ieee754sp x); -int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cop); +int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cop, int sig); /* * basic sp math */ @@ -179,14 +179,14 @@ ieee754dp ieee754dp_neg(ieee754dp x); ieee754dp ieee754dp_scalb(ieee754dp x, int); -/* return exponent as integer in floating point format +/* return exponent as integer in floating point format */ ieee754dp ieee754dp_logb(ieee754dp x); ieee754dp ieee754dp_fint(int x); ieee754dp ieee754dp_funs(unsigned x); -ieee754dp ieee754dp_flong(long long x); -ieee754dp ieee754dp_fulong(unsigned long long x); +ieee754dp ieee754dp_flong(s64 x); +ieee754dp ieee754dp_fulong(u64 x); ieee754dp ieee754dp_fsp(ieee754sp x); ieee754dp ieee754dp_ceil(ieee754dp x); @@ -195,10 +195,10 @@ int ieee754dp_tint(ieee754dp x); unsigned int ieee754dp_tuns(ieee754dp x); -long long ieee754dp_tlong(ieee754dp x); -unsigned long long ieee754dp_tulong(ieee754dp x); +s64 ieee754dp_tlong(ieee754dp x); +u64 ieee754dp_tulong(ieee754dp x); -int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cop); +int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cop, int sig); /* * basic sp math */ @@ -214,7 +214,7 @@ -/* 5 types of floating point number +/* 5 types of floating point number */ #define IEEE754_CLASS_NORM 0x00 #define IEEE754_CLASS_ZERO 0x01 @@ -238,7 +238,7 @@ #define IEEE754_CGT 0x04 #define IEEE754_CUN 0x08 -/* rounding mode +/* rounding mode */ #define IEEE754_RN 0 /* round to nearest */ #define IEEE754_RZ 1 /* round toward zero */ @@ -253,65 +253,65 @@ */ static __inline int ieee754sp_eq(ieee754sp x, ieee754sp y) { - return ieee754sp_cmp(x, y, IEEE754_CEQ); + return ieee754sp_cmp(x, y, IEEE754_CEQ, 0); } static __inline int ieee754sp_ne(ieee754sp x, ieee754sp y) { return ieee754sp_cmp(x, y, - IEEE754_CLT | IEEE754_CGT | IEEE754_CUN); + IEEE754_CLT | IEEE754_CGT | IEEE754_CUN, 0); } static __inline int ieee754sp_lt(ieee754sp x, ieee754sp y) { - return ieee754sp_cmp(x, y, IEEE754_CLT); + return ieee754sp_cmp(x, y, IEEE754_CLT, 0); } static __inline int ieee754sp_le(ieee754sp x, ieee754sp y) { - return ieee754sp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ); + return ieee754sp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ, 0); } static __inline int ieee754sp_gt(ieee754sp x, ieee754sp y) { - return ieee754sp_cmp(x, y, IEEE754_CGT); + return ieee754sp_cmp(x, y, IEEE754_CGT, 0); } static __inline int ieee754sp_ge(ieee754sp x, ieee754sp y) { - return ieee754sp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ); + return ieee754sp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ, 0); } static __inline int ieee754dp_eq(ieee754dp x, ieee754dp y) { - return ieee754dp_cmp(x, y, IEEE754_CEQ); + return ieee754dp_cmp(x, y, IEEE754_CEQ, 0); } static __inline int ieee754dp_ne(ieee754dp x, ieee754dp y) { return ieee754dp_cmp(x, y, - IEEE754_CLT | IEEE754_CGT | IEEE754_CUN); + IEEE754_CLT | IEEE754_CGT | IEEE754_CUN, 0); } static __inline int ieee754dp_lt(ieee754dp x, ieee754dp y) { - return ieee754dp_cmp(x, y, IEEE754_CLT); + return ieee754dp_cmp(x, y, IEEE754_CLT, 0); } static __inline int ieee754dp_le(ieee754dp x, ieee754dp y) { - return ieee754dp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ); + return ieee754dp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ, 0); } static __inline int ieee754dp_gt(ieee754dp x, ieee754dp y) { - return ieee754dp_cmp(x, y, IEEE754_CGT); + return ieee754dp_cmp(x, y, IEEE754_CGT, 0); } static __inline int ieee754dp_ge(ieee754dp x, ieee754dp y) { - return ieee754dp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ); + return ieee754dp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ, 0); } @@ -321,11 +321,10 @@ char *ieee754dp_tstr(ieee754dp x, int prec, int fmt, int af); -/* the control status register +/* the control status register */ struct ieee754_csr { unsigned pad:13; - unsigned noq:1; /* set 1 for no quiet NaN's */ unsigned nod:1; /* set 1 for no denormalised numbers */ unsigned cx:5; /* exceptions this operation */ unsigned mx:5; /* exception enable mask */ @@ -351,7 +350,7 @@ return (ieee754_csr.cx); } -/* test for current exception condition +/* test for current exception condition */ static __inline int ieee754_cxtest(unsigned n) { @@ -373,7 +372,7 @@ return (ieee754_csr.sx = 0); } -/* test for sticky exception condition +/* test for sticky exception condition */ static __inline int ieee754_sxtest(unsigned n) { @@ -451,13 +450,13 @@ #define ieee754sp_1e63() \ (ieee754sp_spcvals[IEEE754_SPCVAL_P1E63]) -/* indefinite integer value +/* indefinite integer value */ -#define ieee754si_indef() INT_MIN -#ifdef LONG_LONG_MIN -#define ieee754di_indef() LONG_LONG_MIN +#define ieee754si_indef() INT_MAX +#ifdef LONG_LONG_MAX +#define ieee754di_indef() LONG_LONG_MAX #else -#define ieee754di_indef() (-9223372036854775807LL-1) +#define ieee754di_indef() ((s64)(~0ULL>>1)) #endif /* IEEE exception context, passed to handler */ @@ -471,7 +470,7 @@ ieee754xp xp; /* extended precision */ #endif int si; /* standard signed integer (32bits) */ - long long di; /* extended signed integer (64bits) */ + s64 di; /* extended signed integer (64bits) */ } rv; /* default result format implied by op */ va_list ap; }; diff -Nru a/arch/mips/math-emu/ieee754d.c b/arch/mips/math-emu/ieee754d.c --- a/arch/mips/math-emu/ieee754d.c Tue Jul 1 18:44:37 2003 +++ b/arch/mips/math-emu/ieee754d.c Tue Jul 1 18:44:37 2003 @@ -1,12 +1,11 @@ -/* some debug functions -*/ /* + * Some debug functions + * * MIPS floating point support + * * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. * http://www.algor.co.uk * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -20,17 +19,14 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. * - * ######################################################################## - */ - -/************************************************************************** * Nov 7, 2000 - * Modified to build and operate in Linux kernel environment. + * Modified to build and operate in Linux kernel environment. * * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - *************************************************************************/ + */ +#include #include "ieee754.h" #define DP_EBIAS 1023 @@ -43,12 +39,12 @@ #define SP_EMAX 127 #define SP_FBITS 23 -#define DP_MBIT(x) ((unsigned long long)1 << (x)) +#define DP_MBIT(x) ((u64)1 << (x)) #define DP_HIDDEN_BIT DP_MBIT(DP_FBITS) #define DP_SIGN_BIT DP_MBIT(63) -#define SP_MBIT(x) ((unsigned long)1 << (x)) +#define SP_MBIT(x) ((u32)1 << (x)) #define SP_HIDDEN_BIT SP_MBIT(SP_FBITS) #define SP_SIGN_BIT SP_MBIT(31) diff -Nru a/arch/mips/math-emu/ieee754dp.c b/arch/mips/math-emu/ieee754dp.c --- a/arch/mips/math-emu/ieee754dp.c Tue Jul 1 18:44:36 2003 +++ b/arch/mips/math-emu/ieee754dp.c Tue Jul 1 18:44:36 2003 @@ -42,9 +42,7 @@ int ieee754dp_issnan(ieee754dp x) { assert(ieee754dp_isnan(x)); - if (ieee754_csr.noq) - return 1; - return !(DPMANT(x) & DP_MBIT(DP_MBITS - 1)); + return ((DPMANT(x) & DP_MBIT(DP_MBITS-1)) == DP_MBIT(DP_MBITS-1)); } @@ -71,12 +69,13 @@ if (!ieee754dp_issnan(r)) /* QNAN does not cause invalid op !! */ return r; - if (!SETCX(IEEE754_INVALID_OPERATION)) { + if (!SETANDTESTCX(IEEE754_INVALID_OPERATION)) { /* not enabled convert to a quiet NaN */ - if (ieee754_csr.noq) + DPMANT(r) &= (~DP_MBIT(DP_MBITS-1)); + if (ieee754dp_isnan(r)) return r; - DPMANT(r) |= DP_MBIT(DP_MBITS - 1); - return r; + else + return ieee754dp_indef(); } ax.op = op; @@ -99,12 +98,38 @@ } +static u64 get_rounding(int sn, u64 xm) +{ + /* inexact must round of 3 bits + */ + if (xm & (DP_MBIT(3) - 1)) { + switch (ieee754_csr.rm) { + case IEEE754_RZ: + break; + case IEEE754_RN: + xm += 0x3 + ((xm >> 3) & 1); + /* xm += (xm&0x8)?0x4:0x3 */ + break; + case IEEE754_RU: /* toward +Infinity */ + if (!sn) /* ?? */ + xm += 0x8; + break; + case IEEE754_RD: /* toward -Infinity */ + if (sn) /* ?? */ + xm += 0x8; + break; + } + } + return xm; +} + + /* generate a normal/denormal number with over,under handling * sn is sign * xe is an unbiased exponent * xm is 3bit extended precision value. */ -ieee754dp ieee754dp_format(int sn, int xe, unsigned long long xm) +ieee754dp ieee754dp_format(int sn, int xe, u64 xm) { assert(xm); /* we don't gen exact zeros (probably should) */ @@ -117,40 +142,59 @@ if (ieee754_csr.nod) { SETCX(IEEE754_UNDERFLOW); - return ieee754dp_zero(sn); - } + SETCX(IEEE754_INEXACT); - /* sticky right shift es bits - */ - xm = XDPSRS(xm, es); - xe += es; + switch(ieee754_csr.rm) { + case IEEE754_RN: + return ieee754dp_zero(sn); + case IEEE754_RZ: + return ieee754dp_zero(sn); + case IEEE754_RU: /* toward +Infinity */ + if(sn == 0) + return ieee754dp_min(0); + else + return ieee754dp_zero(1); + case IEEE754_RD: /* toward -Infinity */ + if(sn == 0) + return ieee754dp_zero(0); + else + return ieee754dp_min(1); + } + } - assert((xm & (DP_HIDDEN_BIT << 3)) == 0); - assert(xe == DP_EMIN); + if (xe == DP_EMIN - 1 + && get_rounding(sn, xm) >> (DP_MBITS + 1 + 3)) + { + /* Not tiny after rounding */ + SETCX(IEEE754_INEXACT); + xm = get_rounding(sn, xm); + xm >>= 1; + /* Clear grs bits */ + xm &= ~(DP_MBIT(3) - 1); + xe++; + } + else { + /* sticky right shift es bits + */ + xm = XDPSRS(xm, es); + xe += es; + assert((xm & (DP_HIDDEN_BIT << 3)) == 0); + assert(xe == DP_EMIN); + } } if (xm & (DP_MBIT(3) - 1)) { SETCX(IEEE754_INEXACT); - /* inexact must round of 3 bits - */ - switch (ieee754_csr.rm) { - case IEEE754_RZ: - break; - case IEEE754_RN: - xm += 0x3 + ((xm >> 3) & 1); - /* xm += (xm&0x8)?0x4:0x3 */ - break; - case IEEE754_RU: /* toward +Infinity */ - if (!sn) /* ?? */ - xm += 0x8; - break; - case IEEE754_RD: /* toward -Infinity */ - if (sn) /* ?? */ - xm += 0x8; - break; + if ((xm & (DP_HIDDEN_BIT << 3)) == 0) { + SETCX(IEEE754_UNDERFLOW); } - /* adjust exponent for rounding add overflowing + + /* inexact must round of 3 bits */ - if (xm >> (DP_MBITS + 3 + 1)) { /* add causes mantissa overflow */ + xm = get_rounding(sn, xm); + /* adjust exponent for rounding add overflowing + */ + if (xm >> (DP_MBITS + 3 + 1)) { + /* add causes mantissa overflow */ xm >>= 1; xe++; } @@ -163,6 +207,7 @@ if (xe > DP_EMAX) { SETCX(IEEE754_OVERFLOW); + SETCX(IEEE754_INEXACT); /* -O can be table indexed by (rm,sn) */ switch (ieee754_csr.rm) { case IEEE754_RN: @@ -186,7 +231,8 @@ if ((xm & DP_HIDDEN_BIT) == 0) { /* we underflow (tiny/zero) */ assert(xe == DP_EMIN); - SETCX(IEEE754_UNDERFLOW); + if (ieee754_csr.mx & IEEE754_UNDERFLOW) + SETCX(IEEE754_UNDERFLOW); return builddp(sn, DP_EMIN - 1 + DP_EBIAS, xm); } else { assert((xm >> (DP_MBITS + 1)) == 0); /* no execess */ diff -Nru a/arch/mips/math-emu/ieee754dp.h b/arch/mips/math-emu/ieee754dp.h --- a/arch/mips/math-emu/ieee754dp.h Tue Jul 1 18:44:35 2003 +++ b/arch/mips/math-emu/ieee754dp.h Tue Jul 1 18:44:35 2003 @@ -1,4 +1,4 @@ -/* +/* * IEEE754 floating point * double precision internal header file */ @@ -46,7 +46,7 @@ #define DPDNORMX DPDNORMx(xm,xe) #define DPDNORMY DPDNORMx(ym,ye) -static __inline ieee754dp builddp(int s, int bx, unsigned long long m) +static __inline ieee754dp builddp(int s, int bx, u64 m) { ieee754dp r; @@ -64,11 +64,11 @@ extern int ieee754dp_isnan(ieee754dp); extern int ieee754dp_issnan(ieee754dp); extern int ieee754si_xcpt(int, const char *, ...); -extern long long ieee754di_xcpt(long long, const char *, ...); +extern s64 ieee754di_xcpt(s64, const char *, ...); extern ieee754dp ieee754dp_xcpt(ieee754dp, const char *, ...); extern ieee754dp ieee754dp_nanxcpt(ieee754dp, const char *, ...); extern ieee754dp ieee754dp_bestnan(ieee754dp, ieee754dp); -extern ieee754dp ieee754dp_format(int, int, unsigned long long); +extern ieee754dp ieee754dp_format(int, int, u64); #define DPNORMRET2(s,e,m,name,a0,a1) \ diff -Nru a/arch/mips/math-emu/ieee754int.h b/arch/mips/math-emu/ieee754int.h --- a/arch/mips/math-emu/ieee754int.h Tue Jul 1 18:44:35 2003 +++ b/arch/mips/math-emu/ieee754int.h Tue Jul 1 18:44:35 2003 @@ -1,4 +1,4 @@ -/* +/* * IEEE754 floating point * common internal header file */ @@ -38,11 +38,11 @@ #define SP_EMAX 127 #define SP_MBITS 23 -#define DP_MBIT(x) ((unsigned long long)1 << (x)) +#define DP_MBIT(x) ((u64)1 << (x)) #define DP_HIDDEN_BIT DP_MBIT(DP_MBITS) #define DP_SIGN_BIT DP_MBIT(63) -#define SP_MBIT(x) ((unsigned long)1 << (x)) +#define SP_MBIT(x) ((u32)1 << (x)) #define SP_HIDDEN_BIT SP_MBIT(SP_MBITS) #define SP_SIGN_BIT SP_MBIT(31) @@ -61,7 +61,10 @@ (ieee754_csr.cx = 0) #define SETCX(x) \ - (ieee754_csr.cx |= (x),ieee754_csr.sx |= (x),ieee754_csr.mx & (x)) + (ieee754_csr.cx |= (x),ieee754_csr.sx |= (x)) + +#define SETANDTESTCX(x) \ + (SETCX(x),ieee754_csr.mx & (x)) #define TSTX() \ (ieee754_csr.cx & ieee754_csr.mx) @@ -82,9 +85,9 @@ if(vm == 0)\ vc = IEEE754_CLASS_INF;\ else if(vm & SP_MBIT(SP_MBITS-1)) \ - vc = IEEE754_CLASS_QNAN;\ - else \ vc = IEEE754_CLASS_SNAN;\ + else \ + vc = IEEE754_CLASS_QNAN;\ } else if(ve == SP_EMIN-1+SP_EBIAS) {\ if(vm) {\ ve = SP_EMIN;\ @@ -102,10 +105,10 @@ #define COMPXDP \ -unsigned long long xm; int xe; int xs; int xc +u64 xm; int xe; int xs; int xc #define COMPYDP \ -unsigned long long ym; int ye; int ys; int yc +u64 ym; int ye; int ys; int yc #define EXPLODEDP(v,vc,vs,ve,vm) \ {\ @@ -116,9 +119,9 @@ if(vm == 0)\ vc = IEEE754_CLASS_INF;\ else if(vm & DP_MBIT(DP_MBITS-1)) \ - vc = IEEE754_CLASS_QNAN;\ - else \ vc = IEEE754_CLASS_SNAN;\ + else \ + vc = IEEE754_CLASS_QNAN;\ } else if(ve == DP_EMIN-1+DP_EBIAS) {\ if(vm) {\ ve = DP_EMIN;\ @@ -133,3 +136,30 @@ } #define EXPLODEXDP EXPLODEDP(x,xc,xs,xe,xm) #define EXPLODEYDP EXPLODEDP(y,yc,ys,ye,ym) + +#define FLUSHDP(v,vc,vs,ve,vm) \ + if(vc==IEEE754_CLASS_DNORM) {\ + if(ieee754_csr.nod) {\ + SETCX(IEEE754_INEXACT);\ + vc = IEEE754_CLASS_ZERO;\ + ve = DP_EMIN-1+DP_EBIAS;\ + vm = 0;\ + v = ieee754dp_zero(vs);\ + }\ + } + +#define FLUSHSP(v,vc,vs,ve,vm) \ + if(vc==IEEE754_CLASS_DNORM) {\ + if(ieee754_csr.nod) {\ + SETCX(IEEE754_INEXACT);\ + vc = IEEE754_CLASS_ZERO;\ + ve = SP_EMIN-1+SP_EBIAS;\ + vm = 0;\ + v = ieee754sp_zero(vs);\ + }\ + } + +#define FLUSHXDP FLUSHDP(x,xc,xs,xe,xm) +#define FLUSHYDP FLUSHDP(y,yc,ys,ye,ym) +#define FLUSHXSP FLUSHSP(x,xc,xs,xe,xm) +#define FLUSHYSP FLUSHSP(y,yc,ys,ye,ym) diff -Nru a/arch/mips/math-emu/ieee754sp.c b/arch/mips/math-emu/ieee754sp.c --- a/arch/mips/math-emu/ieee754sp.c Tue Jul 1 18:44:34 2003 +++ b/arch/mips/math-emu/ieee754sp.c Tue Jul 1 18:44:34 2003 @@ -42,9 +42,7 @@ int ieee754sp_issnan(ieee754sp x) { assert(ieee754sp_isnan(x)); - if (ieee754_csr.noq) - return 1; - return !(SPMANT(x) & SP_MBIT(SP_MBITS - 1)); + return (SPMANT(x) & SP_MBIT(SP_MBITS-1)); } @@ -72,12 +70,13 @@ if (!ieee754sp_issnan(r)) /* QNAN does not cause invalid op !! */ return r; - if (!SETCX(IEEE754_INVALID_OPERATION)) { + if (!SETANDTESTCX(IEEE754_INVALID_OPERATION)) { /* not enabled convert to a quiet NaN */ - if (ieee754_csr.noq) + SPMANT(r) &= (~SP_MBIT(SP_MBITS-1)); + if (ieee754sp_isnan(r)) return r; - SPMANT(r) |= SP_MBIT(SP_MBITS - 1); - return r; + else + return ieee754sp_indef(); } ax.op = op; @@ -100,6 +99,32 @@ } +static unsigned get_rounding(int sn, unsigned xm) +{ + /* inexact must round of 3 bits + */ + if (xm & (SP_MBIT(3) - 1)) { + switch (ieee754_csr.rm) { + case IEEE754_RZ: + break; + case IEEE754_RN: + xm += 0x3 + ((xm >> 3) & 1); + /* xm += (xm&0x8)?0x4:0x3 */ + break; + case IEEE754_RU: /* toward +Infinity */ + if (!sn) /* ?? */ + xm += 0x8; + break; + case IEEE754_RD: /* toward -Infinity */ + if (sn) /* ?? */ + xm += 0x8; + break; + } + } + return xm; +} + + /* generate a normal/denormal number with over,under handling * sn is sign * xe is an unbiased exponent @@ -118,39 +143,58 @@ if (ieee754_csr.nod) { SETCX(IEEE754_UNDERFLOW); - return ieee754sp_zero(sn); - } + SETCX(IEEE754_INEXACT); - /* sticky right shift es bits - */ - SPXSRSXn(es); + switch(ieee754_csr.rm) { + case IEEE754_RN: + return ieee754sp_zero(sn); + case IEEE754_RZ: + return ieee754sp_zero(sn); + case IEEE754_RU: /* toward +Infinity */ + if(sn == 0) + return ieee754sp_min(0); + else + return ieee754sp_zero(1); + case IEEE754_RD: /* toward -Infinity */ + if(sn == 0) + return ieee754sp_zero(0); + else + return ieee754sp_min(1); + } + } - assert((xm & (SP_HIDDEN_BIT << 3)) == 0); - assert(xe == SP_EMIN); + if (xe == SP_EMIN - 1 + && get_rounding(sn, xm) >> (SP_MBITS + 1 + 3)) + { + /* Not tiny after rounding */ + SETCX(IEEE754_INEXACT); + xm = get_rounding(sn, xm); + xm >>= 1; + /* Clear grs bits */ + xm &= ~(SP_MBIT(3) - 1); + xe++; + } + else { + /* sticky right shift es bits + */ + SPXSRSXn(es); + assert((xm & (SP_HIDDEN_BIT << 3)) == 0); + assert(xe == SP_EMIN); + } } if (xm & (SP_MBIT(3) - 1)) { SETCX(IEEE754_INEXACT); - /* inexact must round of 3 bits - */ - switch (ieee754_csr.rm) { - case IEEE754_RZ: - break; - case IEEE754_RN: - xm += 0x3 + ((xm >> 3) & 1); - /* xm += (xm&0x8)?0x4:0x3 */ - break; - case IEEE754_RU: /* toward +Infinity */ - if (!sn) /* ?? */ - xm += 0x8; - break; - case IEEE754_RD: /* toward -Infinity */ - if (sn) /* ?? */ - xm += 0x8; - break; + if ((xm & (SP_HIDDEN_BIT << 3)) == 0) { + SETCX(IEEE754_UNDERFLOW); } - /* adjust exponent for rounding add overflowing + + /* inexact must round of 3 bits */ - if (xm >> (SP_MBITS + 1 + 3)) { /* add causes mantissa overflow */ + xm = get_rounding(sn, xm); + /* adjust exponent for rounding add overflowing + */ + if (xm >> (SP_MBITS + 1 + 3)) { + /* add causes mantissa overflow */ xm >>= 1; xe++; } @@ -163,6 +207,7 @@ if (xe > SP_EMAX) { SETCX(IEEE754_OVERFLOW); + SETCX(IEEE754_INEXACT); /* -O can be table indexed by (rm,sn) */ switch (ieee754_csr.rm) { case IEEE754_RN: @@ -186,7 +231,8 @@ if ((xm & SP_HIDDEN_BIT) == 0) { /* we underflow (tiny/zero) */ assert(xe == SP_EMIN); - SETCX(IEEE754_UNDERFLOW); + if (ieee754_csr.mx & IEEE754_UNDERFLOW) + SETCX(IEEE754_UNDERFLOW); return buildsp(sn, SP_EMIN - 1 + SP_EBIAS, xm); } else { assert((xm >> (SP_MBITS + 1)) == 0); /* no execess */ diff -Nru a/arch/mips/math-emu/ieee754sp.h b/arch/mips/math-emu/ieee754sp.h --- a/arch/mips/math-emu/ieee754sp.h Tue Jul 1 18:44:31 2003 +++ b/arch/mips/math-emu/ieee754sp.h Tue Jul 1 18:44:31 2003 @@ -1,4 +1,4 @@ -/* +/* * IEEE754 floating point * double precision internal header file */ @@ -70,7 +70,7 @@ extern int ieee754sp_isnan(ieee754sp); extern int ieee754sp_issnan(ieee754sp); extern int ieee754si_xcpt(int, const char *, ...); -extern long long ieee754di_xcpt(long long, const char *, ...); +extern s64 ieee754di_xcpt(s64, const char *, ...); extern ieee754sp ieee754sp_xcpt(ieee754sp, const char *, ...); extern ieee754sp ieee754sp_nanxcpt(ieee754sp, const char *, ...); extern ieee754sp ieee754sp_bestnan(ieee754sp, ieee754sp); diff -Nru a/arch/mips/math-emu/ieee754xcpt.c b/arch/mips/math-emu/ieee754xcpt.c --- a/arch/mips/math-emu/ieee754xcpt.c Tue Jul 1 18:44:32 2003 +++ b/arch/mips/math-emu/ieee754xcpt.c Tue Jul 1 18:44:32 2003 @@ -23,12 +23,13 @@ /************************************************************************** * Nov 7, 2000 - * Added preprocessor hacks to map to Linux kernel diagnostics. + * Added preprocessor hacks to map to Linux kernel diagnostics. * * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. *************************************************************************/ +#include #include "ieee754.h" /* @@ -42,7 +43,7 @@ void ieee754_xcpt(struct ieee754xctx *xcp) { - printk("floating point exception in \"%s\", type=%s\n", + printk(KERN_DEBUG "floating point exception in \"%s\", type=%s\n", xcp->op, rtnames[xcp->rt]); } diff -Nru a/arch/mips/math-emu/kernel_linkage.c b/arch/mips/math-emu/kernel_linkage.c --- a/arch/mips/math-emu/kernel_linkage.c Tue Jul 1 18:44:31 2003 +++ b/arch/mips/math-emu/kernel_linkage.c Tue Jul 1 18:44:31 2003 @@ -20,13 +20,10 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. * - *************************************************************************/ -/* * Routines corresponding to Linux kernel FP context * manipulation primitives for the Algorithmics MIPS * FPU Emulator */ - #include #include #include @@ -42,10 +39,10 @@ { static int first = 1; int i; - + if (first) { first = 0; - printk("Algorithmics/MIPS FPU Emulator v1.4\n"); + printk("Algorithmics/MIPS FPU Emulator v1.5\n"); } current->thread.fpu.soft.sr = 0; diff -Nru a/arch/mips/math-emu/sp_add.c b/arch/mips/math-emu/sp_add.c --- a/arch/mips/math-emu/sp_add.c Tue Jul 1 18:44:37 2003 +++ b/arch/mips/math-emu/sp_add.c Tue Jul 1 18:44:37 2003 @@ -37,27 +37,23 @@ CLEARCX; - switch (CLPAIR(xc, yc)) { - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): - return ieee754sp_nanxcpt(ieee754sp_bestnan(x, y), "add", x, - y); + FLUSHXSP; + FLUSHYSP; + switch (CLPAIR(xc, yc)) { + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): - return ieee754sp_nanxcpt(y, "add", x, y); - - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - return ieee754sp_nanxcpt(x, "add", x, y); - - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): - return ieee754sp_bestnan(x, y); + SETCX(IEEE754_INVALID_OPERATION); + return ieee754sp_nanxcpt(ieee754sp_indef(), "add", x, y); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): @@ -65,6 +61,7 @@ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): return y; + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): @@ -72,7 +69,7 @@ return x; - /* Inifity handling + /* Infinity handling */ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): diff -Nru a/arch/mips/math-emu/sp_cmp.c b/arch/mips/math-emu/sp_cmp.c --- a/arch/mips/math-emu/sp_cmp.c Tue Jul 1 18:44:31 2003 +++ b/arch/mips/math-emu/sp_cmp.c Tue Jul 1 18:44:31 2003 @@ -27,15 +27,24 @@ #include "ieee754sp.h" -int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cmp) +int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cmp, int sig) { - CLEARCX; + COMPXSP; + COMPYSP; + + EXPLODEXSP; + EXPLODEYSP; + FLUSHXSP; + FLUSHYSP; + CLEARCX; /* Even clear inexact flag here */ if (ieee754sp_isnan(x) || ieee754sp_isnan(y)) { + if (sig || xc == IEEE754_CLASS_SNAN || yc == IEEE754_CLASS_SNAN) + SETCX(IEEE754_INVALID_OPERATION); if (cmp & IEEE754_CUN) return 1; if (cmp & (IEEE754_CLT | IEEE754_CGT)) { - if (SETCX(IEEE754_INVALID_OPERATION)) + if (sig && SETANDTESTCX(IEEE754_INVALID_OPERATION)) return ieee754si_xcpt(0, "fcmpf", x); } return 0; diff -Nru a/arch/mips/math-emu/sp_div.c b/arch/mips/math-emu/sp_div.c --- a/arch/mips/math-emu/sp_div.c Tue Jul 1 18:44:37 2003 +++ b/arch/mips/math-emu/sp_div.c Tue Jul 1 18:44:37 2003 @@ -32,32 +32,28 @@ COMPXSP; COMPYSP; - CLEARCX; - EXPLODEXSP; EXPLODEYSP; - switch (CLPAIR(xc, yc)) { - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): - return ieee754sp_nanxcpt(ieee754sp_bestnan(x, y), "div", x, - y); + CLEARCX; + + FLUSHXSP; + FLUSHYSP; + switch (CLPAIR(xc, yc)) { + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): - return ieee754sp_nanxcpt(y, "div", x, y); - - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - return ieee754sp_nanxcpt(x, "div", x, y); - - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): - return ieee754sp_bestnan(x, y); + SETCX(IEEE754_INVALID_OPERATION); + return ieee754sp_nanxcpt(ieee754sp_indef(), "div", x, y); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): @@ -65,6 +61,7 @@ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): return y; + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): diff -Nru a/arch/mips/math-emu/sp_fdp.c b/arch/mips/math-emu/sp_fdp.c --- a/arch/mips/math-emu/sp_fdp.c Tue Jul 1 18:44:35 2003 +++ b/arch/mips/math-emu/sp_fdp.c Tue Jul 1 18:44:35 2003 @@ -30,20 +30,24 @@ ieee754sp ieee754sp_fdp(ieee754dp x) { COMPXDP; + ieee754sp nan; + + EXPLODEXDP; CLEARCX; - EXPLODEXDP; + FLUSHXDP; switch (xc) { - case IEEE754_CLASS_QNAN: case IEEE754_CLASS_SNAN: - return ieee754sp_nanxcpt(buildsp(xs, - SP_EMAX + 1 + SP_EBIAS, - (unsigned long) - (xm >> - (DP_MBITS - SP_MBITS))), - "fdp", x); + SETCX(IEEE754_INVALID_OPERATION); + return ieee754sp_nanxcpt(ieee754sp_indef(), "fdp"); + case IEEE754_CLASS_QNAN: + nan = buildsp(xs, SP_EMAX + 1 + SP_EBIAS, (u32) + (xm >> (DP_MBITS - SP_MBITS))); + if (!ieee754sp_isnan(nan)) + nan = ieee754sp_indef(); + return ieee754sp_nanxcpt(nan, "fdp", x); case IEEE754_CLASS_INF: return ieee754sp_inf(xs); case IEEE754_CLASS_ZERO: @@ -51,15 +55,19 @@ case IEEE754_CLASS_DNORM: /* can't possibly be sp representable */ SETCX(IEEE754_UNDERFLOW); + SETCX(IEEE754_INEXACT); + if ((ieee754_csr.rm == IEEE754_RU && !xs) || + (ieee754_csr.rm == IEEE754_RD && xs)) + return ieee754sp_xcpt(ieee754sp_mind(xs), "fdp", x); return ieee754sp_xcpt(ieee754sp_zero(xs), "fdp", x); case IEEE754_CLASS_NORM: break; } { - unsigned long rm; + u32 rm; - /* convert from DP_MBITS to SP_MBITS+3 with sticky right shift + /* convert from DP_MBITS to SP_MBITS+3 with sticky right shift */ rm = (xm >> (DP_MBITS - (SP_MBITS + 3))) | ((xm << (64 - (DP_MBITS - (SP_MBITS + 3)))) != 0); diff -Nru a/arch/mips/math-emu/sp_fint.c b/arch/mips/math-emu/sp_fint.c --- a/arch/mips/math-emu/sp_fint.c Tue Jul 1 18:44:34 2003 +++ b/arch/mips/math-emu/sp_fint.c Tue Jul 1 18:44:34 2003 @@ -52,13 +52,13 @@ xe = SP_MBITS + 3; if (xm >> (SP_MBITS + 1 + 3)) { - /* shunt out overflow bits + /* shunt out overflow bits */ while (xm >> (SP_MBITS + 1 + 3)) { SPXSRSX1(); } } else { - /* normalize in grs extended single precision + /* normalize in grs extended single precision */ while ((xm >> (SP_MBITS + 3)) == 0) { xm <<= 1; diff -Nru a/arch/mips/math-emu/sp_flong.c b/arch/mips/math-emu/sp_flong.c --- a/arch/mips/math-emu/sp_flong.c Tue Jul 1 18:44:37 2003 +++ b/arch/mips/math-emu/sp_flong.c Tue Jul 1 18:44:37 2003 @@ -27,7 +27,7 @@ #include "ieee754sp.h" -ieee754sp ieee754sp_flong(long long x) +ieee754sp ieee754sp_flong(s64 x) { COMPXDP; /* <--- need 64-bit mantissa temp */ @@ -52,7 +52,7 @@ xe = SP_MBITS + 3; if (xm >> (SP_MBITS + 1 + 3)) { - /* shunt out overflow bits + /* shunt out overflow bits */ while (xm >> (SP_MBITS + 1 + 3)) { SPXSRSX1(); @@ -68,9 +68,9 @@ } -ieee754sp ieee754sp_fulong(unsigned long long u) +ieee754sp ieee754sp_fulong(u64 u) { - if ((long long) u < 0) + if ((s64) u < 0) return ieee754sp_add(ieee754sp_1e63(), ieee754sp_flong(u & ~(1ULL << 63))); return ieee754sp_flong(u); diff -Nru a/arch/mips/math-emu/sp_frexp.c b/arch/mips/math-emu/sp_frexp.c --- a/arch/mips/math-emu/sp_frexp.c Tue Jul 1 18:44:31 2003 +++ b/arch/mips/math-emu/sp_frexp.c Tue Jul 1 18:44:31 2003 @@ -27,7 +27,7 @@ #include "ieee754sp.h" -/* close to ieeep754sp_logb +/* close to ieeep754sp_logb */ ieee754sp ieee754sp_frexp(ieee754sp x, int *eptr) { diff -Nru a/arch/mips/math-emu/sp_modf.c b/arch/mips/math-emu/sp_modf.c --- a/arch/mips/math-emu/sp_modf.c Tue Jul 1 18:44:38 2003 +++ b/arch/mips/math-emu/sp_modf.c Tue Jul 1 18:44:38 2003 @@ -59,7 +59,7 @@ *ip = x; return ieee754sp_zero(xs); } - /* generate ipart mantissa by clearing bottom bits + /* generate ipart mantissa by clearing bottom bits */ *ip = buildsp(xs, xe + SP_EBIAS, ((xm >> (SP_MBITS - xe)) << (SP_MBITS - xe)) & diff -Nru a/arch/mips/math-emu/sp_mul.c b/arch/mips/math-emu/sp_mul.c --- a/arch/mips/math-emu/sp_mul.c Tue Jul 1 18:44:36 2003 +++ b/arch/mips/math-emu/sp_mul.c Tue Jul 1 18:44:36 2003 @@ -32,32 +32,28 @@ COMPXSP; COMPYSP; - CLEARCX; - EXPLODEXSP; EXPLODEYSP; - switch (CLPAIR(xc, yc)) { - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): - return ieee754sp_nanxcpt(ieee754sp_bestnan(x, y), "mul", x, - y); + CLEARCX; + + FLUSHXSP; + FLUSHYSP; + switch (CLPAIR(xc, yc)) { + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): - return ieee754sp_nanxcpt(y, "mul", x, y); - - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - return ieee754sp_nanxcpt(x, "mul", x, y); - - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): - return ieee754sp_bestnan(x, y); + SETCX(IEEE754_INVALID_OPERATION); + return ieee754sp_nanxcpt(ieee754sp_indef(), "mul", x, y); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): @@ -65,6 +61,7 @@ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): return y; + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): diff -Nru a/arch/mips/math-emu/sp_simple.c b/arch/mips/math-emu/sp_simple.c --- a/arch/mips/math-emu/sp_simple.c Tue Jul 1 18:44:35 2003 +++ b/arch/mips/math-emu/sp_simple.c Tue Jul 1 18:44:35 2003 @@ -42,7 +42,16 @@ ieee754sp ieee754sp_neg(ieee754sp x) { + COMPXSP; + + EXPLODEXSP; CLEARCX; + FLUSHXSP; + + if (xc == IEEE754_CLASS_SNAN) { + SETCX(IEEE754_INVALID_OPERATION); + return ieee754sp_nanxcpt(ieee754sp_indef(), "neg"); + } if (ieee754sp_isnan(x)) /* but not infinity */ return ieee754sp_nanxcpt(x, "neg", x); @@ -55,7 +64,16 @@ ieee754sp ieee754sp_abs(ieee754sp x) { + COMPXSP; + + EXPLODEXSP; CLEARCX; + FLUSHXSP; + + if (xc == IEEE754_CLASS_SNAN) { + SETCX(IEEE754_INVALID_OPERATION); + return ieee754sp_nanxcpt(ieee754sp_indef(), "abs"); + } if (ieee754sp_isnan(x)) /* but not infinity */ return ieee754sp_nanxcpt(x, "abs", x); diff -Nru a/arch/mips/math-emu/sp_sqrt.c b/arch/mips/math-emu/sp_sqrt.c --- a/arch/mips/math-emu/sp_sqrt.c Tue Jul 1 18:44:32 2003 +++ b/arch/mips/math-emu/sp_sqrt.c Tue Jul 1 18:44:32 2003 @@ -27,43 +27,44 @@ #include "ieee754sp.h" -static const struct ieee754sp_konst knan = { - 0, SP_EBIAS + SP_EMAX + 1, 0 -}; - -#define nan ((ieee754sp)knan) - ieee754sp ieee754sp_sqrt(ieee754sp x) { - int sign = (int) 0x80000000; int ix, s, q, m, t, i; unsigned int r; - COMPXDP; + COMPXSP; /* take care of Inf and NaN */ - EXPLODEXDP; + EXPLODEXSP; + CLEARCX; + FLUSHXSP; /* x == INF or NAN? */ switch (xc) { case IEEE754_CLASS_QNAN: - case IEEE754_CLASS_SNAN: /* sqrt(Nan) = Nan */ return ieee754sp_nanxcpt(x, "sqrt"); + case IEEE754_CLASS_SNAN: + SETCX(IEEE754_INVALID_OPERATION); + return ieee754sp_nanxcpt(ieee754sp_indef(), "sqrt"); case IEEE754_CLASS_ZERO: /* sqrt(0) = 0 */ return x; case IEEE754_CLASS_INF: - if (xs) + if (xs) { /* sqrt(-Inf) = Nan */ - return ieee754sp_nanxcpt(nan, "sqrt"); + SETCX(IEEE754_INVALID_OPERATION); + return ieee754sp_nanxcpt(ieee754sp_indef(), "sqrt"); + } /* sqrt(+Inf) = Inf */ return x; case IEEE754_CLASS_DNORM: case IEEE754_CLASS_NORM: - if (xs) + if (xs) { /* sqrt(-x) = Nan */ - return ieee754sp_nanxcpt(nan, "sqrt"); + SETCX(IEEE754_INVALID_OPERATION); + return ieee754sp_nanxcpt(ieee754sp_indef(), "sqrt"); + } break; } @@ -99,6 +100,7 @@ } if (ix != 0) { + SETCX(IEEE754_INEXACT); switch (ieee754_csr.rm) { case IEEE754_RP: q += 2; diff -Nru a/arch/mips/math-emu/sp_sub.c b/arch/mips/math-emu/sp_sub.c --- a/arch/mips/math-emu/sp_sub.c Tue Jul 1 18:44:34 2003 +++ b/arch/mips/math-emu/sp_sub.c Tue Jul 1 18:44:34 2003 @@ -32,32 +32,28 @@ COMPXSP; COMPYSP; - CLEARCX; - EXPLODEXSP; EXPLODEYSP; - switch (CLPAIR(xc, yc)) { - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): - return ieee754sp_nanxcpt(ieee754sp_bestnan(x, y), "sub", x, - y); + CLEARCX; + FLUSHXSP; + FLUSHYSP; + + switch (CLPAIR(xc, yc)) { + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): + case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): - return ieee754sp_nanxcpt(y, "sub", x, y); - - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - return ieee754sp_nanxcpt(x, "sub", x, y); - - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): - return ieee754sp_bestnan(x, y); + SETCX(IEEE754_INVALID_OPERATION); + return ieee754sp_nanxcpt(ieee754sp_indef(), "sub", x, y); case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): @@ -65,6 +61,7 @@ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): return y; + case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): @@ -72,7 +69,7 @@ return x; - /* Inifity handling + /* Infinity handling */ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): @@ -170,13 +167,13 @@ xe = xe; xs = ys; } - if (xm == 0) + if (xm == 0) { if (ieee754_csr.rm == IEEE754_RD) return ieee754sp_zero(1); /* round negative inf. => sign = -1 */ else return ieee754sp_zero(0); /* other round modes => sign = 1 */ - - /* normalize to rounding precision + } + /* normalize to rounding precision */ while ((xm >> (SP_MBITS + 3)) == 0) { xm <<= 1; diff -Nru a/arch/mips/math-emu/sp_tint.c b/arch/mips/math-emu/sp_tint.c --- a/arch/mips/math-emu/sp_tint.c Tue Jul 1 18:44:39 2003 +++ b/arch/mips/math-emu/sp_tint.c Tue Jul 1 18:44:39 2003 @@ -35,38 +35,78 @@ CLEARCX; EXPLODEXSP; + FLUSHXSP; switch (xc) { case IEEE754_CLASS_SNAN: case IEEE754_CLASS_QNAN: - SETCX(IEEE754_INVALID_OPERATION); - return ieee754si_xcpt(ieee754si_indef(), "fixsp", x); case IEEE754_CLASS_INF: - SETCX(IEEE754_OVERFLOW); - return ieee754si_xcpt(ieee754si_indef(), "fixsp", x); + SETCX(IEEE754_INVALID_OPERATION); + return ieee754si_xcpt(ieee754si_indef(), "sp_tint", x); case IEEE754_CLASS_ZERO: return 0; - case IEEE754_CLASS_DNORM: /* much to small */ - SETCX(IEEE754_UNDERFLOW); - return ieee754si_xcpt(0, "fixsp", x); + case IEEE754_CLASS_DNORM: case IEEE754_CLASS_NORM: break; } if (xe >= 31) { - SETCX(IEEE754_OVERFLOW); - return ieee754si_xcpt(ieee754si_indef(), "fix", x); - } - if (xe < 0) { - SETCX(IEEE754_UNDERFLOW); - return ieee754si_xcpt(0, "fix", x); + /* look for valid corner case */ + if (xe == 31 && xs && xm == SP_HIDDEN_BIT) + return -0x80000000; + /* Set invalid. We will only use overflow for floating + point overflow */ + SETCX(IEEE754_INVALID_OPERATION); + return ieee754si_xcpt(ieee754si_indef(), "sp_tint", x); } /* oh gawd */ if (xe > SP_MBITS) { xm <<= xe - SP_MBITS; - } else if (xe < SP_MBITS) { - /* XXX no rounding - */ - xm >>= SP_MBITS - xe; + } else { + u32 residue; + int round; + int sticky; + int odd; + + if (xe < -1) { + residue = xm; + round = 0; + sticky = residue != 0; + xm = 0; + } + else { + /* Shifting a u32 32 times does not work, + * so we do it in two steps. Be aware that xe + * may be -1 */ + residue = xm << (xe + 1); + residue <<= 31 - SP_MBITS; + round = (residue >> 31) != 0; + sticky = (residue << 1) != 0; + xm >>= SP_MBITS - xe; + } + odd = (xm & 0x1) != 0x0; + switch (ieee754_csr.rm) { + case IEEE754_RN: + if (round && (sticky || odd)) + xm++; + break; + case IEEE754_RZ: + break; + case IEEE754_RU: /* toward +Infinity */ + if ((round || sticky) && !xs) + xm++; + break; + case IEEE754_RD: /* toward -Infinity */ + if ((round || sticky) && xs) + xm++; + break; + } + if ((xm >> 31) != 0) { + /* This can happen after rounding */ + SETCX(IEEE754_INVALID_OPERATION); + return ieee754si_xcpt(ieee754si_indef(), "sp_tint", x); + } + if (round || sticky) + SETCX(IEEE754_INEXACT); } if (xs) return -xm; diff -Nru a/arch/mips/math-emu/sp_tlong.c b/arch/mips/math-emu/sp_tlong.c --- a/arch/mips/math-emu/sp_tlong.c Tue Jul 1 18:44:39 2003 +++ b/arch/mips/math-emu/sp_tlong.c Tue Jul 1 18:44:39 2003 @@ -27,45 +27,81 @@ #include "ieee754sp.h" -long long ieee754sp_tlong(ieee754sp x) +s64 ieee754sp_tlong(ieee754sp x) { COMPXDP; /* <-- need 64-bit mantissa tmp */ CLEARCX; EXPLODEXSP; + FLUSHXSP; switch (xc) { case IEEE754_CLASS_SNAN: case IEEE754_CLASS_QNAN: - SETCX(IEEE754_INVALID_OPERATION); - return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x); case IEEE754_CLASS_INF: - SETCX(IEEE754_OVERFLOW); + SETCX(IEEE754_INVALID_OPERATION); return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x); case IEEE754_CLASS_ZERO: return 0; - case IEEE754_CLASS_DNORM: /* much to small */ - SETCX(IEEE754_UNDERFLOW); - return ieee754di_xcpt(0, "sp_tlong", x); + case IEEE754_CLASS_DNORM: case IEEE754_CLASS_NORM: break; } if (xe >= 63) { - SETCX(IEEE754_OVERFLOW); + /* look for valid corner case */ + if (xe == 63 && xs && xm == SP_HIDDEN_BIT) + return -0x8000000000000000LL; + /* Set invalid. We will only use overflow for floating + point overflow */ + SETCX(IEEE754_INVALID_OPERATION); return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x); } - if (xe < 0) { - SETCX(IEEE754_UNDERFLOW); - return ieee754di_xcpt(0, "sp_tlong", x); - } /* oh gawd */ if (xe > SP_MBITS) { xm <<= xe - SP_MBITS; } else if (xe < SP_MBITS) { - /* XXX no rounding - */ - xm >>= SP_MBITS - xe; + u32 residue; + int round; + int sticky; + int odd; + + if (xe < -1) { + residue = xm; + round = 0; + sticky = residue != 0; + xm = 0; + } + else { + residue = xm << (32 - SP_MBITS + xe); + round = (residue >> 31) != 0; + sticky = (residue << 1) != 0; + xm >>= SP_MBITS - xe; + } + odd = (xm & 0x1) != 0x0; + switch (ieee754_csr.rm) { + case IEEE754_RN: + if (round && (sticky || odd)) + xm++; + break; + case IEEE754_RZ: + break; + case IEEE754_RU: /* toward +Infinity */ + if ((round || sticky) && !xs) + xm++; + break; + case IEEE754_RD: /* toward -Infinity */ + if ((round || sticky) && xs) + xm++; + break; + } + if ((xm >> 63) != 0) { + /* This can happen after rounding */ + SETCX(IEEE754_INVALID_OPERATION); + return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x); + } + if (round || sticky) + SETCX(IEEE754_INEXACT); } if (xs) return -xm; @@ -74,14 +110,14 @@ } -unsigned long long ieee754sp_tulong(ieee754sp x) +u64 ieee754sp_tulong(ieee754sp x) { ieee754sp hb = ieee754sp_1e63(); /* what if x < 0 ?? */ if (ieee754sp_lt(x, hb)) - return (unsigned long long) ieee754sp_tlong(x); + return (u64) ieee754sp_tlong(x); - return (unsigned long long) ieee754sp_tlong(ieee754sp_sub(x, hb)) | + return (u64) ieee754sp_tlong(ieee754sp_sub(x, hb)) | (1ULL << 63); } diff -Nru a/arch/mips/mips-boards/atlas/Makefile b/arch/mips/mips-boards/atlas/Makefile --- a/arch/mips/mips-boards/atlas/Makefile Tue Jul 1 18:44:38 2003 +++ b/arch/mips/mips-boards/atlas/Makefile Tue Jul 1 18:44:38 2003 @@ -7,12 +7,12 @@ # This program is free software; you can distribute it and/or modify it # under the terms of the GNU General Public License (Version 2) as # published by the Free Software Foundation. -# +# # This program is distributed in the hope it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. -# +# # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. diff -Nru a/arch/mips/mips-boards/atlas/atlas_int.c b/arch/mips/mips-boards/atlas/atlas_int.c --- a/arch/mips/mips-boards/atlas/atlas_int.c Tue Jul 1 18:44:36 2003 +++ b/arch/mips/mips-boards/atlas/atlas_int.c Tue Jul 1 18:44:36 2003 @@ -19,17 +19,17 @@ * * ######################################################################## * - * Routines for generic manipulation of the interrupts found on the MIPS + * Routines for generic manipulation of the interrupts found on the MIPS * Atlas board. * */ #include +#include #include #include #include #include #include -#include #include #include @@ -41,10 +41,6 @@ = (struct atlas_ictrl_regs *)ATLAS_ICTRL_REGS_BASE; extern asmlinkage void mipsIRQ(void); -extern void do_IRQ(int irq, struct pt_regs *regs); - -unsigned long spurious_count = 0; -irq_desc_t irq_desc[NR_IRQS]; #if 0 #define DEBUG_INT(x...) printk(x) @@ -52,11 +48,6 @@ #define DEBUG_INT(x...) #endif -void inline disable_irq_nosync(unsigned int irq_nr) -{ - disable_atlas_irq(irq_nr); -} - void disable_atlas_irq(unsigned int irq_nr) { atlas_hw0_icregs->intrsten = (1 << irq_nr); @@ -94,80 +85,6 @@ NULL }; -int show_interrupts(struct seq_file *p, void *v) -{ - int i; - int num = 0; - struct irqaction *action; - unsigned long flags; - - for (i = 0; i < ATLASINT_END; i++, num++) { - spin_lock_irqsave(&irq_desc[i].lock, flags); - action = irq_desc[i].action; - if (!action) - goto skip; - seq_printf(p, "%2d: %8d %c %s", - num, kstat_cpu(0).irqs[num], - (action->flags & SA_INTERRUPT) ? '+' : ' ', - action->name); - for (action=action->next; action; action = action->next) { - seq_printf(p, ",%s %s", - (action->flags & SA_INTERRUPT) ? " +" : "", - action->name); - } - seq_printf(p, " [hw0]\n"); -skip: - spin_unlock_irqrestore(&irq_desc[i].lock, flags); - } - return 0; -} - -int request_irq(unsigned int irq, - void (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, - const char * devname, - void *dev_id) -{ - struct irqaction *action; - - DEBUG_INT("request_irq: irq=%d, devname = %s\n", irq, devname); - - if (irq >= ATLASINT_END) - return -EINVAL; - if (!handler) - return -EINVAL; - - action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL); - if(!action) - return -ENOMEM; - - action->handler = handler; - action->flags = irqflags; - action->mask = 0; - action->name = devname; - action->dev_id = dev_id; - action->next = 0; - irq_desc[irq].action = action; - enable_atlas_irq(irq); - - return 0; -} - -void free_irq(unsigned int irq, void *dev_id) -{ - struct irqaction *action; - - if (irq >= ATLASINT_END) { - printk("Trying to free IRQ%d\n",irq); - return; - } - - action = irq_desc[irq].action; - irq_desc[irq].action = NULL; - disable_atlas_irq(irq); - kfree(action); -} - static inline int ls1bit32(unsigned int x) { int b = 31, s; @@ -183,48 +100,23 @@ void atlas_hw0_irqdispatch(struct pt_regs *regs) { - struct irqaction *action; unsigned long int_status; - int irq, cpu = smp_processor_id(); + int irq; - int_status = atlas_hw0_icregs->intstatus; + int_status = atlas_hw0_icregs->intstatus; /* if int_status == 0, then the interrupt has already been cleared */ - if (int_status == 0) + if (unlikely(int_status == 0)) return; irq = ls1bit32(int_status); - action = irq_desc[irq].action; DEBUG_INT("atlas_hw0_irqdispatch: irq=%d\n", irq); - /* if action == NULL, then we don't have a handler for the irq */ - if ( action == NULL ) { - printk("No handler for hw0 irq: %i\n", irq); - spurious_count++; - return; - } - - irq_enter(cpu, irq); - kstat_cpu(0).irqs[irq]++; - action->handler(irq, action->dev_id, regs); - irq_exit(cpu, irq); - - return; -} - -unsigned long probe_irq_on (void) -{ - return 0; -} - - -int probe_irq_off (unsigned long irqs) -{ - return 0; + do_IRQ(irq, regs); } -#ifdef CONFIG_REMOTE_DEBUG +#ifdef CONFIG_KGDB extern void breakpoint(void); extern int remote_debug; #endif @@ -233,11 +125,11 @@ { int i; - /* - * Mask out all interrupt by writing "1" to all bit position in - * the interrupt reset reg. + /* + * Mask out all interrupt by writing "1" to all bit position in + * the interrupt reset reg. */ - atlas_hw0_icregs->intrsten = 0xffffffff; + atlas_hw0_icregs->intrsten = 0xffffffff; /* Now safe to set the exception vector. */ set_except_vector(0, mipsIRQ); @@ -250,7 +142,7 @@ spin_lock_init(&irq_desc[i].lock); } -#ifdef CONFIG_REMOTE_DEBUG +#ifdef CONFIG_KGDB if (remote_debug) { set_debug_traps(); breakpoint(); diff -Nru a/arch/mips/mips-boards/atlas/atlas_setup.c b/arch/mips/mips-boards/atlas/atlas_setup.c --- a/arch/mips/mips-boards/atlas/atlas_setup.c Tue Jul 1 18:44:35 2003 +++ b/arch/mips/mips-boards/atlas/atlas_setup.c Tue Jul 1 18:44:35 2003 @@ -19,6 +19,7 @@ */ #include #include +#include #include #include #include @@ -28,15 +29,17 @@ #include #include #include -#include #include +#include +#include +#include #if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_PROM_CONSOLE) extern void console_setup(char *, int *); char serial_console[20]; #endif -#ifdef CONFIG_REMOTE_DEBUG +#ifdef CONFIG_KGDB extern void rs_kgdb_hook(int); extern void saa9730_kgdb_hook(void); extern void breakpoint(void); @@ -47,9 +50,18 @@ extern void mips_reboot_setup(void); +const char *get_system_type(void) +{ + return "MIPS Atlas"; +} + +extern void mips_time_init(void); +extern void mips_timer_setup(struct irqaction *irq); +extern unsigned long mips_rtc_get_time(void); + void __init atlas_setup(void) { -#ifdef CONFIG_REMOTE_DEBUG +#ifdef CONFIG_KGDB int rs_putDebugChar(char); char rs_getDebugChar(void); int saa9730_putDebugChar(char); @@ -73,9 +85,9 @@ prom_printf("Config serial console: %s\n", serial_console); console_setup(serial_console, NULL); } -#endif +#endif -#ifdef CONFIG_REMOTE_DEBUG +#ifdef CONFIG_KGDB argptr = prom_getcmdline(); if ((argptr = strstr(argptr, "kgdb=ttyS")) != NULL) { int line; @@ -107,9 +119,12 @@ argptr = prom_getcmdline(); if ((argptr = strstr(argptr, "nofpu")) != NULL) - mips_cpu.options &= ~MIPS_CPU_FPU; + cpu_data[0].options &= ~MIPS_CPU_FPU; rtc_ops = &atlas_rtc_ops; + board_time_init = mips_time_init; + board_timer_setup = mips_timer_setup; + rtc_get_time = mips_rtc_get_time; mips_reboot_setup(); } diff -Nru a/arch/mips/mips-boards/generic/Makefile b/arch/mips/mips-boards/generic/Makefile --- a/arch/mips/mips-boards/generic/Makefile Tue Jul 1 18:44:37 2003 +++ b/arch/mips/mips-boards/generic/Makefile Tue Jul 1 18:44:37 2003 @@ -2,28 +2,26 @@ # Carsten Langgaard, carstenl@mips.com # Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. # -# ######################################################################## -# # This program is free software; you can distribute it and/or modify it # under the terms of the GNU General Public License (Version 2) as # published by the Free Software Foundation. -# +# # This program is distributed in the hope it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. -# +# # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. # -# ####################################################################### -# # Makefile for the MIPS boards generic routines under Linux. # -EXTRA_AFLAGS := $(CFLAGS) +obj-y := mipsIRQ.o reset.o display.o init.o memory.o \ + printf.o cmdline.o +obj-$(CONFIG_MIPS_ATLAS) += time.o +obj-$(CONFIG_MIPS_MALTA) += time.o +obj-$(CONFIG_KGDB) += gdb_hook.o -obj-y := mipsIRQ.o pci.o reset.o display.o init.o \ - memory.o printf.o cmdline.o time.o -obj-$(CONFIG_REMOTE_DEBUG) += gdb_hook.o +EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips/mips-boards/generic/cmdline.c b/arch/mips/mips-boards/generic/cmdline.c --- a/arch/mips/mips-boards/generic/cmdline.c Tue Jul 1 18:44:37 2003 +++ b/arch/mips/mips-boards/generic/cmdline.c Tue Jul 1 18:44:37 2003 @@ -17,16 +17,21 @@ * * Kernel command line creation using the prom monitor (YAMON) argc/argv. */ -#include #include #include #include extern int prom_argc; -extern char **prom_argv; +extern int *_prom_argv; -char arcs_cmdline[COMMAND_LINE_SIZE]; +/* + * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer. + * This macro take care of sign extension. + */ +#define prom_argv(index) ((char *)(((int *)(int)_prom_argv)[(index)])) + +char arcs_cmdline[CL_SIZE]; char * __init prom_getcmdline(void) { @@ -43,8 +48,8 @@ cp = &(arcs_cmdline[0]); while(actr < prom_argc) { - strcpy(cp, prom_argv[actr]); - cp += strlen(prom_argv[actr]); + strcpy(cp, prom_argv(actr)); + cp += strlen(prom_argv(actr)); *cp++ = ' '; actr++; } diff -Nru a/arch/mips/mips-boards/generic/display.c b/arch/mips/mips-boards/generic/display.c --- a/arch/mips/mips-boards/generic/display.c Tue Jul 1 18:44:36 2003 +++ b/arch/mips/mips-boards/generic/display.c Tue Jul 1 18:44:36 2003 @@ -18,7 +18,7 @@ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. * * ######################################################################## - * + * * Display routines for display messages in MIPS boards ascii display. * */ @@ -39,9 +39,11 @@ } } +#ifndef CONFIG_MIPS_SEAD void mips_display_word(unsigned int num) { volatile unsigned int *display = (void *)ASCII_DISPLAY_WORD_BASE; - + *display = num; } +#endif diff -Nru a/arch/mips/mips-boards/generic/gdb_hook.c b/arch/mips/mips-boards/generic/gdb_hook.c --- a/arch/mips/mips-boards/generic/gdb_hook.c Tue Jul 1 18:44:34 2003 +++ b/arch/mips/mips-boards/generic/gdb_hook.c Tue Jul 1 18:44:34 2003 @@ -2,8 +2,6 @@ * Carsten Langgaard, carstenl@mips.com * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -17,12 +15,9 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. * - * ######################################################################## - * * This is the interface to the remote debugger stub. - * */ - +#include #include #include @@ -67,28 +62,28 @@ serial_in(&kdb_port_info, UART_MSR); /* - * Now, initialize the UART + * Now, initialize the UART */ serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8); /* reset DLAB */ if (kdb_port_info.flags & ASYNC_FOURPORT) { kdb_port_info.MCR = UART_MCR_DTR | UART_MCR_RTS; t = UART_MCR_DTR | UART_MCR_OUT1; } else { - kdb_port_info.MCR + kdb_port_info.MCR = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2; t = UART_MCR_DTR | UART_MCR_RTS; } kdb_port_info.MCR = t; /* no interrupts, please */ serial_out(&kdb_port_info, UART_MCR, kdb_port_info.MCR); - + /* * and set the speed of the serial port * (currently hardwired to 9600 8N1 */ /* baud rate is fixed to 9600 (is this sufficient?)*/ - t = kdb_port_info.state->baud_base / 9600; + t = kdb_port_info.state->baud_base / 9600; /* set DLAB */ serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8 | UART_LCR_DLAB); serial_out(&kdb_port_info, UART_DLL, t & 0xff);/* LS of divisor */ @@ -102,7 +97,7 @@ return generic_putDebugChar(c); } -char getDebugChar(void) +char getDebugChar(void) { return generic_getDebugChar(); } @@ -156,7 +151,7 @@ static int saa9730_kgdb_active = 0; -void saa9730_kgdb_hook(void) +void saa9730_kgdb_hook(void) { volatile unsigned char t; diff -Nru a/arch/mips/mips-boards/generic/init.c b/arch/mips/mips-boards/generic/init.c --- a/arch/mips/mips-boards/generic/init.c Tue Jul 1 18:44:31 2003 +++ b/arch/mips/mips-boards/generic/init.c Tue Jul 1 18:44:31 2003 @@ -27,6 +27,8 @@ #include #include #include +#include +#include /* Environment variable */ typedef struct @@ -36,27 +38,37 @@ } t_env_var; int prom_argc; -char **prom_argv, **prom_envp; +int *_prom_argv, *_prom_envp; + +/* + * YAMON (32-bit PROM) pass arguments and environment as 32-bit pointer. + * This macro take care of sign extension, if running in 64-bit mode. + */ +#define prom_envp(index) ((char *)(((int *)(int)_prom_envp)[(index)])) int init_debug = 0; +unsigned int mips_revision_corid; + char *prom_getenv(char *envname) { - /* + /* * Return a pointer to the given environment variable. + * In 64-bit mode: we're using 64-bit pointers, but all pointers + * in the PROM structures are only 32-bit, so we need some + * workarounds, if we are running in 64-bit mode. */ - - t_env_var *env = (t_env_var *)prom_envp; - int i; + int i, index=0; i = strlen(envname); - while(env->name) { - if(strncmp(envname, env->name, i) == 0) { - return(env->val); + while(prom_envp(index)) { + if(strncmp(envname, prom_envp(index), i) == 0) { + return(prom_envp(index+1)); } - env++; + index += 2; } + return(NULL); } @@ -83,7 +95,7 @@ ea[i] = num; } } - + int get_ethernet_addr(char *ethernet_addr) { char *ethaddr_str; @@ -109,28 +121,84 @@ int __init prom_init(int argc, char **argv, char **envp) { prom_argc = argc; - prom_argv = argv; - prom_envp = envp; + _prom_argv = (int *)argv; + _prom_envp = (int *)envp; mips_display_message("LINUX"); - /* - * Setup the North bridge to do Master byte-lane swapping when - * running in bigendian. - */ +#ifdef CONFIG_MIPS_SEAD + set_io_port_base(KSEG1); +#else + mips_revision_corid = MIPS_REVISION_CORID; + switch(mips_revision_corid) { + case MIPS_REVISION_CORID_QED_RM5261: + case MIPS_REVISION_CORID_CORE_LV: + case MIPS_REVISION_CORID_CORE_FPGA: + /* + * Setup the North bridge to do Master byte-lane swapping + * when running in bigendian. + */ +#if defined(__MIPSEL__) + GT_WRITE(GT_PCI0_CMD_OFS, GT_PCI0_CMD_MBYTESWAP_BIT | + GT_PCI0_CMD_SBYTESWAP_BIT); +#else + GT_WRITE(GT_PCI0_CMD_OFS, 0); +#endif + +#if defined(CONFIG_MIPS_MALTA) + set_io_port_base(MALTA_GT_PORT_BASE); +#else + set_io_port_base(KSEG1); +#endif + + break; + case MIPS_REVISION_CORID_BONITO64: + case MIPS_REVISION_CORID_CORE_20K: + /* + * Disable Bonito IOBC. + */ + BONITO_PCIMEMBASECFG = BONITO_PCIMEMBASECFG & + ~(BONITO_PCIMEMBASECFG_MEMBASE0_CACHED | + BONITO_PCIMEMBASECFG_MEMBASE1_CACHED); + + /* + * Setup the North bridge to do Master byte-lane swapping + * when running in bigendian. + */ #if defined(__MIPSEL__) - GT_WRITE(GT_PCI0_CMD_OFS, GT_PCI0_CMD_MBYTESWAP_BIT | - GT_PCI0_CMD_SBYTESWAP_BIT); + BONITO_BONGENCFG = BONITO_BONGENCFG & + ~(BONITO_BONGENCFG_MSTRBYTESWAP | + BONITO_BONGENCFG_BYTESWAP); #else - GT_WRITE(GT_PCI0_CMD_OFS, 0); + BONITO_BONGENCFG = BONITO_BONGENCFG | + BONITO_BONGENCFG_MSTRBYTESWAP | + BONITO_BONGENCFG_BYTESWAP; #endif #if defined(CONFIG_MIPS_MALTA) - mips_io_port_base = MALTA_PORT_BASE; + set_io_port_base(MALTA_BONITO_PORT_BASE); #else - mips_io_port_base = KSEG1; + set_io_port_base(KSEG1); +#endif + break; + + case MIPS_REVISION_CORID_CORE_MSC: + set_io_port_base(MALTA_MSC_PORT_BASE); +#if defined(__MIPSEL__) + MSC_WRITE(MSC01_PCI_SWAP, MSC01_PCI_SWAP_NOSWAP); +#else + MSC_WRITE(MSC01_PCI_SWAP, + MSC01_PCI_SWAP_BYTESWAP << MSC01_PCI_SWAP_IO_SHF | + MSC01_PCI_SWAP_BYTESWAP << MSC01_PCI_SWAP_MEM_SHF | + MSC01_PCI_SWAP_BYTESWAP << MSC01_PCI_SWAP_BAR0_SHF); +#endif + break; + default: + /* Unknown Core card */ + mips_display_message("CC Error"); + while(1); /* We die here... */ + } #endif - setup_prom_printf(0); prom_printf("\nLINUX started...\n"); prom_init_cmdline(); prom_meminit(); diff -Nru a/arch/mips/mips-boards/generic/memory.c b/arch/mips/mips-boards/generic/memory.c --- a/arch/mips/mips-boards/generic/memory.c Tue Jul 1 18:44:32 2003 +++ b/arch/mips/mips-boards/generic/memory.c Tue Jul 1 18:44:32 2003 @@ -2,8 +2,6 @@ * Carsten Langgaard, carstenl@mips.com * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -17,11 +15,8 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. * - * ######################################################################## - * - * PROM library functions for acquiring/using memory descriptors given to + * PROM library functions for acquiring/using memory descriptors given to * us from the YAMON. - * */ #include #include @@ -83,11 +78,11 @@ mdesc[1].size = 0x000ef000; #if (CONFIG_MIPS_MALTA) - /* + /* * The area 0x000f0000-0x000fffff is allocated for BIOS memory by the - * south bridge and PCI access always forwarded to the ISA Bus and + * south bridge and PCI access always forwarded to the ISA Bus and * BIOSCS# is always generated. - * This mean that this area can't be used as DMA memory for PCI + * This mean that this area can't be used as DMA memory for PCI * devices. */ mdesc[2].type = yamon_dontuse; @@ -148,7 +143,7 @@ size = p->size; add_memory_region(base, size, type); - p++; + p++; } } @@ -168,7 +163,7 @@ + boot_mem_map.map[i].size) { ClearPageReserved(virt_to_page(__va(addr))); set_page_count(virt_to_page(__va(addr)), 1); - free_page(__va(addr)); + free_page((unsigned long)__va(addr)); addr += PAGE_SIZE; freed += PAGE_SIZE; } diff -Nru a/arch/mips/mips-boards/generic/mipsIRQ.S b/arch/mips/mips-boards/generic/mipsIRQ.S --- a/arch/mips/mips-boards/generic/mipsIRQ.S Tue Jul 1 18:44:34 2003 +++ b/arch/mips/mips-boards/generic/mipsIRQ.S Tue Jul 1 18:44:34 2003 @@ -56,6 +56,10 @@ * 6 Hardware (ignored) * 7 R4k timer (what we use) * + * Note: On the SEAD board thing are a little bit different. + * Here IRQ 2 (hw0) is wired to the UART0 and IRQ 3 (hw1) is wired + * wired to UART1. + * * We handle the IRQ according to _our_ priority which is: * * Highest ---- R4k Timer @@ -74,7 +78,9 @@ CLI .set at - mfc0 s0, CP0_CAUSE # get irq mask + mfc0 s0, CP0_CAUSE # get irq bits + mfc0 s1, CP0_STATUS # get irq mask + and s0, s1 /* First we check for r4k counter/timer IRQ. */ andi a0, s0, CAUSEF_IP7 @@ -90,16 +96,23 @@ nop 1: +#if defined(CONFIG_MIPS_SEAD) beq a0, zero, 1f - nop + andi a0, s0, CAUSEF_IP3 # delay slot, check hw1 interrupt +#else + beq a0, zero, 1f # delay slot, check hw3 interrupt + andi a0, s0, CAUSEF_IP5 +#endif /* Wheee, combined hardware level zero interrupt. */ #if defined(CONFIG_MIPS_ATLAS) jal atlas_hw0_irqdispatch #elif defined(CONFIG_MIPS_MALTA) jal malta_hw0_irqdispatch +#elif defined(CONFIG_MIPS_SEAD) + jal sead_hw0_irqdispatch #else -#error "MIPS board not supported\n" +#error "MIPS board not supported\n" #endif move a0, sp # delay slot @@ -107,6 +120,24 @@ nop # delay slot 1: +#if defined(CONFIG_MIPS_SEAD) + beq a0, zero, 1f + andi a0, s0, CAUSEF_IP5 # delay slot, check hw3 interrupt + jal sead_hw1_irqdispatch + move a0, sp # delay slot + j ret_from_irq + nop # delay slot +1: +#endif +#if defined(CONFIG_MIPS_MALTA) + beq a0, zero, 1f # check hw3 (coreHI) interrupt + nop + jal corehi_irqdispatch + move a0, sp + j ret_from_irq + nop +1: +#endif /* * Here by mistake? This is possible, what can happen is that by the * time we take the exception the IRQ pin goes low, so just leave if diff -Nru a/arch/mips/mips-boards/generic/pci.c b/arch/mips/mips-boards/generic/pci.c --- a/arch/mips/mips-boards/generic/pci.c Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,267 +0,0 @@ -/* - * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * MIPS boards specific PCI support. - * - */ -#include - -#ifdef CONFIG_PCI - -#include -#include -#include -#include - -#include -#include -#ifdef CONFIG_MIPS_MALTA -#include -#endif - -#define PCI_ACCESS_READ 0 -#define PCI_ACCESS_WRITE 1 - -static int -mips_pcibios_config_access(unsigned char access_type, struct pci_bus *bus_dev, unsigned int dev_fn, unsigned char where, u32 *data) -{ - unsigned char bus = bus_dev->number; - u32 intr; - - if ((bus == 0) && (dev_fn >= PCI_DEVFN(31,0))) - return -1; /* Because of a bug in the galileo (for slot 31). */ - - /* Clear cause register bits */ - GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT | - GT_INTRCAUSE_TARABORT0_BIT)); - - /* Setup address */ - GT_WRITE(GT_PCI0_CFGADDR_OFS, - (bus << GT_PCI0_CFGADDR_BUSNUM_SHF) | - (dev_fn << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | - ((where / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) | - GT_PCI0_CFGADDR_CONFIGEN_BIT); - - if (access_type == PCI_ACCESS_WRITE) { - if (bus == 0 && dev_fn == 0) { - /* - * Galileo is acting differently than other devices. - */ - GT_WRITE(GT_PCI0_CFGDATA_OFS, *data); - } else { - GT_PCI_WRITE(GT_PCI0_CFGDATA_OFS, *data); - } - } else { - if (bus == 0 && dev_fn == 0) { - /* - * Galileo is acting differently than other devices. - */ - GT_READ(GT_PCI0_CFGDATA_OFS, *data); - } else { - GT_PCI_READ(GT_PCI0_CFGDATA_OFS, *data); - } - } - - /* Check for master or target abort */ - GT_READ(GT_INTRCAUSE_OFS, intr); - - if (intr & (GT_INTRCAUSE_MASABORT0_BIT | GT_INTRCAUSE_TARABORT0_BIT)) - { - /* Error occurred */ - - /* Clear bits */ - GT_WRITE( GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT | - GT_INTRCAUSE_TARABORT0_BIT) ); - - return -1; - } - - return 0; -} - - -/* - * We can't address 8 and 16 bit words directly. Instead we have to - * read/write a 32bit word and mask/modify the data we actually want. - */ -static int -mips_pcibios_read (struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val) -{ - u32 data = 0; - - if((size == 2) && (where & 1)) - return PCIBIOS_BAD_REGISTER_NUMBER; - else if ((size == 4) && (where & 3)) - return PCIBIOS_BAD_REGISTER_NUMBER; - if (mips_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where, &data)) - return -1; - if(size == 1) - *val = (u8)(data >> ((where & 3) << 3)) & 0xff; - else if (size == 2) - *val = (u16)(data >> ((where & 3) << 3)) & 0xffff; - else if (size == 4) - *val = data; - - return PCIBIOS_SUCCESSFUL; -} - - -static int -mips_pcibios_write (struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val) -{ - u32 data = 0; - - if((size == 2) && (where & 1)) - return PCIBIOS_BAD_REGISTER_NUMBER; - else if (size == 4) { - if(where & 3) - return PCIBIOS_BAD_REGISTER_NUMBER; - if(mips_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where, &val)) - return -1; - return PCIBIOS_SUCCESSFUL; - } - if (mips_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where, &data)) - return -1; - if(size == 1) { - data = (data & ~(0xff << ((where & 3) << 3))) | - (val << ((where & 3) << 3)); - } else if (size == 2) { - data = (data & ~(0xffff << ((where & 3) << 3))) | - (val << ((where & 3) << 3)); - } - return PCIBIOS_SUCCESSFUL; -} - -struct pci_ops mips_pci_ops = { - .read = mips_pcibios_read, - .write = mips_pcibios_write, -}; - -void __init pcibios_init(void) -{ -#ifdef CONFIG_MIPS_MALTA - struct pci_dev *pdev = NULL; - unsigned char reg_val; -#endif - - printk("PCI: Probing PCI hardware on host bus 0.\n"); - pci_scan_bus(0, &mips_pci_ops, NULL); - - /* - * Due to a bug in the Galileo system controller, we need to setup - * the PCI BAR for the Galileo internal registers. - * This should be done in the bios/bootprom and will be fixed in - * a later revision of YAMON (the MIPS boards boot prom). - */ - GT_WRITE(GT_PCI0_CFGADDR_OFS, - (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) | /* Local bus */ - (0 << GT_PCI0_CFGADDR_DEVNUM_SHF) | /* GT64120 device */ - (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | /* Function 0 */ - ((0x20/4) << GT_PCI0_CFGADDR_REGNUM_SHF) | /* BAR 4 */ - GT_PCI0_CFGADDR_CONFIGEN_BIT ); - - /* Perform the write */ - GT_WRITE( GT_PCI0_CFGDATA_OFS, PHYSADDR(MIPS_GT_BASE)); - -#ifdef CONFIG_MIPS_MALTA - while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) { - if ((pdev->vendor == PCI_VENDOR_ID_INTEL) - && (pdev->device == PCI_DEVICE_ID_INTEL_82371AB) - && (PCI_SLOT(pdev->devfn) == 0x0a)) { - /* - * IDE Decode enable. - */ - pci_read_config_byte(pdev, 0x41, ®_val); - pci_write_config_byte(pdev, 0x41, reg_val | 0x80); - pci_read_config_byte(pdev, 0x43, ®_val); - pci_write_config_byte(pdev, 0x43, reg_val | 0x80); - } - - if ((pdev->vendor == PCI_VENDOR_ID_INTEL) - && (pdev->device == PCI_DEVICE_ID_INTEL_82371AB_0) - && (PCI_SLOT(pdev->devfn) == 0x0a)) { - /* - * Set top of main memory accessible by ISA or DMA - * devices to 16 Mb. - */ - pci_read_config_byte(pdev, 0x69, ®_val); - pci_write_config_byte(pdev, 0x69, reg_val | 0xf0); - } - } - - /* - * Activate Floppy Controller in the SMSC FDC37M817 Super I/O - * Controller. - * This should be done in the bios/bootprom and will be fixed in - * a later revision of YAMON (the MIPS boards boot prom). - */ - /* Entering config state. */ - SMSC_WRITE(SMSC_CONFIG_ENTER, SMSC_CONFIG_REG); - - /* Activate floppy controller. */ - SMSC_WRITE(SMSC_CONFIG_DEVNUM, SMSC_CONFIG_REG); - SMSC_WRITE(SMSC_CONFIG_DEVNUM_FLOPPY, SMSC_DATA_REG); - SMSC_WRITE(SMSC_CONFIG_ACTIVATE, SMSC_CONFIG_REG); - SMSC_WRITE(SMSC_CONFIG_ACTIVATE_ENABLE, SMSC_DATA_REG); - - /* Exit config state. */ - SMSC_WRITE(SMSC_CONFIG_EXIT, SMSC_CONFIG_REG); -#endif -} - -int __init -pcibios_enable_device(struct pci_dev *dev) -{ - /* Not needed, since we enable all devices at startup. */ - return 0; -} - -void __init -pcibios_align_resource(void *data, struct resource *res, - unsigned long size, unsigned long align) -{ -} - -char * __init -pcibios_setup(char *str) -{ - /* Nothing to do for now. */ - - return str; -} - -struct pci_fixup pcibios_fixups[] = { - { 0 } -}; - -#warning pcibios_update_resource() is now a generic implementation - please check - -/* - * Called after each bus is probed, but before its children - * are examined. - */ -void __init pcibios_fixup_bus(struct pci_bus *b) -{ - pci_read_bridge_bases(b); -} - -unsigned __init int pcibios_assign_all_busses(void) -{ - return 1; -} - -#endif /* CONFIG_PCI */ diff -Nru a/arch/mips/mips-boards/generic/printf.c b/arch/mips/mips-boards/generic/printf.c --- a/arch/mips/mips-boards/generic/printf.c Tue Jul 1 18:44:36 2003 +++ b/arch/mips/mips-boards/generic/printf.c Tue Jul 1 18:44:36 2003 @@ -2,8 +2,6 @@ * Carsten Langgaard, carstenl@mips.com * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -17,101 +15,84 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. * - * ######################################################################## - * * Putting things on the screen/serial line using YAMONs facilities. - * */ #include #include #include -#include #include -#include +#include #include -#include +#ifdef CONFIG_MIPS_ATLAS -#ifdef CONFIG_MIPS_ATLAS -/* - * Atlas registers are memory mapped on 64-bit aligned boundaries and +#include + +/* + * Atlas registers are memory mapped on 64-bit aligned boundaries and * only word access are allowed. * When reading the UART 8 bit registers only the LSB are valid. */ -unsigned int atlas_serial_in(struct async_struct *info, int offset) +static inline unsigned int serial_in(int offset) { - return (*(volatile unsigned int *)(info->port + mips_io_port_base + offset*8) & 0xff); + return (*(volatile unsigned int *)(mips_io_port_base + ATLAS_UART_REGS_BASE + offset*8) & 0xff); } -void atlas_serial_out(struct async_struct *info, int offset, int value) +static inline void serial_out(int offset, int value) { - *(volatile unsigned int *)(info->port + mips_io_port_base + offset*8) = value; + *(volatile unsigned int *)(mips_io_port_base + ATLAS_UART_REGS_BASE + offset*8) = value; } -#define serial_in atlas_serial_in -#define serial_out atlas_serial_out +#elif defined(CONFIG_MIPS_SEAD) -#else +#include -static unsigned int serial_in(struct async_struct *info, int offset) +/* + * SEAD registers are just like Atlas registers. + */ +static inline unsigned int serial_in(int offset) { - return inb(info->port + offset); + return (*(volatile unsigned int *)(mips_io_port_base + SEAD_UART0_REGS_BASE + offset*8) & 0xff); } -static void serial_out(struct async_struct *info, int offset, - int value) +static inline void serial_out(int offset, int value) { - outb(value, info->port + offset); + *(volatile unsigned int *)(mips_io_port_base + SEAD_UART0_REGS_BASE + offset*8) = value; } -#endif -static struct serial_state rs_table[] = { - SERIAL_PORT_DFNS /* Defined in serial.h */ -}; - -/* - * Hooks to fake "prom" console I/O before devices - * are fully initialized. - */ -static struct async_struct prom_port_info = {0}; - -void __init setup_prom_printf(int tty_no) { - struct serial_state *ser = &rs_table[tty_no]; +#else - prom_port_info.state = ser; - prom_port_info.magic = SERIAL_MAGIC; - prom_port_info.port = ser->port; - prom_port_info.flags = ser->flags; +static inline unsigned int serial_in(int offset) +{ + return inb(0x3f8 + offset); +} - /* No setup of UART - assume YAMON left in sane state */ +static inline void serial_out(int offset, int value) +{ + outb(value, 0x3f8 + offset); } +#endif int putPromChar(char c) { - if (!prom_port_info.state) { /* need to init device first */ - return 0; - } - - while ((serial_in(&prom_port_info, UART_LSR) & UART_LSR_THRE) == 0) + while ((serial_in(UART_LSR) & UART_LSR_THRE) == 0) ; - serial_out(&prom_port_info, UART_TX, c); + serial_out(UART_TX, c); return 1; } char getPromChar(void) { - if (!prom_port_info.state) { /* need to init device first */ - return 0; - } - - while (!(serial_in(&prom_port_info, UART_LSR) & 1)) + while (!(serial_in(UART_LSR) & 1)) ; - return(serial_in(&prom_port_info, UART_RX)); + return serial_in(UART_RX); } +static spinlock_t con_lock = SPIN_LOCK_UNLOCKED; + static char buf[1024]; void __init prom_printf(char *fmt, ...) @@ -123,8 +104,7 @@ int putPromChar(char); - /* Low level, brute force, not SMP safe... */ - save_and_cli(flags); + spin_lock_irqsave(con_lock, flags); va_start(args, fmt); l = vsprintf(buf, fmt, args); /* hopefully i < sizeof(buf) */ va_end(args); @@ -133,8 +113,9 @@ for (p = buf; p < buf_end; p++) { /* Crude cr/nl handling is better than none */ - if(*p == '\n')putPromChar('\r'); + if (*p == '\n') + putPromChar('\r'); putPromChar(*p); } - restore_flags(flags); + spin_unlock_irqrestore(con_lock, flags); } diff -Nru a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c --- a/arch/mips/mips-boards/generic/time.c Tue Jul 1 18:44:36 2003 +++ b/arch/mips/mips-boards/generic/time.c Tue Jul 1 18:44:36 2003 @@ -23,29 +23,29 @@ * */ +#include #include #include #include #include #include +#include +#include +#include +#include #include #include +#include #include - -#include -#include -#include +#include +#include #include #include -extern volatile unsigned long wall_jiffies; -static long last_rtc_update = 0; -unsigned long missed_heart_beats = 0; - -static unsigned long r4k_offset; /* Amount to increment compare reg each time */ -static unsigned long r4k_cur; /* What counter should be at next timer irq */ +static unsigned int r4k_offset; /* Amount to increment compare reg each time */ +static unsigned int r4k_cur; /* What counter should be at next timer irq */ #define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5) @@ -56,142 +56,37 @@ static char display_string[] = " LINUX ON MALTA "; #endif static unsigned int display_count = 0; -#define MAX_DISPLAY_COUNT (sizeof(display_string) - 8) - -static unsigned int timer_tick_count=0; +#define MAX_DISPLAY_COUNT (sizeof(display_string) - 8) +#define MIPS_CPU_TIMER_IRQ 7 -static inline void ack_r4ktimer(unsigned long newval) -{ - write_32bit_cp0_register(CP0_COMPARE, newval); -} +static unsigned int timer_tick_count=0; -/* - * In order to set the CMOS clock precisely, set_rtc_mmss has to be - * called 500 ms after the second nowtime has started, because when - * nowtime is written into the registers of the CMOS clock, it will - * jump to the next second precisely 500 ms later. Check the Motorola - * MC146818A or Dallas DS12887 data sheet for details. - * - * BUG: This routine does not handle hour overflow properly; it just - * sets the minutes. Usually you won't notice until after reboot! - */ -static int set_rtc_mmss(unsigned long nowtime) +static inline void ack_r4ktimer(unsigned int newval) { - int retval = 0; - int real_seconds, real_minutes, cmos_minutes; - unsigned char save_control, save_freq_select; - - save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ - CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); - - save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */ - CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); - - cmos_minutes = CMOS_READ(RTC_MINUTES); - - /* - * since we're only adjusting minutes and seconds, - * don't interfere with hour overflow. This avoids - * messing with unknown time zones but requires your - * RTC not to be off by more than 15 minutes - */ - real_seconds = nowtime % 60; - real_minutes = nowtime / 60; - if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) - real_minutes += 30; /* correct for half hour time zone */ - real_minutes %= 60; - - if (abs(real_minutes - cmos_minutes) < 30) { - CMOS_WRITE(real_seconds,RTC_SECONDS); - CMOS_WRITE(real_minutes,RTC_MINUTES); - } else { - printk(KERN_WARNING - "set_rtc_mmss: can't update from %d to %d\n", - cmos_minutes, real_minutes); - retval = -1; - } - - /* The following flags have to be released exactly in this order, - * otherwise the DS12887 (popular MC146818A clone with integrated - * battery and quartz) will not reset the oscillator and will not - * update precisely 500 ms later. You won't find this mentioned in - * the Dallas Semiconductor data sheets, but who believes data - * sheets anyway ... -- Markus Kuhn - */ - CMOS_WRITE(save_control, RTC_CONTROL); - CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); - - return retval; + write_c0_compare(newval); } -/* - * There are a lot of conceptually broken versions of the MIPS timer interrupt - * handler floating around. This one is rather different, but the algorithm - * is provably more robust. - */ void mips_timer_interrupt(struct pt_regs *regs) { - unsigned long flags; - int irq = 7; - unsigned long seq; - - if (r4k_offset == 0) - goto null; - - do { - kstat_cpu(0).irqs[irq]++; - do_timer(regs); - - /* Historical comment/code: - * RTC time of day s updated approx. every 11 - * minutes. Because of how the numbers work out - * we need to make absolutely sure we do this update - * within 500ms before the * next second starts, - * thus the following code. - */ - - do { - seq = read_seqbegin_irqsave(&xtime_lock, flags); - - 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)) - if (set_rtc_mmss(xtime.tv_sec) == 0) - last_rtc_update = xtime.tv_sec; - else - /* do it again in 60 s */ - last_rtc_update = xtime.tv_sec - 600; - } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); - - if ((timer_tick_count++ % HZ) == 0) { - mips_display_message(&display_string[display_count++]); - if (display_count == MAX_DISPLAY_COUNT) + if ((timer_tick_count++ % HZ) == 0) { + mips_display_message(&display_string[display_count++]); + if (display_count == MAX_DISPLAY_COUNT) display_count = 0; - } - r4k_cur += r4k_offset; - ack_r4ktimer(r4k_cur); - - } while (((unsigned long)read_32bit_cp0_register(CP0_COUNT) - - r4k_cur) < 0x7fffffff); - - return; + } -null: - ack_r4ktimer(0); + ll_timer_interrupt(MIPS_CPU_TIMER_IRQ, regs); } -/* +/* * Figure out the r4k offset, the amount to increment the compare - * register for each time tick. + * register for each time tick. * Use the RTC to calculate offset. */ -static unsigned long __init cal_r4koff(void) +static unsigned int __init cal_r4koff(void) { - unsigned long count; unsigned int flags; local_irq_save(flags); @@ -201,21 +96,21 @@ while (!(CMOS_READ(RTC_REG_A) & RTC_UIP)); /* Start r4k counter. */ - write_32bit_cp0_register(CP0_COUNT, 0); + write_c0_count(0); /* Read counter exactly on falling edge of update flag */ while (CMOS_READ(RTC_REG_A) & RTC_UIP); while (!(CMOS_READ(RTC_REG_A) & RTC_UIP)); - count = read_32bit_cp0_register(CP0_COUNT); + mips_counter_frequency = read_c0_count(); /* restore interrupts */ local_irq_restore(flags); - return (count / HZ); + return (mips_counter_frequency / HZ); } -static unsigned long __init get_mips_time(void) +unsigned long __init mips_rtc_get_time(void) { unsigned int year, mon, day, hour, min, sec; unsigned char save_control; @@ -235,7 +130,7 @@ if ((hour & 0xf) == 0xc) hour &= 0x80; if (hour & 0x80) - hour = (hour & 0xf) + 12; + hour = (hour & 0xf) + 12; } day = CMOS_READ(RTC_DAY_OF_MONTH); mon = CMOS_READ(RTC_MONTH); @@ -250,170 +145,41 @@ return mktime(year, mon, day, hour, min, sec); } -void __init time_init(void) +void __init mips_time_init(void) { unsigned int est_freq, flags; - /* Set Data mode - binary. */ + local_irq_save(flags); + + /* Set Data mode - binary. */ CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL); printk("calculating r4koff... "); r4k_offset = cal_r4koff(); - printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset); + printk("%08x(%d)\n", r4k_offset, r4k_offset); + + if ((read_c0_prid() & 0xffff00) == + (PRID_COMP_MIPS | PRID_IMP_20KC)) + est_freq = r4k_offset*HZ; + else + est_freq = 2*r4k_offset*HZ; - est_freq = 2*r4k_offset*HZ; est_freq += 5000; /* round */ est_freq -= est_freq%10000; - printk("CPU frequency %d.%02d MHz\n", est_freq/1000000, + printk("CPU frequency %d.%02d MHz\n", est_freq/1000000, (est_freq%1000000)*100/1000000); - r4k_cur = (read_32bit_cp0_register(CP0_COUNT) + r4k_offset); - write_32bit_cp0_register(CP0_COMPARE, r4k_cur); - change_cp0_status(ST0_IM, ALLINTS); - - /* Read time from the RTC chipset. */ - write_seqlock_irqsave (&xtime_lock, flags); - xtime.tv_sec = get_mips_time(); - xtime.tv_usec = 0; - write_sequnlock_irqrestore(&xtime_lock, flags); -} - -/* This is for machines which generate the exact clock. */ -#define USECS_PER_JIFFY (1000000/HZ) -#define USECS_PER_JIFFY_FRAC ((1000000 << 32) / HZ & 0xffffffff) - -/* Cycle counter value at the previous timer interrupt.. */ - -static unsigned int timerhi = 0, timerlo = 0; - -/* - * FIXME: Does playing with the RP bit in c0_status interfere with this code? - */ -static unsigned long do_fast_gettimeoffset(void) -{ - u32 count; - unsigned long res, tmp; - - /* Last jiffy when do_fast_gettimeoffset() was called. */ - static unsigned long last_jiffies=0; - unsigned long quotient; - - /* - * Cached "1/(clocks per usec)*2^32" value. - * It has to be recalculated once each jiffy. - */ - static unsigned long cached_quotient=0; - - tmp = jiffies; - - quotient = cached_quotient; - - if (tmp && last_jiffies != tmp) { - last_jiffies = tmp; -#ifdef CONFIG_CPU_MIPS32 - if (last_jiffies != 0) { - unsigned long r0; - do_div64_32(r0, timerhi, timerlo, tmp); - do_div64_32(quotient, USECS_PER_JIFFY, - USECS_PER_JIFFY_FRAC, r0); - cached_quotient = quotient; - } -#else - __asm__(".set\tnoreorder\n\t" - ".set\tnoat\n\t" - ".set\tmips3\n\t" - "lwu\t%0,%2\n\t" - "dsll32\t$1,%1,0\n\t" - "or\t$1,$1,%0\n\t" - "ddivu\t$0,$1,%3\n\t" - "mflo\t$1\n\t" - "dsll32\t%0,%4,0\n\t" - "nop\n\t" - "ddivu\t$0,%0,$1\n\t" - "mflo\t%0\n\t" - ".set\tmips0\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=&r" (quotient) - :"r" (timerhi), - "m" (timerlo), - "r" (tmp), - "r" (USECS_PER_JIFFY) - :"$1"); - cached_quotient = quotient; -#endif - } - - /* Get last timer tick in absolute kernel time */ - count = read_32bit_cp0_register(CP0_COUNT); - - /* .. relative to previous jiffy (32 bits is enough) */ - count -= timerlo; - - __asm__("multu\t%1,%2\n\t" - "mfhi\t%0" - :"=r" (res) - :"r" (count), - "r" (quotient)); - - /* - * Due to possible jiffies inconsistencies, we need to check - * the result so that we'll get a timer that is monotonic. - */ - if (res >= USECS_PER_JIFFY) - res = USECS_PER_JIFFY-1; - - return res; -} - -void do_gettimeofday(struct timeval *tv) -{ - unsigned long flags; - unsigned long seq; - - do { - seq = read_seqbegin_irqsave(&xtime_lock, flags); - - *tv = xtime; - tv->tv_usec += do_fast_gettimeoffset(); - - /* - * xtime is atomically updated in timer_bh. - * jiffies - wall_jiffies - * is nonzero if the timer bottom half hasnt executed yet. - */ - if (jiffies - wall_jiffies) - tv->tv_usec += USECS_PER_JIFFY; - - } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); - - if (tv->tv_usec >= 1000000) { - tv->tv_usec -= 1000000; - tv->tv_sec++; - } + local_irq_restore(flags); } -void do_settimeofday(struct timeval *tv) +void __init mips_timer_setup(struct irqaction *irq) { - write_seqlock_irq (&xtime_lock); - - /* This is revolting. We need to set the xtime.tv_usec correctly. - * However, the value in this location is is value at the last tick. - * Discover what correction gettimeofday would have done, and then - * undo it! - */ - tv->tv_usec -= do_fast_gettimeoffset(); - - if (tv->tv_usec < 0) { - tv->tv_usec += 1000000; - tv->tv_sec--; - } - - xtime = *tv; - time_adjust = 0; /* stop active adjtime() */ - time_status |= STA_UNSYNC; - time_maxerror = NTP_PHASE_LIMIT; - time_esterror = NTP_PHASE_LIMIT; - - write_sequnlock_irq (&xtime_lock); + /* we are using the cpu counter for timer interrupts */ + irq->handler = no_action; /* we use our own handler */ + setup_irq(MIPS_CPU_TIMER_IRQ, irq); + + /* to generate the first timer interrupt */ + r4k_cur = (read_c0_count() + r4k_offset); + write_c0_compare(r4k_cur); + set_c0_status(ALLINTS); } diff -Nru a/arch/mips/mips-boards/malta/Makefile b/arch/mips/mips-boards/malta/Makefile --- a/arch/mips/mips-boards/malta/Makefile Tue Jul 1 18:44:31 2003 +++ b/arch/mips/mips-boards/malta/Makefile Tue Jul 1 18:44:31 2003 @@ -7,12 +7,12 @@ # This program is free software; you can distribute it and/or modify it # under the terms of the GNU General Public License (Version 2) as # published by the Free Software Foundation. -# +# # This program is distributed in the hope it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. -# +# # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. diff -Nru a/arch/mips/mips-boards/malta/malta_int.c b/arch/mips/mips-boards/malta/malta_int.c --- a/arch/mips/mips-boards/malta/malta_int.c Tue Jul 1 18:44:33 2003 +++ b/arch/mips/mips-boards/malta/malta_int.c Tue Jul 1 18:44:33 2003 @@ -16,65 +16,137 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. * - * Routines for generic manipulation of the interrupts found on the MIPS + * Routines for generic manipulation of the interrupts found on the MIPS * Malta board. - * The interrupt controller is located in the South Bridge a PIIX4 device + * The interrupt controller is located in the South Bridge a PIIX4 device * with two internal 82C95 interrupt controllers. */ #include #include +#include #include #include #include #include #include -#include +#include #include +#include #include #include #include +#include #include -#include extern asmlinkage void mipsIRQ(void); +extern int mips_pcibios_iack(void); -void malta_hw0_irqdispatch(struct pt_regs *regs) +#ifdef CONFIG_KGDB +extern void breakpoint(void); +extern void set_debug_traps(void); +extern int remote_debug; +#endif + +static spinlock_t mips_irq_lock = SPIN_LOCK_UNLOCKED; + +static inline int get_int(int *irq) { - int irq; + unsigned long flags; - /* - * Determine highest priority pending interrupt by performing a PCI - * Interrupt Acknowledge cycle. - */ - GT_READ(GT_PCI0_IACK_OFS, irq); - irq &= 0xFF; + spin_lock_irqsave(&mips_irq_lock, flags); + + *irq = mips_pcibios_iack(); - /* - * IRQ7 is used to detect spurious interrupts. The interrupt - * acknowledge cycle returns IRQ7, if no interrupts is requested. We - * can differentiate between this situation and a "normal" IRQ7 by - * reading the ISR. + /* + * IRQ7 is used to detect spurious interrupts. + * The interrupt acknowledge cycle returns IRQ7, if no + * interrupts is requested. + * We can differentiate between this situation and a + * "Normal" IRQ7 by reading the ISR. */ - if (irq == 7) { - outb(PIIX4_OCW3_SEL | PIIX4_OCW3_ISR, PIIX4_ICTLR1_OCW3); - if (!(inb(PIIX4_ICTLR1_OCW3) & (1 << 7))) - return; /* Spurious interrupt. */ + if (*irq == 7) + { + outb(PIIX4_OCW3_SEL | PIIX4_OCW3_ISR, + PIIX4_ICTLR1_OCW3); + if (!(inb(PIIX4_ICTLR1_OCW3) & (1 << 7))) { + spin_unlock_irqrestore(&mips_irq_lock, flags); + printk("We got a spurious interrupt from PIIX4.\n"); + atomic_inc(&irq_err_count); + return -1; /* Spurious interrupt. */ + } } + spin_unlock_irqrestore(&mips_irq_lock, flags); + + return 0; +} + +void malta_hw0_irqdispatch(struct pt_regs *regs) +{ + int irq; + + if (get_int(&irq)) + return; /* interrupt has already been cleared */ + do_IRQ(irq, regs); } +void corehi_irqdispatch(struct pt_regs *regs) +{ + unsigned int data,datahi; + + /* Mask out corehi interrupt. */ + clear_c0_status(IE_IRQ3); + + printk("CoreHI interrupt, shouldn't happen, so we die here!!!\n"); + printk("epc : %08lx\nStatus: %08lx\nCause : %08lx\nbadVaddr : %08lx\n" +, regs->cp0_epc, regs->cp0_status, regs->cp0_cause, regs->cp0_badvaddr); + switch(mips_revision_corid) { + case MIPS_REVISION_CORID_CORE_MSC: + break; + case MIPS_REVISION_CORID_QED_RM5261: + case MIPS_REVISION_CORID_CORE_LV: + case MIPS_REVISION_CORID_CORE_FPGA: + GT_READ(GT_INTRCAUSE_OFS, data); + printk("GT_INTRCAUSE = %08x\n", data); + GT_READ(0x70, data); + GT_READ(0x78, datahi); + printk("GT_CPU_ERR_ADDR = %0x2%08x\n", datahi,data); + break; + case MIPS_REVISION_CORID_BONITO64: + case MIPS_REVISION_CORID_CORE_20K: + data = BONITO_INTISR; + printk("BONITO_INTISR = %08x\n", data); + data = BONITO_INTEN; + printk("BONITO_INTEN = %08x\n", data); + data = BONITO_INTPOL; + printk("BONITO_INTPOL = %08x\n", data); + data = BONITO_INTEDGE; + printk("BONITO_INTEDGE = %08x\n", data); + data = BONITO_INTSTEER; + printk("BONITO_INTSTEER = %08x\n", data); + data = BONITO_PCICMD; + printk("BONITO_PCICMD = %08x\n", data); + break; + } + + /* We die here*/ + die("CoreHi interrupt", regs); +} + void __init init_IRQ(void) { set_except_vector(0, mipsIRQ); init_generic_irq(); init_i8259_irqs(); -#ifdef CONFIG_REMOTE_DEBUG +#ifdef CONFIG_KGDB if (remote_debug) { set_debug_traps(); breakpoint(); } #endif } + + diff -Nru a/arch/mips/mips-boards/malta/malta_setup.c b/arch/mips/mips-boards/malta/malta_setup.c --- a/arch/mips/mips-boards/malta/malta_setup.c Tue Jul 1 18:44:39 2003 +++ b/arch/mips/mips-boards/malta/malta_setup.c Tue Jul 1 18:44:39 2003 @@ -36,17 +36,20 @@ #include #endif #include +#include +#include +#ifdef CONFIG_VT +#include +#endif #if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_PROM_CONSOLE) extern void console_setup(char *, int *); char serial_console[20]; #endif -#ifdef CONFIG_REMOTE_DEBUG -extern void set_debug_traps(void); +#ifdef CONFIG_KGDB extern void rs_kgdb_hook(int); -extern void breakpoint(void); -static int remote_debug = 0; +int remote_debug = 0; #endif extern struct ide_ops std_ide_ops; @@ -56,6 +59,10 @@ extern void mips_reboot_setup(void); +extern void mips_time_init(void); +extern void mips_timer_setup(struct irqaction *irq); +extern unsigned long mips_rtc_get_time(void); + struct resource standard_io_resources[] = { { "dma1", 0x00, 0x1f, IORESOURCE_BUSY }, { "timer", 0x40, 0x5f, IORESOURCE_BUSY }, @@ -65,9 +72,14 @@ #define STANDARD_IO_RESOURCES (sizeof(standard_io_resources)/sizeof(struct resource)) +const char *get_system_type(void) +{ + return "MIPS Malta"; +} + void __init malta_setup(void) { -#ifdef CONFIG_REMOTE_DEBUG +#ifdef CONFIG_KGDB int rs_putDebugChar(char); char rs_getDebugChar(void); extern int (*generic_putDebugChar)(char); @@ -80,7 +92,7 @@ for (i = 0; i < STANDARD_IO_RESOURCES; i++) request_resource(&ioport_resource, standard_io_resources+i); - /* + /* * Enable DMA channel 4 (cascade channel) in the PIIX4 south bridge. */ enable_dma(4); @@ -93,7 +105,7 @@ } #endif -#ifdef CONFIG_REMOTE_DEBUG +#ifdef CONFIG_KGDB argptr = prom_getcmdline(); if ((argptr = strstr(argptr, "kgdb=ttyS")) != NULL) { int line; @@ -119,17 +131,38 @@ argptr = prom_getcmdline(); if ((argptr = strstr(argptr, "nofpu")) != NULL) - mips_cpu.options &= ~MIPS_CPU_FPU; - + cpu_data[0].options &= ~MIPS_CPU_FPU; + rtc_ops = &malta_rtc_ops; + #ifdef CONFIG_BLK_DEV_IDE ide_ops = &std_ide_ops; #endif #ifdef CONFIG_BLK_DEV_FD fd_ops = &std_fd_ops; #endif -#ifdef CONFIG_PC_KEYB - kbd_ops = &std_kbd_ops; +#ifdef CONFIG_VT +#if defined(CONFIG_VGA_CONSOLE) + conswitchp = &vga_con; + + screen_info = (struct screen_info) { + 0, 25, /* orig-x, orig-y */ + 0, /* unused */ + 0, /* orig-video-page */ + 0, /* orig-video-mode */ + 80, /* orig-video-cols */ + 0,0,0, /* ega_ax, ega_bx, ega_cx */ + 25, /* orig-video-lines */ + 1, /* orig-video-isVGA */ + 16 /* orig-video-points */ + }; +#elif defined(CONFIG_DUMMY_CONSOLE) + conswitchp = &dummy_con; +#endif #endif mips_reboot_setup(); + + board_time_init = mips_time_init; + board_timer_setup = mips_timer_setup; + rtc_get_time = mips_rtc_get_time; } diff -Nru a/arch/mips/mips-boards/sead/Makefile b/arch/mips/mips-boards/sead/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/mips-boards/sead/Makefile Tue Jul 1 18:44:40 2003 @@ -0,0 +1,26 @@ +# +# Carsten Langgaard, carstenl@mips.com +# Copyright (C) 2002 MIPS Technologies, Inc. All rights reserved. +# +# ######################################################################## +# +# This program is free software; you can distribute it and/or modify it +# under the terms of the GNU General Public License (Version 2) as +# published by the Free Software Foundation. +# +# This program is distributed in the hope it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. +# +# ####################################################################### +# +# Makefile for the MIPS SEAD specific kernel interface routines +# under Linux. +# + +obj-y := sead_int.o sead_setup.o sead_time.o diff -Nru a/arch/mips/mips-boards/sead/sead_int.c b/arch/mips/mips-boards/sead/sead_int.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/mips-boards/sead/sead_int.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,115 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2002 MIPS Technologies, Inc. All rights reserved. + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * ######################################################################## + * + * Routines for generic manipulation of the interrupts found on the MIPS + * Sead board. + * + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +extern asmlinkage void mipsIRQ(void); + +void disable_sead_irq(unsigned int irq_nr) +{ + if (irq_nr == SEADINT_UART0) + clear_c0_status(0x00000400); + else + if (irq_nr == SEADINT_UART1) + clear_c0_status(0x00000800); +} + +void enable_sead_irq(unsigned int irq_nr) +{ + if (irq_nr == SEADINT_UART0) + set_c0_status(0x00000400); + else + if (irq_nr == SEADINT_UART1) + set_c0_status(0x00000800); +} + +static unsigned int startup_sead_irq(unsigned int irq) +{ + enable_sead_irq(irq); + return 0; /* never anything pending */ +} + +#define shutdown_sead_irq disable_sead_irq + +#define mask_and_ack_sead_irq disable_sead_irq + +static void end_sead_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_sead_irq(irq); +} + +static struct hw_interrupt_type sead_irq_type = { + "SEAD", + startup_sead_irq, + shutdown_sead_irq, + enable_sead_irq, + disable_sead_irq, + mask_and_ack_sead_irq, + end_sead_irq, + NULL +}; + +void sead_hw0_irqdispatch(struct pt_regs *regs) +{ + do_IRQ(0, regs); +} + +void sead_hw1_irqdispatch(struct pt_regs *regs) +{ + do_IRQ(1, regs); +} + +void __init init_IRQ(void) +{ + int i; + + /* + * Mask out all interrupt + */ + clear_c0_status(0x0000ff00); + + /* Now safe to set the exception vector. */ + set_except_vector(0, mipsIRQ); + + init_generic_irq(); + + for (i = 0; i <= SEADINT_END; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = NULL; + irq_desc[i].depth = 1; + irq_desc[i].lock = SPIN_LOCK_UNLOCKED; + irq_desc[i].handler = &sead_irq_type; + } +} diff -Nru a/arch/mips/mips-boards/sead/sead_setup.c b/arch/mips/mips-boards/sead/sead_setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/mips-boards/sead/sead_setup.c Tue Jul 1 18:44:39 2003 @@ -0,0 +1,77 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2002 MIPS Technologies, Inc. All rights reserved. + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * SEAD specific setup. + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_PROM_CONSOLE) +extern void console_setup(char *, int *); +char serial_console[20]; +#endif + +extern void mips_reboot_setup(void); +extern void mips_time_init(void); +extern void mips_timer_setup(struct irqaction *irq); + +const char *get_system_type(void) +{ + return "MIPS SEAD"; +} + +void __init sead_setup(void) +{ + char *argptr; + + ioport_resource.end = 0x7fffffff; + +#ifdef CONFIG_SERIAL_CONSOLE + argptr = prom_getcmdline(); + if ((argptr = strstr(argptr, "console=ttyS0")) == NULL) { + int i = 0; + char *s = prom_getenv("modetty0"); + while(s[i] >= '0' && s[i] <= '9') + i++; + strcpy(serial_console, "ttyS0,"); + strncpy(serial_console + 6, s, i); + prom_printf("Config serial console: %s\n", serial_console); + console_setup(serial_console, NULL); + } +#endif + + argptr = prom_getcmdline(); + + if ((argptr = strstr(argptr, "nofpu")) != NULL) + cpu_data[0].options &= ~MIPS_CPU_FPU; + + board_time_init = mips_time_init; + board_timer_setup = mips_timer_setup; + + mips_reboot_setup(); +} diff -Nru a/arch/mips/mips-boards/sead/sead_time.c b/arch/mips/mips-boards/sead/sead_time.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/mips-boards/sead/sead_time.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,142 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2002 MIPS Technologies, Inc. All rights reserved. + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Setting up the clock on the MIPS boards. + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include + +extern volatile unsigned long wall_jiffies; + +static unsigned long r4k_offset; /* Amount to increment compare reg each time */ +static unsigned long r4k_cur; /* What counter should be at next timer irq */ + +#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ5) + +static char display_string[] = " LINUX ON SEAD "; + +static unsigned int display_count = 0; +#define MAX_DISPLAY_COUNT (sizeof(display_string) - 8) + +#define MIPS_CPU_TIMER_IRQ 7 + +static unsigned int timer_tick_count=0; + +static inline void ack_r4ktimer(unsigned long newval) +{ + write_c0_compare(newval); +} + +/* + * There are a lot of conceptually broken versions of the MIPS timer interrupt + * handler floating around. This one is rather different, but the algorithm + * is provably more robust. + */ +void mips_timer_interrupt(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + int irq = MIPS_CPU_TIMER_IRQ; + + irq_enter(); + + do { + kstat_cpu(cpu).irqs[irq]++; + do_timer(regs); + + if ((timer_tick_count++ % HZ) == 0) { + mips_display_message(&display_string[display_count++]); + if (display_count == MAX_DISPLAY_COUNT) + display_count = 0; + } + + r4k_cur += r4k_offset; + ack_r4ktimer(r4k_cur); + + } while (((unsigned long)read_c0_count() + - r4k_cur) < 0x7fffffff); + + irq_exit(); + if (softirq_pending(cpu)) + do_softirq(); +} + +/* + * Figure out the r4k offset, the amount to increment the compare + * register for each time tick. + */ +static unsigned long __init cal_r4koff(void) +{ + /* + * The SEAD board doesn't have a real time clock, so we can't + * really calculate the timer offset. + * For now we hardwire the SEAD board frequency to 12MHz. + */ + return(6000000/HZ); +} + +void __init mips_time_init(void) +{ + unsigned int est_freq, flags; + + local_irq_save(flags); + + /* Start r4k counter. */ + write_c0_count(0); + + printk("calculating r4koff... "); + r4k_offset = cal_r4koff(); + printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset); + + if ((read_c0_prid() & 0xffff00) == + (PRID_COMP_MIPS | PRID_IMP_20KC)) + est_freq = r4k_offset*HZ; + else + est_freq = 2*r4k_offset*HZ; + + est_freq += 5000; /* round */ + est_freq -= est_freq%10000; + printk("CPU frequency %d.%02d MHz\n", est_freq/1000000, + (est_freq%1000000)*100/1000000); + + local_irq_restore(flags); +} + +void __init mips_timer_setup(struct irqaction *irq) +{ + /* we are using the cpu counter for timer interrupts */ + irq->handler = no_action; /* we use our own handler */ + setup_irq(MIPS_CPU_TIMER_IRQ, irq); + + /* to generate the first timer interrupt */ + r4k_cur = (read_c0_count() + r4k_offset); + write_c0_compare(r4k_cur); + set_c0_status(ALLINTS); +} diff -Nru a/arch/mips/mm/Makefile b/arch/mips/mm/Makefile --- a/arch/mips/mm/Makefile Tue Jul 1 18:44:36 2003 +++ b/arch/mips/mm/Makefile Tue Jul 1 18:44:36 2003 @@ -2,17 +2,29 @@ # Makefile for the Linux/MIPS-specific parts of the memory manager. # -obj-y += extable.o init.o ioremap.o fault.o loadmmu.o +obj-y += cache.o extable.o init.o ioremap.o fault.o \ + pgtable.o loadmmu.o -obj-$(CONFIG_CPU_R3000) += r2300.o -obj-$(CONFIG_CPU_R4300) += r4xx0.o -obj-$(CONFIG_CPU_R4X00) += r4xx0.o -obj-$(CONFIG_CPU_VR41XX) += r4xx0.o -obj-$(CONFIG_CPU_R5000) += r4xx0.o -obj-$(CONFIG_CPU_NEVADA) += r4xx0.o -obj-$(CONFIG_CPU_R5432) += r5432.o -obj-$(CONFIG_CPU_RM7000) += rm7k.o -obj-$(CONFIG_CPU_MIPS32) += mips32.o -obj-$(CONFIG_CPU_MIPS64) += mips32.o -obj-$(CONFIG_SGI_IP22) += umap.o -obj-$(CONFIG_BAGET_MIPS) += umap.o +obj-$(CONFIG_HIGHMEM) += highmem.o + +obj-$(CONFIG_CPU_R3000) += pg-r3k.o c-r3k.o tlb-r3k.o tlbex-r3k.o +obj-$(CONFIG_CPU_TX39XX) += pg-r3k.o c-tx39.o tlb-r3k.o tlbex-r3k.o +obj-$(CONFIG_CPU_TX49XX) += pg-r4k.o c-r4k.o tlb-r4k.o tlbex-r4k.o +obj-$(CONFIG_CPU_R4300) += pg-r4k.o c-r4k.o tlb-r4k.o tlbex-r4k.o +obj-$(CONFIG_CPU_R4X00) += pg-r4k.o c-r4k.o tlb-r4k.o tlbex-r4k.o +obj-$(CONFIG_CPU_VR41XX) += pg-r4k.o c-r4k.o tlb-r4k.o tlbex-r4k.o +obj-$(CONFIG_CPU_R5000) += pg-r4k.o c-r4k.o tlb-r4k.o tlbex-r4k.o +obj-$(CONFIG_CPU_NEVADA) += pg-r4k.o c-r4k.o tlb-r4k.o tlbex-r4k.o +obj-$(CONFIG_CPU_R5432) += pg-r4k.o c-r4k.o tlb-r4k.o tlbex-r4k.o +obj-$(CONFIG_CPU_RM7000) += pg-r4k.o c-r4k.o tlb-r4k.o tlbex-r4k.o +obj-$(CONFIG_CPU_R10000) += pg-r4k.o c-r4k.o tlb-r4k.o tlbex-r4k.o +obj-$(CONFIG_CPU_MIPS32) += pg-r4k.o c-r4k.o tlb-r4k.o tlbex-r4k.o +obj-$(CONFIG_CPU_MIPS64) += pg-r4k.o c-r4k.o tlb-r4k.o tlbex-r4k.o +obj-$(CONFIG_CPU_SB1) += c-sb1.o cex-sb1.o cerr-sb1.o pg-sb1.o \ + tlb-sb1.o tlbex-r4k.o + +obj-$(CONFIG_CPU_RM7000) += sc-rm7k.o +obj-$(CONFIG_R5000_CPU_SCACHE) += sc-r5k.o +obj-$(CONFIG_SGI_IP22) += sc-ip22.o + +EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips/mm/andes.c b/arch/mips/mm/andes.c --- a/arch/mips/mm/andes.c Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,196 +0,0 @@ -/* - * andes.c: MMU and cache operations for the R10000 (ANDES). - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* page functions */ -void andes_clear_page(void * page) -{ - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "addiu\t$1,%0,%2\n" - "1:\tsw\t$0,(%0)\n\t" - "sw\t$0,4(%0)\n\t" - "sw\t$0,8(%0)\n\t" - "sw\t$0,12(%0)\n\t" - "addiu\t%0,32\n\t" - "sw\t$0,-16(%0)\n\t" - "sw\t$0,-12(%0)\n\t" - "sw\t$0,-8(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sw\t$0,-4(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (page) - :"0" (page), - "I" (PAGE_SIZE) - :"$1","memory"); -} - -static void andes_copy_page(void * to, void * from) -{ - unsigned long dummy1, dummy2; - unsigned long reg1, reg2, reg3, reg4; - - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "addiu\t$1,%0,%8\n" - "1:\tlw\t%2,(%1)\n\t" - "lw\t%3,4(%1)\n\t" - "lw\t%4,8(%1)\n\t" - "lw\t%5,12(%1)\n\t" - "sw\t%2,(%0)\n\t" - "sw\t%3,4(%0)\n\t" - "sw\t%4,8(%0)\n\t" - "sw\t%5,12(%0)\n\t" - "lw\t%2,16(%1)\n\t" - "lw\t%3,20(%1)\n\t" - "lw\t%4,24(%1)\n\t" - "lw\t%5,28(%1)\n\t" - "sw\t%2,16(%0)\n\t" - "sw\t%3,20(%0)\n\t" - "sw\t%4,24(%0)\n\t" - "sw\t%5,28(%0)\n\t" - "addiu\t%0,64\n\t" - "addiu\t%1,64\n\t" - "lw\t%2,-32(%1)\n\t" - "lw\t%3,-28(%1)\n\t" - "lw\t%4,-24(%1)\n\t" - "lw\t%5,-20(%1)\n\t" - "sw\t%2,-32(%0)\n\t" - "sw\t%3,-28(%0)\n\t" - "sw\t%4,-24(%0)\n\t" - "sw\t%5,-20(%0)\n\t" - "lw\t%2,-16(%1)\n\t" - "lw\t%3,-12(%1)\n\t" - "lw\t%4,-8(%1)\n\t" - "lw\t%5,-4(%1)\n\t" - "sw\t%2,-16(%0)\n\t" - "sw\t%3,-12(%0)\n\t" - "sw\t%4,-8(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sw\t%5,-4(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (dummy1), "=r" (dummy2), - "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4) - :"0" (to), "1" (from), - "I" (PAGE_SIZE)); -} - -/* Cache operations. XXX Write these dave... */ -static inline void andes_flush_cache_all(void) -{ - /* XXX */ -} - -static void andes_flush_cache_mm(struct mm_struct *mm) -{ - /* XXX */ -} - -static void andes_flush_cache_range(struct vm_area_struct *vma, - unsigned long start, - unsigned long end) -{ - /* XXX */ -} - -static void andes_flush_cache_page(struct vm_area_struct *vma, - unsigned long page) -{ - /* XXX */ -} - -static void andes_flush_page_to_ram(struct page * page) -{ - /* XXX */ -} - -static void __andes_flush_icache_range(unsigned long start, unsigned long end) -{ - /* XXX */ -} - -static void andes_flush_icache_page(struct vm_area_struct *vma, - struct page *page) -{ - /* XXX */ -} - -static void andes_flush_cache_sigtramp(unsigned long page) -{ - protected_writeback_dcache_line(addr & ~(dc_lsize - 1)); - protected_flush_icache_line(addr & ~(ic_lsize - 1)); -} - -/* TLB operations. XXX Write these dave... */ -void flush_tlb_all(void) -{ - /* XXX */ -} - -void flush_tlb_mm(struct mm_struct *mm) -{ - /* XXX */ -} - -void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, - unsigned long end) -{ - /* XXX */ -} - -void flush_tlb_page(struct vm_area_struct *vma, unsigned long page) -{ - /* XXX */ -} - -void pgd_init(unsigned long page) -{ -} - -void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, - unsigned long entryhi, unsigned long pagemask) -{ - /* XXX */ -} - -void __init ld_mmu_andes(void) -{ - _clear_page = andes_clear_page; - _copy_page = andes_copy_page; - - _flush_cache_all = andes_flush_cache_all; - ___flush_cache_all = andes_flush_cache_all; - _flush_cache_mm = andes_flush_cache_mm; - _flush_cache_range = andes_flush_cache_range; - _flush_cache_page = andes_flush_cache_page; - _flush_cache_sigtramp = andes_flush_cache_sigtramp; - _flush_page_to_ram = andes_flush_page_to_ram; - _flush_icache_page = andes_flush_icache_page; - _flush_icache_range = andes_flush_icache_range; - - write_32bit_cp0_register(CP0_FRAMEMASK, 0); - - flush_cache_all(); - flush_tlb_all(); - - /* - * The R10k might even work for Linux/MIPS - but we're paranoid - * and refuse to run until this is tested on real silicon - */ - panic("CPU too expensive - making holiday in the ANDES!"); -} diff -Nru a/arch/mips/mm/c-r3k.c b/arch/mips/mm/c-r3k.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/mm/c-r3k.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,344 @@ +/* + * r2300.c: R2000 and R3000 specific mmu/cache code. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * with a lot of changes to make this thing work for R3000s + * Tx39XX R4k style caches added. HK + * Copyright (C) 1998, 1999, 2000 Harald Koerfgen + * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov + * Copyright (C) 2001 Maciej W. Rozycki + */ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +void r3k_clear_page(void * page); +void r3k_copy_page(void * to, void * from); + +static unsigned long icache_size, dcache_size; /* Size in bytes */ +static unsigned long icache_lsize, dcache_lsize; /* Size in bytes */ + +#undef DEBUG_CACHE + +unsigned long __init r3k_cache_size(unsigned long ca_flags) +{ + unsigned long flags, status, dummy, size; + volatile unsigned long *p; + + p = (volatile unsigned long *) KSEG0; + + flags = read_c0_status(); + + /* isolate cache space */ + write_c0_status((ca_flags|flags)&~ST0_IEC); + + *p = 0xa5a55a5a; + dummy = *p; + status = read_c0_status(); + + if (dummy != 0xa5a55a5a || (status & ST0_CM)) { + size = 0; + } else { + for (size = 128; size <= 0x40000; size <<= 1) + *(p + size) = 0; + *p = -1; + for (size = 128; + (size <= 0x40000) && (*(p + size) == 0); + size <<= 1) + ; + if (size > 0x40000) + size = 0; + } + + write_c0_status(flags); + + return size * sizeof(*p); +} + +unsigned long __init r3k_cache_lsize(unsigned long ca_flags) +{ + unsigned long flags, status, lsize, i; + volatile unsigned long *p; + + p = (volatile unsigned long *) KSEG0; + + flags = read_c0_status(); + + /* isolate cache space */ + write_c0_status((ca_flags|flags)&~ST0_IEC); + + for (i = 0; i < 128; i++) + *(p + i) = 0; + *(volatile unsigned char *)p = 0; + for (lsize = 1; lsize < 128; lsize <<= 1) { + *(p + lsize); + status = read_c0_status(); + if (!(status & ST0_CM)) + break; + } + for (i = 0; i < 128; i += lsize) + *(volatile unsigned char *)(p + i) = 0; + + write_c0_status(flags); + + return lsize * sizeof(*p); +} + +static void __init r3k_probe_cache(void) +{ + dcache_size = r3k_cache_size(ST0_ISC); + if (dcache_size) + dcache_lsize = r3k_cache_lsize(ST0_ISC); + + icache_size = r3k_cache_size(ST0_ISC|ST0_SWC); + if (icache_size) + icache_lsize = r3k_cache_lsize(ST0_ISC|ST0_SWC); +} + +static void r3k_flush_icache_range(unsigned long start, unsigned long end) +{ + unsigned long size, i, flags; + volatile unsigned char *p; + + size = end - start; + if (size > icache_size || KSEGX(start) != KSEG0) { + start = KSEG0; + size = icache_size; + } + p = (char *)start; + + flags = read_c0_status(); + + /* isolate cache space */ + write_c0_status((ST0_ISC|ST0_SWC|flags)&~ST0_IEC); + + for (i = 0; i < size; i += 0x080) { + asm ( "sb\t$0, 0x000(%0)\n\t" + "sb\t$0, 0x004(%0)\n\t" + "sb\t$0, 0x008(%0)\n\t" + "sb\t$0, 0x00c(%0)\n\t" + "sb\t$0, 0x010(%0)\n\t" + "sb\t$0, 0x014(%0)\n\t" + "sb\t$0, 0x018(%0)\n\t" + "sb\t$0, 0x01c(%0)\n\t" + "sb\t$0, 0x020(%0)\n\t" + "sb\t$0, 0x024(%0)\n\t" + "sb\t$0, 0x028(%0)\n\t" + "sb\t$0, 0x02c(%0)\n\t" + "sb\t$0, 0x030(%0)\n\t" + "sb\t$0, 0x034(%0)\n\t" + "sb\t$0, 0x038(%0)\n\t" + "sb\t$0, 0x03c(%0)\n\t" + "sb\t$0, 0x040(%0)\n\t" + "sb\t$0, 0x044(%0)\n\t" + "sb\t$0, 0x048(%0)\n\t" + "sb\t$0, 0x04c(%0)\n\t" + "sb\t$0, 0x050(%0)\n\t" + "sb\t$0, 0x054(%0)\n\t" + "sb\t$0, 0x058(%0)\n\t" + "sb\t$0, 0x05c(%0)\n\t" + "sb\t$0, 0x060(%0)\n\t" + "sb\t$0, 0x064(%0)\n\t" + "sb\t$0, 0x068(%0)\n\t" + "sb\t$0, 0x06c(%0)\n\t" + "sb\t$0, 0x070(%0)\n\t" + "sb\t$0, 0x074(%0)\n\t" + "sb\t$0, 0x078(%0)\n\t" + "sb\t$0, 0x07c(%0)\n\t" + : : "r" (p) ); + p += 0x080; + } + + write_c0_status(flags); +} + +static void r3k_flush_dcache_range(unsigned long start, unsigned long end) +{ + unsigned long size, i, flags; + volatile unsigned char *p; + + size = end - start; + if (size > dcache_size || KSEGX(start) != KSEG0) { + start = KSEG0; + size = dcache_size; + } + p = (char *)start; + + flags = read_c0_status(); + + /* isolate cache space */ + write_c0_status((ST0_ISC|flags)&~ST0_IEC); + + for (i = 0; i < size; i += 0x080) { + asm ( "sb\t$0, 0x000(%0)\n\t" + "sb\t$0, 0x004(%0)\n\t" + "sb\t$0, 0x008(%0)\n\t" + "sb\t$0, 0x00c(%0)\n\t" + "sb\t$0, 0x010(%0)\n\t" + "sb\t$0, 0x014(%0)\n\t" + "sb\t$0, 0x018(%0)\n\t" + "sb\t$0, 0x01c(%0)\n\t" + "sb\t$0, 0x020(%0)\n\t" + "sb\t$0, 0x024(%0)\n\t" + "sb\t$0, 0x028(%0)\n\t" + "sb\t$0, 0x02c(%0)\n\t" + "sb\t$0, 0x030(%0)\n\t" + "sb\t$0, 0x034(%0)\n\t" + "sb\t$0, 0x038(%0)\n\t" + "sb\t$0, 0x03c(%0)\n\t" + "sb\t$0, 0x040(%0)\n\t" + "sb\t$0, 0x044(%0)\n\t" + "sb\t$0, 0x048(%0)\n\t" + "sb\t$0, 0x04c(%0)\n\t" + "sb\t$0, 0x050(%0)\n\t" + "sb\t$0, 0x054(%0)\n\t" + "sb\t$0, 0x058(%0)\n\t" + "sb\t$0, 0x05c(%0)\n\t" + "sb\t$0, 0x060(%0)\n\t" + "sb\t$0, 0x064(%0)\n\t" + "sb\t$0, 0x068(%0)\n\t" + "sb\t$0, 0x06c(%0)\n\t" + "sb\t$0, 0x070(%0)\n\t" + "sb\t$0, 0x074(%0)\n\t" + "sb\t$0, 0x078(%0)\n\t" + "sb\t$0, 0x07c(%0)\n\t" + : : "r" (p) ); + p += 0x080; + } + + write_c0_status(flags); +} + +static inline unsigned long get_phys_page (unsigned long addr, + struct mm_struct *mm) +{ + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + unsigned long physpage; + + pgd = pgd_offset(mm, addr); + pmd = pmd_offset(pgd, addr); + pte = pte_offset(pmd, addr); + + if ((physpage = pte_val(*pte)) & _PAGE_VALID) + return KSEG0ADDR(physpage & PAGE_MASK); + + return 0; +} + +static inline void r3k_flush_cache_all(void) +{ +} + +static inline void r3k___flush_cache_all(void) +{ + r3k_flush_icache_range(KSEG0, KSEG0 + icache_size); +} + +static void r3k_flush_cache_mm(struct mm_struct *mm) +{ +} + +static void r3k_flush_cache_range(struct vm_area_struct *vma, + unsigned long start, unsigned long end) +{ +} + +static void r3k_flush_cache_page(struct vm_area_struct *vma, + unsigned long page) +{ +} + +static void r3k_flush_data_cache_page(unsigned long addr) +{ +} + +static void r3k_flush_icache_page(struct vm_area_struct *vma, struct page *page) +{ + struct mm_struct *mm = vma->vm_mm; + unsigned long physpage; + + if (cpu_context(smp_processor_id(), mm) == 0) + return; + + if (!(vma->vm_flags & VM_EXEC)) + return; + +#ifdef DEBUG_CACHE + printk("cpage[%d,%08lx]", cpu_context(smp_processor_id(), mm), page); +#endif + + physpage = (unsigned long) page_address(page); + if (physpage) + r3k_flush_icache_range(physpage, physpage + PAGE_SIZE); +} + +static void r3k_flush_cache_sigtramp(unsigned long addr) +{ + unsigned long flags; + +#ifdef DEBUG_CACHE + printk("csigtramp[%08lx]", addr); +#endif + + flags = read_c0_status(); + + write_c0_status(flags&~ST0_IEC); + + /* Fill the TLB to avoid an exception with caches isolated. */ + asm ( "lw\t$0, 0x000(%0)\n\t" + "lw\t$0, 0x004(%0)\n\t" + : : "r" (addr) ); + + write_c0_status((ST0_ISC|ST0_SWC|flags)&~ST0_IEC); + + asm ( "sb\t$0, 0x000(%0)\n\t" + "sb\t$0, 0x004(%0)\n\t" + : : "r" (addr) ); + + write_c0_status(flags); +} + +static void r3k_dma_cache_wback_inv(unsigned long start, unsigned long size) +{ + iob(); + r3k_flush_dcache_range(start, start + size); +} + +void __init ld_mmu_r23000(void) +{ + _clear_page = r3k_clear_page; + _copy_page = r3k_copy_page; + + r3k_probe_cache(); + + flush_cache_all = r3k_flush_cache_all; + __flush_cache_all = r3k___flush_cache_all; + flush_cache_mm = r3k_flush_cache_mm; + flush_cache_range = r3k_flush_cache_range; + flush_cache_page = r3k_flush_cache_page; + flush_icache_page = r3k_flush_icache_page; + flush_icache_range = r3k_flush_icache_range; + + flush_cache_sigtramp = r3k_flush_cache_sigtramp; + flush_data_cache_page = r3k_flush_data_cache_page; + + _dma_cache_wback_inv = r3k_dma_cache_wback_inv; + + printk("Primary instruction cache %ldkB, linesize %ld bytes.\n", + icache_size >> 10, icache_lsize); + printk("Primary data cache %ldkB, linesize %ld bytes.\n", + dcache_size >> 10, dcache_lsize); +} diff -Nru a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/mm/c-r4k.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,1161 @@ +/* + * 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) 1996 David S. Miller (dm@engr.sgi.com) + * Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Primary cache parameters. */ +static unsigned long icache_size, dcache_size, scache_size; +unsigned long icache_way_size, dcache_way_size, scache_way_size; +static unsigned long scache_size; + +#include +#include + +extern void andes_clear_page(void * page); +extern void r4k_clear_page32_d16(void * page); +extern void r4k_clear_page32_d32(void * page); +extern void r4k_clear_page_d16(void * page); +extern void r4k_clear_page_d32(void * page); +extern void r4k_clear_page_r4600_v1(void * page); +extern void r4k_clear_page_r4600_v2(void * page); +extern void r4k_clear_page_s16(void * page); +extern void r4k_clear_page_s32(void * page); +extern void r4k_clear_page_s64(void * page); +extern void r4k_clear_page_s128(void * page); +extern void andes_copy_page(void * to, void * from); +extern void r4k_copy_page_d16(void * to, void * from); +extern void r4k_copy_page_d32(void * to, void * from); +extern void r4k_copy_page_r4600_v1(void * to, void * from); +extern void r4k_copy_page_r4600_v2(void * to, void * from); +extern void r4k_copy_page_s16(void * to, void * from); +extern void r4k_copy_page_s32(void * to, void * from); +extern void r4k_copy_page_s64(void * to, void * from); +extern void r4k_copy_page_s128(void * to, void * from); + +/* + * Dummy cache handling routines for machines without boardcaches + */ +static void no_sc_noop(void) {} + +static struct bcache_ops no_sc_ops = { + .bc_enable = (void *)no_sc_noop, + .bc_disable = (void *)no_sc_noop, + .bc_wback_inv = (void *)no_sc_noop, + .bc_inv = (void *)no_sc_noop +}; + +struct bcache_ops *bcops = &no_sc_ops; + +#define R4600_HIT_CACHEOP_WAR_IMPL \ +do { \ + if (R4600_V2_HIT_CACHEOP_WAR && \ + (read_c0_prid() & 0xfff0) == 0x2020) { /* R4600 V2.0 */\ + *(volatile unsigned long *)KSEG1; \ + } \ + if (R4600_V1_HIT_CACHEOP_WAR) \ + __asm__ __volatile__("nop;nop;nop;nop"); \ +} while (0) + +static void r4k_blast_dcache_page(unsigned long addr) +{ + static void *l = &&init; + unsigned long dc_lsize; + + goto *l; + +dc_16: + blast_dcache16_page(addr); + return; + +dc_32: + R4600_HIT_CACHEOP_WAR_IMPL; + blast_dcache32_page(addr); + return; + +init: + dc_lsize = current_cpu_data.dcache.linesz; + + if (dc_lsize == 16) + l = &&dc_16; + else if (dc_lsize == 32) + l = &&dc_32; + goto *l; +} + +static void r4k_blast_dcache_page_indexed(unsigned long addr) +{ + static void *l = &&init; + unsigned long dc_lsize; + + goto *l; + +dc_16: + blast_dcache16_page_indexed(addr); + return; + +dc_32: + blast_dcache32_page_indexed(addr); + return; + +init: + dc_lsize = current_cpu_data.dcache.linesz; + + if (dc_lsize == 16) + l = &&dc_16; + else if (dc_lsize == 32) + l = &&dc_32; + goto *l; +} + +static void r4k_blast_dcache(void) +{ + static void *l = &&init; + unsigned long dc_lsize; + + goto *l; + +dc_16: + blast_dcache16(); + return; + +dc_32: + blast_dcache32(); + return; + +init: + dc_lsize = current_cpu_data.dcache.linesz; + + if (dc_lsize == 16) + l = &&dc_16; + else if (dc_lsize == 32) + l = &&dc_32; + goto *l; +} + +static void r4k_blast_icache_page(unsigned long addr) +{ + unsigned long ic_lsize = current_cpu_data.icache.linesz; + static void *l = &&init; + + goto *l; + +ic_16: + blast_icache16_page(addr); + return; + +ic_32: + blast_icache32_page(addr); + return; + +ic_64: + blast_icache64_page(addr); + return; + +init: + if (ic_lsize == 16) + l = &&ic_16; + else if (ic_lsize == 32) + l = &&ic_32; + else if (ic_lsize == 64) + l = &&ic_64; + goto *l; +} + +static void r4k_blast_icache_page_indexed(unsigned long addr) +{ + unsigned long ic_lsize = current_cpu_data.icache.linesz; + static void *l = &&init; + + goto *l; + +ic_16: + blast_icache16_page_indexed(addr); + return; + +ic_32: + blast_icache32_page_indexed(addr); + return; + +ic_64: + blast_icache64_page_indexed(addr); + return; + +init: + if (ic_lsize == 16) + l = &&ic_16; + else if (ic_lsize == 32) + l = &&ic_32; + else if (ic_lsize == 64) + l = &&ic_64; + goto *l; +} + +static void r4k_blast_icache(void) +{ + unsigned long ic_lsize = current_cpu_data.icache.linesz; + static void *l = &&init; + + goto *l; + +ic_16: + blast_icache16(); + return; + +ic_32: + blast_icache32(); + return; + +ic_64: + blast_icache64(); + return; + +init: + if (ic_lsize == 16) + l = &&ic_16; + else if (ic_lsize == 32) + l = &&ic_32; + else if (ic_lsize == 64) + l = &&ic_64; + goto *l; +} + +static void r4k_blast_scache_page(unsigned long addr) +{ + unsigned long sc_lsize = current_cpu_data.scache.linesz; + static void *l = &&init; + + goto *l; + +sc_16: + blast_scache16_page(addr); + return; + +sc_32: + blast_scache32_page(addr); + return; + +sc_64: + blast_scache64_page(addr); + return; + +sc_128: + blast_scache128_page(addr); + return; + +init: + if (sc_lsize == 16) + l = &&sc_16; + else if (sc_lsize == 32) + l = &&sc_32; + else if (sc_lsize == 64) + l = &&sc_64; + else if (sc_lsize == 128) + l = &&sc_128; + goto *l; +} + +static void r4k_blast_scache(void) +{ + unsigned long sc_lsize = current_cpu_data.scache.linesz; + static void *l = &&init; + + goto *l; + +sc_16: + blast_scache16(); + return; + +sc_32: + blast_scache32(); + return; + +sc_64: + blast_scache64(); + return; + +sc_128: + blast_scache128(); + return; + +init: + if (sc_lsize == 16) + l = &&sc_16; + else if (sc_lsize == 32) + l = &&sc_32; + else if (sc_lsize == 64) + l = &&sc_64; + else if (sc_lsize == 128) + l = &&sc_128; + goto *l; +} + +static void r4k_flush_cache_all(void) +{ + if (!cpu_has_dc_aliases) + return; + + r4k_blast_dcache(); + r4k_blast_icache(); +} + +static void r4k___flush_cache_all(void) +{ + r4k_blast_dcache(); + r4k_blast_icache(); + + switch (current_cpu_data.cputype) { + case CPU_R4000SC: + case CPU_R4000MC: + case CPU_R4400SC: + case CPU_R4400MC: + case CPU_R10000: + case CPU_R12000: + r4k_blast_scache(); + } +} + +static void r4k_flush_cache_range(struct vm_area_struct *vma, + unsigned long start, unsigned long end) +{ + if (cpu_context(smp_processor_id(), vma->vm_mm) != 0) { + r4k_blast_dcache(); + if (vma->vm_flags & VM_EXEC) + r4k_blast_icache(); + } +} + +static void r4k_flush_cache_mm(struct mm_struct *mm) +{ + if (!cpu_has_dc_aliases) + return; + + if (!cpu_context(smp_processor_id(), mm)) + return; + + r4k_blast_dcache(); + r4k_blast_icache(); + + /* + * Kludge alert. For obscure reasons R4000SC and R4400SC go nuts if we + * only flush the primary caches but R10000 and R12000 behave sane ... + */ + if (current_cpu_data.cputype == CPU_R4000SC || + current_cpu_data.cputype == CPU_R4000MC || + current_cpu_data.cputype == CPU_R4400SC || + current_cpu_data.cputype == CPU_R4400MC) + r4k_blast_scache(); +} + +static void r4k_flush_cache_page(struct vm_area_struct *vma, + unsigned long page) +{ + int exec = vma->vm_flags & VM_EXEC; + struct mm_struct *mm = vma->vm_mm; + pgd_t *pgdp; + pmd_t *pmdp; + pte_t *ptep; + + /* + * If ownes no valid ASID yet, cannot possibly have gotten + * this page into the cache. + */ + if (cpu_context(smp_processor_id(), mm) == 0) + return; + + page &= PAGE_MASK; + pgdp = pgd_offset(mm, page); + pmdp = pmd_offset(pgdp, page); + ptep = pte_offset(pmdp, page); + + /* + * If the page isn't marked valid, the page cannot possibly be + * in the cache. + */ + if (!(pte_val(*ptep) & _PAGE_PRESENT)) + return; + + /* + * Doing flushes for another ASID than the current one is + * too difficult since stupid R4k caches do a TLB translation + * for every cache flush operation. So we do indexed flushes + * in that case, which doesn't overly flush the cache too much. + */ + if ((mm == current->active_mm) && (pte_val(*ptep) & _PAGE_VALID)) { + if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) + r4k_blast_dcache_page(page); + if (exec) + r4k_blast_icache_page(page); + + return; + } + + /* + * Do indexed flush, too much work to get the (possible) TLB refills + * to work correctly. + */ + page = (KSEG0 + (page & (dcache_size - 1))); + if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) + r4k_blast_dcache_page_indexed(page); + if (exec) { + if (cpu_has_vtag_icache) { + int cpu = smp_processor_id(); + + if (cpu_context(cpu, vma->vm_mm) != 0) + drop_mmu_context(vma->vm_mm, cpu); + } else + r4k_blast_icache_page_indexed(page); + } +} + +static void r4k_flush_data_cache_page(unsigned long addr) +{ + r4k_blast_dcache_page(addr); +} + +static void r4k_flush_icache_range(unsigned long start, unsigned long end) +{ + unsigned long dc_lsize = current_cpu_data.dcache.linesz; + unsigned long addr, aend; + + if (!cpu_has_ic_fills_f_dc) { + if (end - start > dcache_size) + r4k_blast_dcache(); + else { + addr = start & ~(dc_lsize - 1); + aend = (end - 1) & ~(dc_lsize - 1); + + while (1) { + /* Hit_Writeback_Inv_D */ + protected_writeback_dcache_line(addr); + if (addr == aend) + break; + addr += dc_lsize; + } + } + } + + if (end - start > icache_size) + r4k_blast_icache(); + else { + addr = start & ~(dc_lsize - 1); + aend = (end - 1) & ~(dc_lsize - 1); + while (1) { + /* Hit_Invalidate_I */ + protected_flush_icache_line(addr); + if (addr == aend) + break; + addr += dc_lsize; + } + } +} + +/* + * Ok, this seriously sucks. We use them to flush a user page but don't + * know the virtual address, so we have to blast away the whole icache + * which is significantly more expensive than the real thing. Otoh we at + * least know the kernel address of the page so we can flush it + * selectivly. + */ +static void r4k_flush_icache_page(struct vm_area_struct *vma, + struct page *page) +{ + /* + * If there's no context yet, or the page isn't executable, no icache + * flush is needed. + */ + if (!(vma->vm_flags & VM_EXEC)) + return; + + /* + * Tricky ... Because we don't know the virtual address we've got the + * choice of either invalidating the entire primary and secondary + * caches or invalidating the secondary caches also. With the subset + * enforcment on R4000SC, R4400SC, R10000 and R12000 invalidating the + * secondary cache will result in any entries in the primary caches + * also getting invalidated which hopefully is a bit more economical. + */ + if (cpu_has_subset_pcaches) { + unsigned long addr = (unsigned long) page_address(page); + r4k_blast_scache_page(addr); + + return; + } + + if (!cpu_has_ic_fills_f_dc) { + unsigned long addr = (unsigned long) page_address(page); + r4k_blast_dcache_page(addr); + } + + /* + * We're not sure of the virtual address(es) involved here, so + * we have to flush the entire I-cache. + */ + if (cpu_has_vtag_icache) { + int cpu = smp_processor_id(); + + if (cpu_context(cpu, vma->vm_mm) != 0) + drop_mmu_context(vma->vm_mm, cpu); + } else + r4k_blast_icache(); +} + +#ifdef CONFIG_NONCOHERENT_IO + +static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size) +{ + unsigned long end, a; + + if (cpu_has_subset_pcaches) { + unsigned long sc_lsize = current_cpu_data.scache.linesz; + + if (size >= scache_size) { + r4k_blast_scache(); + return; + } + + a = addr & ~(sc_lsize - 1); + end = (addr + size - 1) & ~(sc_lsize - 1); + while (1) { + flush_scache_line(a); /* Hit_Writeback_Inv_SD */ + if (a == end) + break; + a += sc_lsize; + } + return; + } + + /* + * Either no secondary cache or the available caches don't have the + * subset property so we have to flush the primary caches + * explicitly + */ + if (size >= dcache_size) { + r4k_blast_dcache(); + } else { + unsigned long dc_lsize = current_cpu_data.dcache.linesz; + + R4600_HIT_CACHEOP_WAR_IMPL; + a = addr & ~(dc_lsize - 1); + end = (addr + size - 1) & ~(dc_lsize - 1); + while (1) { + flush_dcache_line(a); /* Hit_Writeback_Inv_D */ + if (a == end) + break; + a += dc_lsize; + } + } + + bc_wback_inv(addr, size); +} + +static void r4k_dma_cache_inv(unsigned long addr, unsigned long size) +{ + unsigned long end, a; + + if (cpu_has_subset_pcaches) { + unsigned long sc_lsize = current_cpu_data.scache.linesz; + + if (size >= scache_size) { + r4k_blast_scache(); + return; + } + + a = addr & ~(sc_lsize - 1); + end = (addr + size - 1) & ~(sc_lsize - 1); + while (1) { + flush_scache_line(a); /* Hit_Writeback_Inv_SD */ + if (a == end) + break; + a += sc_lsize; + } + return; + } + + if (size >= dcache_size) { + r4k_blast_dcache(); + } else { + unsigned long dc_lsize = current_cpu_data.dcache.linesz; + + R4600_HIT_CACHEOP_WAR_IMPL; + a = addr & ~(dc_lsize - 1); + end = (addr + size - 1) & ~(dc_lsize - 1); + while (1) { + flush_dcache_line(a); /* Hit_Writeback_Inv_D */ + if (a == end) + break; + a += dc_lsize; + } + } + + bc_inv(addr, size); +} +#endif /* CONFIG_NONCOHERENT_IO */ + +/* + * While we're protected against bad userland addresses we don't care + * very much about what happens in that case. Usually a segmentation + * fault will dump the process later on anyway ... + */ +static void r4k_flush_cache_sigtramp(unsigned long addr) +{ + unsigned long ic_lsize = current_cpu_data.icache.linesz; + unsigned long dc_lsize = current_cpu_data.dcache.linesz; + + R4600_HIT_CACHEOP_WAR_IMPL; + protected_writeback_dcache_line(addr & ~(dc_lsize - 1)); + protected_flush_icache_line(addr & ~(ic_lsize - 1)); +} + +static void r4k_flush_icache_all(void) +{ + if (cpu_has_vtag_icache) + r4k_blast_icache(); +} + +static inline void rm7k_erratum31(void) +{ + const unsigned long ic_lsize = 32; + unsigned long addr; + + /* RM7000 erratum #31. The icache is screwed at startup. */ + write_c0_taglo(0); + write_c0_taghi(0); + + for (addr = KSEG0; addr <= KSEG0 + 4096; addr += ic_lsize) { + __asm__ __volatile__ ( + ".set noreorder\n\t" + ".set mips3\n\t" + "cache\t%1, 0(%0)\n\t" + "cache\t%1, 0x1000(%0)\n\t" + "cache\t%1, 0x2000(%0)\n\t" + "cache\t%1, 0x3000(%0)\n\t" + "cache\t%2, 0(%0)\n\t" + "cache\t%2, 0x1000(%0)\n\t" + "cache\t%2, 0x2000(%0)\n\t" + "cache\t%2, 0x3000(%0)\n\t" + "cache\t%1, 0(%0)\n\t" + "cache\t%1, 0x1000(%0)\n\t" + "cache\t%1, 0x2000(%0)\n\t" + "cache\t%1, 0x3000(%0)\n\t" + ".set\tmips0\n\t" + ".set\treorder\n\t" + : + : "r" (addr), "i" (Index_Store_Tag_I), "i" (Fill)); + } +} + +static char *way_string[] = { NULL, "direct mapped", "2-way", "3-way", "4-way", + "5-way", "6-way", "7-way", "8-way" +}; + +static void __init probe_pcache(void) +{ + struct cpuinfo_mips *c = ¤t_cpu_data; + unsigned int config = read_c0_config(); + unsigned int prid = read_c0_prid(); + unsigned long config1; + unsigned int lsize; + + switch (current_cpu_data.cputype) { + case CPU_R4600: /* QED style two way caches? */ + case CPU_R4700: + case CPU_R5000: + case CPU_NEVADA: + icache_size = 1 << (12 + ((config & CONF_IC) >> 9)); + c->icache.linesz = 16 << ((config & CONF_IB) >> 5); + c->icache.ways = 2; + c->icache.waybit = ffs(icache_size/2) - 1; + + dcache_size = 1 << (12 + ((config & CONF_DC) >> 6)); + c->dcache.linesz = 16 << ((config & CONF_DB) >> 4); + c->dcache.ways = 2; + c->dcache.waybit= ffs(dcache_size/2) - 1; + break; + + case CPU_R5432: + case CPU_R5500: + icache_size = 1 << (12 + ((config & CONF_IC) >> 9)); + c->icache.linesz = 16 << ((config & CONF_IB) >> 5); + c->icache.ways = 2; + c->icache.waybit= 0; + + dcache_size = 1 << (12 + ((config & CONF_DC) >> 6)); + c->dcache.linesz = 16 << ((config & CONF_DB) >> 4); + c->dcache.ways = 2; + c->dcache.waybit = 0; + break; + + case CPU_TX49XX: + icache_size = 1 << (12 + ((config & CONF_IC) >> 9)); + c->icache.linesz = 16 << ((config & CONF_IB) >> 5); + c->icache.ways = 4; + c->icache.waybit= 0; + + dcache_size = 1 << (12 + ((config & CONF_DC) >> 6)); + c->dcache.linesz = 16 << ((config & CONF_DB) >> 4); + c->dcache.ways = 4; + c->dcache.waybit = 0; + break; + + case CPU_R4000PC: + case CPU_R4000SC: + case CPU_R4000MC: + case CPU_R4400PC: + case CPU_R4400SC: + case CPU_R4400MC: + icache_size = 1 << (12 + ((config & CONF_IC) >> 9)); + c->icache.linesz = 16 << ((config & CONF_IB) >> 5); + c->icache.ways = 1; + c->icache.waybit = 0; /* doesn't matter */ + + dcache_size = 1 << (12 + ((config & CONF_DC) >> 6)); + c->dcache.linesz = 16 << ((config & CONF_DB) >> 4); + c->dcache.ways = 1; + c->dcache.waybit = 0; /* does not matter */ + break; + + case CPU_R10000: + case CPU_R12000: + icache_size = 1 << (12 + ((config & R10K_CONF_IC) >> 29)); + c->icache.linesz = 64; + c->icache.ways = 2; + c->icache.waybit = 0; + + dcache_size = 1 << (12 + ((config & R10K_CONF_DC) >> 26)); + c->dcache.linesz = 32; + c->dcache.ways = 2; + c->dcache.waybit = 0; + break; + + case CPU_VR4131: + icache_size = 1 << (10 + ((config & CONF_IC) >> 9)); + c->icache.linesz = 16 << ((config & CONF_IB) >> 5); + c->icache.ways = 2; + c->icache.waybit = ffs(icache_size/2) - 1; + + dcache_size = 1 << (10 + ((config & CONF_DC) >> 6)); + c->dcache.linesz = 16 << ((config & CONF_DB) >> 4); + c->dcache.ways = 2; + c->dcache.waybit = ffs(dcache_size/2) - 1; + break; + + case CPU_VR41XX: + case CPU_VR4111: + case CPU_VR4121: + case CPU_VR4122: + case CPU_VR4181: + case CPU_VR4181A: + icache_size = 1 << (10 + ((config & CONF_IC) >> 9)); + c->icache.linesz = 16 << ((config & CONF_IB) >> 5); + c->icache.ways = 1; + c->icache.waybit = 0; /* doesn't matter */ + + dcache_size = 1 << (10 + ((config & CONF_DC) >> 6)); + c->dcache.linesz = 16 << ((config & CONF_DB) >> 4); + c->dcache.ways = 1; + c->dcache.waybit = 0; /* does not matter */ + break; + + case CPU_RM7000: + rm7k_erratum31(); + + icache_size = 1 << (12 + ((config & CONF_IC) >> 9)); + c->icache.linesz = 16 << ((config & CONF_IB) >> 5); + c->icache.ways = 4; + c->icache.waybit = ffs(icache_size / c->icache.ways) - 1; + + dcache_size = 1 << (12 + ((config & CONF_DC) >> 6)); + c->dcache.linesz = 16 << ((config & CONF_DB) >> 4); + c->dcache.ways = 4; + c->dcache.waybit = ffs(dcache_size / c->dcache.ways) - 1; + break; + + default: + if (!(config & MIPS_CONF_M)) + panic("Don't know how to probe P-caches on this cpu."); + + /* + * So we seem to be a MIPS32 or MIPS64 CPU + * So let's probe the I-cache ... + */ + config1 = read_c0_config1(); + + if ((lsize = ((config1 >> 19) & 7))) + c->icache.linesz = 2 << lsize; + else + c->icache.linesz = lsize; + c->icache.sets = 64 << ((config1 >> 22) & 7); + c->icache.ways = 1 + ((config1 >> 16) & 7); + + icache_size = c->icache.sets * + c->icache.ways * + c->icache.linesz; + c->icache.waybit = ffs(icache_size/c->icache.ways) - 1; + + /* + * Now probe the MIPS32 / MIPS64 data cache. + */ + c->dcache.flags = 0; + + if ((lsize = ((config1 >> 10) & 7))) + c->dcache.linesz = 2 << lsize; + else + c->dcache.linesz= lsize; + c->dcache.sets = 64 << ((config1 >> 13) & 7); + c->dcache.ways = 1 + ((config1 >> 7) & 7); + + dcache_size = c->dcache.sets * + c->dcache.ways * + c->dcache.linesz; + c->dcache.waybit = ffs(dcache_size/c->dcache.ways) - 1; + break; + } + + /* + * Processor configuration sanity check for the R4000SC erratum + * #5. With page sizes larger than 32kB there is no possibility + * to get a VCE exception anymore so we don't care about this + * misconfiguration. The case is rather theoretical anyway; + * presumably no vendor is shipping his hardware in the "bad" + * configuration. + */ + if ((prid & 0xff00) == PRID_IMP_R4000 && (prid & 0xff) < 0x40 && + !(config & CONF_SC) && c->icache.linesz != 16 && + PAGE_SIZE <= 0x8000) + panic("Improper R4000SC processor configuration detected"); + + /* compute a couple of other cache variables */ + icache_way_size = icache_size / c->icache.ways; + dcache_way_size = dcache_size / c->dcache.ways; + + c->icache.sets = icache_size / (c->icache.linesz * c->icache.ways); + c->dcache.sets = dcache_size / (c->dcache.linesz * c->dcache.ways); + + /* + * R10000 and R12000 P-caches are odd in a positive way. They're 32kB + * 2-way virtually indexed so normally would suffer from aliases. So + * normally they'd suffer from aliases but magic in the hardware deals + * with that for us so we don't need to take care ourselves. + */ + if (current_cpu_data.cputype != CPU_R10000 && + current_cpu_data.cputype != CPU_R12000) + if (dcache_way_size > PAGE_SIZE) + c->dcache.flags |= MIPS_CACHE_ALIASES; + + if (config & 0x8) /* VI bit */ + c->icache.flags |= MIPS_CACHE_VTAG; + + switch (c->cputype) { + case CPU_20KC: + /* + * Some older 20Kc chips doesn't have the 'VI' bit in + * the config register. + */ + c->icache.flags |= MIPS_CACHE_VTAG; + break; + + case CPU_AU1500: + c->icache.flags |= MIPS_CACHE_IC_F_DC; + break; + } + + printk("Primary instruction cache %ldkB, %s, %s, linesize %d bytes.\n", + icache_size >> 10, + cpu_has_vtag_icache ? "virtually tagged" : "physically tagged", + way_string[c->icache.ways], c->icache.linesz); + + printk("Primary data cache %ldkB %s, linesize %d bytes.\n", + dcache_size >> 10, way_string[c->dcache.ways], c->dcache.linesz); +} + +/* + * If you even _breathe_ on this function, look at the gcc output and make sure + * it does not pop things on and off the stack for the cache sizing loop that + * executes in KSEG1 space or else you will crash and burn badly. You have + * been warned. + */ +static int __init probe_scache(void) +{ + extern unsigned long stext; + unsigned long flags, addr, begin, end, pow2; + unsigned int config = read_c0_config(); + struct cpuinfo_mips *c = ¤t_cpu_data; + int tmp; + + if (config & CONF_SC) + return 0; + + begin = (unsigned long) &stext; + begin &= ~((4 * 1024 * 1024) - 1); + end = begin + (4 * 1024 * 1024); + + /* + * This is such a bitch, you'd think they would make it easy to do + * this. Away you daemons of stupidity! + */ + local_irq_save(flags); + + /* Fill each size-multiple cache line with a valid tag. */ + pow2 = (64 * 1024); + for (addr = begin; addr < end; addr = (begin + pow2)) { + unsigned long *p = (unsigned long *) addr; + __asm__ __volatile__("nop" : : "r" (*p)); /* whee... */ + pow2 <<= 1; + } + + /* Load first line with zero (therefore invalid) tag. */ + write_c0_taglo(0); + write_c0_taghi(0); + __asm__ __volatile__("nop; nop; nop; nop;"); /* avoid the hazard */ + cache_op(Index_Store_Tag_I, begin); + cache_op(Index_Store_Tag_D, begin); + cache_op(Index_Store_Tag_SD, begin); + + /* Now search for the wrap around point. */ + pow2 = (128 * 1024); + tmp = 0; + for (addr = begin + (128 * 1024); addr < end; addr = begin + pow2) { + cache_op(Index_Load_Tag_SD, addr); + __asm__ __volatile__("nop; nop; nop; nop;"); /* hazard... */ + if (!read_c0_taglo()) + break; + pow2 <<= 1; + } + local_irq_restore(flags); + addr -= begin; + + c = ¤t_cpu_data; + scache_size = addr; + c->scache.linesz = 16 << ((config & R4K_CONF_SB) >> 22); + c->scache.ways = 1; + c->dcache.waybit = 0; /* does not matter */ + + return 1; +} + +static void __init setup_noscache_funcs(void) +{ + unsigned int prid; + + switch (current_cpu_data.dcache.linesz) { + case 16: + if (cpu_has_64bits) + _clear_page = r4k_clear_page_d16; + else + _clear_page = r4k_clear_page32_d16; + _copy_page = r4k_copy_page_d16; + + break; + case 32: + prid = read_c0_prid() & 0xfff0; + if (prid == 0x2010) { /* R4600 V1.7 */ + _clear_page = r4k_clear_page_r4600_v1; + _copy_page = r4k_copy_page_r4600_v1; + } else if (prid == 0x2020) { /* R4600 V2.0 */ + _clear_page = r4k_clear_page_r4600_v2; + _copy_page = r4k_copy_page_r4600_v2; + } else { + if (cpu_has_64bits) + _clear_page = r4k_clear_page_d32; + else + _clear_page = r4k_clear_page32_d32; + _copy_page = r4k_copy_page_d32; + } + break; + } +} + +static void __init setup_scache_funcs(void) +{ + if (current_cpu_data.dcache.linesz > current_cpu_data.scache.linesz) + panic("Invalid primary cache configuration detected"); + + if (current_cpu_data.cputype == CPU_R10000 || + current_cpu_data.cputype == CPU_R12000) { + _clear_page = andes_clear_page; + _copy_page = andes_copy_page; + return; + } + + switch (current_cpu_data.scache.linesz) { + case 16: + _clear_page = r4k_clear_page_s16; + _copy_page = r4k_copy_page_s16; + break; + case 32: + _clear_page = r4k_clear_page_s32; + _copy_page = r4k_copy_page_s32; + break; + case 64: + _clear_page = r4k_clear_page_s64; + _copy_page = r4k_copy_page_s64; + break; + case 128: + _clear_page = r4k_clear_page_s128; + _copy_page = r4k_copy_page_s128; + break; + } +} + +typedef int (*probe_func_t)(unsigned long); +extern int r5k_sc_init(void); +extern int rm7k_sc_init(void); + +static void __init setup_scache(void) +{ + struct cpuinfo_mips *c = ¤t_cpu_data; + unsigned int config = read_c0_config(); + probe_func_t probe_scache_kseg1; + int sc_present = 0; + + /* + * Do the probing thing on R4000SC and R4400SC processors. Other + * processors don't have a S-cache that would be relevant to the + * Linux memory managment. + */ + switch (current_cpu_data.cputype) { + case CPU_R4000PC: + case CPU_R4000SC: + case CPU_R4000MC: + case CPU_R4400PC: + case CPU_R4400SC: + case CPU_R4400MC: + probe_scache_kseg1 = (probe_func_t) (KSEG1ADDR(&probe_scache)); + sc_present = probe_scache_kseg1(config); + break; + + case CPU_R10000: + case CPU_R12000: + scache_size = 0x80000 << ((config & R10K_CONF_SS) >> 16); + c->scache.linesz = 64 << ((config >> 13) & 1); + c->scache.ways = 2; + c->scache.waybit= 0; + sc_present = 1; + break; + + case CPU_R5000: + case CPU_NEVADA: + setup_noscache_funcs(); +#ifdef CONFIG_R5000_CPU_SCACHE + r5k_sc_init(); +#endif + return; + + case CPU_RM7000: + setup_noscache_funcs(); +#ifdef CONFIG_RM7000_CPU_SCACHE + rm7k_sc_init(); +#endif + return; + + default: + sc_present = 0; + } + + if (!sc_present) { + setup_noscache_funcs(); + return; + } + + if ((current_cpu_data.isa_level == MIPS_CPU_ISA_M32 || + current_cpu_data.isa_level == MIPS_CPU_ISA_M64) && + !(current_cpu_data.scache.flags & MIPS_CACHE_NOT_PRESENT)) + panic("Dunno how to handle MIPS32 / MIPS64 second level cache"); + + printk("Unified secondary cache %ldkB %s, linesize %d bytes.\n", + scache_size >> 10, way_string[c->scache.ways], c->scache.linesz); + + current_cpu_data.options |= MIPS_CPU_SUBSET_CACHES; + setup_scache_funcs(); +} + +static inline void coherency_setup(void) +{ + change_c0_config(CONF_CM_CMASK, CONF_CM_DEFAULT); + + /* + * c0_status.cu=0 specifies that updates by the sc instruction use + * the coherency mode specified by the TLB; 1 means cachable + * coherent update on write will be used. Not all processors have + * this bit and; some wire it to zero, others like Toshiba had the + * silly idea of putting something else there ... + */ + switch (current_cpu_data.cputype) { + case CPU_R4000PC: + case CPU_R4000SC: + case CPU_R4000MC: + case CPU_R4400PC: + case CPU_R4400SC: + case CPU_R4400MC: + clear_c0_config(CONF_CU); + break; + } + +} + +void __init ld_mmu_r4xx0(void) +{ + extern char except_vec2_generic; + + /* Default cache error handler for R4000 and R5000 family */ + memcpy((void *)(KSEG0 + 0x100), &except_vec2_generic, 0x80); + memcpy((void *)(KSEG1 + 0x100), &except_vec2_generic, 0x80); + + probe_pcache(); + setup_scache(); + coherency_setup(); + + if (current_cpu_data.dcache.sets * + current_cpu_data.dcache.ways > PAGE_SIZE) + current_cpu_data.dcache.flags |= MIPS_CACHE_ALIASES; + + /* + * Some MIPS32 and MIPS64 processors have physically indexed caches. + * This code supports virtually indexed processors and will be + * unnecessarily unefficient on physically indexed processors. + */ + shm_align_mask = max_t(unsigned long, + current_cpu_data.dcache.sets * current_cpu_data.dcache.linesz - 1, + PAGE_SIZE - 1); + + flush_cache_all = r4k_flush_cache_all; + __flush_cache_all = r4k___flush_cache_all; + flush_cache_mm = r4k_flush_cache_mm; + flush_cache_page = r4k_flush_cache_page; + flush_icache_page = r4k_flush_icache_page; + flush_cache_range = r4k_flush_cache_range; + + flush_cache_sigtramp = r4k_flush_cache_sigtramp; + flush_icache_all = r4k_flush_icache_all; + flush_data_cache_page = r4k_flush_data_cache_page; + flush_icache_range = r4k_flush_icache_range; + +#ifdef CONFIG_NONCOHERENT_IO + _dma_cache_wback_inv = r4k_dma_cache_wback_inv; + _dma_cache_wback = r4k_dma_cache_wback_inv; + _dma_cache_inv = r4k_dma_cache_inv; +#endif + + __flush_cache_all(); +} diff -Nru a/arch/mips/mm/c-sb1.c b/arch/mips/mm/c-sb1.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/mm/c-sb1.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,611 @@ +/* + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * Copyright (C) 1997, 2001 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 2000, 2001 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#include +#include +#include +#include +#include +#include +#include + +extern void sb1_clear_page(void * page); +extern void sb1_copy_page(void * to, void * from); + +/* These are probed at ld_mmu time */ +static unsigned long icache_size; +static unsigned long dcache_size; + +static unsigned long icache_line_size; +static unsigned long dcache_line_size; + +static unsigned int icache_index_mask; +static unsigned int dcache_index_mask; + +static unsigned long icache_assoc; +static unsigned long dcache_assoc; + +static unsigned int icache_sets; +static unsigned int dcache_sets; + +static unsigned int icache_range_cutoff; +static unsigned int dcache_range_cutoff; + +void pgd_init(unsigned long page) +{ + unsigned long *p = (unsigned long *) page; + int i; + + for (i = 0; i < USER_PTRS_PER_PGD; i+=8) { + p[i + 0] = (unsigned long) invalid_pte_table; + p[i + 1] = (unsigned long) invalid_pte_table; + p[i + 2] = (unsigned long) invalid_pte_table; + p[i + 3] = (unsigned long) invalid_pte_table; + p[i + 4] = (unsigned long) invalid_pte_table; + p[i + 5] = (unsigned long) invalid_pte_table; + p[i + 6] = (unsigned long) invalid_pte_table; + p[i + 7] = (unsigned long) invalid_pte_table; + } +} + +/* + * The dcache is fully coherent to the system, with one + * big caveat: the instruction stream. In other words, + * if we miss in the icache, and have dirty data in the + * L1 dcache, then we'll go out to memory (or the L2) and + * get the not-as-recent data. + * + * So the only time we have to flush the dcache is when + * we're flushing the icache. Since the L2 is fully + * coherent to everything, including I/O, we never have + * to flush it + */ + +/* + * Writeback and invalidate the entire dcache + */ +static inline void __sb1_writeback_inv_dcache_all(void) +{ + __asm__ __volatile__ ( + ".set push \n" + ".set noreorder \n" + ".set noat \n" + ".set mips4 \n" + " move $1, $0 \n" /* Start at index 0 */ + "1: cache %2, 0($1) \n" /* Invalidate this index */ + " cache %2, (1<<13)($1)\n" /* Invalidate this index */ + " cache %2, (2<<13)($1)\n" /* Invalidate this index */ + " cache %2, (3<<13)($1)\n" /* Invalidate this index */ + " addiu %1, %1, -1 \n" /* Decrement loop count */ + " bnez %1, 1b \n" /* loop test */ + " addu $1, $1, %0 \n" /* Next address */ + ".set pop \n" + : + : "r" (dcache_line_size), "r" (dcache_sets), + "i" (Index_Writeback_Inv_D)); +} + +/* + * Writeback and invalidate a range of the dcache. The addresses are + * virtual, and since we're using index ops and bit 12 is part of both + * the virtual frame and physical index, we have to clear both sets + * (bit 12 set and cleared). + */ +static inline void __sb1_writeback_inv_dcache_range(unsigned long start, + unsigned long end) +{ + __asm__ __volatile__ ( + " .set push \n" + " .set noreorder \n" + " .set noat \n" + " .set mips4 \n" + " and $1, %0, %3 \n" /* mask non-index bits */ + "1: cache %4, (0<<13)($1) \n" /* Index-WB-inval this address */ + " cache %4, (1<<13)($1) \n" /* Index-WB-inval this address */ + " cache %4, (2<<13)($1) \n" /* Index-WB-inval this address */ + " cache %4, (3<<13)($1) \n" /* Index-WB-inval this address */ + " xori $1, $1, 1<<12 \n" /* flip bit 12 (va/pa alias) */ + " cache %4, (0<<13)($1) \n" /* Index-WB-inval this address */ + " cache %4, (1<<13)($1) \n" /* Index-WB-inval this address */ + " cache %4, (2<<13)($1) \n" /* Index-WB-inval this address */ + " cache %4, (3<<13)($1) \n" /* Index-WB-inval this address */ + " addu %0, %0, %2 \n" /* next line */ + " bne %0, %1, 1b \n" /* loop test */ + " and $1, %0, %3 \n" /* mask non-index bits */ + " sync \n" + " .set pop \n" + : + : "r" (start & ~(dcache_line_size - 1)), + "r" ((end + dcache_line_size - 1) & ~(dcache_line_size - 1)), + "r" (dcache_line_size), + "r" (dcache_index_mask), + "i" (Index_Writeback_Inv_D)); +} + +/* + * Writeback and invalidate a range of the dcache. With physical + * addresseses, we don't have to worry about possible bit 12 aliasing. + * XXXKW is it worth turning on KX and using hit ops with xkphys? + */ +static inline void __sb1_writeback_inv_dcache_phys_range(unsigned long start, + unsigned long end) +{ + __asm__ __volatile__ ( + " .set push \n" + " .set noreorder \n" + " .set noat \n" + " .set mips4 \n" + " and $1, %0, %3 \n" /* mask non-index bits */ + "1: cache %4, (0<<13)($1) \n" /* Index-WB-inval this address */ + " cache %4, (1<<13)($1) \n" /* Index-WB-inval this address */ + " cache %4, (2<<13)($1) \n" /* Index-WB-inval this address */ + " cache %4, (3<<13)($1) \n" /* Index-WB-inval this address */ + " addu %0, %0, %2 \n" /* next line */ + " bne %0, %1, 1b \n" /* loop test */ + " and $1, %0, %3 \n" /* mask non-index bits */ + " sync \n" + " .set pop \n" + : + : "r" (start & ~(dcache_line_size - 1)), + "r" ((end + dcache_line_size - 1) & ~(dcache_line_size - 1)), + "r" (dcache_line_size), + "r" (dcache_index_mask), + "i" (Index_Writeback_Inv_D)); +} + + +/* + * Invalidate the entire icache + */ +static inline void __sb1_flush_icache_all(void) +{ + __asm__ __volatile__ ( + ".set push \n" + ".set noreorder \n" + ".set noat \n" + ".set mips4 \n" + " move $1, $0 \n" /* Start at index 0 */ + "1: cache %2, 0($1) \n" /* Invalidate this index */ + " cache %2, (1<<13)($1)\n" /* Invalidate this index */ + " cache %2, (2<<13)($1)\n" /* Invalidate this index */ + " cache %2, (3<<13)($1)\n" /* Invalidate this index */ + " addiu %1, %1, -1 \n" /* Decrement loop count */ + " bnez %1, 1b \n" /* loop test */ + " addu $1, $1, %0 \n" /* Next address */ + " bnezl $0, 2f \n" /* Force mispredict */ + " nop \n" + "2: sync \n" + ".set pop \n" + : + : "r" (icache_line_size), "r" (icache_sets), + "i" (Index_Invalidate_I)); +} + +/* + * Flush the icache for a given physical page. Need to writeback the + * dcache first, then invalidate the icache. If the page isn't + * executable, nothing is required. + */ +static void local_sb1_flush_cache_page(struct vm_area_struct *vma, + unsigned long addr) +{ + int cpu = smp_processor_id(); + +#ifndef CONFIG_SMP + if (!(vma->vm_flags & VM_EXEC)) + return; +#endif + + __sb1_writeback_inv_dcache_range(addr, addr + PAGE_SIZE); + + /* + * Bumping the ASID is probably cheaper than the flush ... + */ + if (cpu_context(cpu, vma->vm_mm) != 0) + drop_mmu_context(vma->vm_mm, cpu); +} + +#ifdef CONFIG_SMP +struct flush_cache_page_args { + struct vm_area_struct *vma; + unsigned long addr; +}; + +static void sb1_flush_cache_page_ipi(void *info) +{ + struct flush_cache_page_args *args = info; + + local_sb1_flush_cache_page(args->vma, args->addr); +} + +/* Dirty dcache could be on another CPU, so do the IPIs */ +static void sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long addr) +{ + struct flush_cache_page_args args; + + if (!(vma->vm_flags & VM_EXEC)) + return; + + args.vma = vma; + args.addr = addr; + on_each_cpu(sb1_flush_cache_page_ipi, (void *) &args, 1, 1); +} +#else +void sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long addr); +asm("sb1_flush_cache_page = local_sb1_flush_cache_page"); +#endif + +/* + * Invalidate a range of the icache. The addresses are virtual, and + * the cache is virtually indexed and tagged. However, we don't + * necessarily have the right ASID context, so use index ops instead + * of hit ops. + */ +static inline void __sb1_flush_icache_range(unsigned long start, + unsigned long end) +{ + __asm__ __volatile__ ( + ".set push \n" + ".set noreorder \n" + ".set noat \n" + ".set mips4 \n" + " and $1, %0, %3 \n" /* mask non-index bits */ + "1: cache %4, (0<<13)($1) \n" /* Index-inval this address */ + " cache %4, (1<<13)($1) \n" /* Index-inval this address */ + " cache %4, (2<<13)($1) \n" /* Index-inval this address */ + " cache %4, (3<<13)($1) \n" /* Index-inval this address */ + " addu %0, %0, %2 \n" /* next line */ + " bne %0, %1, 1b \n" /* loop test */ + " and $1, %0, %3 \n" /* mask non-index bits */ + " bnezl $0, 2f \n" /* Force mispredict */ + " nop \n" + "2: sync \n" + ".set pop \n" + : + : "r" (start & ~(icache_line_size - 1)), + "r" ((end + icache_line_size - 1) & ~(icache_line_size - 1)), + "r" (icache_line_size), + "r" (icache_index_mask), + "i" (Index_Invalidate_I)); +} + + +/* + * Invalidate all caches on this CPU + */ +static void local_sb1___flush_cache_all(void) +{ + __sb1_writeback_inv_dcache_all(); + __sb1_flush_icache_all(); +} + +#ifdef CONFIG_SMP +extern void sb1___flush_cache_all_ipi(void *ignored); +asm("sb1___flush_cache_all_ipi = local_sb1___flush_cache_all"); + +static void sb1___flush_cache_all(void) +{ + on_each_cpu(sb1___flush_cache_all_ipi, 0, 1, 1); +} +#else +extern void sb1___flush_cache_all(void); +asm("sb1___flush_cache_all = local_sb1___flush_cache_all"); +#endif + +/* + * When flushing a range in the icache, we have to first writeback + * the dcache for the same range, so new ifetches will see any + * data that was dirty in the dcache. + * + * The start/end arguments are Kseg addresses (possibly mapped Kseg). + */ + +static void local_sb1_flush_icache_range(unsigned long start, + unsigned long end) +{ + /* Just wb-inv the whole dcache if the range is big enough */ + if ((end - start) > dcache_range_cutoff) + __sb1_writeback_inv_dcache_all(); + else + __sb1_writeback_inv_dcache_range(start, end); + + /* Just flush the whole icache if the range is big enough */ + if ((end - start) > icache_range_cutoff) + __sb1_flush_icache_all(); + else + __sb1_flush_icache_range(start, end); +} + +#ifdef CONFIG_SMP +struct flush_icache_range_args { + unsigned long start; + unsigned long end; +}; + +static void sb1_flush_icache_range_ipi(void *info) +{ + struct flush_icache_range_args *args = info; + + local_sb1_flush_icache_range(args->start, args->end); +} + +void sb1_flush_icache_range(unsigned long start, unsigned long end) +{ + struct flush_icache_range_args args; + + args.start = start; + args.end = end; + on_each_cpu(sb1_flush_icache_range_ipi, &args, 1, 1); +} +#else +void sb1_flush_icache_range(unsigned long start, unsigned long end); +asm("sb1_flush_icache_range = local_sb1_flush_icache_range"); +#endif + +/* + * Flush the icache for a given physical page. Need to writeback the + * dcache first, then invalidate the icache. If the page isn't + * executable, nothing is required. + */ +static void local_sb1_flush_icache_page(struct vm_area_struct *vma, + struct page *page) +{ + unsigned long start; + int cpu = smp_processor_id(); + +#ifndef CONFIG_SMP + if (!(vma->vm_flags & VM_EXEC)) + return; +#endif + + /* Need to writeback any dirty data for that page, we have the PA */ + start = (unsigned long)(page-mem_map) << PAGE_SHIFT; + __sb1_writeback_inv_dcache_phys_range(start, start + PAGE_SIZE); + /* + * If there's a context, bump the ASID (cheaper than a flush, + * since we don't know VAs!) + */ + if (cpu_context(cpu, vma->vm_mm) != 0) { + drop_mmu_context(vma->vm_mm, cpu); + } +} + +#ifdef CONFIG_SMP +struct flush_icache_page_args { + struct vm_area_struct *vma; + struct page *page; +}; + +static void sb1_flush_icache_page_ipi(void *info) +{ + struct flush_icache_page_args *args = info; + local_sb1_flush_icache_page(args->vma, args->page); +} + +/* Dirty dcache could be on another CPU, so do the IPIs */ +static void sb1_flush_icache_page(struct vm_area_struct *vma, + struct page *page) +{ + struct flush_icache_page_args args; + + if (!(vma->vm_flags & VM_EXEC)) + return; + args.vma = vma; + args.page = page; + on_each_cpu(sb1_flush_icache_page_ipi, (void *) &args, 1, 1); +} +#else +void sb1_flush_icache_page(struct vm_area_struct *vma, struct page *page); +asm("sb1_flush_icache_page = local_sb1_flush_icache_page"); +#endif + +/* + * A signal trampoline must fit into a single cacheline. + */ +static void local_sb1_flush_cache_sigtramp(unsigned long addr) +{ + __asm__ __volatile__ ( + " .set push \n" + " .set noreorder \n" + " .set noat \n" + " .set mips4 \n" + " cache %2, (0<<13)(%0) \n" /* Index-inval this address */ + " cache %2, (1<<13)(%0) \n" /* Index-inval this address */ + " cache %2, (2<<13)(%0) \n" /* Index-inval this address */ + " cache %2, (3<<13)(%0) \n" /* Index-inval this address */ + " xori $1, %0, 1<<12 \n" /* Flip index bit 12 */ + " cache %2, (0<<13)($1) \n" /* Index-inval this address */ + " cache %2, (1<<13)($1) \n" /* Index-inval this address */ + " cache %2, (2<<13)($1) \n" /* Index-inval this address */ + " cache %2, (3<<13)($1) \n" /* Index-inval this address */ + " cache %3, (0<<13)(%1) \n" /* Index-inval this address */ + " cache %3, (1<<13)(%1) \n" /* Index-inval this address */ + " cache %3, (2<<13)(%1) \n" /* Index-inval this address */ + " cache %3, (3<<13)(%1) \n" /* Index-inval this address */ + " bnezl $0, 1f \n" /* Force mispredict */ + " nop \n" + "1: \n" + " .set pop \n" + : + : "r" (addr & dcache_index_mask), "r" (addr & icache_index_mask), + "i" (Index_Writeback_Inv_D), "i" (Index_Invalidate_I)); +} + +#ifdef CONFIG_SMP +static void sb1_flush_cache_sigtramp_ipi(void *info) +{ + unsigned long iaddr = (unsigned long) info; + local_sb1_flush_cache_sigtramp(iaddr); +} + +static void sb1_flush_cache_sigtramp(unsigned long addr) +{ + on_each_cpu(sb1_flush_cache_sigtramp_ipi, (void *) addr, 1, 1); +} +#else +void sb1_flush_cache_sigtramp(unsigned long addr); +asm("sb1_flush_cache_sigtramp = local_sb1_flush_cache_sigtramp"); +#endif + + +/* + * Anything that just flushes dcache state can be ignored, as we're always + * coherent in dcache space. This is just a dummy function that all the + * nop'ed routines point to + */ +static void sb1_nop(void) +{ +} + +/* + * Cache set values (from the mips64 spec) + * 0 - 64 + * 1 - 128 + * 2 - 256 + * 3 - 512 + * 4 - 1024 + * 5 - 2048 + * 6 - 4096 + * 7 - Reserved + */ + +static unsigned int decode_cache_sets(unsigned int config_field) +{ + if (config_field == 7) { + /* JDCXXX - Find a graceful way to abort. */ + return 0; + } + return (1<<(config_field + 6)); +} + +/* + * Cache line size values (from the mips64 spec) + * 0 - No cache present. + * 1 - 4 bytes + * 2 - 8 bytes + * 3 - 16 bytes + * 4 - 32 bytes + * 5 - 64 bytes + * 6 - 128 bytes + * 7 - Reserved + */ + +static unsigned int decode_cache_line_size(unsigned int config_field) +{ + if (config_field == 0) { + return 0; + } else if (config_field == 7) { + /* JDCXXX - Find a graceful way to abort. */ + return 0; + } + return (1<<(config_field + 1)); +} + +/* + * Relevant bits of the config1 register format (from the MIPS32/MIPS64 specs) + * + * 24:22 Icache sets per way + * 21:19 Icache line size + * 18:16 Icache Associativity + * 15:13 Dcache sets per way + * 12:10 Dcache line size + * 9:7 Dcache Associativity + */ + +static __init void probe_cache_sizes(void) +{ + u32 config1; + + config1 = read_c0_config1(); + icache_line_size = decode_cache_line_size((config1 >> 19) & 0x7); + dcache_line_size = decode_cache_line_size((config1 >> 10) & 0x7); + icache_sets = decode_cache_sets((config1 >> 22) & 0x7); + dcache_sets = decode_cache_sets((config1 >> 13) & 0x7); + icache_assoc = ((config1 >> 16) & 0x7) + 1; + dcache_assoc = ((config1 >> 7) & 0x7) + 1; + icache_size = icache_line_size * icache_sets * icache_assoc; + dcache_size = dcache_line_size * dcache_sets * dcache_assoc; + /* Need to remove non-index bits for index ops */ + icache_index_mask = (icache_sets - 1) * icache_line_size; + dcache_index_mask = (dcache_sets - 1) * dcache_line_size; + /* + * These are for choosing range (index ops) versus all. + * icache flushes all ways for each set, so drop icache_assoc. + * dcache flushes all ways and each setting of bit 12 for each + * index, so drop dcache_assoc and halve the dcache_sets. + */ + icache_range_cutoff = icache_sets * icache_line_size; + dcache_range_cutoff = (dcache_sets / 2) * icache_line_size; +} + +/* + * This is called from loadmmu.c. We have to set up all the + * memory management function pointers, as well as initialize + * the caches and tlbs + */ +void ld_mmu_sb1(void) +{ + extern char except_vec2_sb1; + unsigned long temp; + + /* Special cache error handler for SB1 */ + memcpy((void *)(KSEG0 + 0x100), &except_vec2_sb1, 0x80); + memcpy((void *)(KSEG1 + 0x100), &except_vec2_sb1, 0x80); + + probe_cache_sizes(); + + _clear_page = sb1_clear_page; + _copy_page = sb1_copy_page; + + /* + * None of these are needed for the SB1 - the Dcache is + * physically indexed and tagged, so no virtual aliasing can + * occur + */ + flush_cache_range = (void *) sb1_nop; + flush_cache_page = sb1_flush_cache_page; + flush_cache_mm = (void (*)(struct mm_struct *))sb1_nop; + flush_cache_all = sb1_nop; + + /* These routines are for Icache coherence with the Dcache */ + flush_icache_range = sb1_flush_icache_range; + flush_icache_page = sb1_flush_icache_page; + flush_icache_all = __sb1_flush_icache_all; /* local only */ + + flush_cache_sigtramp = sb1_flush_cache_sigtramp; + flush_data_cache_page = (void *) sb1_nop; + + /* Full flush */ + __flush_cache_all = sb1___flush_cache_all; + + change_c0_config(CONF_CM_CMASK, CONF_CM_DEFAULT); + /* + * This is the only way to force the update of K0 to complete + * before subsequent instruction fetch. + */ + __asm__ __volatile__ ( + " .set push \n" + " .set mips4 \n" + " la %0, 1f \n" + " mtc0 %0, $14 \n" + " eret \n" + "1: .set pop \n" + : "=r" (temp)); + flush_cache_all(); +} diff -Nru a/arch/mips/mm/c-tx39.c b/arch/mips/mm/c-tx39.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/mm/c-tx39.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,495 @@ +/* + * r2300.c: R2000 and R3000 specific mmu/cache code. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * with a lot of changes to make this thing work for R3000s + * Tx39XX R4k style caches added. HK + * Copyright (C) 1998, 1999, 2000 Harald Koerfgen + * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov + */ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* For R3000 cores with R4000 style caches */ +static unsigned long icache_size, dcache_size; /* Size in bytes */ +static unsigned long icache_way_size, dcache_way_size; /* Size divided by ways */ +#define scache_size 0 +#define scache_way_size 0 + +#include + +extern void r3k_clear_page(void * page); +extern void r3k_copy_page(void * to, void * from); + +extern int r3k_have_wired_reg; /* in r3k-tlb.c */ + +/* This sequence is required to ensure icache is disabled immediately */ +#define TX39_STOP_STREAMING() \ +__asm__ __volatile__( \ + ".set push\n\t" \ + ".set noreorder\n\t" \ + "b 1f\n\t" \ + "nop\n\t" \ + "1:\n\t" \ + ".set pop" \ + ) + +/* TX39H-style cache flush routines. */ +static void tx39h_flush_icache_all(void) +{ + unsigned long start = KSEG0; + unsigned long end = (start + icache_size); + unsigned long flags, config; + + /* disable icache (set ICE#) */ + local_irq_save(flags); + config = read_c0_conf(); + write_c0_conf(config & ~TX39_CONF_ICE); + TX39_STOP_STREAMING(); + + /* invalidate icache */ + while (start < end) { + cache16_unroll32(start, Index_Invalidate_I); + start += 0x200; + } + + write_c0_conf(config); + local_irq_restore(flags); +} + +static void tx39h_dma_cache_wback_inv(unsigned long addr, unsigned long size) +{ + unsigned long end, a; + unsigned long dc_lsize = current_cpu_data.dcache.linesz; + + iob(); + a = addr & ~(dc_lsize - 1); + end = (addr + size - 1) & ~(dc_lsize - 1); + while (1) { + invalidate_dcache_line(a); /* Hit_Invalidate_D */ + if (a == end) break; + a += dc_lsize; + } +} + + +/* TX39H2,TX39H3 */ +static inline void tx39_blast_dcache_page(unsigned long addr) +{ + if (current_cpu_data.cputype != CPU_TX3912) + blast_dcache16_page(addr); +} + +static inline void tx39_blast_dcache_page_indexed(unsigned long addr) +{ + blast_dcache16_page_indexed(addr); +} + +static inline void tx39_blast_dcache(void) +{ + blast_dcache16(); +} + +static inline void tx39_blast_icache_page(unsigned long addr) +{ + unsigned long flags, config; + /* disable icache (set ICE#) */ + local_irq_save(flags); + config = read_c0_conf(); + write_c0_conf(config & ~TX39_CONF_ICE); + TX39_STOP_STREAMING(); + blast_icache16_page(addr); + write_c0_conf(config); + local_irq_restore(flags); +} + +static inline void tx39_blast_icache_page_indexed(unsigned long addr) +{ + unsigned long flags, config; + /* disable icache (set ICE#) */ + local_irq_save(flags); + config = read_c0_conf(); + write_c0_conf(config & ~TX39_CONF_ICE); + TX39_STOP_STREAMING(); + blast_icache16_page_indexed(addr); + write_c0_conf(config); + local_irq_restore(flags); +} + +static inline void tx39_blast_icache(void) +{ + unsigned long flags, config; + /* disable icache (set ICE#) */ + local_irq_save(flags); + config = read_c0_conf(); + write_c0_conf(config & ~TX39_CONF_ICE); + TX39_STOP_STREAMING(); + blast_icache16(); + write_c0_conf(config); + local_irq_restore(flags); +} + +static inline void tx39_flush_cache_all(void) +{ + if (!cpu_has_dc_aliases) + return; + + tx39_blast_dcache(); + tx39_blast_icache(); +} + +static inline void tx39___flush_cache_all(void) +{ + tx39_blast_dcache(); + tx39_blast_icache(); +} + +static void tx39_flush_cache_mm(struct mm_struct *mm) +{ + if (!cpu_has_dc_aliases) + return; + + if (cpu_context(smp_processor_id(), mm) != 0) { + tx39_flush_cache_all(); + } +} + +static void tx39_flush_cache_range(struct vm_area_struct *vma, + unsigned long start, unsigned long end) +{ + struct mm_struct *mm = vma->vm_mm; + + if (!cpu_has_dc_aliases) + return; + + if (cpu_context(smp_processor_id(), mm) != 0) { + tx39_blast_dcache(); + tx39_blast_icache(); + } +} + +static void tx39_flush_cache_page(struct vm_area_struct *vma, + unsigned long page) +{ + int exec = vma->vm_flags & VM_EXEC; + struct mm_struct *mm = vma->vm_mm; + pgd_t *pgdp; + pmd_t *pmdp; + pte_t *ptep; + + /* + * If ownes no valid ASID yet, cannot possibly have gotten + * this page into the cache. + */ + if (cpu_context(smp_processor_id(), mm) == 0) + return; + + page &= PAGE_MASK; + pgdp = pgd_offset(mm, page); + pmdp = pmd_offset(pgdp, page); + ptep = pte_offset(pmdp, page); + + /* + * If the page isn't marked valid, the page cannot possibly be + * in the cache. + */ + if (!(pte_val(*ptep) & _PAGE_PRESENT)) + return; + + /* + * Doing flushes for another ASID than the current one is + * too difficult since stupid R4k caches do a TLB translation + * for every cache flush operation. So we do indexed flushes + * in that case, which doesn't overly flush the cache too much. + */ + if ((mm == current->active_mm) && (pte_val(*ptep) & _PAGE_VALID)) { + if (cpu_has_dc_aliases || exec) + tx39_blast_dcache_page(page); + if (exec) + tx39_blast_icache_page(page); + + return; + } + + /* + * Do indexed flush, too much work to get the (possible) TLB refills + * to work correctly. + */ + page = (KSEG0 + (page & (dcache_size - 1))); + if (cpu_has_dc_aliases || exec) + tx39_blast_dcache_page_indexed(page); + if (exec) + tx39_blast_icache_page_indexed(page); +} + +static void tx39_flush_data_cache_page(unsigned long addr) +{ + tx39_blast_dcache_page(addr); +} + +static void tx39_flush_icache_range(unsigned long start, unsigned long end) +{ + unsigned long dc_lsize = current_cpu_data.dcache.linesz; + unsigned long addr, aend; + + if (end - start > dcache_size) + tx39_blast_dcache(); + else { + addr = start & ~(dc_lsize - 1); + aend = (end - 1) & ~(dc_lsize - 1); + + while (1) { + /* Hit_Writeback_Inv_D */ + protected_writeback_dcache_line(addr); + if (addr == aend) + break; + addr += dc_lsize; + } + } + + if (end - start > icache_size) + tx39_blast_icache(); + else { + unsigned long flags, config; + addr = start & ~(dc_lsize - 1); + aend = (end - 1) & ~(dc_lsize - 1); + /* disable icache (set ICE#) */ + local_irq_save(flags); + config = read_c0_conf(); + write_c0_conf(config & ~TX39_CONF_ICE); + TX39_STOP_STREAMING(); + while (1) { + /* Hit_Invalidate_I */ + protected_flush_icache_line(addr); + if (addr == aend) + break; + addr += dc_lsize; + } + write_c0_conf(config); + local_irq_restore(flags); + } +} + +/* + * Ok, this seriously sucks. We use them to flush a user page but don't + * know the virtual address, so we have to blast away the whole icache + * which is significantly more expensive than the real thing. Otoh we at + * least know the kernel address of the page so we can flush it + * selectivly. + */ +static void tx39_flush_icache_page(struct vm_area_struct *vma, struct page *page) +{ + unsigned long addr; + /* + * If there's no context yet, or the page isn't executable, no icache + * flush is needed. + */ + if (!(vma->vm_flags & VM_EXEC)) + return; + + addr = (unsigned long) page_address(page); + tx39_blast_dcache_page(addr); + + /* + * We're not sure of the virtual address(es) involved here, so + * we have to flush the entire I-cache. + */ + tx39_blast_icache(); +} + +static void tx39_dma_cache_wback_inv(unsigned long addr, unsigned long size) +{ + unsigned long end, a; + + if (((size | addr) & (PAGE_SIZE - 1)) == 0) { + end = addr + size; + do { + tx39_blast_dcache_page(addr); + addr += PAGE_SIZE; + } while(addr != end); + } else if (size > dcache_size) { + tx39_blast_dcache(); + } else { + unsigned long dc_lsize = current_cpu_data.dcache.linesz; + a = addr & ~(dc_lsize - 1); + end = (addr + size - 1) & ~(dc_lsize - 1); + while (1) { + flush_dcache_line(a); /* Hit_Writeback_Inv_D */ + if (a == end) break; + a += dc_lsize; + } + } +} + +static void tx39_dma_cache_inv(unsigned long addr, unsigned long size) +{ + unsigned long end, a; + + if (((size | addr) & (PAGE_SIZE - 1)) == 0) { + end = addr + size; + do { + tx39_blast_dcache_page(addr); + addr += PAGE_SIZE; + } while(addr != end); + } else if (size > dcache_size) { + tx39_blast_dcache(); + } else { + unsigned long dc_lsize = current_cpu_data.dcache.linesz; + a = addr & ~(dc_lsize - 1); + end = (addr + size - 1) & ~(dc_lsize - 1); + while (1) { + invalidate_dcache_line(a); /* Hit_Invalidate_D */ + if (a == end) break; + a += dc_lsize; + } + } +} + +static void tx39_flush_cache_sigtramp(unsigned long addr) +{ + unsigned long ic_lsize = current_cpu_data.icache.linesz; + unsigned long dc_lsize = current_cpu_data.dcache.linesz; + unsigned long config; + unsigned long flags; + + protected_writeback_dcache_line(addr & ~(dc_lsize - 1)); + + /* disable icache (set ICE#) */ + local_irq_save(flags); + config = read_c0_conf(); + write_c0_conf(config & ~TX39_CONF_ICE); + TX39_STOP_STREAMING(); + protected_flush_icache_line(addr & ~(ic_lsize - 1)); + write_c0_conf(config); + local_irq_restore(flags); +} + +static __init void tx39_probe_cache(void) +{ + unsigned long config; + + config = read_c0_conf(); + + icache_size = 1 << (10 + ((config & TX39_CONF_ICS_MASK) >> + TX39_CONF_ICS_SHIFT)); + dcache_size = 1 << (10 + ((config & TX39_CONF_DCS_MASK) >> + TX39_CONF_DCS_SHIFT)); + + current_cpu_data.icache.linesz = 16; + switch (current_cpu_data.cputype) { + case CPU_TX3912: + current_cpu_data.icache.ways = 1; + current_cpu_data.dcache.ways = 1; + current_cpu_data.dcache.linesz = 4; + break; + + case CPU_TX3927: + current_cpu_data.icache.ways = 2; + current_cpu_data.dcache.ways = 2; + current_cpu_data.dcache.linesz = 16; + break; + + case CPU_TX3922: + default: + current_cpu_data.icache.ways = 1; + current_cpu_data.dcache.ways = 1; + current_cpu_data.dcache.linesz = 16; + break; + } +} + +void __init ld_mmu_tx39(void) +{ + unsigned long config; + + _clear_page = r3k_clear_page; + _copy_page = r3k_copy_page; + + config = read_c0_conf(); + config &= ~TX39_CONF_WBON; + write_c0_conf(config); + + tx39_probe_cache(); + + switch (current_cpu_data.cputype) { + case CPU_TX3912: + /* TX39/H core (writethru direct-map cache) */ + flush_cache_all = tx39h_flush_icache_all; + __flush_cache_all = tx39h_flush_icache_all; + flush_cache_mm = (void *) tx39h_flush_icache_all; + flush_cache_range = (void *) tx39h_flush_icache_all; + flush_cache_page = (void *) tx39h_flush_icache_all; + flush_icache_page = (void *) tx39h_flush_icache_all; + flush_icache_range = (void *) tx39h_flush_icache_all; + + flush_cache_sigtramp = (void *) tx39h_flush_icache_all; + flush_data_cache_page = (void *) tx39h_flush_icache_all; + + _dma_cache_wback_inv = tx39h_dma_cache_wback_inv; + + shm_align_mask = PAGE_SIZE - 1; + + break; + + case CPU_TX3922: + case CPU_TX3927: + default: + /* TX39/H2,H3 core (writeback 2way-set-associative cache) */ + r3k_have_wired_reg = 1; + write_c0_wired(0); /* set 8 on reset... */ + /* board-dependent init code may set WBON */ + + flush_cache_all = tx39_flush_cache_all; + __flush_cache_all = tx39___flush_cache_all; + flush_cache_mm = tx39_flush_cache_mm; + flush_cache_range = tx39_flush_cache_range; + flush_cache_page = tx39_flush_cache_page; + flush_icache_page = tx39_flush_icache_page; + flush_icache_range = tx39_flush_icache_range; + + flush_cache_sigtramp = tx39_flush_cache_sigtramp; + flush_data_cache_page = tx39_flush_data_cache_page; + + _dma_cache_wback_inv = tx39_dma_cache_wback_inv; + _dma_cache_wback = tx39_dma_cache_wback_inv; + _dma_cache_inv = tx39_dma_cache_inv; + + shm_align_mask = max_t(unsigned long, + (dcache_size / current_cpu_data.dcache.ways) - 1, + PAGE_SIZE - 1); + + break; + } + + icache_way_size = icache_size / current_cpu_data.icache.ways; + dcache_way_size = dcache_size / current_cpu_data.dcache.ways; + + current_cpu_data.icache.sets = + icache_way_size / current_cpu_data.icache.linesz; + current_cpu_data.dcache.sets = + dcache_way_size / current_cpu_data.dcache.linesz; + + if (dcache_way_size > PAGE_SIZE) + current_cpu_data.dcache.flags |= MIPS_CACHE_ALIASES; + + current_cpu_data.icache.waybit = 0; + current_cpu_data.dcache.waybit = 0; + + printk("Primary instruction cache %ldkb, linesize %d bytes\n", + icache_size >> 10, current_cpu_data.icache.linesz); + printk("Primary data cache %ldkb, linesize %d bytes\n", + dcache_size >> 10, current_cpu_data.dcache.linesz); +} diff -Nru a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/mm/cache.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,60 @@ +/* + * 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 - 2003 by Ralf Baechle + */ +#include +#include +#include + +#include + +asmlinkage int sys_cacheflush(void *addr, int bytes, int cache) +{ + /* This should flush more selectivly ... */ + __flush_cache_all(); + + return 0; +} + +void flush_dcache_page(struct page *page) +{ + unsigned long addr; + + if (page->mapping && + list_empty(&page->mapping->i_mmap) && + list_empty(&page->mapping->i_mmap_shared)) { + SetPageDcacheDirty(page); + + return; + } + + /* + * We could delay the flush for the !page->mapping case too. But that + * case is for exec env/arg pages and those are %99 certainly going to + * get faulted into the tlb (and thus flushed) anyways. + */ + addr = (unsigned long) page_address(page); + flush_data_cache_page(addr); +} + +void __update_cache(struct vm_area_struct *vma, unsigned long address, + pte_t pte) +{ + struct page *page; + unsigned long pfn, addr; + + pfn = pte_pfn(pte); + if (pfn_valid(pfn) && (page = pfn_to_page(pfn), page->mapping) && + Page_dcache_dirty(page)) { + if (pages_do_alias((unsigned long)page_address(page), + address & PAGE_MASK)) { + addr = (unsigned long) page_address(page); + flush_data_cache_page(addr); + } + + ClearPageDcacheDirty(page); + } +} diff -Nru a/arch/mips/mm/cerr-sb1.c b/arch/mips/mm/cerr-sb1.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/mm/cerr-sb1.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,542 @@ +/* + * Copyright (C) 2001 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +#ifndef CONFIG_SIBYTE_BUS_WATCHER +#include +#include +#include +#include +#endif + +/* SB1 definitions */ + +/* XXX should come from config1 XXX */ +#define SB1_CACHE_INDEX_MASK 0x1fe0 + +#define CP0_ERRCTL_RECOVERABLE (1 << 31) +#define CP0_ERRCTL_DCACHE (1 << 30) +#define CP0_ERRCTL_ICACHE (1 << 29) +#define CP0_ERRCTL_MULTIBUS (1 << 23) +#define CP0_ERRCTL_MC_TLB (1 << 15) +#define CP0_ERRCTL_MC_TIMEOUT (1 << 14) + +#define CP0_CERRI_TAG_PARITY (1 << 29) +#define CP0_CERRI_DATA_PARITY (1 << 28) +#define CP0_CERRI_EXTERNAL (1 << 26) + +#define CP0_CERRI_IDX_VALID(c) (!((c) & CP0_CERRI_EXTERNAL)) +#define CP0_CERRI_DATA (CP0_CERRI_DATA_PARITY) + +#define CP0_CERRD_MULTIPLE (1 << 31) +#define CP0_CERRD_TAG_STATE (1 << 30) +#define CP0_CERRD_TAG_ADDRESS (1 << 29) +#define CP0_CERRD_DATA_SBE (1 << 28) +#define CP0_CERRD_DATA_DBE (1 << 27) +#define CP0_CERRD_EXTERNAL (1 << 26) +#define CP0_CERRD_LOAD (1 << 25) +#define CP0_CERRD_STORE (1 << 24) +#define CP0_CERRD_FILLWB (1 << 23) +#define CP0_CERRD_COHERENCY (1 << 22) +#define CP0_CERRD_DUPTAG (1 << 21) + +#define CP0_CERRD_DPA_VALID(c) (!((c) & CP0_CERRD_EXTERNAL)) +#define CP0_CERRD_IDX_VALID(c) \ + (((c) & (CP0_CERRD_LOAD | CP0_CERRD_STORE)) ? (!((c) & CP0_CERRD_EXTERNAL)) : 0) +#define CP0_CERRD_CAUSES \ + (CP0_CERRD_LOAD | CP0_CERRD_STORE | CP0_CERRD_FILLWB | CP0_CERRD_COHERENCY | CP0_CERRD_DUPTAG) +#define CP0_CERRD_TYPES \ + (CP0_CERRD_TAG_STATE | CP0_CERRD_TAG_ADDRESS | CP0_CERRD_DATA_SBE | CP0_CERRD_DATA_DBE | CP0_CERRD_EXTERNAL) +#define CP0_CERRD_DATA (CP0_CERRD_DATA_SBE | CP0_CERRD_DATA_DBE) + +static uint32_t extract_ic(unsigned short addr, int data); +static uint32_t extract_dc(unsigned short addr, int data); + +static inline void breakout_errctl(unsigned int val) +{ + if (val & CP0_ERRCTL_RECOVERABLE) + prom_printf(" recoverable"); + if (val & CP0_ERRCTL_DCACHE) + prom_printf(" dcache"); + if (val & CP0_ERRCTL_ICACHE) + prom_printf(" icache"); + if (val & CP0_ERRCTL_MULTIBUS) + prom_printf(" multiple-buserr"); + prom_printf("\n"); +} + +static inline void breakout_cerri(unsigned int val) +{ + if (val & CP0_CERRI_TAG_PARITY) + prom_printf(" tag-parity"); + if (val & CP0_CERRI_DATA_PARITY) + prom_printf(" data-parity"); + if (val & CP0_CERRI_EXTERNAL) + prom_printf(" external"); + prom_printf("\n"); +} + +static inline void breakout_cerrd(unsigned int val) +{ + switch (val & CP0_CERRD_CAUSES) { + case CP0_CERRD_LOAD: + prom_printf(" load,"); + break; + case CP0_CERRD_STORE: + prom_printf(" store,"); + break; + case CP0_CERRD_FILLWB: + prom_printf(" fill/wb,"); + break; + case CP0_CERRD_COHERENCY: + prom_printf(" coherency,"); + break; + case CP0_CERRD_DUPTAG: + prom_printf(" duptags,"); + break; + default: + prom_printf(" NO CAUSE,"); + break; + } + if (!(val & CP0_CERRD_TYPES)) + prom_printf(" NO TYPE"); + else { + if (val & CP0_CERRD_MULTIPLE) + prom_printf(" multi-err"); + if (val & CP0_CERRD_TAG_STATE) + prom_printf(" tag-state"); + if (val & CP0_CERRD_TAG_ADDRESS) + prom_printf(" tag-address"); + if (val & CP0_CERRD_DATA_SBE) + prom_printf(" data-SBE"); + if (val & CP0_CERRD_DATA_DBE) + prom_printf(" data-DBE"); + if (val & CP0_CERRD_EXTERNAL) + prom_printf(" external"); + } + prom_printf("\n"); +} + +#ifndef CONFIG_SIBYTE_BUS_WATCHER + +static void check_bus_watcher(void) +{ + uint32_t status, l2_err, memio_err; + + /* Destructive read, clears register and interrupt */ + status = csr_in32(IO_SPACE_BASE | A_SCD_BUS_ERR_STATUS); + /* Bit 31 is always on, but there's no #define for that */ + if (status & ~(1UL << 31)) { + l2_err = csr_in32(IO_SPACE_BASE | A_BUS_L2_ERRORS); + memio_err = csr_in32(IO_SPACE_BASE | A_BUS_MEM_IO_ERRORS); + prom_printf("Bus watcher error counters: %08x %08x\n", l2_err, memio_err); + prom_printf("\nLast recorded signature:\n"); + prom_printf("Request %02x from %d, answered by %d with Dcode %d\n", + (unsigned int)(G_SCD_BERR_TID(status) & 0x3f), + (int)(G_SCD_BERR_TID(status) >> 6), + (int)G_SCD_BERR_RID(status), + (int)G_SCD_BERR_DCODE(status)); + } else { + prom_printf("Bus watcher indicates no error\n"); + } +} +#else +extern void check_bus_watcher(void); +#endif + +asmlinkage void sb1_cache_error(void) +{ + uint64_t cerr_dpa; + uint32_t errctl, cerr_i, cerr_d, dpalo, dpahi, eepc, res; + + prom_printf("Cache error exception on CPU %x:\n", + (read_c0_prid() >> 25) & 0x7); + + __asm__ __volatile__ ( + " .set push\n\t" + " .set mips64\n\t" + " .set noat\n\t" + " mfc0 %0, $26\n\t" + " mfc0 %1, $27\n\t" + " mfc0 %2, $27, 1\n\t" + " dmfc0 $1, $27, 3\n\t" + " dsrl32 %3, $1, 0 \n\t" + " sll %4, $1, 0 \n\t" + " mfc0 %5, $30\n\t" + " .set pop" + : "=r" (errctl), "=r" (cerr_i), "=r" (cerr_d), + "=r" (dpahi), "=r" (dpalo), "=r" (eepc)); + + cerr_dpa = (((uint64_t)dpahi) << 32) | dpalo; + prom_printf(" cp0_errorepc == %08x\n", eepc); + prom_printf(" cp0_errctl == %08x", errctl); + breakout_errctl(errctl); + if (errctl & CP0_ERRCTL_ICACHE) { + prom_printf(" cp0_cerr_i == %08x", cerr_i); + breakout_cerri(cerr_i); + if (CP0_CERRI_IDX_VALID(cerr_i)) { + if ((eepc & SB1_CACHE_INDEX_MASK) != (cerr_i & SB1_CACHE_INDEX_MASK)) + prom_printf(" cerr_i idx doesn't match eepc\n"); + else { + res = extract_ic(cerr_i & SB1_CACHE_INDEX_MASK, + (cerr_i & CP0_CERRI_DATA) != 0); + if (!(res & cerr_i)) + prom_printf("...didn't see indicated icache problem\n"); + } + } + } + if (errctl & CP0_ERRCTL_DCACHE) { + prom_printf(" cp0_cerr_d == %08x", cerr_d); + breakout_cerrd(cerr_d); + if (CP0_CERRD_DPA_VALID(cerr_d)) { + prom_printf(" cp0_cerr_dpa == %010llx\n", cerr_dpa); + if (!CP0_CERRD_IDX_VALID(cerr_d)) { + res = extract_dc(cerr_dpa & SB1_CACHE_INDEX_MASK, + (cerr_d & CP0_CERRD_DATA) != 0); + if (!(res & cerr_d)) + prom_printf("...didn't see indicated dcache problem\n"); + } else { + if ((cerr_dpa & SB1_CACHE_INDEX_MASK) != (cerr_d & SB1_CACHE_INDEX_MASK)) + prom_printf(" cerr_d idx doesn't match cerr_dpa\n"); + else { + res = extract_dc(cerr_d & SB1_CACHE_INDEX_MASK, + (cerr_d & CP0_CERRD_DATA) != 0); + if (!(res & cerr_d)) + prom_printf("...didn't see indicated problem\n"); + } + } + } + } + + check_bus_watcher(); + + while (1); + /* + * This tends to make things get really ugly; let's just stall instead. + * panic("Can't handle the cache error!"); + */ +} + + +/* Parity lookup table. */ +static const uint8_t parity[256] = { + 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1, + 1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0, + 1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0, + 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1, + 1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0, + 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1, + 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1, + 1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0 +}; + +/* Masks to select bits for Hamming parity, mask_72_64[i] for bit[i] */ +static const uint64_t mask_72_64[8] = { + 0x0738C808099264FFL, + 0x38C808099264FF07L, + 0xC808099264FF0738L, + 0x08099264FF0738C8L, + 0x099264FF0738C808L, + 0x9264FF0738C80809L, + 0x64FF0738C8080992L, + 0xFF0738C808099264L +}; + +/* Calculate the parity on a range of bits */ +static char range_parity(uint64_t dword, int max, int min) +{ + char parity = 0; + int i; + dword >>= min; + for (i=max-min; i>=0; i--) { + if (dword & 0x1) + parity = !parity; + dword >>= 1; + } + return parity; +} + +/* Calculate the 4-bit even byte-parity for an instruction */ +static unsigned char inst_parity(uint32_t word) +{ + int i, j; + char parity = 0; + for (j=0; j<4; j++) { + char byte_parity = 0; + for (i=0; i<8; i++) { + if (word & 0x80000000) + byte_parity = !byte_parity; + word <<= 1; + } + parity <<= 1; + parity |= byte_parity; + } + return parity; +} + +static uint32_t extract_ic(unsigned short addr, int data) +{ + unsigned short way; + int valid; + uint64_t taglo, va, tlo_tmp; + uint32_t taghi, taglolo, taglohi; + uint8_t lru; + int res = 0; + + prom_printf("Icache index 0x%04x ", addr); + for (way = 0; way < 4; way++) { + /* Index-load-tag-I */ + __asm__ __volatile__ ( + " .set push \n\t" + " .set noreorder \n\t" + " .set mips64 \n\t" + " .set noat \n\t" + " cache 4, 0(%3) \n\t" + " mfc0 %0, $29 \n\t" + " dmfc0 $1, $28 \n\t" + " dsrl32 %1, $1, 0 \n\t" + " sll %2, $1, 0 \n\t" + " .set pop" + : "=r" (taghi), "=r" (taglohi), "=r" (taglolo) + : "r" ((way << 13) | addr)); + + taglo = ((unsigned long long)taglohi << 32) | taglolo; + if (way == 0) { + lru = (taghi >> 14) & 0xff; + prom_printf("[Bank %d Set 0x%02x] LRU > %d %d %d %d > MRU\n", + ((addr >> 5) & 0x3), /* bank */ + ((addr >> 7) & 0x3f), /* index */ + (lru & 0x3), + ((lru >> 2) & 0x3), + ((lru >> 4) & 0x3), + ((lru >> 6) & 0x3)); + } + va = (taglo & 0xC0000FFFFFFFE000) | addr; + if ((taglo & (1 << 31)) && (((taglo >> 62) & 0x3) == 3)) + va |= 0x3FFFF00000000000; + valid = ((taghi >> 29) & 1); + if (valid) { + tlo_tmp = taglo & 0xfff3ff; + if (((taglo >> 10) & 1) ^ range_parity(tlo_tmp, 23, 0)) { + prom_printf(" ** bad parity in VTag0/G/ASID\n"); + res |= CP0_CERRI_TAG_PARITY; + } + if (((taglo >> 11) & 1) ^ range_parity(taglo, 63, 24)) { + prom_printf(" ** bad parity in R/VTag1\n"); + res |= CP0_CERRI_TAG_PARITY; + } + } + if (valid ^ ((taghi >> 27) & 1)) { + prom_printf(" ** bad parity for valid bit\n"); + res |= CP0_CERRI_TAG_PARITY; + } + prom_printf(" %d [VA %016llx] [Vld? %d] raw tags: %08X-%016llX\n", + way, va, valid, taghi, taglo); + + if (data) { + uint32_t datahi, insta, instb; + uint8_t predecode; + int offset; + + /* (hit all banks and ways) */ + for (offset = 0; offset < 4; offset++) { + /* Index-load-data-I */ + __asm__ __volatile__ ( + " .set push\n\t" + " .set noreorder\n\t" + " .set mips64\n\t" + " .set noat\n\t" + " cache 6, 0(%3) \n\t" + " mfc0 %0, $29, 1\n\t" + " dmfc0 $1, $28, 1\n\t" + " dsrl32 %1, $1, 0 \n\t" + " sll %2, $1, 0 \n\t" + " .set pop \n" + : "=r" (datahi), "=r" (insta), "=r" (instb) + : "r" ((way << 13) | addr | (offset << 3))); + predecode = (datahi >> 8) & 0xff; + if (((datahi >> 16) & 1) != (uint32_t)range_parity(predecode, 7, 0)) { + prom_printf(" ** bad parity in predecode\n"); + res |= CP0_CERRI_DATA_PARITY; + } + /* XXXKW should/could check predecode bits themselves */ + if (((datahi >> 4) & 0xf) ^ inst_parity(insta)) { + prom_printf(" ** bad parity in instruction a\n"); + res |= CP0_CERRI_DATA_PARITY; + } + if ((datahi & 0xf) ^ inst_parity(instb)) { + prom_printf(" ** bad parity in instruction b\n"); + res |= CP0_CERRI_DATA_PARITY; + } + prom_printf(" %05X-%08X%08X", datahi, insta, instb); + } + prom_printf("\n"); + } + } + return res; +} + +/* Compute the ECC for a data doubleword */ +static uint8_t dc_ecc(uint64_t dword) +{ + uint64_t t; + uint32_t w; + uint8_t p; + int i; + + p = 0; + for (i = 7; i >= 0; i--) + { + p <<= 1; + t = dword & mask_72_64[i]; + w = (uint32_t)(t >> 32); + p ^= (parity[w>>24] ^ parity[(w>>16) & 0xFF] + ^ parity[(w>>8) & 0xFF] ^ parity[w & 0xFF]); + w = (uint32_t)(t & 0xFFFFFFFF); + p ^= (parity[w>>24] ^ parity[(w>>16) & 0xFF] + ^ parity[(w>>8) & 0xFF] ^ parity[w & 0xFF]); + } + return p; +} + +struct dc_state { + unsigned char val; + char *name; +}; + +static struct dc_state dc_states[] = { + { 0x00, "INVALID" }, + { 0x0f, "COH-SHD" }, + { 0x13, "NCO-E-C" }, + { 0x19, "NCO-E-D" }, + { 0x16, "COH-E-C" }, + { 0x1c, "COH-E-D" }, + { 0xff, "*ERROR*" } +}; + +#define DC_TAG_VALID(state) \ + (((state) == 0xf) || ((state) == 0x13) || ((state) == 0x19) || ((state == 0x16)) || ((state) == 0x1c)) + +static char *dc_state_str(unsigned char state) +{ + struct dc_state *dsc = dc_states; + while (dsc->val != 0xff) { + if (dsc->val == state) + break; + dsc++; + } + return dsc->name; +} + +static uint32_t extract_dc(unsigned short addr, int data) +{ + int valid, way; + unsigned char state; + uint64_t taglo, pa; + uint32_t taghi, taglolo, taglohi; + uint8_t ecc, lru; + int res = 0; + + prom_printf("Dcache index 0x%04x ", addr); + for (way = 0; way < 4; way++) { + __asm__ __volatile__ ( + " .set push\n\t" + " .set noreorder\n\t" + " .set mips64\n\t" + " .set noat\n\t" + " cache 5, 0(%3)\n\t" /* Index-load-tag-D */ + " mfc0 %0, $29, 2\n\t" + " dmfc0 $1, $28, 2\n\t" + " dsrl32 %1, $1, 0\n\t" + " sll %2, $1, 0\n\t" + " .set pop" + : "=r" (taghi), "=r" (taglohi), "=r" (taglolo) + : "r" ((way << 13) | addr)); + + taglo = ((unsigned long long)taglohi << 32) | taglolo; + pa = (taglo & 0xFFFFFFE000) | addr; + if (way == 0) { + lru = (taghi >> 14) & 0xff; + prom_printf("[Bank %d Set 0x%02x] LRU > %d %d %d %d > MRU\n", + ((addr >> 11) & 0x2) | ((addr >> 5) & 1), /* bank */ + ((addr >> 6) & 0x3f), /* index */ + (lru & 0x3), + ((lru >> 2) & 0x3), + ((lru >> 4) & 0x3), + ((lru >> 6) & 0x3)); + } + state = (taghi >> 25) & 0x1f; + valid = DC_TAG_VALID(state); + prom_printf(" %d [PA %010llx] [state %s (%02x)] raw tags: %08X-%016llX\n", + way, pa, dc_state_str(state), state, taghi, taglo); + if (valid) { + if (((taglo >> 11) & 1) ^ range_parity(taglo, 39, 26)) { + prom_printf(" ** bad parity in PTag1\n"); + res |= CP0_CERRD_TAG_ADDRESS; + } + if (((taglo >> 10) & 1) ^ range_parity(taglo, 25, 13)) { + prom_printf(" ** bad parity in PTag0\n"); + res |= CP0_CERRD_TAG_ADDRESS; + } + } else { + res |= CP0_CERRD_TAG_STATE; + } + + if (data) { + uint64_t datalo; + uint32_t datalohi, datalolo, datahi; + int offset; + + for (offset = 0; offset < 4; offset++) { + /* Index-load-data-D */ + __asm__ __volatile__ ( + " .set push\n\t" + " .set noreorder\n\t" + " .set mips64\n\t" + " .set noat\n\t" + " cache 7, 0(%3)\n\t" /* Index-load-data-D */ + " mfc0 %0, $29, 3\n\t" + " dmfc0 $1, $28, 3\n\t" + " dsrl32 %1, $1, 0 \n\t" + " sll %2, $1, 0 \n\t" + " .set pop" + : "=r" (datahi), "=r" (datalohi), "=r" (datalolo) + : "r" ((way << 13) | addr | (offset << 3))); + datalo = ((unsigned long long)datalohi << 32) | datalolo; + ecc = dc_ecc(datalo); + if (ecc != datahi) { + int bits = 0; + prom_printf(" ** bad ECC (%02x %02x) ->", + datahi, ecc); + ecc ^= datahi; + while (ecc) { + if (ecc & 1) bits++; + ecc >>= 1; + } + res |= (bits == 1) ? CP0_CERRD_DATA_SBE : CP0_CERRD_DATA_DBE; + } + prom_printf(" %02X-%016llX", datahi, datalo); + } + prom_printf("\n"); + } + } + return res; +} diff -Nru a/arch/mips/mm/cex-sb1.S b/arch/mips/mm/cex-sb1.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/mm/cex-sb1.S Tue Jul 1 18:44:39 2003 @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2001,2002,2003 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#include +#include + +#include +#include +#include +#include +#include + + .text + .set noat + .set mips4 + + __INIT + + /* Cache Error handler for SB1 */ + LEAF(except_vec2_sb1) + mfc0 k1, $26 + # check if error was recoverable + bltz k1, leave_cerr +#ifdef CONFIG_SB1_PASS_1_WORKAROUNDS + # look for signature of spurious CErr + lui k0, 0x4000 + bne k0, k1, 1f + .word 0x401Bd801 # mfc0 k1, $27, 1 + lui k0, 0xffe0 + and k1, k0, k1 + lui k0, 0x0200 + beq k0, k1, leave_cerr +1: +#endif + j handle_vec2_sb1 + +leave_cerr: + # clear/unlock the registers + mtc0 zero, $26 + mtc0 zero, $27 + .word 0x4080d801 # mtc0 zero, $27, 1 + .word 0x4080d803 # mtc0 zero, $27, 3 + eret + END(except_vec2_sb1) + + __FINIT + + LEAF(handle_vec2_sb1) + mfc0 k0,CP0_CONFIG + li k1,~CONF_CM_CMASK + and k0,k0,k1 + ori k0,k0,CONF_CM_UNCACHED + mtc0 k0,CP0_CONFIG + + SSNOP + SSNOP + SSNOP + SSNOP + bnezl $0, 1f +1: + mfc0 k0, CP0_STATUS + sll k0, k0, 3 # check CU0 (kernel?) + bltz k0, 2f + GET_SAVED_SP + move sp, k0 # want Kseg SP (so uncached) +2: + j sb1_cache_error + + END(handle_vec2_sb1) diff -Nru a/arch/mips/mm/extable.c b/arch/mips/mm/extable.c --- a/arch/mips/mm/extable.c Tue Jul 1 18:44:35 2003 +++ b/arch/mips/mm/extable.c Tue Jul 1 18:44:35 2003 @@ -1,62 +1,30 @@ /* - * linux/arch/mips/mm/extable.c + * linux/arch/i386/mm/extable.c */ + #include #include #include #include -extern const struct exception_table_entry __start___ex_table[]; -extern const struct exception_table_entry __stop___ex_table[]; - -static inline unsigned long -search_one_table(const struct exception_table_entry *first, - const struct exception_table_entry *last, - unsigned long value) +/* Simple binary search */ +const struct exception_table_entry * +search_extable(const struct exception_table_entry *first, + const struct exception_table_entry *last, + unsigned long value) { - while (first <= last) { + while (first <= last) { const struct exception_table_entry *mid; long diff; mid = (last - first) / 2 + first; diff = mid->insn - value; - if (diff == 0) - return mid->nextinsn; - else if (diff < 0) - first = mid+1; - else - last = mid-1; - } - return 0; -} - -extern spinlock_t modlist_lock; - -unsigned long -search_exception_table(unsigned long addr) -{ - unsigned long ret = 0; - -#ifndef CONFIG_MODULES - /* There is only the kernel to search. */ - ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr); - return ret; -#else - unsigned long flags; - - /* The kernel is the last "module" -- no need to treat it special. */ - struct module *mp; - - spin_lock_irqsave(&modlist_lock, flags); - for (mp = module_list; mp != NULL; mp = mp->next) { - if (mp->ex_table_start == NULL || !(mp->flags&(MOD_RUNNING|MOD_INITIALIZING))) - continue; - ret = search_one_table(mp->ex_table_start, - mp->ex_table_end - 1, addr); - if (ret) - break; - } - spin_unlock_irqrestore(&modlist_lock, flags); - return ret; -#endif + if (diff == 0) + return mid; + else if (diff < 0) + first = mid+1; + else + last = mid-1; + } + return NULL; } diff -Nru a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c --- a/arch/mips/mm/fault.c Tue Jul 1 18:44:33 2003 +++ b/arch/mips/mm/fault.c Tue Jul 1 18:44:33 2003 @@ -5,6 +5,7 @@ * * Copyright (C) 1995 - 2000 by Ralf Baechle */ +#include #include #include #include @@ -18,23 +19,50 @@ #include #include #include +#include /* For unblank_screen() */ +#include +#include #include #include #include #include #include +#include #define development_version (LINUX_VERSION_CODE & 0x100) -unsigned long asid_cache = ASID_FIRST_VERSION; - /* * Macro for exception fixup code to access integer registers. */ #define dpf_reg(r) (regs->regs[r]) /* + * Unlock any spinlocks which will prevent us from getting the out + */ +void bust_spinlocks(int yes) +{ + int loglevel_save = console_loglevel; + + if (yes) { + oops_in_progress = 1; + return; + } +#ifdef CONFIG_VT + unblank_screen(); +#endif + oops_in_progress = 0; + /* + * OK, the message is on the console. Now we call printk() + * without oops_in_progress set so that printk will give klogd + * a poke. Hold onto your hats... + */ + console_loglevel = 15; /* NMI oopser may have shut the console up */ + printk(" "); + console_loglevel = loglevel_save; +} + +/* * This routine handles page faults. It determines the address, * and the problem, and then passes it off to one of the appropriate * routines. @@ -45,9 +73,14 @@ struct vm_area_struct * vma; struct task_struct *tsk = current; struct mm_struct *mm = tsk->mm; - unsigned long fixup; + const struct exception_table_entry *fixup; siginfo_t info; +#if 0 + printk("Cpu%d[%s:%d:%08lx:%ld:%08lx]\n", smp_processor_id(), + current->comm, current->pid, address, write, regs->cp0_epc); +#endif + /* * We fault-in kernel-space virtual memory on-demand. The * 'reference' page table is init_mm.pgd. @@ -57,7 +90,7 @@ * only copy the information from the master page table, * nothing more. */ - if (address >= TASK_SIZE) + if (address >= VMALLOC_START) goto vmalloc_fault; info.si_code = SEGV_MAPERR; @@ -65,12 +98,9 @@ * If we're in an interrupt or have no user * context, we must not take the fault.. */ - if (in_interrupt() || !mm) + if (in_atomic() || !mm) goto no_context; -#if 0 - printk("[%s:%d:%08lx:%ld:%08lx]\n", current->comm, current->pid, - address, write, regs->cp0_epc); -#endif + down_read(&mm->mmap_sem); vma = find_vma(mm, address); if (!vma) @@ -96,22 +126,25 @@ goto bad_area; } +survive: /* * If for any reason at all we couldn't handle the fault, * make sure we exit gracefully rather than endlessly redo * the fault. */ switch (handle_mm_fault(mm, vma, address, write)) { - case 1: + case VM_FAULT_MINOR: tsk->min_flt++; break; - case 2: + case VM_FAULT_MAJOR: tsk->maj_flt++; break; - case 0: + case VM_FAULT_SIGBUS: goto do_sigbus; - default: + case VM_FAULT_OOM: goto out_of_memory; + default: + BUG(); } up_read(&mm->mmap_sem); @@ -124,7 +157,6 @@ bad_area: up_read(&mm->mmap_sem); -bad_area_nosemaphore: /* User mode accesses just cause a SIGSEGV */ if (user_mode(regs)) { tsk->thread.cp0_badvaddr = address; @@ -148,12 +180,11 @@ no_context: /* Are we prepared to handle this kernel fault? */ - fixup = search_exception_table(regs->cp0_epc); + fixup = search_exception_tables(exception_epc(regs)); if (fixup) { - long new_epc; + unsigned long new_epc = fixup->nextinsn; tsk->thread.cp0_baduaddr = address; - new_epc = fixup_exception(dpf_reg, fixup, regs->cp0_epc); if (development_version) printk(KERN_DEBUG "%s: Exception at [<%lx>] (%lx)\n", tsk->comm, regs->cp0_epc, new_epc); @@ -165,11 +196,13 @@ * Oops. The kernel tried to access some bad page. We'll have to * terminate things with extreme prejudice. */ + + bust_spinlocks(1); + printk(KERN_ALERT "Unable to handle kernel paging request at virtual " "address %08lx, epc == %08lx, ra == %08lx\n", address, regs->cp0_epc, regs->regs[31]); die("Oops", regs); - do_exit(SIGKILL); /* * We ran out of memory, or some other thing happened to us that made @@ -177,6 +210,11 @@ */ out_of_memory: up_read(&mm->mmap_sem); + if (tsk->pid == 1) { + yield(); + down_read(&mm->mmap_sem); + goto survive; + } printk("VM: killing process %s\n", tsk->comm); if (user_mode(regs)) do_exit(SIGKILL); @@ -207,26 +245,31 @@ /* * Synchronize this task's top level page-table * with the 'reference' page table. + * + * Do _not_ use "tsk" here. We might be inside + * an interrupt in the middle of a task switch.. */ - int offset = pgd_index(address); + int offset = __pgd_offset(address); pgd_t *pgd, *pgd_k; pmd_t *pmd, *pmd_k; + pte_t *pte_k; - pgd = tsk->active_mm->pgd + offset; + pgd = (pgd_t *) pgd_current[smp_processor_id()] + offset; pgd_k = init_mm.pgd + offset; - if (!pgd_present(*pgd)) { - if (!pgd_present(*pgd_k)) - goto bad_area_nosemaphore; - set_pgd(pgd, *pgd_k); - return; - } + if (!pgd_present(*pgd_k)) + goto no_context; + set_pgd(pgd, *pgd_k); pmd = pmd_offset(pgd, address); pmd_k = pmd_offset(pgd_k, address); - - if (pmd_present(*pmd) || !pmd_present(*pmd_k)) - goto bad_area_nosemaphore; + if (!pmd_present(*pmd_k)) + goto no_context; set_pmd(pmd, *pmd_k); + + pte_k = pte_offset_kernel(pmd_k, address); + if (!pte_present(*pte_k)) + goto no_context; + return; } } diff -Nru a/arch/mips/mm/highmem.c b/arch/mips/mm/highmem.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/mm/highmem.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,101 @@ +#include +#include +#include + +void *kmap(struct page *page) +{ + void *addr; + + if (in_interrupt()) + BUG(); + + if (page < highmem_start_page) + return page_address(page); + addr = kmap_high(page); + flush_tlb_one((unsigned long)addr); + + return addr; +} + +void kunmap(struct page *page) +{ + if (in_interrupt()) + BUG(); + if (page < highmem_start_page) + return; + kunmap_high(page); +} + +/* + * kmap_atomic/kunmap_atomic is significantly faster than kmap/kunmap because + * no global lock is needed and because the kmap code must perform a global TLB + * invalidation when the kmap pool wraps. + * + * However when holding an atomic kmap is is not legal to sleep, so atomic + * kmaps are appropriate for short, tight code paths only. + */ + +void *kmap_atomic(struct page *page, enum km_type type) +{ + enum fixed_addresses idx; + unsigned long vaddr; + + inc_preempt_count(); + if (page < highmem_start_page) + return page_address(page); + + idx = type + KM_TYPE_NR*smp_processor_id(); + vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); +#ifdef CONFIG_DEBUG_HIGHMEM + if (!pte_none(*(kmap_pte-idx))) + BUG(); +#endif + set_pte(kmap_pte-idx, mk_pte(page, kmap_prot)); + local_flush_tlb_one((unsigned long)vaddr); + + return (void*) vaddr; +} + +void kunmap_atomic(void *kvaddr, enum km_type type) +{ +#ifdef CONFIG_DEBUG_HIGHMEM + unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; + enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id(); + + if (vaddr < FIXADDR_START) { // FIXME + dec_preempt_count(); + return; + } + + if (vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx)) + BUG(); + + /* + * force other mappings to Oops if they'll try to access + * this pte without first remap it + */ + pte_clear(kmap_pte-idx); + local_flush_tlb_one(vaddr); +#endif + + dec_preempt_count(); +} + +struct page *kmap_atomic_to_page(void *ptr) +{ + unsigned long idx, vaddr = (unsigned long)ptr; + pte_t *pte; + + if (vaddr < FIXADDR_START) + return virt_to_page(ptr); + + idx = virt_to_fix(vaddr); + pte = kmap_pte - (idx - FIX_KMAP_BEGIN); + return pte_page(*pte); +} + +EXPORT_SYMBOL(kmap); +EXPORT_SYMBOL(kunmap); +EXPORT_SYMBOL(kmap_atomic); +EXPORT_SYMBOL(kunmap_atomic); +EXPORT_SYMBOL(kmap_atomic_to_page); diff -Nru a/arch/mips/mm/init.c b/arch/mips/mm/init.c --- a/arch/mips/mm/init.c Tue Jul 1 18:44:37 2003 +++ b/arch/mips/mm/init.c Tue Jul 1 18:44:37 2003 @@ -24,36 +24,23 @@ #include #include #include -#ifdef CONFIG_BLK_DEV_INITRD #include -#endif #include +#include #include #include #include -#include -#include -#include #include -#ifdef CONFIG_SGI_IP22 -#include -#endif #include +#include #include DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); -extern void prom_free_prom_memory(void); - - -asmlinkage int sys_cacheflush(void *addr, int bytes, int cache) -{ - /* This should flush more selectivly ... */ - __flush_cache_all(); - - return 0; -} +unsigned long highstart_pfn, highend_pfn; +static unsigned long totalram_pages; +static unsigned long totalhigh_pages; /* * We have upto 8 empty zeroed pages so we can map one of the right colour @@ -68,9 +55,10 @@ { unsigned long order, size; struct page *page; - if(mips_cpu.options & MIPS_CPU_VCE) + + if (cpu_has_vce) order = 3; - else + else order = 0; empty_zero_page = __get_free_pages(GFP_KERNEL, order); @@ -91,69 +79,109 @@ return 1UL << order; } -int do_check_pgt_cache(int low, int high) +#ifdef CONFIG_HIGHMEM +pte_t *kmap_pte; +pgprot_t kmap_prot; + +#define kmap_get_fixmap_pte(vaddr) \ + pte_offset_kernel(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)) + +static void __init kmap_init(void) { - int freed = 0; + unsigned long kmap_vstart; + + /* cache the first kmap pte */ + kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN); + kmap_pte = kmap_get_fixmap_pte(kmap_vstart); - if(pgtable_cache_size > high) { - do { - if(pgd_quicklist) - free_pgd_slow(get_pgd_fast()), freed++; - if(pmd_quicklist) - free_pmd_slow(get_pmd_fast()), freed++; - if(pte_quicklist) - free_pte_slow(get_pte_fast()), freed++; - } while(pgtable_cache_size > low); - } - return freed; -} - -void show_mem(void) -{ - int i, free = 0, total = 0, reserved = 0; - int shared = 0, cached = 0; - - printk("Mem-info:\n"); - show_free_areas(); - printk("Free swap: %6dkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); - i = max_mapnr; - while (i-- > 0) { - total++; - if (PageReserved(mem_map+i)) - reserved++; - else if (PageSwapCache(mem_map+i)) - cached++; - else if (!page_count(mem_map + i)) - free++; - else - shared += page_count(mem_map + i) - 1; - } - printk("%d pages of RAM\n", total); - printk("%d reserved pages\n", reserved); - printk("%d pages shared\n", shared); - printk("%d pages swap cached\n",cached); - printk("%ld pages in page table cache\n",pgtable_cache_size); - printk("%d free pages\n", free); + kmap_prot = PAGE_KERNEL; } -/* References to section boundaries */ +#endif /* CONFIG_HIGHMEM */ -extern char _ftext, _etext, _fdata, _edata; -extern char __init_begin, __init_end; +#ifdef CONFIG_HIGHMEM +static void __init fixrange_init (unsigned long start, unsigned long end, + pgd_t *pgd_base) +{ + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + int i, j; + unsigned long vaddr; + + vaddr = start; + i = __pgd_offset(vaddr); + j = __pmd_offset(vaddr); + pgd = pgd_base + i; + + for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) { + pmd = (pmd_t *)pgd; + for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) { + if (pmd_none(*pmd)) { + pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); + set_pmd(pmd, __pmd(pte)); + if (pte != pte_offset_kernel(pmd, 0)) + BUG(); + } + vaddr += PMD_SIZE; + } + j = 0; + } +} +#endif -void __init paging_init(void) +void __init pagetable_init(void) { - unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0}; - unsigned long max_dma, low; +#ifdef CONFIG_HIGHMEM + unsigned long vaddr; + pgd_t *pgd, *pgd_base; + pmd_t *pmd; + pte_t *pte; +#endif /* Initialize the entire pgd. */ pgd_init((unsigned long)swapper_pg_dir); - pgd_init((unsigned long)swapper_pg_dir + PAGE_SIZE / 2); + pgd_init((unsigned long)swapper_pg_dir + + sizeof(pgd_t ) * USER_PTRS_PER_PGD); + +#ifdef CONFIG_HIGHMEM + pgd_base = swapper_pg_dir; + + /* + * Fixed mappings: + */ + vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK; + fixrange_init(vaddr, 0, pgd_base); + + /* + * Permanent kmaps: + */ + vaddr = PKMAP_BASE; + fixrange_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base); + + pgd = swapper_pg_dir + __pgd_offset(vaddr); + pmd = pmd_offset(pgd, vaddr); + pte = pte_offset_kernel(pmd, vaddr); + pkmap_page_table = pte; +#endif +} + +void __init paging_init(void) +{ + unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0}; + unsigned long max_dma, high, low; + + pagetable_init(); + +#ifdef CONFIG_HIGHMEM + kmap_init(); +#endif max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT; low = max_low_pfn; + high = highend_pfn; -#if defined(CONFIG_PCI) || defined(CONFIG_ISA) +#ifdef CONFIG_ISA if (low < max_dma) zones_size[ZONE_DMA] = low; else { @@ -163,6 +191,9 @@ #else zones_size[ZONE_DMA] = low; #endif +#ifdef CONFIG_HIGHMEM + zones_size[ZONE_HIGHMEM] = high - low; +#endif free_area_init(zones_size); } @@ -197,8 +228,17 @@ unsigned long codesize, reservedpages, datasize, initsize; unsigned long tmp, ram; +#ifdef CONFIG_HIGHMEM + highstart_pfn = (KSEG1 - KSEG0) >> PAGE_SHIFT; + highmem_start_page = mem_map + highstart_pfn; +#ifdef CONFIG_DISCONTIGMEM +#error "CONFIG_HIGHMEM and CONFIG_DISCONTIGMEM dont work together yet" +#endif + max_mapnr = num_physpages = highend_pfn; +#else max_mapnr = num_physpages = max_low_pfn; - high_memory = (void *) __va(max_mapnr << PAGE_SHIFT); +#endif + high_memory = (void *) __va(max_low_pfn * PAGE_SIZE); totalram_pages += free_all_bootmem(); totalram_pages -= setup_zero_pages(); /* Setup zeroed pages. */ @@ -211,25 +251,43 @@ reservedpages++; } - codesize = (unsigned long) &_etext - (unsigned long) &_ftext; - datasize = (unsigned long) &_edata - (unsigned long) &_fdata; +#ifdef CONFIG_HIGHMEM + for (tmp = highstart_pfn; tmp < highend_pfn; tmp++) { + struct page *page = mem_map + tmp; + + if (!page_is_ram(tmp)) { + SetPageReserved(page); + continue; + } + ClearPageReserved(page); + set_bit(PG_highmem, &page->flags); + atomic_set(&page->count, 1); + __free_page(page); + totalhigh_pages++; + } + totalram_pages += totalhigh_pages; +#endif + + codesize = (unsigned long) &_etext - (unsigned long) &_text; + datasize = (unsigned long) &_edata - (unsigned long) &_etext; initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin; - printk("Memory: %luk/%luk available (%ldk kernel code, %ldk reserved, " - "%ldk data, %ldk init)\n", + printk(KERN_INFO "Memory: %luk/%luk available (%ldk kernel code, " + "%ldk reserved, %ldk data, %ldk init, %ldk highmem)\n", (unsigned long) nr_free_pages() << (PAGE_SHIFT-10), ram << (PAGE_SHIFT-10), codesize >> 10, reservedpages << (PAGE_SHIFT-10), datasize >> 10, - initsize >> 10); + initsize >> 10, + (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10))); } #ifdef CONFIG_BLK_DEV_INITRD void free_initrd_mem(unsigned long start, unsigned long end) { if (start < end) - printk("Freeing initrd memory: %ldk freed\n", + printk(KERN_INFO "Freeing initrd memory: %ldk freed\n", (end - start) >> 10); for (; start < end; start += PAGE_SIZE) { @@ -242,14 +300,14 @@ #endif extern char __init_begin, __init_end; -extern void prom_free_prom_memory(void); +extern void prom_free_prom_memory(void) __init; void free_initmem(void) { unsigned long addr; prom_free_prom_memory (); - + addr = (unsigned long) &__init_begin; while (addr < (unsigned long) &__init_end) { ClearPageReserved(virt_to_page(addr)); @@ -258,6 +316,6 @@ totalram_pages++; addr += PAGE_SIZE; } - printk("Freeing unused kernel memory: %dk freed\n", + printk(KERN_INFO "Freeing unused kernel memory: %dk freed\n", (&__init_end - &__init_begin) >> 10); } diff -Nru a/arch/mips/mm/ioremap.c b/arch/mips/mm/ioremap.c --- a/arch/mips/mm/ioremap.c Tue Jul 1 18:44:35 2003 +++ b/arch/mips/mm/ioremap.c Tue Jul 1 18:44:35 2003 @@ -4,20 +4,22 @@ * for more details. * * (C) Copyright 1995 1996 Linus Torvalds - * (C) Copyright 2001 Ralf Baechle + * (C) Copyright 2001, 2002 Ralf Baechle */ #include #include #include #include +#include #include #include +#include -static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size, - unsigned long phys_addr, unsigned long flags) +static inline void remap_area_pte(pte_t * pte, unsigned long address, + phys_t size, phys_t phys_addr, unsigned long flags) { - unsigned long end; + phys_t end; unsigned long pfn; pgprot_t pgprot = __pgprot(_PAGE_GLOBAL | _PAGE_PRESENT | __READABLE | __WRITEABLE | flags); @@ -41,10 +43,10 @@ } while (address && (address < end)); } -static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size, - unsigned long phys_addr, unsigned long flags) +static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, + phys_t size, phys_t phys_addr, unsigned long flags) { - unsigned long end; + phys_t end; address &= ~PGDIR_MASK; end = address + size; @@ -54,7 +56,7 @@ if (address >= end) BUG(); do { - pte_t * pte = pte_alloc(&init_mm, pmd, address); + pte_t * pte = pte_alloc_kernel(&init_mm, pmd, address); if (!pte) return -ENOMEM; remap_area_pte(pte, address, end - address, address + phys_addr, flags); @@ -64,8 +66,8 @@ return 0; } -static int remap_area_pages(unsigned long address, unsigned long phys_addr, - unsigned long size, unsigned long flags) +static int remap_area_pages(unsigned long address, phys_t phys_addr, + phys_t size, unsigned long flags) { int error; pgd_t * dir; @@ -109,13 +111,14 @@ * caller shouldn't need to know that small detail. */ -#define IS_LOW512(addr) (!((unsigned long)(addr) & ~0x1fffffffUL)) +#define IS_LOW512(addr) (!((phys_t)(addr) & ~0x1fffffffUL)) -void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags) +void * __ioremap(phys_t phys_addr, phys_t size, unsigned long flags) { - void * addr; struct vm_struct * area; - unsigned long offset, last_addr; + unsigned long offset; + phys_t last_addr; + void * addr; /* Don't allow wraparound or zero size */ last_addr = phys_addr + size - 1; @@ -123,10 +126,11 @@ return NULL; /* - * Map objects in the low 512mb of address space using KSEG1, otherwise - * map using page tables. + * Map uncached objects in the low 512mb of address space using KSEG1, + * otherwise map using page tables. */ - if (IS_LOW512(phys_addr) && IS_LOW512(phys_addr + size - 1)) + if (IS_LOW512(phys_addr) && IS_LOW512(last_addr) && + flags == _CACHE_UNCACHED) return (void *) KSEG1ADDR(phys_addr); /* @@ -138,7 +142,7 @@ t_addr = __va(phys_addr); t_end = t_addr + (size - 1); - + for(page = virt_to_page(t_addr); page <= virt_to_page(t_end); page++) if(!PageReserved(page)) return NULL; @@ -159,7 +163,7 @@ return NULL; addr = area->addr; if (remap_area_pages(VMALLOC_VMADDR(addr), phys_addr, size, flags)) { - vfree(addr); + vunmap(addr); return NULL; } @@ -170,8 +174,19 @@ void iounmap(void *addr) { - if (!IS_KSEG1(addr)) - return vfree((void *) (PAGE_MASK & (unsigned long) addr)); + struct vm_struct *p; + + if (IS_KSEG1(addr)) + return; + + vfree((void *) (PAGE_MASK & (unsigned long) addr)); + p = remove_vm_area((void *) (PAGE_MASK & (unsigned long) addr)); + if (!p) { + printk(KERN_ERR "iounmap: bad address %p\n", addr); + return; + } + + kfree(p); } EXPORT_SYMBOL(__ioremap); diff -Nru a/arch/mips/mm/loadmmu.c b/arch/mips/mm/loadmmu.c --- a/arch/mips/mm/loadmmu.c Tue Jul 1 18:44:36 2003 +++ b/arch/mips/mm/loadmmu.c Tue Jul 1 18:44:36 2003 @@ -1,7 +1,11 @@ /* - * loadmmu.c: Setup cpu/cache specific function ptrs at boot time. + * 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) 1996 David S. Miller (dm@engr.sgi.com) + * Copyright (C) 1997, 1999, 2000, 2001, 2002, 2003 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 1999 Silicon Graphics, Inc. * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. */ @@ -10,6 +14,7 @@ #include #include #include +#include #include #include @@ -22,80 +27,93 @@ void (*_copy_page)(void * to, void * from); /* Cache operations. */ -void (*_flush_cache_all)(void); -void (*___flush_cache_all)(void); -void (*_flush_cache_mm)(struct mm_struct *mm); -void (*_flush_cache_range)(struct vm_area_struct *vma, unsigned long start, - unsigned long end); -void (*_flush_cache_page)(struct vm_area_struct *vma, unsigned long page); -void (*_flush_cache_sigtramp)(unsigned long addr); -void (*_flush_page_to_ram)(struct page * page); -void (*_flush_icache_range)(unsigned long start, unsigned long end); -void (*_flush_icache_page)(struct vm_area_struct *vma, struct page *page); +void (*flush_cache_all)(void); +void (*__flush_cache_all)(void); +void (*flush_cache_mm)(struct mm_struct *mm); +void (*flush_cache_range)(struct vm_area_struct *vma, unsigned long start, + unsigned long end); +void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page); +void (*flush_icache_range)(unsigned long start, unsigned long end); +void (*flush_icache_page)(struct vm_area_struct *vma, struct page *page); + +/* MIPS specific cache operations */ +void (*flush_cache_sigtramp)(unsigned long addr); +void (*flush_data_cache_page)(unsigned long addr); +void (*flush_icache_all)(void); + +#ifdef CONFIG_NONCOHERENT_IO /* DMA cache operations. */ void (*_dma_cache_wback_inv)(unsigned long start, unsigned long size); void (*_dma_cache_wback)(unsigned long start, unsigned long size); void (*_dma_cache_inv)(unsigned long start, unsigned long size); +EXPORT_SYMBOL(_dma_cache_wback_inv); +EXPORT_SYMBOL(_dma_cache_wback); +EXPORT_SYMBOL(_dma_cache_inv); + +#endif /* CONFIG_NONCOHERENT_IO */ + extern void ld_mmu_r23000(void); extern void ld_mmu_r4xx0(void); -extern void ld_mmu_r5432(void); +extern void ld_mmu_tx39(void); extern void ld_mmu_r6000(void); -extern void ld_mmu_rm7k(void); extern void ld_mmu_tfp(void); extern void ld_mmu_andes(void); extern void ld_mmu_sb1(void); -extern void ld_mmu_mips32(void); +extern void sb1_tlb_init(void); +extern void r3k_tlb_init(void); +extern void r4k_tlb_init(void); +extern void sb1_tlb_init(void); -void __init loadmmu(void) +void __init load_mmu(void) { - - if (mips_cpu.options & MIPS_CPU_4KTLB) { -#if defined(CONFIG_CPU_R4X00) || defined(CONFIG_CPU_VR41XX) || \ - defined(CONFIG_CPU_R4300) || defined(CONFIG_CPU_R5000) || \ - defined(CONFIG_CPU_NEVADA) - printk("Loading R4000 MMU routines.\n"); + if (cpu_has_4ktlb) { +#if defined(CONFIG_CPU_R4X00) || defined(CONFIG_CPU_VR41XX) || \ + defined(CONFIG_CPU_R4300) || defined(CONFIG_CPU_R5000) || \ + defined(CONFIG_CPU_NEVADA) || defined(CONFIG_CPU_R5432) || \ + defined(CONFIG_CPU_R5500) || defined(CONFIG_CPU_MIPS32) || \ + defined(CONFIG_CPU_MIPS64) || defined(CONFIG_CPU_TX49XX) || \ + defined(CONFIG_CPU_RM7000) ld_mmu_r4xx0(); + r4k_tlb_init(); #endif -#if defined(CONFIG_CPU_RM7000) - printk("Loading RM7000 MMU routines.\n"); - ld_mmu_rm7k(); -#endif -#if defined(CONFIG_CPU_R5432) - printk("Loading R5432 MMU routines.\n"); - ld_mmu_r5432(); -#endif - -#if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64) - printk("Loading MIPS32 MMU routines.\n"); - ld_mmu_mips32(); -#endif - } else switch(mips_cpu.cputype) { + } else switch (current_cpu_data.cputype) { #ifdef CONFIG_CPU_R3000 case CPU_R2000: case CPU_R3000: case CPU_R3000A: + case CPU_R3081E: + ld_mmu_r23000(); + r3k_tlb_init(); + break; +#endif +#ifdef CONFIG_CPU_TX39XX case CPU_TX3912: case CPU_TX3922: case CPU_TX3927: - case CPU_R3081E: - printk("Loading R[23]000 MMU routines.\n"); - ld_mmu_r23000(); + ld_mmu_tx39(); + r3k_tlb_init(); break; #endif #ifdef CONFIG_CPU_R10000 case CPU_R10000: - printk("Loading R10000 MMU routines.\n"); - ld_mmu_andes(); + case CPU_R12000: + ld_mmu_r4xx0(); + andes_tlb_init(); break; #endif #ifdef CONFIG_CPU_SB1 case CPU_SB1: - printk("Loading SB1 MMU routines.\n"); ld_mmu_sb1(); + sb1_tlb_init(); break; #endif + + case CPU_R8000: + panic("R8000 is unsupported"); + break; + default: panic("Yeee, unsupported mmu/cache architecture."); } diff -Nru a/arch/mips/mm/mips32.c b/arch/mips/mm/mips32.c --- a/arch/mips/mm/mips32.c Tue Jul 1 18:44:38 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,1065 +0,0 @@ -/* - * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * MIPS32 CPU variant specific MMU/Cache routines. - */ -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -/* CP0 hazard avoidance. */ -#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \ - "nop; nop; nop; nop; nop; nop;\n\t" \ - ".set reorder\n\t") - -/* Primary cache parameters. */ -static int icache_size, dcache_size; /* Size in bytes */ -static int ic_lsize, dc_lsize; /* LineSize in bytes */ - -/* Secondary cache (if present) parameters. */ -static unsigned int scache_size, sc_lsize; /* Again, in bytes */ - -#include -#include - -#undef DEBUG_CACHE - -/* - * Dummy cache handling routines for machines without boardcaches - */ -static void no_sc_noop(void) {} - -static struct bcache_ops no_sc_ops = { - (void *)no_sc_noop, (void *)no_sc_noop, - (void *)no_sc_noop, (void *)no_sc_noop -}; - -struct bcache_ops *bcops = &no_sc_ops; - - -/* - * Zero an entire page. - */ - -static void mips32_clear_page_dc(unsigned long page) -{ - unsigned long i; - - if (mips_cpu.options & MIPS_CPU_CACHE_CDEX) { - for (i=page; ivm_mm; - unsigned long flags; - - if(mm->context == 0) - return; - - start &= PAGE_MASK; -#ifdef DEBUG_CACHE - printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); -#endif - if (vma) { - if(mm->context != current->mm->context) { - mips32_flush_cache_all_sc(); - } else { - pgd_t *pgd; - pmd_t *pmd; - pte_t *pte; - - local_irq_save(flags); - while(start < end) { - pgd = pgd_offset(mm, start); - pmd = pmd_offset(pgd, start); - pte = pte_offset(pmd, start); - - if(pte_val(*pte) & _PAGE_VALID) - blast_scache_page(start); - start += PAGE_SIZE; - } - local_irq_restore(flags); - } - } -} - -static void mips32_flush_cache_range_pc(struct vm_area_struct *vma, - unsigned long start, - unsigned long end) -{ - struct mm_struct *mm = vma->vm_mm; - - if(mm->context != 0) { - unsigned long flags; - -#ifdef DEBUG_CACHE - printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); -#endif - local_irq_save(flags); - blast_dcache(); blast_icache(); - local_irq_restore(flags); - } -} - -/* - * On architectures like the Sparc, we could get rid of lines in - * the cache created only by a certain context, but on the MIPS - * (and actually certain Sparc's) we cannot. - */ -static void mips32_flush_cache_mm_sc(struct mm_struct *mm) -{ - if(mm->context != 0) { -#ifdef DEBUG_CACHE - printk("cmm[%d]", (int)mm->context); -#endif - mips32_flush_cache_all_sc(); - } -} - -static void mips32_flush_cache_mm_pc(struct mm_struct *mm) -{ - if(mm->context != 0) { -#ifdef DEBUG_CACHE - printk("cmm[%d]", (int)mm->context); -#endif - mips32_flush_cache_all_pc(); - } -} - - - - - -static void mips32_flush_cache_page_sc(struct vm_area_struct *vma, - unsigned long page) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long flags; - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - - /* - * If ownes no valid ASID yet, cannot possibly have gotten - * this page into the cache. - */ - if (mm->context == 0) - return; - -#ifdef DEBUG_CACHE - printk("cpage[%d,%08lx]", (int)mm->context, page); -#endif - local_irq_save(flags); - page &= PAGE_MASK; - pgdp = pgd_offset(mm, page); - pmdp = pmd_offset(pgdp, page); - ptep = pte_offset(pmdp, page); - - /* - * If the page isn't marked valid, the page cannot possibly be - * in the cache. - */ - if (!(pte_val(*ptep) & _PAGE_VALID)) - goto out; - - /* - * Doing flushes for another ASID than the current one is - * too difficult since R4k caches do a TLB translation - * for every cache flush operation. So we do indexed flushes - * in that case, which doesn't overly flush the cache too much. - */ - if (mm->context != current->active_mm->context) { - /* - * Do indexed flush, too much work to get the (possible) - * tlb refills to work correctly. - */ - page = (KSEG0 + (page & (scache_size - 1))); - blast_dcache_page_indexed(page); - blast_scache_page_indexed(page); - } else - blast_scache_page(page); -out: - local_irq_restore(flags); -} - -static void mips32_flush_cache_page_pc(struct vm_area_struct *vma, - unsigned long page) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long flags; - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - - /* - * If ownes no valid ASID yet, cannot possibly have gotten - * this page into the cache. - */ - if (mm->context == 0) - return; - -#ifdef DEBUG_CACHE - printk("cpage[%d,%08lx]", (int)mm->context, page); -#endif - local_irq_save(flags); - page &= PAGE_MASK; - pgdp = pgd_offset(mm, page); - pmdp = pmd_offset(pgdp, page); - ptep = pte_offset(pmdp, page); - - /* - * If the page isn't marked valid, the page cannot possibly be - * in the cache. - */ - if (!(pte_val(*ptep) & _PAGE_VALID)) - goto out; - - /* - * Doing flushes for another ASID than the current one is - * too difficult since Mips32 caches do a TLB translation - * for every cache flush operation. So we do indexed flushes - * in that case, which doesn't overly flush the cache too much. - */ - if (mm == current->active_mm) { - blast_dcache_page(page); - } else { - /* Do indexed flush, too much work to get the (possible) - * tlb refills to work correctly. - */ - page = (KSEG0 + (page & (dcache_size - 1))); - blast_dcache_page_indexed(page); - } -out: - local_irq_restore(flags); -} - -/* If the addresses passed to these routines are valid, they are - * either: - * - * 1) In KSEG0, so we can do a direct flush of the page. - * 2) In KSEG2, and since every process can translate those - * addresses all the time in kernel mode we can do a direct - * flush. - * 3) In KSEG1, no flush necessary. - */ -static void mips32_flush_page_to_ram_sc(struct page *page) -{ - blast_scache_page((unsigned long)page_address(page)); -} - -static void mips32_flush_page_to_ram_pc(struct page *page) -{ - blast_dcache_page((unsigned long)page_address(page)); -} - -static void -mips32_flush_icache_page_s(struct vm_area_struct *vma, struct page *page) -{ - /* - * We did an scache flush therefore PI is already clean. - */ -} - -static void -mips32_flush_icache_range(unsigned long start, unsigned long end) -{ - flush_cache_all(); -} - -static void -mips32_flush_icache_page(struct vm_area_struct *vma, struct page *page) -{ - int address; - - if (!(vma->vm_flags & VM_EXEC)) - return; - - address = KSEG0 + ((unsigned long)page_address(page) & PAGE_MASK & (dcache_size - 1)); - blast_icache_page_indexed(address); -} - -/* - * Writeback and invalidate the primary cache dcache before DMA. - */ -static void -mips32_dma_cache_wback_inv_pc(unsigned long addr, unsigned long size) -{ - unsigned long end, a; - unsigned int flags; - - if (size >= dcache_size) { - flush_cache_all(); - } else { - local_irq_save(flags); - a = addr & ~(dc_lsize - 1); - end = (addr + size) & ~(dc_lsize - 1); - while (1) { - flush_dcache_line(a); /* Hit_Writeback_Inv_D */ - if (a == end) break; - a += dc_lsize; - } - local_irq_restore(flags); - } - bc_wback_inv(addr, size); -} - -static void -mips32_dma_cache_wback_inv_sc(unsigned long addr, unsigned long size) -{ - unsigned long end, a; - - if (size >= scache_size) { - flush_cache_all(); - return; - } - - a = addr & ~(sc_lsize - 1); - end = (addr + size) & ~(sc_lsize - 1); - while (1) { - flush_scache_line(a); /* Hit_Writeback_Inv_SD */ - if (a == end) break; - a += sc_lsize; - } -} - -static void -mips32_dma_cache_inv_pc(unsigned long addr, unsigned long size) -{ - unsigned long end, a; - unsigned int flags; - - if (size >= dcache_size) { - flush_cache_all(); - } else { - local_irq_save(flags); - a = addr & ~(dc_lsize - 1); - end = (addr + size) & ~(dc_lsize - 1); - while (1) { - flush_dcache_line(a); /* Hit_Writeback_Inv_D */ - if (a == end) break; - a += dc_lsize; - } - local_irq_restore(flags); - } - - bc_inv(addr, size); -} - -static void -mips32_dma_cache_inv_sc(unsigned long addr, unsigned long size) -{ - unsigned long end, a; - - if (size >= scache_size) { - flush_cache_all(); - return; - } - - a = addr & ~(sc_lsize - 1); - end = (addr + size) & ~(sc_lsize - 1); - while (1) { - flush_scache_line(a); /* Hit_Writeback_Inv_SD */ - if (a == end) break; - a += sc_lsize; - } -} - -static void -mips32_dma_cache_wback(unsigned long addr, unsigned long size) -{ - panic("mips32_dma_cache called - should not happen.\n"); -} - -/* - * While we're protected against bad userland addresses we don't care - * very much about what happens in that case. Usually a segmentation - * fault will dump the process later on anyway ... - */ -static void mips32_flush_cache_sigtramp(unsigned long addr) -{ - protected_writeback_dcache_line(addr & ~(dc_lsize - 1)); - protected_flush_icache_line(addr & ~(ic_lsize - 1)); -} - -#undef DEBUG_TLB -#undef DEBUG_TLBUPDATE - -void flush_tlb_all(void) -{ - unsigned long flags; - unsigned long old_ctx; - int entry; - -#ifdef DEBUG_TLB - printk("[tlball]"); -#endif - - local_irq_save(flags); - /* Save old context and create impossible VPN2 value */ - old_ctx = (get_entryhi() & 0xff); - set_entryhi(KSEG0); - set_entrylo0(0); - set_entrylo1(0); - BARRIER; - - entry = get_wired(); - - /* Blast 'em all away. */ - while(entry < mips_cpu.tlbsize) { - /* Make sure all entries differ. */ - set_entryhi(KSEG0+entry*0x2000); - set_index(entry); - BARRIER; - tlb_write_indexed(); - BARRIER; - entry++; - } - BARRIER; - set_entryhi(old_ctx); - local_irq_restore(flags); -} - -void flush_tlb_mm(struct mm_struct *mm) -{ - if (mm->context != 0) { - unsigned long flags; - -#ifdef DEBUG_TLB - printk("[tlbmm<%d>]", mm->context); -#endif - local_irq_save(flags); - get_new_mmu_context(mm, asid_cache); - if (mm == current->active_mm) - set_entryhi(mm->context & 0xff); - local_irq_restore(flags); - } -} - -void flush_tlb_range(struct mm_struct *mm, unsigned long start, - unsigned long end) -{ - if(mm->context != 0) { - unsigned long flags; - int size; - -#ifdef DEBUG_TLB - printk("[tlbrange<%02x,%08lx,%08lx>]", (mm->context & 0xff), - start, end); -#endif - local_irq_save(flags); - size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; - size = (size + 1) >> 1; - if(size <= mips_cpu.tlbsize/2) { - int oldpid = (get_entryhi() & 0xff); - int newpid = (mm->context & 0xff); - - start &= (PAGE_MASK << 1); - end += ((PAGE_SIZE << 1) - 1); - end &= (PAGE_MASK << 1); - while(start < end) { - int idx; - - set_entryhi(start | newpid); - start += (PAGE_SIZE << 1); - BARRIER; - tlb_probe(); - BARRIER; - idx = get_index(); - set_entrylo0(0); - set_entrylo1(0); - if(idx < 0) - continue; - /* Make sure all entries differ. */ - set_entryhi(KSEG0+idx*0x2000); - BARRIER; - tlb_write_indexed(); - BARRIER; - } - set_entryhi(oldpid); - } else { - get_new_mmu_context(mm, asid_cache); - if (mm == current->active_mm) - set_entryhi(mm->context & 0xff); - } - local_irq_restore(flags); - } -} - -void flush_tlb_page(struct vm_area_struct *vma, unsigned long page) -{ - if (vma->vm_mm->context != 0) { - unsigned long flags; - int oldpid, newpid, idx; - -#ifdef DEBUG_TLB - printk("[tlbpage<%d,%08lx>]", vma->vm_mm->context, page); -#endif - newpid = (vma->vm_mm->context & 0xff); - page &= (PAGE_MASK << 1); - local_irq_save(flags); - oldpid = (get_entryhi() & 0xff); - set_entryhi(page | newpid); - BARRIER; - tlb_probe(); - BARRIER; - idx = get_index(); - set_entrylo0(0); - set_entrylo1(0); - if(idx < 0) - goto finish; - /* Make sure all entries differ. */ - set_entryhi(KSEG0+idx*0x2000); - BARRIER; - tlb_write_indexed(); - - finish: - BARRIER; - set_entryhi(oldpid); - local_irq_restore(flags); - } -} - -void pgd_init(unsigned long page) -{ - unsigned long *p = (unsigned long *) page; - int i; - - for(i = 0; i < USER_PTRS_PER_PGD; i+=8) { - p[i + 0] = (unsigned long) invalid_pte_table; - p[i + 1] = (unsigned long) invalid_pte_table; - p[i + 2] = (unsigned long) invalid_pte_table; - p[i + 3] = (unsigned long) invalid_pte_table; - p[i + 4] = (unsigned long) invalid_pte_table; - p[i + 5] = (unsigned long) invalid_pte_table; - p[i + 6] = (unsigned long) invalid_pte_table; - p[i + 7] = (unsigned long) invalid_pte_table; - } -} - -/* - * Updates the TLB with the new pte(s). - */ -void update_mmu_cache(struct vm_area_struct * vma, - unsigned long address, pte_t pte) -{ - unsigned long flags; - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - int idx, pid; - - /* - * Handle debugger faulting in for debugee. - */ - if (current->active_mm != vma->vm_mm) - return; - - pid = get_entryhi() & 0xff; - -#ifdef DEBUG_TLB - if((pid != (vma->vm_mm->context & 0xff)) || (vma->vm_mm->context == 0)) { - printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%d tlbpid=%d\n", - (int) (vma->vm_mm->context & 0xff), pid); - } -#endif - - local_irq_save(flags); - address &= (PAGE_MASK << 1); - set_entryhi(address | (pid)); - pgdp = pgd_offset(vma->vm_mm, address); - BARRIER; - tlb_probe(); - BARRIER; - pmdp = pmd_offset(pgdp, address); - idx = get_index(); - ptep = pte_offset(pmdp, address); - BARRIER; - set_entrylo0(pte_val(*ptep++) >> 6); - set_entrylo1(pte_val(*ptep) >> 6); - set_entryhi(address | (pid)); - BARRIER; - if(idx < 0) { - tlb_write_random(); - } else { - tlb_write_indexed(); - } - BARRIER; - set_entryhi(pid); - BARRIER; - local_irq_restore(flags); -} - -void show_regs(struct pt_regs * regs) -{ - /* Saved main processor registers. */ - printk("$0 : %08lx %08lx %08lx %08lx\n", - 0UL, regs->regs[1], regs->regs[2], regs->regs[3]); - printk("$4 : %08lx %08lx %08lx %08lx\n", - regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]); - printk("$8 : %08lx %08lx %08lx %08lx\n", - regs->regs[8], regs->regs[9], regs->regs[10], regs->regs[11]); - printk("$12: %08lx %08lx %08lx %08lx\n", - regs->regs[12], regs->regs[13], regs->regs[14], regs->regs[15]); - printk("$16: %08lx %08lx %08lx %08lx\n", - regs->regs[16], regs->regs[17], regs->regs[18], regs->regs[19]); - printk("$20: %08lx %08lx %08lx %08lx\n", - regs->regs[20], regs->regs[21], regs->regs[22], regs->regs[23]); - printk("$24: %08lx %08lx\n", - regs->regs[24], regs->regs[25]); - printk("$28: %08lx %08lx %08lx %08lx\n", - regs->regs[28], regs->regs[29], regs->regs[30], regs->regs[31]); - - /* Saved cp0 registers. */ - printk("epc : %08lx %s\nStatus: %08lx\nCause : %08lx\n", - regs->cp0_epc, print_tainted(), regs->cp0_status, regs->cp0_cause); -} - -void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, - unsigned long entryhi, unsigned long pagemask) -{ - unsigned long flags; - unsigned long wired; - unsigned long old_pagemask; - unsigned long old_ctx; - - local_irq_save(flags); - /* Save old context and create impossible VPN2 value */ - old_ctx = (get_entryhi() & 0xff); - old_pagemask = get_pagemask(); - wired = get_wired(); - set_wired (wired + 1); - set_index (wired); - BARRIER; - set_pagemask (pagemask); - set_entryhi(entryhi); - set_entrylo0(entrylo0); - set_entrylo1(entrylo1); - BARRIER; - tlb_write_indexed(); - BARRIER; - - set_entryhi(old_ctx); - BARRIER; - set_pagemask (old_pagemask); - flush_tlb_all(); - local_irq_restore(flags); -} - -/* Detect and size the various caches. */ -static void __init probe_icache(unsigned long config) -{ - unsigned long config1; - unsigned int lsize; - - if (!(config & (1 << 31))) { - /* - * Not a MIPS32 complainant CPU. - * Config 1 register not supported, we assume R4k style. - */ - icache_size = 1 << (12 + ((config >> 9) & 7)); - ic_lsize = 16 << ((config >> 5) & 1); - mips_cpu.icache.linesz = ic_lsize; - - /* - * We cannot infer associativity - assume direct map - * unless probe template indicates otherwise - */ - if(!mips_cpu.icache.ways) mips_cpu.icache.ways = 1; - mips_cpu.icache.sets = - (icache_size / ic_lsize) / mips_cpu.icache.ways; - } else { - config1 = read_mips32_cp0_config1(); - - if ((lsize = ((config1 >> 19) & 7))) - mips_cpu.icache.linesz = 2 << lsize; - else - mips_cpu.icache.linesz = lsize; - mips_cpu.icache.sets = 64 << ((config1 >> 22) & 7); - mips_cpu.icache.ways = 1 + ((config1 >> 16) & 7); - - ic_lsize = mips_cpu.icache.linesz; - icache_size = mips_cpu.icache.sets * mips_cpu.icache.ways * - ic_lsize; - } - printk("Primary instruction cache %dkb, linesize %d bytes (%d ways)\n", - icache_size >> 10, ic_lsize, mips_cpu.icache.ways); -} - -static void __init probe_dcache(unsigned long config) -{ - unsigned long config1; - unsigned int lsize; - - if (!(config & (1 << 31))) { - /* - * Not a MIPS32 complainant CPU. - * Config 1 register not supported, we assume R4k style. - */ - dcache_size = 1 << (12 + ((config >> 6) & 7)); - dc_lsize = 16 << ((config >> 4) & 1); - mips_cpu.dcache.linesz = dc_lsize; - /* - * We cannot infer associativity - assume direct map - * unless probe template indicates otherwise - */ - if(!mips_cpu.dcache.ways) mips_cpu.dcache.ways = 1; - mips_cpu.dcache.sets = - (dcache_size / dc_lsize) / mips_cpu.dcache.ways; - } else { - config1 = read_mips32_cp0_config1(); - - if ((lsize = ((config1 >> 10) & 7))) - mips_cpu.dcache.linesz = 2 << lsize; - else - mips_cpu.dcache.linesz= lsize; - mips_cpu.dcache.sets = 64 << ((config1 >> 13) & 7); - mips_cpu.dcache.ways = 1 + ((config1 >> 7) & 7); - - dc_lsize = mips_cpu.dcache.linesz; - dcache_size = - mips_cpu.dcache.sets * mips_cpu.dcache.ways - * dc_lsize; - } - printk("Primary data cache %dkb, linesize %d bytes (%d ways)\n", - dcache_size >> 10, dc_lsize, mips_cpu.dcache.ways); -} - - -/* If you even _breathe_ on this function, look at the gcc output - * and make sure it does not pop things on and off the stack for - * the cache sizing loop that executes in KSEG1 space or else - * you will crash and burn badly. You have been warned. - */ -static int __init probe_scache(unsigned long config) -{ - extern unsigned long stext; - unsigned long flags, addr, begin, end, pow2; - int tmp; - - if (mips_cpu.scache.flags == MIPS_CACHE_NOT_PRESENT) - return 0; - - tmp = ((config >> 17) & 1); - if(tmp) - return 0; - tmp = ((config >> 22) & 3); - switch(tmp) { - case 0: - sc_lsize = 16; - break; - case 1: - sc_lsize = 32; - break; - case 2: - sc_lsize = 64; - break; - case 3: - sc_lsize = 128; - break; - } - - begin = (unsigned long) &stext; - begin &= ~((4 * 1024 * 1024) - 1); - end = begin + (4 * 1024 * 1024); - - /* This is such a bitch, you'd think they would make it - * easy to do this. Away you daemons of stupidity! - */ - local_irq_save(flags); - - /* Fill each size-multiple cache line with a valid tag. */ - pow2 = (64 * 1024); - for(addr = begin; addr < end; addr = (begin + pow2)) { - unsigned long *p = (unsigned long *) addr; - __asm__ __volatile__("nop" : : "r" (*p)); /* whee... */ - pow2 <<= 1; - } - - /* Load first line with zero (therefore invalid) tag. */ - set_taglo(0); - set_taghi(0); - __asm__ __volatile__("nop; nop; nop; nop;"); /* avoid the hazard */ - __asm__ __volatile__("\n\t.set noreorder\n\t" - ".set mips3\n\t" - "cache 8, (%0)\n\t" - ".set mips0\n\t" - ".set reorder\n\t" : : "r" (begin)); - __asm__ __volatile__("\n\t.set noreorder\n\t" - ".set mips3\n\t" - "cache 9, (%0)\n\t" - ".set mips0\n\t" - ".set reorder\n\t" : : "r" (begin)); - __asm__ __volatile__("\n\t.set noreorder\n\t" - ".set mips3\n\t" - "cache 11, (%0)\n\t" - ".set mips0\n\t" - ".set reorder\n\t" : : "r" (begin)); - - /* Now search for the wrap around point. */ - pow2 = (128 * 1024); - tmp = 0; - for(addr = (begin + (128 * 1024)); addr < (end); addr = (begin + pow2)) { - __asm__ __volatile__("\n\t.set noreorder\n\t" - ".set mips3\n\t" - "cache 7, (%0)\n\t" - ".set mips0\n\t" - ".set reorder\n\t" : : "r" (addr)); - __asm__ __volatile__("nop; nop; nop; nop;"); /* hazard... */ - if(!get_taglo()) - break; - pow2 <<= 1; - } - local_irq_restore(flags); - addr -= begin; - printk("Secondary cache sized at %dK linesize %d bytes.\n", - (int) (addr >> 10), sc_lsize); - scache_size = addr; - return 1; -} - -static void __init setup_noscache_funcs(void) -{ - _clear_page = (void *)mips32_clear_page_dc; - _copy_page = (void *)mips32_copy_page_dc; - _flush_cache_all = mips32_flush_cache_all_pc; - ___flush_cache_all = mips32_flush_cache_all_pc; - _flush_cache_mm = mips32_flush_cache_mm_pc; - _flush_cache_range = mips32_flush_cache_range_pc; - _flush_cache_page = mips32_flush_cache_page_pc; - _flush_page_to_ram = mips32_flush_page_to_ram_pc; - - _flush_icache_page = mips32_flush_icache_page; - - _dma_cache_wback_inv = mips32_dma_cache_wback_inv_pc; - _dma_cache_wback = mips32_dma_cache_wback; - _dma_cache_inv = mips32_dma_cache_inv_pc; -} - -static void __init setup_scache_funcs(void) -{ - _flush_cache_all = mips32_flush_cache_all_sc; - ___flush_cache_all = mips32_flush_cache_all_sc; - _flush_cache_mm = mips32_flush_cache_mm_sc; - _flush_cache_range = mips32_flush_cache_range_sc; - _flush_cache_page = mips32_flush_cache_page_sc; - _flush_page_to_ram = mips32_flush_page_to_ram_sc; - _clear_page = (void *)mips32_clear_page_sc; - _copy_page = (void *)mips32_copy_page_sc; - - _flush_icache_page = mips32_flush_icache_page_s; - - _dma_cache_wback_inv = mips32_dma_cache_wback_inv_sc; - _dma_cache_wback = mips32_dma_cache_wback; - _dma_cache_inv = mips32_dma_cache_inv_sc; -} - -typedef int (*probe_func_t)(unsigned long); - -static inline void __init setup_scache(unsigned int config) -{ - probe_func_t probe_scache_kseg1; - int sc_present = 0; - - /* Maybe the cpu knows about a l2 cache? */ - probe_scache_kseg1 = (probe_func_t) (KSEG1ADDR(&probe_scache)); - sc_present = probe_scache_kseg1(config); - - if (sc_present) { - mips_cpu.scache.linesz = sc_lsize; - /* - * We cannot infer associativity - assume direct map - * unless probe template indicates otherwise - */ - if(!mips_cpu.scache.ways) mips_cpu.scache.ways = 1; - mips_cpu.scache.sets = - (scache_size / sc_lsize) / mips_cpu.scache.ways; - - setup_scache_funcs(); - return; - } - - setup_noscache_funcs(); -} - -static void __init probe_tlb(unsigned long config) -{ - unsigned long config1; - - if (!(config & (1 << 31))) { - /* - * Not a MIPS32 complainant CPU. - * Config 1 register not supported, we assume R4k style. - */ - mips_cpu.tlbsize = 48; - } else { - config1 = read_mips32_cp0_config1(); - if (!((config >> 7) & 3)) - panic("No MMU present"); - else - mips_cpu.tlbsize = ((config1 >> 25) & 0x3f) + 1; - } - - printk("Number of TLB entries %d.\n", mips_cpu.tlbsize); -} - -void __init ld_mmu_mips32(void) -{ - unsigned long config = read_32bit_cp0_register(CP0_CONFIG); - - printk("CPU revision is: %08x\n", read_32bit_cp0_register(CP0_PRID)); - -#ifdef CONFIG_MIPS_UNCACHED - change_cp0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); -#else - change_cp0_config(CONF_CM_CMASK, CONF_CM_CACHABLE_NONCOHERENT); -#endif - - probe_icache(config); - probe_dcache(config); - setup_scache(config); - probe_tlb(config); - - _flush_cache_sigtramp = mips32_flush_cache_sigtramp; - _flush_icache_range = mips32_flush_icache_range; /* Ouch */ - - __flush_cache_all(); - write_32bit_cp0_register(CP0_WIRED, 0); - - /* - * You should never change this register: - * - The entire mm handling assumes the c0_pagemask register to - * be set for 4kb pages. - */ - write_32bit_cp0_register(CP0_PAGEMASK, PM_4K); - flush_tlb_all(); -} diff -Nru a/arch/mips/mm/pg-r3k.c b/arch/mips/mm/pg-r3k.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/mm/pg-r3k.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2001 Ralf Baechle (ralf@gnu.org) + */ +#include +#include + +/* page functions */ +void r3k_clear_page(void * page) +{ + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "addiu\t$1,%0,%2\n" + "1:\tsw\t$0,(%0)\n\t" + "sw\t$0,4(%0)\n\t" + "sw\t$0,8(%0)\n\t" + "sw\t$0,12(%0)\n\t" + "addiu\t%0,32\n\t" + "sw\t$0,-16(%0)\n\t" + "sw\t$0,-12(%0)\n\t" + "sw\t$0,-8(%0)\n\t" + "bne\t$1,%0,1b\n\t" + "sw\t$0,-4(%0)\n\t" + ".set\tat\n\t" + ".set\treorder" + : "=r" (page) + : "0" (page), "I" (PAGE_SIZE) + : "memory"); +} + +void r3k_copy_page(void * to, void * from) +{ + unsigned long dummy1, dummy2; + unsigned long reg1, reg2, reg3, reg4; + + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "addiu\t$1,%0,%8\n" + "1:\tlw\t%2,(%1)\n\t" + "lw\t%3,4(%1)\n\t" + "lw\t%4,8(%1)\n\t" + "lw\t%5,12(%1)\n\t" + "sw\t%2,(%0)\n\t" + "sw\t%3,4(%0)\n\t" + "sw\t%4,8(%0)\n\t" + "sw\t%5,12(%0)\n\t" + "lw\t%2,16(%1)\n\t" + "lw\t%3,20(%1)\n\t" + "lw\t%4,24(%1)\n\t" + "lw\t%5,28(%1)\n\t" + "sw\t%2,16(%0)\n\t" + "sw\t%3,20(%0)\n\t" + "sw\t%4,24(%0)\n\t" + "sw\t%5,28(%0)\n\t" + "addiu\t%0,64\n\t" + "addiu\t%1,64\n\t" + "lw\t%2,-32(%1)\n\t" + "lw\t%3,-28(%1)\n\t" + "lw\t%4,-24(%1)\n\t" + "lw\t%5,-20(%1)\n\t" + "sw\t%2,-32(%0)\n\t" + "sw\t%3,-28(%0)\n\t" + "sw\t%4,-24(%0)\n\t" + "sw\t%5,-20(%0)\n\t" + "lw\t%2,-16(%1)\n\t" + "lw\t%3,-12(%1)\n\t" + "lw\t%4,-8(%1)\n\t" + "lw\t%5,-4(%1)\n\t" + "sw\t%2,-16(%0)\n\t" + "sw\t%3,-12(%0)\n\t" + "sw\t%4,-8(%0)\n\t" + "bne\t$1,%0,1b\n\t" + "sw\t%5,-4(%0)\n\t" + ".set\tat\n\t" + ".set\treorder" + : "=r" (dummy1), "=r" (dummy2), + "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4) + : "0" (to), "1" (from), + "I" (PAGE_SIZE)); +} + +/* + * Initialize new page directory with pointers to invalid ptes + */ +void pgd_init(unsigned long page) +{ + unsigned long dummy1, dummy2; + + /* + * The plain and boring version for the R3000. No cache flushing + * stuff is implemented since the R3000 has physical caches. + */ + __asm__ __volatile__( + ".set\tnoreorder\n" + "1:\tsw\t%2, (%0)\n\t" + "sw\t%2, 4(%0)\n\t" + "sw\t%2, 8(%0)\n\t" + "sw\t%2, 12(%0)\n\t" + "sw\t%2, 16(%0)\n\t" + "sw\t%2, 20(%0)\n\t" + "sw\t%2, 24(%0)\n\t" + "sw\t%2, 28(%0)\n\t" + "subu\t%1, 1\n\t" + "bnez\t%1, 1b\n\t" + "addiu\t%0, 32\n\t" + ".set\treorder" + :"=r" (dummy1), "=r" (dummy2) + :"r" ((unsigned long) invalid_pte_table), "0" (page), + "1" (USER_PTRS_PER_PGD / 8)); +} diff -Nru a/arch/mips/mm/pg-r4k.S b/arch/mips/mm/pg-r4k.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/mm/pg-r4k.S Tue Jul 1 18:44:40 2003 @@ -0,0 +1,803 @@ +/* + * 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. + * + * r4xx0.c: R4000 processor variant specific MMU/Cache routines. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * Copyright (C) 1997, 1998, 1999, 2000 Ralf Baechle ralf@gnu.org + */ +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_64BIT_PHYS_ADDR +#define PGD_SIZE 0x2000 +#else +#define PGD_SIZE 0x1000 +#endif + + .text + .set noat + +/* + * Zero an entire page. Basically a simple unrolled loop should do the + * job but we want more performance by saving memory bus bandwidth. We + * have five flavours of the routine available for: + * + * - 16byte cachelines and no second level cache + * - 32byte cachelines second level cache + * - a version which handles the buggy R4600 v1.x + * - a version which handles the buggy R4600 v2.0 + * - Finally a last version without fancy cache games for the SC and MC + * versions of R4000 and R4400. + */ + +LEAF(r4k_clear_page32_d16) + .set mips3 + addiu AT, a0, _PAGE_SIZE +1: cache Create_Dirty_Excl_D, (a0) + sw zero, (a0) + sw zero, 4(a0) + sw zero, 8(a0) + sw zero, 12(a0) + addiu a0, 32 + cache Create_Dirty_Excl_D, -16(a0) + sw zero, -16(a0) + sw zero, -12(a0) + sw zero, -8(a0) + sw zero, -4(a0) + bne AT, a0, 1b + jr ra + END(r4k_clear_page32_d16) + +LEAF(r4k_clear_page32_d32) + .set mips3 + addiu AT, a0, _PAGE_SIZE +1: cache Create_Dirty_Excl_D, (a0) + sw zero, (a0) + sw zero, 4(a0) + sw zero, 8(a0) + sw zero, 12(a0) + addiu a0, 32 + sw zero, -16(a0) + sw zero, -12(a0) + sw zero, -8(a0) + sw zero, -4(a0) + bne AT, a0, 1b + jr ra + END(r4k_clear_page32_d32) + +LEAF(r4k_clear_page_d16) + .set mips3 + addiu AT, a0, _PAGE_SIZE +1: cache Create_Dirty_Excl_D, (a0) + sd zero, (a0) + sd zero, 8(a0) + cache Create_Dirty_Excl_D, 16(a0) + sd zero, 16(a0) + sd zero, 24(a0) + addiu a0, 64 + cache Create_Dirty_Excl_D, -32(a0) + sd zero, -32(a0) + sd zero, -24(a0) + cache Create_Dirty_Excl_D, -16(a0) + sd zero, -16(a0) + sd zero, -8(a0) + bne AT, a0, 1b + jr ra + END(r4k_clear_page_d16) + +LEAF(r4k_clear_page_d32) + .set mips3 + addiu AT, a0, _PAGE_SIZE +1: cache Create_Dirty_Excl_D, (a0) + sd zero, (a0) + sd zero, 8(a0) + sd zero, 16(a0) + sd zero, 24(a0) + addiu a0, 64 + cache Create_Dirty_Excl_D, -32(a0) + sd zero, -32(a0) + sd zero, -24(a0) + sd zero, -16(a0) + sd zero, -8(a0) + bne AT, a0, 1b + jr ra + END(r4k_clear_page_d32) + +/* + * This flavour of r4k_clear_page is for the R4600 V1.x. Cite from the + * IDT R4600 V1.7 errata: + * + * 18. The CACHE instructions Hit_Writeback_Invalidate_D, Hit_Writeback_D, + * Hit_Invalidate_D and Create_Dirty_Excl_D should only be + * executed if there is no other dcache activity. If the dcache is + * accessed for another instruction immeidately preceding when these + * cache instructions are executing, it is possible that the dcache + * tag match outputs used by these cache instructions will be + * incorrect. These cache instructions should be preceded by at least + * four instructions that are not any kind of load or store + * instruction. + * + * This is not allowed: lw + * nop + * nop + * nop + * cache Hit_Writeback_Invalidate_D + * + * This is allowed: lw + * nop + * nop + * nop + * nop + * cache Hit_Writeback_Invalidate_D + */ + +LEAF(r4k_clear_page_r4600_v1) + .set mips3 + addiu AT, a0, _PAGE_SIZE +1: nop + nop + nop + nop + cache Create_Dirty_Excl_D, (a0) + sd zero, (a0) + sd zero, 8(a0) + sd zero, 16(a0) + sd zero, 24(a0) + addiu a0, 64 + nop + nop + nop + cache Create_Dirty_Excl_D, -32(a0) + sd zero, -32(a0) + sd zero, -24(a0) + sd zero, -16(a0) + sd zero, -8(a0) + bne AT, a0, 1b + jr ra + END(r4k_clear_page_r4600_v1) + +LEAF(r4k_clear_page_r4600_v2) + .set mips3 + mfc0 a1, CP0_STATUS + ori AT, a1, 1 + xori AT, 1 + mtc0 AT, CP0_STATUS + nop + nop + nop + + .set volatile + la AT, KSEG1 + lw zero, (AT) + .set novolatile + + addiu AT, a0, _PAGE_SIZE +1: cache Create_Dirty_Excl_D, (a0) + sd zero, (a0) + sd zero, 8(a0) + sd zero, 16(a0) + sd zero, 24(a0) + addiu a0, 64 + cache Create_Dirty_Excl_D, -32(a0) + sd zero, -32(a0) + sd zero, -24(a0) + sd zero, -16(a0) + sd zero, -8(a0) + bne AT, a0, 1b + + mfc0 AT, CP0_STATUS # local_irq_restore + andi a1, 1 + ori AT, 1 + xori AT, 1 + or a1, AT + mtc0 a1, CP0_STATUS + nop + nop + nop + + jr ra + END(r4k_clear_page_r4600_v2) + +/* + * The next 4 versions are optimized for all possible scache configurations + * of the SC / MC versions of R4000 and R4400 ... + * + * Todo: For even better performance we should have a routine optimized for + * every legal combination of dcache / scache linesize. When I (Ralf) tried + * this the kernel crashed shortly after mounting the root filesystem. CPU + * bug? Weirdo cache instruction semantics? + */ + +LEAF(r4k_clear_page_s16) + .set mips3 + addiu AT, a0, _PAGE_SIZE +1: cache Create_Dirty_Excl_SD, (a0) + sd zero, (a0) + sd zero, 8(a0) + cache Create_Dirty_Excl_SD, 16(a0) + sd zero, 16(a0) + sd zero, 24(a0) + addiu a0, 64 + cache Create_Dirty_Excl_SD, -32(a0) + sd zero, -32(a0) + sd zero, -24(a0) + cache Create_Dirty_Excl_SD, -16(a0) + sd zero, -16(a0) + sd zero, -8(a0) + bne AT, a0, 1b + jr ra + END(r4k_clear_page_s16) + +LEAF(r4k_clear_page_s32) + .set mips3 + addiu AT, a0, _PAGE_SIZE +1: cache Create_Dirty_Excl_SD, (a0) + sd zero, (a0) + sd zero, 8(a0) + sd zero, 16(a0) + sd zero, 24(a0) + addiu a0, 64 + cache Create_Dirty_Excl_SD, -32(a0) + sd zero, -32(a0) + sd zero, -24(a0) + sd zero, -16(a0) + sd zero, -8(a0) + bne AT, a0, 1b + jr ra + END(r4k_clear_page_s32) + +LEAF(r4k_clear_page_s64) + .set mips3 + addiu AT, a0, _PAGE_SIZE +1: cache Create_Dirty_Excl_SD, (a0) + sd zero, (a0) + sd zero, 8(a0) + sd zero, 16(a0) + sd zero, 24(a0) + addiu a0, 64 + sd zero, -32(a0) + sd zero, -24(a0) + sd zero, -16(a0) + sd zero, -8(a0) + bne AT, a0, 1b + jr ra + END(r4k_clear_page_s64) + +LEAF(r4k_clear_page_s128) + .set mips3 + addiu AT, a0, _PAGE_SIZE +1: cache Create_Dirty_Excl_SD, (a0) + sd zero, (a0) + sd zero, 8(a0) + sd zero, 16(a0) + sd zero, 24(a0) + sd zero, 32(a0) + sd zero, 40(a0) + sd zero, 48(a0) + sd zero, 56(a0) + addiu a0, 128 + sd zero, -64(a0) + sd zero, -56(a0) + sd zero, -48(a0) + sd zero, -40(a0) + sd zero, -32(a0) + sd zero, -24(a0) + sd zero, -16(a0) + sd zero, -8(a0) + bne AT, a0, 1b + jr ra + END(r4k_clear_page_s128) + +/* + * This is suboptimal for 32-bit kernels; we assume that R10000 is only used + * with 64-bit kernels. The prefetch offsets have been experimentally tuned + * an Origin 200. + */ +LEAF(andes_clear_page) + .set mips4 + LONG_ADDIU AT, a0, _PAGE_SIZE +1: pref 7, 512(a0) + sd zero, 0*SZREG(a0) + sd zero, 1*SZREG(a0) + sd zero, 2*SZREG(a0) + sd zero, 3*SZREG(a0) + LONG_ADDIU a0, a0, 8*SZREG + sd zero, -4*SZREG(a0) + sd zero, -3*SZREG(a0) + sd zero, -2*SZREG(a0) + sd zero, -1*SZREG(a0) + bne AT, a0, 1b + j ra + END(andes_clear_page) + .set mips0 + +/* + * This is still inefficient. We only can do better if we know the + * virtual address where the copy will be accessed. + */ + +LEAF(r4k_copy_page_d16) + .set mips3 + addiu AT, a0, _PAGE_SIZE +1: cache Create_Dirty_Excl_D, (a0) + lw a3, (a1) + lw a2, 4(a1) + lw v1, 8(a1) + lw v0, 12(a1) + sw a3, (a0) + sw a2, 4(a0) + sw v1, 8(a0) + sw v0, 12(a0) + cache Create_Dirty_Excl_D, 16(a0) + lw a3, 16(a1) + lw a2, 20(a1) + lw v1, 24(a1) + lw v0, 28(a1) + sw a3, 16(a0) + sw a2, 20(a0) + sw v1, 24(a0) + sw v0, 28(a0) + cache Create_Dirty_Excl_D, 32(a0) + addiu a0, 64 + addiu a1, 64 + lw a3, -32(a1) + lw a2, -28(a1) + lw v1, -24(a1) + lw v0, -20(a1) + sw a3, -32(a0) + sw a2, -28(a0) + sw v1, -24(a0) + sw v0, -20(a0) + cache Create_Dirty_Excl_D, -16(a0) + lw a3, -16(a1) + lw a2, -12(a1) + lw v1, -8(a1) + lw v0, -4(a1) + sw a3, -16(a0) + sw a2, -12(a0) + sw v1, -8(a0) + sw v0, -4(a0) + bne AT, a0, 1b + jr ra + END(r4k_copy_page_d16) + +LEAF(r4k_copy_page_d32) + .set mips3 + addiu AT, a0, _PAGE_SIZE +1: cache Create_Dirty_Excl_D, (a0) + lw a3, (a1) + lw a2, 4(a1) + lw v1, 8(a1) + lw v0, 12(a1) + sw a3, (a0) + sw a2, 4(a0) + sw v1, 8(a0) + sw v0, 12(a0) + lw a3, 16(a1) + lw a2, 20(a1) + lw v1, 24(a1) + lw v0, 28(a1) + sw a3, 16(a0) + sw a2, 20(a0) + sw v1, 24(a0) + sw v0, 28(a0) + cache Create_Dirty_Excl_D, 32(a0) + addiu a0, 64 + addiu a1, 64 + lw a3, -32(a1) + lw a2, -28(a1) + lw v1, -24(a1) + lw v0, -20(a1) + sw a3, -32(a0) + sw a2, -28(a0) + sw v1, -24(a0) + sw v0, -20(a0) + lw a3, -16(a1) + lw a2, -12(a1) + lw v1, -8(a1) + lw v0, -4(a1) + sw a3, -16(a0) + sw a2, -12(a0) + sw v1, -8(a0) + sw v0, -4(a0) + bne AT, a0, 1b + jr ra + END(r4k_copy_page_d32) + +/* + * Again a special version for the R4600 V1.x + */ + +LEAF(r4k_copy_page_r4600_v1) + .set mips3 + addiu AT, a0, _PAGE_SIZE +1: nop + nop + nop + nop + cache Create_Dirty_Excl_D, (a0) + lw a3, (a1) + lw a2, 4(a1) + lw v1, 8(a1) + lw v0, 12(a1) + sw a3, (a0) + sw a2, 4(a0) + sw v1, 8(a0) + sw v0, 12(a0) + lw a3, 16(a1) + lw a2, 20(a1) + lw v1, 24(a1) + lw v0, 28(a1) + sw a3, 16(a0) + sw a2, 20(a0) + sw v1, 24(a0) + sw v0, 28(a0) + nop + nop + nop + nop + cache Create_Dirty_Excl_D, 32(a0) + addiu a0, 64 + addiu a1, 64 + lw a3, -32(a1) + lw a2, -28(a1) + lw v1, -24(a1) + lw v0, -20(a1) + sw a3, -32(a0) + sw a2, -28(a0) + sw v1, -24(a0) + sw v0, -20(a0) + lw a3, -16(a1) + lw a2, -12(a1) + lw v1, -8(a1) + lw v0, -4(a1) + sw a3, -16(a0) + sw a2, -12(a0) + sw v1, -8(a0) + sw v0, -4(a0) + bne AT, a0, 1b + jr ra + END(r4k_copy_page_r4600_v1) + +LEAF(r4k_copy_page_r4600_v2) + .set mips3 + mfc0 v1, CP0_STATUS + ori AT, v1, 1 + xori AT, 1 + + mtc0 AT, CP0_STATUS + nop + nop + nop + + addiu AT, a0, _PAGE_SIZE +1: nop + nop + nop + nop + cache Create_Dirty_Excl_D, (a0) + lw t1, (a1) + lw t0, 4(a1) + lw a3, 8(a1) + lw a2, 12(a1) + sw t1, (a0) + sw t0, 4(a0) + sw a3, 8(a0) + sw a2, 12(a0) + lw t1, 16(a1) + lw t0, 20(a1) + lw a3, 24(a1) + lw a2, 28(a1) + sw t1, 16(a0) + sw t0, 20(a0) + sw a3, 24(a0) + sw a2, 28(a0) + nop + nop + nop + nop + cache Create_Dirty_Excl_D, 32(a0) + addiu a0, 64 + addiu a1, 64 + lw t1, -32(a1) + lw t0, -28(a1) + lw a3, -24(a1) + lw a2, -20(a1) + sw t1, -32(a0) + sw t0, -28(a0) + sw a3, -24(a0) + sw a2, -20(a0) + lw t1, -16(a1) + lw t0, -12(a1) + lw a3, -8(a1) + lw a2, -4(a1) + sw t1, -16(a0) + sw t0, -12(a0) + sw a3, -8(a0) + sw a2, -4(a0) + bne AT, a0, 1b + + mfc0 AT, CP0_STATUS # local_irq_restore + andi v1, 1 + ori AT, 1 + xori AT, 1 + or v1, AT + mtc0 v1, CP0_STATUS + nop + nop + nop + jr ra + END(r4k_copy_page_r4600_v2) + +/* + * These are for R4000SC / R4400MC + */ + +LEAF(r4k_copy_page_s16) + .set mips3 + addiu AT, a0, _PAGE_SIZE +1: cache Create_Dirty_Excl_SD, (a0) + lw a3, (a1) + lw a2, 4(a1) + lw v1, 8(a1) + lw v0, 12(a1) + sw a3, (a0) + sw a2, 4(a0) + sw v1, 8(a0) + sw v0, 12(a0) + cache Create_Dirty_Excl_SD, 16(a0) + lw a3, 16(a1) + lw a2, 20(a1) + lw v1, 24(a1) + lw v0, 28(a1) + sw a3, 16(a0) + sw a2, 20(a0) + sw v1, 24(a0) + sw v0, 28(a0) + cache Create_Dirty_Excl_SD, 32(a0) + addiu a0, 64 + addiu a1, 64 + lw a3, -32(a1) + lw a2, -28(a1) + lw v1, -24(a1) + lw v0, -20(a1) + sw a3, -32(a0) + sw a2, -28(a0) + sw v1, -24(a0) + sw v0, -20(a0) + cache Create_Dirty_Excl_SD, -16(a0) + lw a3, -16(a1) + lw a2, -12(a1) + lw v1, -8(a1) + lw v0, -4(a1) + sw a3, -16(a0) + sw a2, -12(a0) + sw v1, -8(a0) + sw v0, -4(a0) + bne AT, a0, 1b + jr ra + END(r4k_copy_page_s16) + +LEAF(r4k_copy_page_s32) + .set mips3 + addiu AT, a0, _PAGE_SIZE +1: cache Create_Dirty_Excl_SD, (a0) + lw a3, (a1) + lw a2, 4(a1) + lw v1, 8(a1) + lw v0, 12(a1) + sw a3, (a0) + sw a2, 4(a0) + sw v1, 8(a0) + sw v0, 12(a0) + lw a3, 16(a1) + lw a2, 20(a1) + lw v1, 24(a1) + lw v0, 28(a1) + sw a3, 16(a0) + sw a2, 20(a0) + sw v1, 24(a0) + sw v0, 28(a0) + cache Create_Dirty_Excl_SD, 32(a0) + addiu a0, 64 + addiu a1, 64 + lw a3, -32(a1) + lw a2, -28(a1) + lw v1, -24(a1) + lw v0, -20(a1) + sw a3, -32(a0) + sw a2, -28(a0) + sw v1, -24(a0) + sw v0, -20(a0) + lw a3, -16(a1) + lw a2, -12(a1) + lw v1, -8(a1) + lw v0, -4(a1) + sw a3, -16(a0) + sw a2, -12(a0) + sw v1, -8(a0) + sw v0, -4(a0) + bne AT, a0, 1b + jr ra + END(r4k_copy_page_s32) + +LEAF(r4k_copy_page_s64) + .set mips3 + addiu AT, a0, _PAGE_SIZE +1: cache Create_Dirty_Excl_SD, (a0) + lw a3, (a1) + lw a2, 4(a1) + lw v1, 8(a1) + lw v0, 12(a1) + sw a3, (a0) + sw a2, 4(a0) + sw v1, 8(a0) + sw v0, 12(a0) + lw a3, 16(a1) + lw a2, 20(a1) + lw v1, 24(a1) + lw v0, 28(a1) + sw a3, 16(a0) + sw a2, 20(a0) + sw v1, 24(a0) + sw v0, 28(a0) + addiu a0, 64 + addiu a1, 64 + lw a3, -32(a1) + lw a2, -28(a1) + lw v1, -24(a1) + lw v0, -20(a1) + sw a3, -32(a0) + sw a2, -28(a0) + sw v1, -24(a0) + sw v0, -20(a0) + lw a3, -16(a1) + lw a2, -12(a1) + lw v1, -8(a1) + lw v0, -4(a1) + sw a3, -16(a0) + sw a2, -12(a0) + sw v1, -8(a0) + sw v0, -4(a0) + bne AT, a0, 1b + jr ra + END(r4k_copy_page_s64) + +LEAF(r4k_copy_page_s128) + .set mips3 + addiu AT, a0, _PAGE_SIZE +1: cache Create_Dirty_Excl_SD, (a0) + lw a3, (a1) + lw a2, 4(a1) + lw v1, 8(a1) + lw v0, 12(a1) + sw a3, (a0) + sw a2, 4(a0) + sw v1, 8(a0) + sw v0, 12(a0) + lw a3, 16(a1) + lw a2, 20(a1) + lw v1, 24(a1) + lw v0, 28(a1) + sw a3, 16(a0) + sw a2, 20(a0) + sw v1, 24(a0) + sw v0, 28(a0) + lw a3, 32(a1) + lw a2, 36(a1) + lw v1, 40(a1) + lw v0, 44(a1) + sw a3, 32(a0) + sw a2, 36(a0) + sw v1, 40(a0) + sw v0, 44(a0) + lw a3, 48(a1) + lw a2, 52(a1) + lw v1, 56(a1) + lw v0, 60(a1) + sw a3, 48(a0) + sw a2, 52(a0) + sw v1, 56(a0) + sw v0, 60(a0) + addiu a0, 128 + addiu a1, 128 + lw a3, -64(a1) + lw a2, -60(a1) + lw v1, -56(a1) + lw v0, -52(a1) + sw a3, -64(a0) + sw a2, -60(a0) + sw v1, -56(a0) + sw v0, -52(a0) + lw a3, -48(a1) + lw a2, -44(a1) + lw v1, -40(a1) + lw v0, -36(a1) + sw a3, -48(a0) + sw a2, -44(a0) + sw v1, -40(a0) + sw v0, -36(a0) + lw a3, -32(a1) + lw a2, -28(a1) + lw v1, -24(a1) + lw v0, -20(a1) + sw a3, -32(a0) + sw a2, -28(a0) + sw v1, -24(a0) + sw v0, -20(a0) + lw a3, -16(a1) + lw a2, -12(a1) + lw v1, -8(a1) + lw v0, -4(a1) + sw a3, -16(a0) + sw a2, -12(a0) + sw v1, -8(a0) + sw v0, -4(a0) + bne AT, a0, 1b + jr ra + END(r4k_copy_page_s128) + + + .text + .set mips4 + .set noat + + +/* + * This is suboptimal for 32-bit kernels; we assume that R10000 is only used + * with 64-bit kernels. The prefetch offsets have been experimentally tuned + * an Origin 200. + */ +LEAF(andes_copy_page) + .set mips4 + LONG_ADDIU AT, a0, _PAGE_SIZE +1: pref 0, 2*128(a1) + pref 1, 2*128(a0) + LONG_L a3, 0*SZREG(a1) + LONG_L a2, 1*SZREG(a1) + LONG_L v1, 2*SZREG(a1) + LONG_L v0, 3*SZREG(a1) + LONG_S a3, 0*SZREG(a0) + LONG_S a2, 1*SZREG(a0) + LONG_S v1, 2*SZREG(a0) + LONG_S v0, 3*SZREG(a0) + LONG_ADDIU a0, a0, 8*SZREG + LONG_ADDIU a1, a1, 8*SZREG + LONG_L a3, -4*SZREG(a1) + LONG_L a2, -3*SZREG(a1) + LONG_L v1, -2*SZREG(a1) + LONG_L v0, -1*SZREG(a1) + LONG_S a3, -4*SZREG(a0) + LONG_S a2, -3*SZREG(a0) + LONG_S v1, -2*SZREG(a0) + LONG_S v0, -1*SZREG(a0) + bne AT, a0,1b + j ra + END(andes_copy_page) + .set mips0 + +/* This one still needs to receive cache optimizations */ +LEAF(pgd_init) + .set mips0 + addiu AT, a0, PGD_SIZE / 2 + la v0, invalid_pte_table +1: sw v0, (a0) + sw v0, 4(a0) + sw v0, 8(a0) + sw v0, 12(a0) + addiu a0, 32 + sw v0, -16(a0) + sw v0, -12(a0) + sw v0, -8(a0) + sw v0, -4(a0) + bne AT, a0, 1b + jr ra + END(pgd_init) diff -Nru a/arch/mips/mm/pg-sb1.c b/arch/mips/mm/pg-sb1.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/mm/pg-sb1.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,132 @@ +/* + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * Copyright (C) 1997, 2001 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 2000 Sibyte + * + * Written by Justin Carlson (carlson@sibyte.com) + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#include +#include + +#ifdef CONFIG_SB1_PASS_1_WORKAROUNDS +#define SB1_PREF_LOAD_STREAMED_HINT "0" +#define SB1_PREF_STORE_STREAMED_HINT "1" +#else +#define SB1_PREF_LOAD_STREAMED_HINT "4" +#define SB1_PREF_STORE_STREAMED_HINT "5" +#endif + +/* These are the functions hooked by the memory management function pointers */ +void sb1_clear_page(void *page) +{ + /* + * JDCXXX - This should be bottlenecked by the write buffer, but these + * things tend to be mildly unpredictable...should check this on the + * performance model + * + * We prefetch 4 lines ahead. We're also "cheating" slightly here... + * since we know we're on an SB1, we force the assembler to take + * 64-bit operands to speed things up + */ + __asm__ __volatile__( + ".set push \n" + ".set noreorder \n" + ".set noat \n" + ".set mips4 \n" + " addiu $1, %0, %2 \n" /* Calculate the end of the page to clear */ +#ifdef CONFIG_CPU_HAS_PREFETCH + " pref " SB1_PREF_STORE_STREAMED_HINT ", 0(%0) \n" /* Prefetch the first 4 lines */ + " pref " SB1_PREF_STORE_STREAMED_HINT ", 32(%0) \n" + " pref " SB1_PREF_STORE_STREAMED_HINT ", 64(%0) \n" + " pref " SB1_PREF_STORE_STREAMED_HINT ", 96(%0) \n" +#endif + "1: sd $0, 0(%0) \n" /* Throw out a cacheline of 0's */ + " sd $0, 8(%0) \n" + " sd $0, 16(%0) \n" + " sd $0, 24(%0) \n" +#ifdef CONFIG_CPU_HAS_PREFETCH + " pref " SB1_PREF_STORE_STREAMED_HINT ",128(%0) \n" /* Prefetch 4 lines ahead */ +#endif + " bne $1, %0, 1b \n" + " addiu %0, %0, 32 \n" /* Next cacheline (This instruction better be short piped!) */ + ".set pop \n" + : "=r" (page) + : "0" (page), "I" (PAGE_SIZE-32) + : "memory"); + +} + +void sb1_copy_page(void *to, void *from) +{ + + /* + * This should be optimized in assembly...can't use ld/sd, though, + * because the top 32 bits could be nuked if we took an interrupt + * during the routine. And this is not a good place to be cli()'ing + * + * The pref's used here are using "streaming" hints, which cause the + * copied data to be kicked out of the cache sooner. A page copy often + * ends up copying a lot more data than is commonly used, so this seems + * to make sense in terms of reducing cache pollution, but I've no real + * performance data to back this up + */ + + __asm__ __volatile__( + ".set push \n" + ".set noreorder \n" + ".set noat \n" + ".set mips4 \n" + " addiu $1, %0, %4 \n" /* Calculate the end of the page to copy */ +#ifdef CONFIG_CPU_HAS_PREFETCH + " pref " SB1_PREF_LOAD_STREAMED_HINT ", 0(%0) \n" /* Prefetch the first 3 lines */ + " pref " SB1_PREF_STORE_STREAMED_HINT ", 0(%1) \n" + " pref " SB1_PREF_LOAD_STREAMED_HINT ", 32(%0) \n" + " pref " SB1_PREF_STORE_STREAMED_HINT ", 32(%1) \n" + " pref " SB1_PREF_LOAD_STREAMED_HINT ", 64(%0) \n" + " pref " SB1_PREF_STORE_STREAMED_HINT ", 64(%1) \n" +#endif + "1: lw $2, 0(%0) \n" /* Block copy a cacheline */ + " lw $3, 4(%0) \n" + " lw $4, 8(%0) \n" + " lw $5, 12(%0) \n" + " lw $6, 16(%0) \n" + " lw $7, 20(%0) \n" + " lw $8, 24(%0) \n" + " lw $9, 28(%0) \n" +#ifdef CONFIG_CPU_HAS_PREFETCH + " pref " SB1_PREF_LOAD_STREAMED_HINT ", 96(%0) \n" /* Prefetch ahead */ + " pref " SB1_PREF_STORE_STREAMED_HINT ", 96(%1) \n" +#endif + " sw $2, 0(%1) \n" + " sw $3, 4(%1) \n" + " sw $4, 8(%1) \n" + " sw $5, 12(%1) \n" + " sw $6, 16(%1) \n" + " sw $7, 20(%1) \n" + " sw $8, 24(%1) \n" + " sw $9, 28(%1) \n" + " addiu %1, %1, 32 \n" /* Next cacheline */ + " nop \n" /* Force next add to short pipe */ + " nop \n" /* Force next add to short pipe */ + " bne $1, %0, 1b \n" + " addiu %0, %0, 32 \n" /* Next cacheline */ + ".set pop \n" + : "=r" (to), "=r" (from) + : "0" (from), "1" (to), "I" (PAGE_SIZE-32) + : "$2","$3","$4","$5","$6","$7","$8","$9","memory"); +} diff -Nru a/arch/mips/mm/pgtable.c b/arch/mips/mm/pgtable.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/mm/pgtable.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,33 @@ +#include +#include +#include + +void show_mem(void) +{ + int pfn, total = 0, reserved = 0; + int shared = 0, cached = 0; + int highmem = 0; + struct page *page; + + printk("Mem-info:\n"); + show_free_areas(); + printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10)); + pfn = max_mapnr; + while (pfn-- > 0) { + page = pfn_to_page(pfn); + total++; + if (PageHighMem(page)) + highmem++; + if (PageReserved(page)) + reserved++; + else if (PageSwapCache(page)) + cached++; + else if (page_count(page)) + shared += page_count(page) - 1; + } + printk("%d pages of RAM\n", total); + printk("%d pages of HIGHMEM\n",highmem); + printk("%d reserved pages\n",reserved); + printk("%d pages shared\n",shared); + printk("%d pages swap cached\n",cached); +} diff -Nru a/arch/mips/mm/r2300.c b/arch/mips/mm/r2300.c --- a/arch/mips/mm/r2300.c Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,804 +0,0 @@ -/* - * r2300.c: R2000 and R3000 specific mmu/cache code. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * - * with a lot of changes to make this thing work for R3000s - * Tx39XX R4k style caches added. HK - * Copyright (C) 1998, 1999, 2000 Harald Koerfgen - * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov - */ -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * According to the paper written by D. Miller about Linux cache & TLB - * flush implementation, DMA/Driver coherence should be done at the - * driver layer. Thus, normally, we don't need flush dcache for R3000. - * Define this if driver does not handle cache consistency during DMA ops. - */ - -/* For R3000 cores with R4000 style caches */ -static unsigned long icache_size, dcache_size; /* Size in bytes */ -static unsigned long icache_lsize, dcache_lsize; /* Size in bytes */ -static unsigned long scache_size; - -#include -#include - -#undef DEBUG_TLB -#undef DEBUG_CACHE - -/* page functions */ -void r3k_clear_page(void * page) -{ - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "addiu\t$1,%0,%2\n" - "1:\tsw\t$0,(%0)\n\t" - "sw\t$0,4(%0)\n\t" - "sw\t$0,8(%0)\n\t" - "sw\t$0,12(%0)\n\t" - "addiu\t%0,32\n\t" - "sw\t$0,-16(%0)\n\t" - "sw\t$0,-12(%0)\n\t" - "sw\t$0,-8(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sw\t$0,-4(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (page) - :"0" (page), - "I" (PAGE_SIZE) - :"$1","memory"); -} - -static void r3k_copy_page(void * to, void * from) -{ - unsigned long dummy1, dummy2; - unsigned long reg1, reg2, reg3, reg4; - - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "addiu\t$1,%0,%8\n" - "1:\tlw\t%2,(%1)\n\t" - "lw\t%3,4(%1)\n\t" - "lw\t%4,8(%1)\n\t" - "lw\t%5,12(%1)\n\t" - "sw\t%2,(%0)\n\t" - "sw\t%3,4(%0)\n\t" - "sw\t%4,8(%0)\n\t" - "sw\t%5,12(%0)\n\t" - "lw\t%2,16(%1)\n\t" - "lw\t%3,20(%1)\n\t" - "lw\t%4,24(%1)\n\t" - "lw\t%5,28(%1)\n\t" - "sw\t%2,16(%0)\n\t" - "sw\t%3,20(%0)\n\t" - "sw\t%4,24(%0)\n\t" - "sw\t%5,28(%0)\n\t" - "addiu\t%0,64\n\t" - "addiu\t%1,64\n\t" - "lw\t%2,-32(%1)\n\t" - "lw\t%3,-28(%1)\n\t" - "lw\t%4,-24(%1)\n\t" - "lw\t%5,-20(%1)\n\t" - "sw\t%2,-32(%0)\n\t" - "sw\t%3,-28(%0)\n\t" - "sw\t%4,-24(%0)\n\t" - "sw\t%5,-20(%0)\n\t" - "lw\t%2,-16(%1)\n\t" - "lw\t%3,-12(%1)\n\t" - "lw\t%4,-8(%1)\n\t" - "lw\t%5,-4(%1)\n\t" - "sw\t%2,-16(%0)\n\t" - "sw\t%3,-12(%0)\n\t" - "sw\t%4,-8(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sw\t%5,-4(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (dummy1), "=r" (dummy2), - "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4) - :"0" (to), "1" (from), - "I" (PAGE_SIZE)); -} - -unsigned long __init r3k_cache_size(unsigned long ca_flags) -{ - unsigned long flags, status, dummy, size; - volatile unsigned long *p; - - p = (volatile unsigned long *) KSEG0; - - flags = read_32bit_cp0_register(CP0_STATUS); - - /* isolate cache space */ - write_32bit_cp0_register(CP0_STATUS, (ca_flags|flags)&~ST0_IEC); - - *p = 0xa5a55a5a; - dummy = *p; - status = read_32bit_cp0_register(CP0_STATUS); - - if (dummy != 0xa5a55a5a || (status & ST0_CM)) { - size = 0; - } else { - for (size = 128; size <= 0x40000; size <<= 1) - *(p + size) = 0; - *p = -1; - for (size = 128; - (size <= 0x40000) && (*(p + size) == 0); - size <<= 1) - ; - if (size > 0x40000) - size = 0; - } - - write_32bit_cp0_register(CP0_STATUS, flags); - - return size * sizeof(*p); -} - -unsigned long __init r3k_cache_lsize(unsigned long ca_flags) -{ - unsigned long flags, status, lsize, i, j; - volatile unsigned long *p; - - p = (volatile unsigned long *) KSEG0; - - flags = read_32bit_cp0_register(CP0_STATUS); - - /* isolate cache space */ - write_32bit_cp0_register(CP0_STATUS, (ca_flags|flags)&~ST0_IEC); - - for (i = 0; i < 128; i++) - *(p + i) = 0; - *(volatile unsigned char *)p = 0; - for (lsize = 1; lsize < 128; lsize <<= 1) { - *(p + lsize); - status = read_32bit_cp0_register(CP0_STATUS); - if (!(status & ST0_CM)) - break; - } - for (i = 0; i < 128; i += lsize) - *(volatile unsigned char *)(p + i) = 0; - - write_32bit_cp0_register(CP0_STATUS, flags); - - return lsize * sizeof(*p); -} - -static void __init r3k_probe_cache(void) -{ - dcache_size = r3k_cache_size(ST0_ISC); - if (dcache_size) - dcache_lsize = r3k_cache_lsize(ST0_ISC); - - - icache_size = r3k_cache_size(ST0_ISC|ST0_SWC); - if (icache_size) - icache_lsize = r3k_cache_lsize(ST0_ISC|ST0_SWC); -} - -static void r3k_flush_icache_range(unsigned long start, unsigned long end) -{ - unsigned long size, i, flags; - volatile unsigned char *p = (char *)start; - - size = end - start; - if (size > icache_size) - size = icache_size; - - flags = read_32bit_cp0_register(CP0_STATUS); - - /* isolate cache space */ - write_32bit_cp0_register(CP0_STATUS, (ST0_ISC|ST0_SWC|flags)&~ST0_IEC); - - for (i = 0; i < size; i += 0x080) { - asm ( "sb\t$0,0x000(%0)\n\t" - "sb\t$0,0x004(%0)\n\t" - "sb\t$0,0x008(%0)\n\t" - "sb\t$0,0x00c(%0)\n\t" - "sb\t$0,0x010(%0)\n\t" - "sb\t$0,0x014(%0)\n\t" - "sb\t$0,0x018(%0)\n\t" - "sb\t$0,0x01c(%0)\n\t" - "sb\t$0,0x020(%0)\n\t" - "sb\t$0,0x024(%0)\n\t" - "sb\t$0,0x028(%0)\n\t" - "sb\t$0,0x02c(%0)\n\t" - "sb\t$0,0x030(%0)\n\t" - "sb\t$0,0x034(%0)\n\t" - "sb\t$0,0x038(%0)\n\t" - "sb\t$0,0x03c(%0)\n\t" - "sb\t$0,0x040(%0)\n\t" - "sb\t$0,0x044(%0)\n\t" - "sb\t$0,0x048(%0)\n\t" - "sb\t$0,0x04c(%0)\n\t" - "sb\t$0,0x050(%0)\n\t" - "sb\t$0,0x054(%0)\n\t" - "sb\t$0,0x058(%0)\n\t" - "sb\t$0,0x05c(%0)\n\t" - "sb\t$0,0x060(%0)\n\t" - "sb\t$0,0x064(%0)\n\t" - "sb\t$0,0x068(%0)\n\t" - "sb\t$0,0x06c(%0)\n\t" - "sb\t$0,0x070(%0)\n\t" - "sb\t$0,0x074(%0)\n\t" - "sb\t$0,0x078(%0)\n\t" - "sb\t$0,0x07c(%0)\n\t" - : : "r" (p) ); - p += 0x080; - } - - write_32bit_cp0_register(CP0_STATUS,flags); -} - -static void r3k_flush_dcache_range(unsigned long start, unsigned long end) -{ - unsigned long size, i, flags; - volatile unsigned char *p = (char *)start; - - size = end - start; - if (size > dcache_size) - size = dcache_size; - - flags = read_32bit_cp0_register(CP0_STATUS); - - /* isolate cache space */ - write_32bit_cp0_register(CP0_STATUS, (ST0_ISC|flags)&~ST0_IEC); - - for (i = 0; i < size; i += 0x080) { - asm ( "sb\t$0,0x000(%0)\n\t" - "sb\t$0,0x004(%0)\n\t" - "sb\t$0,0x008(%0)\n\t" - "sb\t$0,0x00c(%0)\n\t" - "sb\t$0,0x010(%0)\n\t" - "sb\t$0,0x014(%0)\n\t" - "sb\t$0,0x018(%0)\n\t" - "sb\t$0,0x01c(%0)\n\t" - "sb\t$0,0x020(%0)\n\t" - "sb\t$0,0x024(%0)\n\t" - "sb\t$0,0x028(%0)\n\t" - "sb\t$0,0x02c(%0)\n\t" - "sb\t$0,0x030(%0)\n\t" - "sb\t$0,0x034(%0)\n\t" - "sb\t$0,0x038(%0)\n\t" - "sb\t$0,0x03c(%0)\n\t" - "sb\t$0,0x040(%0)\n\t" - "sb\t$0,0x044(%0)\n\t" - "sb\t$0,0x048(%0)\n\t" - "sb\t$0,0x04c(%0)\n\t" - "sb\t$0,0x050(%0)\n\t" - "sb\t$0,0x054(%0)\n\t" - "sb\t$0,0x058(%0)\n\t" - "sb\t$0,0x05c(%0)\n\t" - "sb\t$0,0x060(%0)\n\t" - "sb\t$0,0x064(%0)\n\t" - "sb\t$0,0x068(%0)\n\t" - "sb\t$0,0x06c(%0)\n\t" - "sb\t$0,0x070(%0)\n\t" - "sb\t$0,0x074(%0)\n\t" - "sb\t$0,0x078(%0)\n\t" - "sb\t$0,0x07c(%0)\n\t" - : : "r" (p) ); - p += 0x080; - } - - write_32bit_cp0_register(CP0_STATUS,flags); -} - -static inline unsigned long get_phys_page (unsigned long addr, - struct mm_struct *mm) -{ - pgd_t *pgd; - pmd_t *pmd; - pte_t *pte; - unsigned long physpage; - - pgd = pgd_offset(mm, addr); - pmd = pmd_offset(pgd, addr); - pte = pte_offset(pmd, addr); - - if ((physpage = pte_val(*pte)) & _PAGE_VALID) - return KSEG0ADDR(physpage & PAGE_MASK); - - return 0; -} - -static inline void r3k_flush_cache_all(void) -{ - r3k_flush_icache_range(KSEG0, KSEG0 + icache_size); -} - -static void r3k_flush_cache_mm(struct mm_struct *mm) -{ - if (mm->context != 0) { - -#ifdef DEBUG_CACHE - printk("cmm[%d]", (int)mm->context); -#endif - r3k_flush_cache_all(); - } -} - -static void r3k_flush_cache_range(struct vm_area_struct *vma, unsigned long start, - unsigned long end) -{ - struct mm_struct *mm = vma->vm_mm; - - if (mm->context == 0) - return; - - start &= PAGE_MASK; -#ifdef DEBUG_CACHE - printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); -#endif - if (mm->context != current->active_mm->context) { - flush_cache_all(); - } else { - unsigned long flags, physpage; - - save_and_cli(flags); - while (start < end) { - if ((physpage = get_phys_page(start, mm))) - r3k_flush_icache_range(physpage, - physpage + PAGE_SIZE); - start += PAGE_SIZE; - } - restore_flags(flags); - } -} - -static void r3k_flush_cache_page(struct vm_area_struct *vma, - unsigned long page) -{ - struct mm_struct *mm = vma->vm_mm; - - if (mm->context == 0) - return; - -#ifdef DEBUG_CACHE - printk("cpage[%d,%08lx]", (int)mm->context, page); -#endif - if (vma->vm_flags & VM_EXEC) { - unsigned long physpage; - - if ((physpage = get_phys_page(page, vma->vm_mm))) - r3k_flush_icache_range(physpage, physpage + PAGE_SIZE); - } -} - -static void r3k_flush_page_to_ram(struct page * page) -{ - /* - * Nothing to be done - */ -} - -static void r3k_flush_icache_page(struct vm_area_struct *vma, struct page *page) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long physpage; - - if (mm->context == 0) - return; - - if (!(vma->vm_flags & VM_EXEC)) - return; - -#ifdef DEBUG_CACHE - printk("cpage[%d,%08lx]", (int)mm->context, page); -#endif - - physpage = (unsigned long) page_address(page); - if (physpage) - r3k_flush_icache_range(physpage, physpage + PAGE_SIZE); -} - -static void r3k_flush_cache_sigtramp(unsigned long addr) -{ - unsigned long flags; - -#ifdef DEBUG_CACHE - printk("csigtramp[%08lx]", addr); -#endif - - flags = read_32bit_cp0_register(CP0_STATUS); - - write_32bit_cp0_register(CP0_STATUS, flags&~ST0_IEC); - - /* Fill the TLB to avoid an exception with caches isolated. */ - asm ( "lw\t$0,0x000(%0)\n\t" - "lw\t$0,0x004(%0)\n\t" - : : "r" (addr) ); - - write_32bit_cp0_register(CP0_STATUS, (ST0_ISC|ST0_SWC|flags)&~ST0_IEC); - - asm ( "sb\t$0,0x000(%0)\n\t" - "sb\t$0,0x004(%0)\n\t" - : : "r" (addr) ); - - write_32bit_cp0_register(CP0_STATUS, flags); -} - -static void r3k_dma_cache_wback_inv(unsigned long start, unsigned long size) -{ - wbflush(); - r3k_flush_dcache_range(start, start + size); -} - -/* TLB operations. */ -void flush_tlb_all(void) -{ - unsigned long flags; - unsigned long old_ctx; - int entry; - -#ifdef DEBUG_TLB - printk("[tlball]"); -#endif - - save_and_cli(flags); - old_ctx = (get_entryhi() & 0xfc0); - write_32bit_cp0_register(CP0_ENTRYLO0, 0); - for (entry = 8; entry < mips_cpu.tlbsize; entry++) { - write_32bit_cp0_register(CP0_INDEX, entry << 8); - write_32bit_cp0_register(CP0_ENTRYHI, ((entry | 0x80000) << 12)); - __asm__ __volatile__("tlbwi"); - } - set_entryhi(old_ctx); - restore_flags(flags); -} - -void flush_tlb_mm(struct mm_struct *mm) -{ - if (mm->context != 0) { - unsigned long flags; - -#ifdef DEBUG_TLB - printk("[tlbmm<%lu>]", (unsigned long) mm->context); -#endif - save_and_cli(flags); - get_new_mmu_context(mm, asid_cache); - if (mm == current->active_mm) - set_entryhi(mm->context & 0xfc0); - restore_flags(flags); - } -} - -void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, - unsigned long end) -{ - struct mm_struct *mm = vma->vm_mm; - - if (mm->context != 0) { - unsigned long flags; - int size; - -#ifdef DEBUG_TLB - printk("[tlbrange<%lu,0x%08lx,0x%08lx>]", - (mm->context & 0xfc0), start, end); -#endif - save_and_cli(flags); - size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; - if(size <= mips_cpu.tlbsize) { - int oldpid = (get_entryhi() & 0xfc0); - int newpid = (mm->context & 0xfc0); - - start &= PAGE_MASK; - end += (PAGE_SIZE - 1); - end &= PAGE_MASK; - while(start < end) { - int idx; - - set_entryhi(start | newpid); - start += PAGE_SIZE; - tlb_probe(); - idx = get_index(); - set_entrylo0(0); - set_entryhi(KSEG0); - if(idx < 0) - continue; - tlb_write_indexed(); - } - set_entryhi(oldpid); - } else { - get_new_mmu_context(mm, asid_cache); - if (mm == current->active_mm) - set_entryhi(mm->context & 0xfc0); - } - restore_flags(flags); - } -} - -void flush_tlb_page(struct vm_area_struct *vma, unsigned long page) -{ - if(vma->vm_mm->context != 0) { - unsigned long flags; - int oldpid, newpid, idx; - -#ifdef DEBUG_TLB - printk("[tlbpage<%lu,0x%08lx>]", vma->vm_mm->context, page); -#endif - newpid = (vma->vm_mm->context & 0xfc0); - page &= PAGE_MASK; - save_and_cli(flags); - oldpid = (get_entryhi() & 0xfc0); - set_entryhi(page | newpid); - tlb_probe(); - idx = get_index(); - set_entrylo0(0); - set_entryhi(KSEG0); - if(idx < 0) - goto finish; - tlb_write_indexed(); - -finish: - set_entryhi(oldpid); - restore_flags(flags); - } -} - -/* - * Initialize new page directory with pointers to invalid ptes - */ -void pgd_init(unsigned long page) -{ - unsigned long dummy1, dummy2; - - /* - * The plain and boring version for the R3000. No cache flushing - * stuff is implemented since the R3000 has physical caches. - */ - __asm__ __volatile__( - ".set\tnoreorder\n" - "1:\tsw\t%2,(%0)\n\t" - "sw\t%2,4(%0)\n\t" - "sw\t%2,8(%0)\n\t" - "sw\t%2,12(%0)\n\t" - "sw\t%2,16(%0)\n\t" - "sw\t%2,20(%0)\n\t" - "sw\t%2,24(%0)\n\t" - "sw\t%2,28(%0)\n\t" - "subu\t%1,1\n\t" - "bnez\t%1,1b\n\t" - "addiu\t%0,32\n\t" - ".set\treorder" - :"=r" (dummy1), - "=r" (dummy2) - :"r" ((unsigned long) invalid_pte_table), - "0" (page), - "1" (PAGE_SIZE/(sizeof(pmd_t)*8))); -} - -void update_mmu_cache(struct vm_area_struct * vma, unsigned long address, - pte_t pte) -{ - unsigned long flags; - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - int idx, pid; - - /* - * Handle debugger faulting in for debugee. - */ - if (current->active_mm != vma->vm_mm) - return; - - pid = get_entryhi() & 0xfc0; - -#ifdef DEBUG_TLB - if((pid != (vma->vm_mm->context & 0xfc0)) || (vma->vm_mm->context == 0)) { - printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%lu tlbpid=%d\n", - (vma->vm_mm->context & 0xfc0), pid); - } -#endif - - save_and_cli(flags); - address &= PAGE_MASK; - set_entryhi(address | (pid)); - pgdp = pgd_offset(vma->vm_mm, address); - tlb_probe(); - pmdp = pmd_offset(pgdp, address); - idx = get_index(); - ptep = pte_offset(pmdp, address); - set_entrylo0(pte_val(*ptep)); - set_entryhi(address | (pid)); - if(idx < 0) { - tlb_write_random(); -#if 0 - printk("[MISS]"); -#endif - } else { - tlb_write_indexed(); -#if 0 - printk("[HIT]"); -#endif - } - set_entryhi(pid); - restore_flags(flags); -} - -void show_regs(struct pt_regs * regs) -{ - /* - * Saved main processor registers - */ - printk("$0 : %08x %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", - 0, (unsigned long) regs->regs[1], (unsigned long) regs->regs[2], - (unsigned long) regs->regs[3], (unsigned long) regs->regs[4], - (unsigned long) regs->regs[5], (unsigned long) regs->regs[6], - (unsigned long) regs->regs[7]); - printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", - (unsigned long) regs->regs[8], (unsigned long) regs->regs[9], - (unsigned long) regs->regs[10], (unsigned long) regs->regs[11], - (unsigned long) regs->regs[12], (unsigned long) regs->regs[13], - (unsigned long) regs->regs[14], (unsigned long) regs->regs[15]); - printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", - (unsigned long) regs->regs[16], (unsigned long) regs->regs[17], - (unsigned long) regs->regs[18], (unsigned long) regs->regs[19], - (unsigned long) regs->regs[20], (unsigned long) regs->regs[21], - (unsigned long) regs->regs[22], (unsigned long) regs->regs[23]); - printk("$24: %08lx %08lx %08lx %08lx %08lx %08lx\n", - (unsigned long) regs->regs[24], (unsigned long) regs->regs[25], - (unsigned long) regs->regs[28], (unsigned long) regs->regs[29], - (unsigned long) regs->regs[30], (unsigned long) regs->regs[31]); - - /* - * Saved cp0 registers - */ - printk("epc : %08lx %s\nStatus: %08x\nCause : %08x\n", - (unsigned long) regs->cp0_epc, - print_tainted(), - (unsigned int) regs->cp0_status, - (unsigned int) regs->cp0_cause); -} - -/* Todo: handle r4k-style TX39 TLB */ -void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, - unsigned long entryhi, unsigned long pagemask) -{ - unsigned long flags; - unsigned long old_ctx; - static unsigned long wired = 0; - - if (wired < 8) { - save_and_cli(flags); - old_ctx = get_entryhi() & 0xfc0; - set_entrylo0(entrylo0); - set_entryhi(entryhi); - set_index(wired); - wired++; - tlb_write_indexed(); - set_entryhi(old_ctx); - flush_tlb_all(); - restore_flags(flags); - } -} - -static void tx39_flush_icache_all(void ) -{ - - unsigned long start = KSEG0; - unsigned long end = (start + icache_size); - unsigned long dummy = 0; - - /* disable icache and stop streaming */ - __asm__ __volatile__( - ".set\tnoreorder\n\t" - "mfc0\t%0,$3\n\t" - "xori\t%0,32\n\t" - "mtc0\t%0,$3\n\t" - "j\t1f\n\t" - "nop\n\t" - "1:\t.set\treorder\n\t" - : : "r"(dummy)); - - /* invalidate icache */ - while (start < end) { - cache16_unroll32(start,Index_Invalidate_I); - start += 0x200; - } - - /* enable icache */ - __asm__ __volatile__( - ".set\tnoreorder\n\t" - "mfc0\t%0,$3\n\t" - "xori\t%0,32\n\t" - "mtc0\t%0,$3\n\t" - ".set\treorder\n\t" - : : "r"(dummy)); -} - -static __init void tx39_probe_cache(void) -{ - unsigned long config; - - config = read_32bit_cp0_register(CP0_CONF); - - icache_size = 1 << (10 + ((config >> 19) & 3)); - icache_lsize = 16; - - dcache_size = 1 << (10 + ((config >> 16) & 3)); - dcache_lsize = 4; -} - -void __init ld_mmu_r23000(void) -{ - unsigned long config; - - printk("CPU revision is: %08x\n", read_32bit_cp0_register(CP0_PRID)); - - _clear_page = r3k_clear_page; - _copy_page = r3k_copy_page; - - switch (mips_cpu.cputype) { - case CPU_R2000: - case CPU_R3000: - case CPU_R3000A: - case CPU_R3081: - case CPU_R3081E: - - r3k_probe_cache(); - - _flush_cache_all = r3k_flush_cache_all; - ___flush_cache_all = r3k_flush_cache_all; - _flush_cache_mm = r3k_flush_cache_mm; - _flush_cache_range = r3k_flush_cache_range; - _flush_cache_page = r3k_flush_cache_page; - _flush_cache_sigtramp = r3k_flush_cache_sigtramp; - _flush_page_to_ram = r3k_flush_page_to_ram; - _flush_icache_page = r3k_flush_icache_page; - _flush_icache_range = r3k_flush_icache_range; - - _dma_cache_wback_inv = r3k_dma_cache_wback_inv; - break; - - case CPU_TX3912: - case CPU_TX3922: - case CPU_TX3927: - - config=read_32bit_cp0_register(CP0_CONF); - config &= ~TX39_CONF_WBON; - write_32bit_cp0_register(CP0_CONF, config); - - tx39_probe_cache(); - - _flush_cache_all = tx39_flush_icache_all; - ___flush_cache_all = tx39_flush_icache_all; - _flush_cache_mm = tx39_flush_icache_all; - _flush_cache_range = tx39_flush_icache_all; - _flush_cache_page = tx39_flush_icache_all; - _flush_cache_sigtramp = tx39_flush_icache_all; - _flush_page_to_ram = r3k_flush_page_to_ram; - _flush_icache_page = tx39_flush_icache_all; - _flush_icache_range = tx39_flush_icache_all; - - _dma_cache_wback_inv = r3k_dma_cache_wback_inv; - - break; - } - - printk("Primary instruction cache %dkb, linesize %d bytes\n", - (int) (icache_size >> 10), (int) icache_lsize); - printk("Primary data cache %dkb, linesize %d bytes\n", - (int) (dcache_size >> 10), (int) dcache_lsize); - - flush_tlb_all(); -} diff -Nru a/arch/mips/mm/r4xx0.c b/arch/mips/mm/r4xx0.c --- a/arch/mips/mm/r4xx0.c Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,2712 +0,0 @@ -/* - * 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. - * - * r4xx0.c: R4000 processor variant specific MMU/Cache routines. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * Copyright (C) 1997, 1998, 1999, 2000 Ralf Baechle ralf@gnu.org - * - * To do: - * - * - this code is a overbloated pig - * - many of the bug workarounds are not efficient at all, but at - * least they are functional ... - */ -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -/* CP0 hazard avoidance. */ -#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \ - "nop; nop; nop; nop; nop; nop;\n\t" \ - ".set reorder\n\t") - -/* Primary cache parameters. */ -static int icache_size, dcache_size; /* Size in bytes */ -static int ic_lsize, dc_lsize; /* LineSize in bytes */ - -/* Secondary cache (if present) parameters. */ -static unsigned int scache_size, sc_lsize; /* Again, in bytes */ - -#include -#include - -#undef DEBUG_CACHE - -/* - * Dummy cache handling routines for machines without boardcaches - */ -static void no_sc_noop(void) {} - -static struct bcache_ops no_sc_ops = { - (void *)no_sc_noop, (void *)no_sc_noop, - (void *)no_sc_noop, (void *)no_sc_noop -}; - -struct bcache_ops *bcops = &no_sc_ops; - -/* - * On processors with QED R4600 style two set assosicative cache - * this is the bit which selects the way in the cache for the - * indexed cachops. - */ -#define icache_waybit (icache_size >> 1) -#define dcache_waybit (dcache_size >> 1) - -/* - * Zero an entire page. Basically a simple unrolled loop should do the - * job but we want more performance by saving memory bus bandwidth. We - * have five flavours of the routine available for: - * - * - 16byte cachelines and no second level cache - * - 32byte cachelines second level cache - * - a version which handles the buggy R4600 v1.x - * - a version which handles the buggy R4600 v2.0 - * - Finally a last version without fancy cache games for the SC and MC - * versions of R4000 and R4400. - */ - -static void r4k_clear_page_d16(void * page) -{ - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - ".set\tmips3\n\t" - "daddiu\t$1,%0,%2\n" - "1:\tcache\t%3,(%0)\n\t" - "sd\t$0,(%0)\n\t" - "sd\t$0,8(%0)\n\t" - "cache\t%3,16(%0)\n\t" - "sd\t$0,16(%0)\n\t" - "sd\t$0,24(%0)\n\t" - "daddiu\t%0,64\n\t" - "cache\t%3,-32(%0)\n\t" - "sd\t$0,-32(%0)\n\t" - "sd\t$0,-24(%0)\n\t" - "cache\t%3,-16(%0)\n\t" - "sd\t$0,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sd\t$0,-8(%0)\n\t" - ".set\tmips0\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (page) - :"0" (page), - "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_D) - :"$1","memory"); -} - -static void r4k_clear_page_d32(void * page) -{ - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - ".set\tmips3\n\t" - "daddiu\t$1,%0,%2\n" - "1:\tcache\t%3,(%0)\n\t" - "sd\t$0,(%0)\n\t" - "sd\t$0,8(%0)\n\t" - "sd\t$0,16(%0)\n\t" - "sd\t$0,24(%0)\n\t" - "daddiu\t%0,64\n\t" - "cache\t%3,-32(%0)\n\t" - "sd\t$0,-32(%0)\n\t" - "sd\t$0,-24(%0)\n\t" - "sd\t$0,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sd\t$0,-8(%0)\n\t" - ".set\tmips0\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (page) - :"0" (page), - "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_D) - :"$1","memory"); -} - - -/* - * This flavour of r4k_clear_page is for the R4600 V1.x. Cite from the - * IDT R4600 V1.7 errata: - * - * 18. The CACHE instructions Hit_Writeback_Invalidate_D, Hit_Writeback_D, - * Hit_Invalidate_D and Create_Dirty_Excl_D should only be - * executed if there is no other dcache activity. If the dcache is - * accessed for another instruction immeidately preceding when these - * cache instructions are executing, it is possible that the dcache - * tag match outputs used by these cache instructions will be - * incorrect. These cache instructions should be preceded by at least - * four instructions that are not any kind of load or store - * instruction. - * - * This is not allowed: lw - * nop - * nop - * nop - * cache Hit_Writeback_Invalidate_D - * - * This is allowed: lw - * nop - * nop - * nop - * nop - * cache Hit_Writeback_Invalidate_D - */ -static void r4k_clear_page_r4600_v1(void * page) -{ - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - ".set\tmips3\n\t" - "daddiu\t$1,%0,%2\n" - "1:\tnop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "cache\t%3,(%0)\n\t" - "sd\t$0,(%0)\n\t" - "sd\t$0,8(%0)\n\t" - "sd\t$0,16(%0)\n\t" - "sd\t$0,24(%0)\n\t" - "daddiu\t%0,64\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "cache\t%3,-32(%0)\n\t" - "sd\t$0,-32(%0)\n\t" - "sd\t$0,-24(%0)\n\t" - "sd\t$0,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sd\t$0,-8(%0)\n\t" - ".set\tmips0\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (page) - :"0" (page), - "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_D) - :"$1","memory"); -} - -/* - * And this one is for the R4600 V2.0 - */ -static void r4k_clear_page_r4600_v2(void * page) -{ - unsigned int flags; - - local_irq_save(flags); - *(volatile unsigned int *)KSEG1; - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - ".set\tmips3\n\t" - "daddiu\t$1,%0,%2\n" - "1:\tcache\t%3,(%0)\n\t" - "sd\t$0,(%0)\n\t" - "sd\t$0,8(%0)\n\t" - "sd\t$0,16(%0)\n\t" - "sd\t$0,24(%0)\n\t" - "daddiu\t%0,64\n\t" - "cache\t%3,-32(%0)\n\t" - "sd\t$0,-32(%0)\n\t" - "sd\t$0,-24(%0)\n\t" - "sd\t$0,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sd\t$0,-8(%0)\n\t" - ".set\tmips0\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (page) - :"0" (page), - "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_D) - :"$1","memory"); - local_irq_restore(flags); -} - -/* - * The next 4 versions are optimized for all possible scache configurations - * of the SC / MC versions of R4000 and R4400 ... - * - * Todo: For even better performance we should have a routine optimized for - * every legal combination of dcache / scache linesize. When I (Ralf) tried - * this the kernel crashed shortly after mounting the root filesystem. CPU - * bug? Weirdo cache instruction semantics? - */ -static void r4k_clear_page_s16(void * page) -{ - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - ".set\tmips3\n\t" - "daddiu\t$1,%0,%2\n" - "1:\tcache\t%3,(%0)\n\t" - "sd\t$0,(%0)\n\t" - "sd\t$0,8(%0)\n\t" - "cache\t%3,16(%0)\n\t" - "sd\t$0,16(%0)\n\t" - "sd\t$0,24(%0)\n\t" - "daddiu\t%0,64\n\t" - "cache\t%3,-32(%0)\n\t" - "sd\t$0,-32(%0)\n\t" - "sd\t$0,-24(%0)\n\t" - "cache\t%3,-16(%0)\n\t" - "sd\t$0,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sd\t$0,-8(%0)\n\t" - ".set\tmips0\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (page) - :"0" (page), - "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_SD) - :"$1","memory"); -} - -static void r4k_clear_page_s32(void * page) -{ - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - ".set\tmips3\n\t" - "daddiu\t$1,%0,%2\n" - "1:\tcache\t%3,(%0)\n\t" - "sd\t$0,(%0)\n\t" - "sd\t$0,8(%0)\n\t" - "sd\t$0,16(%0)\n\t" - "sd\t$0,24(%0)\n\t" - "daddiu\t%0,64\n\t" - "cache\t%3,-32(%0)\n\t" - "sd\t$0,-32(%0)\n\t" - "sd\t$0,-24(%0)\n\t" - "sd\t$0,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sd\t$0,-8(%0)\n\t" - ".set\tmips0\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (page) - :"0" (page), - "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_SD) - :"$1","memory"); -} - -static void r4k_clear_page_s64(void * page) -{ - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - ".set\tmips3\n\t" - "daddiu\t$1,%0,%2\n" - "1:\tcache\t%3,(%0)\n\t" - "sd\t$0,(%0)\n\t" - "sd\t$0,8(%0)\n\t" - "sd\t$0,16(%0)\n\t" - "sd\t$0,24(%0)\n\t" - "daddiu\t%0,64\n\t" - "sd\t$0,-32(%0)\n\t" - "sd\t$0,-24(%0)\n\t" - "sd\t$0,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sd\t$0,-8(%0)\n\t" - ".set\tmips0\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (page) - :"0" (page), - "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_SD) - :"$1","memory"); -} - -static void r4k_clear_page_s128(void * page) -{ - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - ".set\tmips3\n\t" - "daddiu\t$1,%0,%2\n" - "1:\tcache\t%3,(%0)\n\t" - "sd\t$0,(%0)\n\t" - "sd\t$0,8(%0)\n\t" - "sd\t$0,16(%0)\n\t" - "sd\t$0,24(%0)\n\t" - "sd\t$0,32(%0)\n\t" - "sd\t$0,40(%0)\n\t" - "sd\t$0,48(%0)\n\t" - "sd\t$0,56(%0)\n\t" - "daddiu\t%0,128\n\t" - "sd\t$0,-64(%0)\n\t" - "sd\t$0,-56(%0)\n\t" - "sd\t$0,-48(%0)\n\t" - "sd\t$0,-40(%0)\n\t" - "sd\t$0,-32(%0)\n\t" - "sd\t$0,-24(%0)\n\t" - "sd\t$0,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sd\t$0,-8(%0)\n\t" - ".set\tmips0\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (page) - :"0" (page), - "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_SD) - :"$1","memory"); -} - - -/* - * This is still inefficient. We only can do better if we know the - * virtual address where the copy will be accessed. - */ - -static void r4k_copy_page_d16(void * to, void * from) -{ - unsigned long dummy1, dummy2; - unsigned long reg1, reg2, reg3, reg4; - - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - ".set\tmips3\n\t" - "daddiu\t$1,%0,%8\n" - "1:\tcache\t%9,(%0)\n\t" - "lw\t%2,(%1)\n\t" - "lw\t%3,4(%1)\n\t" - "lw\t%4,8(%1)\n\t" - "lw\t%5,12(%1)\n\t" - "sw\t%2,(%0)\n\t" - "sw\t%3,4(%0)\n\t" - "sw\t%4,8(%0)\n\t" - "sw\t%5,12(%0)\n\t" - "cache\t%9,16(%0)\n\t" - "lw\t%2,16(%1)\n\t" - "lw\t%3,20(%1)\n\t" - "lw\t%4,24(%1)\n\t" - "lw\t%5,28(%1)\n\t" - "sw\t%2,16(%0)\n\t" - "sw\t%3,20(%0)\n\t" - "sw\t%4,24(%0)\n\t" - "sw\t%5,28(%0)\n\t" - "cache\t%9,32(%0)\n\t" - "daddiu\t%0,64\n\t" - "daddiu\t%1,64\n\t" - "lw\t%2,-32(%1)\n\t" - "lw\t%3,-28(%1)\n\t" - "lw\t%4,-24(%1)\n\t" - "lw\t%5,-20(%1)\n\t" - "sw\t%2,-32(%0)\n\t" - "sw\t%3,-28(%0)\n\t" - "sw\t%4,-24(%0)\n\t" - "sw\t%5,-20(%0)\n\t" - "cache\t%9,-16(%0)\n\t" - "lw\t%2,-16(%1)\n\t" - "lw\t%3,-12(%1)\n\t" - "lw\t%4,-8(%1)\n\t" - "lw\t%5,-4(%1)\n\t" - "sw\t%2,-16(%0)\n\t" - "sw\t%3,-12(%0)\n\t" - "sw\t%4,-8(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sw\t%5,-4(%0)\n\t" - ".set\tmips0\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (dummy1), "=r" (dummy2), - "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4) - :"0" (to), "1" (from), - "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_D)); -} - -static void r4k_copy_page_d32(void * to, void * from) -{ - unsigned long dummy1, dummy2; - unsigned long reg1, reg2, reg3, reg4; - - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - ".set\tmips3\n\t" - "daddiu\t$1,%0,%8\n" - "1:\tcache\t%9,(%0)\n\t" - "lw\t%2,(%1)\n\t" - "lw\t%3,4(%1)\n\t" - "lw\t%4,8(%1)\n\t" - "lw\t%5,12(%1)\n\t" - "sw\t%2,(%0)\n\t" - "sw\t%3,4(%0)\n\t" - "sw\t%4,8(%0)\n\t" - "sw\t%5,12(%0)\n\t" - "lw\t%2,16(%1)\n\t" - "lw\t%3,20(%1)\n\t" - "lw\t%4,24(%1)\n\t" - "lw\t%5,28(%1)\n\t" - "sw\t%2,16(%0)\n\t" - "sw\t%3,20(%0)\n\t" - "sw\t%4,24(%0)\n\t" - "sw\t%5,28(%0)\n\t" - "cache\t%9,32(%0)\n\t" - "daddiu\t%0,64\n\t" - "daddiu\t%1,64\n\t" - "lw\t%2,-32(%1)\n\t" - "lw\t%3,-28(%1)\n\t" - "lw\t%4,-24(%1)\n\t" - "lw\t%5,-20(%1)\n\t" - "sw\t%2,-32(%0)\n\t" - "sw\t%3,-28(%0)\n\t" - "sw\t%4,-24(%0)\n\t" - "sw\t%5,-20(%0)\n\t" - "lw\t%2,-16(%1)\n\t" - "lw\t%3,-12(%1)\n\t" - "lw\t%4,-8(%1)\n\t" - "lw\t%5,-4(%1)\n\t" - "sw\t%2,-16(%0)\n\t" - "sw\t%3,-12(%0)\n\t" - "sw\t%4,-8(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sw\t%5,-4(%0)\n\t" - ".set\tmips0\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (dummy1), "=r" (dummy2), - "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4) - :"0" (to), "1" (from), - "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_D)); -} - -/* - * Again a special version for the R4600 V1.x - */ -static void r4k_copy_page_r4600_v1(void * to, void * from) -{ - unsigned long dummy1, dummy2; - unsigned long reg1, reg2, reg3, reg4; - - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - ".set\tmips3\n\t" - "daddiu\t$1,%0,%8\n" - "1:\tnop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "\tcache\t%9,(%0)\n\t" - "lw\t%2,(%1)\n\t" - "lw\t%3,4(%1)\n\t" - "lw\t%4,8(%1)\n\t" - "lw\t%5,12(%1)\n\t" - "sw\t%2,(%0)\n\t" - "sw\t%3,4(%0)\n\t" - "sw\t%4,8(%0)\n\t" - "sw\t%5,12(%0)\n\t" - "lw\t%2,16(%1)\n\t" - "lw\t%3,20(%1)\n\t" - "lw\t%4,24(%1)\n\t" - "lw\t%5,28(%1)\n\t" - "sw\t%2,16(%0)\n\t" - "sw\t%3,20(%0)\n\t" - "sw\t%4,24(%0)\n\t" - "sw\t%5,28(%0)\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "cache\t%9,32(%0)\n\t" - "daddiu\t%0,64\n\t" - "daddiu\t%1,64\n\t" - "lw\t%2,-32(%1)\n\t" - "lw\t%3,-28(%1)\n\t" - "lw\t%4,-24(%1)\n\t" - "lw\t%5,-20(%1)\n\t" - "sw\t%2,-32(%0)\n\t" - "sw\t%3,-28(%0)\n\t" - "sw\t%4,-24(%0)\n\t" - "sw\t%5,-20(%0)\n\t" - "lw\t%2,-16(%1)\n\t" - "lw\t%3,-12(%1)\n\t" - "lw\t%4,-8(%1)\n\t" - "lw\t%5,-4(%1)\n\t" - "sw\t%2,-16(%0)\n\t" - "sw\t%3,-12(%0)\n\t" - "sw\t%4,-8(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sw\t%5,-4(%0)\n\t" - ".set\tmips0\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (dummy1), "=r" (dummy2), - "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4) - :"0" (to), "1" (from), - "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_D)); -} - -static void r4k_copy_page_r4600_v2(void * to, void * from) -{ - unsigned long dummy1, dummy2; - unsigned long reg1, reg2, reg3, reg4; - unsigned int flags; - - local_irq_save(flags); - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - ".set\tmips3\n\t" - "daddiu\t$1,%0,%8\n" - "1:\tnop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "\tcache\t%9,(%0)\n\t" - "lw\t%2,(%1)\n\t" - "lw\t%3,4(%1)\n\t" - "lw\t%4,8(%1)\n\t" - "lw\t%5,12(%1)\n\t" - "sw\t%2,(%0)\n\t" - "sw\t%3,4(%0)\n\t" - "sw\t%4,8(%0)\n\t" - "sw\t%5,12(%0)\n\t" - "lw\t%2,16(%1)\n\t" - "lw\t%3,20(%1)\n\t" - "lw\t%4,24(%1)\n\t" - "lw\t%5,28(%1)\n\t" - "sw\t%2,16(%0)\n\t" - "sw\t%3,20(%0)\n\t" - "sw\t%4,24(%0)\n\t" - "sw\t%5,28(%0)\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "cache\t%9,32(%0)\n\t" - "daddiu\t%0,64\n\t" - "daddiu\t%1,64\n\t" - "lw\t%2,-32(%1)\n\t" - "lw\t%3,-28(%1)\n\t" - "lw\t%4,-24(%1)\n\t" - "lw\t%5,-20(%1)\n\t" - "sw\t%2,-32(%0)\n\t" - "sw\t%3,-28(%0)\n\t" - "sw\t%4,-24(%0)\n\t" - "sw\t%5,-20(%0)\n\t" - "lw\t%2,-16(%1)\n\t" - "lw\t%3,-12(%1)\n\t" - "lw\t%4,-8(%1)\n\t" - "lw\t%5,-4(%1)\n\t" - "sw\t%2,-16(%0)\n\t" - "sw\t%3,-12(%0)\n\t" - "sw\t%4,-8(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sw\t%5,-4(%0)\n\t" - ".set\tmips0\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (dummy1), "=r" (dummy2), - "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4) - :"0" (to), "1" (from), - "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_D)); - local_irq_restore(flags); -} - -/* - * These are for R4000SC / R4400MC - */ -static void r4k_copy_page_s16(void * to, void * from) -{ - unsigned long dummy1, dummy2; - unsigned long reg1, reg2, reg3, reg4; - - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - ".set\tmips3\n\t" - "daddiu\t$1,%0,%8\n" - "1:\tcache\t%9,(%0)\n\t" - "lw\t%2,(%1)\n\t" - "lw\t%3,4(%1)\n\t" - "lw\t%4,8(%1)\n\t" - "lw\t%5,12(%1)\n\t" - "sw\t%2,(%0)\n\t" - "sw\t%3,4(%0)\n\t" - "sw\t%4,8(%0)\n\t" - "sw\t%5,12(%0)\n\t" - "cache\t%9,16(%0)\n\t" - "lw\t%2,16(%1)\n\t" - "lw\t%3,20(%1)\n\t" - "lw\t%4,24(%1)\n\t" - "lw\t%5,28(%1)\n\t" - "sw\t%2,16(%0)\n\t" - "sw\t%3,20(%0)\n\t" - "sw\t%4,24(%0)\n\t" - "sw\t%5,28(%0)\n\t" - "cache\t%9,32(%0)\n\t" - "daddiu\t%0,64\n\t" - "daddiu\t%1,64\n\t" - "lw\t%2,-32(%1)\n\t" - "lw\t%3,-28(%1)\n\t" - "lw\t%4,-24(%1)\n\t" - "lw\t%5,-20(%1)\n\t" - "sw\t%2,-32(%0)\n\t" - "sw\t%3,-28(%0)\n\t" - "sw\t%4,-24(%0)\n\t" - "sw\t%5,-20(%0)\n\t" - "cache\t%9,-16(%0)\n\t" - "lw\t%2,-16(%1)\n\t" - "lw\t%3,-12(%1)\n\t" - "lw\t%4,-8(%1)\n\t" - "lw\t%5,-4(%1)\n\t" - "sw\t%2,-16(%0)\n\t" - "sw\t%3,-12(%0)\n\t" - "sw\t%4,-8(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sw\t%5,-4(%0)\n\t" - ".set\tmips0\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (dummy1), "=r" (dummy2), - "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4) - :"0" (to), "1" (from), - "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_SD)); -} - -static void r4k_copy_page_s32(void * to, void * from) -{ - unsigned long dummy1, dummy2; - unsigned long reg1, reg2, reg3, reg4; - - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - ".set\tmips3\n\t" - "daddiu\t$1,%0,%8\n" - "1:\tcache\t%9,(%0)\n\t" - "lw\t%2,(%1)\n\t" - "lw\t%3,4(%1)\n\t" - "lw\t%4,8(%1)\n\t" - "lw\t%5,12(%1)\n\t" - "sw\t%2,(%0)\n\t" - "sw\t%3,4(%0)\n\t" - "sw\t%4,8(%0)\n\t" - "sw\t%5,12(%0)\n\t" - "lw\t%2,16(%1)\n\t" - "lw\t%3,20(%1)\n\t" - "lw\t%4,24(%1)\n\t" - "lw\t%5,28(%1)\n\t" - "sw\t%2,16(%0)\n\t" - "sw\t%3,20(%0)\n\t" - "sw\t%4,24(%0)\n\t" - "sw\t%5,28(%0)\n\t" - "cache\t%9,32(%0)\n\t" - "daddiu\t%0,64\n\t" - "daddiu\t%1,64\n\t" - "lw\t%2,-32(%1)\n\t" - "lw\t%3,-28(%1)\n\t" - "lw\t%4,-24(%1)\n\t" - "lw\t%5,-20(%1)\n\t" - "sw\t%2,-32(%0)\n\t" - "sw\t%3,-28(%0)\n\t" - "sw\t%4,-24(%0)\n\t" - "sw\t%5,-20(%0)\n\t" - "lw\t%2,-16(%1)\n\t" - "lw\t%3,-12(%1)\n\t" - "lw\t%4,-8(%1)\n\t" - "lw\t%5,-4(%1)\n\t" - "sw\t%2,-16(%0)\n\t" - "sw\t%3,-12(%0)\n\t" - "sw\t%4,-8(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sw\t%5,-4(%0)\n\t" - ".set\tmips0\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (dummy1), "=r" (dummy2), - "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4) - :"0" (to), "1" (from), - "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_SD)); -} - -static void r4k_copy_page_s64(void * to, void * from) -{ - unsigned long dummy1, dummy2; - unsigned long reg1, reg2, reg3, reg4; - - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - ".set\tmips3\n\t" - "daddiu\t$1,%0,%8\n" - "1:\tcache\t%9,(%0)\n\t" - "lw\t%2,(%1)\n\t" - "lw\t%3,4(%1)\n\t" - "lw\t%4,8(%1)\n\t" - "lw\t%5,12(%1)\n\t" - "sw\t%2,(%0)\n\t" - "sw\t%3,4(%0)\n\t" - "sw\t%4,8(%0)\n\t" - "sw\t%5,12(%0)\n\t" - "lw\t%2,16(%1)\n\t" - "lw\t%3,20(%1)\n\t" - "lw\t%4,24(%1)\n\t" - "lw\t%5,28(%1)\n\t" - "sw\t%2,16(%0)\n\t" - "sw\t%3,20(%0)\n\t" - "sw\t%4,24(%0)\n\t" - "sw\t%5,28(%0)\n\t" - "daddiu\t%0,64\n\t" - "daddiu\t%1,64\n\t" - "lw\t%2,-32(%1)\n\t" - "lw\t%3,-28(%1)\n\t" - "lw\t%4,-24(%1)\n\t" - "lw\t%5,-20(%1)\n\t" - "sw\t%2,-32(%0)\n\t" - "sw\t%3,-28(%0)\n\t" - "sw\t%4,-24(%0)\n\t" - "sw\t%5,-20(%0)\n\t" - "lw\t%2,-16(%1)\n\t" - "lw\t%3,-12(%1)\n\t" - "lw\t%4,-8(%1)\n\t" - "lw\t%5,-4(%1)\n\t" - "sw\t%2,-16(%0)\n\t" - "sw\t%3,-12(%0)\n\t" - "sw\t%4,-8(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sw\t%5,-4(%0)\n\t" - ".set\tmips0\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (dummy1), "=r" (dummy2), - "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4) - :"0" (to), "1" (from), - "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_SD)); -} - -static void r4k_copy_page_s128(void * to, void * from) -{ - unsigned long dummy1, dummy2; - unsigned long reg1, reg2, reg3, reg4; - - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - ".set\tmips3\n\t" - "daddiu\t$1,%0,%8\n" - "1:\tcache\t%9,(%0)\n\t" - "lw\t%2,(%1)\n\t" - "lw\t%3,4(%1)\n\t" - "lw\t%4,8(%1)\n\t" - "lw\t%5,12(%1)\n\t" - "sw\t%2,(%0)\n\t" - "sw\t%3,4(%0)\n\t" - "sw\t%4,8(%0)\n\t" - "sw\t%5,12(%0)\n\t" - "lw\t%2,16(%1)\n\t" - "lw\t%3,20(%1)\n\t" - "lw\t%4,24(%1)\n\t" - "lw\t%5,28(%1)\n\t" - "sw\t%2,16(%0)\n\t" - "sw\t%3,20(%0)\n\t" - "sw\t%4,24(%0)\n\t" - "sw\t%5,28(%0)\n\t" - "lw\t%2,32(%1)\n\t" - "lw\t%3,36(%1)\n\t" - "lw\t%4,40(%1)\n\t" - "lw\t%5,44(%1)\n\t" - "sw\t%2,32(%0)\n\t" - "sw\t%3,36(%0)\n\t" - "sw\t%4,40(%0)\n\t" - "sw\t%5,44(%0)\n\t" - "lw\t%2,48(%1)\n\t" - "lw\t%3,52(%1)\n\t" - "lw\t%4,56(%1)\n\t" - "lw\t%5,60(%1)\n\t" - "sw\t%2,48(%0)\n\t" - "sw\t%3,52(%0)\n\t" - "sw\t%4,56(%0)\n\t" - "sw\t%5,60(%0)\n\t" - "daddiu\t%0,128\n\t" - "daddiu\t%1,128\n\t" - "lw\t%2,-64(%1)\n\t" - "lw\t%3,-60(%1)\n\t" - "lw\t%4,-56(%1)\n\t" - "lw\t%5,-52(%1)\n\t" - "sw\t%2,-64(%0)\n\t" - "sw\t%3,-60(%0)\n\t" - "sw\t%4,-56(%0)\n\t" - "sw\t%5,-52(%0)\n\t" - "lw\t%2,-48(%1)\n\t" - "lw\t%3,-44(%1)\n\t" - "lw\t%4,-40(%1)\n\t" - "lw\t%5,-36(%1)\n\t" - "sw\t%2,-48(%0)\n\t" - "sw\t%3,-44(%0)\n\t" - "sw\t%4,-40(%0)\n\t" - "sw\t%5,-36(%0)\n\t" - "lw\t%2,-32(%1)\n\t" - "lw\t%3,-28(%1)\n\t" - "lw\t%4,-24(%1)\n\t" - "lw\t%5,-20(%1)\n\t" - "sw\t%2,-32(%0)\n\t" - "sw\t%3,-28(%0)\n\t" - "sw\t%4,-24(%0)\n\t" - "sw\t%5,-20(%0)\n\t" - "lw\t%2,-16(%1)\n\t" - "lw\t%3,-12(%1)\n\t" - "lw\t%4,-8(%1)\n\t" - "lw\t%5,-4(%1)\n\t" - "sw\t%2,-16(%0)\n\t" - "sw\t%3,-12(%0)\n\t" - "sw\t%4,-8(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sw\t%5,-4(%0)\n\t" - ".set\tmips0\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (dummy1), "=r" (dummy2), - "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4) - :"0" (to), "1" (from), - "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_SD)); -} - - -/* - * If you think for one second that this stuff coming up is a lot - * of bulky code eating too many kernel cache lines. Think _again_. - * - * Consider: - * 1) Taken branches have a 3 cycle penalty on R4k - * 2) The branch itself is a real dead cycle on even R4600/R5000. - * 3) Only one of the following variants of each type is even used by - * the kernel based upon the cache parameters we detect at boot time. - * - * QED. - */ - -static inline void r4k_flush_cache_all_s16d16i16(void) -{ - unsigned long flags; - - local_irq_save(flags); - blast_dcache16(); blast_icache16(); blast_scache16(); - local_irq_restore(flags); -} - -static inline void r4k_flush_cache_all_s32d16i16(void) -{ - unsigned long flags; - - local_irq_save(flags); - blast_dcache16(); blast_icache16(); blast_scache32(); - local_irq_restore(flags); -} - -static inline void r4k_flush_cache_all_s64d16i16(void) -{ - unsigned long flags; - - local_irq_save(flags); - blast_dcache16(); blast_icache16(); blast_scache64(); - local_irq_restore(flags); -} - -static inline void r4k_flush_cache_all_s128d16i16(void) -{ - unsigned long flags; - - local_irq_save(flags); - blast_dcache16(); blast_icache16(); blast_scache128(); - local_irq_restore(flags); -} - -static inline void r4k_flush_cache_all_s32d32i32(void) -{ - unsigned long flags; - - local_irq_save(flags); - blast_dcache32(); blast_icache32(); blast_scache32(); - local_irq_restore(flags); -} - -static inline void r4k_flush_cache_all_s64d32i32(void) -{ - unsigned long flags; - - local_irq_save(flags); - blast_dcache32(); blast_icache32(); blast_scache64(); - local_irq_restore(flags); -} - -static inline void r4k_flush_cache_all_s128d32i32(void) -{ - unsigned long flags; - - local_irq_save(flags); - blast_dcache32(); blast_icache32(); blast_scache128(); - local_irq_restore(flags); -} - -static inline void r4k_flush_cache_all_d16i16(void) -{ - unsigned long flags; - - local_irq_save(flags); - blast_dcache16(); blast_icache16(); - local_irq_restore(flags); -} - -static inline void r4k_flush_cache_all_d32i32(void) -{ - unsigned long flags; - - local_irq_save(flags); - blast_dcache32(); blast_icache32(); - local_irq_restore(flags); -} - -static void -r4k_flush_cache_range_s16d16i16(struct vm_area_struct *vma, - unsigned long start, - unsigned long end) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long flags; - - if (mm->context == 0) - return; - - start &= PAGE_MASK; -#ifdef DEBUG_CACHE - printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); -#endif - if (vma) { - if (mm->context != current->active_mm->context) { - r4k_flush_cache_all_s16d16i16(); - } else { - pgd_t *pgd; - pmd_t *pmd; - pte_t *pte; - - local_irq_save(flags); - while(start < end) { - pgd = pgd_offset(mm, start); - pmd = pmd_offset(pgd, start); - pte = pte_offset(pmd, start); - - if(pte_val(*pte) & _PAGE_VALID) - blast_scache16_page(start); - start += PAGE_SIZE; - } - local_irq_restore(flags); - } - } -} - -static void -r4k_flush_cache_range_s32d16i16(struct vm_area_struct *vma, - unsigned long start, - unsigned long end) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long flags; - - if (mm->context == 0) - return; - - start &= PAGE_MASK; -#ifdef DEBUG_CACHE - printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); -#endif - if (vma) { - if (mm->context != current->active_mm->context) { - r4k_flush_cache_all_s32d16i16(); - } else { - pgd_t *pgd; - pmd_t *pmd; - pte_t *pte; - - local_irq_save(flags); - while(start < end) { - pgd = pgd_offset(mm, start); - pmd = pmd_offset(pgd, start); - pte = pte_offset(pmd, start); - - if(pte_val(*pte) & _PAGE_VALID) - blast_scache32_page(start); - start += PAGE_SIZE; - } - local_irq_restore(flags); - } - } -} - -static void r4k_flush_cache_range_s64d16i16(struct vm_area_struct *vma, - unsigned long start, - unsigned long end) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long flags; - - if (mm->context == 0) - return; - - start &= PAGE_MASK; -#ifdef DEBUG_CACHE - printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); -#endif - if(vma) { - if (mm->context != current->active_mm->context) { - r4k_flush_cache_all_s64d16i16(); - } else { - pgd_t *pgd; - pmd_t *pmd; - pte_t *pte; - - local_irq_save(flags); - while(start < end) { - pgd = pgd_offset(mm, start); - pmd = pmd_offset(pgd, start); - pte = pte_offset(pmd, start); - - if(pte_val(*pte) & _PAGE_VALID) - blast_scache64_page(start); - start += PAGE_SIZE; - } - local_irq_restore(flags); - } - } -} - -static void r4k_flush_cache_range_s128d16i16(struct vm_area_struct *vma, - unsigned long start, - unsigned long end) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long flags; - - if (mm->context == 0) - return; - - start &= PAGE_MASK; -#ifdef DEBUG_CACHE - printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); -#endif - if (vma) { - if (mm->context != current->active_mm->context) { - r4k_flush_cache_all_s128d16i16(); - } else { - pgd_t *pgd; - pmd_t *pmd; - pte_t *pte; - - local_irq_save(flags); - while(start < end) { - pgd = pgd_offset(mm, start); - pmd = pmd_offset(pgd, start); - pte = pte_offset(pmd, start); - - if(pte_val(*pte) & _PAGE_VALID) - blast_scache128_page(start); - start += PAGE_SIZE; - } - local_irq_restore(flags); - } - } -} - -static void r4k_flush_cache_range_s32d32i32(struct vm_area_struct *vma, - unsigned long start, - unsigned long end) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long flags; - - if (mm->context == 0) - return; - - start &= PAGE_MASK; -#ifdef DEBUG_CACHE - printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); -#endif - if (vma) { - if (mm->context != current->active_mm->context) { - r4k_flush_cache_all_s32d32i32(); - } else { - pgd_t *pgd; - pmd_t *pmd; - pte_t *pte; - - local_irq_save(flags); - while(start < end) { - pgd = pgd_offset(mm, start); - pmd = pmd_offset(pgd, start); - pte = pte_offset(pmd, start); - - if(pte_val(*pte) & _PAGE_VALID) - blast_scache32_page(start); - start += PAGE_SIZE; - } - local_irq_restore(flags); - } - } -} - -static void r4k_flush_cache_range_s64d32i32(struct vm_area_struct *vma, - unsigned long start, - unsigned long end) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long flags; - - if (mm->context == 0) - return; - - start &= PAGE_MASK; -#ifdef DEBUG_CACHE - printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); -#endif - if (vma) { - if (mm->context != current->active_mm->context) { - r4k_flush_cache_all_s64d32i32(); - } else { - pgd_t *pgd; - pmd_t *pmd; - pte_t *pte; - - local_irq_save(flags); - while(start < end) { - pgd = pgd_offset(mm, start); - pmd = pmd_offset(pgd, start); - pte = pte_offset(pmd, start); - - if(pte_val(*pte) & _PAGE_VALID) - blast_scache64_page(start); - start += PAGE_SIZE; - } - local_irq_restore(flags); - } - } -} - -static void r4k_flush_cache_range_s128d32i32(struct vm_area_struct *vma, - unsigned long start, - unsigned long end) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long flags; - - if (mm->context == 0) - return; - - start &= PAGE_MASK; -#ifdef DEBUG_CACHE - printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); -#endif - if (vma) { - if (mm->context != current->active_mm->context) { - r4k_flush_cache_all_s128d32i32(); - } else { - pgd_t *pgd; - pmd_t *pmd; - pte_t *pte; - - local_irq_save(flags); - while(start < end) { - pgd = pgd_offset(mm, start); - pmd = pmd_offset(pgd, start); - pte = pte_offset(pmd, start); - - if(pte_val(*pte) & _PAGE_VALID) - blast_scache128_page(start); - start += PAGE_SIZE; - } - local_irq_restore(flags); - } - } -} - -static void r4k_flush_cache_range_d16i16(struct mm_struct *vma, - unsigned long start, - unsigned long end) -{ - struct mm_struct *mm = vma->vm_mm; - - if (mm->context != 0) { - unsigned long flags; - -#ifdef DEBUG_CACHE - printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); -#endif - local_irq_save(flags); - blast_dcache16(); blast_icache16(); - local_irq_restore(flags); - } -} - -static void r4k_flush_cache_range_d32i32(struct vm_area_struct *vma, - unsigned long start, - unsigned long end) -{ - struct mm_struct *mm = vma->vm_mm; - - if (mm->context != 0) { - unsigned long flags; - -#ifdef DEBUG_CACHE - printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); -#endif - local_irq_save(flags); - blast_dcache32(); blast_icache32(); - local_irq_restore(flags); - } -} - -/* - * On architectures like the Sparc, we could get rid of lines in - * the cache created only by a certain context, but on the MIPS - * (and actually certain Sparc's) we cannot. - */ -static void r4k_flush_cache_mm_s16d16i16(struct mm_struct *mm) -{ - if (mm->context != 0) { -#ifdef DEBUG_CACHE - printk("cmm[%d]", (int)mm->context); -#endif - r4k_flush_cache_all_s16d16i16(); - } -} - -static void r4k_flush_cache_mm_s32d16i16(struct mm_struct *mm) -{ - if (mm->context != 0) { -#ifdef DEBUG_CACHE - printk("cmm[%d]", (int)mm->context); -#endif - r4k_flush_cache_all_s32d16i16(); - } -} - -static void r4k_flush_cache_mm_s64d16i16(struct mm_struct *mm) -{ - if (mm->context != 0) { -#ifdef DEBUG_CACHE - printk("cmm[%d]", (int)mm->context); -#endif - r4k_flush_cache_all_s64d16i16(); - } -} - -static void r4k_flush_cache_mm_s128d16i16(struct mm_struct *mm) -{ - if (mm->context != 0) { -#ifdef DEBUG_CACHE - printk("cmm[%d]", (int)mm->context); -#endif - r4k_flush_cache_all_s128d16i16(); - } -} - -static void r4k_flush_cache_mm_s32d32i32(struct mm_struct *mm) -{ - if (mm->context != 0) { -#ifdef DEBUG_CACHE - printk("cmm[%d]", (int)mm->context); -#endif - r4k_flush_cache_all_s32d32i32(); - } -} - -static void r4k_flush_cache_mm_s64d32i32(struct mm_struct *mm) -{ - if (mm->context != 0) { -#ifdef DEBUG_CACHE - printk("cmm[%d]", (int)mm->context); -#endif - r4k_flush_cache_all_s64d32i32(); - } -} - -static void r4k_flush_cache_mm_s128d32i32(struct mm_struct *mm) -{ - if (mm->context != 0) { -#ifdef DEBUG_CACHE - printk("cmm[%d]", (int)mm->context); -#endif - r4k_flush_cache_all_s128d32i32(); - } -} - -static void r4k_flush_cache_mm_d16i16(struct mm_struct *mm) -{ - if (mm->context != 0) { -#ifdef DEBUG_CACHE - printk("cmm[%d]", (int)mm->context); -#endif - r4k_flush_cache_all_d16i16(); - } -} - -static void r4k_flush_cache_mm_d32i32(struct mm_struct *mm) -{ - if (mm->context != 0) { -#ifdef DEBUG_CACHE - printk("cmm[%d]", (int)mm->context); -#endif - r4k_flush_cache_all_d32i32(); - } -} - -static void r4k_flush_cache_page_s16d16i16(struct vm_area_struct *vma, - unsigned long page) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long flags; - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - - /* - * If ownes no valid ASID yet, cannot possibly have gotten - * this page into the cache. - */ - if (mm->context == 0) - return; - -#ifdef DEBUG_CACHE - printk("cpage[%d,%08lx]", (int)mm->context, page); -#endif - local_irq_save(flags); - page &= PAGE_MASK; - pgdp = pgd_offset(mm, page); - pmdp = pmd_offset(pgdp, page); - ptep = pte_offset(pmdp, page); - - /* - * If the page isn't marked valid, the page cannot possibly be - * in the cache. - */ - if (!(pte_val(*ptep) & _PAGE_VALID)) - goto out; - - /* - * Doing flushes for another ASID than the current one is - * too difficult since stupid R4k caches do a TLB translation - * for every cache flush operation. So we do indexed flushes - * in that case, which doesn't overly flush the cache too much. - */ - if (mm->context != current->active_mm->context) { - /* - * Do indexed flush, too much work to get the (possible) - * tlb refills to work correctly. - */ - page = (KSEG0 + (page & (scache_size - 1))); - blast_dcache16_page_indexed(page); - blast_scache16_page_indexed(page); - } else - blast_scache16_page(page); -out: - local_irq_restore(flags); -} - -static void r4k_flush_cache_page_s32d16i16(struct vm_area_struct *vma, - unsigned long page) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long flags; - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - - /* - * If ownes no valid ASID yet, cannot possibly have gotten - * this page into the cache. - */ - if (mm->context == 0) - return; - -#ifdef DEBUG_CACHE - printk("cpage[%d,%08lx]", (int)mm->context, page); -#endif - local_irq_save(flags); - page &= PAGE_MASK; - pgdp = pgd_offset(mm, page); - pmdp = pmd_offset(pgdp, page); - ptep = pte_offset(pmdp, page); - - /* If the page isn't marked valid, the page cannot possibly be - * in the cache. - */ - if (!(pte_val(*ptep) & _PAGE_VALID)) - goto out; - - /* - * Doing flushes for another ASID than the current one is - * too difficult since stupid R4k caches do a TLB translation - * for every cache flush operation. So we do indexed flushes - * in that case, which doesn't overly flush the cache too much. - */ - if (mm->context != current->active_mm->context) { - /* - * Do indexed flush, too much work to get the (possible) - * tlb refills to work correctly. - */ - page = (KSEG0 + (page & (scache_size - 1))); - blast_dcache16_page_indexed(page); - blast_scache32_page_indexed(page); - } else - blast_scache32_page(page); -out: - local_irq_restore(flags); -} - -static void r4k_flush_cache_page_s64d16i16(struct vm_area_struct *vma, - unsigned long page) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long flags; - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - - /* - * If ownes no valid ASID yet, cannot possibly have gotten - * this page into the cache. - */ - if (mm->context == 0) - return; - -#ifdef DEBUG_CACHE - printk("cpage[%d,%08lx]", (int)mm->context, page); -#endif - local_irq_save(flags); - page &= PAGE_MASK; - pgdp = pgd_offset(mm, page); - pmdp = pmd_offset(pgdp, page); - ptep = pte_offset(pmdp, page); - - /* If the page isn't marked valid, the page cannot possibly be - * in the cache. - */ - if (!(pte_val(*ptep) & _PAGE_VALID)) - goto out; - - /* - * Doing flushes for another ASID than the current one is - * too difficult since stupid R4k caches do a TLB translation - * for every cache flush operation. So we do indexed flushes - * in that case, which doesn't overly flush the cache too much. - */ - if (mm->context != current->active_mm->context) { - /* - * Do indexed flush, too much work to get the (possible) - * tlb refills to work correctly. - */ - page = (KSEG0 + (page & (scache_size - 1))); - blast_dcache16_page_indexed(page); - blast_scache64_page_indexed(page); - } else - blast_scache64_page(page); -out: - local_irq_restore(flags); -} - -static void r4k_flush_cache_page_s128d16i16(struct vm_area_struct *vma, - unsigned long page) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long flags; - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - - /* - * If ownes no valid ASID yet, cannot possibly have gotten - * this page into the cache. - */ - if (mm->context == 0) - return; - -#ifdef DEBUG_CACHE - printk("cpage[%d,%08lx]", (int)mm->context, page); -#endif - local_irq_save(flags); - page &= PAGE_MASK; - pgdp = pgd_offset(mm, page); - pmdp = pmd_offset(pgdp, page); - ptep = pte_offset(pmdp, page); - - /* - * If the page isn't marked valid, the page cannot possibly be - * in the cache. - */ - if (!(pte_val(*ptep) & _PAGE_VALID)) - goto out; - - /* - * Doing flushes for another ASID than the current one is - * too difficult since stupid R4k caches do a TLB translation - * for every cache flush operation. So we do indexed flushes - * in that case, which doesn't overly flush the cache too much. - */ - if (mm->context != current->active_mm->context) { - /* - * Do indexed flush, too much work to get the (possible) - * tlb refills to work correctly. - */ - page = (KSEG0 + (page & (scache_size - 1))); - blast_dcache16_page_indexed(page); - blast_scache128_page_indexed(page); - } else - blast_scache128_page(page); -out: - local_irq_restore(flags); -} - -static void r4k_flush_cache_page_s32d32i32(struct vm_area_struct *vma, - unsigned long page) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long flags; - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - - /* - * If ownes no valid ASID yet, cannot possibly have gotten - * this page into the cache. - */ - if (mm->context == 0) - return; - -#ifdef DEBUG_CACHE - printk("cpage[%d,%08lx]", (int)mm->context, page); -#endif - local_irq_save(flags); - page &= PAGE_MASK; - pgdp = pgd_offset(mm, page); - pmdp = pmd_offset(pgdp, page); - ptep = pte_offset(pmdp, page); - - /* - * If the page isn't marked valid, the page cannot possibly be - * in the cache. - */ - if (!(pte_val(*ptep) & _PAGE_VALID)) - goto out; - - /* - * Doing flushes for another ASID than the current one is - * too difficult since stupid R4k caches do a TLB translation - * for every cache flush operation. So we do indexed flushes - * in that case, which doesn't overly flush the cache too much. - */ - if (mm->context != current->active_mm->context) { - /* - * Do indexed flush, too much work to get the (possible) - * tlb refills to work correctly. - */ - page = (KSEG0 + (page & (scache_size - 1))); - blast_dcache32_page_indexed(page); - blast_scache32_page_indexed(page); - } else - blast_scache32_page(page); -out: - local_irq_restore(flags); -} - -static void r4k_flush_cache_page_s64d32i32(struct vm_area_struct *vma, - unsigned long page) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long flags; - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - - /* - * If ownes no valid ASID yet, cannot possibly have gotten - * this page into the cache. - */ - if (mm->context == 0) - return; - -#ifdef DEBUG_CACHE - printk("cpage[%d,%08lx]", (int)mm->context, page); -#endif - local_irq_save(flags); - page &= PAGE_MASK; - pgdp = pgd_offset(mm, page); - pmdp = pmd_offset(pgdp, page); - ptep = pte_offset(pmdp, page); - - /* - * If the page isn't marked valid, the page cannot possibly be - * in the cache. - */ - if (!(pte_val(*ptep) & _PAGE_VALID)) - goto out; - - /* - * Doing flushes for another ASID than the current one is - * too difficult since stupid R4k caches do a TLB translation - * for every cache flush operation. So we do indexed flushes - * in that case, which doesn't overly flush the cache too much. - */ - if (mm->context != current->active_mm->context) { - /* - * Do indexed flush, too much work to get the (possible) - * tlb refills to work correctly. - */ - page = (KSEG0 + (page & (scache_size - 1))); - blast_dcache32_page_indexed(page); - blast_scache64_page_indexed(page); - } else - blast_scache64_page(page); -out: - local_irq_restore(flags); -} - -static void r4k_flush_cache_page_s128d32i32(struct vm_area_struct *vma, - unsigned long page) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long flags; - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - - /* - * If ownes no valid ASID yet, cannot possibly have gotten - * this page into the cache. - */ - if (mm->context == 0) - return; - -#ifdef DEBUG_CACHE - printk("cpage[%d,%08lx]", (int)mm->context, page); -#endif - local_irq_save(flags); - page &= PAGE_MASK; - pgdp = pgd_offset(mm, page); - pmdp = pmd_offset(pgdp, page); - ptep = pte_offset(pmdp, page); - - /* - * If the page isn't marked valid, the page cannot possibly be - * in the cache. - */ - if (!(pte_val(*ptep) & _PAGE_VALID)) - goto out; - - /* - * Doing flushes for another ASID than the current one is - * too difficult since stupid R4k caches do a TLB translation - * for every cache flush operation. So we do indexed flushes - * in that case, which doesn't overly flush the cache too much. - */ - if (mm->context != current->active_mm->context) { - /* Do indexed flush, too much work to get the (possible) - * tlb refills to work correctly. - */ - page = (KSEG0 + (page & (scache_size - 1))); - blast_dcache32_page_indexed(page); - blast_scache128_page_indexed(page); - } else - blast_scache128_page(page); -out: - local_irq_restore(flags); -} - -static void r4k_flush_cache_page_d16i16(struct vm_area_struct *vma, - unsigned long page) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long flags; - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - - /* - * If ownes no valid ASID yet, cannot possibly have gotten - * this page into the cache. - */ - if (mm->context == 0) - return; - -#ifdef DEBUG_CACHE - printk("cpage[%d,%08lx]", (int)mm->context, page); -#endif - local_irq_save(flags); - page &= PAGE_MASK; - pgdp = pgd_offset(mm, page); - pmdp = pmd_offset(pgdp, page); - ptep = pte_offset(pmdp, page); - - /* - * If the page isn't marked valid, the page cannot possibly be - * in the cache. - */ - if (!(pte_val(*ptep) & _PAGE_VALID)) - goto out; - - /* - * Doing flushes for another ASID than the current one is - * too difficult since stupid R4k caches do a TLB translation - * for every cache flush operation. So we do indexed flushes - * in that case, which doesn't overly flush the cache too much. - */ - if (mm == current->active_mm) { - blast_dcache16_page(page); - } else { - /* Do indexed flush, too much work to get the (possible) - * tlb refills to work correctly. - */ - page = (KSEG0 + (page & (dcache_size - 1))); - blast_dcache16_page_indexed(page); - } -out: - local_irq_restore(flags); -} - -static void r4k_flush_cache_page_d32i32(struct vm_area_struct *vma, - unsigned long page) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long flags; - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - - /* - * If ownes no valid ASID yet, cannot possibly have gotten - * this page into the cache. - */ - if (mm->context == 0) - return; - -#ifdef DEBUG_CACHE - printk("cpage[%d,%08lx]", (int)mm->context, page); -#endif - local_irq_save(flags); - page &= PAGE_MASK; - pgdp = pgd_offset(mm, page); - pmdp = pmd_offset(pgdp, page); - ptep = pte_offset(pmdp, page); - - /* - * If the page isn't marked valid, the page cannot possibly be - * in the cache. - */ - if (!(pte_val(*ptep) & _PAGE_PRESENT)) - goto out; - - /* - * Doing flushes for another ASID than the current one is - * too difficult since stupid R4k caches do a TLB translation - * for every cache flush operation. So we do indexed flushes - * in that case, which doesn't overly flush the cache too much. - */ - if ((mm == current->active_mm) && (pte_val(*ptep) & _PAGE_VALID)) { - blast_dcache32_page(page); - } else { - /* - * Do indexed flush, too much work to get the (possible) - * tlb refills to work correctly. - */ - page = (KSEG0 + (page & (dcache_size - 1))); - blast_dcache32_page_indexed(page); - } -out: - local_irq_restore(flags); -} - -static void r4k_flush_cache_page_d32i32_r4600(struct vm_area_struct *vma, - unsigned long page) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long flags; - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - - /* - * If ownes no valid ASID yet, cannot possibly have gotten - * this page into the cache. - */ - if (mm->context == 0) - return; - -#ifdef DEBUG_CACHE - printk("cpage[%d,%08lx]", (int)mm->context, page); -#endif - local_irq_save(flags); - page &= PAGE_MASK; - pgdp = pgd_offset(mm, page); - pmdp = pmd_offset(pgdp, page); - ptep = pte_offset(pmdp, page); - - /* - * If the page isn't marked valid, the page cannot possibly be - * in the cache. - */ - if (!(pte_val(*ptep) & _PAGE_PRESENT)) - goto out; - - /* - * Doing flushes for another ASID than the current one is - * too difficult since stupid R4k caches do a TLB translation - * for every cache flush operation. So we do indexed flushes - * in that case, which doesn't overly flush the cache too much. - */ - if ((mm == current->active_mm) && (pte_val(*ptep) & _PAGE_VALID)) { - blast_dcache32_page(page); - } else { - /* Do indexed flush, too much work to get the (possible) - * tlb refills to work correctly. - */ - page = (KSEG0 + (page & (dcache_size - 1))); - blast_dcache32_page_indexed(page); - blast_dcache32_page_indexed(page ^ dcache_waybit); - } -out: - local_irq_restore(flags); -} - -/* If the addresses passed to these routines are valid, they are - * either: - * - * 1) In KSEG0, so we can do a direct flush of the page. - * 2) In KSEG2, and since every process can translate those - * addresses all the time in kernel mode we can do a direct - * flush. - * 3) In KSEG1, no flush necessary. - */ -static void r4k_flush_page_to_ram_s16(struct page *page) -{ - blast_scache16_page((unsigned long)page_address(page)); -} - -static void r4k_flush_page_to_ram_s32(struct page *page) -{ - blast_scache32_page((unsigned long)page_address(page)); -} - -static void r4k_flush_page_to_ram_s64(struct page *page) -{ - blast_scache64_page((unsigned long)page_address(page)); -} - -static void r4k_flush_page_to_ram_s128(struct page *page) -{ - blast_scache128_page((unsigned long)page_address(page)); -} - -static void r4k_flush_page_to_ram_d16(struct page *page) -{ - blast_dcache16_page((unsigned long)page_address(page)); -} - -static void r4k_flush_page_to_ram_d32(struct page *page) -{ - blast_dcache32_page((unsigned long)page_address(page)); -} - -static void r4k_flush_page_to_ram_d32_r4600(struct page *page) -{ - unsigned long flags; - - local_irq_save(flags); /* For R4600 v1.7 bug. */ - blast_dcache32_page((unsigned long)page_address(page)); - local_irq_restore(flags); -} - -static void -r4k_flush_icache_page_s(struct vm_area_struct *vma, struct page *page) -{ - /* - * We did an scache flush therefore PI is already clean. - */ -} - -static void -r4k_flush_icache_range(unsigned long start, unsigned long end) -{ - flush_cache_all(); -} - -/* - * Ok, this seriously sucks. We use them to flush a user page but don't - * know the virtual address, so we have to blast away the whole icache - * which is significantly more expensive than the real thing. - */ -static void -r4k_flush_icache_page_p(struct vm_area_struct *vma, struct page *page) -{ - if (!(vma->vm_flags & VM_EXEC)) - return; - - flush_cache_all(); -} - -/* - * Writeback and invalidate the primary cache dcache before DMA. - * - * R4600 v2.0 bug: "The CACHE instructions Hit_Writeback_Inv_D, - * Hit_Writeback_D, Hit_Invalidate_D and Create_Dirty_Exclusive_D will only - * operate correctly if the internal data cache refill buffer is empty. These - * CACHE instructions should be separated from any potential data cache miss - * by a load instruction to an uncached address to empty the response buffer." - * (Revision 2.0 device errata from IDT available on http://www.idt.com/ - * in .pdf format.) - */ -static void -r4k_dma_cache_wback_inv_pc(unsigned long addr, unsigned long size) -{ - unsigned long end, a; - unsigned int flags; - - if (size >= dcache_size) { - flush_cache_all(); - } else { - /* Workaround for R4600 bug. See comment above. */ - local_irq_save(flags); - *(volatile unsigned long *)KSEG1; - - a = addr & ~(dc_lsize - 1); - end = (addr + size) & ~(dc_lsize - 1); - while (1) { - flush_dcache_line(a); /* Hit_Writeback_Inv_D */ - if (a == end) break; - a += dc_lsize; - } - local_irq_restore(flags); - } - bc_wback_inv(addr, size); -} - -static void -r4k_dma_cache_wback_inv_sc(unsigned long addr, unsigned long size) -{ - unsigned long end, a; - - if (size >= scache_size) { - flush_cache_all(); - return; - } - - a = addr & ~(sc_lsize - 1); - end = (addr + size) & ~(sc_lsize - 1); - while (1) { - flush_scache_line(a); /* Hit_Writeback_Inv_SD */ - if (a == end) break; - a += sc_lsize; - } -} - -static void -r4k_dma_cache_inv_pc(unsigned long addr, unsigned long size) -{ - unsigned long end, a; - unsigned int flags; - - if (size >= dcache_size) { - flush_cache_all(); - } else { - /* Workaround for R4600 bug. See comment above. */ - local_irq_save(flags); - *(volatile unsigned long *)KSEG1; - - a = addr & ~(dc_lsize - 1); - end = (addr + size) & ~(dc_lsize - 1); - while (1) { - flush_dcache_line(a); /* Hit_Writeback_Inv_D */ - if (a == end) break; - a += dc_lsize; - } - local_irq_restore(flags); - } - - bc_inv(addr, size); -} - -static void -r4k_dma_cache_inv_sc(unsigned long addr, unsigned long size) -{ - unsigned long end, a; - - if (size >= scache_size) { - flush_cache_all(); - return; - } - - a = addr & ~(sc_lsize - 1); - end = (addr + size) & ~(sc_lsize - 1); - while (1) { - flush_scache_line(a); /* Hit_Writeback_Inv_SD */ - if (a == end) break; - a += sc_lsize; - } -} - -static void -r4k_dma_cache_wback(unsigned long addr, unsigned long size) -{ - panic("r4k_dma_cache called - should not happen.\n"); -} - -/* - * While we're protected against bad userland addresses we don't care - * very much about what happens in that case. Usually a segmentation - * fault will dump the process later on anyway ... - */ -static void r4k_flush_cache_sigtramp(unsigned long addr) -{ - __asm__ __volatile__("nop;nop;nop;nop"); /* R4600 V1.7 */ - protected_writeback_dcache_line(addr & ~(dc_lsize - 1)); - protected_flush_icache_line(addr & ~(ic_lsize - 1)); -} - -static void r4600v20k_flush_cache_sigtramp(unsigned long addr) -{ - unsigned int flags; - - local_irq_save(flags); - - /* Clear internal cache refill buffer */ - *(volatile unsigned int *)KSEG1; - - protected_writeback_dcache_line(addr & ~(dc_lsize - 1)); - protected_flush_icache_line(addr & ~(ic_lsize - 1)); - - local_irq_restore(flags); -} - -#undef DEBUG_TLB -#undef DEBUG_TLBUPDATE - -void flush_tlb_all(void) -{ - unsigned long flags; - unsigned long old_ctx; - int entry; - -#ifdef DEBUG_TLB - printk("[tlball]"); -#endif - - local_irq_save(flags); - /* Save old context and create impossible VPN2 value */ - old_ctx = (get_entryhi() & 0xff); - set_entryhi(KSEG0); - set_entrylo0(0); - set_entrylo1(0); - BARRIER; - - entry = get_wired(); - - /* Blast 'em all away. */ - while(entry < mips_cpu.tlbsize) { - set_index(entry); - BARRIER; - tlb_write_indexed(); - BARRIER; - entry++; - } - BARRIER; - set_entryhi(old_ctx); - local_irq_restore(flags); -} - -void flush_tlb_mm(struct mm_struct *mm) -{ - if (mm->context != 0) { - unsigned long flags; - -#ifdef DEBUG_TLB - printk("[tlbmm<%d>]", mm->context); -#endif - local_irq_save(flags); - get_new_mmu_context(mm, asid_cache); - if (mm == current->active_mm) - set_entryhi(mm->context & 0xff); - local_irq_restore(flags); - } -} - -void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, - unsigned long end) -{ - struct mm_struct *mm = vma->vm_mm; - - if (mm->context != 0) { - unsigned long flags; - int size; - -#ifdef DEBUG_TLB - printk("[tlbrange<%02x,%08lx,%08lx>]", (mm->context & 0xff), - start, end); -#endif - local_irq_save(flags); - size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; - size = (size + 1) >> 1; - if(size <= mips_cpu.tlbsize/2) { - int oldpid = (get_entryhi() & 0xff); - int newpid = (mm->context & 0xff); - - start &= (PAGE_MASK << 1); - end += ((PAGE_SIZE << 1) - 1); - end &= (PAGE_MASK << 1); - while(start < end) { - int idx; - - set_entryhi(start | newpid); - start += (PAGE_SIZE << 1); - BARRIER; - tlb_probe(); - BARRIER; - idx = get_index(); - set_entrylo0(0); - set_entrylo1(0); - set_entryhi(KSEG0); - BARRIER; - if(idx < 0) - continue; - tlb_write_indexed(); - BARRIER; - } - set_entryhi(oldpid); - } else { - get_new_mmu_context(mm, asid_cache); - if (mm == current->active_mm) - set_entryhi(mm->context & 0xff); - } - local_irq_restore(flags); - } -} - -void flush_tlb_page(struct vm_area_struct *vma, unsigned long page) -{ - if (vma->vm_mm->context != 0) { - unsigned long flags; - int oldpid, newpid, idx; - -#ifdef DEBUG_TLB - printk("[tlbpage<%d,%08lx>]", vma->vm_mm->context, page); -#endif - newpid = (vma->vm_mm->context & 0xff); - page &= (PAGE_MASK << 1); - local_irq_save(flags); - oldpid = (get_entryhi() & 0xff); - set_entryhi(page | newpid); - BARRIER; - tlb_probe(); - BARRIER; - idx = get_index(); - set_entrylo0(0); - set_entrylo1(0); - set_entryhi(KSEG0); - if(idx < 0) - goto finish; - BARRIER; - tlb_write_indexed(); - - finish: - BARRIER; - set_entryhi(oldpid); - local_irq_restore(flags); - } -} - -void pgd_init(unsigned long page) -{ - unsigned long *p = (unsigned long *) page; - int i; - - for(i = 0; i < USER_PTRS_PER_PGD; i+=8) { - p[i + 0] = (unsigned long) invalid_pte_table; - p[i + 1] = (unsigned long) invalid_pte_table; - p[i + 2] = (unsigned long) invalid_pte_table; - p[i + 3] = (unsigned long) invalid_pte_table; - p[i + 4] = (unsigned long) invalid_pte_table; - p[i + 5] = (unsigned long) invalid_pte_table; - p[i + 6] = (unsigned long) invalid_pte_table; - p[i + 7] = (unsigned long) invalid_pte_table; - } -} - -/* We will need multiple versions of update_mmu_cache(), one that just - * updates the TLB with the new pte(s), and another which also checks - * for the R4k "end of page" hardware bug and does the needy. - */ -void update_mmu_cache(struct vm_area_struct * vma, - unsigned long address, pte_t pte) -{ - unsigned long flags; - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - int idx, pid; - - /* - * Handle debugger faulting in for debugee. - */ - if (current->active_mm != vma->vm_mm) - return; - - pid = get_entryhi() & 0xff; - -#ifdef DEBUG_TLB - if((pid != (vma->vm_mm->context & 0xff)) || (vma->vm_mm->context == 0)) { - printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%d tlbpid=%d\n", - (int) (vma->vm_mm->context & 0xff), pid); - } -#endif - - local_irq_save(flags); - address &= (PAGE_MASK << 1); - set_entryhi(address | (pid)); - pgdp = pgd_offset(vma->vm_mm, address); - BARRIER; - tlb_probe(); - BARRIER; - pmdp = pmd_offset(pgdp, address); - idx = get_index(); - ptep = pte_offset(pmdp, address); - BARRIER; - set_entrylo0(pte_val(*ptep++) >> 6); - set_entrylo1(pte_val(*ptep) >> 6); - set_entryhi(address | (pid)); - BARRIER; - if(idx < 0) { - tlb_write_random(); - } else { - tlb_write_indexed(); - } - BARRIER; - set_entryhi(pid); - BARRIER; - local_irq_restore(flags); -} - -#if 0 -static void r4k_update_mmu_cache_hwbug(struct vm_area_struct * vma, - unsigned long address, pte_t pte) -{ - unsigned long flags; - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - int idx; - - local_irq_save(flags); - address &= (PAGE_MASK << 1); - set_entryhi(address | (get_entryhi() & 0xff)); - pgdp = pgd_offset(vma->vm_mm, address); - tlb_probe(); - pmdp = pmd_offset(pgdp, address); - idx = get_index(); - ptep = pte_offset(pmdp, address); - set_entrylo0(pte_val(*ptep++) >> 6); - set_entrylo1(pte_val(*ptep) >> 6); - BARRIER; - if(idx < 0) - tlb_write_random(); - else - tlb_write_indexed(); - BARRIER; - local_irq_restore(flags); -} -#endif - -void show_regs(struct pt_regs * regs) -{ - /* Saved main processor registers. */ - printk("$0 : %08lx %08lx %08lx %08lx\n", - 0UL, regs->regs[1], regs->regs[2], regs->regs[3]); - printk("$4 : %08lx %08lx %08lx %08lx\n", - regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]); - printk("$8 : %08lx %08lx %08lx %08lx\n", - regs->regs[8], regs->regs[9], regs->regs[10], regs->regs[11]); - printk("$12: %08lx %08lx %08lx %08lx\n", - regs->regs[12], regs->regs[13], regs->regs[14], regs->regs[15]); - printk("$16: %08lx %08lx %08lx %08lx\n", - regs->regs[16], regs->regs[17], regs->regs[18], regs->regs[19]); - printk("$20: %08lx %08lx %08lx %08lx\n", - regs->regs[20], regs->regs[21], regs->regs[22], regs->regs[23]); - printk("$24: %08lx %08lx\n", - regs->regs[24], regs->regs[25]); - printk("$28: %08lx %08lx %08lx %08lx\n", - regs->regs[28], regs->regs[29], regs->regs[30], regs->regs[31]); - - /* Saved cp0 registers. */ - printk("epc : %08lx %s\nStatus: %08lx\nCause : %08lx\n", - regs->cp0_epc, print_tainted(), regs->cp0_status, regs->cp0_cause); -} - -void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, - unsigned long entryhi, unsigned long pagemask) -{ - unsigned long flags; - unsigned long wired; - unsigned long old_pagemask; - unsigned long old_ctx; - - local_irq_save(flags); - /* Save old context and create impossible VPN2 value */ - old_ctx = (get_entryhi() & 0xff); - old_pagemask = get_pagemask(); - wired = get_wired(); - set_wired (wired + 1); - set_index (wired); - BARRIER; - set_pagemask (pagemask); - set_entryhi(entryhi); - set_entrylo0(entrylo0); - set_entrylo1(entrylo1); - BARRIER; - tlb_write_indexed(); - BARRIER; - - set_entryhi(old_ctx); - BARRIER; - set_pagemask (old_pagemask); - flush_tlb_all(); - local_irq_restore(flags); -} - -/* Detect and size the various r4k caches. */ -static void __init probe_icache(unsigned long config) -{ - switch (mips_cpu.cputype) { - case CPU_VR41XX: - icache_size = 1 << (10 + ((config >> 9) & 7)); - break; - default: - icache_size = 1 << (12 + ((config >> 9) & 7)); - break; - } - ic_lsize = 16 << ((config >> 5) & 1); - - printk("Primary instruction cache %dkb, linesize %d bytes.\n", - icache_size >> 10, ic_lsize); -} - -static void __init probe_dcache(unsigned long config) -{ - switch (mips_cpu.cputype) { - case CPU_VR41XX: - dcache_size = 1 << (10 + ((config >> 6) & 7)); - break; - default: - dcache_size = 1 << (12 + ((config >> 6) & 7)); - break; - } - dc_lsize = 16 << ((config >> 4) & 1); - - printk("Primary data cache %dkb, linesize %d bytes.\n", - dcache_size >> 10, dc_lsize); -} - - -/* If you even _breathe_ on this function, look at the gcc output - * and make sure it does not pop things on and off the stack for - * the cache sizing loop that executes in KSEG1 space or else - * you will crash and burn badly. You have been warned. - */ -static int __init probe_scache(unsigned long config) -{ - extern unsigned long stext; - unsigned long flags, addr, begin, end, pow2; - int tmp; - - tmp = ((config >> 17) & 1); - if(tmp) - return 0; - tmp = ((config >> 22) & 3); - switch(tmp) { - case 0: - sc_lsize = 16; - break; - case 1: - sc_lsize = 32; - break; - case 2: - sc_lsize = 64; - break; - case 3: - sc_lsize = 128; - break; - } - - begin = (unsigned long) &stext; - begin &= ~((4 * 1024 * 1024) - 1); - end = begin + (4 * 1024 * 1024); - - /* This is such a bitch, you'd think they would make it - * easy to do this. Away you daemons of stupidity! - */ - local_irq_save(flags); - - /* Fill each size-multiple cache line with a valid tag. */ - pow2 = (64 * 1024); - for(addr = begin; addr < end; addr = (begin + pow2)) { - unsigned long *p = (unsigned long *) addr; - __asm__ __volatile__("nop" : : "r" (*p)); /* whee... */ - pow2 <<= 1; - } - - /* Load first line with zero (therefore invalid) tag. */ - set_taglo(0); - set_taghi(0); - __asm__ __volatile__("nop; nop; nop; nop;"); /* avoid the hazard */ - __asm__ __volatile__("\n\t.set noreorder\n\t" - ".set mips3\n\t" - "cache 8, (%0)\n\t" - ".set mips0\n\t" - ".set reorder\n\t" : : "r" (begin)); - __asm__ __volatile__("\n\t.set noreorder\n\t" - ".set mips3\n\t" - "cache 9, (%0)\n\t" - ".set mips0\n\t" - ".set reorder\n\t" : : "r" (begin)); - __asm__ __volatile__("\n\t.set noreorder\n\t" - ".set mips3\n\t" - "cache 11, (%0)\n\t" - ".set mips0\n\t" - ".set reorder\n\t" : : "r" (begin)); - - /* Now search for the wrap around point. */ - pow2 = (128 * 1024); - tmp = 0; - for(addr = (begin + (128 * 1024)); addr < (end); addr = (begin + pow2)) { - __asm__ __volatile__("\n\t.set noreorder\n\t" - ".set mips3\n\t" - "cache 7, (%0)\n\t" - ".set mips0\n\t" - ".set reorder\n\t" : : "r" (addr)); - __asm__ __volatile__("nop; nop; nop; nop;"); /* hazard... */ - if(!get_taglo()) - break; - pow2 <<= 1; - } - local_irq_restore(flags); - addr -= begin; - printk("Secondary cache sized at %dK linesize %d bytes.\n", - (int) (addr >> 10), sc_lsize); - scache_size = addr; - return 1; -} - -static void __init setup_noscache_funcs(void) -{ - unsigned int prid; - - switch(dc_lsize) { - case 16: - _clear_page = r4k_clear_page_d16; - _copy_page = r4k_copy_page_d16; - _flush_cache_all = r4k_flush_cache_all_d16i16; - _flush_cache_mm = r4k_flush_cache_mm_d16i16; - _flush_cache_range = r4k_flush_cache_range_d16i16; - _flush_cache_page = r4k_flush_cache_page_d16i16; - _flush_page_to_ram = r4k_flush_page_to_ram_d16; - break; - case 32: - prid = read_32bit_cp0_register(CP0_PRID) & 0xfff0; - if (prid == 0x2010) { /* R4600 V1.7 */ - _clear_page = r4k_clear_page_r4600_v1; - _copy_page = r4k_copy_page_r4600_v1; - _flush_page_to_ram = r4k_flush_page_to_ram_d32_r4600; - } else if (prid == 0x2020) { /* R4600 V2.0 */ - _clear_page = r4k_clear_page_r4600_v2; - _copy_page = r4k_copy_page_r4600_v2; - _flush_page_to_ram = r4k_flush_page_to_ram_d32; - } else { - _clear_page = r4k_clear_page_d32; - _copy_page = r4k_copy_page_d32; - _flush_page_to_ram = r4k_flush_page_to_ram_d32; - } - _flush_cache_all = r4k_flush_cache_all_d32i32; - _flush_cache_mm = r4k_flush_cache_mm_d32i32; - _flush_cache_range = r4k_flush_cache_range_d32i32; - _flush_cache_page = r4k_flush_cache_page_d32i32; - break; - } - ___flush_cache_all = _flush_cache_all; - - _flush_icache_page = r4k_flush_icache_page_p; - - _dma_cache_wback_inv = r4k_dma_cache_wback_inv_pc; - _dma_cache_wback = r4k_dma_cache_wback; - _dma_cache_inv = r4k_dma_cache_inv_pc; -} - -static void __init setup_scache_funcs(void) -{ - switch(sc_lsize) { - case 16: - switch(dc_lsize) { - case 16: - _flush_cache_all = r4k_flush_cache_all_s16d16i16; - _flush_cache_mm = r4k_flush_cache_mm_s16d16i16; - _flush_cache_range = r4k_flush_cache_range_s16d16i16; - _flush_cache_page = r4k_flush_cache_page_s16d16i16; - break; - case 32: - panic("Invalid cache configuration detected"); - }; - _flush_page_to_ram = r4k_flush_page_to_ram_s16; - _clear_page = r4k_clear_page_s16; - _copy_page = r4k_copy_page_s16; - break; - case 32: - switch(dc_lsize) { - case 16: - _flush_cache_all = r4k_flush_cache_all_s32d16i16; - _flush_cache_mm = r4k_flush_cache_mm_s32d16i16; - _flush_cache_range = r4k_flush_cache_range_s32d16i16; - _flush_cache_page = r4k_flush_cache_page_s32d16i16; - break; - case 32: - _flush_cache_all = r4k_flush_cache_all_s32d32i32; - _flush_cache_mm = r4k_flush_cache_mm_s32d32i32; - _flush_cache_range = r4k_flush_cache_range_s32d32i32; - _flush_cache_page = r4k_flush_cache_page_s32d32i32; - break; - }; - _flush_page_to_ram = r4k_flush_page_to_ram_s32; - _clear_page = r4k_clear_page_s32; - _copy_page = r4k_copy_page_s32; - break; - case 64: - switch(dc_lsize) { - case 16: - _flush_cache_all = r4k_flush_cache_all_s64d16i16; - _flush_cache_mm = r4k_flush_cache_mm_s64d16i16; - _flush_cache_range = r4k_flush_cache_range_s64d16i16; - _flush_cache_page = r4k_flush_cache_page_s64d16i16; - break; - case 32: - _flush_cache_all = r4k_flush_cache_all_s64d32i32; - _flush_cache_mm = r4k_flush_cache_mm_s64d32i32; - _flush_cache_range = r4k_flush_cache_range_s64d32i32; - _flush_cache_page = r4k_flush_cache_page_s64d32i32; - break; - }; - _flush_page_to_ram = r4k_flush_page_to_ram_s64; - _clear_page = r4k_clear_page_s64; - _copy_page = r4k_copy_page_s64; - break; - case 128: - switch(dc_lsize) { - case 16: - _flush_cache_all = r4k_flush_cache_all_s128d16i16; - _flush_cache_mm = r4k_flush_cache_mm_s128d16i16; - _flush_cache_range = r4k_flush_cache_range_s128d16i16; - _flush_cache_page = r4k_flush_cache_page_s128d16i16; - break; - case 32: - _flush_cache_all = r4k_flush_cache_all_s128d32i32; - _flush_cache_mm = r4k_flush_cache_mm_s128d32i32; - _flush_cache_range = r4k_flush_cache_range_s128d32i32; - _flush_cache_page = r4k_flush_cache_page_s128d32i32; - break; - }; - _flush_page_to_ram = r4k_flush_page_to_ram_s128; - _clear_page = r4k_clear_page_s128; - _copy_page = r4k_copy_page_s128; - break; - } - ___flush_cache_all = _flush_cache_all; - _flush_icache_page = r4k_flush_icache_page_s; - _dma_cache_wback_inv = r4k_dma_cache_wback_inv_sc; - _dma_cache_wback = r4k_dma_cache_wback; - _dma_cache_inv = r4k_dma_cache_inv_sc; -} - -typedef int (*probe_func_t)(unsigned long); - -static inline void __init setup_scache(unsigned int config) -{ - probe_func_t probe_scache_kseg1; - int sc_present = 0; - - /* Maybe the cpu knows about a l2 cache? */ - probe_scache_kseg1 = (probe_func_t) (KSEG1ADDR(&probe_scache)); - sc_present = probe_scache_kseg1(config); - - if (sc_present) { - setup_scache_funcs(); - return; - } - - setup_noscache_funcs(); -} - -void __init ld_mmu_r4xx0(void) -{ - unsigned long config = read_32bit_cp0_register(CP0_CONFIG); - - printk("CPU revision is: %08x\n", read_32bit_cp0_register(CP0_PRID)); - -#ifdef CONFIG_MIPS_UNCACHED - change_cp0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); -#else - change_cp0_config(CONF_CM_CMASK, CONF_CM_CACHABLE_NONCOHERENT); -#endif - - probe_icache(config); - probe_dcache(config); - setup_scache(config); - - switch(mips_cpu.cputype) { - case CPU_R4600: /* QED style two way caches? */ - case CPU_R4700: - case CPU_R5000: - case CPU_NEVADA: - _flush_cache_page = r4k_flush_cache_page_d32i32_r4600; - } - - _flush_cache_sigtramp = r4k_flush_cache_sigtramp; - _flush_icache_range = r4k_flush_icache_range; /* Ouch */ - if ((read_32bit_cp0_register(CP0_PRID) & 0xfff0) == 0x2020) { - _flush_cache_sigtramp = r4600v20k_flush_cache_sigtramp; - } - - __flush_cache_all(); - write_32bit_cp0_register(CP0_WIRED, 0); - - /* - * You should never change this register: - * - On R4600 1.7 the tlbp never hits for pages smaller than - * the value in the c0_pagemask register. - * - The entire mm handling assumes the c0_pagemask register to - * be set for 4kb pages. - */ - set_pagemask(PM_4K); - flush_tlb_all(); -} diff -Nru a/arch/mips/mm/r5432.c b/arch/mips/mm/r5432.c --- a/arch/mips/mm/r5432.c Tue Jul 1 18:44:35 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,864 +0,0 @@ -/* - * 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. - * - * r5432.c: NEC Vr5432 processor. We cannot use r4xx0.c because of - * its unique way-selection method for indexed operations. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * Copyright (C) 1997, 1998, 1999, 2000 Ralf Baechle (ralf@gnu.org) - * Copyright (C) 2000 Jun Sun (jsun@mvista.com) - * - */ - -/* - * [jsun] - * In a sense, this is really silly. We cannot re-use r4xx0.c because - * the lowest-level indexed cache operation does not take way-selection - * into account. So all what I am doing here is to copy all the funcs - * and macros (in r4kcache.h) relavent to R5432 to this file, and then - * modify a few indexed cache operations. *sigh* - */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -/* CP0 hazard avoidance. */ -#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \ - "nop; nop; nop; nop; nop; nop;\n\t" \ - ".set reorder\n\t") - -#include -#include - -#undef DEBUG_CACHE - -/* Primary cache parameters. */ -static int icache_size, dcache_size; /* Size in bytes */ -static int ic_lsize, dc_lsize; /* LineSize in bytes */ - - -/* -------------------------------------------------------------------- */ -/* #include */ - -extern inline void flush_icache_line_indexed(unsigned long addr) -{ - __asm__ __volatile__( - ".set noreorder\n\t" - ".set mips3\n\t" - "cache %1, (%0)\n\t" - "cache %1, 1(%0)\n\t" - ".set mips0\n\t" - ".set reorder" - : - : "r" (addr), - "i" (Index_Invalidate_I)); -} - -extern inline void flush_dcache_line_indexed(unsigned long addr) -{ - __asm__ __volatile__( - ".set noreorder\n\t" - ".set mips3\n\t" - "cache %1, (%0)\n\t" - "cache %1, 1(%0)\n\t" - ".set mips0\n\t" - ".set reorder" - : - : "r" (addr), - "i" (Index_Writeback_Inv_D)); -} - -extern inline void flush_icache_line(unsigned long addr) -{ - __asm__ __volatile__( - ".set noreorder\n\t" - ".set mips3\n\t" - "cache %1, (%0)\n\t" - ".set mips0\n\t" - ".set reorder" - : - : "r" (addr), - "i" (Hit_Invalidate_I)); -} - -extern inline void flush_dcache_line(unsigned long addr) -{ - __asm__ __volatile__( - ".set noreorder\n\t" - ".set mips3\n\t" - "cache %1, (%0)\n\t" - ".set mips0\n\t" - ".set reorder" - : - : "r" (addr), - "i" (Hit_Writeback_Inv_D)); -} - -extern inline void invalidate_dcache_line(unsigned long addr) -{ - __asm__ __volatile__( - ".set noreorder\n\t" - ".set mips3\n\t" - "cache %1, (%0)\n\t" - ".set mips0\n\t" - ".set reorder" - : - : "r" (addr), - "i" (Hit_Invalidate_D)); -} - - -/* - * The next two are for badland addresses like signal trampolines. - */ -extern inline void protected_flush_icache_line(unsigned long addr) -{ - __asm__ __volatile__( - ".set noreorder\n\t" - ".set mips3\n" - "1:\tcache %1,(%0)\n" - "2:\t.set mips0\n\t" - ".set reorder\n\t" - ".section\t__ex_table,\"a\"\n\t" - STR(PTR)"\t1b,2b\n\t" - ".previous" - : - : "r" (addr), - "i" (Hit_Invalidate_I)); -} - -extern inline void protected_writeback_dcache_line(unsigned long addr) -{ - __asm__ __volatile__( - ".set noreorder\n\t" - ".set mips3\n" - "1:\tcache %1,(%0)\n" - "2:\t.set mips0\n\t" - ".set reorder\n\t" - ".section\t__ex_table,\"a\"\n\t" - STR(PTR)"\t1b,2b\n\t" - ".previous" - : - : "r" (addr), - "i" (Hit_Writeback_D)); -} - - -#define cache32_unroll32(base,op) \ - __asm__ __volatile__(" \ - .set noreorder; \ - .set mips3; \ - cache %1, 0x000(%0); cache %1, 0x020(%0); \ - cache %1, 0x040(%0); cache %1, 0x060(%0); \ - cache %1, 0x080(%0); cache %1, 0x0a0(%0); \ - cache %1, 0x0c0(%0); cache %1, 0x0e0(%0); \ - cache %1, 0x100(%0); cache %1, 0x120(%0); \ - cache %1, 0x140(%0); cache %1, 0x160(%0); \ - cache %1, 0x180(%0); cache %1, 0x1a0(%0); \ - cache %1, 0x1c0(%0); cache %1, 0x1e0(%0); \ - cache %1, 0x200(%0); cache %1, 0x220(%0); \ - cache %1, 0x240(%0); cache %1, 0x260(%0); \ - cache %1, 0x280(%0); cache %1, 0x2a0(%0); \ - cache %1, 0x2c0(%0); cache %1, 0x2e0(%0); \ - cache %1, 0x300(%0); cache %1, 0x320(%0); \ - cache %1, 0x340(%0); cache %1, 0x360(%0); \ - cache %1, 0x380(%0); cache %1, 0x3a0(%0); \ - cache %1, 0x3c0(%0); cache %1, 0x3e0(%0); \ - .set mips0; \ - .set reorder" \ - : \ - : "r" (base), \ - "i" (op)); - -extern inline void blast_dcache32(void) -{ - unsigned long start = KSEG0; - unsigned long end = (start + dcache_size/2); - - while(start < end) { - cache32_unroll32(start,Index_Writeback_Inv_D); - cache32_unroll32(start+1,Index_Writeback_Inv_D); - start += 0x400; - } -} - -extern inline void blast_dcache32_page(unsigned long page) -{ - unsigned long start = page; - unsigned long end = (start + PAGE_SIZE); - - while(start < end) { - cache32_unroll32(start,Hit_Writeback_Inv_D); - start += 0x400; - } -} - -extern inline void blast_dcache32_page_indexed(unsigned long page) -{ - unsigned long start = page; - unsigned long end = (start + PAGE_SIZE); - - while(start < end) { - cache32_unroll32(start,Index_Writeback_Inv_D); - cache32_unroll32(start+1,Index_Writeback_Inv_D); - start += 0x400; - } -} - -extern inline void blast_icache32(void) -{ - unsigned long start = KSEG0; - unsigned long end = (start + icache_size/2); - - while(start < end) { - cache32_unroll32(start,Index_Invalidate_I); - cache32_unroll32(start+1,Index_Invalidate_I); - start += 0x400; - } -} - -extern inline void blast_icache32_page(unsigned long page) -{ - unsigned long start = page; - unsigned long end = (start + PAGE_SIZE); - - while(start < end) { - cache32_unroll32(start,Hit_Invalidate_I); - start += 0x400; - } -} - -extern inline void blast_icache32_page_indexed(unsigned long page) -{ - unsigned long start = page; - unsigned long end = (start + PAGE_SIZE); - - while(start < end) { - cache32_unroll32(start,Index_Invalidate_I); - cache32_unroll32(start+1,Index_Invalidate_I); - start += 0x400; - } -} - -/* -------------------------------------------------------------------- */ - -static void r5432_clear_page_d32(void * page) -{ - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - ".set\tmips3\n\t" - "daddiu\t$1,%0,%2\n" - "1:\tcache\t%3,(%0)\n\t" - "sd\t$0,(%0)\n\t" - "sd\t$0,8(%0)\n\t" - "sd\t$0,16(%0)\n\t" - "sd\t$0,24(%0)\n\t" - "daddiu\t%0,64\n\t" - "cache\t%3,-32(%0)\n\t" - "sd\t$0,-32(%0)\n\t" - "sd\t$0,-24(%0)\n\t" - "sd\t$0,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sd\t$0,-8(%0)\n\t" - ".set\tmips0\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (page) - :"0" (page), - "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_D) - :"$1","memory"); -} - - - -/* - * This is still inefficient. We only can do better if we know the - * virtual address where the copy will be accessed. - */ - -static void r5432_copy_page_d32(void * to, void * from) -{ - unsigned long dummy1, dummy2; - unsigned long reg1, reg2, reg3, reg4; - - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - ".set\tmips3\n\t" - "daddiu\t$1,%0,%8\n" - "1:\tcache\t%9,(%0)\n\t" - "lw\t%2,(%1)\n\t" - "lw\t%3,4(%1)\n\t" - "lw\t%4,8(%1)\n\t" - "lw\t%5,12(%1)\n\t" - "sw\t%2,(%0)\n\t" - "sw\t%3,4(%0)\n\t" - "sw\t%4,8(%0)\n\t" - "sw\t%5,12(%0)\n\t" - "lw\t%2,16(%1)\n\t" - "lw\t%3,20(%1)\n\t" - "lw\t%4,24(%1)\n\t" - "lw\t%5,28(%1)\n\t" - "sw\t%2,16(%0)\n\t" - "sw\t%3,20(%0)\n\t" - "sw\t%4,24(%0)\n\t" - "sw\t%5,28(%0)\n\t" - "cache\t%9,32(%0)\n\t" - "daddiu\t%0,64\n\t" - "daddiu\t%1,64\n\t" - "lw\t%2,-32(%1)\n\t" - "lw\t%3,-28(%1)\n\t" - "lw\t%4,-24(%1)\n\t" - "lw\t%5,-20(%1)\n\t" - "sw\t%2,-32(%0)\n\t" - "sw\t%3,-28(%0)\n\t" - "sw\t%4,-24(%0)\n\t" - "sw\t%5,-20(%0)\n\t" - "lw\t%2,-16(%1)\n\t" - "lw\t%3,-12(%1)\n\t" - "lw\t%4,-8(%1)\n\t" - "lw\t%5,-4(%1)\n\t" - "sw\t%2,-16(%0)\n\t" - "sw\t%3,-12(%0)\n\t" - "sw\t%4,-8(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sw\t%5,-4(%0)\n\t" - ".set\tmips0\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (dummy1), "=r" (dummy2), - "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4) - :"0" (to), "1" (from), - "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_D)); -} - - -/* - * If you think for one second that this stuff coming up is a lot - * of bulky code eating too many kernel cache lines. Think _again_. - * - * Consider: - * 1) Taken branches have a 3 cycle penalty on R4k - * 2) The branch itself is a real dead cycle on even R4600/R5000. - * 3) Only one of the following variants of each type is even used by - * the kernel based upon the cache parameters we detect at boot time. - * - * QED. - */ - -static inline void r5432_flush_cache_all_d32i32(void) -{ - blast_dcache32(); blast_icache32(); -} - -static void r5432_flush_cache_range_d32i32(struct vm_area_struct *vma, - unsigned long start, - unsigned long end) -{ - struct mm_struct *mm = vma->vm_mm; - - if (mm->context != 0) { -#ifdef DEBUG_CACHE - printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); -#endif - blast_dcache32(); blast_icache32(); - } -} - -/* - * On architectures like the Sparc, we could get rid of lines in - * the cache created only by a certain context, but on the MIPS - * (and actually certain Sparc's) we cannot. - */ -static void r5432_flush_cache_mm_d32i32(struct mm_struct *mm) -{ - if (mm->context != 0) { -#ifdef DEBUG_CACHE - printk("cmm[%d]", (int)mm->context); -#endif - r5432_flush_cache_all_d32i32(); - } -} - -static void r5432_flush_cache_page_d32i32(struct vm_area_struct *vma, - unsigned long page) -{ - struct mm_struct *mm = vma->vm_mm; - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - - /* - * If ownes no valid ASID yet, cannot possibly have gotten - * this page into the cache. - */ - if (mm->context == 0) - return; - -#ifdef DEBUG_CACHE - printk("cpage[%d,%08lx]", (int)mm->context, page); -#endif - page &= PAGE_MASK; - pgdp = pgd_offset(mm, page); - pmdp = pmd_offset(pgdp, page); - ptep = pte_offset(pmdp, page); - - /* - * If the page isn't marked valid, the page cannot possibly be - * in the cache. - */ - if (!(pte_val(*ptep) & _PAGE_PRESENT)) - return; - - /* - * Doing flushes for another ASID than the current one is - * too difficult since stupid R4k caches do a TLB translation - * for every cache flush operation. So we do indexed flushes - * in that case, which doesn't overly flush the cache too much. - */ - if ((mm == current->active_mm) && (pte_val(*ptep) & _PAGE_VALID)) { - blast_dcache32_page(page); - } else { - /* - * Do indexed flush, too much work to get the (possible) - * tlb refills to work correctly. - */ - page = (KSEG0 + (page & (dcache_size - 1))); - blast_dcache32_page_indexed(page); - } -} - - -/* If the addresses passed to these routines are valid, they are - * either: - * - * 1) In KSEG0, so we can do a direct flush of the page. - * 2) In KSEG2, and since every process can translate those - * addresses all the time in kernel mode we can do a direct - * flush. - * 3) In KSEG1, no flush necessary. - */ -static void r5432_flush_page_to_ram_d32(struct page *page) -{ - blast_dcache32_page((unsigned long)page_address(page)); -} - -static void -r5432_flush_icache_range(unsigned long start, unsigned long end) -{ - r5432_flush_cache_all_d32i32(); -} - -/* - * Ok, this seriously sucks. We use them to flush a user page but don't - * know the virtual address, so we have to blast away the whole icache - * which is significantly more expensive than the real thing. - */ -static void -r5432_flush_icache_page_i32(struct vm_area_struct *vma, struct page *page) -{ - if (!(vma->vm_flags & VM_EXEC)) - return; - - r5432_flush_cache_all_d32i32(); -} - -/* - * Writeback and invalidate the primary cache dcache before DMA. - */ -static void -r5432_dma_cache_wback_inv_pc(unsigned long addr, unsigned long size) -{ - unsigned long end, a; - - if (size >= dcache_size) { - flush_cache_all(); - } else { - a = addr & ~(dc_lsize - 1); - end = (addr + size) & ~(dc_lsize - 1); - while (1) { - flush_dcache_line(a); /* Hit_Writeback_Inv_D */ - if (a == end) break; - a += dc_lsize; - } - } - bc_wback_inv(addr, size); -} - -static void -r5432_dma_cache_inv_pc(unsigned long addr, unsigned long size) -{ - unsigned long end, a; - - if (size >= dcache_size) { - flush_cache_all(); - } else { - a = addr & ~(dc_lsize - 1); - end = (addr + size) & ~(dc_lsize - 1); - while (1) { - flush_dcache_line(a); /* Hit_Writeback_Inv_D */ - if (a == end) break; - a += dc_lsize; - } - } - - bc_inv(addr, size); -} - -static void -r5432_dma_cache_wback(unsigned long addr, unsigned long size) -{ - panic("r5432_dma_cache called - should not happen.\n"); -} - -/* - * While we're protected against bad userland addresses we don't care - * very much about what happens in that case. Usually a segmentation - * fault will dump the process later on anyway ... - */ -static void r5432_flush_cache_sigtramp(unsigned long addr) -{ - protected_writeback_dcache_line(addr & ~(dc_lsize - 1)); - protected_flush_icache_line(addr & ~(ic_lsize - 1)); -} - -#undef DEBUG_TLB -#undef DEBUG_TLBUPDATE - -#define NTLB_ENTRIES 48 /* Fixed on all R4XX0 variants... */ - -#define NTLB_ENTRIES_HALF 24 /* Fixed on all R4XX0 variants... */ - -void flush_tlb_all(void) -{ - unsigned long old_ctx; - int entry; - unsigned long flags; - -#ifdef DEBUG_TLB - printk("[tlball]"); -#endif - - local_irq_save(flags); - /* Save old context and create impossible VPN2 value */ - old_ctx = (get_entryhi() & 0xff); - set_entryhi(KSEG0); - set_entrylo0(0); - set_entrylo1(0); - BARRIER; - - entry = get_wired(); - - /* Blast 'em all away. */ - while(entry < NTLB_ENTRIES) { - set_index(entry); - BARRIER; - tlb_write_indexed(); - BARRIER; - entry++; - } - BARRIER; - set_entryhi(old_ctx); - local_irq_restore(flags); -} - -void flush_tlb_mm(struct mm_struct *mm) -{ - if (mm->context != 0) { - unsigned long flags; - -#ifdef DEBUG_TLB - printk("[tlbmm<%d>]", mm->context); -#endif - local_irq_save(flags); - get_new_mmu_context(mm, asid_cache); - if (mm == current->active_mm) - set_entryhi(mm->context & 0xff); - local_irq_restore(flags); - } -} - -void flush_tlb_range(struct mm_struct *mm, unsigned long start, - unsigned long end) -{ - if(mm->context != 0) { - unsigned long flags; - int size; - -#ifdef DEBUG_TLB - printk("[tlbrange<%02x,%08lx,%08lx>]", (mm->context & 0xff), - start, end); -#endif - local_irq_save(flags); - size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; - size = (size + 1) >> 1; - if(size <= NTLB_ENTRIES_HALF) { - int oldpid = (get_entryhi() & 0xff); - int newpid = (mm->context & 0xff); - - start &= (PAGE_MASK << 1); - end += ((PAGE_SIZE << 1) - 1); - end &= (PAGE_MASK << 1); - while(start < end) { - int idx; - - set_entryhi(start | newpid); - start += (PAGE_SIZE << 1); - BARRIER; - tlb_probe(); - BARRIER; - idx = get_index(); - set_entrylo0(0); - set_entrylo1(0); - set_entryhi(KSEG0); - BARRIER; - if(idx < 0) - continue; - tlb_write_indexed(); - BARRIER; - } - set_entryhi(oldpid); - } else { - get_new_mmu_context(mm, asid_cache); - if (mm == current->active_mm) - set_entryhi(mm->context & 0xff); - } - local_irq_restore(flags); - } -} - -void flush_tlb_page(struct vm_area_struct *vma, unsigned long page) -{ - if (vma->vm_mm->context != 0) { - unsigned long flags; - int oldpid, newpid, idx; - -#ifdef DEBUG_TLB - printk("[tlbpage<%d,%08lx>]", vma->vm_mm->context, page); -#endif - newpid = (vma->vm_mm->context & 0xff); - page &= (PAGE_MASK << 1); - local_irq_save(flags); - oldpid = (get_entryhi() & 0xff); - set_entryhi(page | newpid); - BARRIER; - tlb_probe(); - BARRIER; - idx = get_index(); - set_entrylo0(0); - set_entrylo1(0); - set_entryhi(KSEG0); - if(idx < 0) - goto finish; - BARRIER; - tlb_write_indexed(); - - finish: - BARRIER; - set_entryhi(oldpid); - local_irq_restore(flags); - } -} - -void pgd_init(unsigned long page) -{ - unsigned long *p = (unsigned long *) page; - int i; - - for(i = 0; i < USER_PTRS_PER_PGD; i+=8) { - p[i + 0] = (unsigned long) invalid_pte_table; - p[i + 1] = (unsigned long) invalid_pte_table; - p[i + 2] = (unsigned long) invalid_pte_table; - p[i + 3] = (unsigned long) invalid_pte_table; - p[i + 4] = (unsigned long) invalid_pte_table; - p[i + 5] = (unsigned long) invalid_pte_table; - p[i + 6] = (unsigned long) invalid_pte_table; - p[i + 7] = (unsigned long) invalid_pte_table; - } -} - -/* We will need multiple versions of update_mmu_cache(), one that just - * updates the TLB with the new pte(s), and another which also checks - * for the R4k "end of page" hardware bug and does the needy. - */ -void update_mmu_cache(struct vm_area_struct * vma, - unsigned long address, pte_t pte) -{ - unsigned long flags; - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - int idx, pid; - - /* - * Handle debugger faulting in for debugee. - */ - if (current->active_mm != vma->vm_mm) - return; - - pid = get_entryhi() & 0xff; - -#ifdef DEBUG_TLB - if((pid != (vma->vm_mm->context & 0xff)) || (vma->vm_mm->context == 0)) { - printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%d tlbpid=%d\n", - (int) (vma->vm_mm->context & 0xff), pid); - } -#endif - - local_irq_save(flags); - address &= (PAGE_MASK << 1); - set_entryhi(address | (pid)); - pgdp = pgd_offset(vma->vm_mm, address); - BARRIER; - tlb_probe(); - BARRIER; - pmdp = pmd_offset(pgdp, address); - idx = get_index(); - ptep = pte_offset(pmdp, address); - BARRIER; - set_entrylo0(pte_val(*ptep++) >> 6); - set_entrylo1(pte_val(*ptep) >> 6); - set_entryhi(address | (pid)); - BARRIER; - if(idx < 0) { - tlb_write_random(); - } else { - tlb_write_indexed(); - } - BARRIER; - set_entryhi(pid); - BARRIER; - local_irq_restore(flags); -} - -void show_regs(struct pt_regs * regs) -{ - /* Saved main processor registers. */ - printk("$0 : %08lx %08lx %08lx %08lx\n", - 0UL, regs->regs[1], regs->regs[2], regs->regs[3]); - printk("$4 : %08lx %08lx %08lx %08lx\n", - regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]); - printk("$8 : %08lx %08lx %08lx %08lx\n", - regs->regs[8], regs->regs[9], regs->regs[10], regs->regs[11]); - printk("$12: %08lx %08lx %08lx %08lx\n", - regs->regs[12], regs->regs[13], regs->regs[14], regs->regs[15]); - printk("$16: %08lx %08lx %08lx %08lx\n", - regs->regs[16], regs->regs[17], regs->regs[18], regs->regs[19]); - printk("$20: %08lx %08lx %08lx %08lx\n", - regs->regs[20], regs->regs[21], regs->regs[22], regs->regs[23]); - printk("$24: %08lx %08lx\n", - regs->regs[24], regs->regs[25]); - printk("$28: %08lx %08lx %08lx %08lx\n", - regs->regs[28], regs->regs[29], regs->regs[30], regs->regs[31]); - - /* Saved cp0 registers. */ - printk("epc : %08lx %s\nStatus: %08lx\nCause : %08lx\n", - regs->cp0_epc, print_tainted(), regs->cp0_status, regs->cp0_cause); -} - -void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, - unsigned long entryhi, unsigned long pagemask) -{ - unsigned long flags; - unsigned long wired; - unsigned long old_pagemask; - unsigned long old_ctx; - - local_irq_save(flags); - /* Save old context and create impossible VPN2 value */ - old_ctx = (get_entryhi() & 0xff); - old_pagemask = get_pagemask(); - wired = get_wired(); - set_wired (wired + 1); - set_index (wired); - BARRIER; - set_pagemask (pagemask); - set_entryhi(entryhi); - set_entrylo0(entrylo0); - set_entrylo1(entrylo1); - BARRIER; - tlb_write_indexed(); - BARRIER; - - set_entryhi(old_ctx); - BARRIER; - set_pagemask (old_pagemask); - flush_tlb_all(); - local_irq_restore(flags); -} - -/* Detect and size the various r4k caches. */ -static void __init probe_icache(unsigned long config) -{ - icache_size = 1 << (12 + ((config >> 9) & 7)); - ic_lsize = 16 << ((config >> 5) & 1); - - printk("Primary instruction cache %dkb, linesize %d bytes.\n", - icache_size >> 10, ic_lsize); -} - -static void __init probe_dcache(unsigned long config) -{ - dcache_size = 1 << (12 + ((config >> 6) & 7)); - dc_lsize = 16 << ((config >> 4) & 1); - - printk("Primary data cache %dkb, linesize %d bytes.\n", - dcache_size >> 10, dc_lsize); -} - - -void __init ld_mmu_r5432(void) -{ - unsigned long config = read_32bit_cp0_register(CP0_CONFIG); - - printk("CPU revision is: %08x\n", read_32bit_cp0_register(CP0_PRID)); - - change_cp0_config(CONF_CM_CMASK, CONF_CM_CACHABLE_NONCOHERENT); - - probe_icache(config); - probe_dcache(config); - - _clear_page = r5432_clear_page_d32; - _copy_page = r5432_copy_page_d32; - _flush_cache_all = r5432_flush_cache_all_d32i32; - ___flush_cache_all = r5432_flush_cache_all_d32i32; - _flush_page_to_ram = r5432_flush_page_to_ram_d32; - _flush_cache_mm = r5432_flush_cache_mm_d32i32; - _flush_cache_range = r5432_flush_cache_range_d32i32; - _flush_cache_page = r5432_flush_cache_page_d32i32; - _flush_icache_page = r5432_flush_icache_page_i32; - _dma_cache_wback_inv = r5432_dma_cache_wback_inv_pc; - _dma_cache_wback = r5432_dma_cache_wback; - _dma_cache_inv = r5432_dma_cache_inv_pc; - - _flush_cache_sigtramp = r5432_flush_cache_sigtramp; - _flush_icache_range = r5432_flush_icache_range; /* Ouch */ - - __flush_cache_all(); - write_32bit_cp0_register(CP0_WIRED, 0); - - /* - * You should never change this register: - * - On R4600 1.7 the tlbp never hits for pages smaller than - * the value in the c0_pagemask register. - * - The entire mm handling assumes the c0_pagemask register to - * be set for 4kb pages. - */ - write_32bit_cp0_register(CP0_PAGEMASK, PM_4K); - flush_tlb_all(); -} diff -Nru a/arch/mips/mm/rm7k.c b/arch/mips/mm/rm7k.c --- a/arch/mips/mm/rm7k.c Tue Jul 1 18:44:31 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,751 +0,0 @@ -/* - * 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. - * - * r4xx0.c: R4000 processor variant specific MMU/Cache routines. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * Copyright (C) 1997, 1998 Ralf Baechle ralf@gnu.org - * - * To do: - * - * - this code is a overbloated pig - * - many of the bug workarounds are not efficient at all, but at - * least they are functional ... - */ -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -/* CP0 hazard avoidance. */ -#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \ - "nop; nop; nop; nop; nop; nop;\n\t" \ - ".set reorder\n\t") - -/* Primary cache parameters. */ -static int icache_size, dcache_size; /* Size in bytes */ - -#define ic_lsize 32 /* Fixed to 32 byte on RM7000 */ -#define dc_lsize 32 /* Fixed to 32 byte on RM7000 */ -#define sc_lsize 32 /* Fixed to 32 byte on RM7000 */ -#define tc_pagesize (32*128) - -/* Secondary cache parameters. */ -#define scache_size (256*1024) /* Fixed to 256KiB on RM7000 */ - -#include -#include - -int rm7k_tcache_enabled = 0; - -/* - * Not added to asm/r4kcache.h because it seems to be RM7000-specific. - */ -#define Page_Invalidate_T 0x16 - -static inline void invalidate_tcache_page(unsigned long addr) -{ - __asm__ __volatile__( - ".set\tnoreorder\t\t\t# invalidate_tcache_page\n\t" - ".set\tmips3\n\t" - "cache\t%1, (%0)\n\t" - ".set\tmips0\n\t" - ".set\treorder" - : - : "r" (addr), - "i" (Page_Invalidate_T)); -} - -/* - * Zero an entire page. Note that while the RM7000 has a second level cache - * it doesn't have a Create_Dirty_Excl_SD operation. - */ -static void rm7k_clear_page(void * page) -{ - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - ".set\tmips3\n\t" - "daddiu\t$1,%0,%2\n" - "1:\tcache\t%3,(%0)\n\t" - "sd\t$0,(%0)\n\t" - "sd\t$0,8(%0)\n\t" - "sd\t$0,16(%0)\n\t" - "sd\t$0,24(%0)\n\t" - "daddiu\t%0,64\n\t" - "cache\t%3,-32(%0)\n\t" - "sd\t$0,-32(%0)\n\t" - "sd\t$0,-24(%0)\n\t" - "sd\t$0,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sd\t$0,-8(%0)\n\t" - ".set\tmips0\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (page) - :"0" (page), - "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_D) - :"$1","memory"); -} - - -/* - * Copy an entire page. Note that while the RM7000 has a second level cache - * it doesn't have a Create_Dirty_Excl_SD operation. - */ -static void rm7k_copy_page(void * to, void * from) -{ - unsigned long dummy1, dummy2; - unsigned long reg1, reg2, reg3, reg4; - - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - ".set\tmips3\n\t" - "daddiu\t$1,%0,%8\n" - "1:\tcache\t%9,(%0)\n\t" - "lw\t%2,(%1)\n\t" - "lw\t%3,4(%1)\n\t" - "lw\t%4,8(%1)\n\t" - "lw\t%5,12(%1)\n\t" - "sw\t%2,(%0)\n\t" - "sw\t%3,4(%0)\n\t" - "sw\t%4,8(%0)\n\t" - "sw\t%5,12(%0)\n\t" - "lw\t%2,16(%1)\n\t" - "lw\t%3,20(%1)\n\t" - "lw\t%4,24(%1)\n\t" - "lw\t%5,28(%1)\n\t" - "sw\t%2,16(%0)\n\t" - "sw\t%3,20(%0)\n\t" - "sw\t%4,24(%0)\n\t" - "sw\t%5,28(%0)\n\t" - "cache\t%9,32(%0)\n\t" - "daddiu\t%0,64\n\t" - "daddiu\t%1,64\n\t" - "lw\t%2,-32(%1)\n\t" - "lw\t%3,-28(%1)\n\t" - "lw\t%4,-24(%1)\n\t" - "lw\t%5,-20(%1)\n\t" - "sw\t%2,-32(%0)\n\t" - "sw\t%3,-28(%0)\n\t" - "sw\t%4,-24(%0)\n\t" - "sw\t%5,-20(%0)\n\t" - "lw\t%2,-16(%1)\n\t" - "lw\t%3,-12(%1)\n\t" - "lw\t%4,-8(%1)\n\t" - "lw\t%5,-4(%1)\n\t" - "sw\t%2,-16(%0)\n\t" - "sw\t%3,-12(%0)\n\t" - "sw\t%4,-8(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sw\t%5,-4(%0)\n\t" - ".set\tmips0\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (dummy1), "=r" (dummy2), - "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4) - :"0" (to), "1" (from), - "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_D)); -} - -static void __flush_cache_all_d32i32(void) -{ - blast_dcache32(); - blast_icache32(); -} - -static inline void rm7k_flush_cache_all_d32i32(void) -{ - /* Yes! Caches that don't suck ... */ -} - -static void rm7k_flush_cache_range_d32i32(struct vm_area_struct *vma, - unsigned long start, - unsigned long end) -{ - /* RM7000 caches are sane ... */ -} - -static void rm7k_flush_cache_mm_d32i32(struct mm_struct *mm) -{ - /* RM7000 caches are sane ... */ -} - -static void rm7k_flush_cache_page_d32i32(struct vm_area_struct *vma, - unsigned long page) -{ - /* RM7000 caches are sane ... */ -} - -static void rm7k_flush_page_to_ram_d32i32(struct page * page) -{ - /* Yes! Caches that don't suck! */ -} - -static void rm7k_flush_icache_range(unsigned long start, unsigned long end) -{ - /* - * FIXME: This is overdoing things and harms performance. - */ - __flush_cache_all_d32i32(); -} - -static void rm7k_flush_icache_page(struct vm_area_struct *vma, - struct page *page) -{ - /* - * FIXME: We should not flush the entire cache but establish some - * temporary mapping and use hit_invalidate operation to flush out - * the line from the cache. - */ - __flush_cache_all_d32i32(); -} - - -/* - * Writeback and invalidate the primary cache dcache before DMA. - * (XXX These need to be fixed ...) - */ -static void -rm7k_dma_cache_wback_inv(unsigned long addr, unsigned long size) -{ - unsigned long end, a; - - a = addr & ~(sc_lsize - 1); - end = (addr + size) & ~(sc_lsize - 1); - while (1) { - flush_dcache_line(a); /* Hit_Writeback_Inv_D */ - flush_icache_line(a); /* Hit_Invalidate_I */ - flush_scache_line(a); /* Hit_Writeback_Inv_SD */ - if (a == end) break; - a += sc_lsize; - } - - if (!rm7k_tcache_enabled) - return; - - a = addr & ~(tc_pagesize - 1); - end = (addr + size) & ~(tc_pagesize - 1); - while(1) { - invalidate_tcache_page(a); /* Page_Invalidate_T */ - if (a == end) break; - a += tc_pagesize; - } -} - -static void -rm7k_dma_cache_inv(unsigned long addr, unsigned long size) -{ - unsigned long end, a; - - a = addr & ~(sc_lsize - 1); - end = (addr + size) & ~(sc_lsize - 1); - while (1) { - invalidate_dcache_line(a); /* Hit_Invalidate_D */ - flush_icache_line(a); /* Hit_Invalidate_I */ - invalidate_scache_line(a); /* Hit_Invalidate_SD */ - if (a == end) break; - a += sc_lsize; - } - - if (!rm7k_tcache_enabled) - return; - - a = addr & ~(tc_pagesize - 1); - end = (addr + size) & ~(tc_pagesize - 1); - while(1) { - invalidate_tcache_page(a); /* Page_Invalidate_T */ - if (a == end) break; - a += tc_pagesize; - } -} - -static void -rm7k_dma_cache_wback(unsigned long addr, unsigned long size) -{ - panic("rm7k_dma_cache_wback called - should not happen.\n"); -} - -/* - * While we're protected against bad userland addresses we don't care - * very much about what happens in that case. Usually a segmentation - * fault will dump the process later on anyway ... - */ -static void rm7k_flush_cache_sigtramp(unsigned long addr) -{ - protected_writeback_dcache_line(addr & ~(dc_lsize - 1)); - protected_flush_icache_line(addr & ~(ic_lsize - 1)); -} - -/* - * Undocumented RM7000: Bit 29 in the info register of the RM7000 v2.0 - * indicates if the TLB has 48 or 64 entries. - * - * 29 1 => 64 entry JTLB - * 0 => 48 entry JTLB - */ -static inline int __attribute__((const)) ntlb_entries(void) -{ - if (get_info() & (1 << 29)) - return 64; - - return 48; -} - -void flush_tlb_all(void) -{ - unsigned long flags; - unsigned long old_ctx; - int entry; - - local_irq_save(flags); - /* Save old context and create impossible VPN2 value */ - old_ctx = get_entryhi() & 0xff; - set_entryhi(KSEG0); - set_entrylo0(0); - set_entrylo1(0); - BARRIER; - - entry = get_wired(); - - /* Blast 'em all away. */ - while (entry < ntlb_entries()) { - set_index(entry); - BARRIER; - tlb_write_indexed(); - BARRIER; - entry++; - } - BARRIER; - set_entryhi(old_ctx); - local_irq_restore(flags); -} - -void flush_tlb_mm(struct mm_struct *mm) -{ - if(mm->context != 0) { - unsigned long flags; - - local_irq_save(flags); - get_new_mmu_context(mm, asid_cache); - if (mm == current->mm) - set_entryhi(mm->context & 0xff); - local_irq_restore(flags); - } -} - -void flush_tlb_range(struct mm_struct *mm, unsigned long start, - unsigned long end) -{ - if(mm->context != 0) { - unsigned long flags; - int size; - - local_irq_save(flags); - size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; - size = (size + 1) >> 1; - if (size <= (ntlb_entries() / 2)) { - int oldpid = (get_entryhi() & 0xff); - int newpid = (mm->context & 0xff); - - start &= (PAGE_MASK << 1); - end += ((PAGE_SIZE << 1) - 1); - end &= (PAGE_MASK << 1); - while(start < end) { - int idx; - - set_entryhi(start | newpid); - start += (PAGE_SIZE << 1); - BARRIER; - tlb_probe(); - BARRIER; - idx = get_index(); - set_entrylo0(0); - set_entrylo1(0); - set_entryhi(KSEG0); - BARRIER; - if(idx < 0) - continue; - tlb_write_indexed(); - BARRIER; - } - set_entryhi(oldpid); - } else { - get_new_mmu_context(mm, asid_cache); - if(mm == current->mm) - set_entryhi(mm->context & 0xff); - } - local_irq_restore(flags); - } -} - -void flush_tlb_page(struct vm_area_struct *vma, unsigned long page) -{ - if(vma->vm_mm->context != 0) { - unsigned long flags; - int oldpid, newpid, idx; - - newpid = (vma->vm_mm->context & 0xff); - page &= (PAGE_MASK << 1); - local_irq_save(flags); - oldpid = (get_entryhi() & 0xff); - set_entryhi(page | newpid); - BARRIER; - tlb_probe(); - BARRIER; - idx = get_index(); - set_entrylo0(0); - set_entrylo1(0); - set_entryhi(KSEG0); - if(idx < 0) - goto finish; - BARRIER; - tlb_write_indexed(); - - finish: - BARRIER; - set_entryhi(oldpid); - local_irq_restore(flags); - } -} - -void pgd_init(unsigned long page) -{ - unsigned long *p = (unsigned long *) page; - int i; - - for (i = 0; i < USER_PTRS_PER_PGD; i+=8) { - p[i + 0] = (unsigned long) invalid_pte_table; - p[i + 1] = (unsigned long) invalid_pte_table; - p[i + 2] = (unsigned long) invalid_pte_table; - p[i + 3] = (unsigned long) invalid_pte_table; - p[i + 4] = (unsigned long) invalid_pte_table; - p[i + 5] = (unsigned long) invalid_pte_table; - p[i + 6] = (unsigned long) invalid_pte_table; - p[i + 7] = (unsigned long) invalid_pte_table; - } -} - -/* - * We will need multiple versions of update_mmu_cache(), one that just - * updates the TLB with the new pte(s), and another which also checks - * for the R4k "end of page" hardware bug and does the needy. - */ -void update_mmu_cache(struct vm_area_struct * vma, - unsigned long address, pte_t pte) -{ - unsigned long flags; - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - int idx, pid; - - /* - * Handle debugger faulting in for debugee. - */ - if (current->active_mm != vma->vm_mm) - return; - - pid = get_entryhi() & 0xff; - - local_irq_save(flags); - address &= (PAGE_MASK << 1); - set_entryhi(address | (pid)); - pgdp = pgd_offset(vma->vm_mm, address); - BARRIER; - tlb_probe(); - BARRIER; - pmdp = pmd_offset(pgdp, address); - idx = get_index(); - ptep = pte_offset(pmdp, address); - BARRIER; - set_entrylo0(pte_val(*ptep++) >> 6); - set_entrylo1(pte_val(*ptep) >> 6); - set_entryhi(address | (pid)); - BARRIER; - if (idx < 0) { - tlb_write_random(); - } else { - tlb_write_indexed(); - } - BARRIER; - set_entryhi(pid); - BARRIER; - local_irq_restore(flags); -} - -void show_regs(struct pt_regs * regs) -{ - /* Saved main processor registers. */ - printk(KERN_INFO "$0 : %08lx %08lx %08lx %08lx\n", - 0UL, regs->regs[1], regs->regs[2], regs->regs[3]); - printk(KERN_INFO "$4 : %08lx %08lx %08lx %08lx\n", - regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]); - printk(KERN_INFO "$8 : %08lx %08lx %08lx %08lx\n", - regs->regs[8], regs->regs[9], regs->regs[10], regs->regs[11]); - printk(KERN_INFO "$12: %08lx %08lx %08lx %08lx\n", - regs->regs[12], regs->regs[13], regs->regs[14], regs->regs[15]); - printk(KERN_INFO "$16: %08lx %08lx %08lx %08lx\n", - regs->regs[16], regs->regs[17], regs->regs[18], regs->regs[19]); - printk(KERN_INFO "$20: %08lx %08lx %08lx %08lx\n", - regs->regs[20], regs->regs[21], regs->regs[22], regs->regs[23]); - printk(KERN_INFO "$24: %08lx %08lx\n", - regs->regs[24], regs->regs[25]); - printk(KERN_INFO "$28: %08lx %08lx %08lx %08lx\n", - regs->regs[28], regs->regs[29], regs->regs[30], regs->regs[31]); - - /* Saved cp0 registers. */ - printk(KERN_INFO "epc : %08lx %s\nStatus: %08lx\nCause : %08lx\n", - regs->cp0_epc, print_tainted(), regs->cp0_status, regs->cp0_cause); -} - -void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, - unsigned long entryhi, unsigned long pagemask) -{ - unsigned long flags; - unsigned long wired; - unsigned long old_pagemask; - unsigned long old_ctx; - - local_irq_save(flags); - /* Save old context and create impossible VPN2 value */ - old_ctx = (get_entryhi() & 0xff); - old_pagemask = get_pagemask(); - wired = get_wired(); - set_wired (wired + 1); - set_index (wired); - BARRIER; - set_pagemask (pagemask); - set_entryhi(entryhi); - set_entrylo0(entrylo0); - set_entrylo1(entrylo1); - BARRIER; - tlb_write_indexed(); - BARRIER; - - set_entryhi(old_ctx); - BARRIER; - set_pagemask (old_pagemask); - flush_tlb_all(); - local_irq_restore(flags); -} - -/* Used for loading TLB entries before trap_init() has started, when we - don't actually want to add a wired entry which remains throughout the - lifetime of the system */ - -static int temp_tlb_entry __initdata; - -__init int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1, - unsigned long entryhi, unsigned long pagemask) -{ - int ret = 0; - unsigned long flags; - unsigned long wired; - unsigned long old_pagemask; - unsigned long old_ctx; - - local_irq_save(flags); - /* Save old context and create impossible VPN2 value */ - old_ctx = (get_entryhi() & 0xff); - old_pagemask = get_pagemask(); - wired = get_wired(); - if (--temp_tlb_entry < wired) { - printk(KERN_WARNING "No TLB space left for add_temporary_entry\n"); - ret = -ENOSPC; - goto out; - } - - set_index (temp_tlb_entry); - BARRIER; - set_pagemask (pagemask); - set_entryhi(entryhi); - set_entrylo0(entrylo0); - set_entrylo1(entrylo1); - BARRIER; - tlb_write_indexed(); - BARRIER; - - set_entryhi(old_ctx); - BARRIER; - set_pagemask (old_pagemask); - out: - local_irq_restore(flags); - return ret; -} - - - -/* Detect and size the caches. */ -static inline void probe_icache(unsigned long config) -{ - icache_size = 1 << (12 + ((config >> 9) & 7)); - - printk(KERN_INFO "Primary instruction cache %dKiB.\n", icache_size >> 10); -} - -static inline void probe_dcache(unsigned long config) -{ - dcache_size = 1 << (12 + ((config >> 6) & 7)); - - printk(KERN_INFO "Primary data cache %dKiB.\n", dcache_size >> 10); -} - - -/* - * This function is executed in the uncached segment KSEG1. - * It must not touch the stack, because the stack pointer still points - * into KSEG0. - * - * Three options: - * - Write it in assembly and guarantee that we don't use the stack. - * - Disable caching for KSEG0 before calling it. - * - Pray that GCC doesn't randomly start using the stack. - * - * This being Linux, we obviously take the least sane of those options - - * following DaveM's lead in r4xx0.c - * - * It seems we get our kicks from relying on unguaranteed behaviour in GCC - */ -static __init void setup_scache(void) -{ - int register i; - - set_cp0_config(1<<3 /* CONF_SE */); - - set_taglo(0); - set_taghi(0); - - for (i=0; i> 31) & 1) - return; - - printk(KERN_INFO "Secondary cache %dKiB, linesize %d bytes.\n", - (scache_size >> 10), sc_lsize); - - if ((config >> 3) & 1) - return; - - printk(KERN_INFO "Enabling secondary cache..."); - func(); - printk("Done\n"); -} - -static inline void probe_tcache(unsigned long config) -{ - if ((config >> 17) & 1) - return; - - /* We can't enable the L3 cache yet. There may be board-specific - * magic necessary to turn it on, and blindly asking the CPU to - * start using it would may give cache errors. - * - * Also, board-specific knowledge may allow us to use the - * CACHE Flash_Invalidate_T instruction if the tag RAM supports - * it, and may specify the size of the L3 cache so we don't have - * to probe it. - */ - printk(KERN_INFO "Tertiary cache present, %s enabled\n", - config&(1<<12) ? "already" : "not (yet)"); - - if ((config >> 12) & 1) - rm7k_tcache_enabled = 1; -} - -void __init ld_mmu_rm7k(void) -{ - unsigned long config = read_32bit_cp0_register(CP0_CONFIG); - unsigned long addr; - - printk("CPU revision is: %08x\n", read_32bit_cp0_register(CP0_PRID)); - - change_cp0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); - - /* RM7000 erratum #31. The icache is screwed at startup. */ - set_taglo(0); - set_taghi(0); - for (addr = KSEG0; addr <= KSEG0 + 4096; addr += ic_lsize) { - __asm__ __volatile__ ( - ".set noreorder\n\t" - ".set mips3\n\t" - "cache\t%1, 0(%0)\n\t" - "cache\t%1, 0x1000(%0)\n\t" - "cache\t%1, 0x2000(%0)\n\t" - "cache\t%1, 0x3000(%0)\n\t" - "cache\t%2, 0(%0)\n\t" - "cache\t%2, 0x1000(%0)\n\t" - "cache\t%2, 0x2000(%0)\n\t" - "cache\t%2, 0x3000(%0)\n\t" - "cache\t%1, 0(%0)\n\t" - "cache\t%1, 0x1000(%0)\n\t" - "cache\t%1, 0x2000(%0)\n\t" - "cache\t%1, 0x3000(%0)\n\t" - ".set\tmips0\n\t" - ".set\treorder\n\t" - : - : "r" (addr), "i" (Index_Store_Tag_I), "i" (Fill)); - } - -#ifndef CONFIG_MIPS_UNCACHED - change_cp0_config(CONF_CM_CMASK, CONF_CM_CACHABLE_NONCOHERENT); -#endif - - probe_icache(config); - probe_dcache(config); - probe_scache(config); - probe_tcache(config); - - printk("TLB has %d entries.\n", ntlb_entries()); - - _clear_page = rm7k_clear_page; - _copy_page = rm7k_copy_page; - - _flush_cache_all = rm7k_flush_cache_all_d32i32; - ___flush_cache_all = __flush_cache_all_d32i32; - _flush_cache_mm = rm7k_flush_cache_mm_d32i32; - _flush_cache_range = rm7k_flush_cache_range_d32i32; - _flush_cache_page = rm7k_flush_cache_page_d32i32; - _flush_page_to_ram = rm7k_flush_page_to_ram_d32i32; - _flush_cache_sigtramp = rm7k_flush_cache_sigtramp; - _flush_icache_range = rm7k_flush_icache_range; - _flush_icache_page = rm7k_flush_icache_page; - - _dma_cache_wback_inv = rm7k_dma_cache_wback_inv; - _dma_cache_wback = rm7k_dma_cache_wback; - _dma_cache_inv = rm7k_dma_cache_inv; - - __flush_cache_all_d32i32(); - write_32bit_cp0_register(CP0_WIRED, 0); - temp_tlb_entry = ntlb_entries() - 1; - write_32bit_cp0_register(CP0_PAGEMASK, PM_4K); - flush_tlb_all(); -} diff -Nru a/arch/mips/mm/sb1.c b/arch/mips/mm/sb1.c --- a/arch/mips/mm/sb1.c Tue Jul 1 18:44:31 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,436 +0,0 @@ -/* - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * Copyright (C) 1997, 2001 Ralf Baechle (ralf@gnu.org) - * Copyright (C) 2000 Sibyte - * - * Written by Justin Carlson (carlson@sibyte.com) - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - - -/* - * In this entire file, I'm not sure what the role of the L2 on the sb1250 - * is. Since it is coherent to the system, we should never need to flush - * it...right?...right??? -JDC - */ - -#include - -/* These are probed at ld_mmu time */ -static unsigned int icache_size; -static unsigned int dcache_size; - -static unsigned int icache_line_size; -static unsigned int dcache_line_size; - -static unsigned int icache_assoc; -static unsigned int dcache_assoc; - -static unsigned int icache_sets; -static unsigned int dcache_sets; -static unsigned int tlb_entries; - -void pgd_init(unsigned long page) -{ - unsigned long *p = (unsigned long *) page; - int i; - - for (i = 0; i < USER_PTRS_PER_PGD; i+=8) { - p[i + 0] = (unsigned long) invalid_pte_table; - p[i + 1] = (unsigned long) invalid_pte_table; - p[i + 2] = (unsigned long) invalid_pte_table; - p[i + 3] = (unsigned long) invalid_pte_table; - p[i + 4] = (unsigned long) invalid_pte_table; - p[i + 5] = (unsigned long) invalid_pte_table; - p[i + 6] = (unsigned long) invalid_pte_table; - p[i + 7] = (unsigned long) invalid_pte_table; - } -} - -void flush_tlb_all(void) -{ - unsigned long flags; - unsigned long old_ctx; - int entry; - - local_irq_save(flags); - /* Save old context and create impossible VPN2 value */ - old_ctx = (get_entryhi() & 0xff); - set_entrylo0(0); - set_entrylo1(0); - for (entry = 0; entry < tlb_entries; entry++) { - set_entryhi(KSEG0 + (PAGE_SIZE << 1) * entry); - set_index(entry); - tlb_write_indexed(); - } - set_entryhi(old_ctx); - local_irq_restore(flags); -} - - - -/* These are the functions hooked by the memory management function pointers */ -static void sb1_clear_page(void *page) -{ - /* JDCXXX - This should be bottlenecked by the write buffer, but these - things tend to be mildly unpredictable...should check this on the - performance model */ - - /* We prefetch 4 lines ahead. We're also "cheating" slightly here... - since we know we're on an SB1, we force the assembler to take - 64-bit operands to speed things up */ - __asm__ __volatile__( - ".set push \n" - ".set noreorder \n" - ".set noat \n" - ".set mips4 \n" - " addiu $1, %0, %2 \n" /* Calculate the end of the page to clear */ - " pref 5, 0(%0) \n" /* Prefetch the first 4 lines */ - " pref 5, 32(%0) \n" - " pref 5, 64(%0) \n" - " pref 5, 96(%0) \n" - "1: sd $0, 0(%0) \n" /* Throw out a cacheline of 0's */ - " sd $0, 8(%0) \n" - " sd $0, 16(%0) \n" - " sd $0, 24(%0) \n" - " pref 5,128(%0) \n" /* Prefetch 4 lines ahead */ - " bne $1, %0, 1b \n" - " addiu %0, %0, 32 \n" /* Next cacheline (This instruction better be short piped!) */ - ".set pop \n" - :"=r" (page) - :"0" (page), - "I" (PAGE_SIZE-32) - :"$1","memory"); - -} - -static void sb1_copy_page(void *to, void *from) -{ - - /* This should be optimized in assembly...can't use ld/sd, though, - * because the top 32 bits could be nuked if we took an interrupt - * during the routine. And this is not a good place to be cli()'ing - */ - - /* The pref's used here are using "streaming" hints, which cause the - * copied data to be kicked out of the cache sooner. A page copy often - * ends up copying a lot more data than is commonly used, so this seems - * to make sense in terms of reducing cache pollution, but I've no real - * performance data to back this up - */ - - __asm__ __volatile__( - ".set push \n" - ".set noreorder \n" - ".set noat \n" - ".set mips4 \n" - " addiu $1, %0, %4 \n" /* Calculate the end of the page to copy */ - " pref 4, 0(%0) \n" /* Prefetch the first 3 lines to be read and copied */ - " pref 5, 0(%1) \n" - " pref 4, 32(%0) \n" - " pref 5, 32(%1) \n" - " pref 4, 64(%0) \n" - " pref 5, 64(%1) \n" - "1: lw $2, 0(%0) \n" /* Block copy a cacheline */ - " lw $3, 4(%0) \n" - " lw $4, 8(%0) \n" - " lw $5, 12(%0) \n" - " lw $6, 16(%0) \n" - " lw $7, 20(%0) \n" - " lw $8, 24(%0) \n" - " lw $9, 28(%0) \n" - " pref 4, 96(%0) \n" /* Prefetch ahead */ - " pref 5, 96(%1) \n" - " sw $2, 0(%1) \n" - " sw $3, 4(%1) \n" - " sw $4, 8(%1) \n" - " sw $5, 12(%1) \n" - " sw $6, 16(%1) \n" - " sw $7, 20(%1) \n" - " sw $8, 24(%1) \n" - " sw $9, 28(%1) \n" - " addiu %1, %1, 32 \n" /* Next cacheline */ - " nop \n" /* Force next add to short pipe */ - " nop \n" /* Force next add to short pipe */ - " bne $1, %0, 1b \n" - " addiu %0, %0, 32 \n" /* Next cacheline */ - ".set pop \n" - :"=r" (to), - "=r" (from) - : - "0" (from), - "1" (to), - "I" (PAGE_SIZE-32) - :"$1","$2","$3","$4","$5","$6","$7","$8","$9","memory"); -/* - unsigned long *src = from; - unsigned long *dest = to; - unsigned long *target = (unsigned long *) (((unsigned long)src) + PAGE_SIZE); - while (src != target) { - *dest++ = *src++; - } -*/ -} - -/* - * The dcache is fully coherent to the system, with one - * big caveat: the instruction stream. In other words, - * if we miss in the icache, and have dirty data in the - * L1 dcache, then we'll go out to memory (or the L2) and - * get the not-as-recent data. - * - * So the only time we have to flush the dcache is when - * we're flushing the icache. Since the L2 is fully - * coherent to everything, including I/O, we never have - * to flush it - */ - -static void sb1_flush_cache_all(void) -{ - - /* - * Haven't worried too much about speed here; given that we're flushing - * the icache, the time to invalidate is dwarfed by the time it's going - * to take to refill it. Register usage: - * - * $1 - moving cache index - * $2 - set count - */ - if (icache_sets) { - __asm__ __volatile__ ( - ".set push \n" - ".set noreorder \n" - ".set noat \n" - ".set mips4 \n" - " move $1, %2 \n" /* Start at index 0 */ - "1: cache 0, 0($1) \n" /* Invalidate this index */ - " addiu %1, %1, -1 \n" /* Decrement loop count */ - " bnez %1, 1b \n" /* loop test */ - " addu $1, $1, %0 \n" /* Next address JDCXXX - Should be short piped */ - ".set pop \n" - ::"r" (icache_line_size), - "r" (icache_sets * icache_assoc), - "r" (KSEG0) - :"$1"); - } - if (dcache_sets) { - __asm__ __volatile__ ( - ".set push \n" - ".set noreorder \n" - ".set noat \n" - ".set mips4 \n" - " move $1, %2 \n" /* Start at index 0 */ - "1: cache 0x1, 0($1) \n" /* WB/Invalidate this index */ - " addiu %1, %1, -1 \n" /* Decrement loop count */ - " bnez %1, 1b \n" /* loop test */ - " addu $1, $1, %0 \n" /* Next address JDCXXX - Should be short piped */ - ".set pop \n" - ::"r" (dcache_line_size), - "r" (dcache_sets * dcache_assoc), - "r" (KSEG0) - :"$1"); - } -} - -/* - * When flushing a range in the icache, we have to first writeback - * the dcache for the same range, so new ifetches will see any - * data that was dirty in the dcache - */ - -static void sb1_flush_icache_range(unsigned long start, unsigned long end) -{ - - /* JDCXXX - Implement me! */ - sb1_flush_cache_all(); -} - -static void sb1_flush_cache_mm(struct mm_struct *mm) -{ - /* Don't need to do this, as the dcache is physically tagged */ -} - -static void sb1_flush_cache_range(struct vm_area_struct *vma, - unsigned long start, - unsigned long end) -{ - /* Don't need to do this, as the dcache is physically tagged */ -} - - -static void sb1_flush_cache_sigtramp(unsigned long page) -{ - /* JDCXXX - Implement me! */ - sb1_flush_cache_all(); -} - - -/* - * This only needs to make sure stores done up to this - * point are visible to other agents outside the CPU. Given - * the coherent nature of the ZBus, all that's required here is - * a sync to make sure the data gets out to the caches and is - * visible to an arbitrary A Phase from an external agent - * - * Actually, I'm not even sure that's necessary; the semantics - * of this function aren't clear. If it's supposed to serve as - * a memory barrier, this is needed. If it's only meant to - * prevent data from being invisible to non-cpu memory accessors - * for some indefinite period of time (e.g. in a non-coherent - * dcache) then this function would be a complete nop. - */ -static void sb1_flush_page_to_ram(struct page *page) -{ - __asm__ __volatile__( - " sync \n" /* Short pipe */ - :::"memory"); -} - - -/* Cribbed from the r2300 code */ -static void sb1_flush_cache_page(struct vm_area_struct *vma, - unsigned long page) -{ - sb1_flush_cache_all(); -#if 0 - struct mm_struct *mm = vma->vm_mm; - unsigned long physpage; - - /* No icache flush needed without context; */ - if (mm->context == 0) - return; - - /* No icache flush needed if the page isn't executable */ - if (!(vma->vm_flags & VM_EXEC)) - return; - - physpage = (unsigned long) page_address(page); - if (physpage) - sb1_flush_icache_range(physpage, physpage + PAGE_SIZE); -#endif -} - - -/* - * Cache set values (from the mips64 spec) - * 0 - 64 - * 1 - 128 - * 2 - 256 - * 3 - 512 - * 4 - 1024 - * 5 - 2048 - * 6 - 4096 - * 7 - Reserved - */ -static unsigned int decode_cache_sets(unsigned int config_field) -{ - if (config_field == 7) { - /* JDCXXX - Find a graceful way to abort. */ - return 0; - } - - return (1<<(config_field + 6)); -} - -/* - * Cache line size values (from the mips64 spec) - * 0 - No cache present. - * 1 - 4 bytes - * 2 - 8 bytes - * 3 - 16 bytes - * 4 - 32 bytes - * 5 - 64 bytes - * 6 - 128 bytes - * 7 - Reserved - */ -static unsigned int decode_cache_line_size(unsigned int config_field) -{ - if (config_field == 0) { - return 0; - } else if (config_field == 7) { - /* JDCXXX - Find a graceful way to abort. */ - return 0; - } - return (1<<(config_field + 1)); -} - -/* - * Relevant bits of the config1 register format (from the MIPS32/MIPS64 specs) - * - * 24:22 Icache sets per way - * 21:19 Icache line size - * 18:16 Icache Associativity - * 15:13 Dcache sets per way - * 12:10 Dcache line size - * 9:7 Dcache Associativity - */ - - -static void probe_cache_sizes(void) -{ - u32 config1; - - __asm__ __volatile__( - ".set push \n" - ".set mips64 \n" - " mfc0 %0, $16, 1 \n" /* Get config1 register */ - ".set pop \n" - :"=r" (config1)); - icache_line_size = decode_cache_line_size((config1 >> 19) & 0x7); - dcache_line_size = decode_cache_line_size((config1 >> 10) & 0x7); - icache_sets = decode_cache_sets((config1 >> 22) & 0x7); - dcache_sets = decode_cache_sets((config1 >> 13) & 0x7); - icache_assoc = ((config1 >> 16) & 0x7) + 1; - dcache_assoc = ((config1 >> 7) & 0x7) + 1; - icache_size = icache_line_size * icache_sets * icache_assoc; - dcache_size = dcache_line_size * dcache_sets * dcache_assoc; - tlb_entries = ((config1 >> 25) & 0x3f) + 1; -} - - -/* This is called from loadmmu.c. We have to set up all the - memory management function pointers, as well as initialize - the caches and tlbs */ -void ld_mmu_sb1(void) -{ - probe_cache_sizes(); - - _clear_page = sb1_clear_page; - _copy_page = sb1_copy_page; - - _flush_cache_all = sb1_flush_cache_all; - _flush_cache_mm = sb1_flush_cache_mm; - _flush_cache_range = sb1_flush_cache_range; - _flush_cache_page = sb1_flush_cache_page; - _flush_cache_sigtramp = sb1_flush_cache_sigtramp; - - _flush_page_to_ram = sb1_flush_page_to_ram; - _flush_icache_page = sb1_flush_cache_page; - _flush_icache_range = sb1_flush_icache_range; - - - /* - * JDCXXX I'm not sure whether these are necessary: is this the right - * place to initialize the tlb? If it is, why is it done - * at this level instead of as common code in loadmmu()? - */ - flush_cache_all(); - flush_tlb_all(); - - /* Turn on caching in kseg0 */ - set_cp0_config(CONF_CM_CMASK, 0); -} diff -Nru a/arch/mips/mm/sc-ip22.c b/arch/mips/mm/sc-ip22.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/mm/sc-ip22.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,177 @@ +/* + * sc-ip22.c: Indy cache management functions. + * + * Copyright (C) 1997, 2001 Ralf Baechle (ralf@gnu.org), + * derived from r4xx0.c by David S. Miller (dm@engr.sgi.com). + */ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/* Secondary cache size in bytes, if present. */ +static unsigned long scache_size; + +#undef DEBUG_CACHE + +#define SC_SIZE 0x00080000 +#define SC_LINE 32 +#define CI_MASK (SC_SIZE - SC_LINE) +#define SC_INDEX(n) ((n) & CI_MASK) + +static inline void indy_sc_wipe(unsigned long first, unsigned long last) +{ + unsigned long tmp; + + __asm__ __volatile__( + ".set\tpush\t\t\t# indy_sc_wipe\n\t" + ".set\tnoreorder\n\t" + ".set\tmips3\n\t" + ".set\tnoat\n\t" + "mfc0\t%2, $12\n\t" + "li\t$1, 0x80\t\t\t# Go 64 bit\n\t" + "mtc0\t$1, $12\n\t" + + "dli\t$1, 0x9000000080000000\n\t" + "or\t%0, $1\t\t\t# first line to flush\n\t" + "or\t%1, $1\t\t\t# last line to flush\n\t" + ".set\tat\n\t" + + "1:\tsw\t$0, 0(%0)\n\t" + "bne\t%0, %1, 1b\n\t" + " daddu\t%0, 32\n\t" + + "mtc0\t%2, $12\t\t\t# Back to 32 bit\n\t" + "nop; nop; nop; nop;\n\t" + ".set\tpop" + : "=r" (first), "=r" (last), "=&r" (tmp) + : "0" (first), "1" (last)); +} + +static void indy_sc_wback_invalidate(unsigned long addr, unsigned long size) +{ + unsigned long first_line, last_line; + unsigned int flags; + +#ifdef DEBUG_CACHE + printk("indy_sc_wback_invalidate[%08lx,%08lx]", addr, size); +#endif + + if (!size) + return; + + /* Which lines to flush? */ + first_line = SC_INDEX(addr); + last_line = SC_INDEX(addr + size - 1); + + local_irq_save(flags); + if (first_line <= last_line) { + indy_sc_wipe(first_line, last_line); + goto out; + } + + indy_sc_wipe(first_line, SC_SIZE - SC_LINE); + indy_sc_wipe(0, last_line); +out: + local_irq_restore(flags); +} + +static void indy_sc_enable(void) +{ + unsigned long addr, tmp1, tmp2; + + /* This is really cool... */ +#ifdef DEBUG_CACHE + printk("Enabling R4600 SCACHE\n"); +#endif + __asm__ __volatile__( + ".set\tpush\n\t" + ".set\tnoreorder\n\t" + ".set\tmips3\n\t" + "mfc0\t%2, $12\n\t" + "nop; nop; nop; nop;\n\t" + "li\t%1, 0x80\n\t" + "mtc0\t%1, $12\n\t" + "nop; nop; nop; nop;\n\t" + "li\t%0, 0x1\n\t" + "dsll\t%0, 31\n\t" + "lui\t%1, 0x9000\n\t" + "dsll32\t%1, 0\n\t" + "or\t%0, %1, %0\n\t" + "sb\t$0, 0(%0)\n\t" + "mtc0\t$0, $12\n\t" + "nop; nop; nop; nop;\n\t" + "mtc0\t%2, $12\n\t" + "nop; nop; nop; nop;\n\t" + ".set\tpop" + : "=r" (tmp1), "=r" (tmp2), "=r" (addr)); +} + +static void indy_sc_disable(void) +{ + unsigned long tmp1, tmp2, tmp3; + +#ifdef DEBUG_CACHE + printk("Disabling R4600 SCACHE\n"); +#endif + __asm__ __volatile__( + ".set\tpush\n\t" + ".set\tnoreorder\n\t" + ".set\tmips3\n\t" + "li\t%0, 0x1\n\t" + "dsll\t%0, 31\n\t" + "lui\t%1, 0x9000\n\t" + "dsll32\t%1, 0\n\t" + "or\t%0, %1, %0\n\t" + "mfc0\t%2, $12\n\t" + "nop; nop; nop; nop\n\t" + "li\t%1, 0x80\n\t" + "mtc0\t%1, $12\n\t" + "nop; nop; nop; nop\n\t" + "sh\t$0, 0(%0)\n\t" + "mtc0\t$0, $12\n\t" + "nop; nop; nop; nop\n\t" + "mtc0\t%2, $12\n\t" + "nop; nop; nop; nop\n\t" + ".set\tpop" + : "=r" (tmp1), "=r" (tmp2), "=r" (tmp3)); +} + +static inline int __init indy_sc_probe(void) +{ + unsigned int size = ip22_eeprom_read(&sgimc->eeprom, 17); + if (size == 0) + return 0; + + size <<= PAGE_SHIFT; + printk(KERN_INFO "R4600/R5000 SCACHE size %ldK, linesize 32 bytes.\n", + size >> 10); + scache_size = size; + + return 1; +} + +/* XXX Check with wje if the Indy caches can differenciate between + writeback + invalidate and just invalidate. */ +struct bcache_ops indy_sc_ops = { + .bc_enable = indy_sc_enable, + .bc_disable = indy_sc_disable, + .bc_wback_inv = indy_sc_wback_invalidate, + .bc_inv = indy_sc_wback_invalidate +}; + +void __init indy_sc_init(void) +{ + if (indy_sc_probe()) { + indy_sc_enable(); + bcops = &indy_sc_ops; + } +} diff -Nru a/arch/mips/mm/sc-r5k.c b/arch/mips/mm/sc-r5k.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/mm/sc-r5k.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,115 @@ +/* + * Copyright (C) 1997, 2001 Ralf Baechle (ralf@gnu.org), + * derived from r4xx0.c by David S. Miller (dm@engr.sgi.com). + */ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/* Secondary cache size in bytes, if present. */ +static unsigned long scache_size; + +#define SC_LINE 32 +#define SC_PAGE (128*SC_LINE) + +#define cache_op(base,op) \ +__asm__ __volatile__(" \ + .set noreorder; \ + .set mips3; \ + cache %1, (%0); \ + .set mips0; \ + .set reorder" \ + : \ + : "r" (base), \ + "i" (op)); + +static inline void blast_r5000_scache(void) +{ + unsigned long start = KSEG0; + unsigned long end = KSEG0 + scache_size; + + while(start < end) { + cache_op(start, R5K_Page_Invalidate_S); + start += SC_PAGE; + } +} + +static void r5k_dma_cache_inv_sc(unsigned long addr, unsigned long size) +{ + unsigned long end, a; + + if (size >= scache_size) { + blast_r5000_scache(); + return; + } + + /* On the R5000 secondary cache we cannot + * invalidate less than a page at a time. + * The secondary cache is physically indexed, write-through. + */ + a = addr & ~(SC_PAGE - 1); + end = (addr + size - 1) & ~(SC_PAGE - 1); + while (a <= end) { + cache_op(a, R5K_Page_Invalidate_S); + a += SC_PAGE; + } +} + +static void r5k_sc_enable(void) +{ + unsigned long flags; + + local_irq_save(flags); + change_c0_config(R5K_CONF_SE, R5K_CONF_SE); + blast_r5000_scache(); + local_irq_restore(flags); +} + +static void r5k_sc_disable(void) +{ + unsigned long flags; + + local_irq_save(flags); + blast_r5000_scache(); + change_c0_config(R5K_CONF_SE, 0); + local_irq_restore(flags); +} + +static inline int __init r5k_sc_probe(void) +{ + unsigned long config = read_c0_config(); + + if (config & CONF_SC) + return(0); + + scache_size = (512 * 1024) << ((config & R5K_CONF_SS) >> 20); + + printk("R5000 SCACHE size %ldkB, linesize 32 bytes.\n", + scache_size >> 10); + + return 1; +} + +static struct bcache_ops r5k_sc_ops = { + .bc_enable = r5k_sc_enable, + .bc_disable = r5k_sc_disable, + .bc_wback_inv = r5k_dma_cache_inv_sc, + .bc_inv = r5k_dma_cache_inv_sc +}; + +void __init r5k_sc_init(void) +{ + if (r5k_sc_probe()) { + r5k_sc_enable(); + bcops = &r5k_sc_ops; + } +} diff -Nru a/arch/mips/mm/sc-rm7k.c b/arch/mips/mm/sc-rm7k.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/mm/sc-rm7k.c Tue Jul 1 18:44:39 2003 @@ -0,0 +1,191 @@ +/* + * sc-rm7k.c: RM7000 cache management functions. + * + * Copyright (C) 1997, 2001, 2003 Ralf Baechle (ralf@gnu.org), + */ +#include +#include +#include + +#include +#include +#include +#include +#include + +/* Primary cache parameters. */ +#define sc_lsize 32 +#define tc_pagesize (32*128) + +/* Secondary cache parameters. */ +#define scache_size (256*1024) /* Fixed to 256KiB on RM7000 */ + +extern unsigned long icache_way_size, dcache_way_size; + +#include + +int rm7k_tcache_enabled; + +/* + * Writeback and invalidate the primary cache dcache before DMA. + * (XXX These need to be fixed ...) + */ +static void rm7k_sc_wback_inv(unsigned long addr, unsigned long size) +{ + unsigned long end, a; + +#ifdef DEBUG_CACHE + printk("rm7k_sc_wback_inv[%08lx,%08lx]", addr, size); +#endif + + a = addr & ~(sc_lsize - 1); + end = (addr + size - 1) & ~(sc_lsize - 1); + while (1) { + flush_scache_line(a); /* Hit_Writeback_Inv_SD */ + if (a == end) + break; + a += sc_lsize; + } + + if (!rm7k_tcache_enabled) + return; + + a = addr & ~(tc_pagesize - 1); + end = (addr + size - 1) & ~(tc_pagesize - 1); + while(1) { + invalidate_tcache_page(a); /* Page_Invalidate_T */ + if (a == end) + break; + a += tc_pagesize; + } +} + +static void rm7k_sc_inv(unsigned long addr, unsigned long size) +{ + unsigned long end, a; + +#ifdef DEBUG_CACHE + printk("rm7k_sc_inv[%08lx,%08lx]", addr, size); +#endif + + a = addr & ~(sc_lsize - 1); + end = (addr + size - 1) & ~(sc_lsize - 1); + while (1) { + invalidate_scache_line(a); /* Hit_Invalidate_SD */ + if (a == end) + break; + a += sc_lsize; + } + + if (!rm7k_tcache_enabled) + return; + + a = addr & ~(tc_pagesize - 1); + end = (addr + size - 1) & ~(tc_pagesize - 1); + while(1) { + invalidate_tcache_page(a); /* Page_Invalidate_T */ + if (a == end) + break; + a += tc_pagesize; + } +} + +/* + * This function is executed in the uncached segment KSEG1. + * It must not touch the stack, because the stack pointer still points + * into KSEG0. + * + * Three options: + * - Write it in assembly and guarantee that we don't use the stack. + * - Disable caching for KSEG0 before calling it. + * - Pray that GCC doesn't randomly start using the stack. + * + * This being Linux, we obviously take the least sane of those options - + * following DaveM's lead in c-r4k.c + * + * It seems we get our kicks from relying on unguaranteed behaviour in GCC + */ +static __init void rm7k_sc_enable(void) +{ + int i; + + set_c0_config(1<<3); /* CONF_SE */ + + write_c0_taglo(0); + write_c0_taghi(0); + + for (i=0; i> 31) & 1) + return 0; + + printk(KERN_INFO "Secondary cache size %ldK, linesize 32 bytes.\n", + (scache_size >> 10), sc_lsize); + + if ((config >> 3) & 1) + return; + + printk(KERN_INFO "Enabling secondary cache..."); + func(); + printk(" done\n"); + + /* + * While we're at it let's deal with the tertiary cache. + */ + if ((config >> 17) & 1) + return 1; + + /* + * We can't enable the L3 cache yet. There may be board-specific + * magic necessary to turn it on, and blindly asking the CPU to + * start using it would may give cache errors. + * + * Also, board-specific knowledge may allow us to use the + * CACHE Flash_Invalidate_T instruction if the tag RAM supports + * it, and may specify the size of the L3 cache so we don't have + * to probe it. + */ + printk(KERN_INFO "Tertiary cache present, %s enabled\n", + config&(1<<12) ? "already" : "not (yet)"); + + if ((config >> 12) & 1) + rm7k_tcache_enabled = 1; + + return 1; +} + +struct bcache_ops rm7k_sc_ops = { + .bc_enable = rm7k_sc_enable, + .bc_disable = rm7k_sc_disable, + .bc_wback_inv = rm7k_sc_wback_inv, + .bc_inv = rm7k_sc_inv +}; + +void __init rm7k_sc_init(void) +{ + if (rm7k_sc_probe()) { + rm7k_sc_enable(); + bcops = &rm7k_sc_ops; + } +} diff -Nru a/arch/mips/mm/tlb-r3k.c b/arch/mips/mm/tlb-r3k.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/mm/tlb-r3k.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,290 @@ +/* + * r2300.c: R2000 and R3000 specific mmu/cache code. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * with a lot of changes to make this thing work for R3000s + * Tx39XX R4k style caches added. HK + * Copyright (C) 1998, 1999, 2000 Harald Koerfgen + * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov + * Copyright (C) 2002 Ralf Baechle + * Copyright (C) 2002 Maciej W. Rozycki + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#undef DEBUG_TLB + +extern char except_vec0_r2300; + +/* CP0 hazard avoidance. */ +#define BARRIER \ + __asm__ __volatile__( \ + ".set push\n\t" \ + ".set noreorder\n\t" \ + "nop\n\t" \ + ".set pop\n\t") + +int r3k_have_wired_reg; /* should be in cpu_data? */ + +/* TLB operations. */ +void local_flush_tlb_all(void) +{ + unsigned long flags; + unsigned long old_ctx; + int entry; + +#ifdef DEBUG_TLB + printk("[tlball]"); +#endif + + local_irq_save(flags); + old_ctx = read_c0_entryhi() & ASID_MASK; + write_c0_entrylo0(0); + entry = r3k_have_wired_reg ? read_c0_wired() : 8; + for (; entry < current_cpu_data.tlbsize; entry++) { + write_c0_index(entry << 8); + write_c0_entryhi((entry | 0x80000) << 12); + BARRIER; + tlb_write_indexed(); + } + write_c0_entryhi(old_ctx); + local_irq_restore(flags); +} + +void local_flush_tlb_mm(struct mm_struct *mm) +{ + int cpu = smp_processor_id(); + + if (cpu_context(cpu, mm) != 0) { +#ifdef DEBUG_TLB + printk("[tlbmm<%lu>]", (unsigned long)cpu_context(cpu, mm)); +#endif + drop_mmu_context(mm, cpu); + } +} + +void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, + unsigned long end) +{ + struct mm_struct *mm = vma->vm_mm; + int cpu = smp_processor_id(); + + if (cpu_context(cpu, mm) != 0) { + unsigned long flags; + int size; + +#ifdef DEBUG_TLB + printk("[tlbrange<%lu,0x%08lx,0x%08lx>]", + cpu_context(cpu, mm) & ASID_MASK, start, end); +#endif + local_irq_save(flags); + size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + if (size <= current_cpu_data.tlbsize) { + int oldpid = read_c0_entryhi() & ASID_MASK; + int newpid = cpu_context(cpu, mm) & ASID_MASK; + + start &= PAGE_MASK; + end += PAGE_SIZE - 1; + end &= PAGE_MASK; + while (start < end) { + int idx; + + write_c0_entryhi(start | newpid); + start += PAGE_SIZE; /* BARRIER */ + tlb_probe(); + idx = read_c0_index(); + write_c0_entrylo0(0); + write_c0_entryhi(KSEG0); + if (idx < 0) /* BARRIER */ + continue; + tlb_write_indexed(); + } + write_c0_entryhi(oldpid); + } else { + drop_mmu_context(mm, cpu); + } + local_irq_restore(flags); + } +} + +void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) +{ + unsigned long flags; + int size; + +#ifdef DEBUG_TLB + printk("[tlbrange<%lu,0x%08lx,0x%08lx>]", start, end); +#endif + local_irq_save(flags); + size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + if (size <= current_cpu_data.tlbsize) { + int pid = read_c0_entryhi(); + + start &= PAGE_MASK; + end += PAGE_SIZE - 1; + end &= PAGE_MASK; + + while (start < end) { + int idx; + + write_c0_entryhi(start); + start += PAGE_SIZE; /* BARRIER */ + tlb_probe(); + idx = read_c0_index(); + write_c0_entrylo0(0); + write_c0_entryhi(KSEG0); + if (idx < 0) /* BARRIER */ + continue; + tlb_write_indexed(); + } + write_c0_entryhi(pid); + } else { + local_flush_tlb_all(); + } + local_irq_restore(flags); +} + +void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) +{ + int cpu = smp_processor_id(); + + if (!vma || cpu_context(cpu, vma->vm_mm) != 0) { + unsigned long flags; + int oldpid, newpid, idx; + +#ifdef DEBUG_TLB + printk("[tlbpage<%lu,0x%08lx>]", cpu_context(cpu, vma->vm_mm), page); +#endif + newpid = cpu_context(cpu, vma->vm_mm) & ASID_MASK; + page &= PAGE_MASK; + local_irq_save(flags); + oldpid = read_c0_entryhi() & ASID_MASK; + write_c0_entryhi(page | newpid); + BARRIER; + tlb_probe(); + idx = read_c0_index(); + write_c0_entrylo0(0); + write_c0_entryhi(KSEG0); + if (idx < 0) /* BARRIER */ + goto finish; + tlb_write_indexed(); + +finish: + write_c0_entryhi(oldpid); + local_irq_restore(flags); + } +} + +void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte) +{ + unsigned long flags; + int idx, pid; + + /* + * Handle debugger faulting in for debugee. + */ + if (current->active_mm != vma->vm_mm) + return; + + pid = read_c0_entryhi() & ASID_MASK; + +#ifdef DEBUG_TLB + if ((pid != (cpu_context(cpu, vma->vm_mm) & ASID_MASK)) || (cpu_context(cpu, vma->vm_mm) == 0)) { + printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%lu tlbpid=%d\n", + (cpu_context(cpu, vma->vm_mm)), pid); + } +#endif + + local_irq_save(flags); + address &= PAGE_MASK; + write_c0_entryhi(address | pid); + BARRIER; + tlb_probe(); + idx = read_c0_index(); + write_c0_entrylo0(pte_val(pte)); + write_c0_entryhi(address | pid); + if (idx < 0) { /* BARRIER */ + tlb_write_random(); + } else { + tlb_write_indexed(); + } + write_c0_entryhi(pid); + local_irq_restore(flags); +} + +void __init add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, + unsigned long entryhi, unsigned long pagemask) +{ + unsigned long flags; + unsigned long old_ctx; + static unsigned long wired = 0; + + if (r3k_have_wired_reg) { /* TX39XX */ + unsigned long old_pagemask; + unsigned long w; + +#ifdef DEBUG_TLB + printk("[tlbwired]\n", + entrylo0, entryhi, pagemask); +#endif + + local_irq_save(flags); + /* Save old context and create impossible VPN2 value */ + old_ctx = read_c0_entryhi() & ASID_MASK; + old_pagemask = read_c0_pagemask(); + w = read_c0_wired(); + write_c0_wired(w + 1); + if (read_c0_wired() != w + 1) { + printk("[tlbwired] No WIRED reg?\n"); + return; + } + write_c0_index(w << 8); + write_c0_pagemask(pagemask); + write_c0_entryhi(entryhi); + write_c0_entrylo0(entrylo0); + BARRIER; + tlb_write_indexed(); + + write_c0_entryhi(old_ctx); + write_c0_pagemask(old_pagemask); + local_flush_tlb_all(); + local_irq_restore(flags); + + } else if (wired < 8) { +#ifdef DEBUG_TLB + printk("[tlbwired]\n", + entrylo0, entryhi); +#endif + + local_irq_save(flags); + old_ctx = read_c0_entryhi() & ASID_MASK; + write_c0_entrylo0(entrylo0); + write_c0_entryhi(entryhi); + write_c0_index(wired); + wired++; /* BARRIER */ + tlb_write_indexed(); + write_c0_entryhi(old_ctx); + local_flush_tlb_all(); + local_irq_restore(flags); + } +} + +void __init r3k_tlb_init(void) +{ + local_flush_tlb_all(); + memcpy((void *)KSEG0, &except_vec0_r2300, 0x80); + flush_icache_range(KSEG0, KSEG0 + 0x80); +} diff -Nru a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/mm/tlb-r4k.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,459 @@ +/* + * 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. + * + * r4xx0.c: R4000 processor variant specific MMU/Cache routines. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * Copyright (C) 1997, 1998, 1999, 2000 Ralf Baechle ralf@gnu.org + * + * To do: + * + * - this code is a overbloated pig + * - many of the bug workarounds are not efficient at all, but at + * least they are functional ... + */ +#include +#include +#include + +#include +#include +#include +#include +#include + +#undef DEBUG_TLB +#undef DEBUG_TLBUPDATE + +extern char except_vec0_nevada, except_vec0_r4000, except_vec0_r4600; + +/* CP0 hazard avoidance. */ +#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \ + "nop; nop; nop; nop; nop; nop;\n\t" \ + ".set reorder\n\t") + +void local_flush_tlb_all(void) +{ + unsigned long flags; + unsigned long old_ctx; + int entry; + +#ifdef DEBUG_TLB + printk("[tlball]"); +#endif + + local_irq_save(flags); + /* Save old context and create impossible VPN2 value */ + old_ctx = (read_c0_entryhi() & ASID_MASK); + write_c0_entrylo0(0); + write_c0_entrylo1(0); + BARRIER; + + entry = read_c0_wired(); + + /* Blast 'em all away. */ + while (entry < current_cpu_data.tlbsize) { + /* + * Make sure all entries differ. If they're not different + * MIPS32 will take revenge ... + */ + write_c0_entryhi(KSEG0 + entry*0x2000); + write_c0_index(entry); + BARRIER; + tlb_write_indexed(); + BARRIER; + entry++; + } + BARRIER; + write_c0_entryhi(old_ctx); + local_irq_restore(flags); +} + +void local_flush_tlb_mm(struct mm_struct *mm) +{ + int cpu = smp_processor_id(); + + if (cpu_context(cpu, mm) != 0) { +#ifdef DEBUG_TLB + printk("[tlbmm<%d>]", cpu_context(cpu, mm)); +#endif + drop_mmu_context(mm,cpu); + } +} + +void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, + unsigned long end) +{ + struct mm_struct *mm = vma->vm_mm; + int cpu = smp_processor_id(); + + if (cpu_context(cpu, mm) != 0) { + unsigned long flags; + int size; + +#ifdef DEBUG_TLB + printk("[tlbrange<%02x,%08lx,%08lx>]", cpu_context(cpu, mm) & ASID_MASK, + start, end); +#endif + local_irq_save(flags); + size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + size = (size + 1) >> 1; + if (size <= current_cpu_data.tlbsize/2) { + int oldpid = read_c0_entryhi() & ASID_MASK; + int newpid = cpu_context(cpu, mm) & ASID_MASK; + + start &= (PAGE_MASK << 1); + end += ((PAGE_SIZE << 1) - 1); + end &= (PAGE_MASK << 1); + while (start < end) { + int idx; + + write_c0_entryhi(start | newpid); + start += (PAGE_SIZE << 1); + BARRIER; + tlb_probe(); + BARRIER; + idx = read_c0_index(); + write_c0_entrylo0(0); + write_c0_entrylo1(0); + if (idx < 0) + continue; + /* Make sure all entries differ. */ + write_c0_entryhi(KSEG0 + idx*0x2000); + BARRIER; + tlb_write_indexed(); + BARRIER; + } + write_c0_entryhi(oldpid); + } else { + drop_mmu_context(mm, cpu); + } + local_irq_restore(flags); + } +} + +void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) +{ + unsigned long flags; + int size; + +#ifdef DEBUG_TLB + printk("[tlbkernelrange<%02x,%08lx,%08lx>]", start, end); +#endif + local_irq_save(flags); + size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + size = (size + 1) >> 1; + if (size <= current_cpu_data.tlbsize / 2) { + int pid = read_c0_entryhi(); + + start &= (PAGE_MASK << 1); + end += ((PAGE_SIZE << 1) - 1); + end &= (PAGE_MASK << 1); + + while (start < end) { + int idx; + + write_c0_entryhi(start); + start += (PAGE_SIZE << 1); + BARRIER; + tlb_probe(); + BARRIER; + idx = read_c0_index(); + write_c0_entrylo0(0); + write_c0_entrylo1(0); + if (idx < 0) + continue; + /* Make sure all entries differ. */ + write_c0_entryhi(KSEG0 + idx*0x2000); + BARRIER; + tlb_write_indexed(); + BARRIER; + } + write_c0_entryhi(pid); + } else { + local_flush_tlb_all(); + } + local_irq_restore(flags); +} + +void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) +{ + int cpu = smp_processor_id(); + + if (!vma || cpu_context(cpu, vma->vm_mm) != 0) { + unsigned long flags; + int oldpid, newpid, idx; + +#ifdef DEBUG_TLB + printk("[tlbpage<%d,%08lx>]", cpu_context(cpu, vma->vm_mm), + page); +#endif + newpid = (cpu_context(cpu, vma->vm_mm) & ASID_MASK); + page &= (PAGE_MASK << 1); + local_irq_save(flags); + oldpid = (read_c0_entryhi() & ASID_MASK); + write_c0_entryhi(page | newpid); + BARRIER; + tlb_probe(); + BARRIER; + idx = read_c0_index(); + write_c0_entrylo0(0); + write_c0_entrylo1(0); + if(idx < 0) + goto finish; + /* Make sure all entries differ. */ + write_c0_entryhi(KSEG0+idx*0x2000); + BARRIER; + tlb_write_indexed(); + + finish: + BARRIER; + write_c0_entryhi(oldpid); + local_irq_restore(flags); + } +} + +/* + * This one is only used for pages with the global bit set so we don't care + * much about the ASID. + */ +void local_flush_tlb_one(unsigned long page) +{ + unsigned long flags; + int oldpid, idx; + + local_irq_save(flags); + page &= (PAGE_MASK << 1); + oldpid = read_c0_entryhi() & 0xff; + write_c0_entryhi(page); + BARRIER; + tlb_probe(); + BARRIER; + idx = read_c0_index(); + write_c0_entrylo0(0); + write_c0_entrylo1(0); + if (idx >= 0) { + /* Make sure all entries differ. */ + write_c0_entryhi(KSEG0+(idx<<(PAGE_SHIFT+1))); + BARRIER; + tlb_write_indexed(); + } + BARRIER; + write_c0_entryhi(oldpid); + + local_irq_restore(flags); +} + +/* We will need multiple versions of update_mmu_cache(), one that just + * updates the TLB with the new pte(s), and another which also checks + * for the R4k "end of page" hardware bug and does the needy. + */ +void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte) +{ + unsigned long flags; + pgd_t *pgdp; + pmd_t *pmdp; + pte_t *ptep; + int idx, pid; + + /* + * Handle debugger faulting in for debugee. + */ + if (current->active_mm != vma->vm_mm) + return; + + pid = read_c0_entryhi() & ASID_MASK; + +#ifdef DEBUG_TLB + if ((pid != cpu_context(cpu, vma->vm_mm) & ASID_MASK) || + (cpu_context(vma->vm_mm) == 0)) { + printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%d " + "tlbpid=%d\n", + (int) (cpu_context(cpu, vma->vm_mm) & ASID_MASK), pid); + } +#endif + + local_irq_save(flags); + address &= (PAGE_MASK << 1); + write_c0_entryhi(address | pid); + pgdp = pgd_offset(vma->vm_mm, address); + BARRIER; + tlb_probe(); + BARRIER; + pmdp = pmd_offset(pgdp, address); + idx = read_c0_index(); + ptep = pte_offset_map(pmdp, address); + BARRIER; + write_c0_entrylo0(pte_val(*ptep++) >> 6); + write_c0_entrylo1(pte_val(*ptep) >> 6); + write_c0_entryhi(address | pid); + BARRIER; + if (idx < 0) { + tlb_write_random(); + } else { + tlb_write_indexed(); + } + BARRIER; + write_c0_entryhi(pid); + BARRIER; + local_irq_restore(flags); +} + +#if 0 +static void r4k_update_mmu_cache_hwbug(struct vm_area_struct * vma, + unsigned long address, pte_t pte) +{ + unsigned long flags; + pgd_t *pgdp; + pmd_t *pmdp; + pte_t *ptep; + int idx; + + local_irq_save(flags); + address &= (PAGE_MASK << 1); + write_c0_entryhi(address | (read_c0_entryhi() & ASID_MASK)); + pgdp = pgd_offset(vma->vm_mm, address); + tlb_probe(); + pmdp = pmd_offset(pgdp, address); + idx = read_c0_index(); + ptep = pte_offset_map(pmdp, address); + write_c0_entrylo0(pte_val(*ptep++) >> 6); + write_c0_entrylo1(pte_val(*ptep) >> 6); + BARRIER; + if (idx < 0) + tlb_write_random(); + else + tlb_write_indexed(); + BARRIER; + local_irq_restore(flags); +} +#endif + +void __init add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, + unsigned long entryhi, unsigned long pagemask) +{ + unsigned long flags; + unsigned long wired; + unsigned long old_pagemask; + unsigned long old_ctx; + + local_irq_save(flags); + /* Save old context and create impossible VPN2 value */ + old_ctx = read_c0_entryhi() & ASID_MASK; + old_pagemask = read_c0_pagemask(); + wired = read_c0_wired(); + write_c0_wired(wired + 1); + write_c0_index(wired); + BARRIER; + write_c0_pagemask(pagemask); + write_c0_entryhi(entryhi); + write_c0_entrylo0(entrylo0); + write_c0_entrylo1(entrylo1); + BARRIER; + tlb_write_indexed(); + BARRIER; + + write_c0_entryhi(old_ctx); + BARRIER; + write_c0_pagemask(old_pagemask); + local_flush_tlb_all(); + local_irq_restore(flags); +} + +/* + * Used for loading TLB entries before trap_init() has started, when we + * don't actually want to add a wired entry which remains throughout the + * lifetime of the system + */ + +static int temp_tlb_entry __initdata; + +__init int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1, + unsigned long entryhi, unsigned long pagemask) +{ + int ret = 0; + unsigned long flags; + unsigned long wired; + unsigned long old_pagemask; + unsigned long old_ctx; + + local_irq_save(flags); + /* Save old context and create impossible VPN2 value */ + old_ctx = read_c0_entryhi() & ASID_MASK; + old_pagemask = read_c0_pagemask(); + wired = read_c0_wired(); + if (--temp_tlb_entry < wired) { + printk(KERN_WARNING "No TLB space left for add_temporary_entry\n"); + ret = -ENOSPC; + goto out; + } + + write_c0_index(temp_tlb_entry); + BARRIER; + write_c0_pagemask(pagemask); + write_c0_entryhi(entryhi); + write_c0_entrylo0(entrylo0); + write_c0_entrylo1(entrylo1); + BARRIER; + tlb_write_indexed(); + BARRIER; + + write_c0_entryhi(old_ctx); + BARRIER; + write_c0_pagemask(old_pagemask); +out: + local_irq_restore(flags); + return ret; +} + +static void __init probe_tlb(unsigned long config) +{ + unsigned int prid, config1; + + prid = read_c0_prid() & ASID_MASK; + if (prid == PRID_IMP_RM7000 || !(config & (1 << 31))) + /* + * Not a MIPS32 complianant CPU. Config 1 register not + * supported, we assume R4k style. Cpu probing already figured + * out the number of tlb entries. + */ + return; + +#if defined(CONFIG_CPU_MIPS32) || defined (CONFIG_CPU_MIPS64) + config1 = read_c0_config1(); + if (!((config >> 7) & 3)) + panic("No MMU present"); + else + current_cpu_data.tlbsize = ((config1 >> 25) & 0x3f) + 1; +#endif +} + +void __init r4k_tlb_init(void) +{ + u32 config = read_c0_config(); + + /* + * You should never change this register: + * - On R4600 1.7 the tlbp never hits for pages smaller than + * the value in the c0_pagemask register. + * - The entire mm handling assumes the c0_pagemask register to + * be set for 4kb pages. + */ + probe_tlb(config); + write_c0_pagemask(PM_4K); + write_c0_wired(0); + temp_tlb_entry = current_cpu_data.tlbsize - 1; + local_flush_tlb_all(); + + if (cpu_has_4kex && cpu_has_4ktlb) { + if (current_cpu_data.cputype == CPU_NEVADA) + memcpy((void *)KSEG0, &except_vec0_nevada, 0x80); + else if (current_cpu_data.cputype == CPU_R4600) + memcpy((void *)KSEG0, &except_vec0_r4600, 0x80); + else + memcpy((void *)KSEG0, &except_vec0_r4000, 0x80); + flush_icache_range(KSEG0, KSEG0 + 0x80); + } +} diff -Nru a/arch/mips/mm/tlb-sb1.c b/arch/mips/mm/tlb-sb1.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/mm/tlb-sb1.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,339 @@ +/* + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * Copyright (C) 1997, 2001 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 2000, 2001 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#include +#include +#include +#include + +extern char except_vec0_sb1[]; + +/* Dump the current entry* and pagemask registers */ +static inline void dump_cur_tlb_regs(void) +{ + unsigned int entryhihi, entryhilo, entrylo0hi, entrylo0lo, entrylo1hi; + unsigned int entrylo1lo, pagemask; + + __asm__ __volatile__ ( + ".set push \n" + ".set noreorder \n" + ".set mips64 \n" + ".set noat \n" + " dmfc0 $1, $10 \n" + " dsrl32 %0, $1, 0 \n" + " sll %1, $1, 0 \n" + " dmfc0 $1, $2 \n" + " dsrl32 %2, $1, 0 \n" + " sll %3, $1, 0 \n" + " dmfc0 $1, $3 \n" + " dsrl32 %4, $1, 0 \n" + " sll %5, $1, 0 \n" + " mfc0 %6, $5 \n" + ".set pop \n" + : "=r" (entryhihi), "=r" (entryhilo), + "=r" (entrylo0hi), "=r" (entrylo0lo), + "=r" (entrylo1hi), "=r" (entrylo1lo), + "=r" (pagemask)); + + printk("%08X%08X %08X%08X %08X%08X %08X", + entryhihi, entryhilo, + entrylo0hi, entrylo0lo, + entrylo1hi, entrylo1lo, + pagemask); +} + +void sb1_dump_tlb(void) +{ + unsigned long old_ctx; + unsigned long flags; + int entry; + local_irq_save(flags); + old_ctx = read_c0_entryhi(); + printk("Current TLB registers state:\n" + " EntryHi EntryLo0 EntryLo1 PageMask Index\n" + "--------------------------------------------------------------------\n"); + dump_cur_tlb_regs(); + printk(" %08X\n", read_c0_index()); + printk("\n\nFull TLB Dump:\n" + "Idx EntryHi EntryLo0 EntryLo1 PageMask\n" + "--------------------------------------------------------------\n"); + for (entry = 0; entry < current_cpu_data.tlbsize; entry++) { + write_c0_index(entry); + printk("\n%02i ", entry); + tlb_read(); + dump_cur_tlb_regs(); + } + printk("\n"); + write_c0_entryhi(old_ctx); + local_irq_restore(flags); +} + +void local_flush_tlb_all(void) +{ + unsigned long flags; + unsigned long old_ctx; + int entry; + + local_irq_save(flags); + /* Save old context and create impossible VPN2 value */ + old_ctx = read_c0_entryhi() & ASID_MASK; + write_c0_entrylo0(0); + write_c0_entrylo1(0); + for (entry = 0; entry < current_cpu_data.tlbsize; entry++) { + write_c0_entryhi(KSEG0 + (PAGE_SIZE << 1) * entry); + write_c0_index(entry); + tlb_write_indexed(); + } + write_c0_entryhi(old_ctx); + local_irq_restore(flags); +} + + +/* + * Use a bogus region of memory (starting at 0) to sanitize the TLB's. + * Use increments of the maximum page size (16MB), and check for duplicate + * entries before doing a given write. Then, when we're safe from collisions + * with the firmware, go back and give all the entries invalid addresses with + * the normal flush routine. + */ +void sb1_sanitize_tlb(void) +{ + int entry; + long addr = 0; + + long inc = 1<<24; /* 16MB */ + /* Save old context and create impossible VPN2 value */ + write_c0_entrylo0(0); + write_c0_entrylo1(0); + for (entry = 0; entry < current_cpu_data.tlbsize; entry++) { + do { + addr += inc; + write_c0_entryhi(addr); + tlb_probe(); + } while ((int)(read_c0_index()) >= 0); + write_c0_index(entry); + tlb_write_indexed(); + } + /* Now that we know we're safe from collisions, we can safely flush + the TLB with the "normal" routine. */ + local_flush_tlb_all(); +} + +void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, + unsigned long end) +{ + struct mm_struct *mm = vma->vm_mm; + unsigned long flags; + int cpu; + + local_irq_save(flags); + cpu = smp_processor_id(); + if (cpu_context(cpu, mm) != 0) { + int size; + size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + size = (size + 1) >> 1; + if (size <= (current_cpu_data.tlbsize/2)) { + int oldpid = read_c0_entryhi() & ASID_MASK; + int newpid = cpu_asid(cpu, mm); + + start &= (PAGE_MASK << 1); + end += ((PAGE_SIZE << 1) - 1); + end &= (PAGE_MASK << 1); + while (start < end) { + int idx; + + write_c0_entryhi(start | newpid); + start += (PAGE_SIZE << 1); + tlb_probe(); + idx = read_c0_index(); + write_c0_entrylo0(0); + write_c0_entrylo1(0); + write_c0_entryhi(KSEG0 + (idx << (PAGE_SHIFT+1))); + if (idx < 0) + continue; + tlb_write_indexed(); + } + write_c0_entryhi(oldpid); + } else { + drop_mmu_context(mm, cpu); + } + } + local_irq_restore(flags); +} + +void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) +{ + unsigned long flags; + int size; + + size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + size = (size + 1) >> 1; + + local_irq_save(flags); + if (size <= (current_cpu_data.tlbsize/2)) { + int pid = read_c0_entryhi(); + + start &= (PAGE_MASK << 1); + end += ((PAGE_SIZE << 1) - 1); + end &= (PAGE_MASK << 1); + + while (start < end) { + int idx; + + write_c0_entryhi(start); + start += (PAGE_SIZE << 1); + tlb_probe(); + idx = read_c0_index(); + write_c0_entrylo0(0); + write_c0_entrylo1(0); + write_c0_entryhi(KSEG0 + (idx << (PAGE_SHIFT+1))); + if (idx < 0) + continue; + tlb_write_indexed(); + } + write_c0_entryhi(pid); + } else { + local_flush_tlb_all(); + } + local_irq_restore(flags); +} + +void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) +{ + unsigned long flags; + int cpu = smp_processor_id(); + + local_irq_save(flags); + if (cpu_context(cpu, vma->vm_mm) != 0) { + int oldpid, newpid, idx; + newpid = cpu_asid(cpu, vma->vm_mm); + page &= (PAGE_MASK << 1); + oldpid = read_c0_entryhi() & ASID_MASK; + write_c0_entryhi(page | newpid); + tlb_probe(); + idx = read_c0_index(); + write_c0_entrylo0(0); + write_c0_entrylo1(0); + if(idx < 0) + goto finish; + /* Make sure all entries differ. */ + write_c0_entryhi(KSEG0+(idx<<(PAGE_SHIFT+1))); + tlb_write_indexed(); + finish: + write_c0_entryhi(oldpid); + } + local_irq_restore(flags); +} + +/* + * This one is only used for pages with the global bit set so we don't care + * much about the ASID. + */ +void local_flush_tlb_one(unsigned long page) +{ + unsigned long flags; + int oldpid, idx; + + local_irq_save(flags); + page &= (PAGE_MASK << 1); + oldpid = read_c0_entryhi() & ASID_MASK; + write_c0_entryhi(page); + tlb_probe(); + idx = read_c0_index(); + write_c0_entrylo0(0); + write_c0_entrylo1(0); + if (idx >= 0) { + /* Make sure all entries differ. */ + write_c0_entryhi(KSEG0+(idx<<(PAGE_SHIFT+1))); + tlb_write_indexed(); + } + write_c0_entryhi(oldpid); + + local_irq_restore(flags); +} + +/* All entries common to a mm share an asid. To effectively flush + these entries, we just bump the asid. */ +void local_flush_tlb_mm(struct mm_struct *mm) +{ + int cpu = smp_processor_id(); + if (cpu_context(cpu, mm) != 0) { + drop_mmu_context(mm, cpu); + } +} + +/* Stolen from mips32 routines */ + +void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte) +{ + unsigned long flags; + pgd_t *pgdp; + pmd_t *pmdp; + pte_t *ptep; + int idx, pid; + + /* + * Handle debugger faulting in for debugee. + */ + if (current->active_mm != vma->vm_mm) + return; + + local_irq_save(flags); + + pid = read_c0_entryhi() & ASID_MASK; + address &= (PAGE_MASK << 1); + write_c0_entryhi(address | (pid)); + pgdp = pgd_offset(vma->vm_mm, address); + tlb_probe(); + pmdp = pmd_offset(pgdp, address); + idx = read_c0_index(); + ptep = pte_offset_map(pmdp, address); + write_c0_entrylo0(pte_val(*ptep++) >> 6); + write_c0_entrylo1(pte_val(*ptep) >> 6); + if (idx < 0) { + tlb_write_random(); + } else { + tlb_write_indexed(); + } + local_irq_restore(flags); +} + +/* + * This is called from loadmmu.c. We have to set up all the + * memory management function pointers, as well as initialize + * the caches and tlbs + */ +void sb1_tlb_init(void) +{ + u32 config1; + + write_c0_pagemask(PM_4K); + config1 = read_c0_config1(); + current_cpu_data.tlbsize = ((config1 >> 25) & 0x3f) + 1; + + /* + * We don't know what state the firmware left the TLB's in, so this is + * the ultra-conservative way to flush the TLB's and avoid machine + * check exceptions due to duplicate TLB entries + */ + sb1_sanitize_tlb(); + + memcpy((void *)KSEG0, except_vec0_sb1, 0x80); + flush_icache_range(KSEG0, KSEG0 + 0x80); +} diff -Nru a/arch/mips/mm/tlbex-r3k.S b/arch/mips/mm/tlbex-r3k.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/mm/tlbex-r3k.S Tue Jul 1 18:44:40 2003 @@ -0,0 +1,225 @@ +/* + * TLB exception handling code for R2000/R3000. + * + * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse + * + * Multi-CPU abstraction reworking: + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * Further modifications to make this work: + * Copyright (c) 1998 Harald Koerfgen + * Copyright (c) 1998, 1999 Gleb Raiko & Vladimir Roganov + * Copyright (c) 2001 Ralf Baechle + * Copyright (c) 2001 MIPS Technologies, Inc. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TLB_OPTIMIZE /* If you are paranoid, disable this. */ + + .text + .set mips1 + .set noreorder + + __INIT + + /* TLB refill, R[23]00 version */ + LEAF(except_vec0_r2300) + .set noat + .set mips1 + mfc0 k0, CP0_BADVADDR + lw k1, pgd_current # get pgd pointer + srl k0, k0, 22 + sll k0, k0, 2 + addu k1, k1, k0 + mfc0 k0, CP0_CONTEXT + lw k1, (k1) + and k0, k0, 0xffc + addu k1, k1, k0 + lw k0, (k1) + nop + mtc0 k0, CP0_ENTRYLO0 + mfc0 k1, CP0_EPC + tlbwr + jr k1 + rfe + END(except_vec0_r2300) + + __FINIT + + /* ABUSE of CPP macros 101. */ + + /* After this macro runs, the pte faulted on is + * in register PTE, a ptr into the table in which + * the pte belongs is in PTR. + */ +#define LOAD_PTE(pte, ptr) \ + mfc0 pte, CP0_BADVADDR; \ + lw ptr, pgd_current; \ + srl pte, pte, 22; \ + sll pte, pte, 2; \ + addu ptr, ptr, pte; \ + mfc0 pte, CP0_CONTEXT; \ + lw ptr, (ptr); \ + andi pte, pte, 0xffc; \ + addu ptr, ptr, pte; \ + lw pte, (ptr); \ + nop; + + /* This places the even/odd pte pair in the page + * table at PTR into ENTRYLO0 and ENTRYLO1 using + * TMP as a scratch register. + */ +#define PTE_RELOAD(ptr) \ + lw ptr, (ptr) ; \ + nop ; \ + mtc0 ptr, CP0_ENTRYLO0; \ + nop; + +#define DO_FAULT(write) \ + .set noat; \ + .set macro; \ + SAVE_ALL; \ + mfc0 a2, CP0_BADVADDR; \ + KMODE; \ + .set at; \ + move a0, sp; \ + jal do_page_fault; \ + li a1, write; \ + j ret_from_exception; \ + nop; \ + .set noat; \ + .set nomacro; + + /* Check is PTE is present, if not then jump to LABEL. + * PTR points to the page table where this PTE is located, + * when the macro is done executing PTE will be restored + * with it's original value. + */ +#define PTE_PRESENT(pte, ptr, label) \ + andi pte, pte, (_PAGE_PRESENT | _PAGE_READ); \ + xori pte, pte, (_PAGE_PRESENT | _PAGE_READ); \ + bnez pte, label; \ + .set push; \ + .set reorder; \ + lw pte, (ptr); \ + .set pop; + + /* Make PTE valid, store result in PTR. */ +#define PTE_MAKEVALID(pte, ptr) \ + ori pte, pte, (_PAGE_VALID | _PAGE_ACCESSED); \ + sw pte, (ptr); + + /* Check if PTE can be written to, if not branch to LABEL. + * Regardless restore PTE with value from PTR when done. + */ +#define PTE_WRITABLE(pte, ptr, label) \ + andi pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \ + xori pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \ + bnez pte, label; \ + .set push; \ + .set reorder; \ + lw pte, (ptr); \ + .set pop; + + + /* Make PTE writable, update software status bits as well, + * then store at PTR. + */ +#define PTE_MAKEWRITE(pte, ptr) \ + ori pte, pte, (_PAGE_ACCESSED | _PAGE_MODIFIED | \ + _PAGE_VALID | _PAGE_DIRTY); \ + sw pte, (ptr); + +/* + * The index register may have the probe fail bit set, + * because we would trap on access kseg2, i.e. without refill. + */ +#define TLB_WRITE(reg) \ + mfc0 reg, CP0_INDEX; \ + nop; \ + bltz reg, 1f; \ + nop; \ + tlbwi; \ + j 2f; \ + nop; \ +1: tlbwr; \ +2: + +#define RET(reg) \ + mfc0 reg, CP0_EPC; \ + nop; \ + jr reg; \ + rfe + + .set noreorder + + .align 5 +NESTED(handle_tlbl, PT_SIZE, sp) + .set noat + +#ifdef TLB_OPTIMIZE + /* Test present bit in entry. */ + LOAD_PTE(k0, k1) + tlbp + PTE_PRESENT(k0, k1, nopage_tlbl) + PTE_MAKEVALID(k0, k1) + PTE_RELOAD(k1) + TLB_WRITE(k0) + RET(k0) +nopage_tlbl: +#endif + + DO_FAULT(0) +END(handle_tlbl) + +NESTED(handle_tlbs, PT_SIZE, sp) + .set noat + +#ifdef TLB_OPTIMIZE + LOAD_PTE(k0, k1) + tlbp # find faulting entry + PTE_WRITABLE(k0, k1, nopage_tlbs) + PTE_MAKEWRITE(k0, k1) + PTE_RELOAD(k1) + TLB_WRITE(k0) + RET(k0) +nopage_tlbs: +#endif + + DO_FAULT(1) +END(handle_tlbs) + + .align 5 +NESTED(handle_mod, PT_SIZE, sp) + .set noat +#ifdef TLB_OPTIMIZE + LOAD_PTE(k0, k1) + tlbp # find faulting entry + andi k0, k0, _PAGE_WRITE + beqz k0, nowrite_mod + .set push + .set reorder + lw k0, (k1) + .set pop + + /* Present and writable bits set, set accessed and dirty bits. */ + PTE_MAKEWRITE(k0, k1) + + /* Now reload the entry into the tlb. */ + PTE_RELOAD(k1) + tlbwi + RET(k0) +#endif + +nowrite_mod: + DO_FAULT(1) +END(handle_mod) diff -Nru a/arch/mips/mm/tlbex-r4k.S b/arch/mips/mm/tlbex-r4k.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/mm/tlbex-r4k.S Tue Jul 1 18:44:40 2003 @@ -0,0 +1,532 @@ +/* + * TLB exception handling code for r4k. + * + * Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Andreas Busse + * + * Multi-cpu abstraction and reworking: + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. + */ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TLB_OPTIMIZE /* If you are paranoid, disable this. */ + +#ifdef CONFIG_64BIT_PHYS_ADDR +#define PTE_L ld +#define PTE_S sd +#define PTE_SRL dsrl +#define P_MTC0 dmtc0 +#define PTE_SIZE 8 +#define PTEP_INDX_MSK 0xff0 +#define PTE_INDX_MSK 0xff8 +#define PTE_INDX_SHIFT 9 +#else +#define PTE_L lw +#define PTE_S sw +#define PTE_SRL srl +#define P_MTC0 mtc0 +#define PTE_SIZE 4 +#define PTEP_INDX_MSK 0xff8 +#define PTE_INDX_MSK 0xffc +#define PTE_INDX_SHIFT 10 +#endif + +/* + * ABUSE of CPP macros 101. + * + * After this macro runs, the pte faulted on is + * in register PTE, a ptr into the table in which + * the pte belongs is in PTR. + */ + +#ifdef CONFIG_SMP +#define GET_PGD(scratch, ptr) \ + mfc0 ptr, CP0_CONTEXT; \ + la scratch, pgd_current;\ + srl ptr, 23; \ + sll ptr, 2; \ + addu ptr, scratch, ptr; \ + lw ptr, (ptr); +#else +#define GET_PGD(scratch, ptr) \ + lw ptr, pgd_current; +#endif + +#define LOAD_PTE(pte, ptr) \ + GET_PGD(pte, ptr) \ + mfc0 pte, CP0_BADVADDR; \ + srl pte, pte, _PGDIR_SHIFT; \ + sll pte, pte, 2; \ + addu ptr, ptr, pte; \ + mfc0 pte, CP0_BADVADDR; \ + lw ptr, (ptr); \ + srl pte, pte, PTE_INDX_SHIFT; \ + and pte, pte, PTE_INDX_MSK; \ + addu ptr, ptr, pte; \ + PTE_L pte, (ptr); + + /* This places the even/odd pte pair in the page + * table at PTR into ENTRYLO0 and ENTRYLO1 using + * TMP as a scratch register. + */ +#define PTE_RELOAD(ptr, tmp) \ + ori ptr, ptr, PTE_SIZE; \ + xori ptr, ptr, PTE_SIZE; \ + PTE_L tmp, PTE_SIZE(ptr); \ + PTE_L ptr, 0(ptr); \ + PTE_SRL tmp, tmp, 6; \ + P_MTC0 tmp, CP0_ENTRYLO1; \ + PTE_SRL ptr, ptr, 6; \ + P_MTC0 ptr, CP0_ENTRYLO0; + +#define DO_FAULT(write) \ + .set noat; \ + SAVE_ALL; \ + mfc0 a2, CP0_BADVADDR; \ + KMODE; \ + .set at; \ + move a0, sp; \ + jal do_page_fault; \ + li a1, write; \ + j ret_from_exception; \ + nop; \ + .set noat; + + /* Check is PTE is present, if not then jump to LABEL. + * PTR points to the page table where this PTE is located, + * when the macro is done executing PTE will be restored + * with it's original value. + */ +#define PTE_PRESENT(pte, ptr, label) \ + andi pte, pte, (_PAGE_PRESENT | _PAGE_READ); \ + xori pte, pte, (_PAGE_PRESENT | _PAGE_READ); \ + bnez pte, label; \ + PTE_L pte, (ptr); + + /* Make PTE valid, store result in PTR. */ +#define PTE_MAKEVALID(pte, ptr) \ + ori pte, pte, (_PAGE_VALID | _PAGE_ACCESSED); \ + PTE_S pte, (ptr); + + /* Check if PTE can be written to, if not branch to LABEL. + * Regardless restore PTE with value from PTR when done. + */ +#define PTE_WRITABLE(pte, ptr, label) \ + andi pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \ + xori pte, pte, (_PAGE_PRESENT | _PAGE_WRITE); \ + bnez pte, label; \ + PTE_L pte, (ptr); + + /* Make PTE writable, update software status bits as well, + * then store at PTR. + */ +#define PTE_MAKEWRITE(pte, ptr) \ + ori pte, pte, (_PAGE_ACCESSED | _PAGE_MODIFIED | \ + _PAGE_VALID | _PAGE_DIRTY); \ + PTE_S pte, (ptr); + + __INIT + +#ifdef CONFIG_64BIT_PHYS_ADDR +#define GET_PTE_OFF(reg) +#elif CONFIG_CPU_VR41XX +#define GET_PTE_OFF(reg) srl reg, reg, 3 +#else +#define GET_PTE_OFF(reg) srl reg, reg, 1 +#endif + +/* + * These handlers much be written in a relocatable manner + * because based upon the cpu type an arbitrary one of the + * following pieces of code will be copied to the KSEG0 + * vector location. + */ + /* TLB refill, EXL == 0, R4xx0, non-R4600 version */ + .set noreorder + .set noat + LEAF(except_vec0_r4000) + .set mips3 + GET_PGD(k0, k1) # get pgd pointer + mfc0 k0, CP0_BADVADDR # Get faulting address + srl k0, k0, _PGDIR_SHIFT # get pgd only bits + + sll k0, k0, 2 + addu k1, k1, k0 # add in pgd offset + mfc0 k0, CP0_CONTEXT # get context reg + lw k1, (k1) + GET_PTE_OFF(k0) # get pte offset + and k0, k0, PTEP_INDX_MSK + addu k1, k1, k0 # add in offset + PTE_L k0, 0(k1) # get even pte + PTE_L k1, PTE_SIZE(k1) # get odd pte + PTE_SRL k0, k0, 6 # convert to entrylo0 + P_MTC0 k0, CP0_ENTRYLO0 # load it + PTE_SRL k1, k1, 6 # convert to entrylo1 + P_MTC0 k1, CP0_ENTRYLO1 # load it + b 1f + tlbwr # write random tlb entry +1: + nop + eret # return from trap + END(except_vec0_r4000) + + /* TLB refill, EXL == 0, R4600 version */ + LEAF(except_vec0_r4600) + .set mips3 + GET_PGD(k0, k1) # get pgd pointer + mfc0 k0, CP0_BADVADDR + srl k0, k0, _PGDIR_SHIFT + sll k0, k0, 2 # log2(sizeof(pgd_t) + addu k1, k1, k0 + mfc0 k0, CP0_CONTEXT + lw k1, (k1) + GET_PTE_OFF(k0) # get pte offset + and k0, k0, PTEP_INDX_MSK + addu k1, k1, k0 + PTE_L k0, 0(k1) + PTE_L k1, PTE_SIZE(k1) + PTE_SRL k0, k0, 6 + P_MTC0 k0, CP0_ENTRYLO0 + PTE_SRL k1, k1, 6 + P_MTC0 k1, CP0_ENTRYLO1 + nop + tlbwr + nop + eret + END(except_vec0_r4600) + + /* TLB refill, EXL == 0, R52x0 "Nevada" version */ + /* + * This version has a bug workaround for the Nevada. It seems + * as if under certain circumstances the move from cp0_context + * might produce a bogus result when the mfc0 instruction and + * it's consumer are in a different cacheline or a load instruction, + * probably any memory reference, is between them. This is + * potencially slower than the R4000 version, so we use this + * special version. + */ + .set noreorder + .set noat + LEAF(except_vec0_nevada) + .set mips3 + mfc0 k0, CP0_BADVADDR # Get faulting address + srl k0, k0, _PGDIR_SHIFT # get pgd only bits + lw k1, pgd_current # get pgd pointer + sll k0, k0, 2 # log2(sizeof(pgd_t) + addu k1, k1, k0 # add in pgd offset + lw k1, (k1) + mfc0 k0, CP0_CONTEXT # get context reg + GET_PTE_OFF(k0) # get pte offset + and k0, k0, PTEP_INDX_MSK + addu k1, k1, k0 # add in offset + PTE_L k0, 0(k1) # get even pte + PTE_L k1, PTE_SIZE(k1) # get odd pte + PTE_SRL k0, k0, 6 # convert to entrylo0 + P_MTC0 k0, CP0_ENTRYLO0 # load it + PTE_SRL k1, k1, 6 # convert to entrylo1 + P_MTC0 k1, CP0_ENTRYLO1 # load it + nop # QED specified nops + nop + tlbwr # write random tlb entry + nop # traditional nop + eret # return from trap + END(except_vec0_nevada) + + /* TLB refill, EXL == 0, SB1 with M3 errata handling version */ + LEAF(except_vec0_sb1) +#if BCM1250_M3_WAR + mfc0 k0, CP0_BADVADDR + mfc0 k1, CP0_ENTRYHI + xor k0, k1 + srl k0, k0, PAGE_SHIFT+1 + bnez k0, 1f +#endif + GET_PGD(k0, k1) # get pgd pointer + mfc0 k0, CP0_BADVADDR # Get faulting address + srl k0, k0, _PGDIR_SHIFT # get pgd only bits + sll k0, k0, 2 + addu k1, k1, k0 # add in pgd offset + mfc0 k0, CP0_CONTEXT # get context reg + lw k1, (k1) + GET_PTE_OFF(k0) # get pte offset + and k0, k0, PTEP_INDX_MSK + addu k1, k1, k0 # add in offset + PTE_L k0, 0(k1) # get even pte + PTE_L k1, PTE_SIZE(k1) # get odd pte + PTE_SRL k0, k0, 6 # convert to entrylo0 + P_MTC0 k0, CP0_ENTRYLO0 # load it + PTE_SRL k1, k1, 6 # convert to entrylo1 + P_MTC0 k1, CP0_ENTRYLO1 # load it + tlbwr # write random tlb entry +1: eret # return from trap + END(except_vec0_sb1) + + /* TLB refill, EXL == 0, R4[40]00/R5000 badvaddr hwbug version */ + LEAF(except_vec0_r45k_bvahwbug) + .set mips3 + GET_PGD(k0, k1) # get pgd pointer + mfc0 k0, CP0_BADVADDR + srl k0, k0, _PGDIR_SHIFT + sll k0, k0, 2 # log2(sizeof(pgd_t) + addu k1, k1, k0 + mfc0 k0, CP0_CONTEXT + lw k1, (k1) +#ifndef CONFIG_64BIT_PHYS_ADDR + srl k0, k0, 1 +#endif + and k0, k0, PTEP_INDX_MSK + addu k1, k1, k0 + PTE_L k0, 0(k1) + PTE_L k1, PTE_SIZE(k1) + nop /* XXX */ + tlbp + PTE_SRL k0, k0, 6 + P_MTC0 k0, CP0_ENTRYLO0 + PTE_SRL k1, k1, 6 + mfc0 k0, CP0_INDEX + P_MTC0 k1, CP0_ENTRYLO1 + bltzl k0, 1f + tlbwr +1: + nop + eret + END(except_vec0_r45k_bvahwbug) + +#ifdef CONFIG_SMP + /* TLB refill, EXL == 0, R4000 MP badvaddr hwbug version */ + LEAF(except_vec0_r4k_mphwbug) + .set mips3 + GET_PGD(k0, k1) # get pgd pointer + mfc0 k0, CP0_BADVADDR + srl k0, k0, _PGDIR_SHIFT + sll k0, k0, 2 # log2(sizeof(pgd_t) + addu k1, k1, k0 + mfc0 k0, CP0_CONTEXT + lw k1, (k1) +#ifndef CONFIG_64BIT_PHYS_ADDR + srl k0, k0, 1 +#endif + and k0, k0, PTEP_INDX_MSK + addu k1, k1, k0 + PTE_L k0, 0(k1) + PTE_L k1, PTE_SIZE(k1) + nop /* XXX */ + tlbp + PTE_SRL k0, k0, 6 + P_MTC0 k0, CP0_ENTRYLO0 + PTE_SRL k1, k1, 6 + mfc0 k0, CP0_INDEX + P_MTC0 k1, CP0_ENTRYLO1 + bltzl k0, 1f + tlbwr +1: + nop + eret + END(except_vec0_r4k_mphwbug) +#endif + + /* TLB refill, EXL == 0, R4000 UP 250MHZ entrylo[01] hwbug version */ + LEAF(except_vec0_r4k_250MHZhwbug) + .set mips3 + GET_PGD(k0, k1) # get pgd pointer + mfc0 k0, CP0_BADVADDR + srl k0, k0, _PGDIR_SHIFT + sll k0, k0, 2 # log2(sizeof(pgd_t) + addu k1, k1, k0 + mfc0 k0, CP0_CONTEXT + lw k1, (k1) +#ifndef CONFIG_64BIT_PHYS_ADDR + srl k0, k0, 1 +#endif + and k0, k0, PTEP_INDX_MSK + addu k1, k1, k0 + PTE_L k0, 0(k1) + PTE_L k1, PTE_SIZE(k1) + PTE_SRL k0, k0, 6 + P_MTC0 zero, CP0_ENTRYLO0 + P_MTC0 k0, CP0_ENTRYLO0 + PTE_SRL k1, k1, 6 + P_MTC0 zero, CP0_ENTRYLO1 + P_MTC0 k1, CP0_ENTRYLO1 + b 1f + tlbwr +1: + nop + eret + END(except_vec0_r4k_250MHZhwbug) + +#ifdef CONFIG_SMP + /* TLB refill, EXL == 0, R4000 MP 250MHZ entrylo[01]+badvaddr bug version */ + LEAF(except_vec0_r4k_MP250MHZhwbug) + .set mips3 + GET_PGD(k0, k1) # get pgd pointer + mfc0 k0, CP0_BADVADDR + srl k0, k0, _PGDIR_SHIFT + sll k0, k0, 2 # log2(sizeof(pgd_t) + addu k1, k1, k0 + mfc0 k0, CP0_CONTEXT + lw k1, (k1) +#ifndef CONFIG_64BIT_PHYS_ADDR + srl k0, k0, 1 +#endif + and k0, k0, PTEP_INDX_MSK + addu k1, k1, k0 + PTE_L k0, 0(k1) + PTE_L k1, PTE_SIZE(k1) + nop /* XXX */ + tlbp + PTE_SRL k0, k0, 6 + P_MTC0 zero, CP0_ENTRYLO0 + P_MTC0 k0, CP0_ENTRYLO0 + mfc0 k0, CP0_INDEX + PTE_SRL k1, k1, 6 + P_MTC0 zero, CP0_ENTRYLO1 + P_MTC0 k1, CP0_ENTRYLO1 + bltzl k0, 1f + tlbwr +1: + nop + eret + END(except_vec0_r4k_MP250MHZhwbug) +#endif + + __FINIT + + .set noreorder + +/* + * From the IDT errata for the QED RM5230 (Nevada), processor revision 1.0: + * 2. A timing hazard exists for the TLBP instruction. + * + * stalling_instruction + * TLBP + * + * The JTLB is being read for the TLBP throughout the stall generated by the + * previous instruction. This is not really correct as the stalling instruction + * can modify the address used to access the JTLB. The failure symptom is that + * the TLBP instruction will use an address created for the stalling instruction + * and not the address held in C0_ENHI and thus report the wrong results. + * + * The software work-around is to not allow the instruction preceding the TLBP + * to stall - make it an NOP or some other instruction guaranteed not to stall. + * + * Errata 2 will not be fixed. This errata is also on the R5000. + * + * As if we MIPS hackers wouldn't know how to nop pipelines happy ... + */ +#define R5K_HAZARD nop + + /* + * Note for many R4k variants tlb probes cannot be executed out + * of the instruction cache else you get bogus results. + */ + .align 5 + NESTED(handle_tlbl, PT_SIZE, sp) + .set noat +#if BCM1250_M3_WAR + mfc0 k0, CP0_BADVADDR + mfc0 k1, CP0_ENTRYHI + xor k0, k1 + srl k0, k0, PAGE_SHIFT+1 + beqz k0, 1f + nop + .set mips3 + eret + .set mips0 +1: +#endif +invalid_tlbl: +#ifdef TLB_OPTIMIZE + /* Test present bit in entry. */ + LOAD_PTE(k0, k1) + R5K_HAZARD + tlbp + PTE_PRESENT(k0, k1, nopage_tlbl) + PTE_MAKEVALID(k0, k1) + PTE_RELOAD(k1, k0) + nop + b 1f + tlbwi +1: + nop + .set mips3 + eret + .set mips0 +#endif + +nopage_tlbl: + DO_FAULT(0) + END(handle_tlbl) + + .align 5 + NESTED(handle_tlbs, PT_SIZE, sp) + .set noat +#ifdef TLB_OPTIMIZE + .set mips3 + li k0,0 + LOAD_PTE(k0, k1) + R5K_HAZARD + tlbp # find faulting entry + PTE_WRITABLE(k0, k1, nopage_tlbs) + PTE_MAKEWRITE(k0, k1) + PTE_RELOAD(k1, k0) + nop + b 1f + tlbwi +1: + nop + .set mips3 + eret + .set mips0 +#endif + +nopage_tlbs: + DO_FAULT(1) + END(handle_tlbs) + + .align 5 + NESTED(handle_mod, PT_SIZE, sp) + .set noat +#ifdef TLB_OPTIMIZE + .set mips3 + LOAD_PTE(k0, k1) + R5K_HAZARD + tlbp # find faulting entry + andi k0, k0, _PAGE_WRITE + beqz k0, nowrite_mod + PTE_L k0, (k1) + + /* Present and writable bits set, set accessed and dirty bits. */ + PTE_MAKEWRITE(k0, k1) + + /* Now reload the entry into the tlb. */ + PTE_RELOAD(k1, k0) + nop + b 1f + tlbwi +1: + nop + .set mips3 + eret + .set mips0 +#endif + +nowrite_mod: + DO_FAULT(1) + END(handle_mod) + diff -Nru a/arch/mips/mm/umap.c b/arch/mips/mm/umap.c --- a/arch/mips/mm/umap.c Tue Jul 1 18:44:37 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,222 +0,0 @@ -/* - * (C) Copyright 1994 Linus Torvalds - * - * Changes: - * - * Modified from Linus source to removing active mappings from any - * task. This is required for implementing the virtual graphics - * interface for direct rendering on the SGI - miguel. - * - * Added a routine to map a vmalloc()ed area into user space, this one - * is required by the /dev/shmiq driver - miguel. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -static inline void -remove_mapping_pte_range (pmd_t *pmd, unsigned long address, unsigned long size) -{ - pte_t *pte; - unsigned long end; - - if (pmd_none (*pmd)) - return; - if (pmd_bad (*pmd)){ - printk ("remove_graphics_pte_range: bad pmd (%08lx)\n", pmd_val (*pmd)); - pmd_clear (pmd); - return; - } - pte = pte_offset (pmd, address); - address &= ~PMD_MASK; - end = address + size; - if (end > PMD_SIZE) - end = PMD_SIZE; - do { - pte_t entry = *pte; - if (pte_present (entry)) - set_pte (pte, pte_modify (entry, PAGE_NONE)); - address += PAGE_SIZE; - pte++; - } while (address < end); - -} - -static inline void -remove_mapping_pmd_range (pgd_t *pgd, unsigned long address, unsigned long size) -{ - pmd_t *pmd; - unsigned long end; - - if (pgd_none (*pgd)) - return; - - if (pgd_bad (*pgd)){ - printk ("remove_graphics_pmd_range: bad pgd (%08lx)\n", pgd_val (*pgd)); - pgd_clear (pgd); - return; - } - pmd = pmd_offset (pgd, address); - address &= ~PGDIR_MASK; - end = address + size; - if (end > PGDIR_SIZE) - end = PGDIR_SIZE; - do { - remove_mapping_pte_range (pmd, address, end - address); - address = (address + PMD_SIZE) & PMD_MASK; - pmd++; - } while (address < end); - -} - -/* - * This routine is called from the page fault handler to remove a - * range of active mappings at this point - */ -void -remove_mapping (struct vm_area_struct *vma, struct task_struct *task, unsigned long start, unsigned long end) -{ - unsigned long beg = start; - pgd_t *dir; - - down_write (&task->mm->mmap_sem); - dir = pgd_offset (task->mm, start); - flush_cache_range (vma, beg, end); - while (start < end){ - remove_mapping_pmd_range (dir, start, end - start); - start = (start + PGDIR_SIZE) & PGDIR_MASK; - dir++; - } - flush_tlb_range (vma, beg, end); - up_write (&task->mm->mmap_sem); -} - -EXPORT_SYMBOL(remove_mapping); - -void *vmalloc_uncached (unsigned long size) -{ - return __vmalloc (size, GFP_KERNEL | __GFP_HIGHMEM, - PAGE_KERNEL_UNCACHED); -} - -static inline void free_pte(pte_t page) -{ - if (pte_present(page)) { - unsigned long pfn = pte_pfn(page); - struct page *ptpage; - if (!pfn_valid(pfn)) - return; - ptpage = pfn_to_page(pfn); - if (PageReserved(ptpage)) - return; - __free_page(ptpage); - if (current->mm->rss <= 0) - return; - current->mm->rss--; - return; - } - swap_free(pte_to_swp_entry(page)); -} - -static inline void forget_pte(pte_t page) -{ - if (!pte_none(page)) { - printk("forget_pte: old mapping existed!\n"); - free_pte(page); - } -} - -/* - * maps a range of vmalloc()ed memory into the requested pages. the old - * mappings are removed. - */ -static inline void -vmap_pte_range (pte_t *pte, unsigned long address, unsigned long size, unsigned long vaddr) -{ - unsigned long end; - pgd_t *vdir; - pmd_t *vpmd; - pte_t *vpte; - - address &= ~PMD_MASK; - end = address + size; - if (end > PMD_SIZE) - end = PMD_SIZE; - do { - pte_t oldpage = *pte; - struct page * page; - pte_clear(pte); - - vdir = pgd_offset_k (vaddr); - vpmd = pmd_offset (vdir, vaddr); - vpte = pte_offset (vpmd, vaddr); - page = pte_page (*vpte); - - set_pte(pte, mk_pte(page, PAGE_USERIO)); - forget_pte(oldpage); - address += PAGE_SIZE; - vaddr += PAGE_SIZE; - pte++; - } while (address < end); -} - -static inline int -vmap_pmd_range (pmd_t *pmd, unsigned long address, unsigned long size, unsigned long vaddr) -{ - unsigned long end; - - address &= ~PGDIR_MASK; - end = address + size; - if (end > PGDIR_SIZE) - end = PGDIR_SIZE; - vaddr -= address; - do { - pte_t * pte = pte_alloc(current->mm, pmd, address); - if (!pte) - return -ENOMEM; - vmap_pte_range(pte, address, end - address, address + vaddr); - address = (address + PMD_SIZE) & PMD_MASK; - pmd++; - } while (address < end); - return 0; -} - -int -vmap_page_range (struct vm_area_struct *vma, unsigned long from, unsigned long size, unsigned long vaddr) -{ - int error = 0; - pgd_t * dir; - unsigned long beg = from; - unsigned long end = from + size; - - vaddr -= from; - dir = pgd_offset(current->mm, from); - flush_cache_range(vma, beg, end); - while (from < end) { - pmd_t *pmd = pmd_alloc(current->mm, dir, from); - error = -ENOMEM; - if (!pmd) - break; - error = vmap_pmd_range(pmd, from, end - from, vaddr + from); - if (error) - break; - from = (from + PGDIR_SIZE) & PGDIR_MASK; - dir++; - } - flush_tlb_range(vma, beg, end); - return error; -} diff -Nru a/arch/mips/momentum/ocelot_c/Makefile b/arch/mips/momentum/ocelot_c/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/momentum/ocelot_c/Makefile Tue Jul 1 18:44:40 2003 @@ -0,0 +1,8 @@ +# +# Makefile for Momentum Computer's Ocelot-C and -CS boards. +# + +obj-y += mv-irq.o cpci-irq.o uart-irq.o int-handler.o irq.o \ + pci-irq.o prom.o reset.o setup.o + +obj-$(CONFIG_KGDB) += dbg_io.o diff -Nru a/arch/mips/momentum/ocelot_c/cpci-irq.c b/arch/mips/momentum/ocelot_c/cpci-irq.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/momentum/ocelot_c/cpci-irq.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,154 @@ +/* + * Copyright 2002 Momentum Computer + * Author: mdharm@momenco.com + * + * arch/mips/momentum/ocelot_c/cpci-irq.c + * Interrupt routines for cpci. Interrupt numbers are assigned from + * CPCI_IRQ_BASE to CPCI_IRQ_BASE+8 (8 interrupt sources). + * + * Note that the high-level software will need to be careful about using + * these interrupts. If this board is asserting a cPCI interrupt, it will + * also see the asserted interrupt. Care must be taken to avoid an + * interrupt flood. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ocelot_c_fpga.h" + +#define CPCI_IRQ_BASE 8 + +static inline int ls1bit8(unsigned int x) +{ + int b = 7, s; + + s = 4; if (((unsigned char)(x << 4)) == 0) s = 0; b -= s; x <<= s; + s = 2; if (((unsigned char)(x << 2)) == 0) s = 0; b -= s; x <<= s; + s = 1; if (((unsigned char)(x << 1)) == 0) s = 0; b -= s; + + return b; +} + +/* mask off an interrupt -- 0 is enable, 1 is disable */ +static inline void mask_cpci_irq(unsigned int irq) +{ + uint32_t value; + + value = OCELOT_FPGA_READ(INTMASK); + value |= 1 << (irq - CPCI_IRQ_BASE); + OCELOT_FPGA_WRITE(value, INTMASK); + + /* read the value back to assure that it's really been written */ + value = OCELOT_FPGA_READ(INTMASK); +} + +/* unmask an interrupt -- 0 is enable, 1 is disable */ +static inline void unmask_cpci_irq(unsigned int irq) +{ + uint32_t value; + + value = OCELOT_FPGA_READ(INTMASK); + value &= ~(1 << (irq - CPCI_IRQ_BASE)); + OCELOT_FPGA_WRITE(value, INTMASK); + + /* read the value back to assure that it's really been written */ + value = OCELOT_FPGA_READ(INTMASK); +} + +/* + * Enables the IRQ in the FPGA + */ +static void enable_cpci_irq(unsigned int irq) +{ + unmask_cpci_irq(irq); +} + +/* + * Initialize the IRQ in the FPGA + */ +static unsigned int startup_cpci_irq(unsigned int irq) +{ + unmask_cpci_irq(irq); + return 0; +} + +/* + * Disables the IRQ in the FPGA + */ +static void disable_cpci_irq(unsigned int irq) +{ + mask_cpci_irq(irq); +} + +/* + * Masks and ACKs an IRQ + */ +static void mask_and_ack_cpci_irq(unsigned int irq) +{ + mask_cpci_irq(irq); +} + +/* + * End IRQ processing + */ +static void end_cpci_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + unmask_cpci_irq(irq); +} + +/* + * Interrupt handler for interrupts coming from the FPGA chip. + * It could be built in ethernet ports etc... + */ +void ll_cpci_irq(struct pt_regs *regs) +{ + unsigned int irq_src, irq_mask; + + /* read the interrupt status registers */ + irq_src = OCELOT_FPGA_READ(INTSTAT); + irq_mask = OCELOT_FPGA_READ(INTMASK); + + /* mask for just the interrupts we want */ + irq_src &= ~irq_mask; + + do_IRQ(ls1bit8(irq_src) + CPCI_IRQ_BASE, regs); +} + +#define shutdown_cpci_irq disable_cpci_irq + +struct hw_interrupt_type cpci_irq_type = { + "CPCI/FPGA", + startup_cpci_irq, + shutdown_cpci_irq, + enable_cpci_irq, + disable_cpci_irq, + mask_and_ack_cpci_irq, + end_cpci_irq, + NULL +}; + +void cpci_irq_init(void) +{ + int i; + + /* Reset irq handlers pointers to NULL */ + for (i = CPCI_IRQ_BASE; i < (CPCI_IRQ_BASE + 8); i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = 2; + irq_desc[i].handler = &cpci_irq_type; + } +} diff -Nru a/arch/mips/momentum/ocelot_c/dbg_io.c b/arch/mips/momentum/ocelot_c/dbg_io.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/momentum/ocelot_c/dbg_io.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,126 @@ +#include + +#if defined(CONFIG_KGDB) + +#include /* For the serial port location and base baud */ + +/* --- CONFIG --- */ + +typedef unsigned char uint8; +typedef unsigned int uint32; + +/* --- END OF CONFIG --- */ + +#define UART16550_BAUD_2400 2400 +#define UART16550_BAUD_4800 4800 +#define UART16550_BAUD_9600 9600 +#define UART16550_BAUD_19200 19200 +#define UART16550_BAUD_38400 38400 +#define UART16550_BAUD_57600 57600 +#define UART16550_BAUD_115200 115200 + +#define UART16550_PARITY_NONE 0 +#define UART16550_PARITY_ODD 0x08 +#define UART16550_PARITY_EVEN 0x18 +#define UART16550_PARITY_MARK 0x28 +#define UART16550_PARITY_SPACE 0x38 + +#define UART16550_DATA_5BIT 0x0 +#define UART16550_DATA_6BIT 0x1 +#define UART16550_DATA_7BIT 0x2 +#define UART16550_DATA_8BIT 0x3 + +#define UART16550_STOP_1BIT 0x0 +#define UART16550_STOP_2BIT 0x4 + +/* ----------------------------------------------------- */ + +/* === CONFIG === */ + +/* [jsun] we use the second serial port for kdb */ +#define BASE OCELOT_SERIAL1_BASE +#define MAX_BAUD OCELOT_BASE_BAUD + +/* === END OF CONFIG === */ + +#define REG_OFFSET 4 + +/* register offset */ +#define OFS_RCV_BUFFER 0 +#define OFS_TRANS_HOLD 0 +#define OFS_SEND_BUFFER 0 +#define OFS_INTR_ENABLE (1*REG_OFFSET) +#define OFS_INTR_ID (2*REG_OFFSET) +#define OFS_DATA_FORMAT (3*REG_OFFSET) +#define OFS_LINE_CONTROL (3*REG_OFFSET) +#define OFS_MODEM_CONTROL (4*REG_OFFSET) +#define OFS_RS232_OUTPUT (4*REG_OFFSET) +#define OFS_LINE_STATUS (5*REG_OFFSET) +#define OFS_MODEM_STATUS (6*REG_OFFSET) +#define OFS_RS232_INPUT (6*REG_OFFSET) +#define OFS_SCRATCH_PAD (7*REG_OFFSET) + +#define OFS_DIVISOR_LSB (0*REG_OFFSET) +#define OFS_DIVISOR_MSB (1*REG_OFFSET) + + +/* memory-mapped read/write of the port */ +#define UART16550_READ(y) (*((volatile uint8*)(BASE + y))) +#define UART16550_WRITE(y, z) ((*((volatile uint8*)(BASE + y))) = z) + +void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop) +{ + /* disable interrupts */ + UART16550_WRITE(OFS_INTR_ENABLE, 0); + + /* set up buad rate */ + { + uint32 divisor; + + /* set DIAB bit */ + UART16550_WRITE(OFS_LINE_CONTROL, 0x80); + + /* set divisor */ + divisor = MAX_BAUD / baud; + UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff); + UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8); + + /* clear DIAB bit */ + UART16550_WRITE(OFS_LINE_CONTROL, 0x0); + } + + /* set data format */ + UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop); +} + +static int remoteDebugInitialized = 0; + +uint8 getDebugChar(void) +{ + if (!remoteDebugInitialized) { + remoteDebugInitialized = 1; + debugInit(UART16550_BAUD_38400, + UART16550_DATA_8BIT, + UART16550_PARITY_NONE, UART16550_STOP_1BIT); + } + + while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0); + return UART16550_READ(OFS_RCV_BUFFER); +} + + +int putDebugChar(uint8 byte) +{ + if (!remoteDebugInitialized) { + remoteDebugInitialized = 1; + debugInit(UART16550_BAUD_38400, + UART16550_DATA_8BIT, + UART16550_PARITY_NONE, UART16550_STOP_1BIT); + } + + while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0); + UART16550_WRITE(OFS_SEND_BUFFER, byte); + return 1; +} + +#endif diff -Nru a/arch/mips/momentum/ocelot_c/int-handler.S b/arch/mips/momentum/ocelot_c/int-handler.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/momentum/ocelot_c/int-handler.S Tue Jul 1 18:44:40 2003 @@ -0,0 +1,104 @@ +/* + * Copyright 2002 Momentum Computer Inc. + * Author: Matthew Dharm + * + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * First-level interrupt dispatcher for Ocelot-CS board. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#define __ASSEMBLY__ +#include +#include +#include +#include +#include +#include +#include "ocelot_c_fpga.h" + +/* + * First level interrupt dispatcher for Ocelot-CS board + */ + .align 5 + NESTED(ocelot_handle_int, PT_SIZE, sp) + SAVE_ALL + CLI + .set at + mfc0 t0, CP0_CAUSE + mfc0 t2, CP0_STATUS + + and t0, t2 + + andi t1, t0, STATUSF_IP0 /* sw0 software interrupt */ + bnez t1, ll_sw0_irq + andi t1, t0, STATUSF_IP1 /* sw1 software interrupt */ + bnez t1, ll_sw1_irq + andi t1, t0, STATUSF_IP2 /* int0 hardware line */ + bnez t1, ll_scsi_irq + andi t1, t0, STATUSF_IP3 /* int1 hardware line */ + bnez t1, ll_uart_decode_irq + andi t1, t0, STATUSF_IP4 /* int2 hardware line */ + bnez t1, ll_pmc_irq + andi t1, t0, STATUSF_IP5 /* int3 hardware line */ + bnez t1, ll_cpci_decode_irq + andi t1, t0, STATUSF_IP6 /* int4 hardware line */ + bnez t1, ll_mv64340_decode_irq + andi t1, t0, STATUSF_IP7 /* cpu timer */ + bnez t1, ll_cputimer_irq + + .set reorder + + /* wrong alarm or masked ... */ + j spurious_interrupt + nop + END(ocelot_handle_int) + + .align 5 +ll_sw0_irq: + li a0, 0 + move a1, sp + jal do_IRQ + j ret_from_irq +ll_sw1_irq: + li a0, 1 + move a1, sp + jal do_IRQ + j ret_from_irq +ll_scsi_irq: + li a0, 2 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_uart_decode_irq: + move a0, sp + jal ll_uart_irq + j ret_from_irq + +ll_pmc_irq: + li a0, 4 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_cpci_decode_irq: + move a0, sp + jal ll_cpci_irq + j ret_from_irq + +ll_mv64340_decode_irq: + move a0, sp + jal ll_mv64340_irq + j ret_from_irq + +ll_cputimer_irq: + li a0, 7 + move a1, sp + jal do_IRQ + j ret_from_irq + diff -Nru a/arch/mips/momentum/ocelot_c/irq.c b/arch/mips/momentum/ocelot_c/irq.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/momentum/ocelot_c/irq.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2000 RidgeRun, Inc. + * Author: RidgeRun, Inc. + * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com + * + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.org) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static spinlock_t irq_lock = SPIN_LOCK_UNLOCKED; + +/* Function for careful CP0 interrupt mask access */ +static inline void modify_cp0_intmask(unsigned clr_mask_in, unsigned set_mask_in) +{ + unsigned long status; + unsigned clr_mask; + unsigned set_mask; + + /* do the low 8 bits first */ + clr_mask = 0xff & clr_mask_in; + set_mask = 0xff & set_mask_in; + status = read_c0_status(); + status &= ~((clr_mask & 0xFF) << 8); + status |= (set_mask & 0xFF) << 8; + write_c0_status(status); +} + +static inline void mask_irq(unsigned int irq) +{ + modify_cp0_intmask(irq, 0); +} + +static inline void unmask_irq(unsigned int irq) +{ + modify_cp0_intmask(0, irq); +} + +static void enable_cp7000_irq(unsigned int irq) +{ + unsigned long flags; + + spin_lock_irqsave(&irq_lock, flags); + unmask_irq(1 << irq); + spin_unlock_irqrestore(&irq_lock, flags); +} + +static unsigned int startup_cp7000_irq(unsigned int irq) +{ + enable_cp7000_irq(irq); + + return 0; /* never anything pending */ +} + +static void disable_cp7000_irq(unsigned int irq) +{ + unsigned long flags; + + spin_lock_irqsave(&irq_lock, flags); + mask_irq(1 << irq); + spin_unlock_irqrestore(&irq_lock, flags); +} + +#define shutdown_cp7000_irq disable_cp7000_irq + +static void mask_and_ack_cp7000_irq(unsigned int irq) +{ + mask_irq(1 << irq); +} + +static void end_cp7000_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + unmask_irq(1 << irq); +} + +static struct hw_interrupt_type cp7000_hpcdma_irq_type = { +#ifdef CONFIG_CPU_SR71000 + "SR71000", +#else + "RM7000", +#endif + startup_cp7000_irq, + shutdown_cp7000_irq, + enable_cp7000_irq, + disable_cp7000_irq, + mask_and_ack_cp7000_irq, + end_cp7000_irq, + NULL +}; + +extern asmlinkage void ocelot_handle_int(void); +extern void mv64340_irq_init(void); +extern void uart_irq_init(void); +extern void cpci_irq_init(void); + +static struct irqaction cascade_fpga = + { no_action, SA_INTERRUPT, 0, "cascade via FPGA", NULL, NULL }; +static struct irqaction cascade_mv64340 = + { no_action, SA_INTERRUPT, 0, "cascade via MV64340", NULL, NULL }; + +void __init init_IRQ(void) +{ + int i; + + /* + * Clear all of the interrupts while we change the able around a bit. + * int-handler is not on bootstrap + */ + clear_c0_status(ST0_IM | ST0_BEV); + __cli(); + + /* Sets the first-level interrupt dispatcher. */ + set_except_vector(0, ocelot_handle_int); + init_generic_irq(); + + /* set up handler for first 8 IRQs as the CPU */ + for (i = 0; i < 8; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = 1; + irq_desc[i].handler = &cp7000_hpcdma_irq_type; + } + + /* set up the cascading interrupts */ + setup_irq(3, &cascade_fpga); + setup_irq(5, &cascade_fpga); + setup_irq(6, &cascade_mv64340); + + mv64340_irq_init(); + uart_irq_init(); + cpci_irq_init(); + +#ifdef CONFIG_KGDB + printk("start kgdb ...\n"); + set_debug_traps(); + breakpoint(); /* you may move this line to whereever you want :-) */ +#endif +#ifdef CONFIG_GDB_CONSOLE + register_gdb_console(); +#endif +} diff -Nru a/arch/mips/momentum/ocelot_c/mv-irq.c b/arch/mips/momentum/ocelot_c/mv-irq.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/momentum/ocelot_c/mv-irq.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,164 @@ +/* + * Copyright 2002 Momentum Computer + * Author: mdharm@momenco.com + * + * arch/mips/momentum/ocelot_c/mv-irq.c + * Interrupt routines for mv64340. Interrupt numbers are assigned from + * MV64340_IRQ_BASE to MV64340_IRQ_BASE+64. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MV64340_IRQ_BASE 16 + +static inline int ls1bit32(unsigned int x) +{ + int b = 31, s; + + s = 16; if (x << 16 == 0) s = 0; b -= s; x <<= s; + s = 8; if (x << 8 == 0) s = 0; b -= s; x <<= s; + s = 4; if (x << 4 == 0) s = 0; b -= s; x <<= s; + s = 2; if (x << 2 == 0) s = 0; b -= s; x <<= s; + s = 1; if (x << 1 == 0) s = 0; b -= s; + + return b; +} + +/* mask off an interrupt -- 1 is enable, 0 is disable */ +static inline void mask_mv64340_irq(unsigned int irq) +{ + uint32_t value; + + if (irq < (MV64340_IRQ_BASE + 32)) { + MV_READ(MV64340_INTERRUPT0_MASK_0_LOW, &value); + value &= ~(1 << (irq - MV64340_IRQ_BASE)); + MV_WRITE(MV64340_INTERRUPT0_MASK_0_LOW, value); + } else { + MV_READ(MV64340_INTERRUPT0_MASK_0_HIGH, &value); + value &= ~(1 << (irq - (MV64340_IRQ_BASE - 32))); + MV_WRITE(MV64340_INTERRUPT0_MASK_0_HIGH, value); + } +} + +/* unmask an interrupt -- 1 is enable, 0 is disable */ +static inline void unmask_mv64340_irq(unsigned int irq) +{ + uint32_t value; + + if (irq < (MV64340_IRQ_BASE + 32)) { + MV_READ(MV64340_INTERRUPT0_MASK_0_LOW, &value); + value |= 1 << (irq - MV64340_IRQ_BASE); + MV_WRITE(MV64340_INTERRUPT0_MASK_0_LOW, value); + } else { + MV_READ(MV64340_INTERRUPT0_MASK_0_HIGH, &value); + value |= 1 << (irq - (MV64340_IRQ_BASE - 32)); + MV_WRITE(MV64340_INTERRUPT0_MASK_0_HIGH, value); + } +} + +/* + * Enables the IRQ on Marvell Chip + */ +static void enable_mv64340_irq(unsigned int irq) +{ + unmask_mv64340_irq(irq); +} + +/* + * Initialize the IRQ on Marvell Chip + */ +static unsigned int startup_mv64340_irq(unsigned int irq) +{ + unmask_mv64340_irq(irq); + return 0; +} + +/* + * Disables the IRQ on Marvell Chip + */ +static void disable_mv64340_irq(unsigned int irq) +{ + mask_mv64340_irq(irq); +} + +/* + * Masks and ACKs an IRQ + */ +static void mask_and_ack_mv64340_irq(unsigned int irq) +{ + mask_mv64340_irq(irq); +} + +/* + * End IRQ processing + */ +static void end_mv64340_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + unmask_mv64340_irq(irq); +} + +/* + * Interrupt handler for interrupts coming from the Marvell chip. + * It could be built in ethernet ports etc... + */ +void ll_mv64340_irq(struct pt_regs *regs) +{ + unsigned int irq_src_low, irq_src_high; + unsigned int irq_mask_low, irq_mask_high; + + /* read the interrupt status registers */ + MV_READ(MV64340_INTERRUPT0_MASK_0_LOW, &irq_mask_low); + MV_READ(MV64340_INTERRUPT0_MASK_0_HIGH, &irq_mask_high); + MV_READ(MV64340_MAIN_INTERRUPT_CAUSE_LOW, &irq_src_low); + MV_READ(MV64340_MAIN_INTERRUPT_CAUSE_HIGH, &irq_src_high); + + /* mask for just the interrupts we want */ + irq_src_low &= irq_mask_low; + irq_src_high &= irq_mask_high; + + if (irq_src_low) + do_IRQ(ls1bit32(irq_src_low) + MV64340_IRQ_BASE, regs); + else + do_IRQ(ls1bit32(irq_src_high) + MV64340_IRQ_BASE + 32, regs); +} + +#define shutdown_mv64340_irq disable_mv64340_irq + +struct hw_interrupt_type mv64340_irq_type = { + "MV-64340", + startup_mv64340_irq, + shutdown_mv64340_irq, + enable_mv64340_irq, + disable_mv64340_irq, + mask_and_ack_mv64340_irq, + end_mv64340_irq, + NULL +}; + +void mv64340_irq_init(void) +{ + int i; + + /* Reset irq handlers pointers to NULL */ + for (i = MV64340_IRQ_BASE; i < (MV64340_IRQ_BASE + 64); i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = 2; + irq_desc[i].handler = &mv64340_irq_type; + } +} diff -Nru a/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h b/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/momentum/ocelot_c/ocelot_c_fpga.h Tue Jul 1 18:44:40 2003 @@ -0,0 +1,50 @@ +/* + * Ocelot-C Board Register Definitions + * + * (C) 2002 Momentum Computer Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#ifndef __OCELOT_C_FPGA_H__ +#define __OCELOT_C_FPGA_H__ + +#define OCELOT_C_CS0_ADDR (0xfc000000) + +#define OCELOT_C_REG_BOARDREV 0x0 +#define OCELOT_C_REG_FPGA_REV 0x1 +#define OCELOT_C_REG_FPGA_TYPE 0x2 +#define OCELOT_C_REG_RESET_STATUS 0x3 +#define OCELOT_C_REG_BOARD_STATUS 0x4 +#define OCELOT_C_REG_CPCI_ID 0x5 +#define OCELOT_C_REG_SET 0x6 +#define OCELOT_C_REG_CLR 0x7 +#define OCELOT_C_REG_EEPROM_MODE 0x9 +#define OCELOT_C_REG_INTMASK 0xa +#define OCELOT_C_REG_INTSTAT 0xb +#define OCELOT_C_REG_UART_INTMASK 0xc +#define OCELOT_C_REG_UART_INTSTAT 0xd +#define OCELOT_C_REG_INTSET 0xe +#define OCELOT_C_REG_INTCLR 0xf + +#define OCELOT_FPGA_WRITE(x, y) writeb(x, OCELOT_C_CS0_ADDR + OCELOT_C_REG_##y) +#define OCELOT_FPGA_READ(x) readb(OCELOT_C_CS0_ADDR + OCELOT_C_REG_##x) + +#endif diff -Nru a/arch/mips/momentum/ocelot_c/pci-irq.c b/arch/mips/momentum/ocelot_c/pci-irq.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/momentum/ocelot_c/pci-irq.c Tue Jul 1 18:44:39 2003 @@ -0,0 +1,73 @@ +/* + * Copyright 2002 Momentum Computer Inc. + * Author: Matthew Dharm + * + * Based on work for the Linux port to the Ocelot board, which is + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * arch/mips/momentum/ocelot_g/pci.c + * Board-specific PCI routines for mv64340 controller. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include +#include +#include +#include + + +void __init mv64340_board_pcibios_fixup_bus(struct pci_bus *bus) +{ + struct pci_bus *current_bus = bus; + struct pci_dev *devices; + struct list_head *devices_link; + u16 cmd; + + /* loop over all known devices on this bus */ + list_for_each(devices_link, &(current_bus->devices)) { + + devices = pci_dev_b(devices_link); + if (devices == NULL) + continue; + + if ((current_bus->number == 0) && + (PCI_SLOT(devices->devfn) == 1) && + (PCI_FUNC(devices->devfn) == 0)) { + /* LSI 53C10101R SCSI (A) */ + devices->irq = 2; + } else if ((current_bus->number == 0) && + (PCI_SLOT(devices->devfn) == 1) && + (PCI_FUNC(devices->devfn) == 1)) { + /* LSI 53C10101R SCSI (B) */ + devices->irq = 2; + } else if ((current_bus->number == 1) && + (PCI_SLOT(devices->devfn) == 1)) { + /* Intel 21555 bridge */ + devices->irq = 12; + } else if ((current_bus->number == 1) && + (PCI_SLOT(devices->devfn) == 2)) { + /* PMC Slot */ + devices->irq = 4; + } else { + /* We don't have assign interrupts for other devices. */ + devices->irq = 0xff; + } + + /* Assign an interrupt number for the device */ + bus->ops->write_byte(devices, PCI_INTERRUPT_LINE, devices->irq); + + /* enable master for everything but the MV-64340 */ + if (((current_bus->number != 0) && (current_bus->number != 1)) + || (PCI_SLOT(devices->devfn) != 0)) { + bus->ops->read_word(devices, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_MASTER; + bus->ops->write_word(devices, PCI_COMMAND, cmd); + } + } +} diff -Nru a/arch/mips/momentum/ocelot_c/prom.c b/arch/mips/momentum/ocelot_c/prom.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/momentum/ocelot_c/prom.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,151 @@ +/* + * Copyright 2002 Momentum Computer Inc. + * Author: Matthew Dharm + * + * Based on Ocelot Linux port, which is + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "ocelot_c_fpga.h" + +struct callvectors { + int (*open) (char*, int, int); + int (*close) (int); + int (*read) (int, void*, int); + int (*write) (int, void*, int); + off_t (*lseek) (int, off_t, int); + int (*printf) (const char*, ...); + void (*cacheflush) (void); + char* (*gets) (char*); +}; + +struct callvectors* debug_vectors; +char arcs_cmdline[CL_SIZE]; + +extern unsigned long mv64340_base; +extern unsigned long cpu_clock; + +#ifdef CONFIG_MV64340_ETH +extern unsigned char prom_mac_addr_base[6]; +#endif + +const char *get_system_type(void) +{ +#ifdef CONFIG_CPU_SR71000 + return "Momentum Ocelot-CS"; +#else + return "Momentum Ocelot-C"; +#endif +} + +#ifdef CONFIG_MV64340_ETH +static void burn_clocks(void) +{ + int i; + + /* this loop should burn at least 1us -- this should be plenty */ + for (i = 0; i < 0x10000; i++) + ; +} + +static u8 exchange_bit(u8 val, u8 cs) +{ + /* place the data */ + OCELOT_FPGA_WRITE((val << 2) | cs, EEPROM_MODE); + burn_clocks(); + + /* turn the clock on */ + OCELOT_FPGA_WRITE((val << 2) | cs | 0x2, EEPROM_MODE); + burn_clocks(); + + /* turn the clock off and read-strobe */ + OCELOT_FPGA_WRITE((val << 2) | cs | 0x10, EEPROM_MODE); + + /* return the data */ + return ((OCELOT_FPGA_READ(EEPROM_MODE) >> 3) & 0x1); +} + +void get_mac(char dest[6]) +{ + u8 read_opcode[12] = {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + int i,j; + + for (i = 0; i < 12; i++) + exchange_bit(read_opcode[i], 1); + + for (j = 0; j < 6; j++) { + dest[j] = 0; + for (i = 0; i < 8; i++) { + dest[j] <<= 1; + dest[j] |= exchange_bit(0, 1); + } + } + + /* turn off CS */ + exchange_bit(0,0); +} +#endif + +/* [jsun@junsun.net] PMON passes arguments in C main() style */ +void __init prom_init(int argc, char **arg, char** env, struct callvectors *cv) +{ + int i; + + /* save the PROM vectors for debugging use */ + debug_vectors = cv; + + /* arg[0] is "g", the rest is boot parameters */ + arcs_cmdline[0] = '\0'; + for (i = 1; i < argc; i++) { + if (strlen(arcs_cmdline) + strlen(arg[i] + 1) + >= sizeof(arcs_cmdline)) + break; + strcat(arcs_cmdline, arg[i]); + strcat(arcs_cmdline, " "); + } + + mips_machgroup = MACH_GROUP_MOMENCO; + mips_machtype = MACH_MOMENCO_OCELOT_C; + + while (*env) { + if (strncmp("gtbase", *env, strlen("gtbase")) == 0) { + mv64340_base = simple_strtol(*env + strlen("gtbase="), + NULL, 16); + } + if (strncmp("cpuclock", *env, strlen("cpuclock")) == 0) { + cpu_clock = simple_strtol(*env + strlen("cpuclock="), + NULL, 10); + } + env++; + } + +#ifdef CONFIG_MV64340_ETH + /* get the base MAC address for on-board ethernet ports */ + get_mac(prom_mac_addr_base); +#endif + + debug_vectors->printf("Booting Linux kernel...\n"); +} + +void __init prom_free_prom_memory(void) +{ +} + +void __init prom_fixup_mem_map(unsigned long start, unsigned long end) +{ +} diff -Nru a/arch/mips/momentum/ocelot_c/reset.c b/arch/mips/momentum/ocelot_c/reset.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/momentum/ocelot_c/reset.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,50 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * Copyright (C) 1997, 2001 Ralf Baechle + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * Copyright (C) 2002 Momentum Computer Inc. + * Author: Matthew Dharm + */ +#include +#include +#include +#include +#include +#include +#include +#include + +void momenco_ocelot_restart(char *command) +{ + /* base address of timekeeper portion of part */ + void *nvram = (void*) 0xfc807000; + + /* Ask the NVRAM/RTC/watchdog chip to assert reset in 1/16 second */ + writeb(0x84, nvram + 0xff7); + + /* wait for the watchdog to go off */ + mdelay(100+(1000/16)); + + /* if the watchdog fails for some reason, let people know */ + printk(KERN_NOTICE "Watchdog reset failed\n"); +} + +void momenco_ocelot_halt(void) +{ + printk(KERN_NOTICE "\n** You can safely turn off the power\n"); + while (1) + __asm__(".set\tmips3\n\t" + "wait\n\t" + ".set\tmips0"); +} + +void momenco_ocelot_power_off(void) +{ + momenco_ocelot_halt(); +} diff -Nru a/arch/mips/momentum/ocelot_c/setup.c b/arch/mips/momentum/ocelot_c/setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/momentum/ocelot_c/setup.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,326 @@ +/* + * BRIEF MODULE DESCRIPTION + * Momentum Computer Ocelot-C and -CS board dependent boot routines + * + * Copyright (C) 1996, 1997, 2001 Ralf Baechle + * Copyright (C) 2000 RidgeRun, Inc. + * Copyright (C) 2001 Red Hat, Inc. + * Copyright (C) 2002 Momentum Computer + * + * Author: Matthew Dharm, Momentum Computer + * mdharm@momenco.com + * + * Author: RidgeRun, Inc. + * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com + * + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ocelot_c_fpga.h" + +unsigned long mv64340_base; +unsigned long cpu_clock; + +/* These functions are used for rebooting or halting the machine*/ +extern void momenco_ocelot_restart(char *command); +extern void momenco_ocelot_halt(void); +extern void momenco_ocelot_power_off(void); + +void momenco_time_init(void); + +static char reset_reason; + +#define ENTRYLO(x) ((pte_val(mk_pte_phys((x), PAGE_KERNEL_UNCACHED)) >> 6)|1) + +/* setup code for a handoff from a version 2 PMON 2000 PROM */ +void PMON_v2_setup(void) +{ + /* Some wired TLB entries for the MV64340 and perhiperals. The + MV64340 is going to be hit on every IRQ anyway - there's + absolutely no point in letting it be a random TLB entry, as + it'll just cause needless churning of the TLB. And we use + the other half for the serial port, which is just a PITA + otherwise :) + + Device Physical Virtual + MV64340 Internal Regs 0xf4000000 0xf4000000 + Ocelot-C[S] PLD (CS0) 0xfc000000 0xfc000000 + NVRAM (CS1) 0xfc800000 0xfc800000 + UARTs (CS2) 0xfd000000 0xfd000000 + Internal SRAM 0xfe000000 0xfe000000 + M-Systems DOC (CS3) 0xff000000 0xff000000 + */ + + /* marvell and extra space */ + add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000), 0xf4000000, PM_64K); + /* fpga, rtc, and uart */ + add_wired_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfd000000), 0xfc000000, PM_16M); + /* m-sys and internal SRAM */ + add_wired_entry(ENTRYLO(0xfe000000), ENTRYLO(0xff000000), 0xfe000000, PM_16M); + + mv64340_base = 0xf4000000; +} + +unsigned long m48t37y_get_time(void) +{ + unsigned char* rtc_base = (unsigned char*)0xfc800000; + unsigned int year, month, day, hour, min, sec; + + /* stop the update */ + rtc_base[0x7ff8] = 0x40; + + year = BCD2BIN(rtc_base[0x7fff]); + year += BCD2BIN(rtc_base[0x7ff1]) * 100; + + month = BCD2BIN(rtc_base[0x7ffe]); + + day = BCD2BIN(rtc_base[0x7ffd]); + + hour = BCD2BIN(rtc_base[0x7ffb]); + min = BCD2BIN(rtc_base[0x7ffa]); + sec = BCD2BIN(rtc_base[0x7ff9]); + + /* start the update */ + rtc_base[0x7ff8] = 0x00; + + return mktime(year, month, day, hour, min, sec); +} + +int m48t37y_set_time(unsigned long sec) +{ + unsigned char* rtc_base = (unsigned char*)0xfc800000; + struct rtc_time tm; + + /* convert to a more useful format -- note months count from 0 */ + to_tm(sec, &tm); + tm.tm_mon += 1; + + /* enable writing */ + rtc_base[0x7ff8] = 0x80; + + /* year */ + rtc_base[0x7fff] = BIN2BCD(tm.tm_year % 100); + rtc_base[0x7ff1] = BIN2BCD(tm.tm_year / 100); + + /* month */ + rtc_base[0x7ffe] = BIN2BCD(tm.tm_mon); + + /* day */ + rtc_base[0x7ffd] = BIN2BCD(tm.tm_mday); + + /* hour/min/sec */ + rtc_base[0x7ffb] = BIN2BCD(tm.tm_hour); + rtc_base[0x7ffa] = BIN2BCD(tm.tm_min); + rtc_base[0x7ff9] = BIN2BCD(tm.tm_sec); + + /* day of week -- not really used, but let's keep it up-to-date */ + rtc_base[0x7ffc] = CONV_BIN2BCD(tm.tm_wday + 1); + + /* disable writing */ + rtc_base[0x7ff8] = 0x00; + + return 0; +} + +void momenco_timer_setup(struct irqaction *irq) +{ + setup_irq(7, irq); +} + +void momenco_time_init(void) +{ +#ifdef CONFIG_CPU_SR71000 + mips_counter_frequency = cpu_clock; +#elif defined(CONFIG_CPU_RM7000) + mips_counter_frequency = cpu_clock / 2; +#else +#error Unknown CPU for this board +#endif + board_timer_setup = momenco_timer_setup; + + rtc_get_time = m48t37y_get_time; + rtc_set_time = m48t37y_set_time; +} + +void __init momenco_ocelot_c_setup(void) +{ + unsigned int tmpword; + + board_time_init = momenco_time_init; + + _machine_restart = momenco_ocelot_restart; + _machine_halt = momenco_ocelot_halt; + _machine_power_off = momenco_ocelot_power_off; + + /* + * initrd_start = (ulong)ocelot_initrd_start; + * initrd_end = (ulong)ocelot_initrd_start + (ulong)ocelot_initrd_size; + * initrd_below_start_ok = 1; + */ + + /* do handoff reconfiguration */ + PMON_v2_setup(); + + /* shut down ethernet ports, just to be sure our memory doesn't get + * corrupted by random ethernet traffic. + */ + MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(0), 0xff << 8); + MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(1), 0xff << 8); + MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(0), 0xff << 8); + MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(1), 0xff << 8); + do {} + while (MV_READ_DATA(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(0)) & 0xff); + do {} + while (MV_READ_DATA(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(1)) & 0xff); + do {} + while (MV_READ_DATA(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(0)) & 0xff); + do {} + while (MV_READ_DATA(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(1)) & 0xff); + MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(0), MV_READ_DATA(MV64340_ETH_PORT_SERIAL_CONTROL_REG(0)) & ~1); + MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(1), MV_READ_DATA(MV64340_ETH_PORT_SERIAL_CONTROL_REG(1)) & ~1); + + /* Turn off the Bit-Error LED */ + OCELOT_FPGA_WRITE(0x80, CLR); + + tmpword = OCELOT_FPGA_READ(BOARDREV); +#ifdef CONFIG_CPU_SR71000 + if (tmpword < 26) + printk("Momenco Ocelot-CS: Board Assembly Rev. %c\n", + 'A'+tmpword); + else + printk("Momenco Ocelot-CS: Board Assembly Revision #0x%x\n", + tmpword); +#else + if (tmpword < 26) + printk("Momenco Ocelot-C: Board Assembly Rev. %c\n", + 'A'+tmpword); + else + printk("Momenco Ocelot-C: Board Assembly Revision #0x%x\n", + tmpword); +#endif + + tmpword = OCELOT_FPGA_READ(FPGA_REV); + printk("FPGA Rev: %d.%d\n", tmpword>>4, tmpword&15); + tmpword = OCELOT_FPGA_READ(RESET_STATUS); + printk("Reset reason: 0x%x\n", tmpword); + switch (tmpword) { + case 0x1: + printk(" - Power-up reset\n"); + break; + case 0x2: + printk(" - Push-button reset\n"); + break; + case 0x4: + printk(" - cPCI bus reset\n"); + break; + case 0x8: + printk(" - Watchdog reset\n"); + break; + case 0x10: + printk(" - Software reset\n"); + break; + default: + printk(" - Unknown reset cause\n"); + } + reset_reason = tmpword; + OCELOT_FPGA_WRITE(0xff, RESET_STATUS); + + tmpword = OCELOT_FPGA_READ(CPCI_ID); + printk("cPCI ID register: 0x%02x\n", tmpword); + printk(" - Slot number: %d\n", tmpword & 0x1f); + printk(" - PCI bus present: %s\n", tmpword & 0x40 ? "yes" : "no"); + printk(" - System Slot: %s\n", tmpword & 0x20 ? "yes" : "no"); + + tmpword = OCELOT_FPGA_READ(BOARD_STATUS); + printk("Board Status register: 0x%02x\n", tmpword); + printk(" - User jumper: %s\n", (tmpword & 0x80)?"installed":"absent"); + printk(" - Boot flash write jumper: %s\n", (tmpword&0x40)?"installed":"absent"); + printk(" - L3 Cache size: %d MiB\n", (1<<((tmpword&12) >> 2))&~1); + printk(" - SDRAM size: %d MiB\n", 1<<(6+(tmpword&3))); + + switch(tmpword &3) { + case 3: + /* 512MiB */ + add_memory_region(0x0, 0x200<<20, BOOT_MEM_RAM); + break; + case 2: + /* 256MiB */ + add_memory_region(0x0, 0x100<<20, BOOT_MEM_RAM); + break; + case 1: + /* 128MiB */ + add_memory_region(0x0, 0x80<<20, BOOT_MEM_RAM); + break; + case 0: + /* 1GiB -- needs CONFIG_HIGHMEM */ + add_memory_region(0x0, 0x400<<20, BOOT_MEM_RAM); + break; + } +} + +/* This needs to be one of the first initcalls, because no I/O port access + can work before this */ +static int io_base_ioremap(void) +{ + /* we're mapping PCI accesses from 0xc0000000 to 0xf0000000 */ + void *io_remap_range = ioremap(0xc0000000, 0x30000000); + + if (!io_remap_range) { + panic("Could not ioremap I/O port range"); + } + printk("io_remap_range set at 0x%08x\n", (uint32_t)io_remap_range); + set_io_port_base(io_remap_range - 0xc0000000); + + return 0; +} + +module_init(io_base_ioremap); diff -Nru a/arch/mips/momentum/ocelot_c/uart-irq.c b/arch/mips/momentum/ocelot_c/uart-irq.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/momentum/ocelot_c/uart-irq.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,148 @@ +/* + * Copyright 2002 Momentum Computer + * Author: mdharm@momenco.com + * + * arch/mips/momentum/ocelot_c/uart-irq.c + * Interrupt routines for UARTs. Interrupt numbers are assigned from + * 80 to 81 (2 interrupt sources). + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ocelot_c_fpga.h" + +static inline int ls1bit8(unsigned int x) +{ + int b = 7, s; + + s = 4; if (((unsigned char)(x << 4)) == 0) s = 0; b -= s; x <<= s; + s = 2; if (((unsigned char)(x << 2)) == 0) s = 0; b -= s; x <<= s; + s = 1; if (((unsigned char)(x << 1)) == 0) s = 0; b -= s; + + return b; +} + +/* mask off an interrupt -- 0 is enable, 1 is disable */ +static inline void mask_uart_irq(unsigned int irq) +{ + uint8_t value; + + value = OCELOT_FPGA_READ(UART_INTMASK); + value |= 1 << (irq - 74); + OCELOT_FPGA_WRITE(value, UART_INTMASK); + + /* read the value back to assure that it's really been written */ + value = OCELOT_FPGA_READ(UART_INTMASK); +} + +/* unmask an interrupt -- 0 is enable, 1 is disable */ +static inline void unmask_uart_irq(unsigned int irq) +{ + uint8_t value; + + value = OCELOT_FPGA_READ(UART_INTMASK); + value &= ~(1 << (irq - 74)); + OCELOT_FPGA_WRITE(value, UART_INTMASK); + + /* read the value back to assure that it's really been written */ + value = OCELOT_FPGA_READ(UART_INTMASK); +} + +/* + * Enables the IRQ in the FPGA + */ +static void enable_uart_irq(unsigned int irq) +{ + unmask_uart_irq(irq); +} + +/* + * Initialize the IRQ in the FPGA + */ +static unsigned int startup_uart_irq(unsigned int irq) +{ + unmask_uart_irq(irq); + return 0; +} + +/* + * Disables the IRQ in the FPGA + */ +static void disable_uart_irq(unsigned int irq) +{ + mask_uart_irq(irq); +} + +/* + * Masks and ACKs an IRQ + */ +static void mask_and_ack_uart_irq(unsigned int irq) +{ + mask_uart_irq(irq); +} + +/* + * End IRQ processing + */ +static void end_uart_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + unmask_uart_irq(irq); +} + +/* + * Interrupt handler for interrupts coming from the FPGA chip. + */ +void ll_uart_irq(struct pt_regs *regs) +{ + unsigned int irq_src, irq_mask; + + /* read the interrupt status registers */ + irq_src = OCELOT_FPGA_READ(UART_INTSTAT); + irq_mask = OCELOT_FPGA_READ(UART_INTMASK); + + /* mask for just the interrupts we want */ + irq_src &= ~irq_mask; + + do_IRQ(ls1bit8(irq_src) + 74, regs); +} + +#define shutdown_uart_irq disable_uart_irq + +struct hw_interrupt_type uart_irq_type = { + "UART/FPGA", + startup_uart_irq, + shutdown_uart_irq, + enable_uart_irq, + disable_uart_irq, + mask_and_ack_uart_irq, + end_uart_irq, + NULL +}; + +void uart_irq_init(void) +{ + /* Reset irq handlers pointers to NULL */ + irq_desc[80].status = IRQ_DISABLED; + irq_desc[80].action = 0; + irq_desc[80].depth = 2; + irq_desc[80].handler = &uart_irq_type; + + irq_desc[81].status = IRQ_DISABLED; + irq_desc[81].action = 0; + irq_desc[81].depth = 2; + irq_desc[81].handler = &uart_irq_type; +} diff -Nru a/arch/mips/momentum/ocelot_g/Makefile b/arch/mips/momentum/ocelot_g/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/momentum/ocelot_g/Makefile Tue Jul 1 18:44:40 2003 @@ -0,0 +1,9 @@ +# +# Makefile for Momentum Computer's Ocelot-G board. +# + +obj-y += gt-irq.o pci-irq.o int-handler.o irq.o prom.o \ + reset.o setup.o +obj-$(CONFIG_KGDB) += dbg_io.o + +EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips/momentum/ocelot_g/dbg_io.c b/arch/mips/momentum/ocelot_g/dbg_io.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/momentum/ocelot_g/dbg_io.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,126 @@ +#include + +#if defined(CONFIG_KGDB) + +#include /* For the serial port location and base baud */ + +/* --- CONFIG --- */ + +typedef unsigned char uint8; +typedef unsigned int uint32; + +/* --- END OF CONFIG --- */ + +#define UART16550_BAUD_2400 2400 +#define UART16550_BAUD_4800 4800 +#define UART16550_BAUD_9600 9600 +#define UART16550_BAUD_19200 19200 +#define UART16550_BAUD_38400 38400 +#define UART16550_BAUD_57600 57600 +#define UART16550_BAUD_115200 115200 + +#define UART16550_PARITY_NONE 0 +#define UART16550_PARITY_ODD 0x08 +#define UART16550_PARITY_EVEN 0x18 +#define UART16550_PARITY_MARK 0x28 +#define UART16550_PARITY_SPACE 0x38 + +#define UART16550_DATA_5BIT 0x0 +#define UART16550_DATA_6BIT 0x1 +#define UART16550_DATA_7BIT 0x2 +#define UART16550_DATA_8BIT 0x3 + +#define UART16550_STOP_1BIT 0x0 +#define UART16550_STOP_2BIT 0x4 + +/* ----------------------------------------------------- */ + +/* === CONFIG === */ + +/* [jsun] we use the second serial port for kdb */ +#define BASE OCELOT_SERIAL1_BASE +#define MAX_BAUD OCELOT_BASE_BAUD + +/* === END OF CONFIG === */ + +#define REG_OFFSET 4 + +/* register offset */ +#define OFS_RCV_BUFFER 0 +#define OFS_TRANS_HOLD 0 +#define OFS_SEND_BUFFER 0 +#define OFS_INTR_ENABLE (1*REG_OFFSET) +#define OFS_INTR_ID (2*REG_OFFSET) +#define OFS_DATA_FORMAT (3*REG_OFFSET) +#define OFS_LINE_CONTROL (3*REG_OFFSET) +#define OFS_MODEM_CONTROL (4*REG_OFFSET) +#define OFS_RS232_OUTPUT (4*REG_OFFSET) +#define OFS_LINE_STATUS (5*REG_OFFSET) +#define OFS_MODEM_STATUS (6*REG_OFFSET) +#define OFS_RS232_INPUT (6*REG_OFFSET) +#define OFS_SCRATCH_PAD (7*REG_OFFSET) + +#define OFS_DIVISOR_LSB (0*REG_OFFSET) +#define OFS_DIVISOR_MSB (1*REG_OFFSET) + + +/* memory-mapped read/write of the port */ +#define UART16550_READ(y) (*((volatile uint8*)(BASE + y))) +#define UART16550_WRITE(y, z) ((*((volatile uint8*)(BASE + y))) = z) + +void debugInit(uint32 baud, uint8 data, uint8 parity, uint8 stop) +{ + /* disable interrupts */ + UART16550_WRITE(OFS_INTR_ENABLE, 0); + + /* set up buad rate */ + { + uint32 divisor; + + /* set DIAB bit */ + UART16550_WRITE(OFS_LINE_CONTROL, 0x80); + + /* set divisor */ + divisor = MAX_BAUD / baud; + UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff); + UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8); + + /* clear DIAB bit */ + UART16550_WRITE(OFS_LINE_CONTROL, 0x0); + } + + /* set data format */ + UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop); +} + +static int remoteDebugInitialized = 0; + +uint8 getDebugChar(void) +{ + if (!remoteDebugInitialized) { + remoteDebugInitialized = 1; + debugInit(UART16550_BAUD_38400, + UART16550_DATA_8BIT, + UART16550_PARITY_NONE, UART16550_STOP_1BIT); + } + + while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0); + return UART16550_READ(OFS_RCV_BUFFER); +} + + +int putDebugChar(uint8 byte) +{ + if (!remoteDebugInitialized) { + remoteDebugInitialized = 1; + debugInit(UART16550_BAUD_38400, + UART16550_DATA_8BIT, + UART16550_PARITY_NONE, UART16550_STOP_1BIT); + } + + while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0); + UART16550_WRITE(OFS_SEND_BUFFER, byte); + return 1; +} + +#endif diff -Nru a/arch/mips/momentum/ocelot_g/gt-irq.c b/arch/mips/momentum/ocelot_g/gt-irq.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/momentum/ocelot_g/gt-irq.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,294 @@ +/* + * + * Copyright 2002 Momentum Computer + * Author: mdharm@momenco.com + * + * arch/mips/momentum/ocelot_g/gt_irq.c + * Interrupt routines for gt64240. Currently it only handles timer irq. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "gt64240.h" + +unsigned long bus_clock; + +/* + * These are interrupt handlers for the GT on-chip interrupts. They + * all come in to the MIPS on a single interrupt line, and have to + * be handled and ack'ed differently than other MIPS interrupts. + */ + +#if CURRENTLY_UNUSED + +struct tq_struct irq_handlers[MAX_CAUSE_REGS][MAX_CAUSE_REG_WIDTH]; +void hook_irq_handler(int int_cause, int bit_num, void *isr_ptr); + +/* + * Hooks IRQ handler to the system. When the system is interrupted + * the interrupt service routine is called. + * + * Inputs : + * int_cause - The interrupt cause number. In EVB64120 two parameters + * are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH. + * bit_num - Indicates which bit number in the cause register + * isr_ptr - Pointer to the interrupt service routine + */ +void hook_irq_handler(int int_cause, int bit_num, void *isr_ptr) +{ + irq_handlers[int_cause][bit_num].routine = isr_ptr; +} + + +/* + * Enables the IRQ on Galileo Chip + * + * Inputs : + * int_cause - The interrupt cause number. In EVB64120 two parameters + * are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH. + * bit_num - Indicates which bit number in the cause register + * + * Outputs : + * 1 if succesful, 0 if failure + */ +int enable_galileo_irq(int int_cause, int bit_num) +{ + if (int_cause == INT_CAUSE_MAIN) + SET_REG_BITS(CPU_INTERRUPT_MASK_REGISTER, (1 << bit_num)); + else if (int_cause == INT_CAUSE_HIGH) + SET_REG_BITS(CPU_HIGH_INTERRUPT_MASK_REGISTER, + (1 << bit_num)); + else + return 0; + + return 1; +} + +/* + * Disables the IRQ on Galileo Chip + * + * Inputs : + * int_cause - The interrupt cause number. In EVB64120 two parameters + * are declared, INT_CAUSE_MAIN and INT_CAUSE_HIGH. + * bit_num - Indicates which bit number in the cause register + * + * Outputs : + * 1 if succesful, 0 if failure + */ +int disable_galileo_irq(int int_cause, int bit_num) +{ + if (int_cause == INT_CAUSE_MAIN) + RESET_REG_BITS(CPU_INTERRUPT_MASK_REGISTER, + (1 << bit_num)); + else if (int_cause == INT_CAUSE_HIGH) + RESET_REG_BITS(CPU_HIGH_INTERRUPT_MASK_REGISTER, + (1 << bit_num)); + else + return 0; + return 1; +} +#endif /* UNUSED */ + +/* + * Interrupt handler for interrupts coming from the Galileo chip via P0_INT#. + * + * We route the timer interrupt to P0_INT# (IRQ 6), and that's all this + * routine can handle, for now. + * + * In the future, we'll route more interrupts to this pin, and that's why + * we keep this particular structure in the function. + */ + +static void gt64240_p0int_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + uint32_t irq_src, irq_src_mask; + int handled; + + /* get the low interrupt cause register */ + GT_READ(LOW_INTERRUPT_CAUSE_REGISTER, &irq_src); + + /* get the mask register for this pin */ + GT_READ(PCI_0INTERRUPT_CAUSE_MASK_REGISTER_LOW, &irq_src_mask); + + /* mask off only the interrupts we're interested in */ + irq_src = irq_src & irq_src_mask; + + handled = 0; + + /* Check for timer interrupt */ + if (irq_src & 0x00000100) { + handled = 1; + irq_src &= ~0x00000100; + + /* Clear any pending cause bits */ + GT_WRITE(TIMER_COUNTER_0_3_INTERRUPT_CAUSE, 0x0); + + /* handle the timer call */ + do_timer(regs); + } + + if (irq_src) { + printk(KERN_INFO + "UNKNOWN P0_INT# interrupt received, irq_src=0x%x\n", + irq_src); + } +} + +/* + * Interrupt handler for interrupts coming from the Galileo chip. + * It could be built in ethernet ports etc... + */ +static void gt64240_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned int irq_src, int_high_src, irq_src_mask, + int_high_src_mask; + int handled; + +#if 0 + GT_READ(GT_INTRCAUSE_OFS, &irq_src); + GT_READ(GT_INTRMASK_OFS, &irq_src_mask); + GT_READ(GT_HINTRCAUSE_OFS, &int_high_src); + GT_READ(GT_HINTRMASK_OFS, &int_high_src_mask); +#endif + irq_src = irq_src & irq_src_mask; + int_high_src = int_high_src & int_high_src_mask; + + handled = 0; + + /* Execute all interrupt handlers */ + /* Check for timer interrupt */ + if (irq_src & 0x00000800) { + handled = 1; + irq_src &= ~0x00000800; + // RESET_REG_BITS (INTERRUPT_CAUSE_REGISTER,BIT8); + do_timer(regs); + } + + if (irq_src) { + printk(KERN_INFO + "Other Galileo interrupt received irq_src %x\n", + irq_src); +#if CURRENTLY_UNUSED + for (count = 0; count < MAX_CAUSE_REG_WIDTH; count++) { + if (irq_src & (1 << count)) { + if (irq_handlers[INT_CAUSE_MAIN][count]. + routine) { + queue_task(&irq_handlers + [INT_CAUSE_MAIN][count], + &tq_immediate); + mark_bh(IMMEDIATE_BH); + handled = 1; + } + } + } +#endif /* UNUSED */ + } +#if 0 + GT_WRITE(GT_INTRCAUSE_OFS, 0); + GT_WRITE(GT_HINTRCAUSE_OFS, 0); +#endif + +#undef GALILEO_I2O +#ifdef GALILEO_I2O + /* + * Future I2O support. We currently attach I2O interrupt handlers to + * the Galileo interrupt (int 4) and handle them in do_IRQ. + */ + if (isInBoundDoorBellInterruptSet()) { + printk(KERN_INFO "I2O doorbell interrupt received.\n"); + handled = 1; + } + + if (isInBoundPostQueueInterruptSet()) { + printk(KERN_INFO "I2O Queue interrupt received.\n"); + handled = 1; + } + + /* + * This normally would be outside of the ifdef, but since we're + * handling I2O outside of this handler, this printk shows up every + * time we get a valid I2O interrupt. So turn this off for now. + */ + if (handled == 0) { + if (counter < 50) { + printk("Spurious Galileo interrupt...\n"); + counter++; + } + } +#endif +} + +/* + * Initializes timer using galileo's built in timer. + */ + +/* + * This will ignore the standard MIPS timer interrupt handler + * that is passed in as *irq (=irq0 in ../kernel/time.c). + * We will do our own timer interrupt handling. + */ +void gt64240_time_init(void) +{ + extern irq_desc_t irq_desc[NR_IRQS]; + static struct irqaction timer; + + /* Stop the timer -- we'll use timer #0 */ + GT_WRITE(TIMER_COUNTER_0_3_CONTROL, 0x0); + + /* Load timer value for 100 Hz */ + GT_WRITE(TIMER_COUNTER0, bus_clock / 100); + + /* + * Create the IRQ structure entry for the timer. Since we're too early + * in the boot process to use the "request_irq()" call, we'll hard-code + * the values to the correct interrupt line. + */ + timer.handler = >64240_p0int_irq; + timer.flags = SA_SHIRQ | SA_INTERRUPT; + timer.name = "timer"; + timer.dev_id = NULL; + timer.next = NULL; + timer.mask = 0; + irq_desc[6].action = &timer; + + enable_irq(6); + + /* Clear any pending cause bits */ + GT_WRITE(TIMER_COUNTER_0_3_INTERRUPT_CAUSE, 0x0); + + /* Enable the interrupt for timer 0 */ + GT_WRITE(TIMER_COUNTER_0_3_INTERRUPT_MASK, 0x1); + + /* Enable the timer interrupt for GT-64240 pin P0_INT# */ + GT_WRITE (PCI_0INTERRUPT_CAUSE_MASK_REGISTER_LOW, 0x100); + + /* Configure and start the timer */ + GT_WRITE(TIMER_COUNTER_0_3_CONTROL, 0x3); +} + +void gt64240_irq_init(void) +{ +#if CURRENTLY_UNUSED + int i, j; + + /* Reset irq handlers pointers to NULL */ + for (i = 0; i < MAX_CAUSE_REGS; i++) { + for (j = 0; j < MAX_CAUSE_REG_WIDTH; j++) { + irq_handlers[i][j].next = NULL; + irq_handlers[i][j].sync = 0; + irq_handlers[i][j].routine = NULL; + irq_handlers[i][j].data = NULL; + } + } +#endif +} diff -Nru a/arch/mips/momentum/ocelot_g/gt64240.h b/arch/mips/momentum/ocelot_g/gt64240.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/momentum/ocelot_g/gt64240.h Tue Jul 1 18:44:40 2003 @@ -0,0 +1,1238 @@ +/* gt64240r.h - GT-64240 Internal registers definition file */ + +/* Copyright - Galileo technology. */ + +#ifndef __INCgt64240rh +#define __INCgt64240rh + +#define GTREG(v) (((v) & 0xff) << 24) | (((v) & 0xff00) << 8) | \ + (((v) >> 24) & 0xff) | (((v) >> 8) & 0xff00) + +#if 0 +#define GTREG_SHORT(X) (((X) << 8) | ((X) >> 8)) + +#define LONG_GTREG(X) ((l64) \ + (((X)&0x00000000000000ffULL) << 56) | \ + (((X)&0x000000000000ff00ULL) << 40) | \ + (((X)&0x0000000000ff0000ULL) << 24) | \ + (((X)&0x00000000ff000000ULL) << 8) | \ + (((X)&0x000000ff00000000ULL) >> 8) | \ + (((X)&0x0000ff0000000000ULL) >> 24) | \ + (((X)&0x00ff000000000000ULL) >> 40) | \ + (((X)&0xff00000000000000ULL) >> 56)) +#endif + +#include "gt64240_dep.h" + +/****************************************/ +/* CPU Control Registers */ +/****************************************/ + +#define CPU_CONFIGURATION 0x000 +#define CPU_MODE 0x120 +#define CPU_READ_RESPONSE_CROSSBAR_LOW 0x170 +#define CPU_READ_RESPONSE_CROSSBAR_HIGH 0x178 + +/****************************************/ +/* Processor Address Space */ +/****************************************/ + +/* Sdram's BAR'S */ +#define SCS_0_LOW_DECODE_ADDRESS 0x008 +#define SCS_0_HIGH_DECODE_ADDRESS 0x010 +#define SCS_1_LOW_DECODE_ADDRESS 0x208 +#define SCS_1_HIGH_DECODE_ADDRESS 0x210 +#define SCS_2_LOW_DECODE_ADDRESS 0x018 +#define SCS_2_HIGH_DECODE_ADDRESS 0x020 +#define SCS_3_LOW_DECODE_ADDRESS 0x218 +#define SCS_3_HIGH_DECODE_ADDRESS 0x220 +/* Devices BAR'S */ +#define CS_0_LOW_DECODE_ADDRESS 0x028 +#define CS_0_HIGH_DECODE_ADDRESS 0x030 +#define CS_1_LOW_DECODE_ADDRESS 0x228 +#define CS_1_HIGH_DECODE_ADDRESS 0x230 +#define CS_2_LOW_DECODE_ADDRESS 0x248 +#define CS_2_HIGH_DECODE_ADDRESS 0x250 +#define CS_3_LOW_DECODE_ADDRESS 0x038 +#define CS_3_HIGH_DECODE_ADDRESS 0x040 +#define BOOTCS_LOW_DECODE_ADDRESS 0x238 +#define BOOTCS_HIGH_DECODE_ADDRESS 0x240 + +#define PCI_0I_O_LOW_DECODE_ADDRESS 0x048 +#define PCI_0I_O_HIGH_DECODE_ADDRESS 0x050 +#define PCI_0MEMORY0_LOW_DECODE_ADDRESS 0x058 +#define PCI_0MEMORY0_HIGH_DECODE_ADDRESS 0x060 +#define PCI_0MEMORY1_LOW_DECODE_ADDRESS 0x080 +#define PCI_0MEMORY1_HIGH_DECODE_ADDRESS 0x088 +#define PCI_0MEMORY2_LOW_DECODE_ADDRESS 0x258 +#define PCI_0MEMORY2_HIGH_DECODE_ADDRESS 0x260 +#define PCI_0MEMORY3_LOW_DECODE_ADDRESS 0x280 +#define PCI_0MEMORY3_HIGH_DECODE_ADDRESS 0x288 + +#define PCI_1I_O_LOW_DECODE_ADDRESS 0x090 +#define PCI_1I_O_HIGH_DECODE_ADDRESS 0x098 +#define PCI_1MEMORY0_LOW_DECODE_ADDRESS 0x0a0 +#define PCI_1MEMORY0_HIGH_DECODE_ADDRESS 0x0a8 +#define PCI_1MEMORY1_LOW_DECODE_ADDRESS 0x0b0 +#define PCI_1MEMORY1_HIGH_DECODE_ADDRESS 0x0b8 +#define PCI_1MEMORY2_LOW_DECODE_ADDRESS 0x2a0 +#define PCI_1MEMORY2_HIGH_DECODE_ADDRESS 0x2a8 +#define PCI_1MEMORY3_LOW_DECODE_ADDRESS 0x2b0 +#define PCI_1MEMORY3_HIGH_DECODE_ADDRESS 0x2b8 + +#define INTERNAL_SPACE_DECODE 0x068 + +#define CPU_0_LOW_DECODE_ADDRESS 0x290 +#define CPU_0_HIGH_DECODE_ADDRESS 0x298 +#define CPU_1_LOW_DECODE_ADDRESS 0x2c0 +#define CPU_1_HIGH_DECODE_ADDRESS 0x2c8 + +#define PCI_0I_O_ADDRESS_REMAP 0x0f0 +#define PCI_0MEMORY0_ADDRESS_REMAP 0x0f8 +#define PCI_0MEMORY0_HIGH_ADDRESS_REMAP 0x320 +#define PCI_0MEMORY1_ADDRESS_REMAP 0x100 +#define PCI_0MEMORY1_HIGH_ADDRESS_REMAP 0x328 +#define PCI_0MEMORY2_ADDRESS_REMAP 0x2f8 +#define PCI_0MEMORY2_HIGH_ADDRESS_REMAP 0x330 +#define PCI_0MEMORY3_ADDRESS_REMAP 0x300 +#define PCI_0MEMORY3_HIGH_ADDRESS_REMAP 0x338 + +#define PCI_1I_O_ADDRESS_REMAP 0x108 +#define PCI_1MEMORY0_ADDRESS_REMAP 0x110 +#define PCI_1MEMORY0_HIGH_ADDRESS_REMAP 0x340 +#define PCI_1MEMORY1_ADDRESS_REMAP 0x118 +#define PCI_1MEMORY1_HIGH_ADDRESS_REMAP 0x348 +#define PCI_1MEMORY2_ADDRESS_REMAP 0x310 +#define PCI_1MEMORY2_HIGH_ADDRESS_REMAP 0x350 +#define PCI_1MEMORY3_ADDRESS_REMAP 0x318 +#define PCI_1MEMORY3_HIGH_ADDRESS_REMAP 0x358 + +/****************************************/ +/* CPU Sync Barrier */ +/****************************************/ + +#define PCI_0SYNC_BARIER_VIRTUAL_REGISTER 0x0c0 +#define PCI_1SYNC_BARIER_VIRTUAL_REGISTER 0x0c8 + + +/****************************************/ +/* CPU Access Protect */ +/****************************************/ + +#define CPU_LOW_PROTECT_ADDRESS_0 0X180 +#define CPU_HIGH_PROTECT_ADDRESS_0 0X188 +#define CPU_LOW_PROTECT_ADDRESS_1 0X190 +#define CPU_HIGH_PROTECT_ADDRESS_1 0X198 +#define CPU_LOW_PROTECT_ADDRESS_2 0X1a0 +#define CPU_HIGH_PROTECT_ADDRESS_2 0X1a8 +#define CPU_LOW_PROTECT_ADDRESS_3 0X1b0 +#define CPU_HIGH_PROTECT_ADDRESS_3 0X1b8 +#define CPU_LOW_PROTECT_ADDRESS_4 0X1c0 +#define CPU_HIGH_PROTECT_ADDRESS_4 0X1c8 +#define CPU_LOW_PROTECT_ADDRESS_5 0X1d0 +#define CPU_HIGH_PROTECT_ADDRESS_5 0X1d8 +#define CPU_LOW_PROTECT_ADDRESS_6 0X1e0 +#define CPU_HIGH_PROTECT_ADDRESS_6 0X1e8 +#define CPU_LOW_PROTECT_ADDRESS_7 0X1f0 +#define CPU_HIGH_PROTECT_ADDRESS_7 0X1f8 + + +/****************************************/ +/* Snoop Control */ +/****************************************/ + +#define SNOOP_BASE_ADDRESS_0 0x380 +#define SNOOP_TOP_ADDRESS_0 0x388 +#define SNOOP_BASE_ADDRESS_1 0x390 +#define SNOOP_TOP_ADDRESS_1 0x398 +#define SNOOP_BASE_ADDRESS_2 0x3a0 +#define SNOOP_TOP_ADDRESS_2 0x3a8 +#define SNOOP_BASE_ADDRESS_3 0x3b0 +#define SNOOP_TOP_ADDRESS_3 0x3b8 + +/****************************************/ +/* CPU Error Report */ +/****************************************/ + +#define CPU_ERROR_ADDRESS_LOW 0x070 +#define CPU_ERROR_ADDRESS_HIGH 0x078 +#define CPU_ERROR_DATA_LOW 0x128 +#define CPU_ERROR_DATA_HIGH 0x130 +#define CPU_ERROR_PARITY 0x138 +#define CPU_ERROR_CAUSE 0x140 +#define CPU_ERROR_MASK 0x148 + +/****************************************/ +/* Pslave Debug */ +/****************************************/ + +#define X_0_ADDRESS 0x360 +#define X_0_COMMAND_ID 0x368 +#define X_1_ADDRESS 0x370 +#define X_1_COMMAND_ID 0x378 +#define WRITE_DATA_LOW 0x3c0 +#define WRITE_DATA_HIGH 0x3c8 +#define WRITE_BYTE_ENABLE 0X3e0 +#define READ_DATA_LOW 0x3d0 +#define READ_DATA_HIGH 0x3d8 +#define READ_ID 0x3e8 + + +/****************************************/ +/* SDRAM and Device Address Space */ +/****************************************/ + + +/****************************************/ +/* SDRAM Configuration */ +/****************************************/ + +#define SDRAM_CONFIGURATION 0x448 +#define SDRAM_OPERATION_MODE 0x474 +#define SDRAM_ADDRESS_DECODE 0x47C +#define SDRAM_TIMING_PARAMETERS 0x4b4 +#define SDRAM_UMA_CONTROL 0x4a4 +#define SDRAM_CROSS_BAR_CONTROL_LOW 0x4a8 +#define SDRAM_CROSS_BAR_CONTROL_HIGH 0x4ac +#define SDRAM_CROSS_BAR_TIMEOUT 0x4b0 + + +/****************************************/ +/* SDRAM Parameters */ +/****************************************/ + +#define SDRAM_BANK0PARAMETERS 0x44C +#define SDRAM_BANK1PARAMETERS 0x450 +#define SDRAM_BANK2PARAMETERS 0x454 +#define SDRAM_BANK3PARAMETERS 0x458 + + +/****************************************/ +/* SDRAM Error Report */ +/****************************************/ + +#define SDRAM_ERROR_DATA_LOW 0x484 +#define SDRAM_ERROR_DATA_HIGH 0x480 +#define SDRAM_AND_DEVICE_ERROR_ADDRESS 0x490 +#define SDRAM_RECEIVED_ECC 0x488 +#define SDRAM_CALCULATED_ECC 0x48c +#define SDRAM_ECC_CONTROL 0x494 +#define SDRAM_ECC_ERROR_COUNTER 0x498 + + +/****************************************/ +/* SDunit Debug (for internal use) */ +/****************************************/ + +#define X0_ADDRESS 0x500 +#define X0_COMMAND_AND_ID 0x504 +#define X0_WRITE_DATA_LOW 0x508 +#define X0_WRITE_DATA_HIGH 0x50c +#define X0_WRITE_BYTE_ENABLE 0x518 +#define X0_READ_DATA_LOW 0x510 +#define X0_READ_DATA_HIGH 0x514 +#define X0_READ_ID 0x51c +#define X1_ADDRESS 0x520 +#define X1_COMMAND_AND_ID 0x524 +#define X1_WRITE_DATA_LOW 0x528 +#define X1_WRITE_DATA_HIGH 0x52c +#define X1_WRITE_BYTE_ENABLE 0x538 +#define X1_READ_DATA_LOW 0x530 +#define X1_READ_DATA_HIGH 0x534 +#define X1_READ_ID 0x53c +#define X0_SNOOP_ADDRESS 0x540 +#define X0_SNOOP_COMMAND 0x544 +#define X1_SNOOP_ADDRESS 0x548 +#define X1_SNOOP_COMMAND 0x54c + + +/****************************************/ +/* Device Parameters */ +/****************************************/ + +#define DEVICE_BANK0PARAMETERS 0x45c +#define DEVICE_BANK1PARAMETERS 0x460 +#define DEVICE_BANK2PARAMETERS 0x464 +#define DEVICE_BANK3PARAMETERS 0x468 +#define DEVICE_BOOT_BANK_PARAMETERS 0x46c +#define DEVICE_CONTROL 0x4c0 +#define DEVICE_CROSS_BAR_CONTROL_LOW 0x4c8 +#define DEVICE_CROSS_BAR_CONTROL_HIGH 0x4cc +#define DEVICE_CROSS_BAR_TIMEOUT 0x4c4 + + +/****************************************/ +/* Device Interrupt */ +/****************************************/ + +#define DEVICE_INTERRUPT_CAUSE 0x4d0 +#define DEVICE_INTERRUPT_MASK 0x4d4 +#define DEVICE_ERROR_ADDRESS 0x4d8 + +/****************************************/ +/* DMA Record */ +/****************************************/ + +#define CHANNEL0_DMA_BYTE_COUNT 0x800 +#define CHANNEL1_DMA_BYTE_COUNT 0x804 +#define CHANNEL2_DMA_BYTE_COUNT 0x808 +#define CHANNEL3_DMA_BYTE_COUNT 0x80C +#define CHANNEL4_DMA_BYTE_COUNT 0x900 +#define CHANNEL5_DMA_BYTE_COUNT 0x904 +#define CHANNEL6_DMA_BYTE_COUNT 0x908 +#define CHANNEL7_DMA_BYTE_COUNT 0x90C +#define CHANNEL0_DMA_SOURCE_ADDRESS 0x810 +#define CHANNEL1_DMA_SOURCE_ADDRESS 0x814 +#define CHANNEL2_DMA_SOURCE_ADDRESS 0x818 +#define CHANNEL3_DMA_SOURCE_ADDRESS 0x81C +#define CHANNEL4_DMA_SOURCE_ADDRESS 0x910 +#define CHANNEL5_DMA_SOURCE_ADDRESS 0x914 +#define CHANNEL6_DMA_SOURCE_ADDRESS 0x918 +#define CHANNEL7_DMA_SOURCE_ADDRESS 0x91C +#define CHANNEL0_DMA_DESTINATION_ADDRESS 0x820 +#define CHANNEL1_DMA_DESTINATION_ADDRESS 0x824 +#define CHANNEL2_DMA_DESTINATION_ADDRESS 0x828 +#define CHANNEL3_DMA_DESTINATION_ADDRESS 0x82C +#define CHANNEL4_DMA_DESTINATION_ADDRESS 0x920 +#define CHANNEL5_DMA_DESTINATION_ADDRESS 0x924 +#define CHANNEL6_DMA_DESTINATION_ADDRESS 0x928 +#define CHANNEL7_DMA_DESTINATION_ADDRESS 0x92C +#define CHANNEL0NEXT_RECORD_POINTER 0x830 +#define CHANNEL1NEXT_RECORD_POINTER 0x834 +#define CHANNEL2NEXT_RECORD_POINTER 0x838 +#define CHANNEL3NEXT_RECORD_POINTER 0x83C +#define CHANNEL4NEXT_RECORD_POINTER 0x930 +#define CHANNEL5NEXT_RECORD_POINTER 0x934 +#define CHANNEL6NEXT_RECORD_POINTER 0x938 +#define CHANNEL7NEXT_RECORD_POINTER 0x93C +#define CHANNEL0CURRENT_DESCRIPTOR_POINTER 0x870 +#define CHANNEL1CURRENT_DESCRIPTOR_POINTER 0x874 +#define CHANNEL2CURRENT_DESCRIPTOR_POINTER 0x878 +#define CHANNEL3CURRENT_DESCRIPTOR_POINTER 0x87C +#define CHANNEL4CURRENT_DESCRIPTOR_POINTER 0x970 +#define CHANNEL5CURRENT_DESCRIPTOR_POINTER 0x974 +#define CHANNEL6CURRENT_DESCRIPTOR_POINTER 0x978 +#define CHANNEL7CURRENT_DESCRIPTOR_POINTER 0x97C +#define CHANNEL0_DMA_SOURCE_HIGH_PCI_ADDRESS 0x890 +#define CHANNEL1_DMA_SOURCE_HIGH_PCI_ADDRESS 0x894 +#define CHANNEL2_DMA_SOURCE_HIGH_PCI_ADDRESS 0x898 +#define CHANNEL3_DMA_SOURCE_HIGH_PCI_ADDRESS 0x89c +#define CHANNEL4_DMA_SOURCE_HIGH_PCI_ADDRESS 0x990 +#define CHANNEL5_DMA_SOURCE_HIGH_PCI_ADDRESS 0x994 +#define CHANNEL6_DMA_SOURCE_HIGH_PCI_ADDRESS 0x998 +#define CHANNEL7_DMA_SOURCE_HIGH_PCI_ADDRESS 0x99c +#define CHANNEL0_DMA_DESTINATION_HIGH_PCI_ADDRESS 0x8a0 +#define CHANNEL1_DMA_DESTINATION_HIGH_PCI_ADDRESS 0x8a4 +#define CHANNEL2_DMA_DESTINATION_HIGH_PCI_ADDRESS 0x8a8 +#define CHANNEL3_DMA_DESTINATION_HIGH_PCI_ADDRESS 0x8ac +#define CHANNEL4_DMA_DESTINATION_HIGH_PCI_ADDRESS 0x9a0 +#define CHANNEL5_DMA_DESTINATION_HIGH_PCI_ADDRESS 0x9a4 +#define CHANNEL6_DMA_DESTINATION_HIGH_PCI_ADDRESS 0x9a8 +#define CHANNEL7_DMA_DESTINATION_HIGH_PCI_ADDRESS 0x9ac +#define CHANNEL0_DMA_NEXT_RECORD_POINTER_HIGH_PCI_ADDRESS 0x8b0 +#define CHANNEL1_DMA_NEXT_RECORD_POINTER_HIGH_PCI_ADDRESS 0x8b4 +#define CHANNEL2_DMA_NEXT_RECORD_POINTER_HIGH_PCI_ADDRESS 0x8b8 +#define CHANNEL3_DMA_NEXT_RECORD_POINTER_HIGH_PCI_ADDRESS 0x8bc +#define CHANNEL4_DMA_NEXT_RECORD_POINTER_HIGH_PCI_ADDRESS 0x9b0 +#define CHANNEL5_DMA_NEXT_RECORD_POINTER_HIGH_PCI_ADDRESS 0x9b4 +#define CHANNEL6_DMA_NEXT_RECORD_POINTER_HIGH_PCI_ADDRESS 0x9b8 +#define CHANNEL7_DMA_NEXT_RECORD_POINTER_HIGH_PCI_ADDRESS 0x9bc + +/****************************************/ +/* DMA Channel Control */ +/****************************************/ + +#define CHANNEL0CONTROL 0x840 +#define CHANNEL0CONTROL_HIGH 0x880 + +#define CHANNEL1CONTROL 0x844 +#define CHANNEL1CONTROL_HIGH 0x884 + +#define CHANNEL2CONTROL 0x848 +#define CHANNEL2CONTROL_HIGH 0x888 + +#define CHANNEL3CONTROL 0x84C +#define CHANNEL3CONTROL_HIGH 0x88C + +#define CHANNEL4CONTROL 0x940 +#define CHANNEL4CONTROL_HIGH 0x980 + +#define CHANNEL5CONTROL 0x944 +#define CHANNEL5CONTROL_HIGH 0x984 + +#define CHANNEL6CONTROL 0x948 +#define CHANNEL6CONTROL_HIGH 0x988 + +#define CHANNEL7CONTROL 0x94C +#define CHANNEL7CONTROL_HIGH 0x98C + + +/****************************************/ +/* DMA Arbiter */ +/****************************************/ + +#define ARBITER_CONTROL_0_3 0x860 +#define ARBITER_CONTROL_4_7 0x960 + + +/****************************************/ +/* DMA Interrupt */ +/****************************************/ + +#define CHANELS0_3_INTERRUPT_CAUSE 0x8c0 +#define CHANELS0_3_INTERRUPT_MASK 0x8c4 +#define CHANELS0_3_ERROR_ADDRESS 0x8c8 +#define CHANELS0_3_ERROR_SELECT 0x8cc +#define CHANELS4_7_INTERRUPT_CAUSE 0x9c0 +#define CHANELS4_7_INTERRUPT_MASK 0x9c4 +#define CHANELS4_7_ERROR_ADDRESS 0x9c8 +#define CHANELS4_7_ERROR_SELECT 0x9cc + + +/****************************************/ +/* DMA Debug (for internal use) */ +/****************************************/ + +#define DMA_X0_ADDRESS 0x8e0 +#define DMA_X0_COMMAND_AND_ID 0x8e4 +#define DMA_X0_WRITE_DATA_LOW 0x8e8 +#define DMA_X0_WRITE_DATA_HIGH 0x8ec +#define DMA_X0_WRITE_BYTE_ENABLE 0x8f8 +#define DMA_X0_READ_DATA_LOW 0x8f0 +#define DMA_X0_READ_DATA_HIGH 0x8f4 +#define DMA_X0_READ_ID 0x8fc +#define DMA_X1_ADDRESS 0x9e0 +#define DMA_X1_COMMAND_AND_ID 0x9e4 +#define DMA_X1_WRITE_DATA_LOW 0x9e8 +#define DMA_X1_WRITE_DATA_HIGH 0x9ec +#define DMA_X1_WRITE_BYTE_ENABLE 0x9f8 +#define DMA_X1_READ_DATA_LOW 0x9f0 +#define DMA_X1_READ_DATA_HIGH 0x9f4 +#define DMA_X1_READ_ID 0x9fc + +/****************************************/ +/* Timer_Counter */ +/****************************************/ + +#define TIMER_COUNTER0 0x850 +#define TIMER_COUNTER1 0x854 +#define TIMER_COUNTER2 0x858 +#define TIMER_COUNTER3 0x85C +#define TIMER_COUNTER_0_3_CONTROL 0x864 +#define TIMER_COUNTER_0_3_INTERRUPT_CAUSE 0x868 +#define TIMER_COUNTER_0_3_INTERRUPT_MASK 0x86c +#define TIMER_COUNTER4 0x950 +#define TIMER_COUNTER5 0x954 +#define TIMER_COUNTER6 0x958 +#define TIMER_COUNTER7 0x95C +#define TIMER_COUNTER_4_7_CONTROL 0x964 +#define TIMER_COUNTER_4_7_INTERRUPT_CAUSE 0x968 +#define TIMER_COUNTER_4_7_INTERRUPT_MASK 0x96c + +/****************************************/ +/* PCI Slave Address Decoding */ +/****************************************/ + +#define PCI_0SCS_0_BANK_SIZE 0xc08 +#define PCI_1SCS_0_BANK_SIZE 0xc88 +#define PCI_0SCS_1_BANK_SIZE 0xd08 +#define PCI_1SCS_1_BANK_SIZE 0xd88 +#define PCI_0SCS_2_BANK_SIZE 0xc0c +#define PCI_1SCS_2_BANK_SIZE 0xc8c +#define PCI_0SCS_3_BANK_SIZE 0xd0c +#define PCI_1SCS_3_BANK_SIZE 0xd8c +#define PCI_0CS_0_BANK_SIZE 0xc10 +#define PCI_1CS_0_BANK_SIZE 0xc90 +#define PCI_0CS_1_BANK_SIZE 0xd10 +#define PCI_1CS_1_BANK_SIZE 0xd90 +#define PCI_0CS_2_BANK_SIZE 0xd18 +#define PCI_1CS_2_BANK_SIZE 0xd98 +#define PCI_0CS_3_BANK_SIZE 0xc14 +#define PCI_1CS_3_BANK_SIZE 0xc94 +#define PCI_0CS_BOOT_BANK_SIZE 0xd14 +#define PCI_1CS_BOOT_BANK_SIZE 0xd94 +#define PCI_0P2P_MEM0_BAR_SIZE 0xd1c +#define PCI_1P2P_MEM0_BAR_SIZE 0xd9c +#define PCI_0P2P_MEM1_BAR_SIZE 0xd20 +#define PCI_1P2P_MEM1_BAR_SIZE 0xda0 +#define PCI_0P2P_I_O_BAR_SIZE 0xd24 +#define PCI_1P2P_I_O_BAR_SIZE 0xda4 +#define PCI_0CPU_BAR_SIZE 0xd28 +#define PCI_1CPU_BAR_SIZE 0xda8 +#define PCI_0DAC_SCS_0_BANK_SIZE 0xe00 +#define PCI_1DAC_SCS_0_BANK_SIZE 0xe80 +#define PCI_0DAC_SCS_1_BANK_SIZE 0xe04 +#define PCI_1DAC_SCS_1_BANK_SIZE 0xe84 +#define PCI_0DAC_SCS_2_BANK_SIZE 0xe08 +#define PCI_1DAC_SCS_2_BANK_SIZE 0xe88 +#define PCI_0DAC_SCS_3_BANK_SIZE 0xe0c +#define PCI_1DAC_SCS_3_BANK_SIZE 0xe8c +#define PCI_0DAC_CS_0_BANK_SIZE 0xe10 +#define PCI_1DAC_CS_0_BANK_SIZE 0xe90 +#define PCI_0DAC_CS_1_BANK_SIZE 0xe14 +#define PCI_1DAC_CS_1_BANK_SIZE 0xe94 +#define PCI_0DAC_CS_2_BANK_SIZE 0xe18 +#define PCI_1DAC_CS_2_BANK_SIZE 0xe98 +#define PCI_0DAC_CS_3_BANK_SIZE 0xe1c +#define PCI_1DAC_CS_3_BANK_SIZE 0xe9c +#define PCI_0DAC_BOOTCS_BANK_SIZE 0xe20 +#define PCI_1DAC_BOOTCS_BANK_SIZE 0xea0 +#define PCI_0DAC_P2P_MEM0_BAR_SIZE 0xe24 +#define PCI_1DAC_P2P_MEM0_BAR_SIZE 0xea4 +#define PCI_0DAC_P2P_MEM1_BAR_SIZE 0xe28 +#define PCI_1DAC_P2P_MEM1_BAR_SIZE 0xea8 +#define PCI_0DAC_CPU_BAR_SIZE 0xe2c +#define PCI_1DAC_CPU_BAR_SIZE 0xeac +#define PCI_0EXPANSION_ROM_BAR_SIZE 0xd2c +#define PCI_1EXPANSION_ROM_BAR_SIZE 0xdac +#define PCI_0BASE_ADDRESS_REGISTERS_ENABLE 0xc3c +#define PCI_1BASE_ADDRESS_REGISTERS_ENABLE 0xcbc +#define PCI_0SCS_0_BASE_ADDRESS_REMAP 0xc48 +#define PCI_1SCS_0_BASE_ADDRESS_REMAP 0xcc8 +#define PCI_0SCS_1_BASE_ADDRESS_REMAP 0xd48 +#define PCI_1SCS_1_BASE_ADDRESS_REMAP 0xdc8 +#define PCI_0SCS_2_BASE_ADDRESS_REMAP 0xc4c +#define PCI_1SCS_2_BASE_ADDRESS_REMAP 0xccc +#define PCI_0SCS_3_BASE_ADDRESS_REMAP 0xd4c +#define PCI_1SCS_3_BASE_ADDRESS_REMAP 0xdcc +#define PCI_0CS_0_BASE_ADDRESS_REMAP 0xc50 +#define PCI_1CS_0_BASE_ADDRESS_REMAP 0xcd0 +#define PCI_0CS_1_BASE_ADDRESS_REMAP 0xd50 +#define PCI_1CS_1_BASE_ADDRESS_REMAP 0xdd0 +#define PCI_0CS_2_BASE_ADDRESS_REMAP 0xd58 +#define PCI_1CS_2_BASE_ADDRESS_REMAP 0xdd8 +#define PCI_0CS_3_BASE_ADDRESS_REMAP 0xc54 +#define PCI_1CS_3_BASE_ADDRESS_REMAP 0xcd4 +#define PCI_0CS_BOOTCS_BASE_ADDRESS_REMAP 0xd54 +#define PCI_1CS_BOOTCS_BASE_ADDRESS_REMAP 0xdd4 +#define PCI_0P2P_MEM0_BASE_ADDRESS_REMAP_LOW 0xd5c +#define PCI_1P2P_MEM0_BASE_ADDRESS_REMAP_LOW 0xddc +#define PCI_0P2P_MEM0_BASE_ADDRESS_REMAP_HIGH 0xd60 +#define PCI_1P2P_MEM0_BASE_ADDRESS_REMAP_HIGH 0xde0 +#define PCI_0P2P_MEM1_BASE_ADDRESS_REMAP_LOW 0xd64 +#define PCI_1P2P_MEM1_BASE_ADDRESS_REMAP_LOW 0xde4 +#define PCI_0P2P_MEM1_BASE_ADDRESS_REMAP_HIGH 0xd68 +#define PCI_1P2P_MEM1_BASE_ADDRESS_REMAP_HIGH 0xde8 +#define PCI_0P2P_I_O_BASE_ADDRESS_REMAP 0xd6c +#define PCI_1P2P_I_O_BASE_ADDRESS_REMAP 0xdec +#define PCI_0CPU_BASE_ADDRESS_REMAP 0xd70 +#define PCI_1CPU_BASE_ADDRESS_REMAP 0xdf0 +#define PCI_0DAC_SCS_0_BASE_ADDRESS_REMAP 0xf00 +#define PCI_1DAC_SCS_0_BASE_ADDRESS_REMAP 0xff0 +#define PCI_0DAC_SCS_1_BASE_ADDRESS_REMAP 0xf04 +#define PCI_1DAC_SCS_1_BASE_ADDRESS_REMAP 0xf84 +#define PCI_0DAC_SCS_2_BASE_ADDRESS_REMAP 0xf08 +#define PCI_1DAC_SCS_2_BASE_ADDRESS_REMAP 0xf88 +#define PCI_0DAC_SCS_3_BASE_ADDRESS_REMAP 0xf0c +#define PCI_1DAC_SCS_3_BASE_ADDRESS_REMAP 0xf8c +#define PCI_0DAC_CS_0_BASE_ADDRESS_REMAP 0xf10 +#define PCI_1DAC_CS_0_BASE_ADDRESS_REMAP 0xf90 +#define PCI_0DAC_CS_1_BASE_ADDRESS_REMAP 0xf14 +#define PCI_1DAC_CS_1_BASE_ADDRESS_REMAP 0xf94 +#define PCI_0DAC_CS_2_BASE_ADDRESS_REMAP 0xf18 +#define PCI_1DAC_CS_2_BASE_ADDRESS_REMAP 0xf98 +#define PCI_0DAC_CS_3_BASE_ADDRESS_REMAP 0xf1c +#define PCI_1DAC_CS_3_BASE_ADDRESS_REMAP 0xf9c +#define PCI_0DAC_BOOTCS_BASE_ADDRESS_REMAP 0xf20 +#define PCI_1DAC_BOOTCS_BASE_ADDRESS_REMAP 0xfa0 +#define PCI_0DAC_P2P_MEM0_BASE_ADDRESS_REMAP_LOW 0xf24 +#define PCI_1DAC_P2P_MEM0_BASE_ADDRESS_REMAP_LOW 0xfa4 +#define PCI_0DAC_P2P_MEM0_BASE_ADDRESS_REMAP_HIGH 0xf28 +#define PCI_1DAC_P2P_MEM0_BASE_ADDRESS_REMAP_HIGH 0xfa8 +#define PCI_0DAC_P2P_MEM1_BASE_ADDRESS_REMAP_LOW 0xf2c +#define PCI_1DAC_P2P_MEM1_BASE_ADDRESS_REMAP_LOW 0xfac +#define PCI_0DAC_P2P_MEM1_BASE_ADDRESS_REMAP_HIGH 0xf30 +#define PCI_1DAC_P2P_MEM1_BASE_ADDRESS_REMAP_HIGH 0xfb0 +#define PCI_0DAC_CPU_BASE_ADDRESS_REMAP 0xf34 +#define PCI_1DAC_CPU_BASE_ADDRESS_REMAP 0xfb4 +#define PCI_0EXPANSION_ROM_BASE_ADDRESS_REMAP 0xf38 +#define PCI_1EXPANSION_ROM_BASE_ADDRESS_REMAP 0xfb8 +#define PCI_0ADDRESS_DECODE_CONTROL 0xd3c +#define PCI_1ADDRESS_DECODE_CONTROL 0xdbc + +/****************************************/ +/* PCI Control */ +/****************************************/ + +#define PCI_0COMMAND 0xc00 +#define PCI_1COMMAND 0xc80 +#define PCI_0MODE 0xd00 +#define PCI_1MODE 0xd80 +#define PCI_0TIMEOUT_RETRY 0xc04 +#define PCI_1TIMEOUT_RETRY 0xc84 +#define PCI_0READ_BUFFER_DISCARD_TIMER 0xd04 +#define PCI_1READ_BUFFER_DISCARD_TIMER 0xd84 +#define MSI_0TRIGGER_TIMER 0xc38 +#define MSI_1TRIGGER_TIMER 0xcb8 +#define PCI_0ARBITER_CONTROL 0x1d00 +#define PCI_1ARBITER_CONTROL 0x1d80 +/* changing untill here */ +#define PCI_0CROSS_BAR_CONTROL_LOW 0x1d08 +#define PCI_0CROSS_BAR_CONTROL_HIGH 0x1d0c +#define PCI_0CROSS_BAR_TIMEOUT 0x1d04 +#define PCI_0READ_RESPONSE_CROSS_BAR_CONTROL_LOW 0x1d18 +#define PCI_0READ_RESPONSE_CROSS_BAR_CONTROL_HIGH 0x1d1c +#define PCI_0SYNC_BARRIER_VIRTUAL_REGISTER 0x1d10 +#define PCI_0P2P_CONFIGURATION 0x1d14 +#define PCI_0ACCESS_CONTROL_BASE_0_LOW 0x1e00 +#define PCI_0ACCESS_CONTROL_BASE_0_HIGH 0x1e04 +#define PCI_0ACCESS_CONTROL_TOP_0 0x1e08 +#define PCI_0ACCESS_CONTROL_BASE_1_LOW 0c1e10 +#define PCI_0ACCESS_CONTROL_BASE_1_HIGH 0x1e14 +#define PCI_0ACCESS_CONTROL_TOP_1 0x1e18 +#define PCI_0ACCESS_CONTROL_BASE_2_LOW 0c1e20 +#define PCI_0ACCESS_CONTROL_BASE_2_HIGH 0x1e24 +#define PCI_0ACCESS_CONTROL_TOP_2 0x1e28 +#define PCI_0ACCESS_CONTROL_BASE_3_LOW 0c1e30 +#define PCI_0ACCESS_CONTROL_BASE_3_HIGH 0x1e34 +#define PCI_0ACCESS_CONTROL_TOP_3 0x1e38 +#define PCI_0ACCESS_CONTROL_BASE_4_LOW 0c1e40 +#define PCI_0ACCESS_CONTROL_BASE_4_HIGH 0x1e44 +#define PCI_0ACCESS_CONTROL_TOP_4 0x1e48 +#define PCI_0ACCESS_CONTROL_BASE_5_LOW 0c1e50 +#define PCI_0ACCESS_CONTROL_BASE_5_HIGH 0x1e54 +#define PCI_0ACCESS_CONTROL_TOP_5 0x1e58 +#define PCI_0ACCESS_CONTROL_BASE_6_LOW 0c1e60 +#define PCI_0ACCESS_CONTROL_BASE_6_HIGH 0x1e64 +#define PCI_0ACCESS_CONTROL_TOP_6 0x1e68 +#define PCI_0ACCESS_CONTROL_BASE_7_LOW 0c1e70 +#define PCI_0ACCESS_CONTROL_BASE_7_HIGH 0x1e74 +#define PCI_0ACCESS_CONTROL_TOP_7 0x1e78 +#define PCI_1CROSS_BAR_CONTROL_LOW 0x1d88 +#define PCI_1CROSS_BAR_CONTROL_HIGH 0x1d8c +#define PCI_1CROSS_BAR_TIMEOUT 0x1d84 +#define PCI_1READ_RESPONSE_CROSS_BAR_CONTROL_LOW 0x1d98 +#define PCI_1READ_RESPONSE_CROSS_BAR_CONTROL_HIGH 0x1d9c +#define PCI_1SYNC_BARRIER_VIRTUAL_REGISTER 0x1d90 +#define PCI_1P2P_CONFIGURATION 0x1d94 +#define PCI_1ACCESS_CONTROL_BASE_0_LOW 0x1e80 +#define PCI_1ACCESS_CONTROL_BASE_0_HIGH 0x1e84 +#define PCI_1ACCESS_CONTROL_TOP_0 0x1e88 +#define PCI_1ACCESS_CONTROL_BASE_1_LOW 0c1e90 +#define PCI_1ACCESS_CONTROL_BASE_1_HIGH 0x1e94 +#define PCI_1ACCESS_CONTROL_TOP_1 0x1e98 +#define PCI_1ACCESS_CONTROL_BASE_2_LOW 0c1ea0 +#define PCI_1ACCESS_CONTROL_BASE_2_HIGH 0x1ea4 +#define PCI_1ACCESS_CONTROL_TOP_2 0x1ea8 +#define PCI_1ACCESS_CONTROL_BASE_3_LOW 0c1eb0 +#define PCI_1ACCESS_CONTROL_BASE_3_HIGH 0x1eb4 +#define PCI_1ACCESS_CONTROL_TOP_3 0x1eb8 +#define PCI_1ACCESS_CONTROL_BASE_4_LOW 0c1ec0 +#define PCI_1ACCESS_CONTROL_BASE_4_HIGH 0x1ec4 +#define PCI_1ACCESS_CONTROL_TOP_4 0x1ec8 +#define PCI_1ACCESS_CONTROL_BASE_5_LOW 0c1ed0 +#define PCI_1ACCESS_CONTROL_BASE_5_HIGH 0x1ed4 +#define PCI_1ACCESS_CONTROL_TOP_5 0x1ed8 +#define PCI_1ACCESS_CONTROL_BASE_6_LOW 0c1ee0 +#define PCI_1ACCESS_CONTROL_BASE_6_HIGH 0x1ee4 +#define PCI_1ACCESS_CONTROL_TOP_6 0x1ee8 +#define PCI_1ACCESS_CONTROL_BASE_7_LOW 0c1ef0 +#define PCI_1ACCESS_CONTROL_BASE_7_HIGH 0x1ef4 +#define PCI_1ACCESS_CONTROL_TOP_7 0x1ef8 + +/****************************************/ +/* PCI Snoop Control */ +/****************************************/ + +#define PCI_0SNOOP_CONTROL_BASE_0_LOW 0x1f00 +#define PCI_0SNOOP_CONTROL_BASE_0_HIGH 0x1f04 +#define PCI_0SNOOP_CONTROL_TOP_0 0x1f08 +#define PCI_0SNOOP_CONTROL_BASE_1_0_LOW 0x1f10 +#define PCI_0SNOOP_CONTROL_BASE_1_0_HIGH 0x1f14 +#define PCI_0SNOOP_CONTROL_TOP_1 0x1f18 +#define PCI_0SNOOP_CONTROL_BASE_2_0_LOW 0x1f20 +#define PCI_0SNOOP_CONTROL_BASE_2_0_HIGH 0x1f24 +#define PCI_0SNOOP_CONTROL_TOP_2 0x1f28 +#define PCI_0SNOOP_CONTROL_BASE_3_0_LOW 0x1f30 +#define PCI_0SNOOP_CONTROL_BASE_3_0_HIGH 0x1f34 +#define PCI_0SNOOP_CONTROL_TOP_3 0x1f38 +#define PCI_1SNOOP_CONTROL_BASE_0_LOW 0x1f80 +#define PCI_1SNOOP_CONTROL_BASE_0_HIGH 0x1f84 +#define PCI_1SNOOP_CONTROL_TOP_0 0x1f88 +#define PCI_1SNOOP_CONTROL_BASE_1_0_LOW 0x1f90 +#define PCI_1SNOOP_CONTROL_BASE_1_0_HIGH 0x1f94 +#define PCI_1SNOOP_CONTROL_TOP_1 0x1f98 +#define PCI_1SNOOP_CONTROL_BASE_2_0_LOW 0x1fa0 +#define PCI_1SNOOP_CONTROL_BASE_2_0_HIGH 0x1fa4 +#define PCI_1SNOOP_CONTROL_TOP_2 0x1fa8 +#define PCI_1SNOOP_CONTROL_BASE_3_0_LOW 0x1fb0 +#define PCI_1SNOOP_CONTROL_BASE_3_0_HIGH 0x1fb4 +#define PCI_1SNOOP_CONTROL_TOP_3 0x1fb8 + +/****************************************/ +/* PCI Configuration Address */ +/****************************************/ + +#define PCI_0CONFIGURATION_ADDRESS 0xcf8 +#define PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER 0xcfc +#define PCI_1CONFIGURATION_ADDRESS 0xc78 +#define PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER 0xc7c +#define PCI_0INTERRUPT_ACKNOWLEDGE_VIRTUAL_REGISTER 0xc34 +#define PCI_1INTERRUPT_ACKNOWLEDGE_VIRTUAL_REGISTER 0xcb4 + +/****************************************/ +/* PCI Error Report */ +/****************************************/ + +#define PCI_0SERR_MASK 0xc28 +#define PCI_0ERROR_ADDRESS_LOW 0x1d40 +#define PCI_0ERROR_ADDRESS_HIGH 0x1d44 +#define PCI_0ERROR_DATA_LOW 0x1d48 +#define PCI_0ERROR_DATA_HIGH 0x1d4c +#define PCI_0ERROR_COMMAND 0x1d50 +#define PCI_0ERROR_CAUSE 0x1d58 +#define PCI_0ERROR_MASK 0x1d5c + +#define PCI_1SERR_MASK 0xca8 +#define PCI_1ERROR_ADDRESS_LOW 0x1dc0 +#define PCI_1ERROR_ADDRESS_HIGH 0x1dc4 +#define PCI_1ERROR_DATA_LOW 0x1dc8 +#define PCI_1ERROR_DATA_HIGH 0x1dcc +#define PCI_1ERROR_COMMAND 0x1dd0 +#define PCI_1ERROR_CAUSE 0x1dd8 +#define PCI_1ERROR_MASK 0x1ddc + + +/****************************************/ +/* Lslave Debug (for internal use) */ +/****************************************/ + +#define L_SLAVE_X0_ADDRESS 0x1d20 +#define L_SLAVE_X0_COMMAND_AND_ID 0x1d24 +#define L_SLAVE_X1_ADDRESS 0x1d28 +#define L_SLAVE_X1_COMMAND_AND_ID 0x1d2c +#define L_SLAVE_WRITE_DATA_LOW 0x1d30 +#define L_SLAVE_WRITE_DATA_HIGH 0x1d34 +#define L_SLAVE_WRITE_BYTE_ENABLE 0x1d60 +#define L_SLAVE_READ_DATA_LOW 0x1d38 +#define L_SLAVE_READ_DATA_HIGH 0x1d3c +#define L_SLAVE_READ_ID 0x1d64 + +/****************************************/ +/* PCI Configuration Function 0 */ +/****************************************/ + +#define PCI_DEVICE_AND_VENDOR_ID 0x000 +#define PCI_STATUS_AND_COMMAND 0x004 +#define PCI_CLASS_CODE_AND_REVISION_ID 0x008 +#define PCI_BIST_HEADER_TYPE_LATENCY_TIMER_CACHE_LINE 0x00C +#define PCI_SCS_0_BASE_ADDRESS 0x010 +#define PCI_SCS_1_BASE_ADDRESS 0x014 +#define PCI_SCS_2_BASE_ADDRESS 0x018 +#define PCI_SCS_3_BASE_ADDRESS 0x01C +#define PCI_INTERNAL_REGISTERS_MEMORY_MAPPED_BASE_ADDRESS 0x020 +#define PCI_INTERNAL_REGISTERS_I_OMAPPED_BASE_ADDRESS 0x024 +#define PCI_SUBSYSTEM_ID_AND_SUBSYSTEM_VENDOR_ID 0x02C +#define PCI_EXPANSION_ROM_BASE_ADDRESS_REGISTER 0x030 +#define PCI_CAPABILTY_LIST_POINTER 0x034 +#define PCI_INTERRUPT_PIN_AND_LINE 0x03C +#define PCI_POWER_MANAGEMENT_CAPABILITY 0x040 +#define PCI_POWER_MANAGEMENT_STATUS_AND_CONTROL 0x044 +#define PCI_VPD_ADDRESS 0x048 +#define PCI_VPD_DATA 0X04c +#define PCI_MSI_MESSAGE_CONTROL 0x050 +#define PCI_MSI_MESSAGE_ADDRESS 0x054 +#define PCI_MSI_MESSAGE_UPPER_ADDRESS 0x058 +#define PCI_MSI_MESSAGE_DATA 0x05c +#define PCI_COMPACT_PCI_HOT_SWAP_CAPABILITY 0x058 + +/****************************************/ +/* PCI Configuration Function 1 */ +/****************************************/ + +#define PCI_CS_0_BASE_ADDRESS 0x110 +#define PCI_CS_1_BASE_ADDRESS 0x114 +#define PCI_CS_2_BASE_ADDRESS 0x118 +#define PCI_CS_3_BASE_ADDRESS 0x11c +#define PCI_BOOTCS_BASE_ADDRESS 0x120 + +/****************************************/ +/* PCI Configuration Function 2 */ +/****************************************/ + +#define PCI_P2P_MEM0_BASE_ADDRESS 0x210 +#define PCI_P2P_MEM1_BASE_ADDRESS 0x214 +#define PCI_P2P_I_O_BASE_ADDRESS 0x218 +#define PCI_CPU_BASE_ADDRESS 0x21c + +/****************************************/ +/* PCI Configuration Function 4 */ +/****************************************/ + +#define PCI_DAC_SCS_0_BASE_ADDRESS_LOW 0x410 +#define PCI_DAC_SCS_0_BASE_ADDRESS_HIGH 0x414 +#define PCI_DAC_SCS_1_BASE_ADDRESS_LOW 0x418 +#define PCI_DAC_SCS_1_BASE_ADDRESS_HIGH 0x41c +#define PCI_DAC_P2P_MEM0_BASE_ADDRESS_LOW 0x420 +#define PCI_DAC_P2P_MEM0_BASE_ADDRESS_HIGH 0x424 + + +/****************************************/ +/* PCI Configuration Function 5 */ +/****************************************/ + +#define PCI_DAC_SCS_2_BASE_ADDRESS_LOW 0x510 +#define PCI_DAC_SCS_2_BASE_ADDRESS_HIGH 0x514 +#define PCI_DAC_SCS_3_BASE_ADDRESS_LOW 0x518 +#define PCI_DAC_SCS_3_BASE_ADDRESS_HIGH 0x51c +#define PCI_DAC_P2P_MEM1_BASE_ADDRESS_LOW 0x520 +#define PCI_DAC_P2P_MEM1_BASE_ADDRESS_HIGH 0x524 + + +/****************************************/ +/* PCI Configuration Function 6 */ +/****************************************/ + +#define PCI_DAC_CS_0_BASE_ADDRESS_LOW 0x610 +#define PCI_DAC_CS_0_BASE_ADDRESS_HIGH 0x614 +#define PCI_DAC_CS_1_BASE_ADDRESS_LOW 0x618 +#define PCI_DAC_CS_1_BASE_ADDRESS_HIGH 0x61c +#define PCI_DAC_CS_2_BASE_ADDRESS_LOW 0x620 +#define PCI_DAC_CS_2_BASE_ADDRESS_HIGH 0x624 + +/****************************************/ +/* PCI Configuration Function 7 */ +/****************************************/ + +#define PCI_DAC_CS_3_BASE_ADDRESS_LOW 0x710 +#define PCI_DAC_CS_3_BASE_ADDRESS_HIGH 0x714 +#define PCI_DAC_BOOTCS_BASE_ADDRESS_LOW 0x718 +#define PCI_DAC_BOOTCS_BASE_ADDRESS_HIGH 0x71c +#define PCI_DAC_CPU_BASE_ADDRESS_LOW 0x720 +#define PCI_DAC_CPU_BASE_ADDRESS_HIGH 0x724 + +/****************************************/ +/* Interrupts */ +/****************************************/ + +#define LOW_INTERRUPT_CAUSE_REGISTER 0xc18 +#define HIGH_INTERRUPT_CAUSE_REGISTER 0xc68 +#define CPU_INTERRUPT_MASK_REGISTER_LOW 0xc1c +#define CPU_INTERRUPT_MASK_REGISTER_HIGH 0xc6c +#define CPU_SELECT_CAUSE_REGISTER 0xc70 +#define PCI_0INTERRUPT_CAUSE_MASK_REGISTER_LOW 0xc24 +#define PCI_0INTERRUPT_CAUSE_MASK_REGISTER_HIGH 0xc64 +#define PCI_0SELECT_CAUSE 0xc74 +#define PCI_1INTERRUPT_CAUSE_MASK_REGISTER_LOW 0xca4 +#define PCI_1INTERRUPT_CAUSE_MASK_REGISTER_HIGH 0xce4 +#define PCI_1SELECT_CAUSE 0xcf4 +#define CPU_INT_0_MASK 0xe60 +#define CPU_INT_1_MASK 0xe64 +#define CPU_INT_2_MASK 0xe68 +#define CPU_INT_3_MASK 0xe6c + +/****************************************/ +/* I20 Support registers */ +/****************************************/ + +#define INBOUND_MESSAGE_REGISTER0_PCI0_SIDE 0x010 +#define INBOUND_MESSAGE_REGISTER1_PCI0_SIDE 0x014 +#define OUTBOUND_MESSAGE_REGISTER0_PCI0_SIDE 0x018 +#define OUTBOUND_MESSAGE_REGISTER1_PCI0_SIDE 0x01C +#define INBOUND_DOORBELL_REGISTER_PCI0_SIDE 0x020 +#define INBOUND_INTERRUPT_CAUSE_REGISTER_PCI0_SIDE 0x024 +#define INBOUND_INTERRUPT_MASK_REGISTER_PCI0_SIDE 0x028 +#define OUTBOUND_DOORBELL_REGISTER_PCI0_SIDE 0x02C +#define OUTBOUND_INTERRUPT_CAUSE_REGISTER_PCI0_SIDE 0x030 +#define OUTBOUND_INTERRUPT_MASK_REGISTER_PCI0_SIDE 0x034 +#define INBOUND_QUEUE_PORT_VIRTUAL_REGISTER_PCI0_SIDE 0x040 +#define OUTBOUND_QUEUE_PORT_VIRTUAL_REGISTER_PCI0_SIDE 0x044 +#define QUEUE_CONTROL_REGISTER_PCI0_SIDE 0x050 +#define QUEUE_BASE_ADDRESS_REGISTER_PCI0_SIDE 0x054 +#define INBOUND_FREE_HEAD_POINTER_REGISTER_PCI0_SIDE 0x060 +#define INBOUND_FREE_TAIL_POINTER_REGISTER_PCI0_SIDE 0x064 +#define INBOUND_POST_HEAD_POINTER_REGISTER_PCI0_SIDE 0x068 +#define INBOUND_POST_TAIL_POINTER_REGISTER_PCI0_SIDE 0x06C +#define OUTBOUND_FREE_HEAD_POINTER_REGISTER_PCI0_SIDE 0x070 +#define OUTBOUND_FREE_TAIL_POINTER_REGISTER_PCI0_SIDE 0x074 +#define OUTBOUND_POST_HEAD_POINTER_REGISTER_PCI0_SIDE 0x0F8 +#define OUTBOUND_POST_TAIL_POINTER_REGISTER_PCI0_SIDE 0x0FC + +#define INBOUND_MESSAGE_REGISTER0_PCI1_SIDE 0x090 +#define INBOUND_MESSAGE_REGISTER1_PCI1_SIDE 0x094 +#define OUTBOUND_MESSAGE_REGISTER0_PCI1_SIDE 0x098 +#define OUTBOUND_MESSAGE_REGISTER1_PCI1_SIDE 0x09C +#define INBOUND_DOORBELL_REGISTER_PCI1_SIDE 0x0A0 +#define INBOUND_INTERRUPT_CAUSE_REGISTER_PCI1_SIDE 0x0A4 +#define INBOUND_INTERRUPT_MASK_REGISTER_PCI1_SIDE 0x0A8 +#define OUTBOUND_DOORBELL_REGISTER_PCI1_SIDE 0x0AC +#define OUTBOUND_INTERRUPT_CAUSE_REGISTER_PCI1_SIDE 0x0B0 +#define OUTBOUND_INTERRUPT_MASK_REGISTER_PCI1_SIDE 0x0B4 +#define INBOUND_QUEUE_PORT_VIRTUAL_REGISTER_PCI1_SIDE 0x0C0 +#define OUTBOUND_QUEUE_PORT_VIRTUAL_REGISTER_PCI1_SIDE 0x0C4 +#define QUEUE_CONTROL_REGISTER_PCI1_SIDE 0x0D0 +#define QUEUE_BASE_ADDRESS_REGISTER_PCI1_SIDE 0x0D4 +#define INBOUND_FREE_HEAD_POINTER_REGISTER_PCI1_SIDE 0x0E0 +#define INBOUND_FREE_TAIL_POINTER_REGISTER_PCI1_SIDE 0x0E4 +#define INBOUND_POST_HEAD_POINTER_REGISTER_PCI1_SIDE 0x0E8 +#define INBOUND_POST_TAIL_POINTER_REGISTER_PCI1_SIDE 0x0EC +#define OUTBOUND_FREE_HEAD_POINTER_REGISTER_PCI1_SIDE 0x0F0 +#define OUTBOUND_FREE_TAIL_POINTER_REGISTER_PCI1_SIDE 0x0F4 +#define OUTBOUND_POST_HEAD_POINTER_REGISTER_PCI1_SIDE 0x078 +#define OUTBOUND_POST_TAIL_POINTER_REGISTER_PCI1_SIDE 0x07C + +#define INBOUND_MESSAGE_REGISTER0_CPU0_SIDE 0X1C10 +#define INBOUND_MESSAGE_REGISTER1_CPU0_SIDE 0X1C14 +#define OUTBOUND_MESSAGE_REGISTER0_CPU0_SIDE 0X1C18 +#define OUTBOUND_MESSAGE_REGISTER1_CPU0_SIDE 0X1C1C +#define INBOUND_DOORBELL_REGISTER_CPU0_SIDE 0X1C20 +#define INBOUND_INTERRUPT_CAUSE_REGISTER_CPU0_SIDE 0X1C24 +#define INBOUND_INTERRUPT_MASK_REGISTER_CPU0_SIDE 0X1C28 +#define OUTBOUND_DOORBELL_REGISTER_CPU0_SIDE 0X1C2C +#define OUTBOUND_INTERRUPT_CAUSE_REGISTER_CPU0_SIDE 0X1C30 +#define OUTBOUND_INTERRUPT_MASK_REGISTER_CPU0_SIDE 0X1C34 +#define INBOUND_QUEUE_PORT_VIRTUAL_REGISTER_CPU0_SIDE 0X1C40 +#define OUTBOUND_QUEUE_PORT_VIRTUAL_REGISTER_CPU0_SIDE 0X1C44 +#define QUEUE_CONTROL_REGISTER_CPU0_SIDE 0X1C50 +#define QUEUE_BASE_ADDRESS_REGISTER_CPU0_SIDE 0X1C54 +#define INBOUND_FREE_HEAD_POINTER_REGISTER_CPU0_SIDE 0X1C60 +#define INBOUND_FREE_TAIL_POINTER_REGISTER_CPU0_SIDE 0X1C64 +#define INBOUND_POST_HEAD_POINTER_REGISTER_CPU0_SIDE 0X1C68 +#define INBOUND_POST_TAIL_POINTER_REGISTER_CPU0_SIDE 0X1C6C +#define OUTBOUND_FREE_HEAD_POINTER_REGISTER_CPU0_SIDE 0X1C70 +#define OUTBOUND_FREE_TAIL_POINTER_REGISTER_CPU0_SIDE 0X1C74 +#define OUTBOUND_POST_HEAD_POINTER_REGISTER_CPU0_SIDE 0X1CF8 +#define OUTBOUND_POST_TAIL_POINTER_REGISTER_CPU0_SIDE 0X1CFC + +#define INBOUND_MESSAGE_REGISTER0_CPU1_SIDE 0X1C90 +#define INBOUND_MESSAGE_REGISTER1_CPU1_SIDE 0X1C94 +#define OUTBOUND_MESSAGE_REGISTER0_CPU1_SIDE 0X1C98 +#define OUTBOUND_MESSAGE_REGISTER1_CPU1_SIDE 0X1C9C +#define INBOUND_DOORBELL_REGISTER_CPU1_SIDE 0X1CA0 +#define INBOUND_INTERRUPT_CAUSE_REGISTER_CPU1_SIDE 0X1CA4 +#define INBOUND_INTERRUPT_MASK_REGISTER_CPU1_SIDE 0X1CA8 +#define OUTBOUND_DOORBELL_REGISTER_CPU1_SIDE 0X1CAC +#define OUTBOUND_INTERRUPT_CAUSE_REGISTER_CPU1_SIDE 0X1CB0 +#define OUTBOUND_INTERRUPT_MASK_REGISTER_CPU1_SIDE 0X1CB4 +#define INBOUND_QUEUE_PORT_VIRTUAL_REGISTER_CPU1_SIDE 0X1CC0 +#define OUTBOUND_QUEUE_PORT_VIRTUAL_REGISTER_CPU1_SIDE 0X1CC4 +#define QUEUE_CONTROL_REGISTER_CPU1_SIDE 0X1CD0 +#define QUEUE_BASE_ADDRESS_REGISTER_CPU1_SIDE 0X1CD4 +#define INBOUND_FREE_HEAD_POINTER_REGISTER_CPU1_SIDE 0X1CE0 +#define INBOUND_FREE_TAIL_POINTER_REGISTER_CPU1_SIDE 0X1CE4 +#define INBOUND_POST_HEAD_POINTER_REGISTER_CPU1_SIDE 0X1CE8 +#define INBOUND_POST_TAIL_POINTER_REGISTER_CPU1_SIDE 0X1CEC +#define OUTBOUND_FREE_HEAD_POINTER_REGISTER_CPU1_SIDE 0X1CF0 +#define OUTBOUND_FREE_TAIL_POINTER_REGISTER_CPU1_SIDE 0X1CF4 +#define OUTBOUND_POST_HEAD_POINTER_REGISTER_CPU1_SIDE 0X1C78 +#define OUTBOUND_POST_TAIL_POINTER_REGISTER_CPU1_SIDE 0X1C7C + +/****************************************/ +/* Communication Unit Registers */ +/****************************************/ + +#define ETHERNET_0_ADDRESS_CONTROL_LOW +#define ETHERNET_0_ADDRESS_CONTROL_HIGH 0xf204 +#define ETHERNET_0_RECEIVE_BUFFER_PCI_HIGH_ADDRESS 0xf208 +#define ETHERNET_0_TRANSMIT_BUFFER_PCI_HIGH_ADDRESS 0xf20c +#define ETHERNET_0_RECEIVE_DESCRIPTOR_PCI_HIGH_ADDRESS 0xf210 +#define ETHERNET_0_TRANSMIT_DESCRIPTOR_PCI_HIGH_ADDRESS 0xf214 +#define ETHERNET_0_HASH_TABLE_PCI_HIGH_ADDRESS 0xf218 +#define ETHERNET_1_ADDRESS_CONTROL_LOW 0xf220 +#define ETHERNET_1_ADDRESS_CONTROL_HIGH 0xf224 +#define ETHERNET_1_RECEIVE_BUFFER_PCI_HIGH_ADDRESS 0xf228 +#define ETHERNET_1_TRANSMIT_BUFFER_PCI_HIGH_ADDRESS 0xf22c +#define ETHERNET_1_RECEIVE_DESCRIPTOR_PCI_HIGH_ADDRESS 0xf230 +#define ETHERNET_1_TRANSMIT_DESCRIPTOR_PCI_HIGH_ADDRESS 0xf234 +#define ETHERNET_1_HASH_TABLE_PCI_HIGH_ADDRESS 0xf238 +#define ETHERNET_2_ADDRESS_CONTROL_LOW 0xf240 +#define ETHERNET_2_ADDRESS_CONTROL_HIGH 0xf244 +#define ETHERNET_2_RECEIVE_BUFFER_PCI_HIGH_ADDRESS 0xf248 +#define ETHERNET_2_TRANSMIT_BUFFER_PCI_HIGH_ADDRESS 0xf24c +#define ETHERNET_2_RECEIVE_DESCRIPTOR_PCI_HIGH_ADDRESS 0xf250 +#define ETHERNET_2_TRANSMIT_DESCRIPTOR_PCI_HIGH_ADDRESS 0xf254 +#define ETHERNET_2_HASH_TABLE_PCI_HIGH_ADDRESS 0xf258 +#define MPSC_0_ADDRESS_CONTROL_LOW 0xf280 +#define MPSC_0_ADDRESS_CONTROL_HIGH 0xf284 +#define MPSC_0_RECEIVE_BUFFER_PCI_HIGH_ADDRESS 0xf288 +#define MPSC_0_TRANSMIT_BUFFER_PCI_HIGH_ADDRESS 0xf28c +#define MPSC_0_RECEIVE_DESCRIPTOR_PCI_HIGH_ADDRESS 0xf290 +#define MPSC_0_TRANSMIT_DESCRIPTOR_PCI_HIGH_ADDRESS 0xf294 +#define MPSC_1_ADDRESS_CONTROL_LOW 0xf2a0 +#define MPSC_1_ADDRESS_CONTROL_HIGH 0xf2a4 +#define MPSC_1_RECEIVE_BUFFER_PCI_HIGH_ADDRESS 0xf2a8 +#define MPSC_1_TRANSMIT_BUFFER_PCI_HIGH_ADDRESS 0xf2ac +#define MPSC_1_RECEIVE_DESCRIPTOR_PCI_HIGH_ADDRESS 0xf2b0 +#define MPSC_1_TRANSMIT_DESCRIPTOR_PCI_HIGH_ADDRESS 0xf2b4 +#define MPSC_2_ADDRESS_CONTROL_LOW 0xf2c0 +#define MPSC_2_ADDRESS_CONTROL_HIGH 0xf2c4 +#define MPSC_2_RECEIVE_BUFFER_PCI_HIGH_ADDRESS 0xf2c8 +#define MPSC_2_TRANSMIT_BUFFER_PCI_HIGH_ADDRESS 0xf2cc +#define MPSC_2_RECEIVE_DESCRIPTOR_PCI_HIGH_ADDRESS 0xf2d0 +#define MPSC_2_TRANSMIT_DESCRIPTOR_PCI_HIGH_ADDRESS 0xf2d4 +#define SERIAL_INIT_PCI_HIGH_ADDRESS 0xf320 +#define SERIAL_INIT_LAST_DATA 0xf324 +#define SERIAL_INIT_STATUS_AND_CONTROL 0xf328 +#define COMM_UNIT_ARBITER_CONTROL 0xf300 +#define COMM_UNIT_CROSS_BAR_TIMEOUT 0xf304 +#define COMM_UNIT_INTERRUPT_CAUSE 0xf310 +#define COMM_UNIT_INTERRUPT_MASK 0xf314 +#define COMM_UNIT_ERROR_ADDRESS 0xf314 + +/****************************************/ +/* Cunit Debug (for internal use) */ +/****************************************/ + +#define CUNIT_ADDRESS 0xf340 +#define CUNIT_COMMAND_AND_ID 0xf344 +#define CUNIT_WRITE_DATA_LOW 0xf348 +#define CUNIT_WRITE_DATA_HIGH 0xf34c +#define CUNIT_WRITE_BYTE_ENABLE 0xf358 +#define CUNIT_READ_DATA_LOW 0xf350 +#define CUNIT_READ_DATA_HIGH 0xf354 +#define CUNIT_READ_ID 0xf35c + +/****************************************/ +/* Fast Ethernet Unit Registers */ +/****************************************/ + +/* Ethernet */ + +#define ETHERNET_PHY_ADDRESS_REGISTER 0x2000 +#define ETHERNET_SMI_REGISTER 0x2010 + +/* Ethernet 0 */ + +#define ETHERNET0_PORT_CONFIGURATION_REGISTER 0x2400 +#define ETHERNET0_PORT_CONFIGURATION_EXTEND_REGISTER 0x2408 +#define ETHERNET0_PORT_COMMAND_REGISTER 0x2410 +#define ETHERNET0_PORT_STATUS_REGISTER 0x2418 +#define ETHERNET0_SERIAL_PARAMETRS_REGISTER 0x2420 +#define ETHERNET0_HASH_TABLE_POINTER_REGISTER 0x2428 +#define ETHERNET0_FLOW_CONTROL_SOURCE_ADDRESS_LOW 0x2430 +#define ETHERNET0_FLOW_CONTROL_SOURCE_ADDRESS_HIGH 0x2438 +#define ETHERNET0_SDMA_CONFIGURATION_REGISTER 0x2440 +#define ETHERNET0_SDMA_COMMAND_REGISTER 0x2448 +#define ETHERNET0_INTERRUPT_CAUSE_REGISTER 0x2450 +#define ETHERNET0_INTERRUPT_MASK_REGISTER 0x2458 +#define ETHERNET0_FIRST_RX_DESCRIPTOR_POINTER0 0x2480 +#define ETHERNET0_FIRST_RX_DESCRIPTOR_POINTER1 0x2484 +#define ETHERNET0_FIRST_RX_DESCRIPTOR_POINTER2 0x2488 +#define ETHERNET0_FIRST_RX_DESCRIPTOR_POINTER3 0x248c +#define ETHERNET0_CURRENT_RX_DESCRIPTOR_POINTER0 0x24a0 +#define ETHERNET0_CURRENT_RX_DESCRIPTOR_POINTER1 0x24a4 +#define ETHERNET0_CURRENT_RX_DESCRIPTOR_POINTER2 0x24a8 +#define ETHERNET0_CURRENT_RX_DESCRIPTOR_POINTER3 0x24ac +#define ETHERNET0_CURRENT_TX_DESCRIPTOR_POINTER0 0x24e0 +#define ETHERNET0_CURRENT_TX_DESCRIPTOR_POINTER1 0x24e4 +#define ETHERNET0_MIB_COUNTER_BASE 0x2500 + +/* Ethernet 1 */ + +#define ETHERNET1_PORT_CONFIGURATION_REGISTER 0x2800 +#define ETHERNET1_PORT_CONFIGURATION_EXTEND_REGISTER 0x2808 +#define ETHERNET1_PORT_COMMAND_REGISTER 0x2810 +#define ETHERNET1_PORT_STATUS_REGISTER 0x2818 +#define ETHERNET1_SERIAL_PARAMETRS_REGISTER 0x2820 +#define ETHERNET1_HASH_TABLE_POINTER_REGISTER 0x2828 +#define ETHERNET1_FLOW_CONTROL_SOURCE_ADDRESS_LOW 0x2830 +#define ETHERNET1_FLOW_CONTROL_SOURCE_ADDRESS_HIGH 0x2838 +#define ETHERNET1_SDMA_CONFIGURATION_REGISTER 0x2840 +#define ETHERNET1_SDMA_COMMAND_REGISTER 0x2848 +#define ETHERNET1_INTERRUPT_CAUSE_REGISTER 0x2850 +#define ETHERNET1_INTERRUPT_MASK_REGISTER 0x2858 +#define ETHERNET1_FIRST_RX_DESCRIPTOR_POINTER0 0x2880 +#define ETHERNET1_FIRST_RX_DESCRIPTOR_POINTER1 0x2884 +#define ETHERNET1_FIRST_RX_DESCRIPTOR_POINTER2 0x2888 +#define ETHERNET1_FIRST_RX_DESCRIPTOR_POINTER3 0x288c +#define ETHERNET1_CURRENT_RX_DESCRIPTOR_POINTER0 0x28a0 +#define ETHERNET1_CURRENT_RX_DESCRIPTOR_POINTER1 0x28a4 +#define ETHERNET1_CURRENT_RX_DESCRIPTOR_POINTER2 0x28a8 +#define ETHERNET1_CURRENT_RX_DESCRIPTOR_POINTER3 0x28ac +#define ETHERNET1_CURRENT_TX_DESCRIPTOR_POINTER0 0x28e0 +#define ETHERNET1_CURRENT_TX_DESCRIPTOR_POINTER1 0x28e4 +#define ETHERNET1_MIB_COUNTER_BASE 0x2900 + +/* Ethernet 2 */ + +#define ETHERNET2_PORT_CONFIGURATION_REGISTER 0x2c00 +#define ETHERNET2_PORT_CONFIGURATION_EXTEND_REGISTER 0x2c08 +#define ETHERNET2_PORT_COMMAND_REGISTER 0x2c10 +#define ETHERNET2_PORT_STATUS_REGISTER 0x2c18 +#define ETHERNET2_SERIAL_PARAMETRS_REGISTER 0x2c20 +#define ETHERNET2_HASH_TABLE_POINTER_REGISTER 0x2c28 +#define ETHERNET2_FLOW_CONTROL_SOURCE_ADDRESS_LOW 0x2c30 +#define ETHERNET2_FLOW_CONTROL_SOURCE_ADDRESS_HIGH 0x2c38 +#define ETHERNET2_SDMA_CONFIGURATION_REGISTER 0x2c40 +#define ETHERNET2_SDMA_COMMAND_REGISTER 0x2c48 +#define ETHERNET2_INTERRUPT_CAUSE_REGISTER 0x2c50 +#define ETHERNET2_INTERRUPT_MASK_REGISTER 0x2c58 +#define ETHERNET2_FIRST_RX_DESCRIPTOR_POINTER0 0x2c80 +#define ETHERNET2_FIRST_RX_DESCRIPTOR_POINTER1 0x2c84 +#define ETHERNET2_FIRST_RX_DESCRIPTOR_POINTER2 0x2c88 +#define ETHERNET2_FIRST_RX_DESCRIPTOR_POINTER3 0x2c8c +#define ETHERNET2_CURRENT_RX_DESCRIPTOR_POINTER0 0x2ca0 +#define ETHERNET2_CURRENT_RX_DESCRIPTOR_POINTER1 0x2ca4 +#define ETHERNET2_CURRENT_RX_DESCRIPTOR_POINTER2 0x2ca8 +#define ETHERNET2_CURRENT_RX_DESCRIPTOR_POINTER3 0x2cac +#define ETHERNET2_CURRENT_TX_DESCRIPTOR_POINTER0 0x2ce0 +#define ETHERNET2_CURRENT_TX_DESCRIPTOR_POINTER1 0x2ce4 +#define ETHERNET2_MIB_COUNTER_BASE 0x2d00 + +/****************************************/ +/* SDMA Registers */ +/****************************************/ + +#define SDMA_GROUP_CONFIGURATION_REGISTER 0xb1f0 +#define CHANNEL0_CONFIGURATION_REGISTER 0x4000 +#define CHANNEL0_COMMAND_REGISTER 0x4008 +#define CHANNEL0_RX_CMD_STATUS 0x4800 +#define CHANNEL0_RX_PACKET_AND_BUFFER_SIZES 0x4804 +#define CHANNEL0_RX_BUFFER_POINTER 0x4808 +#define CHANNEL0_RX_NEXT_POINTER 0x480c +#define CHANNEL0_CURRENT_RX_DESCRIPTOR_POINTER 0x4810 +#define CHANNEL0_TX_CMD_STATUS 0x4C00 +#define CHANNEL0_TX_PACKET_SIZE 0x4C04 +#define CHANNEL0_TX_BUFFER_POINTER 0x4C08 +#define CHANNEL0_TX_NEXT_POINTER 0x4C0c +#define CHANNEL0_CURRENT_TX_DESCRIPTOR_POINTER 0x4c10 +#define CHANNEL0_FIRST_TX_DESCRIPTOR_POINTER 0x4c14 +#define CHANNEL1_CONFIGURATION_REGISTER 0x6000 +#define CHANNEL1_COMMAND_REGISTER 0x6008 +#define CHANNEL1_RX_CMD_STATUS 0x6800 +#define CHANNEL1_RX_PACKET_AND_BUFFER_SIZES 0x6804 +#define CHANNEL1_RX_BUFFER_POINTER 0x6808 +#define CHANNEL1_RX_NEXT_POINTER 0x680c +#define CHANNEL1_CURRENT_RX_DESCRIPTOR_POINTER 0x6810 +#define CHANNEL1_TX_CMD_STATUS 0x6C00 +#define CHANNEL1_TX_PACKET_SIZE 0x6C04 +#define CHANNEL1_TX_BUFFER_POINTER 0x6C08 +#define CHANNEL1_TX_NEXT_POINTER 0x6C0c +#define CHANNEL1_CURRENT_RX_DESCRIPTOR_POINTER 0x6810 +#define CHANNEL1_CURRENT_TX_DESCRIPTOR_POINTER 0x6c10 +#define CHANNEL1_FIRST_TX_DESCRIPTOR_POINTER 0x6c14 + +/* SDMA Interrupt */ + +#define SDMA_CAUSE 0xb820 +#define SDMA_MASK 0xb8a0 + + +/****************************************/ +/* Baude Rate Generators Registers */ +/****************************************/ + +/* BRG 0 */ + +#define BRG0_CONFIGURATION_REGISTER 0xb200 +#define BRG0_BAUDE_TUNING_REGISTER 0xb204 + +/* BRG 1 */ + +#define BRG1_CONFIGURATION_REGISTER 0xb208 +#define BRG1_BAUDE_TUNING_REGISTER 0xb20c + +/* BRG 2 */ + +#define BRG2_CONFIGURATION_REGISTER 0xb210 +#define BRG2_BAUDE_TUNING_REGISTER 0xb214 + +/* BRG Interrupts */ + +#define BRG_CAUSE_REGISTER 0xb834 +#define BRG_MASK_REGISTER 0xb8b4 + +/* MISC */ + +#define MAIN_ROUTING_REGISTER 0xb400 +#define RECEIVE_CLOCK_ROUTING_REGISTER 0xb404 +#define TRANSMIT_CLOCK_ROUTING_REGISTER 0xb408 +#define COMM_UNIT_ARBITER_CONFIGURATION_REGISTER 0xb40c +#define WATCHDOG_CONFIGURATION_REGISTER 0xb410 +#define WATCHDOG_VALUE_REGISTER 0xb414 + + +/****************************************/ +/* Flex TDM Registers */ +/****************************************/ + +/* FTDM Port */ + +#define FLEXTDM_TRANSMIT_READ_POINTER 0xa800 +#define FLEXTDM_RECEIVE_READ_POINTER 0xa804 +#define FLEXTDM_CONFIGURATION_REGISTER 0xa808 +#define FLEXTDM_AUX_CHANNELA_TX_REGISTER 0xa80c +#define FLEXTDM_AUX_CHANNELA_RX_REGISTER 0xa810 +#define FLEXTDM_AUX_CHANNELB_TX_REGISTER 0xa814 +#define FLEXTDM_AUX_CHANNELB_RX_REGISTER 0xa818 + +/* FTDM Interrupts */ + +#define FTDM_CAUSE_REGISTER 0xb830 +#define FTDM_MASK_REGISTER 0xb8b0 + + +/****************************************/ +/* GPP Interface Registers */ +/****************************************/ + +#define GPP_IO_CONTROL 0xf100 +#define GPP_LEVEL_CONTROL 0xf110 +#define GPP_VALUE 0xf104 +#define GPP_INTERRUPT_CAUSE 0xf108 +#define GPP_INTERRUPT_MASK 0xf10c + +#define MPP_CONTROL0 0xf000 +#define MPP_CONTROL1 0xf004 +#define MPP_CONTROL2 0xf008 +#define MPP_CONTROL3 0xf00c +#define DEBUG_PORT_MULTIPLEX 0xf014 +#define SERIAL_PORT_MULTIPLEX 0xf010 + +/****************************************/ +/* I2C Registers */ +/****************************************/ + +#define I2C_SLAVE_ADDRESS 0xc000 +#define I2C_EXTENDED_SLAVE_ADDRESS 0xc040 +#define I2C_DATA 0xc004 +#define I2C_CONTROL 0xc008 +#define I2C_STATUS_BAUDE_RATE 0xc00C +#define I2C_SOFT_RESET 0xc01c + +/****************************************/ +/* MPSC Registers */ +/****************************************/ + +/* MPSC0 */ + +#define MPSC0_MAIN_CONFIGURATION_LOW 0x8000 +#define MPSC0_MAIN_CONFIGURATION_HIGH 0x8004 +#define MPSC0_PROTOCOL_CONFIGURATION 0x8008 +#define CHANNEL0_REGISTER1 0x800c +#define CHANNEL0_REGISTER2 0x8010 +#define CHANNEL0_REGISTER3 0x8014 +#define CHANNEL0_REGISTER4 0x8018 +#define CHANNEL0_REGISTER5 0x801c +#define CHANNEL0_REGISTER6 0x8020 +#define CHANNEL0_REGISTER7 0x8024 +#define CHANNEL0_REGISTER8 0x8028 +#define CHANNEL0_REGISTER9 0x802c +#define CHANNEL0_REGISTER10 0x8030 +#define CHANNEL0_REGISTER11 0x8034 + +/* MPSC1 */ + +#define MPSC1_MAIN_CONFIGURATION_LOW 0x9000 +#define MPSC1_MAIN_CONFIGURATION_HIGH 0x9004 +#define MPSC1_PROTOCOL_CONFIGURATION 0x9008 +#define CHANNEL1_REGISTER1 0x900c +#define CHANNEL1_REGISTER2 0x9010 +#define CHANNEL1_REGISTER3 0x9014 +#define CHANNEL1_REGISTER4 0x9018 +#define CHANNEL1_REGISTER5 0x901c +#define CHANNEL1_REGISTER6 0x9020 +#define CHANNEL1_REGISTER7 0x9024 +#define CHANNEL1_REGISTER8 0x9028 +#define CHANNEL1_REGISTER9 0x902c +#define CHANNEL1_REGISTER10 0x9030 +#define CHANNEL1_REGISTER11 0x9034 + +/* MPSCs Interupts */ + +#define MPSC0_CAUSE 0xb804 +#define MPSC0_MASK 0xb884 +#define MPSC1_CAUSE 0xb80c +#define MPSC1_MASK 0xb88c + +#endif /* __INCgt64240rh */ diff -Nru a/arch/mips/momentum/ocelot_g/gt64240_dep.h b/arch/mips/momentum/ocelot_g/gt64240_dep.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/momentum/ocelot_g/gt64240_dep.h Tue Jul 1 18:44:40 2003 @@ -0,0 +1,57 @@ +/*********************************************************************** + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * arch/mips/gt64240/gt64240-dep.h + * Board-dependent definitions for GT-64120 chip. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + *********************************************************************** + */ + +#ifndef _ASM_GT64240_DEP_H +#define _ASM_GT64240_DEP_H + +#include /* for KSEG1ADDR() */ +#include /* for cpu_to_le32() */ + +/* + * PCI address allocation + */ +#if 0 +#define GT_PCI_MEM_BASE (0x22000000) +#define GT_PCI_MEM_SIZE GT_DEF_PCI0_MEM0_SIZE +#define GT_PCI_IO_BASE (0x20000000) +#define GT_PCI_IO_SIZE GT_DEF_PCI0_IO_SIZE +#endif + +extern unsigned long gt64240_base; + +#define GT64240_BASE (gt64240_base) + +/* + * Because of an error/peculiarity in the Galileo chip, we need to swap the + * bytes when running bigendian. + */ + +#define GT_WRITE(ofs, data) \ + *(volatile u32 *)(GT64240_BASE+(ofs)) = cpu_to_le32(data) +#define GT_READ(ofs, data) \ + *(data) = le32_to_cpu(*(volatile u32 *)(GT64240_BASE+(ofs))) +#define GT_READ_DATA(ofs) \ + le32_to_cpu(*(volatile u32 *)(GT64240_BASE+(ofs))) + +#define GT_WRITE_16(ofs, data) \ + *(volatile u16 *)(GT64240_BASE+(ofs)) = cpu_to_le16(data) +#define GT_READ_16(ofs, data) \ + *(data) = le16_to_cpu(*(volatile u16 *)(GT64240_BASE+(ofs))) + +#define GT_WRITE_8(ofs, data) \ + *(volatile u8 *)(GT64240_BASE+(ofs)) = data +#define GT_READ_8(ofs, data) \ + *(data) = *(volatile u8 *)(GT64240_BASE+(ofs)) + +#endif /* _ASM_GT64120_MOMENCO_OCELOT_GT64120_DEP_H */ diff -Nru a/arch/mips/momentum/ocelot_g/int-handler.S b/arch/mips/momentum/ocelot_g/int-handler.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/momentum/ocelot_g/int-handler.S Tue Jul 1 18:44:39 2003 @@ -0,0 +1,133 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * First-level interrupt dispatcher for ocelot board. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#define __ASSEMBLY__ +#include +#include +#include +#include +#include +#include + +/* + * first level interrupt dispatcher for ocelot board - + * We check for the timer first, then check PCI ints A and D. + * Then check for serial IRQ and fall through. + */ + .align 5 + NESTED(ocelot_handle_int, PT_SIZE, sp) + SAVE_ALL + CLI + .set at + mfc0 t0, CP0_CAUSE + mfc0 t2, CP0_STATUS + + and t0, t2 + + andi t1, t0, STATUSF_IP2 /* int0 hardware line */ + bnez t1, ll_pri_enet_irq + andi t1, t0, STATUSF_IP3 /* int1 hardware line */ + bnez t1, ll_sec_enet_irq + andi t1, t0, STATUSF_IP4 /* int2 hardware line */ + bnez t1, ll_uart_irq + andi t1, t0, STATUSF_IP5 /* int3 hardware line */ + bnez t1, ll_cpci_irq + andi t1, t0, STATUSF_IP6 /* int4 hardware line */ + bnez t1, ll_galileo_p0_irq + andi t1, t0, STATUSF_IP7 /* cpu timer */ + bnez t1, ll_cputimer_irq + + /* now look at the extended interrupts */ + mfc0 t0, CP0_CAUSE + cfc0 t1, CP0_S1_INTCONTROL + + /* shift the mask 8 bits left to line up the bits */ + sll t2, t1, 8 + + and t0, t2 + srl t0, t0, 16 + + andi t1, t0, STATUSF_IP8 /* int6 hardware line */ + bnez t1, ll_galileo_p1_irq + andi t1, t0, STATUSF_IP9 /* int7 hardware line */ + bnez t1, ll_pmc_irq + andi t1, t0, STATUSF_IP10 /* int8 hardware line */ + bnez t1, ll_cpci_abcd_irq + andi t1, t0, STATUSF_IP11 /* int9 hardware line */ + bnez t1, ll_testpoint_irq + + .set reorder + + /* wrong alarm or masked ... */ + j spurious_interrupt + nop + END(ocelot_handle_int) + + .align 5 +ll_pri_enet_irq: + li a0, 2 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_sec_enet_irq: + li a0, 3 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_uart_irq: + li a0, 4 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_cpci_irq: + li a0, 5 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_galileo_p0_irq: + li a0, 6 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_cputimer_irq: + li a0, 7 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_galileo_p1_irq: + li a0, 8 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_pmc_irq: + li a0, 9 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_cpci_abcd_irq: + li a0, 10 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_testpoint_irq: + li a0, 11 + move a1, sp + jal do_IRQ + j ret_from_irq diff -Nru a/arch/mips/momentum/ocelot_g/irq.c b/arch/mips/momentum/ocelot_g/irq.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/momentum/ocelot_g/irq.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2000 RidgeRun, Inc. + * Author: RidgeRun, Inc. + * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com + * + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.org) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static spinlock_t rm7000_irq_lock = SPIN_LOCK_UNLOCKED; + +/* Function for careful CP0 interrupt mask access */ +static inline void modify_cp0_intmask(unsigned clr_mask_in, unsigned set_mask_in) +{ + unsigned long status; + unsigned clr_mask; + unsigned set_mask; + + /* do the low 8 bits first */ + clr_mask = 0xff & clr_mask_in; + set_mask = 0xff & set_mask_in; + status = read_c0_status(); + status &= ~((clr_mask & 0xFF) << 8); + status |= (set_mask & 0xFF) << 8; + write_c0_status(status); + + /* do the high 8 bits */ + clr_mask = 0xff & (clr_mask_in >> 8); + set_mask = 0xff & (set_mask_in >> 8); + status = read_c0_intcontrol(); + status &= ~((clr_mask & 0xFF) << 8); + status |= (set_mask & 0xFF) << 8; + write_c0_intrcontrol(status); +} + +static inline void mask_irq(unsigned int irq) +{ + modify_cp0_intmask(irq, 0); +} + +static inline void unmask_irq(unsigned int irq) +{ + modify_cp0_intmask(0, irq); +} + +static void enable_cp7000_irq(unsigned int irq) +{ + unsigned long flags; + + spin_lock_irqsave(&rm7000_irq_lock, flags); + unmask_irq(1 << irq); + spin_unlock_irqrestore(&rm7000_irq_lock, flags); +} + +static unsigned int startup_cp7000_irq(unsigned int irq) +{ + enable_cp7000_irq(irq); + + return 0; /* never anything pending */ +} + +static void disable_cp7000_irq(unsigned int irq) +{ + unsigned long flags; + + spin_lock_irqsave(&rm7000_irq_lock, flags); + mask_irq(1 << irq); + spin_unlock_irqrestore(&rm7000_irq_lock, flags); +} + +#define shutdown_cp7000_irq disable_cp7000_irq + +static void mask_and_ack_cp7000_irq(unsigned int irq) +{ + mask_irq(1 << irq); +} + +static void end_cp7000_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + unmask_irq(1 << irq); +} + +static struct hw_interrupt_type cp7000_hpcdma_irq_type = { + "CP7000", + startup_cp7000_irq, + shutdown_cp7000_irq, + enable_cp7000_irq, + disable_cp7000_irq, + mask_and_ack_cp7000_irq, + end_cp7000_irq, + NULL +}; + + +extern asmlinkage void ocelot_handle_int(void); +extern void gt64240_irq_init(void); + +void __init init_IRQ(void) +{ + int i; + + /* + * Clear all of the interrupts while we change the able around a bit. + * int-handler is not on bootstrap + */ + clear_c0_status(ST0_IM | ST0_BEV); + local_irq_disable(); + + /* Sets the first-level interrupt dispatcher. */ + set_except_vector(0, ocelot_handle_int); + init_generic_irq(); + + for (i = 0; i <= 15; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = 1; + irq_desc[i].handler = &cp7000_hpcdma_irq_type; + } + + gt64240_irq_init(); + +#ifdef CONFIG_KGDB + printk("start kgdb ...\n"); + set_debug_traps(); + breakpoint(); /* you may move this line to whereever you want :-) */ +#endif +#ifdef CONFIG_GDB_CONSOLE + register_gdb_console(); +#endif +} diff -Nru a/arch/mips/momentum/ocelot_g/ocelot_pld.h b/arch/mips/momentum/ocelot_g/ocelot_pld.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/momentum/ocelot_g/ocelot_pld.h Tue Jul 1 18:44:40 2003 @@ -0,0 +1,30 @@ +/* + * Ocelot Board Register Definitions + * + * (C) 2001 Red Hat, Inc. + * + * GPL'd + */ +#ifndef __MOMENCO_OCELOT_PLD_H__ +#define __MOMENCO_OCELOT_PLD_H__ + +#define OCELOT_CS0_ADDR (0xfc000000) + +#define OCELOT_REG_BOARDREV (0) +#define OCELOT_REG_PLD1_ID (1) +#define OCELOT_REG_PLD2_ID (2) +#define OCELOT_REG_RESET_STATUS (3) +#define OCELOT_REG_BOARD_STATUS (4) +#define OCELOT_REG_CPCI_ID (5) +#define OCELOT_REG_I2C_CTRL (8) +#define OCELOT_REG_EEPROM_MODE (9) +#define OCELOT_REG_INTMASK (10) +#define OCELOT_REG_INTSTATUS (11) +#define OCELOT_REG_INTSET (12) +#define OCELOT_REG_INTCLR (13) + +#define OCELOT_PLD_WRITE(x, y) writeb(x, OCELOT_CS0_ADDR + OCELOT_REG_##y) +#define OCELOT_PLD_READ(x) readb(OCELOT_CS0_ADDR + OCELOT_REG_##x) + + +#endif /* __MOMENCO_OCELOT_PLD_H__ */ diff -Nru a/arch/mips/momentum/ocelot_g/pci-irq.c b/arch/mips/momentum/ocelot_g/pci-irq.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/momentum/ocelot_g/pci-irq.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,74 @@ +/* + * Copyright 2002 Momentum Computer Inc. + * Author: Matthew Dharm + * + * Based on work for the Linux port to the Ocelot board, which is + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * arch/mips/momentum/ocelot_g/pci.c + * Board-specific PCI routines for gt64240 controller. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include +#include +#include +#include + + +void __devinit gt64240_board_pcibios_fixup_bus(struct pci_bus *bus) +{ + struct pci_bus *current_bus = bus; + struct pci_dev *devices; + struct list_head *devices_link; + u16 cmd; + + /* loop over all known devices on this bus */ + list_for_each(devices_link, &(current_bus->devices)) { + + devices = pci_dev_b(devices_link); + if (devices == NULL) + continue; + + if ((current_bus->number == 0) && + PCI_SLOT(devices->devfn) == 1) { + /* Intel 82543 Gigabit MAC */ + devices->irq = 2; /* irq_nr is 2 for INT0 */ + } else if ((current_bus->number == 0) && + PCI_SLOT(devices->devfn) == 2) { + /* Intel 82543 Gigabit MAC */ + devices->irq = 3; /* irq_nr is 3 for INT1 */ + } else if ((current_bus->number == 1) && + PCI_SLOT(devices->devfn) == 3) { + /* Intel 21555 bridge */ + devices->irq = 5; /* irq_nr is 8 for INT6 */ + } else if ((current_bus->number == 1) && + PCI_SLOT(devices->devfn) == 4) { + /* PMC Slot */ + devices->irq = 9; /* irq_nr is 9 for INT7 */ + } else { + /* We don't have assign interrupts for other devices. */ + devices->irq = 0xff; + } + + /* Assign an interrupt number for the device */ + bus->ops->write(current_bus, devices, + PCI_INTERRUPT_LINE, 1, devices->irq); + + /* enable master for everything but the GT-64240 */ + if (((current_bus->number != 0) && (current_bus->number != 1)) + || (PCI_SLOT(devices->devfn) != 0)) { + bus->ops->read(current_bus, devices, + PCI_COMMAND, 2, &cmd); + cmd |= PCI_COMMAND_MASTER; + bus->ops->write(current_bus, devices, + PCI_COMMAND, 2, cmd); + } + } +} diff -Nru a/arch/mips/momentum/ocelot_g/prom.c b/arch/mips/momentum/ocelot_g/prom.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/momentum/ocelot_g/prom.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,100 @@ +/* + * Copyright 2002 Momentum Computer Inc. + * Author: Matthew Dharm + * + * Based on Ocelot Linux port, which is + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include +#include +#include + +#include +#include + +#include "gt64240.h" +#include "ocelot_pld.h" + +struct callvectors { + int (*open) (char*, int, int); + int (*close) (int); + int (*read) (int, void*, int); + int (*write) (int, void*, int); + off_t (*lseek) (int, off_t, int); + int (*printf) (const char*, ...); + void (*cacheflush) (void); + char* (*gets) (char*); +}; + +struct callvectors* debug_vectors; +char arcs_cmdline[CL_SIZE]; + +extern unsigned long gt64240_base; +extern unsigned long bus_clock; + +#ifdef CONFIG_GALILLEO_GT64240_ETH +extern unsigned char prom_mac_addr_base[6]; +#endif + +const char *get_system_type(void) +{ + return "Momentum Ocelot"; +} + +/* [jsun@junsun.net] PMON passes arguments in C main() style */ +void __init prom_init(int argc, char **arg, char** env, struct callvectors *cv) +{ + int i; + uint32_t tmp; + + /* save the PROM vectors for debugging use */ + debug_vectors = cv; + + /* arg[0] is "g", the rest is boot parameters */ + arcs_cmdline[0] = '\0'; + for (i = 1; i < argc; i++) { + if (strlen(arcs_cmdline) + strlen(arg[i] + 1) + >= sizeof(arcs_cmdline)) + break; + strcat(arcs_cmdline, arg[i]); + strcat(arcs_cmdline, " "); + } + + mips_machgroup = MACH_GROUP_MOMENCO; + mips_machtype = MACH_MOMENCO_OCELOT_G; + +#ifdef CONFIG_GALILLEO_GT64240_ETH + /* get the base MAC address for on-board ethernet ports */ + memcpy(prom_mac_addr_base, (void*)0xfc807cf2, 6); +#endif + + while (*env) { + if (strncmp("gtbase", *env, strlen("gtbase")) == 0) { + gt64240_base = simple_strtol(*env + strlen("gtbase="), + NULL, 16); + } + if (strncmp("busclock", *env, strlen("busclock")) == 0) { + bus_clock = simple_strtol(*env + strlen("busclock="), + NULL, 10); + } + *env++; + } + + debug_vectors->printf("Booting Linux kernel...\n"); +} + +void __init prom_free_prom_memory(void) +{ +} + +void __init prom_fixup_mem_map(unsigned long start, unsigned long end) +{ +} diff -Nru a/arch/mips/momentum/ocelot_g/reset.c b/arch/mips/momentum/ocelot_g/reset.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/momentum/ocelot_g/reset.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,47 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * Copyright (C) 1997, 2001 Ralf Baechle + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + */ +#include +#include +#include +#include +#include +#include +#include +#include + +void momenco_ocelot_restart(char *command) +{ + void *nvram = ioremap_nocache(0x2c807000, 0x1000); + + if (!nvram) { + printk(KERN_NOTICE "ioremap of reset register failed\n"); + return; + } + writeb(0x84, nvram + 0xff7); /* Ask the NVRAM/RTC/watchdog chip to + assert reset in 1/16 second */ + mdelay(10+(1000/16)); + iounmap(nvram); + printk(KERN_NOTICE "Watchdog reset failed\n"); +} + +void momenco_ocelot_halt(void) +{ + printk(KERN_NOTICE "\n** You can safely turn off the power\n"); + while (1) + __asm__(".set\tmips3\n\t" + "wait\n\t" + ".set\tmips0"); +} + +void momenco_ocelot_power_off(void) +{ + momenco_ocelot_halt(); +} diff -Nru a/arch/mips/momentum/ocelot_g/setup.c b/arch/mips/momentum/ocelot_g/setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/momentum/ocelot_g/setup.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,265 @@ +/* + * setup.c + * + * BRIEF MODULE DESCRIPTION + * Momentum Computer Ocelot-G (CP7000G) - board dependent boot routines + * + * Copyright (C) 1996, 1997, 2001 Ralf Baechle + * Copyright (C) 2000 RidgeRun, Inc. + * Copyright (C) 2001 Red Hat, Inc. + * Copyright (C) 2002 Momentum Computer + * + * Author: Matthew Dharm, Momentum Computer + * mdharm@momenco.com + * + * Author: RidgeRun, Inc. + * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com + * + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "gt64240.h" +#include "ocelot_pld.h" + +extern struct rtc_ops no_rtc_ops; + +#ifdef CONFIG_GALILLEO_GT64240_ETH +extern unsigned char prom_mac_addr_base[6]; +#endif + +unsigned long gt64240_base; + +/* These functions are used for rebooting or halting the machine*/ +extern void momenco_ocelot_restart(char *command); +extern void momenco_ocelot_halt(void); +extern void momenco_ocelot_power_off(void); + +extern void gt64240_time_init(void); +extern void momenco_ocelot_irq_setup(void); + +static char reset_reason; + +#define ENTRYLO(x) ((pte_val(pfn_pte((x) >> PAGE_SHIFT, PAGE_KERNEL_UNCACHED)) >> 6)|1) + +static void __init setup_l3cache(unsigned long size); + +/* setup code for a handoff from a version 2 PMON 2000 PROM */ +void PMON_v2_setup(void) +{ + /* A wired TLB entry for the GT64240 and the serial port. The + GT64240 is going to be hit on every IRQ anyway - there's + absolutely no point in letting it be a random TLB entry, as + it'll just cause needless churning of the TLB. And we use + the other half for the serial port, which is just a PITA + otherwise :) + + Device Physical Virtual + GT64240 Internal Regs 0xf4000000 0xe0000000 + UARTs (CS2) 0xfd000000 0xe0001000 + */ + add_wired_entry(ENTRYLO(0xf4000000), ENTRYLO(0xf4010000), 0xf4000000, PM_64K); + add_wired_entry(ENTRYLO(0xfd000000), ENTRYLO(0xfd001000), 0xfd000000, PM_4K); + + /* Also a temporary entry to let us talk to the Ocelot PLD and NVRAM + in the CS[012] region. We can't use ioremap() yet. The NVRAM + is a ST M48T37Y, which includes NVRAM, RTC, and Watchdog functions. + + Ocelot PLD (CS0) 0xfc000000 0xe0020000 + NVRAM (CS1) 0xfc800000 0xe0030000 + */ + add_temporary_entry(ENTRYLO(0xfc000000), ENTRYLO(0xfc010000), 0xfc000000, PM_64K); + add_temporary_entry(ENTRYLO(0xfc800000), ENTRYLO(0xfc810000), 0xfc800000, PM_64K); + + gt64240_base = 0xf4000000; +} + +void __init momenco_ocelot_g_setup(void) +{ + void (*l3func)(unsigned long)=KSEG1ADDR(&setup_l3cache); + unsigned int tmpword; + + board_time_init = gt64240_time_init; + + _machine_restart = momenco_ocelot_restart; + _machine_halt = momenco_ocelot_halt; + _machine_power_off = momenco_ocelot_power_off; + + /* + * initrd_start = (ulong)ocelot_initrd_start; + * initrd_end = (ulong)ocelot_initrd_start + (ulong)ocelot_initrd_size; + * initrd_below_start_ok = 1; + */ + rtc_ops = &no_rtc_ops; + + /* do handoff reconfiguration */ + PMON_v2_setup(); + +#ifdef CONFIG_GALILLEO_GT64240_ETH + /* get the mac addr */ + memcpy(prom_mac_addr_base, (void*)0xfc807cf2, 6); +#endif + + /* Turn off the Bit-Error LED */ + OCELOT_PLD_WRITE(0x80, INTCLR); + + tmpword = OCELOT_PLD_READ(BOARDREV); + if (tmpword < 26) + printk("Momenco Ocelot-G: Board Assembly Rev. %c\n", 'A'+tmpword); + else + printk("Momenco Ocelot-G: Board Assembly Revision #0x%x\n", tmpword); + + tmpword = OCELOT_PLD_READ(PLD1_ID); + printk("PLD 1 ID: %d.%d\n", tmpword>>4, tmpword&15); + tmpword = OCELOT_PLD_READ(PLD2_ID); + printk("PLD 2 ID: %d.%d\n", tmpword>>4, tmpword&15); + tmpword = OCELOT_PLD_READ(RESET_STATUS); + printk("Reset reason: 0x%x\n", tmpword); + reset_reason = tmpword; + OCELOT_PLD_WRITE(0xff, RESET_STATUS); + + tmpword = OCELOT_PLD_READ(BOARD_STATUS); + printk("Board Status register: 0x%02x\n", tmpword); + printk(" - User jumper: %s\n", (tmpword & 0x80)?"installed":"absent"); + printk(" - Boot flash write jumper: %s\n", (tmpword&0x40)?"installed":"absent"); + printk(" - Tulip PHY %s connected\n", (tmpword&0x10)?"is":"not"); + printk(" - L3 Cache size: %d MiB\n", (1<<((tmpword&12) >> 2))&~1); + printk(" - SDRAM size: %d MiB\n", 1<<(6+(tmpword&3))); + + if (tmpword&12) + l3func((1<<(((tmpword&12) >> 2)+20))); + + switch(tmpword &3) { + case 3: + /* 512MiB -- two banks of 256MiB */ + add_memory_region( 0x0<<20, 0x100<<20, BOOT_MEM_RAM); +/* + add_memory_region(0x100<<20, 0x100<<20, BOOT_MEM_RAM); +*/ + break; + case 2: + /* 256MiB -- two banks of 128MiB */ + add_memory_region( 0x0<<20, 0x80<<20, BOOT_MEM_RAM); + add_memory_region(0x80<<20, 0x80<<20, BOOT_MEM_RAM); + break; + case 1: + /* 128MiB -- 64MiB per bank */ + add_memory_region( 0x0<<20, 0x40<<20, BOOT_MEM_RAM); + add_memory_region(0x40<<20, 0x40<<20, BOOT_MEM_RAM); + break; + case 0: + /* 64MiB */ + add_memory_region( 0x0<<20, 0x40<<20, BOOT_MEM_RAM); + break; + } + + /* FIXME: Fix up the DiskOnChip mapping */ + GT_WRITE(0x468, 0xfef73); +} + +extern int rm7k_tcache_enabled; +/* + * This runs in KSEG1. See the verbiage in rm7k.c::probe_scache() + */ +#define Page_Invalidate_T 0x16 +static void __init setup_l3cache(unsigned long size) +{ + int register i; + unsigned long tmp; + + printk("Enabling L3 cache..."); + + /* Enable the L3 cache in the GT64120A's CPU Configuration register */ + GT_READ(0, &tmp); + GT_WRITE(0, tmp | (1<<14)); + + /* Enable the L3 cache in the CPU */ + set_c0_config(1<<12 /* CONF_TE */); + + /* Clear the cache */ + write_c0_taglo(0); + write_c0_taghi(0); + + for (i=0; i < size; i+= 4096) { + __asm__ __volatile__ ( + ".set noreorder\n\t" + ".set mips3\n\t" + "cache %1, (%0)\n\t" + ".set mips0\n\t" + ".set reorder" + : + : "r" (KSEG0ADDR(i)), + "i" (Page_Invalidate_T)); + } + + /* Let the RM7000 MM code know that the tertiary cache is enabled */ + rm7k_tcache_enabled = 1; + + printk("Done\n"); +} + + +/* This needs to be one of the first initcalls, because no I/O port access + can work before this */ + +static int io_base_ioremap(void) +{ + /* we're mapping PCI accesses from 0xc0000000 to 0xf0000000 */ + void *io_remap_range = ioremap(0xc0000000, 0x30000000); + + if (!io_remap_range) { + panic("Could not ioremap I/O port range"); + } + printk("io_remap_range set at 0x%08x\n", (uint32_t)io_remap_range); + set_io_port_base(io_remap_range - 0xc0000000); + + return 0; +} + +module_init(io_base_ioremap); diff -Nru a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/Makefile Tue Jul 1 18:44:39 2003 @@ -0,0 +1,36 @@ +# +# Makefile for the PCI specific kernel interface routines under Linux. +# +# This is all organized on a per system base which is horribly wrong and +# really wants a cleanup. You have been warned. +# + +obj-$(CONFIG_NEW_PCI) += pci.o +obj-$(CONFIG_PCI_AUTO) += pci-auto.o +obj-$(CONFIG_DDB5074) += pci-ddb5074.o ops-ddb5074.o +obj-$(CONFIG_DDB5476) += pci-ddb5476.o ops-ddb5476.o +obj-$(CONFIG_DDB5477) += pci-ddb5477.o ops-ddb5477.o +obj-$(CONFIG_HP_LASERJET) += pci-hplj.o +obj-$(CONFIG_ITE_BOARD_GEN) += ops-it8172.o +obj-$(CONFIG_LASAT) += pci-lasat.o +obj-$(CONFIG_MIPS_BOARDS_GEN) += pci-mips.o +obj-$(CONFIG_MIPS_COBALT) += pci-cobalt.o +obj-$(CONFIG_MIPS_EV64120) += ops-ev64120.o +obj-$(CONFIG_MIPS_EV96100) += fixup-ev96100.o ops-ev96100.o +obj-$(CONFIG_MIPS_ITE8172) += fixup-ite8172g.o +obj-$(CONFIG_MIPS_IVR) += fixup-ivr.o +obj-$(CONFIG_MIPS_PB1500) += fixups-au1000.o ops-au1000.o +obj-$(CONFIG_MOMENCO_OCELOT) += fixups-ocelot.o ops-ocelot.o +obj-$(CONFIG_NEC_EAGLE) += fixup-eagle.o ops-vrc4173.o +obj-$(CONFIG_SGI_IP27) += pci-ip27.o +obj-$(CONFIG_SGI_IP32) += pci-ip32.o +obj-$(CONFIG_SIBYTE_SB1250) += pci-sb1250.o +obj-$(CONFIG_SNI_RM200_PCI) += pci-sni.o +obj-$(CONFIG_TANBAC_TB0226) += fixup-tb0226.o +obj-$(CONFIG_TANBAC_TB0229) += fixup-tb0229.o +obj-$(CONFIG_TOSHIBA_JMR3927) += fixup-jmr3927.o ops-jmr3927.o +#obj-$(CONFIG_MOMENCO_OCELOT_C) += pci-ocelot-c.o +obj-$(CONFIG_MOMENCO_OCELOT_G) += pci-ocelot-g.o +obj-$(CONFIG_VICTOR_MPC30X) += fixup-capcella.o +obj-$(CONFIG_VR41XX_COMMON) += pci-vr41xx.o +obj-$(CONFIG_ZAO_CAPCELLA) += fixup-victor-mpc30x.o diff -Nru a/arch/mips/pci/common.c b/arch/mips/pci/common.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/common.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,69 @@ +void __init pcibios_fixup_bus(struct pci_bus *b) +{ + Dprintk("pcibios_fixup_bus()\n"); +} + +static int pcibios_enable_resources(struct pci_dev *dev, int mask) +{ + u16 cmd, old_cmd; + int idx; + struct resource *r; + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + old_cmd = cmd; + for (idx = 0; idx < 6; idx++) { + /* Only set up the requested stuff */ + if (!(mask & (1 << idx))) + continue; + + r = &dev->resource[idx]; + if (!r->start && r->end) { + printk(KERN_ERR + "PCI: Device %s not available because of resource collisions\n", + dev->slot_name); + return -EINVAL; + } + if (r->flags & IORESOURCE_IO) + cmd |= PCI_COMMAND_IO; + if (r->flags & IORESOURCE_MEM) + cmd |= PCI_COMMAND_MEMORY; + } + if (dev->resource[PCI_ROM_RESOURCE].start) + cmd |= PCI_COMMAND_MEMORY; + if (cmd != old_cmd) { + printk("PCI: Enabling device %s (%04x -> %04x)\n", + dev->slot_name, old_cmd, cmd); + pci_write_config_word(dev, PCI_COMMAND, cmd); + } + return 0; +} + +int pcibios_enable_device(struct pci_dev *dev, int mask) +{ + int err; + + if ((err = pcibios_enable_resources(dev, mask)) < 0) + return err; + + return 0; +} + +void __init pcibios_align_resource(void *data, struct resource *res, + unsigned long size, unsigned long align) +{ + panic("Uhhoh called pcibios_align_resource"); +} + +unsigned __init int pcibios_assign_all_busses(void) +{ + return 1; +} + +char *pcibios_setup(char *str) +{ + return str; +} + +struct pci_fixup pcibios_fixups[] = { + {0} +}; diff -Nru a/arch/mips/pci/fixup-au1000.c b/arch/mips/pci/fixup-au1000.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/fixup-au1000.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,124 @@ +/* + * BRIEF MODULE DESCRIPTION + * Board specific pci fixups. + * + * Copyright 2001-2003 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include + +#include +//#include +#ifdef CONFIG_MIPS_PB1000 +#include +#endif + +#undef DEBUG +#ifdef DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +static void fixup_resource(int r_num, struct pci_dev *dev); +#ifdef CONFIG_SOC_AU1500 +static unsigned long virt_io_addr; +#endif + +void __init pcibios_fixup_resources(struct pci_dev *dev) +{ + /* will need to fixup IO resources */ +} + +void __init pcibios_fixup(void) +{ +#ifdef CONFIG_SOC_AU1500 + int i; + struct pci_dev *dev; + + virt_io_addr = (unsigned long) ioremap(Au1500_PCI_IO_START, + Au1500_PCI_IO_END - + Au1500_PCI_IO_START + 1); + + if (!virt_io_addr) { + printk(KERN_ERR "Unable to ioremap pci space\n"); + return; + } + + set_io_port_base(virt_io_addr); +#endif + +#ifdef CONFIG_MIPS_PB1000 /* This is truly board specific */ + unsigned long pci_mem_start = (unsigned long) PCI_MEM_START; + + au_writel(0, PCI_BRIDGE_CONFIG); // set extend byte to 0 + au_writel(0, SDRAM_MBAR); // set mbar to 0 + au_writel(0x2, SDRAM_CMD); // enable memory accesses + au_sync_delay(1); + + // set extend byte to mbar of ext slot + au_writel(((pci_mem_start >> 24) & 0xff) | + (1 << 8 | 1 << 9 | 1 << 10 | 1 << 27), + PCI_BRIDGE_CONFIG); + DBG("Set bridge config to %x\n", au_readl(PCI_BRIDGE_CONFIG)); +#endif +} + +void __init pcibios_fixup_irqs(void) +{ +#ifdef CONFIG_SOC_AU1500 + unsigned int slot, func; + unsigned char pin; + struct pci_dev *dev = NULL; + + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + if (dev->bus->number != 0) + return; + + dev->irq = 0xff; + slot = PCI_SLOT(dev->devfn); + switch (slot) { + case 12: + case 13: + dev->irq = AU1000_PCI_INTA; + break; + + } + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); + DBG("slot %d irq %d\n", slot, dev->irq); + } +#endif +} +unsigned int pcibios_assign_all_busses(void) +{ + return 0; +} + +static void fixup_resource(int r_num, struct pci_dev *dev) +{ +} diff -Nru a/arch/mips/pci/fixup-capcella.c b/arch/mips/pci/fixup-capcella.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/fixup-capcella.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,72 @@ +/* + * FILE NAME + * arch/mips/vr41xx/zao-capcella/pci_fixup.c + * + * BRIEF MODULE DESCRIPTION + * The ZAO Networks Capcella specific PCI fixups. + * + * Copyright 2002 Yoichi Yuasa + * yuasa@hh.iij4u.or.jp + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include + +#include + +void __init pcibios_fixup_resources(struct pci_dev *dev) +{ +} + +void __init pcibios_fixup(void) +{ +} + +void __init pcibios_fixup_irqs(void) +{ + struct pci_dev *dev = NULL; + u8 slot, func, pin; + + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + slot = PCI_SLOT(dev->devfn); + func = PCI_FUNC(dev->devfn); + dev->irq = 0; + + switch (slot) { + case 11: + dev->irq = RTL8139_1_IRQ; + break; + case 12: + dev->irq = RTL8139_2_IRQ; + break; + case 14: + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); + switch (pin) { + case 1: + dev->irq = PC104PLUS_INTA_IRQ; + break; + case 2: + dev->irq = PC104PLUS_INTB_IRQ; + break; + case 3: + dev->irq = PC104PLUS_INTC_IRQ; + break; + case 4: + dev->irq = PC104PLUS_INTD_IRQ; + break; + } + break; + } + + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); + } +} + +unsigned int pcibios_assign_all_busses(void) +{ + return 0; +} diff -Nru a/arch/mips/pci/fixup-eagle.c b/arch/mips/pci/fixup-eagle.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/fixup-eagle.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,166 @@ +/* + * FILE NAME + * arch/mips/vr41xx/nec-eagle/pci_fixup.c + * + * BRIEF MODULE DESCRIPTION + * The NEC Eagle/Hawk Board specific PCI fixups. + * + * Author: Yoichi Yuasa + * yyuasa@mvista.com or source@mvista.com + * + * Copyright 2001,2002 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * Changes: + * MontaVista Software Inc. or + * - Moved mips_pci_channels[] to arch/mips/vr41xx/vr4122/eagle/setup.c. + * - Added support for NEC Hawk. + * + * Paul Mundt + * - Fix empty break statements. + * + * MontaVista Software Inc. or + * - New creation, NEC Eagle is supported. + */ +#include +#include + +#include +#include + +void __init pcibios_fixup_resources(struct pci_dev *dev) +{ +} + +void __init pcibios_fixup(void) +{ +} + +void __init pcibios_fixup_irqs(void) +{ + struct pci_dev *dev = NULL; + u8 slot, func, pin; + + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + slot = PCI_SLOT(dev->devfn); + func = PCI_FUNC(dev->devfn); + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); + dev->irq = 0; + + switch (slot) { + case 8: + switch (pin) { + case 1: + dev->irq = CP_INTA_IRQ; + break; + case 2: + dev->irq = CP_INTB_IRQ; + break; + case 3: + dev->irq = CP_INTC_IRQ; + break; + case 4: + dev->irq = CP_INTD_IRQ; + break; + } + break; + case 9: + switch (pin) { + case 1: + dev->irq = CP_INTD_IRQ; + break; + case 2: + dev->irq = CP_INTA_IRQ; + break; + case 3: + dev->irq = CP_INTB_IRQ; + break; + case 4: + dev->irq = CP_INTC_IRQ; + break; + } + break; + case 10: + switch (pin) { + case 1: + dev->irq = CP_INTC_IRQ; + break; + case 2: + dev->irq = CP_INTD_IRQ; + break; + case 3: + dev->irq = CP_INTA_IRQ; + break; + case 4: + dev->irq = CP_INTB_IRQ; + break; + } + break; + case 12: + dev->irq = VRC4173_PCMCIA1_IRQ; + break; + case 13: + dev->irq = VRC4173_PCMCIA2_IRQ; + break; + case 28: + dev->irq = LANINTA_IRQ; + break; + case 29: + switch (pin) { + case 1: + dev->irq = PCISLOT_IRQ; + break; + case 2: + dev->irq = CP_INTB_IRQ; + break; + case 3: + dev->irq = CP_INTC_IRQ; + break; + case 4: + dev->irq = CP_INTD_IRQ; + break; + } + break; + case 30: + switch (func) { + case 0: + dev->irq = VRC4173_CASCADE_IRQ; + break; + case 1: + dev->irq = VRC4173_AC97_IRQ; + break; + case 2: + dev->irq = VRC4173_USB_IRQ; + break; + } + break; + } + + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); + } +} + +unsigned int pcibios_assign_all_busses(void) +{ + return 0; +} diff -Nru a/arch/mips/pci/fixup-ite8172g.c b/arch/mips/pci/fixup-ite8172g.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/fixup-ite8172g.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,189 @@ +/* + * BRIEF MODULE DESCRIPTION + * Board specific pci fixups. + * + * Copyright 2000 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include + +#include +#include +#include + +void __init pcibios_fixup_resources(struct pci_dev *dev) +{ +} + +void __init pcibios_fixup(void) +{ +} + +void __init pcibios_fixup_irqs(void) +{ + unsigned int slot, func; + unsigned char pin; + struct pci_dev *dev = NULL; + + const int internal_func_irqs[7] = { + IT8172_AC97_IRQ, + IT8172_DMA_IRQ, + IT8172_CDMA_IRQ, + IT8172_USB_IRQ, + IT8172_BRIDGE_MASTER_IRQ, + IT8172_IDE_IRQ, + IT8172_MC68K_IRQ + }; + + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + if (dev->bus->number != 0) + return; + + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); + slot = PCI_SLOT(dev->devfn); + func = PCI_FUNC(dev->devfn); + + switch (slot) { + case 0x01: + /* + * Internal device 1 is actually 7 different + * internal devices on the IT8172G (a multi- + * function device). + */ + if (func < 7) + dev->irq = internal_func_irqs[func]; + break; + case 0x10: + switch (pin) { + case 1: /* pin A */ + dev->irq = IT8172_PCI_INTA_IRQ; + break; + case 2: /* pin B */ + dev->irq = IT8172_PCI_INTB_IRQ; + break; + case 3: /* pin C */ + dev->irq = IT8172_PCI_INTC_IRQ; + break; + case 4: /* pin D */ + dev->irq = IT8172_PCI_INTD_IRQ; + break; + default: + dev->irq = 0xff; + break; + + } + break; + case 0x11: + switch (pin) { + case 1: /* pin A */ + dev->irq = IT8172_PCI_INTA_IRQ; + break; + case 2: /* pin B */ + dev->irq = IT8172_PCI_INTB_IRQ; + break; + case 3: /* pin C */ + dev->irq = IT8172_PCI_INTC_IRQ; + break; + case 4: /* pin D */ + dev->irq = IT8172_PCI_INTD_IRQ; + break; + default: + dev->irq = 0xff; + break; + + } + break; + case 0x12: + switch (pin) { + case 1: /* pin A */ + dev->irq = IT8172_PCI_INTB_IRQ; + break; + case 2: /* pin B */ + dev->irq = IT8172_PCI_INTC_IRQ; + break; + case 3: /* pin C */ + dev->irq = IT8172_PCI_INTD_IRQ; + break; + case 4: /* pin D */ + dev->irq = IT8172_PCI_INTA_IRQ; + break; + default: + dev->irq = 0xff; + break; + + } + break; + case 0x13: + switch (pin) { + case 1: /* pin A */ + dev->irq = IT8172_PCI_INTC_IRQ; + break; + case 2: /* pin B */ + dev->irq = IT8172_PCI_INTD_IRQ; + break; + case 3: /* pin C */ + dev->irq = IT8172_PCI_INTA_IRQ; + break; + case 4: /* pin D */ + dev->irq = IT8172_PCI_INTB_IRQ; + break; + default: + dev->irq = 0xff; + break; + + } + break; + case 0x14: + switch (pin) { + case 1: /* pin A */ + dev->irq = IT8172_PCI_INTD_IRQ; + break; + case 2: /* pin B */ + dev->irq = IT8172_PCI_INTA_IRQ; + break; + case 3: /* pin C */ + dev->irq = IT8172_PCI_INTB_IRQ; + break; + case 4: /* pin D */ + dev->irq = IT8172_PCI_INTC_IRQ; + break; + default: + dev->irq = 0xff; + break; + + } + break; + default: + continue; /* do nothing */ + } +#ifdef DEBUG + printk("irq fixup: slot %d, int line %d, int number %d\n", + slot, pin, dev->irq); +#endif + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); + } +} diff -Nru a/arch/mips/pci/fixup-ivr.c b/arch/mips/pci/fixup-ivr.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/fixup-ivr.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,153 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * Globespan IVR board-specific pci fixups. + * + * Copyright 2000 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include + +#include +#include +#include + +void __init pcibios_fixup_resources(struct pci_dev *dev) +{ +} + +void __init pcibios_fixup(void) +{ +} + +void __init pcibios_fixup_irqs(void) +{ + unsigned int slot, func; + unsigned char pin; + struct pci_dev *dev = NULL; + + const int internal_func_irqs[7] = { + IT8172_AC97_IRQ, + IT8172_DMA_IRQ, + IT8172_CDMA_IRQ, + IT8172_USB_IRQ, + IT8172_BRIDGE_MASTER_IRQ, + IT8172_IDE_IRQ, + IT8172_MC68K_IRQ + }; + + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + if (dev->bus->number != 0) + return; + + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); + slot = PCI_SLOT(dev->devfn); + func = PCI_FUNC(dev->devfn); + + switch (slot) { + case 0x01: + /* + * Internal device 1 is actually 7 different + * internal devices on the IT8172G (multi-function + * device). + */ + if (func < 7) + dev->irq = internal_func_irqs[func]; + break; + case 0x11: // Realtek RTL-8139 + switch (pin) { + case 0: /* pin A, hardware bug */ + case 1: /* pin A */ + dev->irq = IT8172_PCI_INTC_IRQ; + break; + case 2: /* pin B */ + dev->irq = IT8172_PCI_INTD_IRQ; + break; + case 3: /* pin C */ + dev->irq = IT8172_PCI_INTA_IRQ; + break; + case 4: /* pin D */ + dev->irq = IT8172_PCI_INTB_IRQ; + break; + default: + dev->irq = 0xff; + break; + + } + break; + case 0x12: // ivr slot + switch (pin) { + case 0: /* pin A, hardware bug */ + case 1: /* pin A */ + dev->irq = IT8172_PCI_INTB_IRQ; + break; + case 2: /* pin B */ + dev->irq = IT8172_PCI_INTB_IRQ; + break; + case 3: /* pin C */ + dev->irq = IT8172_PCI_INTC_IRQ; + break; + case 4: /* pin D */ + dev->irq = IT8172_PCI_INTD_IRQ; + break; + default: + dev->irq = 0xff; + break; + + } + break; + case 0x13: // expansion slot + switch (pin) { + case 0: /* pin A, hardware bug */ + case 1: /* pin A */ + dev->irq = IT8172_PCI_INTA_IRQ; + break; + case 2: /* pin B */ + dev->irq = IT8172_PCI_INTB_IRQ; + break; + case 3: /* pin C */ + dev->irq = IT8172_PCI_INTC_IRQ; + break; + case 4: /* pin D */ + dev->irq = IT8172_PCI_INTD_IRQ; + break; + default: + dev->irq = 0xff; + break; + + } + break; + default: + break; + } +#ifdef DEBUG + printk("irq fixup: slot %d, int line %d, int number %d\n", + slot, pin, dev->irq); +#endif + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); + } +} diff -Nru a/arch/mips/pci/fixup-jmr3927.c b/arch/mips/pci/fixup-jmr3927.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/fixup-jmr3927.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,138 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * Board specific pci fixups. + * + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include + +#include + +#undef DEBUG +#ifdef DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +void __init pcibios_fixup_resources(struct pci_dev *dev) +{ + /* will need to fixup IO resources */ +} + +void __init pcibios_fixup(void) +{ + /* nothing to do here */ +} + +int pci_get_irq(struct pci_dev *dev, int pin) +{ + unsigned char irq = pin; + + /* IRQ rotation (PICMG) */ + irq--; /* 0-3 */ + if (dev->bus->parent == NULL && + PCI_SLOT(dev->devfn) == TX3927_PCIC_IDSEL_AD_TO_SLOT(23)) { + /* PCI CardSlot (IDSEL=A23, DevNu=12) */ + /* PCIA => PCIC (IDSEL=A23) */ + /* NOTE: JMR3927 JP1 must be set to OPEN */ + irq = (irq + 2) % 4; + } else if (dev->bus->parent == NULL && + PCI_SLOT(dev->devfn) == + TX3927_PCIC_IDSEL_AD_TO_SLOT(22)) { + /* PCI CardSlot (IDSEL=A22, DevNu=11) */ + /* PCIA => PCIA (IDSEL=A22) */ + /* NOTE: JMR3927 JP1 must be set to OPEN */ + irq = (irq + 0) % 4; + } else { + /* PCI Backplane */ + irq = (irq + 3 + PCI_SLOT(dev->devfn)) % 4; +#if 0 /* ??? */ + for (bus = dev->bus; bus->parent != NULL; + bus = bus->parent) { + irq = (irq + 3 + PCI_SLOT(bus->self->devfn)) % 4; + } +#endif + } + irq++; /* 1-4 */ + + switch (irq) { + case 1: + irq = JMR3927_IRQ_IOC_PCIA; + break; + case 2: + // wrong for backplane irq = JMR3927_IRQ_IOC_PCIB; + irq = JMR3927_IRQ_IOC_PCID; + break; + case 3: + irq = JMR3927_IRQ_IOC_PCIC; + break; + case 4: + // wrong for backplane irq = JMR3927_IRQ_IOC_PCID; + irq = JMR3927_IRQ_IOC_PCIB; + break; + } + + /* Check OnBoard Ethernet (IDSEL=A24, DevNu=13) */ + if (dev->bus->parent == NULL && + PCI_SLOT(dev->devfn) == TX3927_PCIC_IDSEL_AD_TO_SLOT(24)) { + extern int jmr3927_ether1_irq; + /* check this irq line was reserved for ether1 */ + if (jmr3927_ether1_irq != JMR3927_IRQ_ETHER0) + irq = JMR3927_IRQ_ETHER0; + else + irq = 0; /* disable */ + } + return irq; +} + +void __init pcibios_fixup_irqs(void) +{ + unsigned char irq; + struct pci_dev *dev = NULL; + + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq); + if (irq == 0) + return; + + /* SMSC SLC90E66 IDE uses irq 14, 15 (default) */ + if (!(dev->vendor == PCI_VENDOR_ID_EFAR && + dev->device == PCI_DEVICE_ID_EFAR_SLC90E66_1)) { + irq = pci_get_irq(dev, irq); + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, + irq); + } + + pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); + printk(KERN_INFO "PCI: %02x:%02x IRQ %02x\n", + dev->bus->number, dev->devfn, irq); + dev->irq = irq; + } +} diff -Nru a/arch/mips/pci/fixup-ocelot.c b/arch/mips/pci/fixup-ocelot.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/fixup-ocelot.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,77 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * arch/mips/gt64120/momenco_ocelot/pci.c + * Board-specific PCI routines for gt64120 controller. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include +#include +#include +#include + + +void __devinit gt64120_board_pcibios_fixup_bus(struct pci_bus *bus) +{ + struct pci_bus *current_bus = bus; + struct pci_dev *devices; + struct list_head *devices_link; + u16 cmd; + + list_for_each(devices_link, &(current_bus->devices)) { + + devices = pci_dev_b(devices_link); + if (devices == NULL) + continue; + + if (PCI_SLOT(devices->devfn) == 1) { + /* + * Slot 1 is primary ether port, i82559 + * we double-check against that assumption + */ + if ((devices->vendor != 0x8086) || + (devices->device != 0x1209)) { + panic + ("gt64120_board_pcibios_fixup_bus: found " + "unexpected PCI device in slot 1."); + } + devices->irq = 2; /* irq_nr is 2 for INT0 */ + } else if (PCI_SLOT(devices->devfn) == 2) { + /* + * Slot 2 is secondary ether port, i21143 + * we double-check against that assumption + */ + if ((devices->vendor != 0x1011) || + (devices->device != 0x19)) { + panic("galileo_pcibios_fixup_bus: " + "found unexpected PCI device in slot 2."); + } + devices->irq = 3; /* irq_nr is 3 for INT1 */ + } else if (PCI_SLOT(devices->devfn) == 4) { + /* PMC Slot 1 */ + devices->irq = 8; /* irq_nr is 8 for INT6 */ + } else if (PCI_SLOT(devices->devfn) == 5) { + /* PMC Slot 1 */ + devices->irq = 9; /* irq_nr is 9 for INT7 */ + } else { + /* We don't have assign interrupts for other devices. */ + devices->irq = 0xff; + } + + /* Assign an interrupt number for the device */ + bus->ops->write_byte(devices, PCI_INTERRUPT_LINE, + devices->irq); + + /* enable master */ + bus->ops->read_word(devices, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_MASTER; + bus->ops->write_word(devices, PCI_COMMAND, cmd); + } +} diff -Nru a/arch/mips/pci/fixup-tb0226.c b/arch/mips/pci/fixup-tb0226.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/fixup-tb0226.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,91 @@ +/* + * FILE NAME + * arch/mips/vr41xx/tanbac-tb0226/pci_fixup.c + * + * BRIEF MODULE DESCRIPTION + * The TANBAC TB0226 specific PCI fixups. + * + * Copyright 2002,2003 Yoichi Yuasa + * yuasa@hh.iij4u.or.jp + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include + +#include + +void __init pcibios_fixup_resources(struct pci_dev *dev) +{ +} + +void __init pcibios_fixup(void) +{ +} + +void __init pcibios_fixup_irqs(void) +{ + struct pci_dev *dev = NULL; + u8 slot, pin; + + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + slot = PCI_SLOT(dev->devfn); + dev->irq = 0; + + switch (slot) { + case 12: + vr41xx_set_irq_trigger(GD82559_1_PIN, + TRIGGER_LEVEL, + SIGNAL_THROUGH); + vr41xx_set_irq_level(GD82559_1_PIN, LEVEL_LOW); + dev->irq = GD82559_1_IRQ; + break; + case 13: + vr41xx_set_irq_trigger(GD82559_2_PIN, + TRIGGER_LEVEL, + SIGNAL_THROUGH); + vr41xx_set_irq_level(GD82559_2_PIN, LEVEL_LOW); + dev->irq = GD82559_2_IRQ; + break; + case 14: + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); + switch (pin) { + case 1: + vr41xx_set_irq_trigger(UPD720100_INTA_PIN, + TRIGGER_LEVEL, + SIGNAL_THROUGH); + vr41xx_set_irq_level(UPD720100_INTA_PIN, + LEVEL_LOW); + dev->irq = UPD720100_INTA_IRQ; + break; + case 2: + vr41xx_set_irq_trigger(UPD720100_INTB_PIN, + TRIGGER_LEVEL, + SIGNAL_THROUGH); + vr41xx_set_irq_level(UPD720100_INTB_PIN, + LEVEL_LOW); + dev->irq = UPD720100_INTB_IRQ; + break; + case 3: + vr41xx_set_irq_trigger(UPD720100_INTC_PIN, + TRIGGER_LEVEL, + SIGNAL_THROUGH); + vr41xx_set_irq_level(UPD720100_INTC_PIN, + LEVEL_LOW); + dev->irq = UPD720100_INTC_IRQ; + break; + } + break; + } + + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); + } +} + +unsigned int pcibios_assign_all_busses(void) +{ + return 0; +} diff -Nru a/arch/mips/pci/fixup-tb0229.c b/arch/mips/pci/fixup-tb0229.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/fixup-tb0229.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,77 @@ +/* + * FILE NAME + * arch/mips/vr41xx/tanbac-tb0229/pci_fixup.c + * + * BRIEF MODULE DESCRIPTION + * The TANBAC TB0229(VR4131DIMM) specific PCI fixups. + * + * Copyright 2003 Megasolution Inc. + * matsu@megasolution.jp + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include + +#include + +void __init pcibios_fixup_resources(struct pci_dev *dev) +{ +} + +void __init pcibios_fixup(void) +{ +} + +void __init pcibios_fixup_irqs(void) +{ +#ifdef CONFIG_TANBAC_TB0219 + struct pci_dev *dev = NULL; + u8 slot; + + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + slot = PCI_SLOT(dev->devfn); + dev->irq = 0; + + switch (slot) { + case 12: + vr41xx_set_irq_trigger(TB0219_PCI_SLOT1_PIN, + TRIGGER_LEVEL, + SIGNAL_THROUGH); + vr41xx_set_irq_level(TB0219_PCI_SLOT1_PIN, + LEVEL_LOW); + dev->irq = TB0219_PCI_SLOT1_IRQ; + break; + case 13: + vr41xx_set_irq_trigger(TB0219_PCI_SLOT2_PIN, + TRIGGER_LEVEL, + SIGNAL_THROUGH); + vr41xx_set_irq_level(TB0219_PCI_SLOT2_PIN, + LEVEL_LOW); + dev->irq = TB0219_PCI_SLOT2_IRQ; + break; + case 14: + vr41xx_set_irq_trigger(TB0219_PCI_SLOT3_PIN, + TRIGGER_LEVEL, + SIGNAL_THROUGH); + vr41xx_set_irq_level(TB0219_PCI_SLOT3_PIN, + LEVEL_LOW); + dev->irq = TB0219_PCI_SLOT3_IRQ; + break; + default: + break; + } + + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); + } +#endif +} + +unsigned int pcibios_assign_all_busses(void) +{ + return 0; +} diff -Nru a/arch/mips/pci/fixup-victor-mpc30x.c b/arch/mips/pci/fixup-victor-mpc30x.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/fixup-victor-mpc30x.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,72 @@ +/* + * FILE NAME + * arch/mips/vr41xx/victor-mpc30x/pci_fixup.c + * + * BRIEF MODULE DESCRIPTION + * The Victor MP-C303/304 specific PCI fixups. + * + * Copyright 2002 Yoichi Yuasa + * yuasa@hh.iij4u.or.jp + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include + +#include +#include + +void __init pcibios_fixup_resources(struct pci_dev *dev) +{ +} + +void __init pcibios_fixup(void) +{ +} + +void __init pcibios_fixup_irqs(void) +{ + struct pci_dev *dev = NULL; + u8 slot, func; + + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + slot = PCI_SLOT(dev->devfn); + func = PCI_FUNC(dev->devfn); + dev->irq = 0; + + switch (slot) { + case 12: /* NEC VRC4173 CARDU1 */ + dev->irq = VRC4173_PCMCIA1_IRQ; + break; + case 13: /* NEC VRC4173 CARDU2 */ + dev->irq = VRC4173_PCMCIA2_IRQ; + break; + case 29: /* mediaQ MQ-200 */ + dev->irq = MQ200_IRQ; + break; + case 30: + switch (func) { + case 0: /* NEC VRC4173 */ + dev->irq = VRC4173_CASCADE_IRQ; + break; + case 1: /* NEC VRC4173 AC97U */ + dev->irq = VRC4173_AC97_IRQ; + break; + case 2: /* NEC VRC4173 USBU */ + dev->irq = VRC4173_USB_IRQ; + break; + } + break; + } + + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); + } +} + +unsigned int pcibios_assign_all_busses(void) +{ + return 0; +} diff -Nru a/arch/mips/pci/fixups-ev96100.c b/arch/mips/pci/fixups-ev96100.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/fixups-ev96100.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,91 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * EV96100 Board specific pci fixups. + * + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include + +#include +#include + +extern unsigned short get_gt_devid(void); + +void __init pcibios_fixup_resources(struct pci_dev *dev) +{ +} + +void __init pcibios_fixup(void) +{ +} + +void __init pcibios_fixup_irqs(void) +{ + struct pci_dev *dev = NULL; + unsigned int slot; + u32 vendor; + unsigned short gt_devid = get_gt_devid(); + + /* + ** EV96100/A interrupt routing for pci bus 0 + ** + ** Note: EV96100A board with irq jumper set on 'VxWorks' + ** for EV96100 compatibility. + */ + + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + if (dev->bus->number != 0) + return; + + slot = PCI_SLOT(dev->devfn); + pci_read_config_dword(dev, PCI_SUBSYSTEM_VENDOR_ID, + &vendor); + +#ifdef DEBUG + printk("devfn %x, slot %d devid %x\n", + dev->devfn, slot, gt_devid); +#endif + + /* fixup irq line based on slot # */ + if (slot == 8) { + dev->irq = 5; + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, + dev->irq); + } else if (slot == 9) { + dev->irq = 2; + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, + dev->irq); + } + } +} +unsigned int pcibios_assign_all_busses(void) +{ + return 0; +} diff -Nru a/arch/mips/pci/ops-au1000.c b/arch/mips/pci/ops-au1000.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/ops-au1000.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,330 @@ +/* + * BRIEF MODULE DESCRIPTION + * Alchemy/AMD Au1x00 pci support. + * + * Copyright 2001,2002,2003 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * Support for all devices (greater than 16) added by David Gathright. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include + +#include +#ifdef CONFIG_MIPS_PB1000 +#include +#endif +#include + +#define PCI_ACCESS_READ 0 +#define PCI_ACCESS_WRITE 1 + +#undef DEBUG +#ifdef DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +/* TBD */ +static struct resource pci_io_resource = { + "pci IO space", + (u32) PCI_IO_START, + (u32) PCI_IO_END, + IORESOURCE_IO +}; + +static struct resource pci_mem_resource = { + "pci memory space", + (u32) PCI_MEM_START, + (u32) PCI_MEM_END, + IORESOURCE_MEM +}; + +extern struct pci_ops au1x_pci_ops; + +struct pci_channel mips_pci_channels[] = { + {&au1x_pci_ops, &pci_io_resource, &pci_mem_resource, + PCI_FIRST_DEVFN, PCI_LAST_DEVFN}, + {(struct pci_ops *) NULL, (struct resource *) NULL, + (struct resource *) NULL, (int) NULL, (int) NULL} +}; + + +#ifdef CONFIG_MIPS_PB1000 +/* + * "Bus 2" is really the first and only external slot on the pb1000. + * We'll call that bus 0, and limit the accesses to that single + * external slot only. The SDRAM is already initialized in setup.c. + */ +static int config_access(unsigned char access_type, struct pci_dev *dev, + unsigned char where, u32 * data) +{ + unsigned char bus = dev->bus->number; + unsigned char dev_fn = dev->devfn; + unsigned long config; + + if (((dev_fn >> 3) != 0) || (bus != 0)) { + *data = 0xffffffff; + return -1; + } + + config = PCI_CONFIG_BASE | (where & ~0x3); + + if (access_type == PCI_ACCESS_WRITE) { + au_writel(*data, config); + } else { + *data = au_readl(config); + } + au_sync_udelay(1); + + DBG("config_access: %d bus %d dev_fn %x at %x *data %x, conf %x\n", + access_type, bus, dev_fn, where, *data, config); + + DBG("bridge config reg: %x (%x)\n", au_readl(PCI_BRIDGE_CONFIG), + *data); + + if (au_readl(PCI_BRIDGE_CONFIG) & (1 << 16)) { + *data = 0xffffffff; + return -1; + } else { + return PCIBIOS_SUCCESSFUL; + } +} + +#else + +static int config_access(unsigned char access_type, struct pci_bus *bus, + unsigned int devfn, unsigned char where, + u32 * data) +{ +#ifdef CONFIG_SOC_AU1500 + unsigned int device = PCI_SLOT(devfn); + unsigned int function = PCI_FUNC(devfn); + unsigned long config, status; + unsigned long cfg_addr; + + if (device > 19) { + *data = 0xffffffff; + return -1; + } + + au_writel(((0x2000 << 16) | + (au_readl(Au1500_PCI_STATCMD) & 0xffff)), + Au1500_PCI_STATCMD); + //au_writel(au_readl(Au1500_PCI_CFG) & ~PCI_ERROR, Au1500_PCI_CFG); + au_sync_udelay(1); + + /* setup the config window */ + if (bus->number == 0) { + cfg_addr = (unsigned long) ioremap(Au1500_EXT_CFG | + ((1 << device) << 11), + 0x00100000); + } else { + cfg_addr = (unsigned long) ioremap(Au1500_EXT_CFG_TYPE1 | + (bus-> + number << 16) | (device + << + 11), + 0x00100000); + } + + if (!cfg_addr) + panic(KERN_ERR "PCI unable to ioremap cfg space\n"); + + /* setup the lower bits of the 36 bit address */ + config = cfg_addr | (function << 8) | (where & ~0x3); + +#if 0 + if (access_type == PCI_ACCESS_WRITE) { + printk("cfg write: "); + } else { + printk("cfg read: "); + } + printk("devfn %x, device %x func %x \n", devfn, device, function); + if (access_type == PCI_ACCESS_WRITE) { + printk("data %x\n", *data); + } +#endif + + if (access_type == PCI_ACCESS_WRITE) { + au_writel(*data, config); + } else { + *data = au_readl(config); + } + au_sync_udelay(2); + + + DBG("config_access: %d bus %d device %d at %x *data %x, conf %x\n", + access_type, bus->number, device, where, *data, config); + + /* unmap io space */ + iounmap((void *) cfg_addr); + + /* check master abort */ + status = au_readl(Au1500_PCI_STATCMD); +#if 0 + if (access_type == PCI_ACCESS_READ) { + printk("read data: %x\n", *data); + } +#endif + if (status & (1 << 29)) { + *data = 0xffffffff; + return -1; + } else if ((status >> 28) & 0xf) { + printk("PCI ERR detected: status %x\n", status); + *data = 0xffffffff; + return -1; + } else { + return PCIBIOS_SUCCESSFUL; + } +#endif +} +#endif + +static int read_config_byte(struct pci_bus *bus, unsigned int devfn, + int where, u8 * val) +{ + u32 data; + int ret; + + ret = config_access(PCI_ACCESS_READ, bus, devfn, where, &data); + if (where & 1) + data >>= 8; + if (where & 2) + data >>= 16; + *val = data & 0xff; + return ret; +} + + +static int read_config_word(struct pci_bus *bus, unsigned int devfn, + int where, u16 * val) +{ + u32 data; + int ret; + + ret = config_access(PCI_ACCESS_READ, bus, devfn, where, &data); + if (where & 2) + data >>= 16; + *val = data & 0xffff; + return ret; +} + +static int read_config_dword(struct pci_bus *bus, unsigned int devfn, + int where, u32 * val) +{ + int ret; + + ret = config_access(PCI_ACCESS_READ, bus, devfn, where, val); + return ret; +} + +static int +write_config_byte(struct pci_bus *bus, unsigned int devfn, int where, + u8 val) +{ + u32 data = 0; + + if (config_access(PCI_ACCESS_READ, bus, devfn, where, &data)) + return -1; + + data = (data & ~(0xff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + + if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data)) + return -1; + + return PCIBIOS_SUCCESSFUL; +} + +static int +write_config_word(struct pci_bus *bus, unsigned int devfn, int where, + u16 val) +{ + u32 data = 0; + + if (where & 1) + return PCIBIOS_BAD_REGISTER_NUMBER; + + if (config_access(PCI_ACCESS_READ, bus, devfn, where, &data)) + return -1; + + data = (data & ~(0xffff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + + if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data)) + return -1; + + + return PCIBIOS_SUCCESSFUL; +} + +static int +write_config_dword(struct pci_bus *bus, unsigned int devfn, int where, + u32 val) +{ + if (where & 3) + return PCIBIOS_BAD_REGISTER_NUMBER; + + if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &val)) + return -1; + + return PCIBIOS_SUCCESSFUL; +} + +static int config_read(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 * val) +{ + switch (size) { + case 1: + return read_config_byte(bus, devfn, where, (u8 *) val); + case 2: + return read_config_word(bus, devfn, where, (u16 *) val); + default: + return read_config_dword(bus, devfn, where, val); + } +} + +static int config_write(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) +{ + switch (size) { + case 1: + return write_config_byte(bus, devfn, where, (u8) val); + case 2: + return write_config_word(bus, devfn, where, (u16) val); + default: + return write_config_dword(bus, devfn, where, val); + } +} + + +struct pci_ops au1x_pci_ops = { + config_read, + config_write +}; diff -Nru a/arch/mips/pci/ops-ddb5074.c b/arch/mips/pci/ops-ddb5074.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/ops-ddb5074.c Tue Jul 1 18:44:39 2003 @@ -0,0 +1,335 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * arch/mips/ddb5xxx/ddb5476/pci_ops.c + * Define the pci_ops for DB5477. + * + * Much of the code is derived from the original DDB5074 port by + * Geert Uytterhoeven + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ +#include +#include +#include +#include + +#include +#include + +#include + +/* + * config_swap structure records what set of pdar/pmr are used + * to access pci config space. It also provides a place hold the + * original values for future restoring. + */ +struct pci_config_swap { + u32 pdar; + u32 pmr; + u32 config_base; + u32 config_size; + u32 pdar_backup; + u32 pmr_backup; +}; + +/* + * On DDB5476, we have one set of swap registers + */ +struct pci_config_swap ext_pci_swap = { + DDB_PCIW0, + DDB_PCIINIT0, + DDB_PCI_CONFIG_BASE, + DDB_PCI_CONFIG_SIZE +}; + +static int pci_config_workaround = 1; + +/* + * access config space + */ +static inline u32 ddb_access_config_base(struct pci_config_swap *swap, u32 bus, /* 0 means top level bus */ + u32 slot_num) +{ + u32 pci_addr = 0; + u32 pciinit_offset = 0; + u32 virt_addr = swap->config_base; + u32 option; + + if (pci_config_workaround) { + if (slot_num == 5) + slot_num = 14; + } else { + if (slot_num == 5) + return DDB_BASE + DDB_PCI_BASE; + } + + /* minimum pdar (window) size is 2MB */ + db_assert(swap->config_size >= (2 << 20)); + + db_assert(slot_num < (1 << 5)); + db_assert(bus < (1 << 8)); + + /* backup registers */ + swap->pdar_backup = ddb_in32(swap->pdar); + swap->pmr_backup = ddb_in32(swap->pmr); + + /* set the pdar (pci window) register */ + ddb_set_pdar(swap->pdar, swap->config_base, swap->config_size, 32, /* 32 bit wide */ + 0, /* not on local memory bus */ + 0); /* not visible from PCI bus (N/A) */ + + /* + * calcuate the absolute pci config addr; + * according to the spec, we start scanning from adr:11 (0x800) + */ + if (bus == 0) { + /* type 0 config */ + pci_addr = 0x00040000 << slot_num; + } else { + /* type 1 config */ + pci_addr = 0x00040000 << slot_num; + panic + ("ddb_access_config_base: we don't support type 1 config Yet"); + } + + /* + * if pci_addr is less than pci config window size, we set + * pciinit_offset to 0 and adjust the virt_address. + * Otherwise we will try to adjust pciinit_offset. + */ + if (pci_addr < swap->config_size) { + virt_addr = KSEG1ADDR(swap->config_base + pci_addr); + pciinit_offset = 0; + } else { + db_assert((pci_addr & (swap->config_size - 1)) == 0); + virt_addr = KSEG1ADDR(swap->config_base); + pciinit_offset = pci_addr; + } + + /* set the pmr register */ + option = DDB_PCI_ACCESS_32; + if (bus != 0) + option |= DDB_PCI_CFGTYPE1; + ddb_set_pmr(swap->pmr, DDB_PCICMD_CFG, pciinit_offset, option); + + return virt_addr; +} + +static inline void ddb_close_config_base(struct pci_config_swap *swap) +{ + ddb_out32(swap->pdar, swap->pdar_backup); + ddb_out32(swap->pmr, swap->pmr_backup); +} + +static int read_config_dword(struct pci_config_swap *swap, + struct pci_dev *dev, u32 where, u32 * val) +{ + u32 bus, slot_num, func_num; + u32 base; + + db_assert((where & 3) == 0); + db_assert(where < (1 << 8)); + + /* check if the bus is top-level */ + if (dev->bus->parent != NULL) { + bus = dev->bus->number; + db_assert(bus != 0); + } else { + bus = 0; + } + + slot_num = PCI_SLOT(dev->devfn); + func_num = PCI_FUNC(dev->devfn); + base = ddb_access_config_base(swap, bus, slot_num); + *val = *(volatile u32 *) (base + (func_num << 8) + where); + ddb_close_config_base(swap); + return PCIBIOS_SUCCESSFUL; +} + +static int read_config_word(struct pci_config_swap *swap, + struct pci_dev *dev, u32 where, u16 * val) +{ + int status; + u32 result; + + db_assert((where & 1) == 0); + + status = read_config_dword(swap, dev, where & ~3, &result); + if (where & 2) + result >>= 16; + *val = result & 0xffff; + return status; +} + +static int read_config_byte(struct pci_config_swap *swap, + struct pci_dev *dev, u32 where, u8 * val) +{ + int status; + u32 result; + + status = read_config_dword(swap, dev, where & ~3, &result); + if (where & 1) + result >>= 8; + if (where & 2) + result >>= 16; + *val = result & 0xff; + return status; +} + +static int write_config_dword(struct pci_config_swap *swap, + struct pci_dev *dev, u32 where, u32 val) +{ + u32 bus, slot_num, func_num; + u32 base; + + db_assert((where & 3) == 0); + db_assert(where < (1 << 8)); + + /* check if the bus is top-level */ + if (dev->bus->parent != NULL) { + bus = dev->bus->number; + db_assert(bus != 0); + } else { + bus = 0; + } + + slot_num = PCI_SLOT(dev->devfn); + func_num = PCI_FUNC(dev->devfn); + base = ddb_access_config_base(swap, bus, slot_num); + *(volatile u32 *) (base + (func_num << 8) + where) = val; + ddb_close_config_base(swap); + return PCIBIOS_SUCCESSFUL; +} + +static int write_config_word(struct pci_config_swap *swap, + struct pci_dev *dev, u32 where, u16 val) +{ + int status, shift = 0; + u32 result; + + db_assert((where & 1) == 0); + + status = read_config_dword(swap, dev, where & ~3, &result); + if (status != PCIBIOS_SUCCESSFUL) + return status; + + if (where & 2) + shift += 16; + result &= ~(0xffff << shift); + result |= val << shift; + return write_config_dword(swap, dev, where & ~3, result); +} + +static int write_config_byte(struct pci_config_swap *swap, + struct pci_dev *dev, u32 where, u8 val) +{ + int status, shift = 0; + u32 result; + + status = read_config_dword(swap, dev, where & ~3, &result); + if (status != PCIBIOS_SUCCESSFUL) + return status; + + if (where & 2) + shift += 16; + if (where & 1) + shift += 8; + result &= ~(0xff << shift); + result |= val << shift; + return write_config_dword(swap, dev, where & ~3, result); +} + +#define MAKE_PCI_OPS(prefix, rw, unitname, unittype, pciswap) \ +static int prefix##_##rw##_config_##unitname(struct pci_dev *dev, int where, unittype val) \ +{ \ + return rw##_config_##unitname(pciswap, \ + dev, \ + where, \ + val); \ +} + +MAKE_PCI_OPS(extpci, read, byte, u8 *, &ext_pci_swap) + MAKE_PCI_OPS(extpci, read, word, u16 *, &ext_pci_swap) + MAKE_PCI_OPS(extpci, read, dword, u32 *, &ext_pci_swap) + + MAKE_PCI_OPS(extpci, write, byte, u8, &ext_pci_swap) + MAKE_PCI_OPS(extpci, write, word, u16, &ext_pci_swap) + MAKE_PCI_OPS(extpci, write, dword, u32, &ext_pci_swap) + +struct pci_ops ddb5476_ext_pci_ops = { + extpci_read_config_byte, + extpci_read_config_word, + extpci_read_config_dword, + extpci_write_config_byte, + extpci_write_config_word, + extpci_write_config_dword +}; + + +#if defined(CONFIG_RUNTIME_DEBUG) +void jsun_scan_pci_bus(void) +{ + struct pci_bus bus; + struct pci_dev dev; + unsigned int devfn; + int j; + + pci_config_workaround = 0; + + bus.parent = NULL; /* we scan the top level only */ + dev.bus = &bus; + dev.sysdata = NULL; + + /* scan ext pci bus and io pci bus */ + for (j = 0; j < 1; j++) { + printk(KERN_INFO "scan ddb5476 external PCI bus:\n"); + bus.ops = &ddb5476_ext_pci_ops; + + for (devfn = 0; devfn < 0x100; devfn += 8) { + u32 temp; + u16 temp16; + u8 temp8; + int i; + + dev.devfn = devfn; + db_verify(pci_read_config_dword(&dev, 0, &temp), + == PCIBIOS_SUCCESSFUL); + if (temp == 0xffffffff) + continue; + + printk(KERN_INFO "slot %d: (addr %d) \n", + devfn / 8, 11 + devfn / 8); + + /* verify read word and byte */ + db_verify(pci_read_config_word(&dev, 2, &temp16), + == PCIBIOS_SUCCESSFUL); + db_assert(temp16 == (temp >> 16)); + db_verify(pci_read_config_byte(&dev, 3, &temp8), + == PCIBIOS_SUCCESSFUL); + db_assert(temp8 == (temp >> 24)); + db_verify(pci_read_config_byte(&dev, 1, &temp8), + == PCIBIOS_SUCCESSFUL); + db_assert(temp8 == ((temp >> 8) & 0xff)); + + for (i = 0; i < 16; i++) { + if ((i % 4) == 0) + printk(KERN_INFO); + db_verify(pci_read_config_dword + (&dev, i * 4, &temp), + == PCIBIOS_SUCCESSFUL); + printk("\t%08X", temp); + if ((i % 4) == 3) + printk("\n"); + } + } + } + + pci_config_workaround = 1; +} +#endif diff -Nru a/arch/mips/pci/ops-ddb5476.c b/arch/mips/pci/ops-ddb5476.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/ops-ddb5476.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,350 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * arch/mips/ddb5xxx/ddb5476/pci_ops.c + * Define the pci_ops for DB5477. + * + * Much of the code is derived from the original DDB5074 port by + * Geert Uytterhoeven + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ +#include +#include +#include +#include + +#include +#include + +#include + +/* + * config_swap structure records what set of pdar/pmr are used + * to access pci config space. It also provides a place hold the + * original values for future restoring. + */ +struct pci_config_swap { + u32 pdar; + u32 pmr; + u32 config_base; + u32 config_size; + u32 pdar_backup; + u32 pmr_backup; +}; + +/* + * On DDB5476, we have one set of swap registers + */ +struct pci_config_swap ext_pci_swap = { + DDB_PCIW0, + DDB_PCIINIT0, + DDB_PCI_CONFIG_BASE, + DDB_PCI_CONFIG_SIZE +}; + +static int pci_config_workaround = 1; + +/* + * access config space + */ +static inline u32 ddb_access_config_base(struct pci_config_swap *swap, u32 bus, /* 0 means top level bus */ + u32 slot_num) +{ + u32 pci_addr = 0; + u32 pciinit_offset = 0; + u32 virt_addr = swap->config_base; + u32 option; + + if (pci_config_workaround) { + /* [jsun] work around Vrc5476 controller itself, returnning + * slot 0 essentially makes vrc5476 invisible + */ + if (slot_num == 12) + slot_num = 0; + +#if 0 + /* BUG : skip P2P bridge for now */ + if (slot_num == 5) + slot_num = 0; +#endif + + } else { + /* now we have to be hornest, returning the true + * PCI config headers for vrc5476 + */ + if (slot_num == 12) { + swap->pdar_backup = ddb_in32(swap->pdar); + swap->pmr_backup = ddb_in32(swap->pmr); + return DDB_BASE + DDB_PCI_BASE; + } + } + + /* minimum pdar (window) size is 2MB */ + db_assert(swap->config_size >= (2 << 20)); + + db_assert(slot_num < (1 << 5)); + db_assert(bus < (1 << 8)); + + /* backup registers */ + swap->pdar_backup = ddb_in32(swap->pdar); + swap->pmr_backup = ddb_in32(swap->pmr); + + /* set the pdar (pci window) register */ + ddb_set_pdar(swap->pdar, swap->config_base, swap->config_size, 32, /* 32 bit wide */ + 0, /* not on local memory bus */ + 0); /* not visible from PCI bus (N/A) */ + + /* + * calcuate the absolute pci config addr; + * according to the spec, we start scanning from adr:11 (0x800) + */ + if (bus == 0) { + /* type 0 config */ + pci_addr = 0x800 << slot_num; + } else { + /* type 1 config */ + pci_addr = (bus << 16) | (slot_num << 11); + /* panic("ddb_access_config_base: we don't support type 1 config Yet"); */ + } + + /* + * if pci_addr is less than pci config window size, we set + * pciinit_offset to 0 and adjust the virt_address. + * Otherwise we will try to adjust pciinit_offset. + */ + if (pci_addr < swap->config_size) { + virt_addr = KSEG1ADDR(swap->config_base + pci_addr); + pciinit_offset = 0; + } else { + db_assert((pci_addr & (swap->config_size - 1)) == 0); + virt_addr = KSEG1ADDR(swap->config_base); + pciinit_offset = pci_addr; + } + + /* set the pmr register */ + option = DDB_PCI_ACCESS_32; + if (bus != 0) + option |= DDB_PCI_CFGTYPE1; + ddb_set_pmr(swap->pmr, DDB_PCICMD_CFG, pciinit_offset, option); + + return virt_addr; +} + +static inline void ddb_close_config_base(struct pci_config_swap *swap) +{ + ddb_out32(swap->pdar, swap->pdar_backup); + ddb_out32(swap->pmr, swap->pmr_backup); +} + +static int read_config_dword(struct pci_config_swap *swap, + struct pci_dev *dev, u32 where, u32 * val) +{ + u32 bus, slot_num, func_num; + u32 base; + + db_assert((where & 3) == 0); + db_assert(where < (1 << 8)); + + /* check if the bus is top-level */ + if (dev->bus->parent != NULL) { + bus = dev->bus->number; + db_assert(bus != 0); + } else { + bus = 0; + } + + slot_num = PCI_SLOT(dev->devfn); + func_num = PCI_FUNC(dev->devfn); + base = ddb_access_config_base(swap, bus, slot_num); + *val = *(volatile u32 *) (base + (func_num << 8) + where); + ddb_close_config_base(swap); + return PCIBIOS_SUCCESSFUL; +} + +static int read_config_word(struct pci_config_swap *swap, + struct pci_dev *dev, u32 where, u16 * val) +{ + int status; + u32 result; + + db_assert((where & 1) == 0); + + status = read_config_dword(swap, dev, where & ~3, &result); + if (where & 2) + result >>= 16; + *val = result & 0xffff; + return status; +} + +static int read_config_byte(struct pci_config_swap *swap, + struct pci_dev *dev, u32 where, u8 * val) +{ + int status; + u32 result; + + status = read_config_dword(swap, dev, where & ~3, &result); + if (where & 1) + result >>= 8; + if (where & 2) + result >>= 16; + *val = result & 0xff; + return status; +} + +static int write_config_dword(struct pci_config_swap *swap, + struct pci_dev *dev, u32 where, u32 val) +{ + u32 bus, slot_num, func_num; + u32 base; + + db_assert((where & 3) == 0); + db_assert(where < (1 << 8)); + + /* check if the bus is top-level */ + if (dev->bus->parent != NULL) { + bus = dev->bus->number; + db_assert(bus != 0); + } else { + bus = 0; + } + + slot_num = PCI_SLOT(dev->devfn); + func_num = PCI_FUNC(dev->devfn); + base = ddb_access_config_base(swap, bus, slot_num); + *(volatile u32 *) (base + (func_num << 8) + where) = val; + ddb_close_config_base(swap); + return PCIBIOS_SUCCESSFUL; +} + +static int write_config_word(struct pci_config_swap *swap, + struct pci_dev *dev, u32 where, u16 val) +{ + int status, shift = 0; + u32 result; + + db_assert((where & 1) == 0); + + status = read_config_dword(swap, dev, where & ~3, &result); + if (status != PCIBIOS_SUCCESSFUL) + return status; + + if (where & 2) + shift += 16; + result &= ~(0xffff << shift); + result |= val << shift; + return write_config_dword(swap, dev, where & ~3, result); +} + +static int write_config_byte(struct pci_config_swap *swap, + struct pci_dev *dev, u32 where, u8 val) +{ + int status, shift = 0; + u32 result; + + status = read_config_dword(swap, dev, where & ~3, &result); + if (status != PCIBIOS_SUCCESSFUL) + return status; + + if (where & 2) + shift += 16; + if (where & 1) + shift += 8; + result &= ~(0xff << shift); + result |= val << shift; + return write_config_dword(swap, dev, where & ~3, result); +} + +#define MAKE_PCI_OPS(prefix, rw, unitname, unittype, pciswap) \ +static int prefix##_##rw##_config_##unitname(struct pci_dev *dev, int where, unittype val) \ +{ \ + return rw##_config_##unitname(pciswap, \ + dev, \ + where, \ + val); \ +} + +MAKE_PCI_OPS(extpci, read, byte, u8 *, &ext_pci_swap) + MAKE_PCI_OPS(extpci, read, word, u16 *, &ext_pci_swap) + MAKE_PCI_OPS(extpci, read, dword, u32 *, &ext_pci_swap) + + MAKE_PCI_OPS(extpci, write, byte, u8, &ext_pci_swap) + MAKE_PCI_OPS(extpci, write, word, u16, &ext_pci_swap) + MAKE_PCI_OPS(extpci, write, dword, u32, &ext_pci_swap) + +struct pci_ops ddb5476_ext_pci_ops = { + extpci_read_config_byte, + extpci_read_config_word, + extpci_read_config_dword, + extpci_write_config_byte, + extpci_write_config_word, + extpci_write_config_dword +}; + + +#if defined(CONFIG_RUNTIME_DEBUG) +void jsun_scan_pci_bus(void) +{ + struct pci_bus bus; + struct pci_dev dev; + unsigned int devfn; + int j; + + pci_config_workaround = 0; + + bus.parent = NULL; /* we scan the top level only */ + dev.bus = &bus; + dev.sysdata = NULL; + + /* scan ext pci bus and io pci bus */ + for (j = 0; j < 1; j++) { + printk(KERN_INFO "scan ddb5476 external PCI bus:\n"); + bus.ops = &ddb5476_ext_pci_ops; + + for (devfn = 0; devfn < 0x100; devfn += 8) { + u32 temp; + u16 temp16; + u8 temp8; + int i; + + dev.devfn = devfn; + db_verify(pci_read_config_dword(&dev, 0, &temp), + == PCIBIOS_SUCCESSFUL); + if (temp == 0xffffffff) + continue; + + printk(KERN_INFO "slot %d: (addr %d) \n", + devfn / 8, 11 + devfn / 8); + + /* verify read word and byte */ + db_verify(pci_read_config_word(&dev, 2, &temp16), + == PCIBIOS_SUCCESSFUL); + db_assert(temp16 == (temp >> 16)); + db_verify(pci_read_config_byte(&dev, 3, &temp8), + == PCIBIOS_SUCCESSFUL); + db_assert(temp8 == (temp >> 24)); + db_verify(pci_read_config_byte(&dev, 1, &temp8), + == PCIBIOS_SUCCESSFUL); + db_assert(temp8 == ((temp >> 8) & 0xff)); + + for (i = 0; i < 16; i++) { + if ((i % 4) == 0) + printk(KERN_INFO); + db_verify(pci_read_config_dword + (&dev, i * 4, &temp), + == PCIBIOS_SUCCESSFUL); + printk("\t%08X", temp); + if ((i % 4) == 3) + printk("\n"); + } + } + } + + pci_config_workaround = 1; +} +#endif diff -Nru a/arch/mips/pci/ops-ddb5477.c b/arch/mips/pci/ops-ddb5477.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/ops-ddb5477.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,281 @@ +/*********************************************************************** + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * arch/mips/ddb5xxx/ddb5477/pci_ops.c + * Define the pci_ops for DB5477. + * + * Much of the code is derived from the original DDB5074 port by + * Geert Uytterhoeven + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + *********************************************************************** + */ + +/* + * DDB5477 has two PCI channels, external PCI and IOPIC (internal) + * Therefore we provide two sets of pci_ops. + */ +#include +#include +#include + +#include +#include + +#include + +/* + * config_swap structure records what set of pdar/pmr are used + * to access pci config space. It also provides a place hold the + * original values for future restoring. + */ +struct pci_config_swap { + u32 pdar; + u32 pmr; + u32 config_base; + u32 config_size; + u32 pdar_backup; + u32 pmr_backup; +}; + +/* + * On DDB5477, we have two sets of swap registers, for ext PCI and IOPCI. + */ +struct pci_config_swap ext_pci_swap = { + DDB_PCIW0, + DDB_PCIINIT00, + DDB_PCI0_CONFIG_BASE, + DDB_PCI0_CONFIG_SIZE +}; +struct pci_config_swap io_pci_swap = { + DDB_IOPCIW0, + DDB_PCIINIT01, + DDB_PCI1_CONFIG_BASE, + DDB_PCI1_CONFIG_SIZE +}; + + +/* + * access config space + */ +static inline u32 ddb_access_config_base(struct pci_config_swap *swap, u32 bus, /* 0 means top level bus */ + u32 slot_num) +{ + u32 pci_addr = 0; + u32 pciinit_offset = 0; + u32 virt_addr = swap->config_base; + u32 option; + + /* minimum pdar (window) size is 2MB */ + db_assert(swap->config_size >= (2 << 20)); + + db_assert(slot_num < (1 << 5)); + db_assert(bus < (1 << 8)); + + /* backup registers */ + swap->pdar_backup = ddb_in32(swap->pdar); + swap->pmr_backup = ddb_in32(swap->pmr); + + /* set the pdar (pci window) register */ + ddb_set_pdar(swap->pdar, swap->config_base, swap->config_size, 32, /* 32 bit wide */ + 0, /* not on local memory bus */ + 0); /* not visible from PCI bus (N/A) */ + + /* + * calcuate the absolute pci config addr; + * according to the spec, we start scanning from adr:11 (0x800) + */ + if (bus == 0) { + /* type 0 config */ + pci_addr = 0x800 << slot_num; + } else { + /* type 1 config */ + pci_addr = (bus << 16) | (slot_num << 11); + } + + /* + * if pci_addr is less than pci config window size, we set + * pciinit_offset to 0 and adjust the virt_address. + * Otherwise we will try to adjust pciinit_offset. + */ + if (pci_addr < swap->config_size) { + virt_addr = KSEG1ADDR(swap->config_base + pci_addr); + pciinit_offset = 0; + } else { + db_assert((pci_addr & (swap->config_size - 1)) == 0); + virt_addr = KSEG1ADDR(swap->config_base); + pciinit_offset = pci_addr; + } + + /* set the pmr register */ + option = DDB_PCI_ACCESS_32; + if (bus != 0) + option |= DDB_PCI_CFGTYPE1; + ddb_set_pmr(swap->pmr, DDB_PCICMD_CFG, pciinit_offset, option); + + return virt_addr; +} + +static inline void ddb_close_config_base(struct pci_config_swap *swap) +{ + ddb_out32(swap->pdar, swap->pdar_backup); + ddb_out32(swap->pmr, swap->pmr_backup); +} + +static int read_config_dword(struct pci_config_swap *swap, + struct pci_bus *bus, u32 where, u32 * val) +{ + u32 bus, slot_num, func_num; + u32 base; + + db_assert((where & 3) == 0); + db_assert(where < (1 << 8)); + + /* check if the bus is top-level */ + if (dev->bus->parent != NULL) { + bus = dev->bus->number; + db_assert(bus != 0); + } else { + bus = 0; + } + + slot_num = PCI_SLOT(dev->devfn); + func_num = PCI_FUNC(dev->devfn); + base = ddb_access_config_base(swap, bus, slot_num); + *val = *(volatile u32 *) (base + (func_num << 8) + where); + ddb_close_config_base(swap); + return PCIBIOS_SUCCESSFUL; +} + +static int read_config_word(struct pci_config_swap *swap, + struct pci_bus *bus, u32 where, u16 * val) +{ + int status; + u32 result; + + db_assert((where & 1) == 0); + + status = read_config_dword(swap, bus, where & ~3, &result); + if (where & 2) + result >>= 16; + *val = result & 0xffff; + return status; +} + +static int read_config_byte(struct pci_config_swap *swap, + struct pci_bus *bus, unsigned int devfn, + u8 * val) +{ + int status; + u32 result; + + status = read_config_dword(swap, bus, where & ~3, &result); + if (where & 1) + result >>= 8; + if (where & 2) + result >>= 16; + *val = result & 0xff; + + return status; +} + +static int write_config_dword(struct pci_config_swap *swap, + struct pci_bus *bus, unsigned int devfn, + u32 val) +{ + u32 busno, slot_num, func_num; + u32 base; + + db_assert((where & 3) == 0); + db_assert(where < (1 << 8)); + + /* check if the bus is top-level */ + if (bus->parent != NULL) { + busno = bus->number; + db_assert(busno != 0); + } else { + busno = 0; + } + + slot_num = PCI_SLOT(devfn); + func_num = PCI_FUNC(devfn); + base = ddb_access_config_base(swap, busno, slot_num); + *(volatile u32 *) (base + (func_num << 8) + where) = val; + ddb_close_config_base(swap); + return PCIBIOS_SUCCESSFUL; +} + +static int write_config_word(struct pci_config_swap *swap, + struct pci_bus *bus, unsigned int devfn, + int where, u16 val) +{ + int status, shift = 0; + u32 result; + + db_assert((where & 1) == 0); + + status = read_config_dword(swap, dev, where & ~3, &result); + if (status != PCIBIOS_SUCCESSFUL) + return status; + + if (where & 2) + shift += 16; + result &= ~(0xffff << shift); + result |= val << shift; + return write_config_dword(swap, dev, where & ~3, result); +} + +static int write_config_byte(struct pci_config_swap *swap, + struct pci_bus *bus, unsigned int devfn, + int where, u8 val) +{ + int status, shift = 0; + u32 result; + + status = read_config_dword(swap, dev, where & ~3, &result); + if (status != PCIBIOS_SUCCESSFUL) + return status; + + if (where & 2) + shift += 16; + if (where & 1) + shift += 8; + result &= ~(0xff << shift); + result |= val << shift; + return write_config_dword(swap, dev, where & ~3, result); +} + +/* + * Dump solution for now so I don't break hw I can't test on ... + */ +#define MAKE_PCI_OPS(prefix, rw, unitname, unittype, pciswap) \ +static int prefix##_##rw##_config(struct pci_bus *bus, int where, int size, unittype val) \ +{ \ + if (size == 1) \ + return rw##_config_byte(pciswap, bus, where, val); \ + else if (size == 2) \ + return rw##_config_word(pciswap, bus, where, val); \ + /* Size must be 4 */ \ + return rw##_config_dword(pciswap, bus, where, val); \ +} + +MAKE_PCI_OPS(extpci, read, &ext_pci_swap) + MAKE_PCI_OPS(extpci, write, &ext_pci_swap) + + MAKE_PCI_OPS(iopci, read, &io_pci_swap) + MAKE_PCI_OPS(iopci, write, &io_pci_swap) + +struct pci_ops ddb5477_ext_pci_ops = { + .read = extpci_read_config, + .write = extpci_write_config +}; + + +struct pci_ops ddb5477_io_pci_ops = { + .read = iopci_read_config, + .write = iopci_write_config +}; diff -Nru a/arch/mips/pci/ops-ev64120.c b/arch/mips/pci/ops-ev64120.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/ops-ev64120.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,1201 @@ +/* + * BRIEF MODULE DESCRIPTION + * Galileo Evaluation Boards PCI support. + * + * The general-purpose functions to read/write and configure the GT64120A's + * PCI registers (function names start with pci0 or pci1) are either direct + * copies of functions written by Galileo Technology, or are modifications + * of their functions to work with Linux 2.4 vs Linux 2.2. These functions + * are Copyright - Galileo Technology. + * + * Other functions are derived from other MIPS PCI implementations, or were + * written by RidgeRun, Inc, Copyright (C) 2000 RidgeRun, Inc. + * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#undef PCI_DEBUG + +#ifdef PCI_DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +#define SELF 0 + +/* + * These functions and structures provide the BIOS scan and mapping of the PCI + * devices. + */ + +#define MAX_PCI_DEVS 10 + +struct pci_device { + u32 slot; + u32 BARtype[6]; + u32 BARsize[6]; +}; + +static void __init scan_and_initialize_pci(void); +static u32 __init scan_pci_bus(struct pci_device *pci_devices); +static void __init allocate_pci_space(struct pci_device *pci_devices); + +static void __devinit galileo_pcibios_fixup_bus(struct pci_bus *bus); + +/* + * The functions that actually read and write to the controller. + * Copied from or modified from Galileo Technology code. + */ +static unsigned int pci0ReadConfigReg(int offset, struct pci_dev *device); +static void pci0WriteConfigReg(unsigned int offset, + struct pci_dev *device, unsigned int data); +static unsigned int pci1ReadConfigReg(int offset, struct pci_dev *device); +static void pci1WriteConfigReg(unsigned int offset, + struct pci_dev *device, unsigned int data); + +static void pci0MapIOspace(unsigned int pci0IoBase, + unsigned int pci0IoLength); +static void pci1MapIOspace(unsigned int pci1IoBase, + unsigned int pci1IoLength); +static void pci0MapMemory0space(unsigned int pci0Mem0Base, + unsigned int pci0Mem0Length); +static void pci1MapMemory0space(unsigned int pci1Mem0Base, + unsigned int pci1Mem0Length); +static void pci0MapMemory1space(unsigned int pci0Mem1Base, + unsigned int pci0Mem1Length); +static void pci1MapMemory1space(unsigned int pci1Mem1Base, + unsigned int pci1Mem1Length); +static unsigned int pci0GetIOspaceBase(void); +static unsigned int pci0GetIOspaceSize(void); +static unsigned int pci0GetMemory0Base(void); +static unsigned int pci0GetMemory0Size(void); +static unsigned int pci0GetMemory1Base(void); +static unsigned int pci0GetMemory1Size(void); +static unsigned int pci1GetIOspaceBase(void); +static unsigned int pci1GetIOspaceSize(void); +static unsigned int pci1GetMemory0Base(void); +static unsigned int pci1GetMemory0Size(void); +static unsigned int pci1GetMemory1Base(void); +static unsigned int pci1GetMemory1Size(void); + + +/* Functions to implement "pci ops" */ +static int galileo_pcibios_read_config_word(struct pci_dev *dev, + int offset, u16 * val); +static int galileo_pcibios_read_config_byte(struct pci_dev *dev, + int offset, u8 * val); +static int galileo_pcibios_read_config_dword(struct pci_dev *dev, + int offset, u32 * val); +static int galileo_pcibios_write_config_byte(struct pci_dev *dev, + int offset, u8 val); +static int galileo_pcibios_write_config_word(struct pci_dev *dev, + int offset, u16 val); +static int galileo_pcibios_write_config_dword(struct pci_dev *dev, + int offset, u32 val); +static void galileo_pcibios_set_master(struct pci_dev *dev); + +/* + * General-purpose PCI functions. + */ + +/* + * pci0MapIOspace - Maps PCI0 IO space for the master. + * Inputs: base and length of pci0Io + */ +static void pci0MapIOspace(unsigned int pci0IoBase, + unsigned int pci0IoLength) +{ + unsigned int pci0IoTop = + (unsigned int) (pci0IoBase + pci0IoLength); + + if (pci0IoLength == 0) + pci0IoTop++; + + pci0IoBase = (unsigned int) (pci0IoBase >> 21); + pci0IoTop = (unsigned int) (((pci0IoTop - 1) & 0x0fffffff) >> 21); + GT_WRITE(GT_PCI0IOLD_OFS, pci0IoBase); + GT_WRITE(GT_PCI0IOHD_OFS, pci0IoTop); +} + +/* + * pci1MapIOspace - Maps PCI1 IO space for the master. + * Inputs: base and length of pci1Io + */ + +static void pci1MapIOspace(unsigned int pci1IoBase, + unsigned int pci1IoLength) +{ + unsigned int pci1IoTop = + (unsigned int) (pci1IoBase + pci1IoLength); + + if (pci1IoLength == 0) + pci1IoTop++; + + pci1IoBase = (unsigned int) (pci1IoBase >> 21); + pci1IoTop = (unsigned int) (((pci1IoTop - 1) & 0x0fffffff) >> 21); + GT_WRITE(GT_PCI1IOLD_OFS, pci1IoBase); + GT_WRITE(GT_PCI1IOHD_OFS, pci1IoTop); +} + +/* + * pci0MapMemory0space - Maps PCI0 memory0 space for the master. + * Inputs: base and length of pci0Mem0 + */ + +static void pci0MapMemory0space(unsigned int pci0Mem0Base, + unsigned int pci0Mem0Length) +{ + unsigned int pci0Mem0Top = pci0Mem0Base + pci0Mem0Length; + + if (pci0Mem0Length == 0) + pci0Mem0Top++; + + pci0Mem0Base = pci0Mem0Base >> 21; + pci0Mem0Top = ((pci0Mem0Top - 1) & 0x0fffffff) >> 21; + GT_WRITE(GT_PCI0M0LD_OFS, pci0Mem0Base); + GT_WRITE(GT_PCI0M0HD_OFS, pci0Mem0Top); +} + +/* + * pci1MapMemory0space - Maps PCI1 memory0 space for the master. + * Inputs: base and length of pci1Mem0 + */ + +static void pci1MapMemory0space(unsigned int pci1Mem0Base, + unsigned int pci1Mem0Length) +{ + unsigned int pci1Mem0Top = pci1Mem0Base + pci1Mem0Length; + + if (pci1Mem0Length == 0) + pci1Mem0Top++; + + pci1Mem0Base = pci1Mem0Base >> 21; + pci1Mem0Top = ((pci1Mem0Top - 1) & 0x0fffffff) >> 21; + GT_WRITE(GT_PCI1M0LD_OFS, pci1Mem0Base); + GT_WRITE(GT_PCI1M0HD_OFS, pci1Mem0Top); +} + +/* + * pci0MapMemory1space - Maps PCI0 memory1 space for the master. + * Inputs: base and length of pci0Mem1 + */ + +static void pci0MapMemory1space(unsigned int pci0Mem1Base, + unsigned int pci0Mem1Length) +{ + unsigned int pci0Mem1Top = pci0Mem1Base + pci0Mem1Length; + + if (pci0Mem1Length == 0) + pci0Mem1Top++; + + pci0Mem1Base = pci0Mem1Base >> 21; + pci0Mem1Top = ((pci0Mem1Top - 1) & 0x0fffffff) >> 21; + GT_WRITE(GT_PCI0M1LD_OFS, pci0Mem1Base); + GT_WRITE(GT_PCI0M1HD_OFS, pci0Mem1Top); + +} + +/* + * pci1MapMemory1space - Maps PCI1 memory1 space for the master. + * Inputs: base and length of pci1Mem1 + */ + +static void pci1MapMemory1space(unsigned int pci1Mem1Base, + unsigned int pci1Mem1Length) +{ + unsigned int pci1Mem1Top = pci1Mem1Base + pci1Mem1Length; + + if (pci1Mem1Length == 0) + pci1Mem1Top++; + + pci1Mem1Base = pci1Mem1Base >> 21; + pci1Mem1Top = ((pci1Mem1Top - 1) & 0x0fffffff) >> 21; + GT_WRITE(GT_PCI1M1LD_OFS, pci1Mem1Base); + GT_WRITE(GT_PCI1M1HD_OFS, pci1Mem1Top); +} + +/* + * pci0GetIOspaceBase - Return PCI0 IO Base Address. + * Inputs: N/A + * Returns: PCI0 IO Base Address. + */ + +static unsigned int pci0GetIOspaceBase(void) +{ + unsigned int base; + GT_READ(GT_PCI0IOLD_OFS, &base); + base = base << 21; + return base; +} + +/* + * pci0GetIOspaceSize - Return PCI0 IO Bar Size. + * Inputs: N/A + * Returns: PCI0 IO Bar Size. + */ +static unsigned int pci0GetIOspaceSize(void) +{ + unsigned int top, base, size; + GT_READ(GT_PCI0IOLD_OFS, &base); + base = base << 21; + GT_READ(GT_PCI0IOHD_OFS, &top); + top = (top << 21); + size = ((top - base) & 0xfffffff); + size = size | 0x1fffff; + return (size + 1); +} + +/* + * pci0GetMemory0Base - Return PCI0 Memory 0 Base Address. + * Inputs: N/A + * Returns: PCI0 Memory 0 Base Address. + */ +static unsigned int pci0GetMemory0Base(void) +{ + unsigned int base; + GT_READ(GT_PCI0M0LD_OFS, &base); + base = base << 21; + return base; +} + +/* + * pci0GetMemory0Size - Return PCI0 Memory 0 Bar Size. + * Inputs: N/A + * Returns: PCI0 Memory 0 Bar Size. + */ +static unsigned int pci0GetMemory0Size(void) +{ + unsigned int top, base, size; + GT_READ(GT_PCI0M0LD_OFS, &base); + base = base << 21; + GT_READ(GT_PCI0M0HD_OFS, &top); + top = (top << 21); + size = ((top - base) & 0xfffffff); + size = size | 0x1fffff; + return (size + 1); +} + +/* + * pci0GetMemory1Base - Return PCI0 Memory 1 Base Address. + * Inputs: N/A + * Returns: PCI0 Memory 1 Base Address. + */ +static unsigned int pci0GetMemory1Base(void) +{ + unsigned int base; + GT_READ(GT_PCI0M1LD_OFS, &base); + base = base << 21; + return base; +} + +/* + * pci0GetMemory1Size - Return PCI0 Memory 1 Bar Size. + * Inputs: N/A + * Returns: PCI0 Memory 1 Bar Size. + */ + +static unsigned int pci0GetMemory1Size(void) +{ + unsigned int top, base, size; + GT_READ(GT_PCI0M1LD_OFS, &base); + base = base << 21; + GT_READ(GT_PCI0M1HD_OFS, &top); + top = (top << 21); + size = ((top - base) & 0xfffffff); + size = size | 0x1fffff; + return (size + 1); +} + +/* + * pci1GetIOspaceBase - Return PCI1 IO Base Address. + * Inputs: N/A + * Returns: PCI1 IO Base Address. + */ + +static unsigned int pci1GetIOspaceBase(void) +{ + unsigned int base; + GT_READ(GT_PCI1IOLD_OFS, &base); + base = base << 21; + return base; +} + +/* + * pci1GetIOspaceSize - Return PCI1 IO Bar Size. + * Inputs: N/A + * Returns: PCI1 IO Bar Size. + */ + +static unsigned int pci1GetIOspaceSize(void) +{ + unsigned int top, base, size; + GT_READ(GT_PCI1IOLD_OFS, &base); + base = base << 21; + GT_READ(GT_PCI1IOHD_OFS, &top); + top = (top << 21); + size = ((top - base) & 0xfffffff); + size = size | 0x1fffff; + return (size + 1); +} + +/* + * pci1GetMemory0Base - Return PCI1 Memory 0 Base Address. + * Inputs: N/A + * Returns: PCI1 Memory 0 Base Address. + */ + +static unsigned int pci1GetMemory0Base(void) +{ + unsigned int base; + GT_READ(GT_PCI1M0LD_OFS, &base); + base = base << 21; + return base; +} + +/* + * pci1GetMemory0Size - Return PCI1 Memory 0 Bar Size. + * Inputs: N/A + * Returns: PCI1 Memory 0 Bar Size. + */ + +static unsigned int pci1GetMemory0Size(void) +{ + unsigned int top, base, size; + GT_READ(GT_PCI1M1LD_OFS, &base); + base = base << 21; + GT_READ(GT_PCI1M1HD_OFS, &top); + top = (top << 21); + size = ((top - base) & 0xfffffff); + size = size | 0x1fffff; + return (size + 1); +} + +/* + * pci1GetMemory1Base - Return PCI1 Memory 1 Base Address. + * Inputs: N/A + * Returns: PCI1 Memory 1 Base Address. + */ + +static unsigned int pci1GetMemory1Base(void) +{ + unsigned int base; + GT_READ(GT_PCI1M1LD_OFS, &base); + base = base << 21; + return base; +} + +/* + * pci1GetMemory1Size - Return PCI1 Memory 1 Bar Size. + * Inputs: N/A + * Returns: PCI1 Memory 1 Bar Size. + */ + +static unsigned int pci1GetMemory1Size(void) +{ + unsigned int top, base, size; + GT_READ(GT_PCI1M1LD_OFS, &base); + base = base << 21; + GT_READ(GT_PCI1M1HD_OFS, &top); + top = (top << 21); + size = ((top - base) & 0xfffffff); + size = size | 0x1fffff; + return (size + 1); +} + + + +/* + * pci_range_ck - + * + * Check if the pci device that are trying to access does really exists + * on the evaluation board. + * + * Inputs : + * bus - bus number (0 for PCI 0 ; 1 for PCI 1) + * dev - number of device on the specific pci bus + * + * Outpus : + * 0 - if OK , 1 - if failure + */ +static __inline__ int pci_range_ck(unsigned char bus, unsigned char dev) +{ + //DBG(KERN_INFO "p_r_c %d %d\n",bus,dev); + if (((bus == 0) || (bus == 1)) && (dev >= 6) && (dev <= 8)) + return 0; // Bus/Device Number OK + return -1; // Bus/Device Number not OK +} + +/* + * pciXReadConfigReg - Read from a PCI configuration register + * - Make sure the GT is configured as a master before + * reading from another device on the PCI. + * - The function takes care of Big/Little endian conversion. + * INPUTS: regOffset: The register offset as it apears in the GT spec (or PCI + * spec) + * pciDevNum: The device number needs to be addressed. + * RETURNS: data , if the data == 0xffffffff check the master abort bit in the + * cause register to make sure the data is valid + * + * Configuration Address 0xCF8: + * + * 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number + * |congif|Reserved| Bus |Device|Function|Register|00| + * |Enable| |Number|Number| Number | Number | | <=field Name + * + */ +static unsigned int pci0ReadConfigReg(int offset, struct pci_dev *device) +{ + unsigned int DataForRegCf8; + unsigned int data; + + DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) | + (PCI_FUNC(device->devfn) << 8) | + (offset & ~0x3)) | 0x80000000; + GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8); + + /* The casual observer might wonder why the READ is duplicated here, + rather than immediately following the WRITE, and just have the + swap in the "if". That's because there is a latency problem + with trying to read immediately after setting up the address + register. The "if" check gives enough time for the address + to stabilize, so the READ can work. + */ + if (PCI_SLOT(device->devfn) == SELF) { /* This board */ + GT_READ(GT_PCI0_CFGDATA_OFS, &data); + return data; + } else { /* The PCI is working in LE Mode so swap the Data. */ + GT_READ(GT_PCI0_CFGDATA_OFS, &data); + return cpu_to_le32(data); + } +} + +static unsigned int pci1ReadConfigReg(int offset, struct pci_dev *device) +{ + unsigned int DataForRegCf8; + unsigned int data; + + DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) | + (PCI_FUNC(device->devfn) << 8) | + (offset & ~0x3)) | 0x80000000; + /* The casual observer might wonder why the READ is duplicated here, + rather than immediately following the WRITE, and just have the + swap in the "if". That's because there is a latency problem + with trying to read immediately after setting up the address + register. The "if" check gives enough time for the address + to stabilize, so the READ can work. + */ + if (PCI_SLOT(device->devfn) == SELF) { /* This board */ + /* when configurating our own PCI 1 L-unit the access is through + the PCI 0 interface with reg number = reg number + 0x80 */ + DataForRegCf8 |= 0x80; + GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8); + } else { /* The PCI is working in LE Mode so swap the Data. */ + GT_WRITE(GT_PCI1_CFGADDR_OFS, DataForRegCf8); + } + if (PCI_SLOT(device->devfn) == SELF) { /* This board */ + GT_READ(GT_PCI0_CFGDATA_OFS, &data); + return data; + } else { + GT_READ(GT_PCI1_CFGDATA_OFS, &data); + return cpu_to_le32(data); + } +} + + + +/* + * pciXWriteConfigReg - Write to a PCI configuration register + * - Make sure the GT is configured as a master before + * writingto another device on the PCI. + * - The function takes care of Big/Little endian conversion. + * Inputs: unsigned int regOffset: The register offset as it apears in the + * GT spec + * (or any other PCI device spec) + * pciDevNum: The device number needs to be addressed. + * + * Configuration Address 0xCF8: + * + * 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number + * |congif|Reserved| Bus |Device|Function|Register|00| + * |Enable| |Number|Number| Number | Number | | <=field Name + * + */ +static void pci0WriteConfigReg(unsigned int offset, + struct pci_dev *device, unsigned int data) +{ + unsigned int DataForRegCf8; + + DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) | + (PCI_FUNC(device->devfn) << 8) | + (offset & ~0x3)) | 0x80000000; + GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8); + if (PCI_SLOT(device->devfn) == SELF) { /* This board */ + GT_WRITE(GT_PCI0_CFGDATA_OFS, data); + } else { /* configuration Transaction over the pci. */ + /* The PCI is working in LE Mode so swap the Data. */ + GT_WRITE(GT_PCI0_CFGDATA_OFS, le32_to_cpu(data)); + } +} + +static void pci1WriteConfigReg(unsigned int offset, + struct pci_dev *device, unsigned int data) +{ + unsigned int DataForRegCf8; + + DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) | + (PCI_FUNC(device->devfn) << 8) | + (offset & ~0x3)) | 0x80000000; + /* There is a latency problem + with trying to read immediately after setting up the address + register. The "if" check gives enough time for the address + to stabilize, so the WRITE can work. + */ + if (PCI_SLOT(device->devfn) == SELF) { /* This board */ + /* when configurating our own PCI 1 L-unit the access is through + the PCI 0 interface with reg number = reg number + 0x80 */ + DataForRegCf8 |= 0x80; + GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8); + } else { /* configuration Transaction over the pci. */ + /* The PCI is working in LE Mode so swap the Data. */ + GT_WRITE(GT_PCI1_CFGADDR_OFS, DataForRegCf8); + } + if (PCI_SLOT(device->devfn) == SELF) { /* This board */ + GT_WRITE(GT_PCI0_CFGDATA_OFS, data); + } else { /* configuration Transaction over the pci. */ + GT_WRITE(GT_PCI1_CFGADDR_OFS, le32_to_cpu(data)); + } +} + + +/* + * galileo_pcibios_(read/write)_config_(dword/word/byte) - + * + * reads/write a dword/word/byte register from the configuration space + * of a device. + * + * Inputs : + * bus - bus number + * dev - device number + * offset - register offset in the configuration space + * val - value to be written / read + * + * Outputs : + * PCIBIOS_SUCCESSFUL when operation was succesfull + * PCIBIOS_DEVICE_NOT_FOUND when the bus or dev is errorneous + * PCIBIOS_BAD_REGISTER_NUMBER when accessing non aligned + */ + +static int galileo_pcibios_read_config_dword(struct pci_dev *device, + int offset, u32 * val) +{ + int dev, bus; + //DBG(KERN_INFO "rcd entry \n",offset,val); + bus = device->bus->number; + dev = PCI_SLOT(device->devfn); + + if (pci_range_ck(bus, dev)) { + *val = 0xffffffff; + return PCIBIOS_DEVICE_NOT_FOUND; + } + if (offset & 0x3) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (bus == 0) + *val = pci0ReadConfigReg(offset, device); +// if (bus == 1) *val = pci1ReadConfigReg (offset,device); + DBG(KERN_INFO "rr: rcd dev %d offset %x %x\n", dev, offset, *val); + + /* + * This is so that the upper PCI layer will get the correct return + * value if we're not attached to anything. + */ + if ((offset == 0) && (*val == 0xffffffff)) { + return PCIBIOS_DEVICE_NOT_FOUND; + } + + return PCIBIOS_SUCCESSFUL; +} + +static int galileo_pcibios_read_config_word(struct pci_dev *device, + int offset, u16 * val) +{ + int dev, bus; + + bus = device->bus->number; + dev = PCI_SLOT(device->devfn); + + if (pci_range_ck(bus, dev)) { + *val = 0xffff; + return PCIBIOS_DEVICE_NOT_FOUND; + } + if (offset & 0x1) + return PCIBIOS_BAD_REGISTER_NUMBER; + + if (bus == 0) + *val = + (unsigned short) (pci0ReadConfigReg(offset, device) >> + ((offset & ~0x3) * 8)); +// if (bus == 1) *val = (unsigned short) (pci1ReadConfigReg(offset,device) >> ((offset & ~0x3) * 8)); + + DBG(KERN_INFO "rr: rcw dev %d offset %x %x\n", dev, offset, *val); + + return PCIBIOS_SUCCESSFUL; +} + +static int galileo_pcibios_read_config_byte(struct pci_dev *device, + int offset, u8 * val) +{ + int dev, bus; + + bus = device->bus->number; + dev = PCI_SLOT(device->devfn); + + if (pci_range_ck(bus, dev)) { + *val = 0xff; + return PCIBIOS_DEVICE_NOT_FOUND; + } + + if (bus == 0) + *val = + (unsigned char) (pci0ReadConfigReg(offset, device) >> + ((offset & ~0x3) * 8)); +// if (bus == 1) *val = (unsigned char) (pci1ReadConfigReg(offset,device) >> ((offset & ~0x3) * 8)); + + DBG(KERN_INFO "rr: rcb dev %d offset %x %x\n", dev, offset, *val); + + /* This is so that the upper PCI layer will get the correct return value if + we're not attached to anything. */ + if ((offset == 0xe) && (*val == 0xff)) { + u32 MasterAbort; + GT_READ(GT_INTRCAUSE_OFS, &MasterAbort); + if (MasterAbort & 0x40000) { + DBG(KERN_INFO "PCI Master Abort, ICR %x\n", + MasterAbort); + GT_WRITE(GT_INTRCAUSE_OFS, + (MasterAbort & 0xfffbffff)); + return PCIBIOS_DEVICE_NOT_FOUND; + } + } + + return PCIBIOS_SUCCESSFUL; +} + +static int galileo_pcibios_write_config_dword(struct pci_dev *device, + int offset, u32 val) +{ + int dev, bus; + + bus = device->bus->number; + dev = PCI_SLOT(device->devfn); + + if (pci_range_ck(bus, dev)) + return PCIBIOS_DEVICE_NOT_FOUND; + if (offset & 0x3) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (bus == 0) + pci0WriteConfigReg(offset, device, val); +// if (bus == 1) pci1WriteConfigReg (offset,device,val); + + DBG(KERN_INFO "rr: wcd dev %d, offset %x, val %x\n", dev, offset, + val); + return PCIBIOS_SUCCESSFUL; +} + + +static int galileo_pcibios_write_config_word(struct pci_dev *device, + int offset, u16 val) +{ + int dev, bus; + unsigned long tmp; + + bus = device->bus->number; + dev = PCI_SLOT(device->devfn); + + if (pci_range_ck(bus, dev)) + return PCIBIOS_DEVICE_NOT_FOUND; + if (offset & 0x1) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (bus == 0) + tmp = pci0ReadConfigReg(offset, device); +// if (bus == 1) tmp = pci1ReadConfigReg (offset,device); + + if ((offset % 4) == 0) + tmp = (tmp & 0xffff0000) | (val & 0xffff); + if ((offset % 4) == 2) + tmp = (tmp & 0x0000ffff) | ((val & 0xffff) << 16); + + if (bus == 0) + pci0WriteConfigReg(offset, device, tmp); +// if (bus == 1) pci1WriteConfigReg (offset,device,tmp); + DBG(KERN_INFO "rr: wcw dev %d, offset %x, val %x\n", dev, offset, + val); + return PCIBIOS_SUCCESSFUL; +} + +static int galileo_pcibios_write_config_byte(struct pci_dev *device, + int offset, u8 val) +{ + int dev, bus; + unsigned long tmp; + + bus = device->bus->number; + dev = PCI_SLOT(device->devfn); + + if (pci_range_ck(bus, dev)) + return PCIBIOS_DEVICE_NOT_FOUND; + if (bus == 0) + tmp = pci0ReadConfigReg(offset, device); +// if (bus == 1) tmp = pci1ReadConfigReg (offset,device); + + if ((offset % 4) == 0) + tmp = (tmp & 0xffffff00) | (val & 0xff); + if ((offset % 4) == 1) + tmp = (tmp & 0xffff00ff) | ((val & 0xff) << 8); + if ((offset % 4) == 2) + tmp = (tmp & 0xff00ffff) | ((val & 0xff) << 16); + if ((offset % 4) == 3) + tmp = (tmp & 0x00ffffff) | ((val & 0xff) << 24); + + if (bus == 0) + pci0WriteConfigReg(offset, device, tmp); +// if (bus == 1) pci1WriteConfigReg (offset,device,tmp); + DBG(KERN_INFO "rr: wcb dev %d, offset %x, val %x\n", dev, offset, + val); + + return PCIBIOS_SUCCESSFUL; +} + +static void galileo_pcibios_set_master(struct pci_dev *dev) +{ + u16 cmd; + + DBG(KERN_INFO "rr: galileo_pcibios_set_master\n"); + + galileo_pcibios_read_config_word(dev, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_MASTER; + galileo_pcibios_write_config_word(dev, PCI_COMMAND, cmd); + DBG("PCI: Enabling device %s (%04x)\n", dev->slot_name, cmd); +} + +/* Externally-expected functions. Do not change function names */ + +int pcibios_enable_resources(struct pci_dev *dev) +{ + u16 cmd, old_cmd; + u16 tmp; + u8 tmp1; + int idx; + struct resource *r; + + DBG(KERN_INFO "rr: pcibios_enable_resources\n"); + + galileo_pcibios_read_config_word(dev, PCI_COMMAND, &cmd); + old_cmd = cmd; + for (idx = 0; idx < 6; idx++) { + r = &dev->resource[idx]; + DBG(KERN_INFO + "rr: BAR %d, start %lx, end %lx, flags %lx\n", idx, + r->start, r->end, r->flags); + if (!r->start && r->end) { + printk(KERN_ERR + "PCI: Device %s not available because of resource collisions\n", + dev->slot_name); + return -EINVAL; + } + if (r->flags & IORESOURCE_IO) + cmd |= PCI_COMMAND_IO; + if (r->flags & IORESOURCE_MEM) + cmd |= PCI_COMMAND_MEMORY; + } + if (cmd != old_cmd) { + DBG(KERN_INFO "PCI: Enabling device %s (%04x -> %04x)\n", + dev->slot_name, old_cmd, cmd); + galileo_pcibios_write_config_word(dev, PCI_COMMAND, cmd); + } + + /* + Let's fix up the latency timer and cache line size here. Cache line size = + 32 bytes / sizeof dword (4) = 8. + Latency timer must be > 8. 32 is random but appears to work. + */ + galileo_pcibios_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &tmp1); + if (tmp1 != 8) { + DBG(KERN_INFO + "rr: PCI setting cache line size to 8 from %d\n", + tmp1); + galileo_pcibios_write_config_byte(dev, PCI_CACHE_LINE_SIZE, + 8); + } + galileo_pcibios_read_config_byte(dev, PCI_LATENCY_TIMER, &tmp1); + if (tmp1 < 32) { + DBG(KERN_INFO + "rr: PCI setting latency timer to 32 from %d\n", tmp1); + galileo_pcibios_write_config_byte(dev, PCI_LATENCY_TIMER, + 32); + } + + return 0; +} + +int pcibios_enable_device(struct pci_dev *dev, int mask) +{ + DBG(KERN_INFO "rr: pcibios_enable_device\n"); + return pcibios_enable_resources(dev); +} + +void pcibios_align_resource(void *data, struct resource *res, + unsigned long size, unsigned long align) +{ + if (res->flags & IORESOURCE_IO) { + unsigned long start = res->start; + + /* We need to avoid collisions with `mirrored' VGA ports + and other strange ISA hardware, so we always want the + addresses kilobyte aligned. */ + if (size > 0x100) { + DBG(KERN_ERR "PCI: I/O Region %s/%d too large" + " (%ld bytes)\n", dev->slot_name, + dev->resource - res, size); + } + + start = (start + 1024 - 1) & ~(1024 - 1); + res->start = start; + } +} + +/* + * structure galileo_pci_ops + * + * This structure holds the pointers for the PCI configuration space + * access, and the fixup for the interrupts. + * This structure is registered to the operating system in boot time + */ +struct pci_ops galileo_pci_ops = { + galileo_pcibios_read_config_byte, + galileo_pcibios_read_config_word, + galileo_pcibios_read_config_dword, + galileo_pcibios_write_config_byte, + galileo_pcibios_write_config_word, + galileo_pcibios_write_config_dword +}; + +/* + * galileo_pcibios_fixup_bus - + * + * After detecting all agents over the PCI , this function is called + * in order to give an interrupt number for each PCI device starting + * from IRQ 20. It does also enables master for each device. + * + * Inputs : + * mem_start , mem_end are not relevant in MIPS architecture. + * + * Outpus : + * return always mem_start + */ +static void __devinit galileo_pcibios_fixup_bus(struct pci_bus *bus) +{ + unsigned int Current_IRQ = 20; + struct pci_bus *current_bus = bus; + struct pci_dev *devices; + struct list_head *devices_link; + + list_for_each(devices_link, &(current_bus->devices)) { + devices = pci_dev_b(devices_link); + if (devices != NULL) { + devices->irq = Current_IRQ++; + + /* Assign an interrupt number for the device */ + galileo_pcibios_write_config_byte(devices, + PCI_INTERRUPT_LINE, + Current_IRQ); + galileo_pcibios_set_master(devices); + + } + } + +} + +struct pci_fixup pcibios_fixups[] = { +// { PCI_FIXUP_HEADER, 0x4620, 0x11ab, galileo_pcibios_fixup }, + {0} +}; + +void __devinit pcibios_fixup_bus(struct pci_bus *c) +{ + DBG(KERN_INFO "rr: pcibios_fixup_bus\n"); + galileo_pcibios_fixup_bus(c); +} + +/* + * This code was derived from Galileo Technology's example + * and significantly reworked. + * + * This is very simple. It does not scan multiple function devices. It does + * not scan behind bridges. Those would be simple to implement, but we don't + * currently need this. + */ +static void __init scan_and_initialize_pci(void) +{ + struct pci_device pci_devices[MAX_PCI_DEVS]; + + if (scan_pci_bus(pci_devices)) { + allocate_pci_space(pci_devices); + } +} + +/* + * This is your basic PCI scan. It goes through each slot and checks to + * see if there's something that responds. If so, then get the size and + * type of each of the responding BARs. Save them for later. + */ + +static u32 __init scan_pci_bus(struct pci_device *pci_devices) +{ + u32 arrayCounter = 0; + u32 memType; + u32 memSize; + u32 pci_slot, bar; + u32 id; + u32 c18RegValue; + struct pci_dev device; + + DBG(KERN_INFO "rr: scan_pci_bus\n"); + + /* + According to PCI REV 2.1 MAX agents on the bus are 21. + We don't bother scanning ourselves (slot 0). + */ + for (pci_slot = 1; pci_slot < 22; pci_slot++) { + + device.devfn = PCI_DEVFN(pci_slot, 0); + id = pci0ReadConfigReg(PCI_VENDOR_ID, &device); + + /* Check for a PCI Master Abort (nothing responds in the slot) */ + GT_READ(GT_INTRCAUSE_OFS, &c18RegValue); + /* Clearing bit 18 of in the Cause Register 0xc18 by writting 0. */ + GT_WRITE(GT_INTRCAUSE_OFS, (c18RegValue & 0xfffbffff)); + if ((id != 0xffffffff) && !(c18RegValue & 0x40000)) { + DBG(KERN_INFO "rr: found device %x, slot %d\n", id, + pci_slot); + pci_devices[arrayCounter].slot = pci_slot; + for (bar = 0; bar < 6; bar++) { + memType = + pci0ReadConfigReg(PCI_BASE_ADDRESS_0 + + (bar * 4), &device); + pci_devices[arrayCounter].BARtype[bar] = + memType & 1; + pci0WriteConfigReg(PCI_BASE_ADDRESS_0 + + (bar * 4), &device, + 0xffffffff); + memSize = + pci0ReadConfigReg(PCI_BASE_ADDRESS_0 + + (bar * 4), &device); + if (memType & 1) { /* IO space */ + pci_devices[arrayCounter]. + BARsize[bar] = + ~(memSize & 0xfffffffc) + 1; + } else { /* memory space */ + pci_devices[arrayCounter]. + BARsize[bar] = + ~(memSize & 0xfffffff0) + 1; + } + DBG(KERN_INFO + "rr: BAR %d, type %d, size %x\n", bar, + (memType & 1), + pci_devices[arrayCounter]. + BARsize[bar]); + } /* BAR counter */ + + arrayCounter++; + } + /* found a device */ + } /* slot counter */ + + DBG(KERN_INFO "rr: found %d devices\n", arrayCounter); + if (arrayCounter < MAX_PCI_DEVS) { + pci_devices[arrayCounter].slot = -1; + } + return (arrayCounter); +} + +#define ALIGN(val,align) (((val) + ((align) - 1)) & ~((align) - 1)) +#define MAX(val1, val2) ((val1) > (val2) ? (val1) : (val2)) + +/* + * This function goes through the list of devices and allocates the BARs in + * either IO or MEM space. It does it in order of size, which will limit the + * amount of fragmentation we have in the IO and MEM spaces. + */ + +static void __init allocate_pci_space(struct pci_device *pci_devices) +{ + u32 count, maxcount, bar; + u32 maxSize, maxDevice, maxBAR; + u32 alignto; + u32 base; + u32 pci0_mem_base = pci0GetMemory0Base(); + u32 pci0_io_base = pci0GetIOspaceBase(); + struct pci_dev device; + + DBG(KERN_INFO "rr: allocate_pci_space\n"); + + DBG(KERN_INFO "pci0_io_base %x\n", pci0_io_base); + DBG(KERN_INFO "pci0_mem_base %x\n", pci0_mem_base); + + /* How many PCI devices do we have? */ + maxcount = MAX_PCI_DEVS; + for (count = 0; count < MAX_PCI_DEVS; count++) { + if (pci_devices[count].slot == -1) { + maxcount = count; + break; + } + } + +// DBG(KERN_INFO "Found %d devices\n", maxcount); + + do { + /* Find the largest size BAR we need to allocate */ + maxSize = 0; + for (count = 0; count < maxcount; count++) { + for (bar = 0; bar < 6; bar++) { + if (pci_devices[count].BARsize[bar] > + maxSize) { + maxSize = + pci_devices[count]. + BARsize[bar]; + maxDevice = count; + maxBAR = bar; + } + } + } + + /* + We've found the largest BAR. Allocate it into IO or + mem space. We don't idiot check the bases to make + sure they haven't overflowed the current size for that aperture. + + Don't bother to enable the device's IO or MEM space here. That will + be done in pci_enable_resources if the device is activated by a driver. + */ + if (maxSize) { + device.devfn = + PCI_DEVFN(pci_devices[maxDevice].slot, 0); + if (pci_devices[maxDevice].BARtype[maxBAR] == 1) { + alignto = MAX(0x1000, maxSize); + base = ALIGN(pci0_io_base, alignto); + pci0WriteConfigReg(PCI_BASE_ADDRESS_0 + + (maxBAR * 4), &device, + base | 0x1); + pci0_io_base = base + alignto; + DBG(KERN_INFO + "Device %d BAR %d address %x\n", + pci_devices[maxDevice].slot, maxBAR, + base); + DBG(KERN_INFO "New IO base %x\n", + pci0_io_base); + } else { + alignto = MAX(0x1000, maxSize); + base = ALIGN(pci0_mem_base, alignto); + pci0WriteConfigReg(PCI_BASE_ADDRESS_0 + + (maxBAR * 4), &device, + base); + pci0_mem_base = base + alignto; + DBG(KERN_INFO + "Device %d BAR %d address %x\n", + pci_devices[maxDevice].slot, maxBAR, + base); + DBG(KERN_INFO "New mem base %x\n", + pci0_mem_base); + } + /* + This entry is finished. Remove it from the list we'll scan. + */ + pci_devices[maxDevice].BARsize[maxBAR] = 0; + } + } while (maxSize); +} + +unsigned __init int pcibios_assign_all_busses(void) +{ + return 1; +} + +static int __init pcibios_init(void) +{ + + u32 tmp; + struct pci_dev controller; + + controller.devfn = SELF; + + DBG(KERN_INFO "rr: pcibios_init\n"); + GT_READ(GT_PCI0_CMD_OFS, &tmp); + DBG(KERN_INFO "rr: PCI0 command - %x\n", tmp); + GT_READ(GT_PCI0_BARE_OFS, &tmp); + DBG(KERN_INFO "rr: BAR0 - %x\n", tmp); + + /* + * You have to enable bus mastering to configure any other + * card on the bus. + */ + tmp = pci0ReadConfigReg(PCI_COMMAND, &controller); + DBG(KERN_INFO "rr: command/status - %x\n", tmp); + tmp |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_SERR; + DBG(KERN_INFO "rr: new command/status - %x\n", tmp); + pci0WriteConfigReg(PCI_COMMAND, &controller, tmp); + + /* This scans the PCI bus and sets up initial values. */ + scan_and_initialize_pci(); + + /* + * Reset PCI I/O and PCI MEM values to ones supported by EVM. + */ + ioport_resource.start = 0x10000000; + ioport_resource.end = 0x11ffffff; /* 32 MB */ + iomem_resource.start = 0x12000000; + iomem_resource.end = 0x13ffffff; /* 32 MB */ + + pci_scan_bus(0, &galileo_pci_ops, NULL); + + return 0; +} + +subsys_initcall(pcibios_init); + +char *pcibios_setup(char *str) +{ + printk(KERN_INFO "rr: pcibios_setup\n"); + /* Nothing to do for now. */ + + return str; +} diff -Nru a/arch/mips/pci/ops-ev96100.c b/arch/mips/pci/ops-ev96100.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/ops-ev96100.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,264 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * Galileo EV96100 board specific pci support. + * + * Copyright 2000 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This file was derived from Carsten Langgaard's + * arch/mips/mips-boards/generic/pci.c + * + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include + +#include +#include +#include +#include + +#define PCI_ACCESS_READ 0 +#define PCI_ACCESS_WRITE 1 + +#undef DEBUG + +#ifdef DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +#define GT_PCI_MEM_BASE 0x12000000 +#define GT_PCI_MEM_SIZE 0x02000000 +#define GT_PCI_IO_BASE 0x10000000 +#define GT_PCI_IO_SIZE 0x02000000 +static struct resource pci_io_resource = { + "io pci IO space", + 0x10000000, + 0x10000000 + 0x02000000, + IORESOURCE_IO +}; + +static struct resource pci_mem_resource = { + "ext pci memory space", + 0x12000000, + 0x12000000 + 0x02000000, + IORESOURCE_MEM +}; + +extern struct pci_ops gt96100_pci_ops; + +struct pci_channel mips_pci_channels[] = { + {>96100_pci_ops, &pci_io_resource, &pci_mem_resource, 1, 0xff}, + {NULL, NULL, NULL, NULL, NULL} +}; + +int +static gt96100_config_access(unsigned char access_type, + struct pci_dev *dev, unsigned char where, + u32 * data) +{ + unsigned char bus = dev->bus->number; + unsigned char dev_fn = dev->devfn; + u32 intr; + + + if ((bus == 0) && (dev_fn >= PCI_DEVFN(31, 0))) { + return -1; /* Because of a bug in the galileo (for slot 31). */ + } + + /* Clear cause register bits */ + GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT | + GT_INTRCAUSE_TARABORT0_BIT)); + + /* Setup address */ + GT_WRITE(GT_PCI0_CFGADDR_OFS, + (bus << GT_PCI0_CFGADDR_BUSNUM_SHF) | + (dev_fn << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | + ((where / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) | + GT_PCI0_CFGADDR_CONFIGEN_BIT); + udelay(2); + + + if (access_type == PCI_ACCESS_WRITE) { + if (dev_fn != 0) { + *data = le32_to_cpu(*data); + } + GT_WRITE(GT_PCI0_CFGDATA_OFS, *data); + } else { + GT_READ(GT_PCI0_CFGDATA_OFS, *data); + if (dev_fn != 0) { + *data = le32_to_cpu(*data); + } + } + + udelay(2); + + /* Check for master or target abort */ + GT_READ(GT_INTRCAUSE_OFS, intr); + + if (intr & + (GT_INTRCAUSE_MASABORT0_BIT | GT_INTRCAUSE_TARABORT0_BIT)) { + //printk("config access error: %x:%x\n", dev_fn,where); + /* Error occured */ + + /* Clear bits */ + GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT | + GT_INTRCAUSE_TARABORT0_BIT)); + + if (access_type == PCI_ACCESS_READ) { + *data = 0xffffffff; + } + return -1; + } + return 0; +} + + +/* + * We can't address 8 and 16 bit words directly. Instead we have to + * read/write a 32bit word and mask/modify the data we actually want. + */ +static int read_config_byte(struct pci_dev *dev, int where, u8 * val) +{ + u32 data = 0; + + if (gt96100_config_access(PCI_ACCESS_READ, dev, where, &data)) { + *val = 0xff; + return -1; + } + + *val = (data >> ((where & 3) << 3)) & 0xff; + DBG("cfg read byte: bus %d dev_fn %x where %x: val %x\n", + dev->bus->number, dev->devfn, where, *val); + + return PCIBIOS_SUCCESSFUL; +} + + +static int read_config_word(struct pci_dev *dev, int where, u16 * val) +{ + u32 data = 0; + + if (where & 1) + return PCIBIOS_BAD_REGISTER_NUMBER; + + if (gt96100_config_access(PCI_ACCESS_READ, dev, where, &data)) { + *val = 0xffff; + return -1; + } + + *val = (data >> ((where & 3) << 3)) & 0xffff; + DBG("cfg read word: bus %d dev_fn %x where %x: val %x\n", + dev->bus->number, dev->devfn, where, *val); + + return PCIBIOS_SUCCESSFUL; +} + +static int read_config_dword(struct pci_dev *dev, int where, u32 * val) +{ + u32 data = 0; + + if (where & 3) + return PCIBIOS_BAD_REGISTER_NUMBER; + + if (gt96100_config_access(PCI_ACCESS_READ, dev, where, &data)) { + *val = 0xffffffff; + return -1; + } + + *val = data; + DBG("cfg read dword: bus %d dev_fn %x where %x: val %x\n", + dev->bus->number, dev->devfn, where, *val); + + return PCIBIOS_SUCCESSFUL; +} + + +static int write_config_byte(struct pci_dev *dev, int where, u8 val) +{ + u32 data = 0; + + if (gt96100_config_access(PCI_ACCESS_READ, dev, where, &data)) + return -1; + + data = (data & ~(0xff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + DBG("cfg write byte: bus %d dev_fn %x where %x: val %x\n", + dev->bus->number, dev->devfn, where, val); + + if (gt96100_config_access(PCI_ACCESS_WRITE, dev, where, &data)) + return -1; + + return PCIBIOS_SUCCESSFUL; +} + +static int write_config_word(struct pci_dev *dev, int where, u16 val) +{ + u32 data = 0; + + if (where & 1) + return PCIBIOS_BAD_REGISTER_NUMBER; + + if (gt96100_config_access(PCI_ACCESS_READ, dev, where, &data)) + return -1; + + data = (data & ~(0xffff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + DBG("cfg write word: bus %d dev_fn %x where %x: val %x\n", + dev->bus->number, dev->devfn, where, val); + + if (gt96100_config_access(PCI_ACCESS_WRITE, dev, where, &data)) + return -1; + + + return PCIBIOS_SUCCESSFUL; +} + +static int write_config_dword(struct pci_dev *dev, int where, u32 val) +{ + if (where & 3) + return PCIBIOS_BAD_REGISTER_NUMBER; + + if (gt96100_config_access(PCI_ACCESS_WRITE, dev, where, &val)) + return -1; + DBG("cfg write dword: bus %d dev_fn %x where %x: val %x\n", + dev->bus->number, dev->devfn, where, val); + + return PCIBIOS_SUCCESSFUL; +} + +struct pci_ops gt96100_pci_ops = { + read_config_byte, + read_config_word, + read_config_dword, + write_config_byte, + write_config_word, + write_config_dword +}; diff -Nru a/arch/mips/pci/ops-it8172.c b/arch/mips/pci/ops-it8172.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/ops-it8172.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,219 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * IT8172 system controller specific pci support. + * + * Copyright 2000 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include + +#include +#include +#include + +#define PCI_ACCESS_READ 0 +#define PCI_ACCESS_WRITE 1 + +#undef DEBUG +#ifdef DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +static struct resource pci_mem_resource_1; + +static struct resource pci_io_resource = { + "io pci IO space", + 0x14018000, + 0x17FFFFFF, + IORESOURCE_IO +}; + +static struct resource pci_mem_resource_0 = { + "ext pci memory space 0/1", + 0x10101000, + 0x13FFFFFF, + IORESOURCE_MEM, + &pci_mem_resource_0, + NULL, + &pci_mem_resource_1 +}; + +static struct resource pci_mem_resource_1 = { + "ext pci memory space 2/3", + 0x1A000000, + 0x1FBFFFFF, + IORESOURCE_MEM, + &pci_mem_resource_0, + NULL, + NULL +}; + +extern struct pci_ops it8172_pci_ops; + +struct pci_channel mips_pci_channels[] = { + {&it8172_pci_ops, &pci_io_resource, &pci_mem_resource_0, 0x10, + 0xff}, + {NULL, NULL, NULL, NULL, NULL} +}; + +static int it8172_pcibios_config_access(unsigned char access_type, + struct pci_bus *bus, + unsigned int devfn, int where, + u32 * data) +{ + /* + * config cycles are on 4 byte boundary only + */ + + /* Setup address */ + IT_WRITE(IT_CONFADDR, (bus->number << IT_BUSNUM_SHF) | + (devfn << IT_FUNCNUM_SHF) | (where & ~0x3)); + + if (access_type == PCI_ACCESS_WRITE) { + IT_WRITE(IT_CONFDATA, *data); + } else { + IT_READ(IT_CONFDATA, *data); + } + + /* + * Revisit: check for master or target abort. + */ + return 0; +} + + +/* + * We can't address 8 and 16 bit words directly. Instead we have to + * read/write a 32bit word and mask/modify the data we actually want. + */ +static write_config(struct pci_bus *bus, unsigned int devfn, int where, + int size, u32 val) +{ + u32 data = 0; + + switch (size) { + case 1: + if (it8172_pcibios_config_access + (PCI_ACCESS_READ, dev, where, &data)) + return -1; + + *val = (data >> ((where & 3) << 3)) & 0xff; + + return PCIBIOS_SUCCESSFUL; + + case 2: + + if (where & 1) + return PCIBIOS_BAD_REGISTER_NUMBER; + + if (it8172_pcibios_config_access + (PCI_ACCESS_READ, dev, where, &data)) + return -1; + + *val = (data >> ((where & 3) << 3)) & 0xffff; + DBG("cfg read word: bus %d dev_fn %x where %x: val %x\n", + dev->bus->number, dev->devfn, where, *val); + + return PCIBIOS_SUCCESSFUL; + + case 4: + + if (where & 3) + return PCIBIOS_BAD_REGISTER_NUMBER; + + if (it8172_pcibios_config_access + (PCI_ACCESS_READ, dev, where, &data)) + return -1; + + *val = data; + + return PCIBIOS_SUCCESSFUL; + } +} + + +static write_config(struct pci_bus *bus, unsigned int devfn, int where, + int size, u32 val) +{ + u32 data = 0; + + switch (size) { + case 1: + if (it8172_pcibios_config_access + (PCI_ACCESS_READ, dev, where, &data)) + return -1; + + data = (data & ~(0xff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + + if (it8172_pcibios_config_access + (PCI_ACCESS_WRITE, dev, where, &data)) + return -1; + + return PCIBIOS_SUCCESSFUL; + + case 2: + if (where & 1) + return PCIBIOS_BAD_REGISTER_NUMBER; + + if (it8172_pcibios_config_access + (PCI_ACCESS_READ, dev, where, &data)) + eturn - 1; + + data = (data & ~(0xffff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + + if (it8172_pcibios_config_access + (PCI_ACCESS_WRITE, dev, where, &data)) + return -1; + + return PCIBIOS_SUCCESSFUL; + + case 4: + if (where & 3) + return PCIBIOS_BAD_REGISTER_NUMBER; + + if (it8172_pcibios_config_access + (PCI_ACCESS_WRITE, dev, where, &val)) + return -1; + + return PCIBIOS_SUCCESSFUL; + } +} + +struct pci_ops it8172_pci_ops = { + .read = read_config, + .write = write_config, +}; + +unsigned __init int pcibios_assign_all_busses(void) +{ + return 1; +} diff -Nru a/arch/mips/pci/ops-jmr3927.c b/arch/mips/pci/ops-jmr3927.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/ops-jmr3927.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,491 @@ +/*********************************************************************** + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ahennessy@mvista.com + * + * Copyright (C) 2000-2001 Toshiba Corporation + * + * Based on arch/mips/ddb5xxx/ddb5477/pci_ops.c + * + * Define the pci_ops for JMR3927. + * + * Much of the code is derived from the original DDB5074 port by + * Geert Uytterhoeven + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include + +#include +#include +#include +#include + +struct resource pci_io_resource = { + "pci IO space", + 0x1000, /* reserve regacy I/O space */ + 0x1000 + JMR3927_PCIIO_SIZE - 1, + IORESOURCE_IO +}; + +struct resource pci_mem_resource = { + "pci memory space", + JMR3927_PCIMEM, + JMR3927_PCIMEM + JMR3927_PCIMEM_SIZE - 1, + IORESOURCE_MEM +}; + +extern struct pci_ops jmr3927_pci_ops; + +struct pci_channel mips_pci_channels[] = { + {&jmr3927_pci_ops, &pci_io_resource, &pci_mem_resource, 0, 0xff}, + {NULL, NULL, NULL, NULL, NULL} +}; + +unsigned int pcibios_assign_all_busses(void) +{ + return 1; +} + +static int +mkaddr(unsigned char bus, unsigned char dev_fn, unsigned char where, + int *flagsp) +{ + if (bus == 0 && dev_fn >= PCI_DEVFN(TX3927_PCIC_MAX_DEVNU, 0)) + return -1; + + tx3927_pcicptr->ica = ((bus & 0xff) << 0x10) | + ((dev_fn & 0xff) << 0x08) | (where & 0xfc); + /* clear M_ABORT and Disable M_ABORT Int. */ + tx3927_pcicptr->pcistat |= PCI_STATUS_REC_MASTER_ABORT; + tx3927_pcicptr->pcistatim &= ~PCI_STATUS_REC_MASTER_ABORT; + return 0; +} + +static int check_abort(int flags) +{ + int code = PCIBIOS_SUCCESSFUL; + if (tx3927_pcicptr->pcistat & PCI_STATUS_REC_MASTER_ABORT) { + tx3927_pcicptr->pcistat |= PCI_STATUS_REC_MASTER_ABORT; + tx3927_pcicptr->pcistatim |= PCI_STATUS_REC_MASTER_ABORT; + code = PCIBIOS_DEVICE_NOT_FOUND; + } + return code; +} + +/* + * We can't address 8 and 16 bit words directly. Instead we have to + * read/write a 32bit word and mask/modify the data we actually want. + */ +static int jmr3927_pcibios_read_config_byte(struct pci_dev *dev, + int where, unsigned char *val) +{ + int flags; + unsigned char bus, func_num; + + db_assert((where & 3) == 0); + db_assert(where < (1 << 8)); + + /* check if the bus is top-level */ + if (dev->bus->parent != NULL) { + bus = dev->bus->number; + db_assert(bus != 0); + } else { + bus = 0; + } + + func_num = PCI_FUNC(dev->devfn); + if (mkaddr(bus, dev->devfn, where, &flags)) + return -1; + *val = + *(volatile u8 *) ((ulong) & tx3927_pcicptr->icd | (where & 3)); + return check_abort(flags); +} + +static int jmr3927_pcibios_read_config_word(struct pci_dev *dev, + int where, unsigned short *val) +{ + int flags; + unsigned char bus, func_num; + + if (where & 1) + return PCIBIOS_BAD_REGISTER_NUMBER; + + db_assert((where & 3) == 0); + db_assert(where < (1 << 8)); + + /* check if the bus is top-level */ + if (dev->bus->parent != NULL) { + bus = dev->bus->number; + db_assert(bus != 0); + } else { + bus = 0; + } + + func_num = PCI_FUNC(dev->devfn); + if (mkaddr(bus, dev->devfn, where, &flags)) + return -1; + *val = + le16_to_cpu(*(volatile u16 *) + ((ulong) & tx3927_pcicptr->icd | (where & 3))); + return check_abort(flags); +} + +static int jmr3927_pcibios_read_config_dword(struct pci_dev *dev, + int where, unsigned int *val) +{ + int flags; + unsigned char bus, func_num; + + if (where & 3) + return PCIBIOS_BAD_REGISTER_NUMBER; + + db_assert((where & 3) == 0); + db_assert(where < (1 << 8)); + + /* check if the bus is top-level */ + if (dev->bus->parent != NULL) { + bus = dev->bus->number; + db_assert(bus != 0); + } else { + bus = 0; + } + + func_num = PCI_FUNC(dev->devfn); + if (mkaddr(bus, dev->devfn, where, &flags)) + return -1; + *val = le32_to_cpu(tx3927_pcicptr->icd); + return check_abort(flags); +} + +static int jmr3927_pcibios_write_config_byte(struct pci_dev *dev, + int where, unsigned char val) +{ + int flags; + unsigned char bus, func_num; + + /* check if the bus is top-level */ + if (dev->bus->parent != NULL) { + bus = dev->bus->number; + db_assert(bus != 0); + } else { + bus = 0; + } + + func_num = PCI_FUNC(dev->devfn); + if (mkaddr(bus, dev->devfn, where, &flags)) + return -1; + *(volatile u8 *) ((ulong) & tx3927_pcicptr->icd | (where & 3)) = + val; + return check_abort(flags); +} + +static int jmr3927_pcibios_write_config_word(struct pci_dev *dev, + int where, unsigned short val) +{ + int flags; + unsigned char bus, func_num; + + if (where & 1) + return PCIBIOS_BAD_REGISTER_NUMBER; + + /* check if the bus is top-level */ + if (dev->bus->parent != NULL) { + bus = dev->bus->number; + db_assert(bus != 0); + } else { + bus = 0; + } + + func_num = PCI_FUNC(dev->devfn); + if (mkaddr(bus, dev->devfn, where, &flags)) + return -1; + *(volatile u16 *) ((ulong) & tx3927_pcicptr->icd | (where & 3)) = + cpu_to_le16(val); + return check_abort(flags); +} + +static int jmr3927_pcibios_write_config_dword(struct pci_dev *dev, + int where, unsigned int val) +{ + int flags; + unsigned char bus, func_num; + + if (where & 3) + return PCIBIOS_BAD_REGISTER_NUMBER; + + /* check if the bus is top-level */ + if (dev->bus->parent != NULL) { + bus = dev->bus->number; + db_assert(bus != 0); + } else { + bus = 0; + } + + func_num = PCI_FUNC(dev->devfn); + if (mkaddr(bus, dev->devfn, where, &flags)) + return -1; + tx3927_pcicptr->icd = cpu_to_le32(val); + return check_abort(flags); +} +struct pci_ops jmr3927_pci_ops = { + jmr3927_pcibios_read_config_byte, + jmr3927_pcibios_read_config_word, + jmr3927_pcibios_read_config_dword, + jmr3927_pcibios_write_config_byte, + jmr3927_pcibios_write_config_word, + jmr3927_pcibios_write_config_dword +}; + +#ifndef JMR3927_INIT_INDIRECT_PCI +inline unsigned long tc_readl(volatile __u32 * addr) +{ + return readl(addr); +} +inline void tc_writel(unsigned long data, volatile __u32 * addr) +{ + writel(data, addr); +} +#else +unsigned long tc_readl(volatile __u32 * addr) +{ + unsigned long val; + + addr = PHYSADDR(addr); + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr = + (unsigned long) addr; + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe = + (PCI_IPCIBE_ICMD_MEMREAD << PCI_IPCIBE_ICMD_SHIFT) | + PCI_IPCIBE_IBE_LONG; + while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); + val = + le32_to_cpu(*(volatile u32 *) (ulong) & tx3927_pcicptr-> + ipcidata); + /* clear by setting */ + tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; + return val; +} +void tc_writel(unsigned long data, volatile __u32 * addr) +{ + addr = PHYSADDR(addr); + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcidata = + cpu_to_le32(data); + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr = + (unsigned long) addr; + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe = + (PCI_IPCIBE_ICMD_MEMWRITE << PCI_IPCIBE_ICMD_SHIFT) | + PCI_IPCIBE_IBE_LONG; + while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); + /* clear by setting */ + tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; +} +unsigned char tx_ioinb(unsigned char *addr) +{ + unsigned long val; + __u32 ioaddr; + int offset; + int byte; + + ioaddr = (unsigned long) addr; + offset = ioaddr & 0x3; + if (offset == 0) + byte = 0x7; + else if (offset == 1) + byte = 0xb; + else if (offset == 2) + byte = 0xd; + else if (offset == 3) + byte = 0xe; + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr = + (unsigned long) ioaddr; + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe = + (PCI_IPCIBE_ICMD_IOREAD << PCI_IPCIBE_ICMD_SHIFT) | byte; + while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); + val = + le32_to_cpu(*(volatile u32 *) (ulong) & tx3927_pcicptr-> + ipcidata); + val = val & 0xff; + /* clear by setting */ + tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; + return val; +} +void tx_iooutb(unsigned long data, unsigned char *addr) +{ + __u32 ioaddr; + int offset; + int byte; + + data = data | (data << 8) | (data << 16) | (data << 24); + ioaddr = (unsigned long) addr; + offset = ioaddr & 0x3; + if (offset == 0) + byte = 0x7; + else if (offset == 1) + byte = 0xb; + else if (offset == 2) + byte = 0xd; + else if (offset == 3) + byte = 0xe; + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcidata = data; + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr = + (unsigned long) ioaddr; + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe = + (PCI_IPCIBE_ICMD_IOWRITE << PCI_IPCIBE_ICMD_SHIFT) | byte; + while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); + /* clear by setting */ + tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; +} +unsigned short tx_ioinw(unsigned short *addr) +{ + unsigned long val; + __u32 ioaddr; + int offset; + int byte; + + ioaddr = (unsigned long) addr; + offset = ioaddr & 0x3; + if (offset == 0) + byte = 0x3; + else if (offset == 2) + byte = 0xc; + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr = + (unsigned long) ioaddr; + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe = + (PCI_IPCIBE_ICMD_IOREAD << PCI_IPCIBE_ICMD_SHIFT) | byte; + while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); + val = + le32_to_cpu(*(volatile u32 *) (ulong) & tx3927_pcicptr-> + ipcidata); + val = val & 0xffff; + /* clear by setting */ + tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; + return val; + +} +void tx_iooutw(unsigned long data, unsigned short *addr) +{ + __u32 ioaddr; + int offset; + int byte; + + data = data | (data << 16); + ioaddr = (unsigned long) addr; + offset = ioaddr & 0x3; + if (offset == 0) + byte = 0x3; + else if (offset == 2) + byte = 0xc; + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcidata = data; + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr = + (unsigned long) ioaddr; + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe = + (PCI_IPCIBE_ICMD_IOWRITE << PCI_IPCIBE_ICMD_SHIFT) | byte; + while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); + /* clear by setting */ + tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; +} +unsigned long tx_ioinl(unsigned int *addr) +{ + unsigned long val; + __u32 ioaddr; + + ioaddr = (unsigned long) addr; + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr = + (unsigned long) ioaddr; + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe = + (PCI_IPCIBE_ICMD_IOREAD << PCI_IPCIBE_ICMD_SHIFT) | + PCI_IPCIBE_IBE_LONG; + while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); + val = + le32_to_cpu(*(volatile u32 *) (ulong) & tx3927_pcicptr-> + ipcidata); + /* clear by setting */ + tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; + return val; +} +void tx_iooutl(unsigned long data, unsigned int *addr) +{ + __u32 ioaddr; + + ioaddr = (unsigned long) addr; + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcidata = + cpu_to_le32(data); + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipciaddr = + (unsigned long) ioaddr; + *(volatile u32 *) (ulong) & tx3927_pcicptr->ipcibe = + (PCI_IPCIBE_ICMD_IOWRITE << PCI_IPCIBE_ICMD_SHIFT) | + PCI_IPCIBE_IBE_LONG; + while (!(tx3927_pcicptr->istat & PCI_ISTAT_IDICC)); + /* clear by setting */ + tx3927_pcicptr->istat |= PCI_ISTAT_IDICC; +} +void tx_insbyte(unsigned char *addr, void *buffer, unsigned int count) +{ + unsigned char *ptr = (unsigned char *) buffer; + + while (count--) { + *ptr++ = tx_ioinb(addr); + } +} +void tx_insword(unsigned short *addr, void *buffer, unsigned int count) +{ + unsigned short *ptr = (unsigned short *) buffer; + + while (count--) { + *ptr++ = tx_ioinw(addr); + } +} +void tx_inslong(unsigned int *addr, void *buffer, unsigned int count) +{ + unsigned long *ptr = (unsigned long *) buffer; + + while (count--) { + *ptr++ = tx_ioinl(addr); + } +} +void tx_outsbyte(unsigned char *addr, void *buffer, unsigned int count) +{ + unsigned char *ptr = (unsigned char *) buffer; + + while (count--) { + tx_iooutb(*ptr++, addr); + } +} +void tx_outsword(unsigned short *addr, void *buffer, unsigned int count) +{ + unsigned short *ptr = (unsigned short *) buffer; + + while (count--) { + tx_iooutw(*ptr++, addr); + } +} +void tx_outslong(unsigned int *addr, void *buffer, unsigned int count) +{ + unsigned long *ptr = (unsigned long *) buffer; + + while (count--) { + tx_iooutl(*ptr++, addr); + } +} +#endif diff -Nru a/arch/mips/pci/ops-ocelot.c b/arch/mips/pci/ops-ocelot.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/ops-ocelot.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,1056 @@ +/* + * BRIEF MODULE DESCRIPTION + * Galileo Evaluation Boards PCI support. + * + * The general-purpose functions to read/write and configure the GT64120A's + * PCI registers (function names start with pci0 or pci1) are either direct + * copies of functions written by Galileo Technology, or are modifications + * of their functions to work with Linux 2.4 vs Linux 2.2. These functions + * are Copyright - Galileo Technology. + * + * Other functions are derived from other MIPS PCI implementations, or were + * written by RidgeRun, Inc, Copyright (C) 2000 RidgeRun, Inc. + * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com + * + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define SELF 0 + +/* + * These functions and structures provide the BIOS scan and mapping of the PCI + * devices. + */ + +#define MAX_PCI_DEVS 10 + +struct pci_device { + u32 slot; + u32 BARtype[6]; + u32 BARsize[6]; +}; + +static void __init scan_and_initialize_pci(void); +static u32 __init scan_pci_bus(struct pci_device *pci_devices); +static void __init allocate_pci_space(struct pci_device *pci_devices); + +/* + * The functions that actually read and write to the controller. + * + * Copied from or modified from Galileo Technology code. + */ +static unsigned int pci0ReadConfigReg(int offset, struct pci_dev *device); +static void pci0WriteConfigReg(unsigned int offset, + struct pci_dev *device, unsigned int data); +static unsigned int pci1ReadConfigReg(int offset, struct pci_dev *device); +static void pci1WriteConfigReg(unsigned int offset, + struct pci_dev *device, unsigned int data); + +static void pci0MapIOspace(unsigned int pci0IoBase, + unsigned int pci0IoLength); +static void pci1MapIOspace(unsigned int pci1IoBase, + unsigned int pci1IoLength); +static void pci0MapMemory0space(unsigned int pci0Mem0Base, + unsigned int pci0Mem0Length); +static void pci1MapMemory0space(unsigned int pci1Mem0Base, + unsigned int pci1Mem0Length); +static void pci0MapMemory1space(unsigned int pci0Mem1Base, + unsigned int pci0Mem1Length); +static void pci1MapMemory1space(unsigned int pci1Mem1Base, + unsigned int pci1Mem1Length); +static unsigned int pci0GetIOspaceBase(void); +static unsigned int pci0GetIOspaceSize(void); +static unsigned int pci0GetMemory0Base(void); +static unsigned int pci0GetMemory0Size(void); +static unsigned int pci0GetMemory1Base(void); +static unsigned int pci0GetMemory1Size(void); +static unsigned int pci1GetIOspaceBase(void); +static unsigned int pci1GetIOspaceSize(void); +static unsigned int pci1GetMemory0Base(void); +static unsigned int pci1GetMemory0Size(void); +static unsigned int pci1GetMemory1Base(void); +static unsigned int pci1GetMemory1Size(void); + + +/* Functions to implement "pci ops" */ +static int galileo_pcibios_read(struct pci_bus *bus, unsigned int devfn, + int offset, int size, u32 * val); +static int galileo_pcibios_write(struct pci_bus *bus, unsigned int devfn, + int offset, int size, u32 val); +static void galileo_pcibios_set_master(struct pci_dev *dev); + +/* + * General-purpose PCI functions. + */ + +/* + * pci0MapIOspace - Maps PCI0 IO space for the master. + * Inputs: base and length of pci0Io + */ + +static void pci0MapIOspace(unsigned int pci0IoBase, + unsigned int pci0IoLength) +{ + unsigned int pci0IoTop = + (unsigned int) (pci0IoBase + pci0IoLength); + + if (pci0IoLength == 0) + pci0IoTop++; + + pci0IoBase = (unsigned int) (pci0IoBase >> 21); + pci0IoTop = (unsigned int) (((pci0IoTop - 1) & 0x0fffffff) >> 21); + GT_WRITE(GT_PCI0IOLD_OFS, pci0IoBase); + GT_WRITE(GT_PCI0IOHD_OFS, pci0IoTop); +} + +/* + * pci1MapIOspace - Maps PCI1 IO space for the master. + * Inputs: base and length of pci1Io + */ + +static void pci1MapIOspace(unsigned int pci1IoBase, + unsigned int pci1IoLength) +{ + unsigned int pci1IoTop = + (unsigned int) (pci1IoBase + pci1IoLength); + + if (pci1IoLength == 0) + pci1IoTop++; + + pci1IoBase = (unsigned int) (pci1IoBase >> 21); + pci1IoTop = (unsigned int) (((pci1IoTop - 1) & 0x0fffffff) >> 21); + GT_WRITE(GT_PCI1IOLD_OFS, pci1IoBase); + GT_WRITE(GT_PCI1IOHD_OFS, pci1IoTop); +} + +/* + * pci0MapMemory0space - Maps PCI0 memory0 space for the master. + * Inputs: base and length of pci0Mem0 + */ + +static void pci0MapMemory0space(unsigned int pci0Mem0Base, + unsigned int pci0Mem0Length) +{ + unsigned int pci0Mem0Top = pci0Mem0Base + pci0Mem0Length; + + if (pci0Mem0Length == 0) + pci0Mem0Top++; + + pci0Mem0Base = pci0Mem0Base >> 21; + pci0Mem0Top = ((pci0Mem0Top - 1) & 0x0fffffff) >> 21; + GT_WRITE(GT_PCI0M0LD_OFS, pci0Mem0Base); + GT_WRITE(GT_PCI0M0HD_OFS, pci0Mem0Top); +} + +/* + * pci1MapMemory0space - Maps PCI1 memory0 space for the master. + * Inputs: base and length of pci1Mem0 + */ + +static void pci1MapMemory0space(unsigned int pci1Mem0Base, + unsigned int pci1Mem0Length) +{ + unsigned int pci1Mem0Top = pci1Mem0Base + pci1Mem0Length; + + if (pci1Mem0Length == 0) + pci1Mem0Top++; + + pci1Mem0Base = pci1Mem0Base >> 21; + pci1Mem0Top = ((pci1Mem0Top - 1) & 0x0fffffff) >> 21; + GT_WRITE(GT_PCI1M0LD_OFS, pci1Mem0Base); + GT_WRITE(GT_PCI1M0HD_OFS, pci1Mem0Top); +} + +/* + * pci0MapMemory1space - Maps PCI0 memory1 space for the master. + * Inputs: base and length of pci0Mem1 + */ + +static void pci0MapMemory1space(unsigned int pci0Mem1Base, + unsigned int pci0Mem1Length) +{ + unsigned int pci0Mem1Top = pci0Mem1Base + pci0Mem1Length; + + if (pci0Mem1Length == 0) + pci0Mem1Top++; + + pci0Mem1Base = pci0Mem1Base >> 21; + pci0Mem1Top = ((pci0Mem1Top - 1) & 0x0fffffff) >> 21; + GT_WRITE(GT_PCI0M1LD_OFS, pci0Mem1Base); + GT_WRITE(GT_PCI0M1HD_OFS, pci0Mem1Top); + +} + +/* + * pci1MapMemory1space - Maps PCI1 memory1 space for the master. + * Inputs: base and length of pci1Mem1 + */ + +static void pci1MapMemory1space(unsigned int pci1Mem1Base, + unsigned int pci1Mem1Length) +{ + unsigned int pci1Mem1Top = pci1Mem1Base + pci1Mem1Length; + + if (pci1Mem1Length == 0) + pci1Mem1Top++; + + pci1Mem1Base = pci1Mem1Base >> 21; + pci1Mem1Top = ((pci1Mem1Top - 1) & 0x0fffffff) >> 21; + GT_WRITE(GT_PCI1M1LD_OFS, pci1Mem1Base); + GT_WRITE(GT_PCI1M1HD_OFS, pci1Mem1Top); +} + +/* + * pci0GetIOspaceBase - Return PCI0 IO Base Address. + * Inputs: N/A + * Returns: PCI0 IO Base Address. + */ + +static unsigned int pci0GetIOspaceBase(void) +{ + unsigned int base; + GT_READ(GT_PCI0IOLD_OFS, &base); + base = base << 21; + return base; +} + +/* + * pci0GetIOspaceSize - Return PCI0 IO Bar Size. + * Inputs: N/A + * Returns: PCI0 IO Bar Size. + */ + +static unsigned int pci0GetIOspaceSize(void) +{ + unsigned int top, base, size; + GT_READ(GT_PCI0IOLD_OFS, &base); + base = base << 21; + GT_READ(GT_PCI0IOHD_OFS, &top); + top = (top << 21); + size = ((top - base) & 0xfffffff); + size = size | 0x1fffff; + return (size + 1); +} + +/* + * pci0GetMemory0Base - Return PCI0 Memory 0 Base Address. + * Inputs: N/A + * Returns: PCI0 Memory 0 Base Address. + */ + +static unsigned int pci0GetMemory0Base(void) +{ + unsigned int base; + GT_READ(GT_PCI0M0LD_OFS, &base); + base = base << 21; + return base; +} + +/* + * pci0GetMemory0Size - Return PCI0 Memory 0 Bar Size. + * Inputs: N/A + * Returns: PCI0 Memory 0 Bar Size. + */ + +static unsigned int pci0GetMemory0Size(void) +{ + unsigned int top, base, size; + GT_READ(GT_PCI0M0LD_OFS, &base); + base = base << 21; + GT_READ(GT_PCI0M0HD_OFS, &top); + top = (top << 21); + size = ((top - base) & 0xfffffff); + size = size | 0x1fffff; + return (size + 1); +} + +/* + * pci0GetMemory1Base - Return PCI0 Memory 1 Base Address. + * Inputs: N/A + * Returns: PCI0 Memory 1 Base Address. + */ + +static unsigned int pci0GetMemory1Base(void) +{ + unsigned int base; + GT_READ(GT_PCI0M1LD_OFS, &base); + base = base << 21; + return base; +} + +/* + * pci0GetMemory1Size - Return PCI0 Memory 1 Bar Size. + * Inputs: N/A + * Returns: PCI0 Memory 1 Bar Size. + */ + +static unsigned int pci0GetMemory1Size(void) +{ + unsigned int top, base, size; + GT_READ(GT_PCI0M1LD_OFS, &base); + base = base << 21; + GT_READ(GT_PCI0M1HD_OFS, &top); + top = (top << 21); + size = ((top - base) & 0xfffffff); + size = size | 0x1fffff; + return (size + 1); +} + +/* + * pci1GetIOspaceBase - Return PCI1 IO Base Address. + * Inputs: N/A + * Returns: PCI1 IO Base Address. + */ + +static unsigned int pci1GetIOspaceBase(void) +{ + unsigned int base; + GT_READ(GT_PCI1IOLD_OFS, &base); + base = base << 21; + return base; +} + +/* + * pci1GetIOspaceSize - Return PCI1 IO Bar Size. + * Inputs: N/A + * Returns: PCI1 IO Bar Size. + */ + +static unsigned int pci1GetIOspaceSize(void) +{ + unsigned int top, base, size; + GT_READ(GT_PCI1IOLD_OFS, &base); + base = base << 21; + GT_READ(GT_PCI1IOHD_OFS, &top); + top = (top << 21); + size = ((top - base) & 0xfffffff); + size = size | 0x1fffff; + return (size + 1); +} + +/* + * pci1GetMemory0Base - Return PCI1 Memory 0 Base Address. + * Inputs: N/A + * Returns: PCI1 Memory 0 Base Address. + */ + +static unsigned int pci1GetMemory0Base(void) +{ + unsigned int base; + GT_READ(GT_PCI1M0LD_OFS, &base); + base = base << 21; + return base; +} + +/* + * pci1GetMemory0Size - Return PCI1 Memory 0 Bar Size. + * Inputs: N/A + * Returns: PCI1 Memory 0 Bar Size. + */ + +static unsigned int pci1GetMemory0Size(void) +{ + unsigned int top, base, size; + GT_READ(GT_PCI1M1LD_OFS, &base); + base = base << 21; + GT_READ(GT_PCI1M1HD_OFS, &top); + top = (top << 21); + size = ((top - base) & 0xfffffff); + size = size | 0x1fffff; + return (size + 1); +} + +/* + * pci1GetMemory1Base - Return PCI1 Memory 1 Base Address. + * Inputs: N/A + * Returns: PCI1 Memory 1 Base Address. + */ + +static unsigned int pci1GetMemory1Base(void) +{ + unsigned int base; + GT_READ(GT_PCI1M1LD_OFS, &base); + base = base << 21; + return base; +} + +/* + * pci1GetMemory1Size - Return PCI1 Memory 1 Bar Size. + * Inputs: N/A + * Returns: PCI1 Memory 1 Bar Size. + */ + +static unsigned int pci1GetMemory1Size(void) +{ + unsigned int top, base, size; + GT_READ(GT_PCI1M1LD_OFS, &base); + base = base << 21; + GT_READ(GT_PCI1M1HD_OFS, &top); + top = (top << 21); + size = ((top - base) & 0xfffffff); + size = size | 0x1fffff; + return (size + 1); +} + + + +/* + * pci_range_ck - + * + * Check if the pci device that are trying to access does really exists + * on the evaluation board. + * + * Inputs : + * bus - bus number (0 for PCI 0 ; 1 for PCI 1) + * dev - number of device on the specific pci bus + * + * Outpus : + * 0 - if OK , 1 - if failure + */ +static __inline__ int pci_range_ck(unsigned char bus, unsigned char dev) +{ + /* + * We don't even pretend to handle other busses than bus 0 correctly. + * Accessing device 31 crashes the CP7000 for some reason. + */ + if ((bus == 0) && (dev != 31)) + return 0; + return -1; +} + +/* + * pciXReadConfigReg - Read from a PCI configuration register + * - Make sure the GT is configured as a master before + * reading from another device on the PCI. + * - The function takes care of Big/Little endian conversion. + * INPUTS: regOffset: The register offset as it apears in the GT spec (or PCI + * spec) + * pciDevNum: The device number needs to be addressed. + * RETURNS: data , if the data == 0xffffffff check the master abort bit in the + * cause register to make sure the data is valid + * + * Configuration Address 0xCF8: + * + * 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number + * |congif|Reserved| Bus |Device|Function|Register|00| + * |Enable| |Number|Number| Number | Number | | <=field Name + * + */ +static unsigned int pci0ReadConfigReg(int offset, struct pci_dev *device) +{ + unsigned int DataForRegCf8; + unsigned int data; + + DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) | + (PCI_FUNC(device->devfn) << 8) | + (offset & ~0x3)) | 0x80000000; + GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8); + + /* + * The casual observer might wonder why the READ is duplicated here, + * rather than immediately following the WRITE, and just have the swap + * in the "if". That's because there is a latency problem with trying + * to read immediately after setting up the address register. The "if" + * check gives enough time for the address to stabilize, so the READ + * can work. + */ + if (PCI_SLOT(device->devfn) == SELF) { /* This board */ + GT_READ(GT_PCI0_CFGDATA_OFS, &data); + return data; + } else { /* The PCI is working in LE Mode so swap the Data. */ + GT_READ(GT_PCI0_CFGDATA_OFS, &data); + return cpu_to_le32(data); + } +} + +static unsigned int pci1ReadConfigReg(int offset, struct pci_dev *device) +{ + unsigned int DataForRegCf8; + unsigned int data; + + DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) | + (PCI_FUNC(device->devfn) << 8) | + (offset & ~0x3)) | 0x80000000; + /* + * The casual observer might wonder why the READ is duplicated here, + * rather than immediately following the WRITE, and just have the + * swap in the "if". That's because there is a latency problem + * with trying to read immediately after setting up the address + * register. The "if" check gives enough time for the address + * to stabilize, so the READ can work. + */ + if (PCI_SLOT(device->devfn) == SELF) { /* This board */ + /* when configurating our own PCI 1 L-unit the access is through + the PCI 0 interface with reg number = reg number + 0x80 */ + DataForRegCf8 |= 0x80; + GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8); + } else { /* The PCI is working in LE Mode so swap the Data. */ + GT_WRITE(GT_PCI1_CFGADDR_OFS, DataForRegCf8); + } + if (PCI_SLOT(device->devfn) == SELF) { /* This board */ + GT_READ(GT_PCI0_CFGDATA_OFS, &data); + return data; + } else { + GT_READ(GT_PCI1_CFGDATA_OFS, &data); + return cpu_to_le32(data); + } +} + + + +/* + * pciXWriteConfigReg - Write to a PCI configuration register + * - Make sure the GT is configured as a master before + * writingto another device on the PCI. + * - The function takes care of Big/Little endian conversion. + * Inputs: unsigned int regOffset: The register offset as it apears in the + * GT spec + * (or any other PCI device spec) + * pciDevNum: The device number needs to be addressed. + * + * Configuration Address 0xCF8: + * + * 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number + * |congif|Reserved| Bus |Device|Function|Register|00| + * |Enable| |Number|Number| Number | Number | | <=field Name + * + */ +static void pci0WriteConfigReg(unsigned int offset, + struct pci_dev *device, unsigned int data) +{ + unsigned int DataForRegCf8; + + DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) | + (PCI_FUNC(device->devfn) << 8) | + (offset & ~0x3)) | 0x80000000; + GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8); + if (PCI_SLOT(device->devfn) == SELF) { /* This board */ + GT_WRITE(GT_PCI0_CFGDATA_OFS, data); + } else { /* configuration Transaction over the pci. */ + /* The PCI is working in LE Mode so swap the Data. */ + GT_WRITE(GT_PCI0_CFGDATA_OFS, le32_to_cpu(data)); + } +} + +static void pci1WriteConfigReg(unsigned int offset, + struct pci_dev *device, unsigned int data) +{ + unsigned int DataForRegCf8; + + DataForRegCf8 = ((PCI_SLOT(device->devfn) << 11) | + (PCI_FUNC(device->devfn) << 8) | + (offset & ~0x3)) | 0x80000000; + /* + * There is a latency problem + * with trying to read immediately after setting up the address + * register. The "if" check gives enough time for the address + * to stabilize, so the WRITE can work. + */ + if (PCI_SLOT(device->devfn) == SELF) { /* This board */ + /* + * when configurating our own PCI 1 L-unit the access is through + * the PCI 0 interface with reg number = reg number + 0x80 + */ + DataForRegCf8 |= 0x80; + GT_WRITE(GT_PCI0_CFGADDR_OFS, DataForRegCf8); + } else { /* configuration Transaction over the pci. */ + /* The PCI is working in LE Mode so swap the Data. */ + GT_WRITE(GT_PCI1_CFGADDR_OFS, DataForRegCf8); + } + if (PCI_SLOT(device->devfn) == SELF) { /* This board */ + GT_WRITE(GT_PCI0_CFGDATA_OFS, data); + } else { /* configuration Transaction over the pci. */ + GT_WRITE(GT_PCI1_CFGADDR_OFS, le32_to_cpu(data)); + } +} + + +/* + * galileo_pcibios_(read/write) - + * + * reads/write a dword/word/byte register from the configuration space + * of a device. + * + * Inputs : + * bus - bus number + * devfn - device function index + * offset - register offset in the configuration space + * size - size of value (1=byte,2=word,4-dword) + * val - value to be written / read + * + * Outputs : + * PCIBIOS_SUCCESSFUL when operation was succesfull + * PCIBIOS_DEVICE_NOT_FOUND when the bus or dev is errorneous + * PCIBIOS_BAD_REGISTER_NUMBER when accessing non aligned + */ + +static int galileo_pcibios_read(struct pci_bus *bus, unsigned int devfn, + int offset, int size, u32 * val) +{ + int dev, busnum; + + busnum = bus->number; + dev = PCI_SLOT(devfn); + + if (pci_range_ck(busnum, dev)) { + if (size == 1) + *val = (u8) 0xff; + else if (size == 2) + *val = (u16) 0xffff; + else if (size == 4) + *val = 0xffffffff; + return PCIBIOS_DEVICE_NOT_FOUND; + } + if ((size == 2) && (offset & 0x1)) + return PCIBIOS_BAD_REGISTER_NUMBER; + else if ((size == 4) && (offset & 0x3)) + return PCIBIOS_BAD_REGISTER_NUMBER; + + if (busnum == 0) { + if (size == 1) { + *val = (u8) (pci0ReadConfigReg(offset, bus->dev) >> + ((offset & ~0x3) * 8)); + } else if (size == 2) { + *val = + (u16) (pci0ReadConfigReg(offset, bus->dev) >> + ((offset & ~0x3) * 8)); + } else if (size == 4) { + *val = pci0ReadConfigReg(offset, bus->dev); + } + } + + /* + * This is so that the upper PCI layer will get the correct return + * value if we're not attached to anything. + */ + switch (size) { + case 1: + if ((offset == 0xe) && (*val == (u8) 0xff)) { + u32 MasterAbort; + GT_READ(GT_INTRCAUSE_OFS, &MasterAbort); + if (MasterAbort & 0x40000) { + GT_WRITE(GT_INTRCAUSE_OFS, + (MasterAbort & 0xfffbffff)); + return PCIBIOS_DEVICE_NOT_FOUND; + } + } + break; + case 4: + if ((offset == 0) && (*val == 0xffffffff)) { + return PCIBIOS_DEVICE_NOT_FOUND; + } + break} + return PCIBIOS_SUCCESSFUL; +} + +static int galileo_pcibios_write(struct pci_bus *bus, unsigned int devfn, + int offset, int size, u32 val) +{ + int dev, busnum; + unsigned long tmp; + + busnum = bus->number; + dev = PCI_SLOT(devfn); + + if (pci_range_ck(busnum, dev)) + return PCIBIOS_DEVICE_NOT_FOUND; + if (size == 4) { + if (offset & 0x3) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (busnum == 0) + pci0WriteConfigReg(offset, bus->dev, val); + //if (busnum == 1) pci1WriteConfigReg (offset,bus->dev,val); + return PCIBIOS_SUCCESSFUL; + } + if ((size == 2) && (offset & 0x1)) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (busnum == 0) { + tmp = pci0ReadConfigReg(offset, bus->dev); + //if (busnum == 1) tmp = pci1ReadConfigReg (offset,bus->dev); + if (size == 1) { + if ((offset % 4) == 0) + tmp = + (tmp & 0xffffff00) | (val & (u8) 0xff); + if ((offset % 4) == 1) + tmp = + (tmp & 0xffff00ff) | ((val & (u8) 0xff) + << 8); + if ((offset % 4) == 2) + tmp = + (tmp & 0xff00ffff) | ((val & (u8) 0xff) + << 16); + if ((offset % 4) == 3) + tmp = + (tmp & 0x00ffffff) | ((val & (u8) 0xff) + << 24); + } else if (size == 2) { + if ((offset % 4) == 0) + tmp = + (tmp & 0xffff0000) | (val & (u16) + 0xffff); + if ((offset % 4) == 2) + tmp = + (tmp & 0x0000ffff) | + ((val & (u16) 0xffff) << 16); + } + if (busnum == 0) + pci0WriteConfigReg(offset, bus->dev, tmp); + //if (busnum == 1) pci1WriteConfigReg (offset,bus->dev,tmp); + } + return PCIBIOS_SUCCESSFUL; +} + +static void galileo_pcibios_set_master(struct pci_dev *dev) +{ + u16 cmd; + + galileo_pcibios_read(dev->bus, dev->devfn, PCI_COMMAND, 2, &cmd); + cmd |= PCI_COMMAND_MASTER; + galileo_pcibios_write(dev->bus, dev->devfn, PCI_COMMAND, 2, cmd); +} + +/* Externally-expected functions. Do not change function names */ + +int pcibios_enable_resources(struct pci_dev *dev) +{ + u16 cmd, old_cmd; + u8 tmp1; + int idx; + struct resource *r; + + galileo_pcibios_read(dev->bus, dev->devfn, PCI_COMMAND, 2, &cmd); + old_cmd = cmd; + for (idx = 0; idx < 6; idx++) { + r = &dev->resource[idx]; + if (!r->start && r->end) { + printk(KERN_ERR + "PCI: Device %s not available because of " + "resource collisions\n", dev->slot_name); + return -EINVAL; + } + if (r->flags & IORESOURCE_IO) + cmd |= PCI_COMMAND_IO; + if (r->flags & IORESOURCE_MEM) + cmd |= PCI_COMMAND_MEMORY; + } + if (cmd != old_cmd) { + galileo_pcibios_write(dev->bus, dev->devfn, PCI_COMMAND, 2, + cmd); + } + + /* + * Let's fix up the latency timer and cache line size here. Cache + * line size = 32 bytes / sizeof dword (4) = 8. + * Latency timer must be > 8. 32 is random but appears to work. + */ + galileo_pcibios_read(dev->bus, dev->devfn, PCI_CACHE_LINE_SIZE, 1, + &tmp1); + if (tmp1 != 8) { + printk(KERN_WARNING + "PCI setting cache line size to 8 from " "%d\n", + tmp1); + galileo_pcibios_write(dev->bus, dev->devfn, + PCI_CACHE_LINE_SIZE, 1, 8); + } + galileo_pcibios_read(dev->bus, dev->devfn, PCI_LATENCY_TIMER, 1, + &tmp1); + if (tmp1 < 32) { + printk(KERN_WARNING + "PCI setting latency timer to 32 from %d\n", tmp1); + galileo_pcibios_write(dev->bus, dev->devfn, + PCI_LATENCY_TIMER, 1, 32); + } + + return 0; +} + +int pcibios_enable_device(struct pci_dev *dev, int mask) +{ + return pcibios_enable_resources(dev); +} + +void pcibios_align_resource(void *data, struct resource *res, + unsigned long size, unsigned long align) +{ + struct pci_dev *dev = data; + + if (res->flags & IORESOURCE_IO) { + unsigned long start = res->start; + + /* We need to avoid collisions with `mirrored' VGA ports + and other strange ISA hardware, so we always want the + addresses kilobyte aligned. */ + if (size > 0x100) { + printk(KERN_ERR "PCI: I/O Region %s/%d too large" + " (%ld bytes)\n", dev->slot_name, + dev->resource - res, size); + } + + start = (start + 1024 - 1) & ~(1024 - 1); + res->start = start; + } +} + +struct pci_ops galileo_pci_ops = { + .read = galileo_pcibios_read, + .write = galileo_pcibios_write, +}; + +struct pci_fixup pcibios_fixups[] = { + {0} +}; + +void __devinit pcibios_fixup_bus(struct pci_bus *c) +{ + gt64120_board_pcibios_fixup_bus(c); +} + +/* + * This code was derived from Galileo Technology's example + * and significantly reworked. + * + * This is very simple. It does not scan multiple function devices. It does + * not scan behind bridges. Those would be simple to implement, but we don't + * currently need this. + */ + +static void __init scan_and_initialize_pci(void) +{ + struct pci_device pci_devices[MAX_PCI_DEVS]; + + if (scan_pci_bus(pci_devices)) { + allocate_pci_space(pci_devices); + } +} + +/* + * This is your basic PCI scan. It goes through each slot and checks to + * see if there's something that responds. If so, then get the size and + * type of each of the responding BARs. Save them for later. + */ + +static u32 __init scan_pci_bus(struct pci_device *pci_devices) +{ + u32 arrayCounter = 0; + u32 memType; + u32 memSize; + u32 pci_slot, bar; + u32 id; + u32 c18RegValue; + struct pci_dev device; + + /* + * According to PCI REV 2.1 MAX agents on the bus are 21. + * We don't bother scanning ourselves (slot 0). + */ + for (pci_slot = 1; pci_slot < 22; pci_slot++) { + + device.devfn = PCI_DEVFN(pci_slot, 0); + id = pci0ReadConfigReg(PCI_VENDOR_ID, &device); + + /* + * Check for a PCI Master Abort (nothing responds in the + * slot) + */ + GT_READ(GT_INTRCAUSE_OFS, &c18RegValue); + /* + * Clearing bit 18 of in the Cause Register 0xc18 by + * writting 0. + */ + GT_WRITE(GT_INTRCAUSE_OFS, (c18RegValue & 0xfffbffff)); + if ((id != 0xffffffff) && !(c18RegValue & 0x40000)) { + pci_devices[arrayCounter].slot = pci_slot; + for (bar = 0; bar < 6; bar++) { + memType = + pci0ReadConfigReg(PCI_BASE_ADDRESS_0 + + (bar * 4), &device); + pci_devices[arrayCounter].BARtype[bar] = + memType & 1; + pci0WriteConfigReg(PCI_BASE_ADDRESS_0 + + (bar * 4), &device, + 0xffffffff); + memSize = + pci0ReadConfigReg(PCI_BASE_ADDRESS_0 + + (bar * 4), &device); + if (memType & 1) { /* IO space */ + pci_devices[arrayCounter]. + BARsize[bar] = + ~(memSize & 0xfffffffc) + 1; + } else { /* memory space */ + pci_devices[arrayCounter]. + BARsize[bar] = + ~(memSize & 0xfffffff0) + 1; + } + } /* BAR counter */ + + arrayCounter++; + } + /* found a device */ + } /* slot counter */ + + if (arrayCounter < MAX_PCI_DEVS) + pci_devices[arrayCounter].slot = -1; + + return arrayCounter; +} + +/* + * This function goes through the list of devices and allocates the BARs in + * either IO or MEM space. It does it in order of size, which will limit the + * amount of fragmentation we have in the IO and MEM spaces. + */ + +static void __init allocate_pci_space(struct pci_device *pci_devices) +{ + u32 count, maxcount, bar; + u32 maxSize, maxDevice, maxBAR; + u32 alignto; + u32 base; + u32 pci0_mem_base = pci0GetMemory0Base(); + u32 pci0_io_base = pci0GetIOspaceBase(); + struct pci_dev device; + + /* How many PCI devices do we have? */ + maxcount = MAX_PCI_DEVS; + for (count = 0; count < MAX_PCI_DEVS; count++) { + if (pci_devices[count].slot == -1) { + maxcount = count; + break; + } + } + + do { + /* Find the largest size BAR we need to allocate */ + maxSize = 0; + for (count = 0; count < maxcount; count++) { + for (bar = 0; bar < 6; bar++) { + if (pci_devices[count].BARsize[bar] > + maxSize) { + maxSize = + pci_devices[count]. + BARsize[bar]; + maxDevice = count; + maxBAR = bar; + } + } + } + + /* + * We've found the largest BAR. Allocate it into IO or + * mem space. We don't idiot check the bases to make + * sure they haven't overflowed the current size for that + * aperture. + * Don't bother to enable the device's IO or MEM space here. + * That will be done in pci_enable_resources if the device is + * activated by a driver. + */ + if (maxSize) { + device.devfn = + PCI_DEVFN(pci_devices[maxDevice].slot, 0); + if (pci_devices[maxDevice].BARtype[maxBAR] == 1) { + alignto = max(0x1000U, maxSize); + base = ALIGN(pci0_io_base, alignto); + pci0WriteConfigReg(PCI_BASE_ADDRESS_0 + + (maxBAR * 4), &device, + base | 0x1); + pci0_io_base = base + alignto; + } else { + alignto = max(0x1000U, maxSize); + base = ALIGN(pci0_mem_base, alignto); + pci0WriteConfigReg(PCI_BASE_ADDRESS_0 + + (maxBAR * 4), &device, + base); + pci0_mem_base = base + alignto; + } + /* + * This entry is finished. Remove it from the list + * we'll scan. + */ + pci_devices[maxDevice].BARsize[maxBAR] = 0; + } + } while (maxSize); +} + +static int __init pcibios_init(void) +{ + u32 tmp; + struct pci_dev controller; + + controller.devfn = SELF; + + GT_READ(GT_PCI0_CMD_OFS, &tmp); + GT_READ(GT_PCI0_BARE_OFS, &tmp); + + /* + * You have to enable bus mastering to configure any other + * card on the bus. + */ + tmp = pci0ReadConfigReg(PCI_COMMAND, &controller); + tmp |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_SERR; + pci0WriteConfigReg(PCI_COMMAND, &controller, tmp); + + /* This scans the PCI bus and sets up initial values. */ + scan_and_initialize_pci(); + + /* + * Reset PCI I/O and PCI MEM values to ones supported by EVM. + */ + ioport_resource.start = GT_PCI_IO_BASE; + ioport_resource.end = GT_PCI_IO_BASE + GT_PCI_IO_SIZE - 1; + iomem_resource.start = GT_PCI_MEM_BASE; + iomem_resource.end = GT_PCI_MEM_BASE + GT_PCI_MEM_BASE - 1; + + pci_scan_bus(0, &galileo_pci_ops, NULL); + + return 0; +} + +subsys_initcall(pcibios_init); + +/* + * for parsing "pci=" kernel boot arguments. + */ +char *pcibios_setup(char *str) +{ + printk(KERN_INFO "rr: pcibios_setup\n"); + /* Nothing to do for now. */ + + return str; +} + +unsigned __init int pcibios_assign_all_busses(void) +{ + return 1; +} diff -Nru a/arch/mips/pci/ops-vrc4173.c b/arch/mips/pci/ops-vrc4173.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/ops-vrc4173.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,120 @@ +/* + * FILE NAME + * arch/mips/vr41xx/nec-eagle/vrc4173.c + * + * BRIEF MODULE DESCRIPTION + * Pre-setup for NEC VRC4173. + * + * Author: Yoichi Yuasa + * yyuasa@mvista.com or source@mvista.com + * + * Copyright 2001,2002 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include + +#include +#include +#include + +#define PCI_CONFIG_ADDR KSEG1ADDR(0x0f000c18) +#define PCI_CONFIG_DATA KSEG1ADDR(0x0f000c14) + +static inline void config_writeb(u8 reg, u8 val) +{ + u32 data; + int shift; + + writel((1UL << 0x1e) | (reg & 0xfc), PCI_CONFIG_ADDR); + data = readl(PCI_CONFIG_DATA); + + shift = (reg & 3) << 3; + data &= ~(0xff << shift); + data |= (((u32) val) << shift); + + writel(data, PCI_CONFIG_DATA); +} + +static inline u16 config_readw(u8 reg) +{ + u32 data; + + writel(((1UL << 30) | (reg & 0xfc)), PCI_CONFIG_ADDR); + data = readl(PCI_CONFIG_DATA); + + return (u16) (data >> ((reg & 2) << 3)); +} + +static inline u32 config_readl(u8 reg) +{ + writel(((1UL << 30) | (reg & 0xfc)), PCI_CONFIG_ADDR); + + return readl(PCI_CONFIG_DATA); +} + +static inline void config_writel(u8 reg, u32 val) +{ + writel((1UL << 0x1e) | (reg & 0xfc), PCI_CONFIG_ADDR); + writel(val, PCI_CONFIG_DATA); +} + +void __init vrc4173_preinit(void) +{ + u32 cmdsts, base; + u16 cmu_mask; + + + if ((config_readw(PCI_VENDOR_ID) == PCI_VENDOR_ID_NEC) && + (config_readw(PCI_DEVICE_ID) == PCI_DEVICE_ID_NEC_VRC4173)) { + /* + * Initialized NEC VRC4173 Bus Control Unit + */ + cmdsts = config_readl(PCI_COMMAND); + config_writel(PCI_COMMAND, + cmdsts | + PCI_COMMAND_IO | + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + + config_writeb(PCI_LATENCY_TIMER, 0x80); + + config_writel(PCI_BASE_ADDRESS_0, VR41XX_PCI_IO_START); + base = config_readl(PCI_BASE_ADDRESS_0); + base &= PCI_BASE_ADDRESS_IO_MASK; + config_writeb(0x40, 0x01); + + /* CARDU1 IDSEL = AD12, CARDU2 IDSEL = AD13 */ + config_writeb(0x41, 0); + + cmu_mask = 0x1000; + outw(cmu_mask, base + 0x040); + cmu_mask |= 0x0800; + outw(cmu_mask, base + 0x040); + + outw(0x000f, base + 0x042); /* Soft reset of CMU */ + cmu_mask |= 0x05e0; + outw(cmu_mask, base + 0x040); + cmu_mask = inw(base + 0x040); /* dummy read */ + outw(0x0000, base + 0x042); + } +} diff -Nru a/arch/mips/pci/pci-auto.c b/arch/mips/pci/pci-auto.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/pci-auto.c Tue Jul 1 18:44:39 2003 @@ -0,0 +1,518 @@ +/* + * PCI autoconfiguration library + * + * Author: Matt Porter + * + * Copyright 2000, 2001, 2002, 2003 MontaVista Software Inc. + * Copyright 2001 Bradley D. LaRonde + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +/* + * Modified for MIPS by Jun Sun, jsun@mvista.com + * + * . Simplify the interface between pci_auto and the rest: a single function. + * . Assign resources from low address to upper address. + * . change most int to u32. + * + * Further modified to include it as mips generic code, ppopov@mvista.com. + * + * 2001-10-26 Bradley D. LaRonde + * - Add a top_bus argument to the "early config" functions so that + * they can set a fake parent bus pointer to convince the underlying + * pci ops to use type 1 configuration for sub busses. + * - Set bridge base and limit registers correctly. + * - Align io and memory base properly before and after bridge setup. + * - Don't fall through to pci_setup_bars for bridge. + * - Reformat the debug output to look more like lspci's output. + * + * 2003-04-09 Yoichi Yuasa, Alice Hennessy, Jun Sun + * - Add cardbus bridge support, mostly copied from PPC + */ + +#include +#include +#include +#include + +#include + +#define DEBUG +#ifdef DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +/* + * These functions are used early on before PCI scanning is done + * and all of the pci_dev and pci_bus structures have been created. + */ +static struct pci_dev *fake_pci_dev(struct pci_channel *hose, + int top_bus, int busnr, int devfn) +{ + static struct pci_dev dev; + static struct pci_bus bus; + + dev.bus = &bus; + dev.sysdata = hose; + dev.devfn = devfn; + bus.number = busnr; + bus.ops = hose->pci_ops; + + if (busnr != top_bus) + /* Fake a parent bus structure. */ + bus.parent = &bus; + else + bus.parent = NULL; + + return &dev; +} + +#define EARLY_PCI_OP(rw, size, type) \ +int early_##rw##_config_##size(struct pci_channel *hose, \ + int top_bus, int bus, int devfn, int offset, type value) \ +{ \ + return pci_##rw##_config_##size( \ + fake_pci_dev(hose, top_bus, bus, devfn), \ + offset, value); \ +} + +EARLY_PCI_OP(read, byte, u8 *) + EARLY_PCI_OP(read, word, u16 *) + EARLY_PCI_OP(read, dword, u32 *) + EARLY_PCI_OP(write, byte, u8) + EARLY_PCI_OP(write, word, u16) + EARLY_PCI_OP(write, dword, u32) + +static struct resource *io_resource_inuse; +static struct resource *mem_resource_inuse; + +static u32 pciauto_lower_iospc; +static u32 pciauto_upper_iospc; + +static u32 pciauto_lower_memspc; +static u32 pciauto_upper_memspc; + +void __init +pciauto_setup_bars(struct pci_channel *hose, + int top_bus, + int current_bus, int pci_devfn, int bar_limit) +{ + u32 bar_response, bar_size, bar_value; + u32 bar, addr_mask, bar_nr = 0; + u32 *upper_limit; + u32 *lower_limit; + int found_mem64 = 0; + + for (bar = PCI_BASE_ADDRESS_0; bar <= bar_limit; bar += 4) { + /* Tickle the BAR and get the response */ + early_write_config_dword(hose, top_bus, + current_bus, + pci_devfn, bar, 0xffffffff); + early_read_config_dword(hose, top_bus, + current_bus, + pci_devfn, bar, &bar_response); + + /* If BAR is not implemented go to the next BAR */ + if (!bar_response) + continue; + + /* + * Workaround for a BAR that doesn't use its upper word, + * like the ALi 1535D+ PCI DC-97 Controller Modem (M5457). + * bdl + */ + if (!(bar_response & 0xffff0000)) + bar_response |= 0xffff0000; + + retry: + /* Check the BAR type and set our address mask */ + if (bar_response & PCI_BASE_ADDRESS_SPACE) { + addr_mask = PCI_BASE_ADDRESS_IO_MASK; + upper_limit = &pciauto_upper_iospc; + lower_limit = &pciauto_lower_iospc; + DBG(" I/O"); + } else { + if ((bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) + == PCI_BASE_ADDRESS_MEM_TYPE_64) + found_mem64 = 1; + + addr_mask = PCI_BASE_ADDRESS_MEM_MASK; + upper_limit = &pciauto_upper_memspc; + lower_limit = &pciauto_lower_memspc; + DBG(" Mem"); + } + + + /* Calculate requested size */ + bar_size = ~(bar_response & addr_mask) + 1; + + /* Allocate a base address */ + bar_value = + ((*lower_limit - 1) & ~(bar_size - 1)) + bar_size; + + if ((bar_value + bar_size) > *upper_limit) { + if (bar_response & PCI_BASE_ADDRESS_SPACE) { + if (io_resource_inuse->child) { + io_resource_inuse = + io_resource_inuse->child; + pciauto_lower_iospc = + io_resource_inuse->start; + pciauto_upper_iospc = + io_resource_inuse->end + 1; + goto retry; + } + + } else { + if (mem_resource_inuse->child) { + mem_resource_inuse = + mem_resource_inuse->child; + pciauto_lower_memspc = + mem_resource_inuse->start; + pciauto_upper_memspc = + mem_resource_inuse->end + 1; + goto retry; + } + } + DBG(" unavailable -- skipping\n"); + continue; + } + + /* Write it out and update our limit */ + early_write_config_dword(hose, top_bus, current_bus, + pci_devfn, bar, bar_value); + + *lower_limit = bar_value + bar_size; + + /* + * If we are a 64-bit decoder then increment to the + * upper 32 bits of the bar and force it to locate + * in the lower 4GB of memory. + */ + if (found_mem64) { + bar += 4; + early_write_config_dword(hose, top_bus, + current_bus, + pci_devfn, + bar, 0x00000000); + } + + DBG(" at 0x%.8x [size=0x%x]\n", bar_value, bar_size); + + bar_nr++; + } + +} + +void __init +pciauto_prescan_setup_bridge(struct pci_channel *hose, + int top_bus, + int current_bus, int pci_devfn, int sub_bus) +{ + /* Configure bus number registers */ + early_write_config_byte(hose, top_bus, current_bus, pci_devfn, + PCI_PRIMARY_BUS, current_bus); + early_write_config_byte(hose, top_bus, current_bus, pci_devfn, + PCI_SECONDARY_BUS, sub_bus + 1); + early_write_config_byte(hose, top_bus, current_bus, pci_devfn, + PCI_SUBORDINATE_BUS, 0xff); + + /* Align memory and I/O to 1MB and 4KB boundaries. */ + pciauto_lower_memspc = (pciauto_lower_memspc + (0x100000 - 1)) + & ~(0x100000 - 1); + pciauto_lower_iospc = (pciauto_lower_iospc + (0x1000 - 1)) + & ~(0x1000 - 1); + + /* Set base (lower limit) of address range behind bridge. */ + early_write_config_word(hose, top_bus, current_bus, pci_devfn, + PCI_MEMORY_BASE, + pciauto_lower_memspc >> 16); + early_write_config_byte(hose, top_bus, current_bus, pci_devfn, + PCI_IO_BASE, + (pciauto_lower_iospc & 0x0000f000) >> 8); + early_write_config_word(hose, top_bus, current_bus, pci_devfn, + PCI_IO_BASE_UPPER16, + pciauto_lower_iospc >> 16); + + /* We don't support prefetchable memory for now, so disable */ + early_write_config_word(hose, top_bus, current_bus, pci_devfn, + PCI_PREF_MEMORY_BASE, 0); + early_write_config_word(hose, top_bus, current_bus, pci_devfn, + PCI_PREF_MEMORY_LIMIT, 0); +} + +void __init +pciauto_postscan_setup_bridge(struct pci_channel *hose, + int top_bus, + int current_bus, int pci_devfn, int sub_bus) +{ + u32 temp; + + /* + * [jsun] we always bump up baselines a little, so that if there + * nothing behind P2P bridge, we don't wind up overlapping IO/MEM + * spaces. + */ + pciauto_lower_memspc += 1; + pciauto_lower_iospc += 1; + + /* Configure bus number registers */ + early_write_config_byte(hose, top_bus, current_bus, pci_devfn, + PCI_SUBORDINATE_BUS, sub_bus); + + /* Set upper limit of address range behind bridge. */ + early_write_config_word(hose, top_bus, current_bus, pci_devfn, + PCI_MEMORY_LIMIT, + pciauto_lower_memspc >> 16); + early_write_config_byte(hose, top_bus, current_bus, pci_devfn, + PCI_IO_LIMIT, + (pciauto_lower_iospc & 0x0000f000) >> 8); + early_write_config_word(hose, top_bus, current_bus, pci_devfn, + PCI_IO_LIMIT_UPPER16, + pciauto_lower_iospc >> 16); + + /* Align memory and I/O to 1MB and 4KB boundaries. */ + pciauto_lower_memspc = (pciauto_lower_memspc + (0x100000 - 1)) + & ~(0x100000 - 1); + pciauto_lower_iospc = (pciauto_lower_iospc + (0x1000 - 1)) + & ~(0x1000 - 1); + + /* Enable memory and I/O accesses, enable bus master */ + early_read_config_dword(hose, top_bus, current_bus, pci_devfn, + PCI_COMMAND, &temp); + early_write_config_dword(hose, top_bus, current_bus, pci_devfn, + PCI_COMMAND, + temp | PCI_COMMAND_IO | PCI_COMMAND_MEMORY + | PCI_COMMAND_MASTER); +} + +void __init +pciauto_prescan_setup_cardbus_bridge(struct pci_channel *hose, + int top_bus, + int current_bus, + int pci_devfn, int sub_bus) +{ + /* Configure bus number registers */ + early_write_config_byte(hose, top_bus, current_bus, pci_devfn, + PCI_PRIMARY_BUS, current_bus); + early_write_config_byte(hose, top_bus, current_bus, pci_devfn, + PCI_SECONDARY_BUS, sub_bus + 1); + early_write_config_byte(hose, top_bus, current_bus, pci_devfn, + PCI_SUBORDINATE_BUS, 0xff); + + /* Align memory and I/O to 4KB and 4 byte boundaries. */ + pciauto_lower_memspc = (pciauto_lower_memspc + (0x1000 - 1)) + & ~(0x1000 - 1); + pciauto_lower_iospc = (pciauto_lower_iospc + (0x4 - 1)) + & ~(0x4 - 1); + + early_write_config_dword(hose, top_bus, current_bus, pci_devfn, + PCI_CB_MEMORY_BASE_0, + pciauto_lower_memspc); + early_write_config_dword(hose, top_bus, current_bus, pci_devfn, + PCI_CB_IO_BASE_0, pciauto_lower_iospc); +} + +void __init +pciauto_postscan_setup_cardbus_bridge(struct pci_channel *hose, + int top_bus, + int current_bus, + int pci_devfn, int sub_bus) +{ + u32 temp; + + /* + * Configure subordinate bus number. The PCI subsystem + * bus scan will renumber buses (reserving three additional + * for this PCI<->CardBus bridge for the case where a CardBus + * adapter contains a P2P or CB2CB bridge. + */ + + early_write_config_byte(hose, top_bus, current_bus, pci_devfn, + PCI_SUBORDINATE_BUS, sub_bus); + + /* + * Reserve an additional 4MB for mem space and 16KB for + * I/O space. This should cover any additional space + * requirement of unusual CardBus devices with + * additional bridges that can consume more address space. + * + * Although pcmcia-cs currently will reprogram bridge + * windows, the goal is to add an option to leave them + * alone and use the bridge window ranges as the regions + * that are searched for free resources upon hot-insertion + * of a device. This will allow a PCI<->CardBus bridge + * configured by this routine to happily live behind a + * P2P bridge in a system. + */ + pciauto_lower_memspc += 0x00400000; + pciauto_lower_iospc += 0x00004000; + + /* Align memory and I/O to 4KB and 4 byte boundaries. */ + pciauto_lower_memspc = (pciauto_lower_memspc + (0x1000 - 1)) + & ~(0x1000 - 1); + pciauto_lower_iospc = (pciauto_lower_iospc + (0x4 - 1)) + & ~(0x4 - 1); + /* Set up memory and I/O filter limits, assume 32-bit I/O space */ + early_write_config_dword(hose, top_bus, current_bus, pci_devfn, + PCI_CB_MEMORY_LIMIT_0, + pciauto_lower_memspc - 1); + early_write_config_dword(hose, top_bus, current_bus, pci_devfn, + PCI_CB_IO_LIMIT_0, + pciauto_lower_iospc - 1); + + /* Enable memory and I/O accesses, enable bus master */ + early_read_config_dword(hose, top_bus, current_bus, pci_devfn, + PCI_COMMAND, &temp); + early_write_config_dword(hose, top_bus, current_bus, pci_devfn, + PCI_COMMAND, + temp | PCI_COMMAND_IO | PCI_COMMAND_MEMORY + | PCI_COMMAND_MASTER); +} + +#define PCIAUTO_IDE_MODE_MASK 0x05 + +int __init +pciauto_bus_scan(struct pci_channel *hose, int top_bus, int current_bus) +{ + int sub_bus; + u32 pci_devfn, pci_class, cmdstat, found_multi = 0; + unsigned short vid, did; + unsigned char header_type; + int devfn_start = 0; + int devfn_stop = 0xff; + + sub_bus = current_bus; + + if (hose->first_devfn) + devfn_start = hose->first_devfn; + if (hose->last_devfn) + devfn_stop = hose->last_devfn; + + for (pci_devfn = devfn_start; pci_devfn < devfn_stop; pci_devfn++) { + + if (PCI_FUNC(pci_devfn) && !found_multi) + continue; + + early_read_config_word(hose, top_bus, current_bus, + pci_devfn, PCI_VENDOR_ID, &vid); + + if (vid == 0xffff) + continue; + + early_read_config_byte(hose, top_bus, current_bus, + pci_devfn, PCI_HEADER_TYPE, + &header_type); + + if (!PCI_FUNC(pci_devfn)) + found_multi = header_type & 0x80; + + early_read_config_word(hose, top_bus, current_bus, + pci_devfn, PCI_DEVICE_ID, &did); + + early_read_config_dword(hose, top_bus, current_bus, + pci_devfn, PCI_CLASS_REVISION, + &pci_class); + + DBG("%.2x:%.2x.%x Class %.4x: %.4x:%.4x", + current_bus, PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn), + pci_class >> 16, vid, did); + if (pci_class & 0xff) + DBG(" (rev %.2x)", pci_class & 0xff); + DBG("\n"); + + if ((pci_class >> 16) == PCI_CLASS_BRIDGE_PCI) { + DBG(" Bridge: primary=%.2x, secondary=%.2x\n", current_bus, sub_bus + 1); + pciauto_setup_bars(hose, top_bus, current_bus, + pci_devfn, PCI_BASE_ADDRESS_1); + pciauto_prescan_setup_bridge(hose, top_bus, + current_bus, + pci_devfn, sub_bus); + DBG("Scanning sub bus %.2x, I/O 0x%.8x, Mem 0x%.8x\n", sub_bus + 1, pciauto_lower_iospc, pciauto_lower_memspc); + sub_bus = + pciauto_bus_scan(hose, top_bus, sub_bus + 1); + DBG("Back to bus %.2x\n", current_bus); + pciauto_postscan_setup_bridge(hose, top_bus, + current_bus, + pci_devfn, sub_bus); + continue; + } else if ((pci_class >> 16) == PCI_CLASS_BRIDGE_CARDBUS) { + DBG(" CARDBUS Bridge: primary=%.2x, secondary=%.2x\n", current_bus, sub_bus + 1); + DBG("PCI Autoconfig: Found CardBus bridge, device %d function %d\n", PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn)); + /* Place CardBus Socket/ExCA registers */ + pciauto_setup_bars(hose, top_bus, current_bus, + pci_devfn, PCI_BASE_ADDRESS_0); + + pciauto_prescan_setup_cardbus_bridge(hose, top_bus, + current_bus, + pci_devfn, + sub_bus); + + DBG("Scanning sub bus %.2x, I/O 0x%.8x, Mem 0x%.8x\n", sub_bus + 1, pciauto_lower_iospc, pciauto_lower_memspc); + sub_bus = + pciauto_bus_scan(hose, top_bus, sub_bus + 1); + DBG("Back to bus %.2x, sub_bus is %x\n", + current_bus, sub_bus); + pciauto_postscan_setup_cardbus_bridge(hose, + top_bus, + current_bus, + pci_devfn, + sub_bus); + continue; + } else if ((pci_class >> 16) == PCI_CLASS_STORAGE_IDE) { + + unsigned char prg_iface; + + early_read_config_byte(hose, top_bus, current_bus, + pci_devfn, PCI_CLASS_PROG, + &prg_iface); + if (!(prg_iface & PCIAUTO_IDE_MODE_MASK)) { + DBG("Skipping legacy mode IDE controller\n"); + continue; + } + } + + /* + * Found a peripheral, enable some standard + * settings + */ + early_read_config_dword(hose, top_bus, current_bus, + pci_devfn, PCI_COMMAND, &cmdstat); + early_write_config_dword(hose, top_bus, current_bus, + pci_devfn, PCI_COMMAND, + cmdstat | PCI_COMMAND_IO | + PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER); + early_write_config_byte(hose, top_bus, current_bus, + pci_devfn, PCI_LATENCY_TIMER, + 0x80); + + /* Allocate PCI I/O and/or memory space */ + pciauto_setup_bars(hose, top_bus, current_bus, pci_devfn, + PCI_BASE_ADDRESS_5); + } + return sub_bus; +} + +int __init pciauto_assign_resources(int busno, struct pci_channel *hose) +{ + /* setup resource limits */ + io_resource_inuse = hose->io_resource; + mem_resource_inuse = hose->mem_resource; + + pciauto_lower_iospc = io_resource_inuse->start; + pciauto_upper_iospc = io_resource_inuse->end + 1; + pciauto_lower_memspc = mem_resource_inuse->start; + pciauto_upper_memspc = mem_resource_inuse->end + 1; + DBG("Autoconfig PCI channel 0x%p\n", hose); + DBG("Scanning bus %.2x, I/O 0x%.8x:0x%.8x, Mem 0x%.8x:0x%.8x\n", + busno, pciauto_lower_iospc, pciauto_upper_iospc, + pciauto_lower_memspc, pciauto_upper_memspc); + + return pciauto_bus_scan(hose, busno, busno); +} diff -Nru a/arch/mips/pci/pci-cobalt.c b/arch/mips/pci/pci-cobalt.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/pci-cobalt.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,433 @@ +/* + * Cobalt Qube/Raq PCI support + * + * 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) 1995, 1996, 1997, 2002 by Ralf Baechle + * Copyright (C) 2001, 2002, 2003 by Liam Davies (ldavies@agile.tv) + */ +#include +#include +#include +#include + +#include +#include +#include + +#include + +int cobalt_board_id; + +static void qube_expansion_slot_bist(struct pci_dev *dev) +{ + unsigned char ctrl; + int timeout = 100000; + + pci_read_config_byte(dev, PCI_BIST, &ctrl); + if (!(ctrl & PCI_BIST_CAPABLE)) + return; + + pci_write_config_byte(dev, PCI_BIST, ctrl | PCI_BIST_START); + do { + pci_read_config_byte(dev, PCI_BIST, &ctrl); + if (!(ctrl & PCI_BIST_START)) + break; + } while (--timeout > 0); + if ((timeout <= 0) || (ctrl & PCI_BIST_CODE_MASK)) + printk + ("PCI: Expansion slot card failed BIST with code %x\n", + (ctrl & PCI_BIST_CODE_MASK)); +} + +static void qube_expansion_slot_fixup(struct pci_dev *dev) +{ + unsigned short pci_cmd; + unsigned long ioaddr_base = 0x10108000; /* It's magic, ask Doug. */ + unsigned long memaddr_base = 0x12001000; + int i; + + /* Enable bits in COMMAND so driver can talk to it. */ + pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); + pci_cmd |= + (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); + pci_write_config_word(dev, PCI_COMMAND, pci_cmd); + + /* Give it a working IRQ. */ + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, + COBALT_QUBE_SLOT_IRQ); + dev->irq = COBALT_QUBE_SLOT_IRQ; + + ioaddr_base += 0x2000 * PCI_FUNC(dev->devfn); + memaddr_base += 0x2000 * PCI_FUNC(dev->devfn); + + /* Fixup base addresses, we only support I/O at the moment. */ + for (i = 0; i <= 5; i++) { + unsigned int regaddr = (PCI_BASE_ADDRESS_0 + (i * 4)); + unsigned int rval, mask, size, alignme, aspace; + unsigned long *basep = &ioaddr_base; + + /* Check type first, punt if non-IO. */ + pci_read_config_dword(dev, regaddr, &rval); + aspace = (rval & PCI_BASE_ADDRESS_SPACE); + if (aspace != PCI_BASE_ADDRESS_SPACE_IO) + basep = &memaddr_base; + + /* Figure out how much it wants, if anything. */ + pci_write_config_dword(dev, regaddr, 0xffffffff); + pci_read_config_dword(dev, regaddr, &rval); + + /* Unused? */ + if (rval == 0) + continue; + + rval &= PCI_BASE_ADDRESS_IO_MASK; + mask = (~rval << 1) | 0x1; + size = (mask & rval) & 0xffffffff; + alignme = size; + if (alignme < 0x400) + alignme = 0x400; + rval = ((*basep + (alignme - 1)) & ~(alignme - 1)); + *basep = (rval + size); + pci_write_config_dword(dev, regaddr, rval | aspace); + dev->resource[i].start = rval; + dev->resource[i].end = *basep - 1; + if (aspace == PCI_BASE_ADDRESS_SPACE_IO) { + dev->resource[i].start -= 0x10000000; + dev->resource[i].end -= 0x10000000; + } + } + qube_expansion_slot_bist(dev); +} + +static void qube_raq_via_bmIDE_fixup(struct pci_dev *dev) +{ + unsigned short cfgword; + unsigned char lt; + + /* Enable Bus Mastering and fast back to back. */ + pci_read_config_word(dev, PCI_COMMAND, &cfgword); + cfgword |= (PCI_COMMAND_FAST_BACK | PCI_COMMAND_MASTER); + pci_write_config_word(dev, PCI_COMMAND, cfgword); + + /* Enable both ide interfaces. ROM only enables primary one. */ + pci_write_config_byte(dev, 0x40, 0xb); + + /* Set latency timer to reasonable value. */ + pci_read_config_byte(dev, PCI_LATENCY_TIMER, <); + if (lt < 64) + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 7); +} + +static void qube_raq_tulip_fixup(struct pci_dev *dev) +{ + unsigned short pci_cmd; + + /* Fixup the first tulip located at device PCICONF_ETH0 */ + if (PCI_SLOT(dev->devfn) == COBALT_PCICONF_ETH0) { + /* Setup the first Tulip */ + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, + COBALT_ETH0_IRQ); + dev->irq = COBALT_ETH0_IRQ; + + dev->resource[0].start = 0x100000; + dev->resource[0].end = 0x10007f; + + dev->resource[1].start = 0x12000000; + dev->resource[1].end = dev->resource[1].start + 0x3ff; + pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, + dev->resource[1].start); + + /* Fixup the second tulip located at device PCICONF_ETH1 */ + } else if (PCI_SLOT(dev->devfn) == COBALT_PCICONF_ETH1) { + + /* Enable the second Tulip device. */ + pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); + pci_cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MASTER); + pci_write_config_word(dev, PCI_COMMAND, pci_cmd); + + /* Give it it's IRQ. */ + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, + COBALT_ETH1_IRQ); + dev->irq = COBALT_ETH1_IRQ; + + /* And finally, a usable I/O space allocation, right after what + * the first Tulip uses. + */ + dev->resource[0].start = 0x101000; + dev->resource[0].end = 0x10107f; + + dev->resource[1].start = 0x12000400; + dev->resource[1].end = dev->resource[1].start + 0x3ff; + pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, + dev->resource[1].start); + } +} + +static void qube_raq_scsi_fixup(struct pci_dev *dev) +{ + unsigned short pci_cmd; + + /* + * Tell the SCSI device that we expect an interrupt at + * IRQ 7 and not the default 0. + */ + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, COBALT_SCSI_IRQ); + dev->irq = COBALT_SCSI_IRQ; + + if (cobalt_board_id == COBALT_BRD_ID_RAQ2) { + + /* Enable the device. */ + pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); + + pci_cmd |= + (PCI_COMMAND_IO | PCI_COMMAND_MASTER | + PCI_COMMAND_MEMORY | PCI_COMMAND_INVALIDATE); + pci_write_config_word(dev, PCI_COMMAND, pci_cmd); + + /* Give it it's RAQ IRQ. */ + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, + COBALT_RAQ_SCSI_IRQ); + dev->irq = COBALT_RAQ_SCSI_IRQ; + + /* And finally, a usable I/O space allocation, right after what + * the second Tulip uses. + */ + dev->resource[0].start = 0x102000; + dev->resource[0].end = dev->resource[0].start + 0xff; + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, + 0x10102000); + + pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, + 0x00002000); + pci_write_config_dword(dev, PCI_BASE_ADDRESS_2, + 0x00100000); + } +} + +static void qube_raq_galileo_fixup(struct pci_dev *dev) +{ + unsigned short galileo_id; + + /* Fix PCI latency-timer and cache-line-size values in Galileo + * host bridge. + */ + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 7); + + /* On all machines prior to Q2, we had the STOP line disconnected + * from Galileo to VIA on PCI. The new Galileo does not function + * correctly unless we have it connected. + * + * Therefore we must set the disconnect/retry cycle values to + * something sensible when using the new Galileo. + */ + pci_read_config_word(dev, PCI_REVISION_ID, &galileo_id); + galileo_id &= 0xff; /* mask off class info */ + if (galileo_id >= 0x10) { + /* New Galileo, assumes PCI stop line to VIA is connected. */ + GALILEO_OUTL(0x4020, GT_PCI0_TOR_OFS); + } else if (galileo_id == 0x1 || galileo_id == 0x2) { + signed int timeo; + /* XXX WE MUST DO THIS ELSE GALILEO LOCKS UP! -DaveM */ + timeo = GALILEO_INL(GT_PCI0_TOR_OFS); + /* Old Galileo, assumes PCI STOP line to VIA is disconnected. */ + GALILEO_OUTL(0xffff, GT_PCI0_TOR_OFS); + } +} + +static void qube_pcibios_fixup(struct pci_dev *dev) +{ + if (PCI_SLOT(dev->devfn) == COBALT_PCICONF_PCISLOT) { + unsigned int tmp; + + /* See if there is a device in the expansion slot, if so + * discover its resources and fixup whatever we need to + */ + pci_read_config_dword(dev, PCI_VENDOR_ID, &tmp); + if (tmp != 0xffffffff && tmp != 0x00000000) + qube_expansion_slot_fixup(dev); + } +} + +struct pci_fixup pcibios_fixups[] = { + {PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_1, + qube_raq_via_bmIDE_fixup}, + {PCI_FIXUP_HEADER, PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142, + qube_raq_tulip_fixup}, + {PCI_FIXUP_HEADER, PCI_VENDOR_ID_GALILEO, PCI_ANY_ID, + qube_raq_galileo_fixup}, + {PCI_FIXUP_HEADER, PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C860, + qube_raq_scsi_fixup}, + {PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, qube_pcibios_fixup} +}; + + +static inline int pci_range_ck(struct pci_bus *bus, unsigned int devfn) +{ + if ((bus->number == 0) + && ((PCI_SLOT(devfn) == 0) + || ((PCI_SLOT(devfn) > 6) + && (PCI_SLOT(devfn) <= 12)))) + return 0; /* OK device number */ + + return -1; /* NOT ok device number */ +} + +#define PCI_CFG_SET(devfn,where) \ + GALILEO_OUTL((0x80000000 | (PCI_SLOT (devfn) << 11) | \ + (PCI_FUNC (devfn) << 8) | (where)), \ + GT_PCI0_CFGADDR_OFS) + + +static int qube_pci_read_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 * val) +{ + switch (size) { + case 4: + if (where & 0x3) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (pci_range_ck(bus, devfn)) { + *val = 0xFFFFFFFF; + return PCIBIOS_DEVICE_NOT_FOUND; + } + PCI_CFG_SET(devfn, where); + *val = GALILEO_INL(GT_PCI0_CFGDATA_OFS); + return PCIBIOS_SUCCESSFUL; + + case 2: + if (where & 0x1) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (pci_range_ck(bus, devfn)) { + *val = 0xffff; + return PCIBIOS_DEVICE_NOT_FOUND; + } + PCI_CFG_SET(devfn, (where & ~0x3)); + *val = GALILEO_INL(GT_PCI0_CFGDATA_OFS) + >> ((where & 3) * 8); + return PCIBIOS_SUCCESSFUL; + + case 1: + if (pci_range_ck(bus, devfn)) { + *val = 0xff; + return PCIBIOS_DEVICE_NOT_FOUND; + } + PCI_CFG_SET(devfn, (where & ~0x3)); + *val = GALILEO_INL(GT_PCI0_CFGDATA_OFS) + >> ((where & 3) * 8); + return PCIBIOS_SUCCESSFUL; + } +} + +static int qube_pci_write_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) +{ + u32 tmp; + + switch (size) { + case 4: + if (where & 0x3) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (pci_range_ck(bus, devfn)) + return PCIBIOS_DEVICE_NOT_FOUND; + PCI_CFG_SET(devfn, where); + GALILEO_OUTL(val, GT_PCI0_CFGDATA_OFS); + + return PCIBIOS_SUCCESSFUL; + + case 2: + if (where & 0x1) + return PCIBIOS_BAD_REGISTER_NUMBER; + if (pci_range_ck(bus, devfn)) + return PCIBIOS_DEVICE_NOT_FOUND; + PCI_CFG_SET(devfn, (where & ~0x3)); + tmp = GALILEO_INL(GT_PCI0_CFGDATA_OFS); + tmp &= ~(0xffff << ((where & 0x3) * 8)); + tmp |= (val << ((where & 0x3) * 8)); + GALILEO_OUTL(tmp, GT_PCI0_CFGDATA_OFS); + + return PCIBIOS_SUCCESSFUL; + + case 1: + + if (pci_range_ck(bus, devfn)) + return PCIBIOS_DEVICE_NOT_FOUND; + PCI_CFG_SET(devfn, (where & ~0x3)); + tmp = GALILEO_INL(GT_PCI0_CFGDATA_OFS); + tmp &= ~(0xff << ((where & 0x3) * 8)); + tmp |= (val << ((where & 0x3) * 8)); + GALILEO_OUTL(tmp, GT_PCI0_CFGDATA_OFS); + + return PCIBIOS_SUCCESSFUL; + } +} + +struct pci_ops qube_pci_ops = { + .read = qube_pci_read_config, + .write = qube_pci_write_config, +}; + +static int __init pcibios_init(void) +{ + unsigned int devfn = PCI_DEVFN(COBALT_PCICONF_VIA, 0); + + printk("PCI: Probing PCI hardware\n"); + + /* Read the cobalt id register out of the PCI config space */ + PCI_CFG_SET(devfn, (VIA_COBALT_BRD_ID_REG & ~0x3)); + cobalt_board_id = GALILEO_INL(GT_PCI0_CFGDATA_OFS) + >> ((VIA_COBALT_BRD_ID_REG & 3) * 8); + cobalt_board_id = VIA_COBALT_BRD_REG_to_ID(cobalt_board_id); + + printk("Cobalt Board ID: %d\n", cobalt_board_id); + + ioport_resource.start = 0x00000000; + ioport_resource.end = 0x0fffffff; + + iomem_resource.start = 0x01000000; + iomem_resource.end = 0xffffffff; + + pci_scan_bus(0, &qube_pci_ops, NULL); + + return 0; +} + +subsys_initcall(pcibios_init); + +char *pcibios_setup(char *str) +{ + return str; +} + +int pcibios_enable_device(struct pci_dev *dev, int mask) +{ + u16 cmd, status; + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + pci_read_config_word(dev, PCI_STATUS, &status); + printk("PCI: Enabling device %s (%04x %04x)\n", dev->slot_name, + cmd, status); + /* We'll sort this out when we know it isn't enabled ;) */ + + return 0; +} + +void pcibios_align_resource(void *data, struct resource *res, + unsigned long size, unsigned long align) +{ + + panic("Uhhoh called pcibios_align_resource\n"); +} + +void __devinit pcibios_fixup_bus(struct pci_bus *bus) +{ + /* We don't have sub-busses to fixup here */ +} + +unsigned int __init pcibios_assign_all_busses(void) +{ + return 1; +} diff -Nru a/arch/mips/pci/pci-ddb5074.c b/arch/mips/pci/pci-ddb5074.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/pci-ddb5074.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,129 @@ +#include +#include +#include +#include + +#include +#include + +#include + +static struct resource extpci_io_resource = { + "pci IO space", + 0x1000, /* leave some room for ISA bus */ + DDB_PCI_IO_SIZE - 1, + IORESOURCE_IO +}; + +static struct resource extpci_mem_resource = { + "pci memory space", + DDB_PCI_MEM_BASE + 0x00100000, /* leave 1 MB for RTC */ + DDB_PCI_MEM_BASE + DDB_PCI_MEM_SIZE - 1, + IORESOURCE_MEM +}; + +extern struct pci_ops ddb5476_ext_pci_ops; + +struct pci_channel mips_pci_channels[] = { + {&ddb5476_ext_pci_ops, &extpci_io_resource, &extpci_mem_resource}, + {NULL, NULL, NULL} +}; + +#define PCI_EXT_INTA 8 +#define PCI_EXT_INTB 9 +#define PCI_EXT_INTC 10 +#define PCI_EXT_INTD 11 +#define PCI_EXT_INTE 12 + +#define MAX_SLOT_NUM 14 + +static unsigned char irq_map[MAX_SLOT_NUM] = { + /* SLOT: 0 */ nile4_to_irq(PCI_EXT_INTE), + /* SLOT: 1 */ nile4_to_irq(PCI_EXT_INTA), + /* SLOT: 2 */ nile4_to_irq(PCI_EXT_INTA), + /* SLOT: 3 */ nile4_to_irq(PCI_EXT_INTB), + /* SLOT: 4 */ nile4_to_irq(PCI_EXT_INTC), + /* SLOT: 5 */ nile4_to_irq(NILE4_INT_UART), + /* SLOT: 6 */ 0xff, + /* SLOT: 7 */ 0xff, + /* SLOT: 8 */ 0xff, + /* SLOT: 9 */ 0xff, + /* SLOT: 10 */ nile4_to_irq(PCI_EXT_INTE), + /* SLOT: 11 */ 0xff, + /* SLOT: 12 */ 0xff, + /* SLOT: 13 */ nile4_to_irq(PCI_EXT_INTE), +}; + +void __init pcibios_fixup_irqs(void) +{ + + struct pci_dev *dev = NULL; + int slot_num; + + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + slot_num = PCI_SLOT(dev->devfn); + db_assert(slot_num < MAX_SLOT_NUM); + printk("irq_map[%d]: %02x\n", slot_num, irq_map[slot_num]); + db_assert(irq_map[slot_num] != 0xff); + + pci_write_config_byte(dev, + PCI_INTERRUPT_LINE, + irq_map[slot_num]); + + dev->irq = irq_map[slot_num]; + } +} + +void __init ddb_pci_reset_bus(void) +{ + u32 temp; + + /* + * I am not sure about the "official" procedure, the following + * steps work as far as I know: + * We first set PCI cold reset bit (bit 31) in PCICTRL-H. + * Then we clear the PCI warm reset bit (bit 30) to 0 in PCICTRL-H. + * The same is true for both PCI channels. + */ + temp = ddb_in32(DDB_PCICTRL + 4); + temp |= 0x80000000; + ddb_out32(DDB_PCICTRL + 4, temp); + temp &= ~0xc0000000; + ddb_out32(DDB_PCICTRL + 4, temp); + +} + +unsigned __init int pcibios_assign_all_busses(void) +{ + /* we hope pci_auto has assigned the bus numbers to all buses */ + return 1; +} + +void __init pcibios_fixup_resources(struct pci_dev *dev) +{ +} + +void __init pcibios_fixup(void) +{ + struct pci_dev *dev = NULL; + + while ((dev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, + dev)) != NULL) { + /* + * It's nice to have the LEDs on the GPIO pins + * available for debugging + */ + extern struct pci_dev *pci_pmu; + u8 t8; + + pci_pmu = dev; /* for LEDs D2 and D3 */ + /* Program the lines for LEDs D2 and D3 to output */ + pci_read_config_byte(dev, 0x7d, &t8); + t8 |= 0xc0; + pci_write_config_byte(dev, 0x7d, t8); + /* Turn LEDs D2 and D3 off */ + pci_read_config_byte(dev, 0x7e, &t8); + t8 |= 0xc0; + pci_write_config_byte(dev, 0x7e, t8); + } +} diff -Nru a/arch/mips/pci/pci-ddb5476.c b/arch/mips/pci/pci-ddb5476.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/pci-ddb5476.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,145 @@ +#include +#include +#include +#include +#include + +#include +#include + +#include + +static struct resource extpci_io_resource = { + "pci IO space", + 0x1000, /* leave some room for ISA bus */ + DDB_PCI_IO_SIZE - 1, + IORESOURCE_IO +}; + +static struct resource extpci_mem_resource = { + "pci memory space", + DDB_PCI_MEM_BASE + 0x00100000, /* leave 1 MB for RTC */ + DDB_PCI_MEM_BASE + DDB_PCI_MEM_SIZE - 1, + IORESOURCE_MEM +}; + +extern struct pci_ops ddb5476_ext_pci_ops; + +struct pci_channel mips_pci_channels[] = { + {&ddb5476_ext_pci_ops, &extpci_io_resource, &extpci_mem_resource}, + {NULL, NULL, NULL} +}; + + +/* + * we fix up irqs based on the slot number. + * The first entry is at AD:11. + * + * This does not work for devices on sub-buses yet. + */ + +/* + * temporary + */ + +#define PCI_EXT_INTA 8 +#define PCI_EXT_INTB 9 +#define PCI_EXT_INTC 10 +#define PCI_EXT_INTD 11 +#define PCI_EXT_INTE 12 + +/* + * based on ddb5477 manual page 11 + */ +#define MAX_SLOT_NUM 21 +static unsigned char irq_map[MAX_SLOT_NUM] = { + /* SLOT: 0, AD:11 */ 0xff, + /* SLOT: 1, AD:12 */ 0xff, + /* SLOT: 2, AD:13 */ 9, + /* USB */ + /* SLOT: 3, AD:14 */ 10, + /* PMU */ + /* SLOT: 4, AD:15 */ 0xff, + /* SLOT: 5, AD:16 */ 0x0, + /* P2P bridge */ + /* SLOT: 6, AD:17 */ nile4_to_irq(PCI_EXT_INTB), + /* SLOT: 7, AD:18 */ nile4_to_irq(PCI_EXT_INTC), + /* SLOT: 8, AD:19 */ nile4_to_irq(PCI_EXT_INTD), + /* SLOT: 9, AD:20 */ nile4_to_irq(PCI_EXT_INTA), + /* SLOT: 10, AD:21 */ 0xff, + /* SLOT: 11, AD:22 */ 0xff, + /* SLOT: 12, AD:23 */ 0xff, + /* SLOT: 13, AD:24 */ 14, + /* HD controller, M5229 */ + /* SLOT: 14, AD:25 */ 0xff, + /* SLOT: 15, AD:26 */ 0xff, + /* SLOT: 16, AD:27 */ 0xff, + /* SLOT: 17, AD:28 */ 0xff, + /* SLOT: 18, AD:29 */ 0xff, + /* SLOT: 19, AD:30 */ 0xff, + /* SLOT: 20, AD:31 */ 0xff +}; + +extern int vrc5477_irq_to_irq(int irq); +void __init pcibios_fixup_irqs(void) +{ + struct pci_dev *dev = NULL; + int slot_num; + + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + slot_num = PCI_SLOT(dev->devfn); + + /* we don't do IRQ fixup for sub-bus yet */ + if (dev->bus->parent != NULL) { + db_run(printk + ("Don't know how to fixup irq for PCI device %d on sub-bus %d\n", + slot_num, dev->bus->number)); + continue; + } + + db_assert(slot_num < MAX_SLOT_NUM); + db_assert(irq_map[slot_num] != 0xff); + + pci_write_config_byte(dev, + PCI_INTERRUPT_LINE, + irq_map[slot_num]); + dev->irq = irq_map[slot_num]; + } +} + +#if defined(CONFIG_RUNTIME_DEBUG) +extern void jsun_scan_pci_bus(void); +#endif + +void __init ddb_pci_reset_bus(void) +{ + u32 temp; + + /* + * I am not sure about the "official" procedure, the following + * steps work as far as I know: + * We first set PCI cold reset bit (bit 31) in PCICTRL-H. + * Then we clear the PCI warm reset bit (bit 30) to 0 in PCICTRL-H. + * The same is true for both PCI channels. + */ + temp = ddb_in32(DDB_PCICTRL + 4); + temp |= 0x80000000; + ddb_out32(DDB_PCICTRL + 4, temp); + temp &= ~0xc0000000; + ddb_out32(DDB_PCICTRL + 4, temp); + +} + +unsigned __init int pcibios_assign_all_busses(void) +{ + /* we hope pci_auto has assigned the bus numbers to all buses */ + return 1; +} + +void __init pcibios_fixup_resources(struct pci_dev *dev) +{ +} + +void __init pcibios_fixup(void) +{ +} diff -Nru a/arch/mips/pci/pci-ddb5477.c b/arch/mips/pci/pci-ddb5477.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/pci-ddb5477.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,299 @@ +/* + * PCI code for DDB5477. + * + * Copyright (C) 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +static struct resource extpci_io_resource = { + "ext pci IO space", + DDB_PCI0_IO_BASE - DDB_PCI_IO_BASE + 0x4000, + DDB_PCI0_IO_BASE - DDB_PCI_IO_BASE + DDB_PCI0_IO_SIZE - 1, + IORESOURCE_IO +}; + +static struct resource extpci_mem_resource = { + "ext pci memory space", + DDB_PCI0_MEM_BASE + 0x100000, + DDB_PCI0_MEM_BASE + DDB_PCI0_MEM_SIZE - 1, + IORESOURCE_MEM +}; + +static struct resource iopci_io_resource = { + "io pci IO space", + DDB_PCI1_IO_BASE - DDB_PCI_IO_BASE, + DDB_PCI1_IO_BASE - DDB_PCI_IO_BASE + DDB_PCI1_IO_SIZE - 1, + IORESOURCE_IO +}; + +static struct resource iopci_mem_resource = { + "ext pci memory space", + DDB_PCI1_MEM_BASE, + DDB_PCI1_MEM_BASE + DDB_PCI1_MEM_SIZE - 1, + IORESOURCE_MEM +}; + +extern struct pci_ops ddb5477_ext_pci_ops; +extern struct pci_ops ddb5477_io_pci_ops; + +struct pci_channel mips_pci_channels[] = { + {&ddb5477_ext_pci_ops, &extpci_io_resource, &extpci_mem_resource}, + {&ddb5477_io_pci_ops, &iopci_io_resource, &iopci_mem_resource}, + {NULL, NULL, NULL} +}; + + +/* + * we fix up irqs based on the slot number. + * The first entry is at AD:11. + * Fortunately this works because, although we have two pci buses, + * they all have different slot numbers (except for rockhopper slot 20 + * which is handled below). + * + */ + +/* + * irq mapping : device -> pci int # -> vrc4377 irq# , + * ddb5477 board manual page 4 and vrc5477 manual page 46 + */ + +/* + * based on ddb5477 manual page 11 + */ +#define MAX_SLOT_NUM 21 +static unsigned char irq_map[MAX_SLOT_NUM] = { + /* SLOT: 0, AD:11 */ 0xff, + /* SLOT: 1, AD:12 */ 0xff, + /* SLOT: 2, AD:13 */ 0xff, + /* SLOT: 3, AD:14 */ 0xff, + /* SLOT: 4, AD:15 */ VRC5477_IRQ_INTA, + /* onboard tulip */ + /* SLOT: 5, AD:16 */ VRC5477_IRQ_INTB, + /* slot 1 */ + /* SLOT: 6, AD:17 */ VRC5477_IRQ_INTC, + /* slot 2 */ + /* SLOT: 7, AD:18 */ VRC5477_IRQ_INTD, + /* slot 3 */ + /* SLOT: 8, AD:19 */ VRC5477_IRQ_INTE, + /* slot 4 */ + /* SLOT: 9, AD:20 */ 0xff, + /* SLOT: 10, AD:21 */ 0xff, + /* SLOT: 11, AD:22 */ 0xff, + /* SLOT: 12, AD:23 */ 0xff, + /* SLOT: 13, AD:24 */ 0xff, + /* SLOT: 14, AD:25 */ 0xff, + /* SLOT: 15, AD:26 */ 0xff, + /* SLOT: 16, AD:27 */ 0xff, + /* SLOT: 17, AD:28 */ 0xff, + /* SLOT: 18, AD:29 */ VRC5477_IRQ_IOPCI_INTC, + /* vrc5477 ac97 */ + /* SLOT: 19, AD:30 */ VRC5477_IRQ_IOPCI_INTB, + /* vrc5477 usb peri */ + /* SLOT: 20, AD:31 */ VRC5477_IRQ_IOPCI_INTA, + /* vrc5477 usb host */ +}; +static unsigned char rockhopperII_irq_map[MAX_SLOT_NUM] = { + /* SLOT: 0, AD:11 */ 0xff, + /* SLOT: 1, AD:12 */ VRC5477_IRQ_INTB, + /* onboard AMD PCNET */ + /* SLOT: 2, AD:13 */ 0xff, + /* SLOT: 3, AD:14 */ 0xff, + /* SLOT: 4, AD:15 */ 14, + /* M5229 ide ISA irq */ + /* SLOT: 5, AD:16 */ VRC5477_IRQ_INTD, + /* slot 3 */ + /* SLOT: 6, AD:17 */ VRC5477_IRQ_INTA, + /* slot 4 */ + /* SLOT: 7, AD:18 */ VRC5477_IRQ_INTD, + /* slot 5 */ + /* SLOT: 8, AD:19 */ 0, + /* M5457 modem nop */ + /* SLOT: 9, AD:20 */ VRC5477_IRQ_INTA, + /* slot 2 */ + /* SLOT: 10, AD:21 */ 0xff, + /* SLOT: 11, AD:22 */ 0xff, + /* SLOT: 12, AD:23 */ 0xff, + /* SLOT: 13, AD:24 */ 0xff, + /* SLOT: 14, AD:25 */ 0xff, + /* SLOT: 15, AD:26 */ 0xff, + /* SLOT: 16, AD:27 */ 0xff, + /* SLOT: 17, AD:28 */ 0, + /* M7101 PMU nop */ + /* SLOT: 18, AD:29 */ VRC5477_IRQ_IOPCI_INTC, + /* vrc5477 ac97 */ + /* SLOT: 19, AD:30 */ VRC5477_IRQ_IOPCI_INTB, + /* vrc5477 usb peri */ + /* SLOT: 20, AD:31 */ VRC5477_IRQ_IOPCI_INTA, + /* vrc5477 usb host */ +}; + +void __init pcibios_fixup_irqs(void) +{ + struct pci_dev *dev = NULL; + int slot_num; + unsigned char *slot_irq_map; + unsigned char irq; + + if (mips_machtype == MACH_NEC_ROCKHOPPERII) + slot_irq_map = rockhopperII_irq_map; + else + slot_irq_map = irq_map; + + + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + slot_num = PCI_SLOT(dev->devfn); + irq = slot_irq_map[slot_num]; + + db_assert(slot_num < MAX_SLOT_NUM); + + db_assert(irq != 0xff); + + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); + + dev->irq = irq; + + if (mips_machtype == MACH_NEC_ROCKHOPPERII) { + /* hack to distinquish overlapping slot 20s, one + * on bus 0 (ALI USB on the M1535 on the backplane), + * and one on bus 2 (NEC USB controller on the CPU board) + * Make the M1535 USB - ISA IRQ number 9. + */ + if (slot_num == 20 && dev->bus->number == 0) { + pci_write_config_byte(dev, + PCI_INTERRUPT_LINE, + 9); + dev->irq = 9; + } + } + + } +} + +#if defined(CONFIG_RUNTIME_DEBUG) +extern void jsun_scan_pci_bus(void); +extern void jsun_assign_pci_resource(void); +#endif +void ddb_pci_reset_bus(void) +{ + u32 temp; + + /* + * I am not sure about the "official" procedure, the following + * steps work as far as I know: + * We first set PCI cold reset bit (bit 31) in PCICTRL-H. + * Then we clear the PCI warm reset bit (bit 30) to 0 in PCICTRL-H. + * The same is true for both PCI channels. + */ + temp = ddb_in32(DDB_PCICTL0_H); + temp |= 0x80000000; + ddb_out32(DDB_PCICTL0_H, temp); + temp &= ~0xc0000000; + ddb_out32(DDB_PCICTL0_H, temp); + + temp = ddb_in32(DDB_PCICTL1_H); + temp |= 0x80000000; + ddb_out32(DDB_PCICTL1_H, temp); + temp &= ~0xc0000000; + ddb_out32(DDB_PCICTL1_H, temp); +} + +unsigned __init int pcibios_assign_all_busses(void) +{ + /* we hope pci_auto has assigned the bus numbers to all buses */ + return 1; +} + +void __init pcibios_fixup_resources(struct pci_dev *dev) +{ +} + +/* + * fixup baseboard AMD chip so that tx does not underflow. + * bcr_18 |= 0x0800 + * This sets NOUFLO bit which makes tx not start until whole pkt + * is fetched to the chip. + */ +#define PCNET32_WIO_RDP 0x10 +#define PCNET32_WIO_RAP 0x12 +#define PCNET32_WIO_RESET 0x14 +#define PCNET32_WIO_BDP 0x16 +void __init fix_amd_lance(struct pci_dev *dev) +{ + unsigned long ioaddr; + u16 temp; + + ioaddr = pci_resource_start(dev, 0); + + inw(ioaddr + PCNET32_WIO_RESET); /* reset chip */ + + /* bcr_18 |= 0x0800 */ + outw(18, ioaddr + PCNET32_WIO_RAP); + temp = inw(ioaddr + PCNET32_WIO_BDP); + temp |= 0x0800; + outw(18, ioaddr + PCNET32_WIO_RAP); + outw(temp, ioaddr + PCNET32_WIO_BDP); +} + +void __init pcibios_fixup(void) +{ + struct pci_dev *dev = NULL; + + if (mips_machtype != MACH_NEC_ROCKHOPPERII) + return; + + +#define M1535_CONFIG_PORT 0x3f0 +#define M1535_INDEX_PORT 0x3f0 +#define M1535_DATA_PORT 0x3f1 + + printk("Configuring ALI M1535 Super I/O mouse irq.\n"); + + request_region(M1535_CONFIG_PORT, 2, "M1535 Super I/O config"); + + /* Enter config mode. */ + outb(0x51, M1535_CONFIG_PORT); + outb(0x23, M1535_CONFIG_PORT); + + /* Select device 0x07. */ + outb(0x07, M1535_INDEX_PORT); + outb(0x07, M1535_DATA_PORT); + + /* Set mouse irq (register 0x72) to 12. */ + outb(0x72, M1535_INDEX_PORT); + outb(0x0c, M1535_DATA_PORT); + + /* Exit config mode. */ + outb(0xbb, M1535_CONFIG_PORT); + + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + if (dev->vendor == PCI_VENDOR_ID_AL) + if (dev->device == PCI_DEVICE_ID_AL_M1535 + || dev->device == PCI_DEVICE_ID_AL_M1533) { + u8 old; + printk + ("Enabling ALI M1533/35 PS2 keyboard/mouse.\n"); + pci_read_config_byte(dev, 0x41, &old); + pci_write_config_byte(dev, 0x41, old | 0xd0); + } + + if (dev->vendor == PCI_VENDOR_ID_AMD && + dev->device == PCI_DEVICE_ID_AMD_LANCE) + fix_amd_lance(dev); + } +} diff -Nru a/arch/mips/pci/pci-hplj.c b/arch/mips/pci/pci-hplj.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/pci-hplj.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,252 @@ +/* + * 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. + * + * SNI specific PCI support for RM200/RM300. + * + * Copyright (C) 1997 - 2000 Ralf Baechle + */ +#include +#include +#include +#include +#include +#include +#include + +volatile u32 *pci_config_address_reg = (volatile u32 *) 0xfdead000; +volatile u32 *pci_config_data_reg = (volatile u32 *) 0xfdead000; + + + +#define cfgaddr(dev, where) (((dev->bus->number & 0xff) << 0x10) | \ + ((dev->devfn & 0xff) << 0x08) | \ + (where & 0xfc)) + +/* + * We can't address 8 and 16 bit words directly. Instead we have to + * read/write a 32bit word and mask/modify the data we actually want. + */ +static int pcimt_read_config_byte(struct pci_dev *dev, + int where, unsigned char *val) +{ + *pci_config_address_reg = cfgaddr(dev, where); + *val = + (le32_to_cpu(*pci_config_data_reg) >> ((where & 3) << 3)) & + 0xff; + //printk("pci_read_byte 0x%x == 0x%x\n", where, *val); + return PCIBIOS_SUCCESSFUL; +} + +static int pcimt_read_config_word(struct pci_dev *dev, + int where, unsigned short *val) +{ + if (where & 1) + return PCIBIOS_BAD_REGISTER_NUMBER; + *pci_config_address_reg = cfgaddr(dev, where); + *val = + (le32_to_cpu(*pci_config_data_reg) >> ((where & 3) << 3)) & + 0xffff; + //printk("pci_read_word 0x%x == 0x%x\n", where, *val); + return PCIBIOS_SUCCESSFUL; +} + +int pcimt_read_config_dword(struct pci_dev *dev, + int where, unsigned int *val) +{ + if (where & 3) + return PCIBIOS_BAD_REGISTER_NUMBER; + *pci_config_address_reg = cfgaddr(dev, where); + *val = le32_to_cpu(*pci_config_data_reg); + //printk("pci_read_dword 0x%x == 0x%x\n", where, *val); + return PCIBIOS_SUCCESSFUL; +} + +static int pcimt_write_config_byte(struct pci_dev *dev, + int where, unsigned char val) +{ + *pci_config_address_reg = cfgaddr(dev, where); + *(volatile u8 *) (((int) pci_config_data_reg) + (where & 3)) = val; + //printk("pci_write_byte 0x%x = 0x%x\n", where, val); + return PCIBIOS_SUCCESSFUL; +} + +static int pcimt_write_config_word(struct pci_dev *dev, + int where, unsigned short val) +{ + if (where & 1) + return PCIBIOS_BAD_REGISTER_NUMBER; + *pci_config_address_reg = cfgaddr(dev, where); + *(volatile u16 *) (((int) pci_config_data_reg) + (where & 2)) = + le16_to_cpu(val); + //printk("pci_write_word 0x%x = 0x%x\n", where, val); + return PCIBIOS_SUCCESSFUL; +} + +int pcimt_write_config_dword(struct pci_dev *dev, + int where, unsigned int val) +{ + if (where & 3) + return PCIBIOS_BAD_REGISTER_NUMBER; + *pci_config_address_reg = cfgaddr(dev, where); + *pci_config_data_reg = le32_to_cpu(val); + //printk("pci_write_dword 0x%x = 0x%x\n", where, val); + return PCIBIOS_SUCCESSFUL; +} + + + +struct pci_ops hp_pci_ops = { + pcimt_read_config_byte, + pcimt_read_config_word, + pcimt_read_config_dword, + pcimt_write_config_byte, + pcimt_write_config_word, + pcimt_write_config_dword +}; + + +struct pci_channel mips_pci_channels[] = { + {&hp_pci_ops, &ioport_resource, &iomem_resource}, + {NULL, NULL, NULL} +}; + +unsigned __init int pcibios_assign_all_busses(void) +{ + return 1; +} + +void __init pcibios_fixup(void) +{ +} + + +void __init pcibios_fixup_irqs(void) +{ + struct pci_dev *dev = NULL; + int slot_num; + + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + slot_num = PCI_SLOT(dev->devfn); + switch (slot_num) { + case 2: + dev->irq = 3; + break; + case 3: + dev->irq = 4; + break; + case 4: + dev->irq = 5; + break; + default: + break; + } + } +} + +#define IO_MEM_LOGICAL_START 0x3e000000 +#define IO_MEM_LOGICAL_END 0x3fefffff + +#define IO_PORT_LOGICAL_START 0x3ff00000 +#define IO_PORT_LOGICAL_END 0x3fffffff + + +#define IO_MEM_VIRTUAL_OFFSET 0xb0000000 +#define IO_PORT_VIRTUAL_OFFSET 0xb0000000 + +#define ONE_MEG (1024 * 1024) + +void __init pci_setup(void) +{ + u32 pci_regs_base_offset = 0xfdead000; + + switch (GetAsicId()) { + case AndrosAsic: + pci_regs_base_offset = 0xbff80000; + break; + case HarmonyAsic: + pci_regs_base_offset = 0xbff70000; + break; + default: + printk("ERROR: PCI does not support %s Asic\n", + GetAsicName()); + while (1); + break; + } + + // set bus stat/command reg + // REVIST this setting may need vary depending on the hardware + *((volatile unsigned int *) (pci_regs_base_offset | 0x0004)) = + 0x38000007; + + + iomem_resource.start = + IO_MEM_LOGICAL_START + IO_MEM_VIRTUAL_OFFSET; + iomem_resource.end = IO_MEM_LOGICAL_END + IO_MEM_VIRTUAL_OFFSET; + + ioport_resource.start = + IO_PORT_LOGICAL_START + IO_PORT_VIRTUAL_OFFSET; + ioport_resource.end = IO_PORT_LOGICAL_END + IO_PORT_VIRTUAL_OFFSET; + + // KLUDGE (mips_io_port_base is screwed up, we've got to work around it here) + // by letting both low (illegal) and high (legal) addresses appear in pci io space + ioport_resource.start = 0x0; + + set_io_port_base(IO_PORT_LOGICAL_START + IO_PORT_VIRTUAL_OFFSET); + + // map the PCI address space + // global map - all levels & processes can access + // except that the range is outside user space + // parameters: lo0, lo1, hi, pagemask + // lo indicates physical page, hi indicates virtual address + add_wired_entry((IO_MEM_LOGICAL_START >> 6) | 0x17, + ((IO_MEM_LOGICAL_START + + (16 * ONE_MEG)) >> 6) | 0x17, 0xee000000, + PM_16M); + + + // These are used in pci r/w routines so need to preceed bus scan + pci_config_data_reg = (u32 *) (((u32) mips_io_port_base) | 0xcfc); + pci_config_address_reg = + (u32 *) (((u32) pci_regs_base_offset) | 0xcf8); + +} + + +void __init pcibios_fixup_resources(struct pci_dev *dev) +{ + int pos; + int bases; + + printk("adjusting pci device: %s\n", dev->name); + + switch (dev->hdr_type) { + case PCI_HEADER_TYPE_NORMAL: + bases = 6; + break; + case PCI_HEADER_TYPE_BRIDGE: + bases = 2; + break; + case PCI_HEADER_TYPE_CARDBUS: + bases = 1; + break; + default: + bases = 0; + break; + } + for (pos = 0; pos < bases; pos++) { + struct resource *res = &dev->resource[pos]; + if (res->start >= IO_MEM_LOGICAL_START && + res->end <= IO_MEM_LOGICAL_END) { + res->start += IO_MEM_VIRTUAL_OFFSET; + res->end += IO_MEM_VIRTUAL_OFFSET; + } + if (res->start >= IO_PORT_LOGICAL_START && + res->end <= IO_PORT_LOGICAL_END) { + res->start += IO_PORT_VIRTUAL_OFFSET; + res->end += IO_PORT_VIRTUAL_OFFSET; + } + } + +} diff -Nru a/arch/mips/pci/pci-ip27.c b/arch/mips/pci/pci-ip27.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/pci-ip27.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,391 @@ +/* + * 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) 1999, 2000 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Max #PCI busses we can handle; ie, max #PCI bridges. + */ +#define MAX_PCI_BUSSES 40 + +/* + * Max #PCI devices (like scsi controllers) we handle on a bus. + */ +#define MAX_DEVICES_PER_PCIBUS 8 + +/* + * No locking needed until PCI initialization is done parallely. + */ +int irqstore[MAX_PCI_BUSSES][MAX_DEVICES_PER_PCIBUS]; +int lastirq = BASE_PCI_IRQ; + +/* + * Translate from irq to software PCI bus number and PCI slot. + */ +int irq_to_bus[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS]; +int irq_to_slot[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS]; + +/* + * The Bridge ASIC supports both type 0 and type 1 access. Type 1 is + * not really documented, so right now I can't write code which uses it. + * Therefore we use type 0 accesses for now even though they won't work + * correcly for PCI-to-PCI bridges. + */ +#define CF0_READ_PCI_CFG(bus,devfn,where,value,bm,mask) \ +do { \ + bridge_t *bridge; \ + int slot = PCI_SLOT(devfn); \ + int fn = PCI_FUNC(devfn); \ + volatile u32 *addr; \ + u32 cf, __bit; \ + unsigned int bus_id = (unsigned) bus->number; \ + \ + bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id], \ + bus_to_wid[bus_id]); \ + \ + __bit = (((where) & (bm)) << 3); \ + addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; \ + if (get_dbe(cf, addr)) \ + return PCIBIOS_DEVICE_NOT_FOUND; \ + *value = (cf >> __bit) & (mask); \ + return PCIBIOS_SUCCESSFUL; \ +} while (0) + +static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 * value) +{ + u32 vprod; + + CF0_READ_PCI_CFG(bus, devfn, PCI_VENDOR_ID, &vprod, 0, 0xffffffff); + if (vprod == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)) + && ((where >= 0x14 && where < 0x40) || (where >= 0x48))) { + *value = 0; + return PCIBIOS_SUCCESSFUL; + } + + if (size == 1) + CF0_READ_PCI_CFG(bus, devfn, where, (u8 *) value, 3, 0xff); + else if (size == 2) + CF0_READ_PCI_CFG(bus, devfn, where, (u16 *) value, 2, + 0xffff); + else + CF0_READ_PCI_CFG(bus, devfn, where, (u32 *) value, 0, + 0xffffffff); +} + +#define CF0_WRITE_PCI_CFG(bus,devfn,where,value,bm,mask) \ +do { \ + bridge_t *bridge; \ + int slot = PCI_SLOT(devfn); \ + int fn = PCI_FUNC(devfn); \ + volatile u32 *addr; \ + u32 cf, __bit; \ + unsigned int bus_id = (unsigned) bus->number; \ + \ + bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id], \ + bus_to_wid[bus_id]); \ + \ + __bit = (((where) & (bm)) << 3); \ + addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; \ + if (get_dbe(cf, addr)) \ + return PCIBIOS_DEVICE_NOT_FOUND; \ + cf &= (~mask); \ + cf |= (value); \ + put_dbe(cf, addr); \ + return PCIBIOS_SUCCESSFUL; \ +} while (0) + +static int pci_conf0_write_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 value) +{ + u32 vprod; + + CF0_READ_PCI_CFG(bus, devfn, PCI_VENDOR_ID, &vprod, 0, 0xffffffff); + if (vprod == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16)) + && ((where >= 0x14 && where < 0x40) || (where >= 0x48))) { + return PCIBIOS_SUCCESSFUL; + } + + if (size == 1) + CF0_WRITE_PCI_CFG(bus, devfn, where, (u8) value, 3, 0xff); + else if (size == 2) + CF0_WRITE_PCI_CFG(bus, devfn, where, (u16) value, 2, + 0xffff); + else + CF0_WRITE_PCI_CFG(bus, devfn, where, (u32) value, 0, + 0xffffffff); +} + +static struct pci_ops bridge_pci_ops = { + .read = pci_conf0_read_config, + .write = pci_conf0_write_config, +}; + +static int __init pcibios_init(void) +{ + struct pci_ops *ops = &bridge_pci_ops; + int i; + + ioport_resource.end = ~0UL; + + for (i = 0; i < num_bridges; i++) { + printk("PCI: Probing PCI hardware on host bus %2d.\n", i); + pci_scan_bus(i, ops, NULL); + } + + return 0; +} + +subsys_initcall(pcibios_init); + +static inline u8 bridge_swizzle(u8 pin, u8 slot) +{ + return (((pin - 1) + slot) % 4) + 1; +} + +static u8 __devinit pci_swizzle(struct pci_dev *dev, u8 * pinp) +{ + u8 pin = *pinp; + + while (dev->bus->self) { /* Move up the chain of bridges. */ + pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)); + dev = dev->bus->self; + } + *pinp = pin; + + return PCI_SLOT(dev->devfn); +} + +/* + * All observed requests have pin == 1. We could have a global here, that + * gets incremented and returned every time - unfortunately, pci_map_irq + * may be called on the same device over and over, and need to return the + * same value. On O2000, pin can be 0 or 1, and PCI slots can be [0..7]. + * + * A given PCI device, in general, should be able to intr any of the cpus + * on any one of the hubs connected to its xbow. + */ +static int __devinit pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + if ((dev->bus->number >= MAX_PCI_BUSSES) + || (pin != 1) + || (slot >= MAX_DEVICES_PER_PCIBUS)) + panic("Increase supported PCI busses %d,%d,%d", + dev->bus->number, slot, pin); + + /* + * Already assigned? Then return previously assigned value ... + */ + if (irqstore[dev->bus->number][slot]) + return irqstore[dev->bus->number][slot]; + + irq_to_bus[lastirq] = dev->bus->number; + irq_to_slot[lastirq] = slot; + irqstore[dev->bus->number][slot] = lastirq; + lastirq++; + return lastirq - 1; +} + +void __init pcibios_update_irq(struct pci_dev *dev, int irq) +{ + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); +} + +void __devinit pcibios_fixup_bus(struct pci_bus *b) +{ + pci_fixup_irqs(pci_swizzle, pci_map_irq); +} + +int pcibios_enable_device(struct pci_dev *dev, int mask) +{ + /* Not needed, since we enable all devices at startup. */ + return 0; +} + +void pcibios_align_resource(void *data, struct resource *res, + unsigned long size, unsigned long align) +{ +} + +unsigned int pcibios_assign_all_busses(void) +{ + return 0; +} + +char *__devinit pcibios_setup(char *str) +{ + /* Nothing to do for now. */ + + return str; +} + +/* + * Device might live on a subordinate PCI bus. XXX Walk up the chain of buses + * to find the slot number in sense of the bridge device register. + * XXX This also means multiple devices might rely on conflicting bridge + * settings. + */ + +static void __init pci_disable_swapping(struct pci_dev *dev) +{ + unsigned int bus_id = (unsigned) dev->bus->number; + bridge_t *bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id], + bus_to_wid[bus_id]); + int slot = PCI_SLOT(dev->devfn); + + /* Turn off byte swapping */ + bridge->b_device[slot].reg &= ~BRIDGE_DEV_SWAP_DIR; + bridge->b_widget.w_tflush; /* Flush */ +} + +static void __init pci_enable_swapping(struct pci_dev *dev) +{ + unsigned int bus_id = (unsigned) dev->bus->number; + bridge_t *bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id], + bus_to_wid[bus_id]); + int slot = PCI_SLOT(dev->devfn); + + /* Turn on byte swapping */ + bridge->b_device[slot].reg |= BRIDGE_DEV_SWAP_DIR; + bridge->b_widget.w_tflush; /* Flush */ +} + +static void __init pci_fixup_ioc3(struct pci_dev *d) +{ + unsigned long bus_id = (unsigned) d->bus->number; + + printk("PCI: Fixing base addresses for IOC3 device %s\n", + d->slot_name); + + d->resource[0].start |= NODE_OFFSET(bus_to_nid[bus_id]); + d->resource[0].end |= NODE_OFFSET(bus_to_nid[bus_id]); + + pci_disable_swapping(d); +} + +static void __init pci_fixup_isp1020(struct pci_dev *d) +{ + unsigned short command; + + d->resource[0].start |= + ((unsigned long) (bus_to_nid[d->bus->number]) << 32); + printk("PCI: Fixing isp1020 in [bus:slot.fn] %s\n", d->slot_name); + + /* + * Configure device to allow bus mastering, i/o and memory mapping. + * Older qlogicisp driver expects to have the IO space enable + * bit set. Things stop working if we program the controllers as not + * having PCI_COMMAND_MEMORY, so we have to fudge the mem_flags. + */ + + pci_set_master(d); + pci_read_config_word(d, PCI_COMMAND, &command); + command |= PCI_COMMAND_MEMORY; + command |= PCI_COMMAND_IO; + pci_write_config_word(d, PCI_COMMAND, command); + d->resource[1].flags |= 1; + + pci_enable_swapping(d); +} + +static void __init pci_fixup_isp2x00(struct pci_dev *d) +{ + unsigned int bus_id = (unsigned) d->bus->number; + bridge_t *bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id], + bus_to_wid[bus_id]); + bridgereg_t devreg; + int i; + int slot = PCI_SLOT(d->devfn); + unsigned int start; + unsigned short command; + + printk("PCI: Fixing isp2x00 in [bus:slot.fn] %s\n", d->slot_name); + + /* set the resource struct for this device */ + start = (u32) (u64) bridge; /* yes, we want to lose the upper 32 bits here */ + start |= BRIDGE_DEVIO(slot); + + d->resource[0].start = start; + d->resource[0].end = d->resource[0].start + 0xff; + d->resource[0].flags = IORESOURCE_IO; + + d->resource[1].start = start; + d->resource[1].end = d->resource[0].start + 0xfff; + d->resource[1].flags = IORESOURCE_MEM; + + /* + * set the bridge device(x) reg for this device + */ + devreg = bridge->b_device[slot].reg; + /* point device(x) to it appropriate small window */ + devreg &= ~BRIDGE_DEV_OFF_MASK; + devreg |= (start >> 20) & BRIDGE_DEV_OFF_MASK; + bridge->b_device[slot].reg = devreg; + + pci_enable_swapping(d); + + /* set card's base addr reg */ + //pci_write_config_dword(d, PCI_BASE_ADDRESS_0, 0x500001); + //pci_write_config_dword(d, PCI_BASE_ADDRESS_1, 0x8b00000); + //pci_write_config_dword(d, PCI_ROM_ADDRESS, 0x8b20000); + + /* I got these from booting irix on system... */ + pci_write_config_dword(d, PCI_BASE_ADDRESS_0, 0x200001); + //pci_write_config_dword(d, PCI_BASE_ADDRESS_1, 0xf800000); + pci_write_config_dword(d, PCI_ROM_ADDRESS, 0x10200000); + + pci_write_config_dword(d, PCI_BASE_ADDRESS_1, start); + //pci_write_config_dword(d, PCI_ROM_ADDRESS, (start | 0x20000)); + + /* set cache line size */ + pci_write_config_dword(d, PCI_CACHE_LINE_SIZE, 0xf080); + + /* set pci bus timeout */ + bridge->b_bus_timeout |= BRIDGE_BUS_PCI_RETRY_HLD(0x3); + bridge->b_wid_tflush; + printk("PCI: bridge bus timeout= 0x%x \n", bridge->b_bus_timeout); + + /* set host error field */ + bridge->b_int_host_err = 0x44; + bridge->b_wid_tflush; + + bridge->b_wid_tflush; /* wait until Bridge PIO complete */ + for (i = 0; i < 8; i++) + printk("PCI: device(%d)= 0x%x\n", i, + bridge->b_device[i].reg); + + /* configure device to allow bus mastering, i/o and memory mapping */ + pci_set_master(d); + pci_read_config_word(d, PCI_COMMAND, &command); + command |= PCI_COMMAND_MEMORY; + command |= PCI_COMMAND_IO; + pci_write_config_word(d, PCI_COMMAND, command); + /*d->resource[1].flags |= 1; */ +} + +struct pci_fixup pcibios_fixups[] = { + {PCI_FIXUP_HEADER, PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, + pci_fixup_ioc3}, + {PCI_FIXUP_HEADER, PCI_VENDOR_ID_QLOGIC, + PCI_DEVICE_ID_QLOGIC_ISP1020, + pci_fixup_isp1020}, + {PCI_FIXUP_HEADER, PCI_VENDOR_ID_QLOGIC, + PCI_DEVICE_ID_QLOGIC_ISP2100, + pci_fixup_isp2x00}, + {PCI_FIXUP_HEADER, PCI_VENDOR_ID_QLOGIC, + PCI_DEVICE_ID_QLOGIC_ISP2200, + pci_fixup_isp2x00}, + {0} +}; diff -Nru a/arch/mips/pci/pci-ip32.c b/arch/mips/pci/pci-ip32.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/pci-ip32.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,457 @@ +/* + * 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) 2000, 2001 Keith M Wesolowski + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef DEBUG_MACE_PCI + +/* + * O2 has up to 5 PCI devices connected into the MACE bridge. The device + * map looks like this: + * + * 0 aic7xxx 0 + * 1 aic7xxx 1 + * 2 expansion slot + * 3 N/C + * 4 N/C + */ + +#define chkslot(_bus,_devfn) \ +do { \ + if ((_bus)->number > 0 || PCI_SLOT (_devfn) < 1 \ + || PCI_SLOT (_devfn) > 3) \ + return PCIBIOS_DEVICE_NOT_FOUND; \ +} while (0) + +#define mkaddr(_devfn, where) \ +((((_devfn) & 0xffUL) << 8) | ((where) & 0xfcUL)) + +void macepci_error(int irq, void *dev, struct pt_regs *regs); + +static int macepci_read_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 * val) +{ + switch (size) { + case 1: + *val = 0xff; + chkslot(bus, devfn); + mace_write_32(MACEPCI_CONFIG_ADDR, mkaddr(devfn, where)); + *val = + mace_read_8(MACEPCI_CONFIG_DATA + + ((where & 3UL) ^ 3UL)); + + return PCIBIOS_SUCCESSFUL; + + case 2: + *val = 0xffff; + chkslot(bus, devfn); + if (where & 1) + return PCIBIOS_BAD_REGISTER_NUMBER; + mace_write_32(MACEPCI_CONFIG_ADDR, mkaddr(devfn, where)); + *val = + mace_read_16(MACEPCI_CONFIG_DATA + + ((where & 2UL) ^ 2UL)); + + return PCIBIOS_SUCCESSFUL; + + case 4: + *val = 0xffffffff; + chkslot(bus, devfn); + if (where & 3) + return PCIBIOS_BAD_REGISTER_NUMBER; + mace_write_32(MACEPCI_CONFIG_ADDR, mkaddr(devfn, where)); + *val = mace_read_32(MACEPCI_CONFIG_DATA); + + return PCIBIOS_SUCCESSFUL; + } +} + +static int macepci_write_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) +{ + switch (size) { + case 1: + chkslot(bus, devfn); + mace_write_32(MACEPCI_CONFIG_ADDR, mkaddr(devfn, where)); + mace_write_8(MACEPCI_CONFIG_DATA + ((where & 3UL) ^ 3UL), + val); + + return PCIBIOS_SUCCESSFUL; + + case 2: + chkslot(bus, devfn); + if (where & 1) + return PCIBIOS_BAD_REGISTER_NUMBER; + mace_write_32(MACEPCI_CONFIG_ADDR, mkaddr(devfn, where)); + mace_write_16(MACEPCI_CONFIG_DATA + ((where & 2UL) ^ 2UL), + val); + + return PCIBIOS_SUCCESSFUL; + + case 4: + chkslot(bus, devfn); + if (where & 3) + return PCIBIOS_BAD_REGISTER_NUMBER; + mace_write_32(MACEPCI_CONFIG_ADDR, mkaddr(devfn, where)); + mace_write_32(MACEPCI_CONFIG_DATA, val); + + return PCIBIOS_SUCCESSFUL; + } +} + +static struct pci_ops macepci_ops = { + .read = macepci_read_config, + .write = macepci_write_config, +}; + +struct pci_fixup pcibios_fixups[] = { {0} }; + +static int __init pcibios_init(void) +{ + struct pci_dev *dev = NULL; + u32 start, size; + u16 cmd; + u32 base_io = 0x3000; /* The first i/o address to assign after SCSI */ + u32 base_mem = 0x80100000; /* Likewise */ + u32 rev = mace_read_32(MACEPCI_REV); + int i; + + printk("MACE: PCI rev %d detected at %016lx\n", rev, + (u64) MACE_BASE + MACE_PCI); + + /* These are *bus* addresses */ + ioport_resource.start = 0; + ioport_resource.end = 0xffffffffUL; + iomem_resource.start = 0x80000000UL; + iomem_resource.end = 0xffffffffUL; + + /* Clear any outstanding errors and enable interrupts */ + mace_write_32(MACEPCI_ERROR_ADDR, 0); + mace_write_32(MACEPCI_ERROR_FLAGS, 0); + mace_write_32(MACEPCI_CONTROL, 0xff008500); + crime_write_64(CRIME_HARD_INT, 0UL); + crime_write_64(CRIME_SOFT_INT, 0UL); + crime_write_64(CRIME_INT_STAT, 0x000000000000ff00UL); + + if (request_irq(MACE_PCI_BRIDGE_IRQ, macepci_error, 0, + "MACE PCI error", NULL)) + panic("PCI bridge can't get interrupt; can't happen."); + + pci_scan_bus(0, &macepci_ops, NULL); + +#ifdef DEBUG_MACE_PCI + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + printk("Device: %d/%d/%d ARCS-assigned bus resource map\n", + dev->bus->number, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn)); + for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { + if (dev->resource[i].start == 0) + continue; + printk("%d: %016lx - %016lx (flags %04lx)\n", + i, dev->resource[i].start, + dev->resource[i].end, + dev->resource[i].flags); + } + } +#endif + /* + * Assign sane resources to and enable all devices. The requirement + * for the SCSI controllers is well-known: a 256-byte I/O region + * which we must assign, and a 1-page memory region which is + * assigned by the system firmware. + */ + dev = NULL; + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + switch (PCI_SLOT(dev->devfn)) { + case 1: /* SCSI bus 0 */ + dev->resource[0].start = 0x1000UL; + dev->resource[0].end = 0x10ffUL; + break; + case 2: /* SCSI bus 1 */ + dev->resource[0].start = 0x2000UL; + dev->resource[0].end = 0x20ffUL; + break; + default: /* Slots - I guess we have only 1 */ + for (i = 0; i < 6; i++) { + size = dev->resource[i].end + - dev->resource[i].start; + if (!size + || !(dev->resource[i].flags + & (IORESOURCE_IO | + IORESOURCE_MEM))) { + dev->resource[i].start = + dev->resource[i].end = 0UL; + continue; + } + if (dev->resource[i].flags & IORESOURCE_IO) { + dev->resource[i].start = base_io; + base_io += PAGE_ALIGN(size); + } else { + dev->resource[i].start = base_mem; + base_mem += 0x100000UL; + } + dev->resource[i].end = + dev->resource[i].start + size; + } + break; + } + for (i = 0; i < 6; i++) { + if (dev->resource[i].start == 0) + continue; + start = dev->resource[i].start; + if (dev->resource[i].flags & IORESOURCE_IO) + start |= 1; + pci_write_config_dword(dev, + PCI_BASE_ADDRESS_0 + + (i << 2), (u32) start); + } + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x20); + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x30); + pci_read_config_word(dev, PCI_COMMAND, &cmd); + cmd |= + (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | + PCI_COMMAND_SPECIAL | PCI_COMMAND_INVALIDATE | + PCI_COMMAND_PARITY); + pci_write_config_word(dev, PCI_COMMAND, cmd); + pci_set_master(dev); + } + /* + * Fixup O2 PCI slot. Bad hack. + */ +/* devtag = pci_make_tag(0, 0, 3, 0); + + slot = macepci_conf_read(0, devtag, PCI_COMMAND_STATUS_REG); + slot |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE; + macepci_conf_write(0, devtag, PCI_COMMAND_STATUS_REG, slot); + + slot = macepci_conf_read(0, devtag, PCI_MAPREG_START); + if (slot == 0xffffffe1) + macepci_conf_write(0, devtag, PCI_MAPREG_START, 0x00001000); + + slot = macepci_conf_read(0, devtag, PCI_MAPREG_START + (2 << 2)); + if ((slot & 0xffff0000) == 0) { + slot += 0x00010000; + macepci_conf_write(0, devtag, PCI_MAPREG_START + (2 << 2), + 0x00000000); + } + */ +#ifdef DEBUG_MACE_PCI + printk("Triggering PCI bridge interrupt...\n"); + mace_write_32(MACEPCI_ERROR_FLAGS, MACEPCI_ERROR_INTERRUPT_TEST); + + dev = NULL; + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + printk("Device: %d/%d/%d final bus resource map\n", + dev->bus->number, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn)); + for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { + if (dev->resource[i].start == 0) + continue; + printk("%d: %016lx - %016lx (flags %04lx)\n", + i, dev->resource[i].start, + dev->resource[i].end, + dev->resource[i].flags); + } + } +#endif + + return 0; +} + +subsys_initcall(pcibios_init); + +/* + * Given a PCI slot number (a la PCI_SLOT(...)) and the interrupt pin of + * the device (1-4 => A-D), tell what irq to use. Note that we don't + * in theory have slots 4 and 5, and we never normally use the shared + * irqs. I suppose a device without a pin A will thank us for doing it + * right if there exists such a broken piece of crap. + */ +static int __devinit macepci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + chkslot(dev->bus, dev->devfn); + if (pin == 0) + pin = 1; + switch (slot) { + case 1: + return MACEPCI_SCSI0_IRQ; + case 2: + return MACEPCI_SCSI1_IRQ; + case 3: + switch (pin) { + case 2: + return MACEPCI_SHARED0_IRQ; + case 3: + return MACEPCI_SHARED1_IRQ; + case 4: + return MACEPCI_SHARED2_IRQ; + case 1: + default: + return MACEPCI_SLOT0_IRQ; + } + case 4: + switch (pin) { + case 2: + return MACEPCI_SHARED2_IRQ; + case 3: + return MACEPCI_SHARED0_IRQ; + case 4: + return MACEPCI_SHARED1_IRQ; + case 1: + default: + return MACEPCI_SLOT1_IRQ; + } + return MACEPCI_SLOT1_IRQ; + case 5: + switch (pin) { + case 2: + return MACEPCI_SHARED1_IRQ; + case 3: + return MACEPCI_SHARED2_IRQ; + case 4: + return MACEPCI_SHARED0_IRQ; + case 1: + default: + return MACEPCI_SLOT2_IRQ; + } + default: + return 0; + } +} + +/* + * It's not entirely clear what this does in a system with no bridges. + * In any case, bridges are not supported by Linux in O2. + */ +static u8 __init macepci_swizzle(struct pci_dev *dev, u8 * pinp) +{ + if (PCI_SLOT(dev->devfn) == 2) + *pinp = 2; + else + *pinp = 1; + return PCI_SLOT(dev->devfn); +} + +/* All devices are enabled during initialization. */ +int pcibios_enable_device(struct pci_dev *dev, int mask) +{ + return PCIBIOS_SUCCESSFUL; +} + +char *__init pcibios_setup(char *str) +{ + return str; +} + +void pcibios_align_resource(void *data, struct resource *res, + unsigned long size, unsigned long align) +{ +} + +void __init pcibios_update_irq(struct pci_dev *dev, int irq) +{ + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); +} + +void __devinit pcibios_fixup_bus(struct pci_bus *b) +{ + pci_fixup_irqs(macepci_swizzle, macepci_map_irq); +} + +/* + * Handle errors from the bridge. This includes master and target aborts, + * various command and address errors, and the interrupt test. This gets + * registered on the bridge error irq. It's conceivable that some of these + * conditions warrant a panic. Anybody care to say which ones? + */ +void macepci_error(int irq, void *dev, struct pt_regs *regs) +{ + u32 flags, error_addr; + char space; + + flags = mace_read_32(MACEPCI_ERROR_FLAGS); + error_addr = mace_read_32(MACEPCI_ERROR_ADDR); + + if (flags & MACEPCI_ERROR_MEMORY_ADDR) + space = 'M'; + else if (flags & MACEPCI_ERROR_CONFIG_ADDR) + space = 'C'; + else + space = 'X'; + + if (flags & MACEPCI_ERROR_MASTER_ABORT) { + printk("MACEPCI: Master abort at 0x%08x (%c)\n", + error_addr, space); + mace_write_32(MACEPCI_ERROR_FLAGS, + flags & ~MACEPCI_ERROR_MASTER_ABORT); + } + if (flags & MACEPCI_ERROR_TARGET_ABORT) { + printk("MACEPCI: Target abort at 0x%08x (%c)\n", + error_addr, space); + mace_write_32(MACEPCI_ERROR_FLAGS, + flags & ~MACEPCI_ERROR_TARGET_ABORT); + } + if (flags & MACEPCI_ERROR_DATA_PARITY_ERR) { + printk("MACEPCI: Data parity error at 0x%08x (%c)\n", + error_addr, space); + mace_write_32(MACEPCI_ERROR_FLAGS, flags + & ~MACEPCI_ERROR_DATA_PARITY_ERR); + } + if (flags & MACEPCI_ERROR_RETRY_ERR) { + printk("MACEPCI: Retry error at 0x%08x (%c)\n", error_addr, + space); + mace_write_32(MACEPCI_ERROR_FLAGS, flags + & ~MACEPCI_ERROR_RETRY_ERR); + } + if (flags & MACEPCI_ERROR_ILLEGAL_CMD) { + printk("MACEPCI: Illegal command at 0x%08x (%c)\n", + error_addr, space); + mace_write_32(MACEPCI_ERROR_FLAGS, + flags & ~MACEPCI_ERROR_ILLEGAL_CMD); + } + if (flags & MACEPCI_ERROR_SYSTEM_ERR) { + printk("MACEPCI: System error at 0x%08x (%c)\n", + error_addr, space); + mace_write_32(MACEPCI_ERROR_FLAGS, flags + & ~MACEPCI_ERROR_SYSTEM_ERR); + } + if (flags & MACEPCI_ERROR_PARITY_ERR) { + printk("MACEPCI: Parity error at 0x%08x (%c)\n", + error_addr, space); + mace_write_32(MACEPCI_ERROR_FLAGS, + flags & ~MACEPCI_ERROR_PARITY_ERR); + } + if (flags & MACEPCI_ERROR_OVERRUN) { + printk("MACEPCI: Overrun error at 0x%08x (%c)\n", + error_addr, space); + mace_write_32(MACEPCI_ERROR_FLAGS, flags + & ~MACEPCI_ERROR_OVERRUN); + } + if (flags & MACEPCI_ERROR_SIG_TABORT) { + printk("MACEPCI: Signaled target abort (clearing)\n"); + mace_write_32(MACEPCI_ERROR_FLAGS, flags + & ~MACEPCI_ERROR_SIG_TABORT); + } + if (flags & MACEPCI_ERROR_INTERRUPT_TEST) { + printk("MACEPCI: Interrupt test triggered (clearing)\n"); + mace_write_32(MACEPCI_ERROR_FLAGS, flags + & ~MACEPCI_ERROR_INTERRUPT_TEST); + } +} + +unsigned int pcibios_assign_all_busses(void) +{ + return 0; +} diff -Nru a/arch/mips/pci/pci-lasat.c b/arch/mips/pci/pci-lasat.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/pci-lasat.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,245 @@ +#include +#include +#include +#include + +#include +#include +#include + +#define PCI_ACCESS_READ 0 +#define PCI_ACCESS_WRITE 1 + +#undef DEBUG_PCI +#ifdef DEBUG_PCI +#define Dprintk(fmt...) printk(fmt) +#else +#define Dprintk(fmt...) +#endif + +static int (*lasat_pcibios_config_access) (unsigned char access_type, + struct pci_bus * bus, + unsigned int devfn, int where, + u32 * val); + +/* + * Because of an error/peculiarity in the Galileo chip, we need to swap the + * bytes when running bigendian. + */ +#define GT_WRITE(ofs, data) \ + *(volatile u32 *)(LASAT_GT_BASE+ofs) = cpu_to_le32(data) +#define GT_READ(ofs, data) \ + data = le32_to_cpu(*(volatile u32 *)(LASAT_GT_BASE+ofs)) + + +static int lasat_pcibios_config_access_100(unsigned char access_type, + struct pci_bus *bus, + unsigned int devfn, int where, + u32 * val) +{ + unsigned char busnum = bus->number; + u32 intr; + + if ((busnum == 0) && (devfn >= PCI_DEVFN(31, 0))) + return -1; /* Because of a bug in the Galileo (for slot 31). */ + + /* Clear cause register bits */ + GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT | + GT_INTRCAUSE_TARABORT0_BIT)); + + /* Setup address */ + GT_WRITE(GT_PCI0_CFGADDR_OFS, + (busnum << GT_PCI0_CFGADDR_BUSNUM_SHF) | + (devfn << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | + ((where / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) | + GT_PCI0_CFGADDR_CONFIGEN_BIT); + + if (access_type == PCI_ACCESS_WRITE) { + GT_WRITE(GT_PCI0_CFGDATA_OFS, *val); + } else { + GT_READ(GT_PCI0_CFGDATA_OFS, *val); + } + + /* Check for master or target abort */ + GT_READ(GT_INTRCAUSE_OFS, intr); + + if (intr & + (GT_INTRCAUSE_MASABORT0_BIT | GT_INTRCAUSE_TARABORT0_BIT)) { + /* Error occurred */ + + /* Clear bits */ + GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT | + GT_INTRCAUSE_TARABORT0_BIT)); + + return -1; + } + + return 0; +} + +#define LO(reg) (reg / 4) +#define HI(reg) (reg / 4 + 1) + +volatile unsigned long *const vrc_pciregs = (void *) Vrc5074_BASE; + +static int lasat_pcibios_config_access_200(unsigned char access_type, + struct pci_bus *bus, + unsigned int devfn, int where, + u32 * val) +{ + unsigned char busnum = bus->number; + u32 adr, mask, err; + + if ((busnum == 0) && (PCI_SLOT(devfn) > 8)) + /* The addressing scheme chosen leaves room for just + * 8 devices on the first busnum (besides the PCI + * controller itself) */ + return -1; + + if ((busnum == 0) && (devfn == PCI_DEVFN(0, 0))) { + /* Access controller registers directly */ + if (access_type == PCI_ACCESS_WRITE) { + vrc_pciregs[(0x200 + where) >> 2] = *val; + } else { + *val = vrc_pciregs[(0x200 + where) >> 2]; + } + return 0; + } + + /* Temporarily map PCI Window 1 to config space */ + mask = vrc_pciregs[LO(NILE4_PCIINIT1)]; + vrc_pciregs[LO(NILE4_PCIINIT1)] = + 0x0000001a | (busnum ? 0x200 : 0); + + /* Clear PCI Error register. This also clears the Error Type + * bits in the Control register */ + vrc_pciregs[LO(NILE4_PCIERR)] = 0; + vrc_pciregs[HI(NILE4_PCIERR)] = 0; + + /* Setup address */ + if (busnum == 0) + adr = + KSEG1ADDR(PCI_WINDOW1) + + ((1 << (PCI_SLOT(devfn) + 15)) | (PCI_FUNC(devfn) << 8) + | (where & ~3)); + else + adr = + KSEG1ADDR(PCI_WINDOW1) | (busnum << 16) | (devfn << 8) + | (where & ~3); + +#ifdef DEBUG_PCI + printk("PCI config %s: adr %x", + access_type == PCI_ACCESS_WRITE ? "write" : "read", adr); +#endif + + if (access_type == PCI_ACCESS_WRITE) { + *(u32 *) adr = *val; + } else { + *val = *(u32 *) adr; + } + +#ifdef DEBUG_PCI + printk(" value = %x\n", *val); +#endif + + /* Check for master or target abort */ + err = (vrc_pciregs[HI(NILE4_PCICTRL)] >> 5) & 0x7; + + /* Restore PCI Window 1 */ + vrc_pciregs[LO(NILE4_PCIINIT1)] = mask; + + if (err) { + /* Error occured */ +#ifdef DEBUG_PCI + printk("\terror %x at adr %x\n", err, + vrc_pciregs[LO(NILE4_PCIERR)]); +#endif + return -1; + } + + return 0; +} + +static int lasat_pcibios_read(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 * val) +{ + u32 data = 0; + + if ((size == 2) && (where & 1)) + return PCIBIOS_BAD_REGISTER_NUMBER; + else if ((size == 4) && (where & 3)) + return PCIBIOS_BAD_REGISTER_NUMBER; + + if (lasat_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where, + &data)) + return -1; + + if (size == 1) + *val = (data >> ((where & 3) << 3)) & 0xff; + else if (size == 2) + *val = (data >> ((where & 3) << 3)) & 0xffff; + else + *val = data; + + return PCIBIOS_SUCCESSFUL; +} + +static int lasat_pcibios_write(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) +{ + u32 data = 0; + + if ((size == 2) && (where & 1)) + return PCIBIOS_BAD_REGISTER_NUMBER; + else if ((size == 4) && (where & 3)) + return PCIBIOS_BAD_REGISTER_NUMBER; + + if (lasat_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where, + &data)) + return -1; + + if (size == 1) + data = (data & ~(0xff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + else if (size == 2) + data = (data & ~(0xffff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + else + data = val; + + if (lasat_pcibios_config_access + (PCI_ACCESS_WRITE, bus, devfn, where, &data)) + return -1; + + return PCIBIOS_SUCCESSFUL; +} + +struct pci_ops lasat_pci_ops = { + .read = lasat_pcibios_read, + .write = lasat_pcibios_write, +}; + +static int __init pcibios_init(void) +{ + switch (mips_machtype) { + case MACH_LASAT_100: + lasat_pcibios_config_access = + &lasat_pcibios_config_access_100; + break; + case MACH_LASAT_200: + lasat_pcibios_config_access = + &lasat_pcibios_config_access_200; + break; + default: + panic("pcibios_init: mips_machtype incorrect"); + } + + Dprintk("pcibios_init()\n"); + pci_scan_bus(0, &lasat_pci_ops, NULL); + return 0; +} + +unsigned __init int pcibios_assign_all_busses(void) +{ + return 1; +} diff -Nru a/arch/mips/pci/pci-mips.c b/arch/mips/pci/pci-mips.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/pci-mips.c Tue Jul 1 18:44:39 2003 @@ -0,0 +1,479 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 1999, 2000 MIPS Technologies, Inc. All rights reserved. + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * MIPS boards specific PCI support. + * + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#ifdef CONFIG_MIPS_MALTA +#include +#endif +#include + +#define PCI_ACCESS_READ 0 +#define PCI_ACCESS_WRITE 1 + +/* + * PCI configuration cycle AD bus definition + */ +/* Type 0 */ +#define PCI_CFG_TYPE0_REG_SHF 0 +#define PCI_CFG_TYPE0_FUNC_SHF 8 + +/* Type 1 */ +#define PCI_CFG_TYPE1_REG_SHF 0 +#define PCI_CFG_TYPE1_FUNC_SHF 8 +#define PCI_CFG_TYPE1_DEV_SHF 11 +#define PCI_CFG_TYPE1_BUS_SHF 16 + +static int mips_pcibios_config_access(unsigned char access_type, + struct pci_bus *bus, + unsigned int devfn, int where, + u32 * data) +{ + unsigned char busnum = bus->number; + unsigned char type; + u32 intr, dummy; + u64 pci_addr; + + switch (mips_revision_corid) { + case MIPS_REVISION_CORID_QED_RM5261: + case MIPS_REVISION_CORID_CORE_LV: + case MIPS_REVISION_CORID_CORE_FPGA: + /* Galileo GT64120 system controller. */ + + if ((busnum == 0) && (devfn >= PCI_DEVFN(31, 0))) + return -1; /* Because of a bug in the galileo (for slot 31). */ + + /* Clear cause register bits */ + GT_READ(GT_INTRCAUSE_OFS, intr); + GT_WRITE(GT_INTRCAUSE_OFS, intr & + ~(GT_INTRCAUSE_MASABORT0_BIT | + GT_INTRCAUSE_TARABORT0_BIT)); + + /* Setup address */ + GT_WRITE(GT_PCI0_CFGADDR_OFS, + (busnum << GT_PCI0_CFGADDR_BUSNUM_SHF) | + (devfn << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | + ((where / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) | + GT_PCI0_CFGADDR_CONFIGEN_BIT); + + if (access_type == PCI_ACCESS_WRITE) { + if (busnum == 0 && devfn == 0) { + /* + * The Galileo system controller is acting + * differently than other devices. + */ + GT_WRITE(GT_PCI0_CFGDATA_OFS, *data); + } else { + GT_PCI_WRITE(GT_PCI0_CFGDATA_OFS, *data); + } + } else { + if (busnum == 0 && devfn == 0) { + /* + * The Galileo system controller is acting + * differently than other devices. + */ + GT_READ(GT_PCI0_CFGDATA_OFS, *data); + } else { + GT_PCI_READ(GT_PCI0_CFGDATA_OFS, *data); + } + } + + /* Check for master or target abort */ + GT_READ(GT_INTRCAUSE_OFS, intr); + + if (intr & (GT_INTRCAUSE_MASABORT0_BIT | + GT_INTRCAUSE_TARABORT0_BIT)) { + /* Error occurred */ + + /* Clear bits */ + GT_READ(GT_INTRCAUSE_OFS, intr); + GT_WRITE(GT_INTRCAUSE_OFS, intr & + ~(GT_INTRCAUSE_MASABORT0_BIT | + GT_INTRCAUSE_TARABORT0_BIT)); + + return -1; + } + + break; + + case MIPS_REVISION_CORID_BONITO64: + case MIPS_REVISION_CORID_CORE_20K: + /* Algorithmics Bonito64 system controller. */ + + if ((busnum == 0) && (PCI_SLOT(devfn) == 0)) { + return -1; + } + + /* Clear cause register bits */ + BONITO_PCICMD |= (BONITO_PCICMD_MABORT_CLR | + BONITO_PCICMD_MTABORT_CLR); + + /* + * Setup pattern to be used as PCI "address" for + * Type 0 cycle + */ + if (busnum == 0) { + /* IDSEL */ + pci_addr = (u64) 1 << (PCI_SLOT(devfn) + 10); + } else { + /* Bus number */ + pci_addr = busnum << PCI_CFG_TYPE1_BUS_SHF; + + /* Device number */ + pci_addr |= + PCI_SLOT(devfn) << PCI_CFG_TYPE1_DEV_SHF; + } + + /* Function (same for Type 0/1) */ + pci_addr |= PCI_FUNC(devfn) << PCI_CFG_TYPE0_FUNC_SHF; + + /* Register number (same for Type 0/1) */ + pci_addr |= (where & ~0x3) << PCI_CFG_TYPE0_REG_SHF; + + if (busnum == 0) { + /* Type 0 */ + BONITO_PCIMAP_CFG = pci_addr >> 16; + } else { + /* Type 1 */ + BONITO_PCIMAP_CFG = (pci_addr >> 16) | 0x10000; + } + + /* Flush Bonito register block */ + dummy = BONITO_PCIMAP_CFG; + iob(); /* sync */ + + /* Perform access */ + if (access_type == PCI_ACCESS_WRITE) { + *(volatile u32 *) (KSEG1ADDR(BONITO_PCICFG_BASE + + (pci_addr & 0xffff))) + = *(u32 *) data; + + /* Wait till done */ + while (BONITO_PCIMSTAT & 0xF); + } else { + *(u32 *) data = + *(volatile u32 + *) (KSEG1ADDR(BONITO_PCICFG_BASE + + (pci_addr & 0xffff))); + } + + /* Detect Master/Target abort */ + if (BONITO_PCICMD & (BONITO_PCICMD_MABORT_CLR | + BONITO_PCICMD_MTABORT_CLR)) { + /* Error occurred */ + + /* Clear bits */ + BONITO_PCICMD |= (BONITO_PCICMD_MABORT_CLR | + BONITO_PCICMD_MTABORT_CLR); + + return -1; + } + break; + + case MIPS_REVISION_CORID_CORE_MSC: + /* MIPS system controller. */ + + if ((busnum == 0) && (PCI_SLOT(devfn) == 0)) { + return -1; + } + + /* Clear status register bits. */ + MSC_WRITE(MSC01_PCI_INTSTAT, + (MSC01_PCI_INTCFG_MA_BIT | + MSC01_PCI_INTCFG_TA_BIT)); + + /* Setup address */ + if (busnum == 0) + type = 0; /* Type 0 */ + else + type = 1; /* Type 1 */ + + MSC_WRITE(MSC01_PCI_CFGADDR, + ((busnum << MSC01_PCI_CFGADDR_BNUM_SHF) | + (PCI_SLOT(devfn) << MSC01_PCI_CFGADDR_DNUM_SHF) + | (PCI_FUNC(devfn) << + MSC01_PCI_CFGADDR_FNUM_SHF) | ((where / + 4) << + MSC01_PCI_CFGADDR_RNUM_SHF) + | (type))); + + /* Perform access */ + if (access_type == PCI_ACCESS_WRITE) { + MSC_WRITE(MSC01_PCI_CFGDATA, *data); + } else { + MSC_READ(MSC01_PCI_CFGDATA, *data); + } + + /* Detect Master/Target abort */ + MSC_READ(MSC01_PCI_INTSTAT, intr); + if (intr & (MSC01_PCI_INTCFG_MA_BIT | + MSC01_PCI_INTCFG_TA_BIT)) { + /* Error occurred */ + + /* Clear bits */ + MSC_READ(MSC01_PCI_INTSTAT, intr); + MSC_WRITE(MSC01_PCI_INTSTAT, + (MSC01_PCI_INTCFG_MA_BIT | + MSC01_PCI_INTCFG_TA_BIT)); + + return -1; + } + break; + default: + printk + ("Unknown Core card, don't know the system controller.\n"); + return -1; + } + + return 0; +} + + +/* + * We can't address 8 and 16 bit words directly. Instead we have to + * read/write a 32bit word and mask/modify the data we actually want. + */ +static int mips_pcibios_read(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 * val) +{ + u32 data = 0; + + if ((size == 2) && (where & 1)) + return PCIBIOS_BAD_REGISTER_NUMBER; + else if ((size == 4) && (where & 3)) + return PCIBIOS_BAD_REGISTER_NUMBER; + + if (mips_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where, + &data)) + return -1; + + if (size == 1) + *val = (data >> ((where & 3) << 3)) & 0xff; + else if (size == 2) + *val = (data >> ((where & 3) << 3)) & 0xffff; + else + *val = data; + + return PCIBIOS_SUCCESSFUL; +} + +static int mips_pcibios_write(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) +{ + u32 data = 0; + + if ((size == 2) && (where & 1)) + return PCIBIOS_BAD_REGISTER_NUMBER; + else if ((size == 4) && (where & 3)) + return PCIBIOS_BAD_REGISTER_NUMBER; + + if (mips_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where, + &data)) + return -1; + + if (size == 1) + data = (data & ~(0xff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + else if (size == 2) + data = (data & ~(0xffff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + + if (mips_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn, where, + &data)) + return -1; + + return PCIBIOS_SUCCESSFUL; +} + +struct pci_ops mips_pci_ops = { + .read = mips_pcibios_read, + .write = mips_pcibios_write +}; + +int mips_pcibios_iack(void) +{ + int irq; + u32 dummy; + + /* + * Determine highest priority pending interrupt by performing + * a PCI Interrupt Acknowledge cycle. + */ + switch (mips_revision_corid) { + case MIPS_REVISION_CORID_QED_RM5261: + case MIPS_REVISION_CORID_CORE_LV: + case MIPS_REVISION_CORID_CORE_FPGA: + case MIPS_REVISION_CORID_CORE_MSC: + if (mips_revision_corid == MIPS_REVISION_CORID_CORE_MSC) + MSC_READ(MSC01_PCI_IACK, irq); + else + GT_READ(GT_PCI0_IACK_OFS, irq); + irq &= 0xff; + break; + case MIPS_REVISION_CORID_BONITO64: + case MIPS_REVISION_CORID_CORE_20K: + /* The following will generate a PCI IACK cycle on the + * Bonito controller. It's a little bit kludgy, but it + * was the easiest way to implement it in hardware at + * the given time. + */ + BONITO_PCIMAP_CFG = 0x20000; + + /* Flush Bonito register block */ + dummy = BONITO_PCIMAP_CFG; + iob(); /* sync */ + + irq = *(volatile u32 *) (KSEG1ADDR(BONITO_PCICFG_BASE)); + iob(); /* sync */ + irq &= 0xff; + BONITO_PCIMAP_CFG = 0; + break; + default: + printk + ("Unknown Core card, don't know the system controller.\n"); + return -1; + } + return irq; +} + +static int __init pcibios_init(void) +{ +#ifdef CONFIG_MIPS_MALTA + struct pci_dev *pdev = NULL; + unsigned char reg_val; +#endif + + printk("PCI: Probing PCI hardware on host bus 0.\n"); + pci_scan_bus(0, &mips_pci_ops, NULL); + + switch (mips_revision_corid) { + case MIPS_REVISION_CORID_QED_RM5261: + case MIPS_REVISION_CORID_CORE_LV: + case MIPS_REVISION_CORID_CORE_FPGA: + /* + * Due to a bug in the Galileo system controller, we need + * to setup the PCI BAR for the Galileo internal registers. + * This should be done in the bios/bootprom and will be + * fixed in a later revision of YAMON (the MIPS boards + * boot prom). + */ + GT_WRITE(GT_PCI0_CFGADDR_OFS, (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) | /* Local bus */ + (0 << GT_PCI0_CFGADDR_DEVNUM_SHF) | /* GT64120 dev */ + (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | /* Function 0 */ + ((0x20 / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) | /* BAR 4 */ + GT_PCI0_CFGADDR_CONFIGEN_BIT); + + /* Perform the write */ + GT_WRITE(GT_PCI0_CFGDATA_OFS, PHYSADDR(MIPS_GT_BASE)); + break; + } + +#ifdef CONFIG_MIPS_MALTA + while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) { + if ((pdev->vendor == PCI_VENDOR_ID_INTEL) + && (pdev->device == PCI_DEVICE_ID_INTEL_82371AB) + && (PCI_SLOT(pdev->devfn) == 0x0a)) { + /* + * IDE Decode enable. + */ + pci_read_config_byte(pdev, 0x41, ®_val); + pci_write_config_byte(pdev, 0x41, reg_val | 0x80); + pci_read_config_byte(pdev, 0x43, ®_val); + pci_write_config_byte(pdev, 0x43, reg_val | 0x80); + } + + if ((pdev->vendor == PCI_VENDOR_ID_INTEL) + && (pdev->device == PCI_DEVICE_ID_INTEL_82371AB_0) + && (PCI_SLOT(pdev->devfn) == 0x0a)) { + /* + * Set top of main memory accessible by ISA or DMA + * devices to 16 Mb. + */ + pci_read_config_byte(pdev, 0x69, ®_val); + pci_write_config_byte(pdev, 0x69, reg_val | 0xf0); + } + } + + /* + * Activate Floppy Controller in the SMSC FDC37M817 Super I/O + * Controller. + * This should be done in the bios/bootprom and will be fixed in + * a later revision of YAMON (the MIPS boards boot prom). + */ + /* Entering config state. */ + SMSC_WRITE(SMSC_CONFIG_ENTER, SMSC_CONFIG_REG); + + /* Activate floppy controller. */ + SMSC_WRITE(SMSC_CONFIG_DEVNUM, SMSC_CONFIG_REG); + SMSC_WRITE(SMSC_CONFIG_DEVNUM_FLOPPY, SMSC_DATA_REG); + SMSC_WRITE(SMSC_CONFIG_ACTIVATE, SMSC_CONFIG_REG); + SMSC_WRITE(SMSC_CONFIG_ACTIVATE_ENABLE, SMSC_DATA_REG); + + /* Exit config state. */ + SMSC_WRITE(SMSC_CONFIG_EXIT, SMSC_CONFIG_REG); +#endif + + return 0; +} + +subsys_initcall(pcibios_init); + +int pcibios_enable_device(struct pci_dev *dev, int mask) +{ + /* Not needed, since we enable all devices at startup. */ + return 0; +} + +void pcibios_align_resource(void *data, struct resource *res, + unsigned long size, unsigned long align) +{ +} + +char *__init pcibios_setup(char *str) +{ + /* Nothing to do for now. */ + + return str; +} + +struct pci_fixup pcibios_fixups[] = { + {0} +}; + +/* + * Called after each bus is probed, but before its children + * are examined. + */ +void __devinit pcibios_fixup_bus(struct pci_bus *b) +{ + pci_read_bridge_bases(b); +} + +unsigned int pcibios_assign_all_busses(void) +{ + return 1; +} diff -Nru a/arch/mips/pci/pci-ocelot-c.c b/arch/mips/pci/pci-ocelot-c.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/pci-ocelot-c.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,458 @@ +/* + * Copyright 2002 Momentum Computer + * Author: Matthew Dharm + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* + * These functions and structures provide the BIOS scan and mapping of the PCI + * devices. + */ + +#define MAX_PCI_DEVS 10 + +void mv64340_board_pcibios_fixup_bus(struct pci_bus *c); + +/* Functions to implement "pci ops" */ +static int marvell_pcibios_read_config_word(struct pci_dev *dev, + int offset, u16 * val); +static int marvell_pcibios_read_config_byte(struct pci_dev *dev, + int offset, u8 * val); +static int marvell_pcibios_read_config_dword(struct pci_dev *dev, + int offset, u32 * val); +static int marvell_pcibios_write_config_byte(struct pci_dev *dev, + int offset, u8 val); +static int marvell_pcibios_write_config_word(struct pci_dev *dev, + int offset, u16 val); +static int marvell_pcibios_write_config_dword(struct pci_dev *dev, + int offset, u32 val); +static void marvell_pcibios_set_master(struct pci_dev *dev); + +/* + * General-purpose PCI functions. + */ + + +/* + * pci_range_ck - + * + * Check if the pci device that are trying to access does really exists + * on the evaluation board. + * + * Inputs : + * bus - bus number (0 for PCI 0 ; 1 for PCI 1) + * dev - number of device on the specific pci bus + * + * Outpus : + * 0 - if OK , 1 - if failure + */ +static __inline__ int pci_range_ck(unsigned char bus, unsigned char dev) +{ + /* Accessing device 31 crashes the MV-64340. */ + if (dev < 5) + return 0; + return -1; +} + +/* + * marvell_pcibios_(read/write)_config_(dword/word/byte) - + * + * reads/write a dword/word/byte register from the configuration space + * of a device. + * + * Note that bus 0 and bus 1 are local, and we assume all other busses are + * bridged from bus 1. This is a safe assumption, since any other + * configuration will require major modifications to the CP7000G + * + * Inputs : + * bus - bus number + * dev - device number + * offset - register offset in the configuration space + * val - value to be written / read + * + * Outputs : + * PCIBIOS_SUCCESSFUL when operation was succesfull + * PCIBIOS_DEVICE_NOT_FOUND when the bus or dev is errorneous + * PCIBIOS_BAD_REGISTER_NUMBER when accessing non aligned + */ + +static int marvell_pcibios_read_config_dword(struct pci_dev *device, + int offset, u32 * val) +{ + int dev, bus, func; + uint32_t address_reg, data_reg; + uint32_t address; + + bus = device->bus->number; + dev = PCI_SLOT(device->devfn); + func = PCI_FUNC(device->devfn); + + /* verify the range */ + if (pci_range_ck(bus, dev)) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* select the MV-64340 registers to communicate with the PCI bus */ + if (bus == 0) { + address_reg = MV64340_PCI_0_CONFIG_ADDR; + data_reg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG; + } else { + address_reg = MV64340_PCI_1_CONFIG_ADDR; + data_reg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG; + } + + address = (bus << 16) | (dev << 11) | (func << 8) | + (offset & 0xfc) | 0x80000000; + + /* start the configuration cycle */ + MV_WRITE(address_reg, address); + + /* read the data */ + MV_READ(data_reg, val); + + return PCIBIOS_SUCCESSFUL; +} + + +static int marvell_pcibios_read_config_word(struct pci_dev *device, + int offset, u16 * val) +{ + int dev, bus, func; + uint32_t address_reg, data_reg; + uint32_t address; + + bus = device->bus->number; + dev = PCI_SLOT(device->devfn); + func = PCI_FUNC(device->devfn); + + /* verify the range */ + if (pci_range_ck(bus, dev)) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* select the MV-64340 registers to communicate with the PCI bus */ + if (bus == 0) { + address_reg = MV64340_PCI_0_CONFIG_ADDR; + data_reg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG; + } else { + address_reg = MV64340_PCI_1_CONFIG_ADDR; + data_reg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG; + } + + address = (bus << 16) | (dev << 11) | (func << 8) | + (offset & 0xfc) | 0x80000000; + + /* start the configuration cycle */ + MV_WRITE(address_reg, address); + + /* read the data */ + MV_READ_16(data_reg + (offset & 0x3), val); + + return PCIBIOS_SUCCESSFUL; +} + +static int marvell_pcibios_read_config_byte(struct pci_dev *device, + int offset, u8 * val) +{ + int dev, bus, func; + uint32_t address_reg, data_reg; + uint32_t address; + + bus = device->bus->number; + dev = PCI_SLOT(device->devfn); + func = PCI_FUNC(device->devfn); + + /* verify the range */ + if (pci_range_ck(bus, dev)) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* select the MV-64340 registers to communicate with the PCI bus */ + if (bus == 0) { + address_reg = MV64340_PCI_0_CONFIG_ADDR; + data_reg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG; + } else { + address_reg = MV64340_PCI_1_CONFIG_ADDR; + data_reg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG; + } + + address = (bus << 16) | (dev << 11) | (func << 8) | + (offset & 0xfc) | 0x80000000; + + /* start the configuration cycle */ + MV_WRITE(address_reg, address); + + /* write the data */ + MV_READ_8(data_reg + (offset & 0x3), val); + + return PCIBIOS_SUCCESSFUL; +} + +static int marvell_pcibios_write_config_dword(struct pci_dev *device, + int offset, u32 val) +{ + int dev, bus, func; + uint32_t address_reg, data_reg; + uint32_t address; + + bus = device->bus->number; + dev = PCI_SLOT(device->devfn); + func = PCI_FUNC(device->devfn); + + /* verify the range */ + if (pci_range_ck(bus, dev)) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* select the MV-64340 registers to communicate with the PCI bus */ + if (bus == 0) { + address_reg = MV64340_PCI_0_CONFIG_ADDR; + data_reg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG; + } else { + address_reg = MV64340_PCI_1_CONFIG_ADDR; + data_reg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG; + } + + address = (bus << 16) | (dev << 11) | (func << 8) | + (offset & 0xfc) | 0x80000000; + + /* start the configuration cycle */ + MV_WRITE(address_reg, address); + + /* write the data */ + MV_WRITE(data_reg, val); + + return PCIBIOS_SUCCESSFUL; +} + + +static int marvell_pcibios_write_config_word(struct pci_dev *device, + int offset, u16 val) +{ + int dev, bus, func; + uint32_t address_reg, data_reg; + uint32_t address; + + bus = device->bus->number; + dev = PCI_SLOT(device->devfn); + func = PCI_FUNC(device->devfn); + + /* verify the range */ + if (pci_range_ck(bus, dev)) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* select the MV-64340 registers to communicate with the PCI bus */ + if (bus == 0) { + address_reg = MV64340_PCI_0_CONFIG_ADDR; + data_reg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG; + } else { + address_reg = MV64340_PCI_1_CONFIG_ADDR; + data_reg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG; + } + + address = (bus << 16) | (dev << 11) | (func << 8) | + (offset & 0xfc) | 0x80000000; + + /* start the configuration cycle */ + MV_WRITE(address_reg, address); + + /* write the data */ + MV_WRITE_16(data_reg + (offset & 0x3), val); + + return PCIBIOS_SUCCESSFUL; +} + +static int marvell_pcibios_write_config_byte(struct pci_dev *device, + int offset, u8 val) +{ + int dev, bus, func; + uint32_t address_reg, data_reg; + uint32_t address; + + bus = device->bus->number; + dev = PCI_SLOT(device->devfn); + func = PCI_FUNC(device->devfn); + + /* verify the range */ + if (pci_range_ck(bus, dev)) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* select the MV-64340 registers to communicate with the PCI bus */ + if (bus == 0) { + address_reg = MV64340_PCI_0_CONFIG_ADDR; + data_reg = MV64340_PCI_0_CONFIG_DATA_VIRTUAL_REG; + } else { + address_reg = MV64340_PCI_1_CONFIG_ADDR; + data_reg = MV64340_PCI_1_CONFIG_DATA_VIRTUAL_REG; + } + + address = (bus << 16) | (dev << 11) | (func << 8) | + (offset & 0xfc) | 0x80000000; + + /* start the configuration cycle */ + MV_WRITE(address_reg, address); + + /* write the data */ + MV_WRITE_8(data_reg + (offset & 0x3), val); + + return PCIBIOS_SUCCESSFUL; +} + +static void marvell_pcibios_set_master(struct pci_dev *dev) +{ + u16 cmd; + + marvell_pcibios_read_config_word(dev, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_MASTER; + marvell_pcibios_write_config_word(dev, PCI_COMMAND, cmd); +} + +/* Externally-expected functions. Do not change function names */ + +int pcibios_enable_resources(struct pci_dev *dev) +{ + u16 cmd, old_cmd; + u8 tmp1; + int idx; + struct resource *r; + + marvell_pcibios_read_config_word(dev, PCI_COMMAND, &cmd); + old_cmd = cmd; + for (idx = 0; idx < 6; idx++) { + r = &dev->resource[idx]; + if (!r->start && r->end) { + printk(KERN_ERR + "PCI: Device %s not available because of " + "resource collisions\n", dev->slot_name); + return -EINVAL; + } + if (r->flags & IORESOURCE_IO) + cmd |= PCI_COMMAND_IO; + if (r->flags & IORESOURCE_MEM) + cmd |= PCI_COMMAND_MEMORY; + } + if (cmd != old_cmd) { + marvell_pcibios_write_config_word(dev, PCI_COMMAND, cmd); + } + + /* + * Let's fix up the latency timer and cache line size here. Cache + * line size = 32 bytes / sizeof dword (4) = 8. + * Latency timer must be > 8. 32 is random but appears to work. + */ + marvell_pcibios_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &tmp1); + if (tmp1 != 8) { + printk(KERN_WARNING + "PCI setting cache line size to 8 from " "%d\n", + tmp1); + marvell_pcibios_write_config_byte(dev, PCI_CACHE_LINE_SIZE, + 8); + } + marvell_pcibios_read_config_byte(dev, PCI_LATENCY_TIMER, &tmp1); + if (tmp1 < 32) { + printk(KERN_WARNING + "PCI setting latency timer to 32 from %d\n", tmp1); + marvell_pcibios_write_config_byte(dev, PCI_LATENCY_TIMER, + 32); + } + + return 0; +} + +int pcibios_enable_device(struct pci_dev *dev, int mask) +{ + return pcibios_enable_resources(dev); +} + +void pcibios_align_resource(void *data, struct resource *res, + unsigned long size) +{ + struct pci_dev *dev = data; + + if (res->flags & IORESOURCE_IO) { + unsigned long start = res->start; + + /* We need to avoid collisions with `mirrored' VGA ports + and other strange ISA hardware, so we always want the + addresses kilobyte aligned. */ + if (size > 0x100) { + printk(KERN_ERR "PCI: I/O Region %s/%d too large" + " (%ld bytes)\n", dev->slot_name, + dev->resource - res, size); + } + + start = (start + 1024 - 1) & ~(1024 - 1); + res->start = start; + } +} + +struct pci_ops marvell_pci_ops = { + marvell_pcibios_read_config_byte, + marvell_pcibios_read_config_word, + marvell_pcibios_read_config_dword, + marvell_pcibios_write_config_byte, + marvell_pcibios_write_config_word, + marvell_pcibios_write_config_dword +}; + +struct pci_fixup pcibios_fixups[] = { + {0} +}; + +void __init pcibios_fixup_bus(struct pci_bus *c) +{ + mv64340_board_pcibios_fixup_bus(c); +} + +void __init pcibios_init(void) +{ + /* Reset PCI I/O and PCI MEM values */ + ioport_resource.start = 0xe0000000; + ioport_resource.end = 0xe0000000 + 0x20000000 - 1; + iomem_resource.start = 0xc0000000; + iomem_resource.end = 0xc0000000 + 0x20000000 - 1; + + pci_scan_bus(0, &marvell_pci_ops, NULL); + pci_scan_bus(1, &marvell_pci_ops, NULL); +} + +/* + * for parsing "pci=" kernel boot arguments. + */ +char *pcibios_setup(char *str) +{ + printk(KERN_INFO "rr: pcibios_setup\n"); + /* Nothing to do for now. */ + + return str; +} + +unsigned __init int pcibios_assign_all_busses(void) +{ + return 1; +} diff -Nru a/arch/mips/pci/pci-ocelot-g.c b/arch/mips/pci/pci-ocelot-g.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/pci-ocelot-g.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,572 @@ +/* + * Copyright 2002 Momentum Computer + * Author: Matthew Dharm + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include "gt64240.h" + +#include + +#define SELF 0 +#define MASTER_ABORT_BIT 0x100 + +/* + * These functions and structures provide the BIOS scan and mapping of the PCI + * devices. + */ + +#define MAX_PCI_DEVS 10 + +void gt64240_board_pcibios_fixup_bus(struct pci_bus *c); + +/* Functions to implement "pci ops" */ +static int galileo_pcibios_read_config_word(int bus, int devfn, + int offset, u16 * val); +static int galileo_pcibios_read_config_byte(int bus, int devfn, + int offset, u8 * val); +static int galileo_pcibios_read_config_dword(int bus, int devfn, + int offset, u32 * val); +static int galileo_pcibios_write_config_byte(int bus, int devfn, + int offset, u8 val); +static int galileo_pcibios_write_config_word(int bus, int devfn, + int offset, u16 val); +static int galileo_pcibios_write_config_dword(int bus, int devfn, + int offset, u32 val); +#if 0 +static void galileo_pcibios_set_master(struct pci_dev *dev); +#endif + +static int pci_read(struct pci_bus *bus, unsigned int devfs, int where, + int size, u32 * val); +static int pci_write(struct pci_bus *bus, unsigned int devfs, int where, + int size, u32 val); + +/* + * General-purpose PCI functions. + */ + + +/* + * pci_range_ck - + * + * Check if the pci device that are trying to access does really exists + * on the evaluation board. + * + * Inputs : + * bus - bus number (0 for PCI 0 ; 1 for PCI 1) + * dev - number of device on the specific pci bus + * + * Outpus : + * 0 - if OK , 1 - if failure + */ +static __inline__ int pci_range_ck(unsigned char bus, unsigned char dev) +{ + /* Accessing device 31 crashes the GT-64240. */ + if (dev < 5) + return 0; + return -1; +} + +/* + * galileo_pcibios_(read/write)_config_(dword/word/byte) - + * + * reads/write a dword/word/byte register from the configuration space + * of a device. + * + * Note that bus 0 and bus 1 are local, and we assume all other busses are + * bridged from bus 1. This is a safe assumption, since any other + * configuration will require major modifications to the CP7000G + * + * Inputs : + * bus - bus number + * dev - device number + * offset - register offset in the configuration space + * val - value to be written / read + * + * Outputs : + * PCIBIOS_SUCCESSFUL when operation was succesfull + * PCIBIOS_DEVICE_NOT_FOUND when the bus or dev is errorneous + * PCIBIOS_BAD_REGISTER_NUMBER when accessing non aligned + */ + +static int galileo_pcibios_read_config_dword(int bus, int devfn, + int offset, u32 * val) +{ + int dev, func; + uint32_t address_reg, data_reg; + uint32_t address; + + dev = PCI_SLOT(devfn); + func = PCI_FUNC(devfn); + + /* verify the range */ + if (pci_range_ck(bus, dev)) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* select the GT-64240 registers to communicate with the PCI bus */ + if (bus == 0) { + address_reg = PCI_0CONFIGURATION_ADDRESS; + data_reg = PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER; + GT_WRITE(PCI_0ERROR_CAUSE, ~MASTER_ABORT_BIT); + } else { + address_reg = PCI_1CONFIGURATION_ADDRESS; + data_reg = PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER; + GT_WRITE(PCI_1ERROR_CAUSE, ~MASTER_ABORT_BIT); + if (bus == 1) + bus = 0; + } + + address = (bus << 16) | (dev << 11) | (func << 8) | + (offset & 0xfc) | 0x80000000; + + /* start the configuration cycle */ + GT_WRITE(address_reg, address); + + /* read the data */ + GT_READ(data_reg, val); + + return PCIBIOS_SUCCESSFUL; +} + + +static int galileo_pcibios_read_config_word(int bus, int devfn, + int offset, u16 * val) +{ + int dev, func; + uint32_t address_reg, data_reg; + uint32_t address; + + dev = PCI_SLOT(devfn); + func = PCI_FUNC(devfn); + + /* verify the range */ + if (pci_range_ck(bus, dev)) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* select the GT-64240 registers to communicate with the PCI bus */ + if (bus == 0) { + address_reg = PCI_0CONFIGURATION_ADDRESS; + data_reg = PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER; + GT_WRITE(PCI_0ERROR_CAUSE, ~MASTER_ABORT_BIT); + } else { + address_reg = PCI_1CONFIGURATION_ADDRESS; + data_reg = PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER; + GT_WRITE(PCI_1ERROR_CAUSE, ~MASTER_ABORT_BIT); + if (bus == 1) + bus = 0; + } + + address = (bus << 16) | (dev << 11) | (func << 8) | + (offset & 0xfc) | 0x80000000; + + /* start the configuration cycle */ + GT_WRITE(address_reg, address); + + /* read the data */ + GT_READ_16(data_reg + (offset & 0x3), val); + + return PCIBIOS_SUCCESSFUL; +} + +static int galileo_pcibios_read_config_byte(int bus, int devfn, + int offset, u8 * val) +{ + int dev, func; + uint32_t address_reg, data_reg; + uint32_t address; + + dev = PCI_SLOT(devfn); + func = PCI_FUNC(devfn); + + /* verify the range */ + if (pci_range_ck(bus, dev)) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* select the GT-64240 registers to communicate with the PCI bus */ + if (bus == 0) { + address_reg = PCI_0CONFIGURATION_ADDRESS; + data_reg = PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER; + } else { + address_reg = PCI_1CONFIGURATION_ADDRESS; + data_reg = PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER; + if (bus == 1) + bus = 0; + } + + address = (bus << 16) | (dev << 11) | (func << 8) | + (offset & 0xfc) | 0x80000000; + + /* start the configuration cycle */ + GT_WRITE(address_reg, address); + + /* write the data */ + GT_READ_8(data_reg + (offset & 0x3), val); + + return PCIBIOS_SUCCESSFUL; +} + +static int galileo_pcibios_write_config_dword(int bus, int devfn, + int offset, u32 val) +{ + int dev, func; + uint32_t address_reg, data_reg; + uint32_t address; + + dev = PCI_SLOT(devfn); + func = PCI_FUNC(devfn); + + /* verify the range */ + if (pci_range_ck(bus, dev)) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* select the GT-64240 registers to communicate with the PCI bus */ + if (bus == 0) { + address_reg = PCI_0CONFIGURATION_ADDRESS; + data_reg = PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER; + } else { + address_reg = PCI_1CONFIGURATION_ADDRESS; + data_reg = PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER; + if (bus == 1) + bus = 0; + } + + address = (bus << 16) | (dev << 11) | (func << 8) | + (offset & 0xfc) | 0x80000000; + + /* start the configuration cycle */ + GT_WRITE(address_reg, address); + + /* write the data */ + GT_WRITE(data_reg, val); + + return PCIBIOS_SUCCESSFUL; +} + + +static int galileo_pcibios_write_config_word(int bus, int devfn, + int offset, u16 val) +{ + int dev, func; + uint32_t address_reg, data_reg; + uint32_t address; + + dev = PCI_SLOT(devfn); + func = PCI_FUNC(devfn); + + /* verify the range */ + if (pci_range_ck(bus, dev)) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* select the GT-64240 registers to communicate with the PCI bus */ + if (bus == 0) { + address_reg = PCI_0CONFIGURATION_ADDRESS; + data_reg = PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER; + } else { + address_reg = PCI_1CONFIGURATION_ADDRESS; + data_reg = PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER; + if (bus == 1) + bus = 0; + } + + address = (bus << 16) | (dev << 11) | (func << 8) | + (offset & 0xfc) | 0x80000000; + + /* start the configuration cycle */ + GT_WRITE(address_reg, address); + + /* write the data */ + GT_WRITE_16(data_reg + (offset & 0x3), val); + + return PCIBIOS_SUCCESSFUL; +} + +static int galileo_pcibios_write_config_byte(int bus, int devfn, + int offset, u8 val) +{ + int dev, func; + uint32_t address_reg, data_reg; + uint32_t address; + + dev = PCI_SLOT(devfn); + func = PCI_FUNC(devfn); + + /* verify the range */ + if (pci_range_ck(bus, dev)) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* select the GT-64240 registers to communicate with the PCI bus */ + if (bus == 0) { + address_reg = PCI_0CONFIGURATION_ADDRESS; + data_reg = PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER; + } else { + address_reg = PCI_1CONFIGURATION_ADDRESS; + data_reg = PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER; + if (bus == 1) + bus = 0; + } + + address = (bus << 16) | (dev << 11) | (func << 8) | + (offset & 0xfc) | 0x80000000; + + /* start the configuration cycle */ + GT_WRITE(address_reg, address); + + /* write the data */ + GT_WRITE_8(data_reg + (offset & 0x3), val); + + return PCIBIOS_SUCCESSFUL; +} + +#if 0 +static void galileo_pcibios_set_master(struct pci_dev *dev) +{ + u16 cmd; + + galileo_pcibios_read_config_word(dev, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_MASTER; + galileo_pcibios_write_config_word(dev, PCI_COMMAND, cmd); +} +#endif + +/* Externally-expected functions. Do not change function names */ + +int pcibios_enable_resources(struct pci_dev *dev) +{ + u16 cmd, old_cmd; + u8 tmp1; + int idx; + struct resource *r; + + pci_read(dev->bus, dev->devfn, PCI_COMMAND, 2, (u32 *) & cmd); + old_cmd = cmd; + for (idx = 0; idx < 6; idx++) { + r = &dev->resource[idx]; + if (!r->start && r->end) { + printk(KERN_ERR + "PCI: Device %s not available because of " + "resource collisions\n", dev->slot_name); + return -EINVAL; + } + if (r->flags & IORESOURCE_IO) + cmd |= PCI_COMMAND_IO; + if (r->flags & IORESOURCE_MEM) + cmd |= PCI_COMMAND_MEMORY; + } + if (cmd != old_cmd) { + pci_write(dev->bus, dev->devfn, PCI_COMMAND, 2, cmd); + } + + /* + * Let's fix up the latency timer and cache line size here. Cache + * line size = 32 bytes / sizeof dword (4) = 8. + * Latency timer must be > 8. 32 is random but appears to work. + */ + pci_read(dev->bus, dev->devfn, PCI_CACHE_LINE_SIZE, 1, + (u32 *) & tmp1); + if (tmp1 != 8) { + printk(KERN_WARNING + "PCI setting cache line size to 8 from " "%d\n", + tmp1); + pci_write(dev->bus, dev->devfn, PCI_CACHE_LINE_SIZE, 1, 8); + } + pci_read(dev->bus, dev->devfn, PCI_LATENCY_TIMER, 1, + (u32 *) & tmp1); + if (tmp1 < 32) { + printk(KERN_WARNING + "PCI setting latency timer to 32 from %d\n", tmp1); + pci_write(dev->bus, dev->devfn, PCI_LATENCY_TIMER, 1, 32); + } + + return 0; +} + +int pcibios_enable_device(struct pci_dev *dev, int mask) +{ + return pcibios_enable_resources(dev); +} + +void pcibios_align_resource(void *data, struct resource *res, + unsigned long size, unsigned long align) +{ + struct pci_dev *dev = data; + + if (res->flags & IORESOURCE_IO) { + unsigned long start = res->start; + + /* We need to avoid collisions with `mirrored' VGA ports + and other strange ISA hardware, so we always want the + addresses kilobyte aligned. */ + if (size > 0x100) { + printk(KERN_ERR "PCI: I/O Region %s/%d too large" + " (%ld bytes)\n", dev->slot_name, + dev->resource - res, size); + } + + start = (start + 1024 - 1) & ~(1024 - 1); + res->start = start; + } +} + +struct pci_ops galileo_pci_ops = { + .read = pci_read, + .write = pci_write +}; + +static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, + int size, u32 * val) +{ + switch (size) { + case 1: + return galileo_pcibios_read_config_byte(bus->number, + devfn, where, + (u8 *) val); + case 2: + return galileo_pcibios_read_config_word(bus->number, + devfn, where, + (u16 *) val); + case 4: + return galileo_pcibios_read_config_dword(bus->number, + devfn, where, + (u32 *) val); + } + return PCIBIOS_FUNC_NOT_SUPPORTED; +} + +static int pci_write(struct pci_bus *bus, unsigned int devfn, int where, + int size, u32 val) +{ + switch (size) { + case 1: + return galileo_pcibios_write_config_byte(bus->number, + devfn, where, + val); + case 2: + return galileo_pcibios_write_config_word(bus->number, + devfn, where, + val); + case 4: + return galileo_pcibios_write_config_dword(bus->number, + devfn, where, + val); + } + return PCIBIOS_FUNC_NOT_SUPPORTED; +} + +struct pci_fixup pcibios_fixups[] = { + {0} +}; + +void __devinit pcibios_fixup_bus(struct pci_bus *c) +{ + gt64240_board_pcibios_fixup_bus(c); +} + + +/******************************************************************** +* pci0P2PConfig - This function set the PCI_0 P2P configurate. +* For more information on the P2P read PCI spec. +* +* Inputs: unsigned int SecondBusLow - Secondery PCI interface Bus Range Lower +* Boundry. +* unsigned int SecondBusHigh - Secondry PCI interface Bus Range upper +* Boundry. +* unsigned int busNum - The CPI bus number to which the PCI interface +* is connected. +* unsigned int devNum - The PCI interface's device number. +* +* Returns: true. +*/ +void pci0P2PConfig(unsigned int SecondBusLow, unsigned int SecondBusHigh, + unsigned int busNum, unsigned int devNum) +{ + uint32_t regData; + + regData = (SecondBusLow & 0xff) | ((SecondBusHigh & 0xff) << 8) | + ((busNum & 0xff) << 16) | ((devNum & 0x1f) << 24); + GT_WRITE(PCI_0P2P_CONFIGURATION, regData); +} + +/******************************************************************** +* pci1P2PConfig - This function set the PCI_1 P2P configurate. +* For more information on the P2P read PCI spec. +* +* Inputs: unsigned int SecondBusLow - Secondery PCI interface Bus Range Lower +* Boundry. +* unsigned int SecondBusHigh - Secondry PCI interface Bus Range upper +* Boundry. +* unsigned int busNum - The CPI bus number to which the PCI interface +* is connected. +* unsigned int devNum - The PCI interface's device number. +* +* Returns: true. +*/ +void pci1P2PConfig(unsigned int SecondBusLow, unsigned int SecondBusHigh, + unsigned int busNum, unsigned int devNum) +{ + uint32_t regData; + + regData = (SecondBusLow & 0xff) | ((SecondBusHigh & 0xff) << 8) | + ((busNum & 0xff) << 16) | ((devNum & 0x1f) << 24); + GT_WRITE(PCI_1P2P_CONFIGURATION, regData); +} + +#define PCI0_STATUS_COMMAND_REG 0x4 +#define PCI1_STATUS_COMMAND_REG 0x84 + +static int __init pcibios_init(void) +{ + /* Reset PCI I/O and PCI MEM values */ + ioport_resource.start = 0xe0000000; + ioport_resource.end = 0xe0000000 + 0x20000000 - 1; + iomem_resource.start = 0xc0000000; + iomem_resource.end = 0xc0000000 + 0x20000000 - 1; + + pci_scan_bus(0, &galileo_pci_ops, NULL); + pci_scan_bus(1, &galileo_pci_ops, NULL); + + return 0; +} + +subsys_initcall(pcibios_init); + +/* + * for parsing "pci=" kernel boot arguments. + */ +char *pcibios_setup(char *str) +{ + printk(KERN_INFO "rr: pcibios_setup\n"); + /* Nothing to do for now. */ + + return str; +} + +unsigned __init int pcibios_assign_all_busses(void) +{ + return 1; +} diff -Nru a/arch/mips/pci/pci-sb1250.c b/arch/mips/pci/pci-sb1250.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/pci-sb1250.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,281 @@ +/* + * Copyright (C) 2001,2002 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * BCM1250-specific PCI support + * + * This module provides the glue between Linux's PCI subsystem + * and the hardware. We basically provide glue for accessing + * configuration space, and set up the translation for I/O + * space accesses. + * + * To access configuration space, we use ioremap. In the 32-bit + * kernel, this consumes either 4 or 8 page table pages, and 16MB of + * kernel mapped memory. Hopefully neither of these should be a huge + * problem. + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* + * Macros for calculating offsets into config space given a device + * structure or dev/fun/reg + */ +#define CFGOFFSET(bus,devfn,where) (((bus)<<16) + ((devfn)<<8) + (where)) +#define CFGADDR(bus,devfn,where) CFGOFFSET((bus)->number,(devfn),where) + +static void *cfg_space; + +#define PCI_BUS_ENABLED 1 +#define LDT_BUS_ENABLED 2 +#define PCI_DEVICE_MODE 4 + +static int sb1250_bus_status = 0; + +#define PCI_BRIDGE_DEVICE 0 +#define LDT_BRIDGE_DEVICE 1 + +#ifdef CONFIG_SIBYTE_HAS_LDT +/* + * HT's level-sensitive interrupts require EOI, which is generated + * through a 4MB memory-mapped region + */ +unsigned long ldt_eoi_space; +#endif + +/* + * Read/write 32-bit values in config space. + */ +static inline u32 READCFG32(u32 addr) +{ + return *(u32 *) (cfg_space + (addr & ~3)); +} + +static inline void WRITECFG32(u32 addr, u32 data) +{ + *(u32 *) (cfg_space + (addr & ~3)) = data; +} + +/* + * Some checks before doing config cycles: + * In PCI Device Mode, hide everything on bus 0 except the LDT host + * bridge. Otherwise, access is controlled by bridge MasterEn bits. + */ +static int sb1250_pci_can_access(struct pci_bus *bus, int devfn) +{ + u32 devno; + + if (!(sb1250_bus_status & (PCI_BUS_ENABLED | PCI_DEVICE_MODE))) + return 0; + + if (bus->number == 0) { + devno = PCI_SLOT(devfn); + if (devno == LDT_BRIDGE_DEVICE) + return (sb1250_bus_status & LDT_BUS_ENABLED) != 0; + else if (sb1250_bus_status & PCI_DEVICE_MODE) + return 0; + else + return 1; + } else + return 1; +} + +/* + * Read/write access functions for various sizes of values + * in config space. Return all 1's for disallowed accesses + * for a kludgy but adequate simulation of master aborts. + */ + +static int sb1250_pcibios_read(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 * val) +{ + u32 data = 0; + + if ((size == 2) && (where & 1)) + return PCIBIOS_BAD_REGISTER_NUMBER; + else if ((size == 4) && (where & 3)) + return PCIBIOS_BAD_REGISTER_NUMBER; + + if (sb1250_pci_can_access(bus, devfn)) + data = READCFG32(CFGADDR(bus, devfn, where)); + else + data = 0xFFFFFFFF; + + if (size == 1) + *val = (data >> ((where & 3) << 3)) & 0xff; + else if (size == 2) + *val = (data >> ((where & 3) << 3)) & 0xffff; + else + *val = data; + + return PCIBIOS_SUCCESSFUL; +} + +static int sb1250_pcibios_write(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) +{ + u32 cfgaddr = CFGADDR(bus, devfn, where); + u32 data = 0; + + if ((size == 2) && (where & 1)) + return PCIBIOS_BAD_REGISTER_NUMBER; + else if ((size == 4) && (where & 3)) + return PCIBIOS_BAD_REGISTER_NUMBER; + + if (!sb1250_pci_can_access(bus, devfn)) + return PCIBIOS_BAD_REGISTER_NUMBER; + + data = READCFG32(cfgaddr); + + if (size == 1) + data = (data & ~(0xff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + else if (size == 2) + data = (data & ~(0xffff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + + WRITECFG32(cfgaddr, data); + + return PCIBIOS_SUCCESSFUL; +} + +struct pci_ops sb1250_pci_ops = { + .read = sb1250_pcibios_read, + .write = sb1250_pcibios_write +}; + + +void __init pcibios_init(void) +{ + uint32_t cmdreg; + uint64_t reg; + + cfg_space = + ioremap(A_PHYS_LDTPCI_CFG_MATCH_BITS, 16 * 1024 * 1024); + + /* + * See if the PCI bus has been configured by the firmware. + */ + reg = *((volatile uint64_t *) KSEG1ADDR(A_SCD_SYSTEM_CFG)); + if (!(reg & M_SYS_PCI_HOST)) { + sb1250_bus_status |= PCI_DEVICE_MODE; + } else { + cmdreg = + READCFG32(CFGOFFSET + (0, PCI_DEVFN(PCI_BRIDGE_DEVICE, 0), + PCI_COMMAND)); + if (!(cmdreg & PCI_COMMAND_MASTER)) { + printk + ("PCI: Skipping PCI probe. Bus is not initialized.\n"); + iounmap(cfg_space); + return; + } + sb1250_bus_status |= PCI_BUS_ENABLED; + } + + /* + * Establish mappings in KSEG2 (kernel virtual) to PCI I/O + * space. Use "match bytes" policy to make everything look + * little-endian. So, you need to also set + * CONFIG_SWAP_IO_SPACE, but this is the combination that + * works correctly with most of Linux's drivers. + * XXX ehs: Should this happen in PCI Device mode? + */ + + set_io_port_base((unsigned long) + ioremap(A_PHYS_LDTPCI_IO_MATCH_BYTES, 65536)); + isa_slot_offset = (unsigned long) + ioremap(A_PHYS_LDTPCI_IO_MATCH_BYTES_32, 1024 * 1024); + +#ifdef CONFIG_SIBYTE_HAS_LDT + /* + * Also check the LDT bridge's enable, just in case we didn't + * initialize that one. + */ + + cmdreg = READCFG32(CFGOFFSET(0, PCI_DEVFN(LDT_BRIDGE_DEVICE, 0), + PCI_COMMAND)); + if (cmdreg & PCI_COMMAND_MASTER) { + sb1250_bus_status |= LDT_BUS_ENABLED; + + /* + * Need bits 23:16 to convey vector number. Note that + * this consumes 4MB of kernel-mapped memory + * (Kseg2/Kseg3) for 32-bit kernel. + */ + ldt_eoi_space = (unsigned long) + ioremap(A_PHYS_LDT_SPECIAL_MATCH_BYTES, + 4 * 1024 * 1024); + } +#endif + + /* Probe for PCI hardware */ + + printk("PCI: Probing PCI hardware on host bus 0.\n"); + pci_scan_bus(0, &sb1250_pci_ops, NULL); + +#ifdef CONFIG_VGA_CONSOLE + take_over_console(&vga_con, 0, MAX_NR_CONSOLES - 1, 1); +#endif +} + +int pcibios_enable_device(struct pci_dev *dev, int mask) +{ + /* Not needed, since we enable all devices at startup. */ + return 0; +} + +void pcibios_align_resource(void *data, struct resource *res, + unsigned long size, unsigned long align) +{ +} + +char *__init pcibios_setup(char *str) +{ + /* Nothing to do for now. */ + + return str; +} + +struct pci_fixup pcibios_fixups[] = { + {0} +}; + +/* + * Called after each bus is probed, but before its children + * are examined. + */ +void __devinit pcibios_fixup_bus(struct pci_bus *b) +{ + pci_read_bridge_bases(b); +} + +unsigned int pcibios_assign_all_busses(void) +{ + return 1; +} diff -Nru a/arch/mips/pci/pci-sni.c b/arch/mips/pci/pci-sni.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/pci-sni.c Tue Jul 1 18:44:39 2003 @@ -0,0 +1,175 @@ +/* + * 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. + * + * SNI specific PCI support for RM200/RM300. + * + * Copyright (C) 1997 - 2000 Ralf Baechle + */ +#include +#include +#include +#include +#include +#include + +#define mkaddr(bus, devfn, where) \ +do { \ + if (bus->number == 0) \ + return -1; \ + *(volatile u32 *)PCIMT_CONFIG_ADDRESS = \ + ((bus->number & 0xff) << 0x10) | \ + ((devfn & 0xff) << 0x08) | \ + (where & 0xfc); \ +} while(0) + +#if 0 +/* To do: Bring this uptodate ... */ +static void pcimt_pcibios_fixup(void) +{ + struct pci_dev *dev = NULL; + + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + /* + * TODO: Take care of RM300 revision D boards for where the + * network slot became an ordinary PCI slot. + */ + if (dev->devfn == PCI_DEVFN(1, 0)) { + /* Evil hack ... */ + set_cp0_config(CONF_CM_CMASK, + CONF_CM_CACHABLE_NO_WA); + dev->irq = PCIMT_IRQ_SCSI; + continue; + } + if (dev->devfn == PCI_DEVFN(2, 0)) { + dev->irq = PCIMT_IRQ_ETHERNET; + continue; + } + + switch (dev->irq) { + case 1...4: + dev->irq += PCIMT_IRQ_INTA - 1; + break; + case 0: + break; + default: + printk("PCI device on bus %d, dev %d, function %d " + "impossible interrupt configured.\n", + dev->bus->number, PCI_SLOT(dev->devfn), + PCI_SLOT(dev->devfn)); + } + } +} +#endif + +/* + * We can't address 8 and 16 bit words directly. Instead we have to + * read/write a 32bit word and mask/modify the data we actually want. + */ +static int pcimt_read(struct pci_bus *bus, unsigned int devfn, int where, + int size, u32 * val) +{ + u32 res; + + switch (size) { + case 1: + mkaddr(bus, devfn, where); + res = *(volatile u32 *) PCIMT_CONFIG_DATA; + res = (le32_to_cpu(res) >> ((where & 3) << 3)) & 0xff; + *val = (u8) res; + break; + case 2: + if (where & 1) + return PCIBIOS_BAD_REGISTER_NUMBER; + mkaddr(bus, devfn, where); + res = *(volatile u32 *) PCIMT_CONFIG_DATA; + res = (le32_to_cpu(res) >> ((where & 3) << 3)) & 0xffff; + *val = (u16) res; + break; + case 4: + if (where & 3) + return PCIBIOS_BAD_REGISTER_NUMBER; + mkaddr(bus, devfn, where); + res = *(volatile u32 *) PCIMT_CONFIG_DATA; + res = le32_to_cpu(res); + *val = res; + break; + } + + return PCIBIOS_SUCCESSFUL; +} + +static int pcimt_write(struct pci_bus *bus, unsigned int devfn, int where, + int size, u32 val) +{ + switch (size) { + case 1: + mkaddr(bus, devfn, where); + *(volatile u8 *) (PCIMT_CONFIG_DATA + (where & 3)) = + (u8) le32_to_cpu(val); + break; + case 2: + if (where & 1) + return PCIBIOS_BAD_REGISTER_NUMBER; + mkaddr(bus, devfn, where); + *(volatile u16 *) (PCIMT_CONFIG_DATA + (where & 3)) = + (u16) le32_to_cpu(val); + break; + case 4: + if (where & 3) + return PCIBIOS_BAD_REGISTER_NUMBER; + mkaddr(bus, devfn, where); + *(volatile u32 *) PCIMT_CONFIG_DATA = le32_to_cpu(val); + break; + } + + return PCIBIOS_SUCCESSFUL; +} + +struct pci_ops sni_pci_ops = { + .read = pcimt_read, + .write = pcimt_write, +}; + +void __devinit pcibios_fixup_bus(struct pci_bus *b) +{ +} + +static int __init pcibios_init(void) +{ + struct pci_ops *ops = &sni_pci_ops; + + pci_scan_bus(0, ops, NULL); + + return 0; +} + +subsys_initcall(pcibios_init); + +int __init pcibios_enable_device(struct pci_dev *dev, int mask) +{ + /* Not needed, since we enable all devices at startup. */ + return 0; +} + +void pcibios_align_resource(void *data, struct resource *res, + unsigned long size, unsigned long align) +{ +} + +unsigned __init int pcibios_assign_all_busses(void) +{ + return 0; +} + +char *__init pcibios_setup(char *str) +{ + /* Nothing to do for now. */ + + return str; +} + +struct pci_fixup pcibios_fixups[] = { + {0} +}; diff -Nru a/arch/mips/pci/pci-vr41xx.c b/arch/mips/pci/pci-vr41xx.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/pci-vr41xx.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,233 @@ +/* + * FILE NAME + * arch/mips/vr41xx/common/pciu.c + * + * BRIEF MODULE DESCRIPTION + * PCI Control Unit routines for the NEC VR4100 series. + * + * Author: Yoichi Yuasa + * yyuasa@mvista.com or source@mvista.com + * + * Copyright 2001,2002 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * Changes: + * Paul Mundt + * - Fix deadlock-causing PCIU access race for VR4131. + * + * MontaVista Software Inc. or + * - New creation, NEC VR4122 and VR4131 are supported. + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "pciu.h" + +extern unsigned long vr41xx_vtclock; + +static inline int vr41xx_pci_config_access(unsigned char bus, + unsigned int devfn, int where) +{ + if (bus == 0) { + /* + * Type 0 configuration + */ + if (PCI_SLOT(devfn) < 11 || where > 255) + return -1; + + writel((1UL << PCI_SLOT(devfn)) | + (PCI_FUNC(devfn) << 8) | + (where & 0xfc), PCICONFAREG); + } else { + /* + * Type 1 configuration + */ + if (where > 255) + return -1; + + writel((bus << 16) | + (devfn << 8) | (where & 0xfc) | 1UL, PCICONFAREG); + } + + return 0; +} + +static int vr41xx_pci_config_read(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 * val) +{ + u32 data; + + *val = 0xffffffffUL; + if (vr41xx_pci_config_access(bus->number, devfn, where) < 0) + return PCIBIOS_DEVICE_NOT_FOUND; + + data = readl(PCICONFDREG); + + switch (size) { + case 1: + *val = (data >> ((where & 3) << 3)) & 0xffUL; + break; + case 2: + *val = (data >> ((where & 2) << 3)) & 0xffffUL; + break; + case 4: + *val = data; + break; + default: + return PCIBIOS_FUNC_NOT_SUPPORTED; + } + + return PCIBIOS_SUCCESSFUL; +} + +static int vr41xx_pci_config_write(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) +{ + u32 data; + int shift; + + if (vr41xx_pci_config_access(bus->number, devfn, where) < 0) + return PCIBIOS_DEVICE_NOT_FOUND; + + data = readl(PCICONFDREG); + + switch (size) { + case 1: + shift = (where & 3) << 3; + data &= ~(0xff << shift); + data |= ((val & 0xff) << shift); + break; + case 2: + shift = (where & 2) << 3; + data &= ~(0xffff << shift); + data |= ((val & 0xffff) << shift); + break; + case 4: + data = val; + break; + default: + return PCIBIOS_FUNC_NOT_SUPPORTED; + } + + writel(data, PCICONFDREG); + + return PCIBIOS_SUCCESSFUL; +} + +struct pci_ops vr41xx_pci_ops = { + .read = vr41xx_pci_config_read, + .write = vr41xx_pci_config_write, +}; + +void __init vr41xx_pciu_init(struct vr41xx_pci_address_map *map) +{ + struct vr41xx_pci_address_space *s; + u32 config; + int n; + + if (!map) + return; + + /* Disable PCI interrupt */ + writew(0, MPCIINTREG); + + /* Supply VTClock to PCIU */ + vr41xx_clock_supply(PCIU_CLOCK); + + /* + * Sleep for 1us after setting MSKPPCIU bit in CMUCLKMSK + * before doing any PCIU access to avoid deadlock on VR4131. + */ + udelay(1); + + /* Select PCI clock */ + if (vr41xx_vtclock < MAX_PCI_CLOCK) + writel(EQUAL_VTCLOCK, PCICLKSELREG); + else if ((vr41xx_vtclock / 2) < MAX_PCI_CLOCK) + writel(HALF_VTCLOCK, PCICLKSELREG); + else if ((vr41xx_vtclock / 4) < MAX_PCI_CLOCK) + writel(QUARTER_VTCLOCK, PCICLKSELREG); + else + printk(KERN_INFO "Warning: PCI Clock is over 33MHz.\n"); + + /* Supply PCI clock by PCI bus */ + vr41xx_clock_supply(PCI_CLOCK); + + /* + * Set PCI memory & I/O space address conversion registers + * for master transaction. + */ + if (map->mem1 != NULL) { + s = map->mem1; + config = (s->internal_base & 0xff000000) | + ((s->address_mask & 0x7f000000) >> 11) | (1UL << 12) | + ((s->pci_base & 0xff000000) >> 24); + writel(config, PCIMMAW1REG); + } + if (map->mem2 != NULL) { + s = map->mem2; + config = (s->internal_base & 0xff000000) | + ((s->address_mask & 0x7f000000) >> 11) | (1UL << 12) | + ((s->pci_base & 0xff000000) >> 24); + writel(config, PCIMMAW2REG); + } + if (map->io != NULL) { + s = map->io; + config = (s->internal_base & 0xff000000) | + ((s->address_mask & 0x7f000000) >> 11) | (1UL << 12) | + ((s->pci_base & 0xff000000) >> 24); + writel(config, PCIMIOAWREG); + } + + /* Set target memory windows */ + writel(0x00081000, PCITAW1REG); + writel(0UL, PCITAW2REG); + pciu_write_config_dword(PCI_BASE_ADDRESS_0, 0UL); + pciu_write_config_dword(PCI_BASE_ADDRESS_1, 0UL); + + /* Clear bus error */ + n = readl(BUSERRADREG); + + if (current_cpu_data.cputype == CPU_VR4122) { + writel(0UL, PCITRDYVREG); + pciu_write_config_dword(PCI_CACHE_LINE_SIZE, 0x0000f804); + } else { + writel(100UL, PCITRDYVREG); + pciu_write_config_dword(PCI_CACHE_LINE_SIZE, 0x00008004); + } + + writel(CONFIG_DONE, PCIENREG); + pciu_write_config_dword(PCI_COMMAND, + PCI_COMMAND_IO | + PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER | + PCI_COMMAND_PARITY | PCI_COMMAND_SERR); +} diff -Nru a/arch/mips/pci/pci-vr41xx.h b/arch/mips/pci/pci-vr41xx.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/pci-vr41xx.h Tue Jul 1 18:44:40 2003 @@ -0,0 +1,167 @@ +/* + * FILE NAME + * arch/mips/vr41xx/common/pciu.h + * + * BRIEF MODULE DESCRIPTION + * Include file for PCI Control Unit of the NEC VR4100 series. + * + * Author: Yoichi Yuasa + * yyuasa@mvista.com or source@mvista.com + * + * Copyright 2002 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * Changes: + * MontaVista Software Inc. or + * - New creation, NEC VR4122 and VR4131 are supported. + */ +#ifndef __VR41XX_PCIU_H +#define __VR41XX_PCIU_H + +#include +#include + +#define BIT(x) (1 << (x)) + +#define PCIMMAW1REG KSEG1ADDR(0x0f000c00) +#define PCIMMAW2REG KSEG1ADDR(0x0f000c04) +#define PCITAW1REG KSEG1ADDR(0x0f000c08) +#define PCITAW2REG KSEG1ADDR(0x0f000c0c) +#define PCIMIOAWREG KSEG1ADDR(0x0f000c10) +#define INTERNAL_BUS_BASE_ADDRESS 0xff000000 +#define ADDRESS_MASK 0x000fe000 +#define PCI_ACCESS_ENABLE BIT(12) +#define PCI_ADDRESS_SETTING 0x000000ff + +#define PCICONFDREG KSEG1ADDR(0x0f000c14) +#define PCICONFAREG KSEG1ADDR(0x0f000c18) +#define PCIMAILREG KSEG1ADDR(0x0f000c1c) + +#define BUSERRADREG KSEG1ADDR(0x0f000c24) +#define ERROR_ADDRESS 0xfffffffc + +#define INTCNTSTAREG KSEG1ADDR(0x0f000c28) +#define MABTCLR BIT(31) +#define TRDYCLR BIT(30) +#define PARCLR BIT(29) +#define MBCLR BIT(28) +#define SERRCLR BIT(27) + +#define PCIEXACCREG KSEG1ADDR(0x0f000c2c) +#define UNLOCK BIT(1) +#define EAREQ BIT(0) + +#define PCIRECONTREG KSEG1ADDR(0x0f000c30) +#define RTRYCNT 0x000000ff + +#define PCIENREG KSEG1ADDR(0x0f000c34) +#define CONFIG_DONE BIT(2) + +#define PCICLKSELREG KSEG1ADDR(0x0f000c38) +#define EQUAL_VTCLOCK 0x00000002 +#define HALF_VTCLOCK 0x00000000 +#define QUARTER_VTCLOCK 0x00000001 + +#define PCITRDYVREG KSEG1ADDR(0x0f000c3c) + +#define PCICLKRUNREG KSEG1ADDR(0x0f000c60) + +#define PCIU_CONFIGREGS_BASE KSEG1ADDR(0x0f000d00) +#define VENDORIDREG KSEG1ADDR(0x0f000d00) +#define DEVICEIDREG KSEG1ADDR(0x0f000d00) +#define COMMANDREG KSEG1ADDR(0x0f000d04) +#define STATUSREG KSEG1ADDR(0x0f000d04) +#define REVIDREG KSEG1ADDR(0x0f000d08) +#define CLASSREG KSEG1ADDR(0x0f000d08) +#define CACHELSREG KSEG1ADDR(0x0f000d0c) +#define LATTIMEREG KSEG1ADDR(0x0f000d0c) +#define MAILBAREG KSEG1ADDR(0x0f000d10) +#define PCIMBA1REG KSEG1ADDR(0x0f000d14) +#define PCIMBA2REG KSEG1ADDR(0x0f000d18) +#define INTLINEREG KSEG1ADDR(0x0f000d3c) +#define INTPINREG KSEG1ADDR(0x0f000d3c) +#define RETVALREG KSEG1ADDR(0x0f000d40) +#define PCIAPCNTREG KSEG1ADDR(0x0f000d40) + +#define MPCIINTREG KSEG1ADDR(0x0f0000b2) + +#define MAX_PCI_CLOCK 33333333 + +#define PCIU_CLOCK 0x0080 +#define PCI_CLOCK 0x2000 + +static inline int pciu_read_config_byte(int where, u8 * val) +{ + u32 data; + + data = readl(PCIU_CONFIGREGS_BASE + where); + *val = (u8) (data >> ((where & 3) << 3)); + + return PCIBIOS_SUCCESSFUL; +} + +static inline int pciu_read_config_word(int where, u16 * val) +{ + u32 data; + + if (where & 1) + return PCIBIOS_BAD_REGISTER_NUMBER; + + data = readl(PCIU_CONFIGREGS_BASE + where); + *val = (u16) (data >> ((where & 2) << 3)); + + return PCIBIOS_SUCCESSFUL; +} + +static inline int pciu_read_config_dword(int where, u32 * val) +{ + if (where & 3) + return PCIBIOS_BAD_REGISTER_NUMBER; + + *val = readl(PCIU_CONFIGREGS_BASE + where); + + return PCIBIOS_SUCCESSFUL; +} + +static inline int pciu_write_config_byte(int where, u8 val) +{ + writel(val, PCIU_CONFIGREGS_BASE + where); + + return 0; +} + +static inline int pciu_write_config_word(int where, u16 val) +{ + writel(val, PCIU_CONFIGREGS_BASE + where); + + return 0; +} + +static inline int pciu_write_config_dword(int where, u32 val) +{ + writel(val, PCIU_CONFIGREGS_BASE + where); + + return 0; +} + +#endif /* __VR41XX_PCIU_H */ diff -Nru a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/pci/pci.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,233 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * Modified to be mips generic, ppopov@mvista.com + * arch/mips/kernel/pci.c + * Common MIPS PCI routines. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +/* + * This file contains common PCI routines meant to be shared for + * all MIPS machines. + * + * Strategies: + * + * . We rely on pci_auto.c file to assign PCI resources (MEM and IO) + * TODO: this should be optional for some machines where they do have + * a real "pcibios" that does resource assignment. + * + * . We then use pci_scan_bus() to "discover" all the resources for + * later use by Linux. + * + * . We finally reply on a board supplied function, pcibios_fixup_irq(), to + * to assign the interrupts. We may use setup-irq.c under drivers/pci + * later. + * + * . Specifically, we will *NOT* use pci_assign_unassigned_resources(), + * because we assume all PCI devices should have the resources correctly + * assigned and recorded. + * + * Limitations: + * + * . We "collapse" all IO and MEM spaces in sub-buses under a top-level bus + * into a contiguous range. + * + * . In the case of Memory space, the rnage is 1:1 mapping with CPU physical + * address space. + * + * . In the case of IO space, it starts from 0, and the beginning address + * is mapped to KSEG0ADDR(mips_io_port) in the CPU physical address. + * + * . These are the current MIPS limitations (by ioremap, etc). In the + * future, we may remove them. + * + * Credits: + * Most of the code are derived from the pci routines from PPC and Alpha, + * which were mostly writtne by + * Cort Dougan, cort@fsmlabs.com + * Matt Porter, mporter@mvista.com + * Dave Rusling david.rusling@reo.mts.dec.com + * David Mosberger davidm@cs.arizona.edu + */ +#include +#include +#include +#include +#include + +#include + +extern void pcibios_fixup(void); +extern void pcibios_fixup_irqs(void); + +void __init pcibios_fixup_irqs(void) +{ + struct pci_dev *dev = NULL; + int slot_num; + + + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + slot_num = PCI_SLOT(dev->devfn); + switch (slot_num) { + case 2: + dev->irq = 3; + break; + case 3: + dev->irq = 4; + break; + case 4: + dev->irq = 5; + break; + default: + break; + } + } +} + +void __init pcibios_fixup_resources(struct pci_dev *dev) +{ /* HP-LJ */ + int pos; + int bases; + + printk("adjusting pci device: %s\n", dev->name); + + switch (dev->hdr_type) { + case PCI_HEADER_TYPE_NORMAL: + bases = 6; + break; + case PCI_HEADER_TYPE_BRIDGE: + bases = 2; + break; + case PCI_HEADER_TYPE_CARDBUS: + bases = 1; + break; + default: + bases = 0; + break; + } + for (pos = 0; pos < bases; pos++) { + struct resource *res = &dev->resource[pos]; + if (res->start >= IO_MEM_LOGICAL_START && + res->end <= IO_MEM_LOGICAL_END) { + res->start += IO_MEM_VIRTUAL_OFFSET; + res->end += IO_MEM_VIRTUAL_OFFSET; + } + if (res->start >= IO_PORT_LOGICAL_START && + res->end <= IO_PORT_LOGICAL_END) { + res->start += IO_PORT_VIRTUAL_OFFSET; + res->end += IO_PORT_VIRTUAL_OFFSET; + } + } + +} + +struct pci_fixup pcibios_fixups[] = { + {PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, + pcibios_fixup_resources}, + {0} +}; + +extern int pciauto_assign_resources(int busno, struct pci_channel *hose); + +static int __init pcibios_init(void) +{ + struct pci_channel *p; + struct pci_bus *bus; + int busno; + +#ifdef CONFIG_PCI_AUTO + /* assign resources */ + busno = 0; + for (p = mips_pci_channels; p->pci_ops != NULL; p++) { + busno = pciauto_assign_resources(busno, p) + 1; + } +#endif + + /* scan the buses */ + busno = 0; + for (p = mips_pci_channels; p->pci_ops != NULL; p++) { + bus = pci_scan_bus(busno, p->pci_ops, p); + busno = bus->subordinate + 1; + } + + /* machine dependent fixups */ + pcibios_fixup(); + /* fixup irqs (board specific routines) */ + pcibios_fixup_irqs(); + + return 0; +} + +subsys_initcall(pcibios_init); + +int pcibios_enable_device(struct pci_dev *dev, int mask) +{ + /* pciauto_assign_resources() will enable all devices found */ + return 0; +} + +unsigned long __init pci_bridge_check_io(struct pci_dev *bridge) +{ + u16 io; + + pci_read_config_word(bridge, PCI_IO_BASE, &io); + if (!io) { + pci_write_config_word(bridge, PCI_IO_BASE, 0xf0f0); + pci_read_config_word(bridge, PCI_IO_BASE, &io); + pci_write_config_word(bridge, PCI_IO_BASE, 0x0); + } + if (io) + return IORESOURCE_IO; + //printk(KERN_WARNING "PCI: bridge %s does not support I/O forwarding!\n", bridge->name); + return 0; +} + +void __devinit pcibios_fixup_bus(struct pci_bus *bus) +{ + /* Propogate hose info into the subordinate devices. */ + + struct pci_channel *hose = bus->sysdata; + struct pci_dev *dev = bus->self; + + if (!dev) { + /* Root bus */ + bus->resource[0] = hose->io_resource; + bus->resource[1] = hose->mem_resource; + } else { + /* This is a bridge. Do not care how it's initialized, + just link its resources to the bus ones */ + int i; + + for (i = 0; i < 3; i++) { + bus->resource[i] = + &dev->resource[PCI_BRIDGE_RESOURCES + i]; + bus->resource[i]->name = bus->name; + } + bus->resource[0]->flags |= pci_bridge_check_io(dev); + bus->resource[1]->flags |= IORESOURCE_MEM; + /* For now, propagate hose limits to the bus; + we'll adjust them later. */ + bus->resource[0]->end = hose->io_resource->end; + bus->resource[1]->end = hose->mem_resource->end; + /* Turn off downstream PF memory address range by default */ + bus->resource[2]->start = 1024 * 1024; + bus->resource[2]->end = bus->resource[2]->start - 1; + } +} + +char *pcibios_setup(char *str) +{ + return str; +} + +void pcibios_align_resource(void *data, struct resource *res, + unsigned long size, unsigned long align) +{ + /* this should not be called */ +} diff -Nru a/arch/mips/philips/nino/Makefile b/arch/mips/philips/nino/Makefile --- a/arch/mips/philips/nino/Makefile Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,17 +0,0 @@ -# -# Makefile for the Philips Nino specific parts of the kernel -# - -obj-y := int-handler.o setup.o irq.o time.o reset.o rtc.o prom.o power.o - -obj-$(CONFIG_REMOTE_DEBUG) += kgdb.o - -obj-$(CONFIG_BLK_DEV_INITRD) += ramdisk.o - -ramdisk.o: - $(MAKE) -C ramdisk - mv ramdisk/ramdisk.o ramdisk.o - -clean: - rm -f *.o - diff -Nru a/arch/mips/philips/nino/int-handler.S b/arch/mips/philips/nino/int-handler.S --- a/arch/mips/philips/nino/int-handler.S Tue Jul 1 18:44:31 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,137 +0,0 @@ -/* - * linux/arch/mips/philips/nino/int-handler.S - * - * Copyright (C) 1999 Harald Koerfgen - * Copyright (C) 2000 Jim Pick (jim@jimpick.com) - * Copyright (C) 2001 Steven J. Hill (sjhill@realitydiluted.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Interrupt handler for Philips Nino. - */ -#include -#include -#include -#include -#include - - .data - .globl HighPriVect - -HighPriVect: .word spurious # Reserved - .word io_posnegint0 # IOPOSINT(0) or IONEGINT(0) - .word spurious # CHIDMACNTINT - .word spurious # TELDMACNTINT - .word spurious # SNDDMACNTINT - .word spurious # Reserved - .word io_negint56 # IONEGINT(6) or IONEGINT(5) - .word spurious # Reserved - .word io_posint56 # IOPOSINT(6) or IOPOSINT(5) - .word spurious # Reserved - .word spurious # UARTBRXINT - .word uarta_rx # UARTARXINT - .word spurious # Reserved - .word periodic_timer # PERINT - .word spurious # ALARMINT - .word spurious # POSPWROKINT or NEGPWROKINT - -/* - * Here is the entry point to handle all interrupts. - */ - .text - .set noreorder - .align 5 - NESTED(nino_handle_int, PT_SIZE, ra) - .set noat - SAVE_ALL - CLI - .set at - - /* - * Get pending Interrupts - */ - mfc0 t0, CP0_CAUSE # Get pending interrupts - andi t2, t0, IE_IRQ4 # IRQ4 (high priority) - bne t2, IE_IRQ4, low_priority - nop - -/* - * Ok, we've got a high priority interrupt (a.k.a. an external interrupt). - * Read Interrupt Status Register 6 to get vector. - */ -high_priority: - lui t0, %hi(IntStatus6) - lw t1, %lo(IntStatus6)(t0) - andi t1, INT6_INTVECT - la t2, HighPriVect - addu t1, t1, t2 - lw t2, 0(t1) - jr t2 - nop - -/* - * Ok, we've got one of over a hundred other interrupts. - */ -low_priority: - lui t0, %hi(IntStatus1) - lw t1, %lo(IntStatus1)(t0) - j handle_it - li a0, 20 - -/* - * We don't currently handle spurious interrupts. - */ -spurious: - j spurious_interrupt - nop - -/* - * We have the IRQ number, dispatch to the real handler. - */ -handle_it: jal do_IRQ - move a1,sp - j ret_from_irq - nop - -/************************************ - * High priority interrupt mappings * - ************************************/ - -/* - * Periodic timer - IRQ 0 - */ -periodic_timer: - j handle_it - li a0, 0 - -/* - * UARTA RX - IRQ 3 - */ -uarta_rx: - j handle_it - li a0, 3 - -/* - * GPIO Pin 0 transition - IRQ 10 - */ -io_posnegint0: - j handle_it - li a0, 10 - -/* - * GPIO Pin 5 or 6 transition (0-to-1) - IRQ 11 - */ -io_posint56: - j handle_it - li a0, 11 - -/* - * GPIO Pin 5 or 6 transition (1-to-0) - IRQ 12 - */ -io_negint56: - j handle_it - li a0, 12 - - END(nino_handle_int) diff -Nru a/arch/mips/philips/nino/irq.c b/arch/mips/philips/nino/irq.c --- a/arch/mips/philips/nino/irq.c Tue Jul 1 18:44:31 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,319 +0,0 @@ -/* - * linux/arch/mips/philips/nino/irq.c - * - * Copyright (C) 1992 Linus Torvalds - * Copyright (C) 1999 Harald Koerfgen - * Copyright (C) 2000 Pavel Machek (pavel@suse.cz) - * Copyright (C) 2001 Steven J. Hill (sjhill@realitydiluted.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Generic interrupt handler for Philips Nino. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -unsigned long spurious_count = 0; - -irq_cpustat_t irq_stat [NR_CPUS]; - -static inline void mask_irq(unsigned int irq_nr) -{ - switch (irq_nr) { - case 0: /* Periodic Timer Interrupt */ - IntClear5 = INT5_PERIODICINT; - IntClear6 = INT6_PERIODICINT; - IntEnable6 &= ~INT6_PERIODICINT; - break; - - case 3: - /* Serial port receive interrupt */ - break; - - case 2: - /* Serial port transmit interrupt */ - break; - - default: - printk( "Attempt to mask unknown IRQ %d?\n", irq_nr ); - } -} - -static inline void unmask_irq(unsigned int irq_nr) -{ - switch (irq_nr) { - case 0: - IntEnable6 |= INT6_PERIODICINT; - break; - - case 3: - /* Serial port receive interrupt */ - break; - - case 2: - /* Serial port transmit interrupt */ - break; - - default: - printk( "Attempt to unmask unknown IRQ %d?\n", irq_nr ); - } -} - -void disable_irq(unsigned int irq_nr) -{ - unsigned long flags; - - save_and_cli(flags); - mask_irq(irq_nr); - restore_flags(flags); -} - -void enable_irq(unsigned int irq_nr) -{ - unsigned long flags; - - save_and_cli(flags); - unmask_irq(irq_nr); - restore_flags(flags); -} - -/* - * Pointers to the low-level handlers: first the general ones, then the - * fast ones, then the bad ones. - */ -extern void interrupt(void); - -static struct irqaction *irq_action[NR_IRQS] = -{ - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - -int show_interrupts(struct seq_file *p, void *v) -{ - int i; - struct irqaction *action; - unsigned long flags; - - for (i = 0; i < NR_IRQS; i++) { - local_irq_save(flags); - action = irq_action[i]; - if (!action) - goto skip; - seq_printf(p, "%2d: %8d %c %s", - i, kstat_cpu(0).irqs[i], - (action->flags & SA_INTERRUPT) ? '+' : ' ', - action->name); - for (action = action->next; action; action = action->next) { - seq_printf(p, ",%s %s", - (action->flags & SA_INTERRUPT) ? " +" : "", - action->name); - } - seq_putc(p, '\n'); -skip: - local_irq_restore(flags); - } - return 0; -} - -atomic_t __mips_bh_counter; - -/* - * do_IRQ handles IRQ's that have been installed without the - * SA_INTERRUPT flag: it uses the full signal-handling return - * and runs with other interrupts enabled. All relatively slow - * IRQ's should use this format: notably the keyboard/timer - * routines. - */ -asmlinkage void do_IRQ(int irq, struct pt_regs *regs) -{ - struct irqaction *action; - int do_random, cpu; - - if (irq == 20) { - if (IntStatus2 & 0xfffff00) { - if (IntStatus2 & 0x0f000000) - return do_IRQ(2, regs); - } - } - - cpu = smp_processor_id(); - irq_enter(cpu, irq); - kstat_cpu(0).irqs[irq]++; - - if (irq == 20) { - printk("20 %08lx %08lx\n %08lx %08lx\n %08lx\n", - IntStatus1, IntStatus2, IntStatus3, - IntStatus4, IntStatus5 ); - printk("20 %08lx %08lx\n %08lx %08lx\n %08lx\n", - IntEnable1, IntEnable2, IntEnable3, - IntEnable4, IntEnable5 ); - - } - - mask_irq(irq); - action = *(irq + irq_action); - if (action) { - if (!(action->flags & SA_INTERRUPT)) - local_irq_enable(); - do_random = 0; - do { - do_random |= action->flags; - action->handler(irq, action->dev_id, regs); - action = action->next; - } while (action); - if (do_random & SA_SAMPLE_RANDOM) - add_interrupt_randomness(irq); - unmask_irq(irq); - local_irq_disable(); - } else { - IntClear1 = ~0; - IntClear3 = ~0; - IntClear4 = ~0; - IntClear5 = ~0; - unmask_irq(irq); - } - irq_exit(cpu, irq); - - /* unmasking and bottom half handling is done magically for us. */ -} - -/* - * Idea is to put all interrupts - * in a single table and differenciate them just by number. - */ -int setup_nino_irq(int irq, struct irqaction *new) -{ - int shared = 0; - struct irqaction *old, **p; - unsigned long flags; - - p = irq_action + irq; - if ((old = *p) != NULL) { - /* Can't share interrupts unless both agree to */ - if (!(old->flags & new->flags & SA_SHIRQ)) - return -EBUSY; - - /* Can't share interrupts unless both are same type */ - if ((old->flags ^ new->flags) & SA_INTERRUPT) - return -EBUSY; - - /* add new interrupt at end of irq queue */ - do { - p = &old->next; - old = *p; - } while (old); - shared = 1; - } - if (new->flags & SA_SAMPLE_RANDOM) - rand_initialize_irq(irq); - - save_and_cli(flags); - *p = new; - - if (!shared) { - unmask_irq(irq); - } - restore_flags(flags); - return 0; -} - -int request_irq(unsigned int irq, - void (*handler) (int, void *, struct pt_regs *), - unsigned long irqflags, - const char *devname, - void *dev_id) -{ - int retval; - struct irqaction *action; - - if (irq >= NR_IRQS) - return -EINVAL; - if (!handler) - return -EINVAL; - - action = (struct irqaction *) kmalloc(sizeof(struct irqaction), GFP_KERNEL); - if (!action) - return -ENOMEM; - - action->handler = handler; - action->flags = irqflags; - action->mask = 0; - action->name = devname; - action->next = NULL; - action->dev_id = dev_id; - - retval = setup_nino_irq(irq, action); - - if (retval) - kfree(action); - return retval; -} - -void free_irq(unsigned int irq, void *dev_id) -{ - struct irqaction *action, **p; - unsigned long flags; - - if (irq >= NR_IRQS) { - printk(KERN_CRIT __FUNCTION__ ": trying to free IRQ%d\n", irq); - return; - } - for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) { - if (action->dev_id != dev_id) - continue; - - /* Found it - now free it */ - save_and_cli(flags); - *p = action->next; - if (!irq[irq_action]) - mask_irq(irq); - restore_flags(flags); - kfree(action); - return; - } - printk(KERN_CRIT __FUNCTION__ ": trying to free free IRQ%d\n", irq); -} - -unsigned long probe_irq_on(void) -{ - /* TODO */ - return 0; -} - -int probe_irq_off(unsigned long irqs) -{ - /* TODO */ - return 0; -} - -void __init init_IRQ(void) -{ - irq_setup(); -} diff -Nru a/arch/mips/philips/nino/kgdb.c b/arch/mips/philips/nino/kgdb.c --- a/arch/mips/philips/nino/kgdb.c Tue Jul 1 18:44:36 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,83 +0,0 @@ -/* - * linux/arch/mips/philips/nino/kgdb.c - * - * Copyright (C) 2001 Steven J. Hill (sjhill@realitydiluted.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Kernel debugging on the Philips Nino. - */ -#include -#include - -static int remoteDebugInitialized = 0; - -void debugInit(void) -{ -/* - * If low-level debugging (before GDB or console operational) is - * configured, then we do not need to re-initialize the UART. - */ -#ifndef CONFIG_DEBUG_LL - earlyInitUartPR31700(); -#endif -} - -char getDebugChar(void) -{ - char buf; - unsigned long int2, flags; - - if (!remoteDebugInitialized) { - debugInit(); - remoteDebugInitialized = 1; - } - - save_and_cli(flags); - - int2 = IntEnable2; - - IntEnable2 = 0; - - while(!(UartA_Ctrl1 & UART_RX_HOLD_FULL)); - - buf = UartA_Data; - - IntEnable2 = int2; - - restore_flags(flags); - - return buf; -} - -int putDebugChar(char c) -{ - int i; - unsigned long int2; - - if (!remoteDebugInitialized) { - debugInit(); - remoteDebugInitialized = 1; - } - - int2 = IntEnable2; - - IntEnable2 &= - ~(INT2_UARTATXINT | INT2_UARTATXOVERRUN | INT2_UARTAEMPTY); - - for (i = 0; !(IntStatus2 & INT2_UARTATXINT) && (i < 10000); i++); - - IntClear2 = INT2_UARTATXINT | INT2_UARTATXOVERRUN | INT2_UARTAEMPTY; - - UartA_Data = c; - - for (i = 0; !(IntStatus2 & INT2_UARTATXINT) && (i < 10000); i++); - - IntClear2 = INT2_UARTATXINT | INT2_UARTATXOVERRUN | INT2_UARTAEMPTY; - - IntEnable2 = int2; - - return 1; -} diff -Nru a/arch/mips/philips/nino/power.c b/arch/mips/philips/nino/power.c --- a/arch/mips/philips/nino/power.c Tue Jul 1 18:44:36 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,36 +0,0 @@ -/* - * linux/arch/mips/philips/nino/power.c - * - * Copyright (C) 2000 Jim Pick - * Copyright (C) 2001 Steven J. Hill (sjhill@realitydiluted.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Power management routines on the Philips Nino. - */ -#include - -void nino_wait(void) -{ - /* We stop the CPU to conserve power */ - PowerControl |= PWR_STOPCPU; - - /* - * We wait until an interrupt happens... - */ - - /* We resume here */ - PowerControl &= ~PWR_STOPCPU; - - /* Give ourselves a little delay */ - __asm__ __volatile__( - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t"); -} diff -Nru a/arch/mips/philips/nino/prom.c b/arch/mips/philips/nino/prom.c --- a/arch/mips/philips/nino/prom.c Tue Jul 1 18:44:31 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,80 +0,0 @@ -/* - * linux/arch/mips/philips/nino/prom.c - * - * Copyright (C) 2001 Steven J. Hill (sjhill@realitydiluted.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Early initialization code for the Philips Nino. - */ -#include -#include -#include -#include -#include -#include -#include - -char arcs_cmdline[COMMAND_LINE_SIZE]; - -#ifdef CONFIG_FB_TX3912 -extern u_long tx3912fb_paddr; -extern u_long tx3912fb_vaddr; -extern u_long tx3912fb_size; -#endif - -/* Do basic initialization */ -void __init prom_init(int argc, char **argv, - unsigned long magic, int *prom_vec) -{ - u_long free_end, mem_size; - u_int i; - - /* - * collect args and prepare cmd_line - */ - for (i = 1; i < argc; i++) { - strcat(arcs_cmdline, argv[i]); - if (i < (argc - 1)) - strcat(arcs_cmdline, " "); - } - - mips_machgroup = MACH_GROUP_PHILIPS; - mips_machtype = MACH_PHILIPS_NINO; - -#ifdef CONFIG_NINO_4MB - mem_size = 4 << 20; -#elif CONFIG_NINO_8MB - mem_size = 8 << 20; -#elif CONFIG_NINO_16MB - mem_size = 16 << 20; -#endif - -#ifdef CONFIG_FB_TX3912 - /* - * The LCD controller requires that the framebuffer - * start address fall within a 1MB segment and is - * aligned on a 16 byte boundary. The way to assure - * this is to place the framebuffer at the end of - * memory and mark it as reserved. - */ - free_end = (mem_size - tx3912fb_size) & PAGE_MASK; - add_memory_region(0, free_end, BOOT_MEM_RAM); - add_memory_region(free_end, (mem_size - free_end), BOOT_MEM_RESERVED); - - /* - * Calculate physical and virtual addresses for - * the beginning of the framebuffer. - */ - tx3912fb_paddr = PHYSADDR(free_end); - tx3912fb_vaddr = KSEG1ADDR(free_end); -#else - add_memory_region(0, mem_size, BOOT_MEM_RAM); -#endif -} - -void __init prom_free_prom_memory (void) -{ -} diff -Nru a/arch/mips/philips/nino/ramdisk/Makefile b/arch/mips/philips/nino/ramdisk/Makefile --- a/arch/mips/philips/nino/ramdisk/Makefile Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,10 +0,0 @@ -# -# Makefile for the Philips Nino ramdisk -# -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# - -ramdisk.o: ramdisk.gz ld.script - $(LD) $(LDFLAGS) -T ld.script -b binary -o $@ ramdisk.gz diff -Nru a/arch/mips/philips/nino/ramdisk/ld.script b/arch/mips/philips/nino/ramdisk/ld.script --- a/arch/mips/philips/nino/ramdisk/ld.script Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,9 +0,0 @@ -OUTPUT_FORMAT("ecoff-littlemips") -OUTPUT_ARCH(mips) -SECTIONS -{ - .initrd : - { - *(.data) - } -} diff -Nru a/arch/mips/philips/nino/reset.c b/arch/mips/philips/nino/reset.c --- a/arch/mips/philips/nino/reset.c Tue Jul 1 18:44:37 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,37 +0,0 @@ -/* - * linux/arch/mips/philips/nino/reset.c - * - * Copyright (C) 2001 Steven J. Hill (sjhill@realitydiluted.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Generic restart, halt and power off functions for Philips Nino. - */ -#include -#include - -void (*reset_vector)(void) = (void (*)(void)) 0xBFC00000; - -void nino_machine_restart(char *command) -{ - reset_vector(); -} - -void nino_machine_halt(void) -{ - reset_vector(); -} - -void nino_machine_power_off(void) -{ - reset_vector(); -} - -void __init setup_nino_reset_vectors(void) -{ - _machine_restart = nino_machine_restart; - _machine_halt = nino_machine_halt; - _machine_power_off = nino_machine_power_off; -} diff -Nru a/arch/mips/philips/nino/rtc.c b/arch/mips/philips/nino/rtc.c --- a/arch/mips/philips/nino/rtc.c Tue Jul 1 18:44:39 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,34 +0,0 @@ -/* - * linux/arch/mips/philips/nino/rtc.c - * - * Copyright (C) 2001 Steven J. Hill (sjhill@realitydiluted.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Functions to access RTC on the Philips Nino. - */ -#include -#include - -static unsigned char nino_rtc_read_data(unsigned long addr) -{ - return 0; -} - -static void nino_rtc_write_data(unsigned char data, unsigned long addr) -{ -} - -static int nino_rtc_bcd_mode(void) -{ - return 0; -} - -struct rtc_ops nino_rtc_ops = -{ - &nino_rtc_read_data, - &nino_rtc_write_data, - &nino_rtc_bcd_mode -}; diff -Nru a/arch/mips/philips/nino/setup.c b/arch/mips/philips/nino/setup.c --- a/arch/mips/philips/nino/setup.c Tue Jul 1 18:44:31 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,120 +0,0 @@ -/* - * linux/arch/mips/philips/nino/setup.c - * - * Copyright (C) 2001 Steven J. Hill (sjhill@realitydiluted.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Interrupt and exception initialization for Philips Nino. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern struct rtc_ops nino_rtc_ops; - -extern void nino_wait(void); -extern void setup_nino_reset_vectors(void); -extern asmlinkage void nino_handle_int(void); -extern int setup_nino_irq(int, struct irqaction *); -void (*board_time_init) (struct irqaction * irq); - -#ifdef CONFIG_REMOTE_DEBUG -extern void set_debug_traps(void); -extern void breakpoint(void); -static int remote_debug = 0; -#endif - -static void __init nino_irq_setup(void) -{ - unsigned int tmp; - - /* Turn all interrupts off */ - IntEnable1 = 0; - IntEnable2 = 0; - IntEnable3 = 0; - IntEnable4 = 0; - IntEnable5 = 0; - IntEnable6 = 0; - - /* Clear all interrupts */ - IntClear1 = 0xffffffff; - IntClear2 = 0xffffffff; - IntClear3 = 0xffffffff; - IntClear4 = 0xffffffff; - IntClear5 = 0xffffffff; - IntClear6 = 0xffffffff; - - /* - * Enable only the interrupts for the UART and negative - * edge (1-to-0) triggered multi-function I/O pins. - */ - change_cp0_status(ST0_BEV, 0); - tmp = read_32bit_cp0_register(CP0_STATUS); - change_cp0_status(ST0_IM, tmp | IE_IRQ2 | IE_IRQ4); - - /* Register the global interrupt handler */ - set_except_vector(0, nino_handle_int); - -#ifdef CONFIG_REMOTE_DEBUG - if (remote_debug) { - set_debug_traps(); - breakpoint(); - } -#endif -} - -static __init void nino_time_init(struct irqaction *irq) -{ - unsigned int scratch = 0; - - /* - * Enable periodic interrupts - */ - setup_nino_irq(0, irq); - - RTCperiodTimer = PER_TIMER_COUNT; - RTCtimerControl = TIM_ENPERTIMER; - IntEnable5 |= INT5_PERIODICINT; - - scratch = inl(TX3912_CLK_CTRL_BASE); - scratch |= TX3912_CLK_CTRL_ENTIMERCLK; - outl(scratch, TX3912_CLK_CTRL_BASE); - - /* Enable all interrupts */ - IntEnable6 |= INT6_GLOBALEN | INT6_PERIODICINT; -} - -void __init nino_setup(void) -{ - irq_setup = nino_irq_setup; - - board_time_init = nino_time_init; - - /* Base address to use for PC type I/O accesses */ - mips_io_port_base = KSEG1ADDR(0xB0C00000); - - setup_nino_reset_vectors(); - - /* Function called during process idle (cpu_idle) */ - cpu_wait = nino_wait; - -#ifdef CONFIG_FB - conswitchp = &dummy_con; -#endif - -#ifdef CONFIG_REMOTE_DEBUG - remote_debug = 1; -#endif - - rtc_ops = &nino_rtc_ops; -} diff -Nru a/arch/mips/philips/nino/time.c b/arch/mips/philips/nino/time.c --- a/arch/mips/philips/nino/time.c Tue Jul 1 18:44:31 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,218 +0,0 @@ -/* - * linux/arch/mips/philips/nino/time.c - * - * Copyright (C) 1999 Harald Koerfgen - * Copyright (C) 2000 Pavel Machek (pavel@suse.cz) - * Copyright (C) 2001 Steven J. Hill (sjhill@realitydiluted.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Time handling functinos for Philips Nino. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern volatile unsigned long wall_jiffies; - -static struct timeval xbase; - -#define USECS_PER_JIFFY (1000000/HZ) - -/* - * Poll the Interrupt Status Registers - */ -#undef POLL_STATUS - -static unsigned long do_gettimeoffset(void) -{ - /* - * This is a kludge - */ - return 0; -} - -static -void inline readRTC(unsigned long *high, unsigned long *low) -{ - /* read twice, and keep reading till we find two - * the same pairs. This is needed in case the RTC - * was updating its registers and we read a old - * High but a new Low. */ - do { - *high = RTChigh & RTC_HIGHMASK; - *low = RTClow; - } while (*high != (RTChigh & RTC_HIGHMASK) || RTClow!=*low); -} - -/* - * This version of gettimeofday has near millisecond resolution. - */ -void do_gettimeofday(struct timeval *tv) -{ - unsigned long flags; - unsigned long seq; - unsigned long high, low; - - do { - seq = read_seqbegin_irqsave(&xtime_lock, flags); - - // 40 bit RTC, driven by 32khz source: - // +-----------+-----------------------------------------+ - // | HHHH.HHHH | LLLL.LLLL.LLLL.LLLL.LMMM.MMMM.MMMM.MMMM | - // +-----------+-----------------------------------------+ - readRTC(&high,&low); - tv->tv_sec = (high << 17) | (low >> 15); - tv->tv_usec = (low % 32768) * 1953 / 64; - tv->tv_sec += xbase.tv_sec; - tv->tv_usec += xbase.tv_usec; - - tv->tv_usec += do_gettimeoffset(); - - /* - * xtime is atomically updated in timer_bh. lost_ticks is - * nonzero if the timer bottom half hasnt executed yet. - */ - if (jiffies - wall_jiffies) - tv->tv_usec += USECS_PER_JIFFY; - } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); - - if (tv->tv_usec >= 1000000) { - tv->tv_usec -= 1000000; - tv->tv_sec++; - } -} - -void do_settimeofday(struct timeval *tv) -{ - write_seqlock_irq(&xtime_lock); - /* This is revolting. We need to set the xtime.tv_usec - * correctly. However, the value in this location is - * is value at the last tick. - * Discover what correction gettimeofday - * would have done, and then undo it! - */ - tv->tv_usec -= do_gettimeoffset(); - - if (tv->tv_usec < 0) { - tv->tv_usec += 1000000; - tv->tv_sec--; - } - - /* reset RTC to 0 (real time is xbase + RTC) */ - xbase = *tv; - RTCtimerControl |= TIM_RTCCLEAR; - RTCtimerControl &= ~TIM_RTCCLEAR; - RTCalarmHigh = RTCalarmLow = ~0UL; - - xtime = *tv; - time_state = TIME_BAD; - time_maxerror = MAXPHASE; - time_esterror = MAXPHASE; - write_sequnlock_irq(&xtime_lock); -} - -static int set_rtc_mmss(unsigned long nowtime) -{ - int retval = 0; - - return retval; -} - -/* last time the cmos clock got updated */ -static long last_rtc_update = 0; - -/* - * timer_interrupt() needs to keep up the real-time clock, - * as well as call the "do_timer()" routine every clocktick - */ - -int do_write = 1; - -static void -timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ -#ifdef POLL_STATUS - static unsigned long old_IntStatus1 = 0; - static unsigned long old_IntStatus3 = 0; - static unsigned long old_IntStatus4 = 0; - static unsigned long old_IntStatus5 = 0; - static int counter = 0; - int i; - - new_spircv = SPIData & 0xff; - if ((old_spircv != new_spircv) && (new_spircv != 0xff)) { - printk( "SPIData changed: %x\n", new_spircv ); - } - old_spircv = new_spircv; - if (do_write) - SPIData = 0; -#endif - - if (!user_mode(regs)) { - if (prof_buffer && current->pid) { - extern int _stext; - unsigned long pc = regs->cp0_epc; - - pc -= (unsigned long) &_stext; - pc >>= prof_shift; - /* - * Dont ignore out-of-bounds pc values silently, - * put them into the last histogram slot, so if - * present, they will show up as a sharp peak. - */ - if (pc > prof_len - 1) - pc = prof_len - 1; - atomic_inc((atomic_t *) & prof_buffer[pc]); - } - } - - /* - * aaaand... action! - */ - do_timer(regs); - - /* - * If we have an externally syncronized Linux clock, then update - * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be - * called as close as possible to 500 ms before the new second starts. - */ - if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 && - xtime.tv_usec > 500000 - (tick >> 1) && - xtime.tv_usec < 500000 + (tick >> 1)) - { - if (set_rtc_mmss(xtime.tv_sec) == 0) - last_rtc_update = xtime.tv_sec; - else - last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ - } -} - -static struct irqaction irq0 = {timer_interrupt, SA_INTERRUPT, 0, - "timer", NULL, NULL}; - -void (*board_time_init) (struct irqaction * irq); - -int __init time_init(void) -{ - struct timeval starttime; - - starttime.tv_sec = mktime(2000, 1, 1, 0, 0, 0); - starttime.tv_usec = 0; - do_settimeofday(&starttime); - - board_time_init(&irq0); - - return 0; -} diff -Nru a/arch/mips/ramdisk/Makefile b/arch/mips/ramdisk/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/ramdisk/Makefile Tue Jul 1 18:44:40 2003 @@ -0,0 +1,9 @@ +# +# Makefile for a ramdisk image +# + +O_FORMAT = $(shell $(OBJDUMP) -i | head -2 | grep elf32) +img = $(CONFIG_EMBEDDED_RAMDISK_IMAGE) +ramdisk.o: $(subst ",,$(img)) ld.script + echo "O_FORMAT: " $(O_FORMAT) + $(LD) -T ld.script -b binary --oformat $(O_FORMAT) -o $@ $(img) diff -Nru a/arch/mips/ramdisk/ld.script b/arch/mips/ramdisk/ld.script --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/ramdisk/ld.script Tue Jul 1 18:44:40 2003 @@ -0,0 +1,9 @@ +OUTPUT_ARCH(mips) +SECTIONS +{ + .initrd : + { + *(.data) + } +} + diff -Nru a/arch/mips/sgi/kernel/Makefile b/arch/mips/sgi/kernel/Makefile --- a/arch/mips/sgi/kernel/Makefile Tue Jul 1 18:44:31 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,9 +0,0 @@ -# -# Makefile for the SGI specific kernel interface routines -# under Linux. -# - -obj-y += indy_mc.o indy_sc.o indy_hpc.o indy_int.o indy_rtc.o system.o \ - indyIRQ.o reset.o setup.o time.o - -EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips/sgi/kernel/indyIRQ.S b/arch/mips/sgi/kernel/indyIRQ.S --- a/arch/mips/sgi/kernel/indyIRQ.S Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,126 +0,0 @@ -/* - * indyIRQ.S: Interrupt exception dispatch code for FullHouse and - * Guiness. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - */ - -#include -#include -#include -#include - - /* A lot of complication here is taken away because: - * - * 1) We handle one interrupt and return, sitting in a loop - * and moving across all the pending IRQ bits in the cause - * register is _NOT_ the answer, the common case is one - * pending IRQ so optimize in that direction. - * - * 2) We need not check against bits in the status register - * IRQ mask, that would make this routine slow as hell. - * - * 3) Linux only thinks in terms of all IRQs on or all IRQs - * off, nothing in between like BSD spl() brain-damage. - * - * Furthermore, the IRQs on the INDY look basically (barring - * software IRQs which we don't use at all) like: - * - * MIPS IRQ Source - * -------- ------ - * 0 Software (ignored) - * 1 Software (ignored) - * 2 Local IRQ level zero - * 3 Local IRQ level one - * 4 8254 Timer zero - * 5 8254 Timer one - * 6 Bus Error - * 7 R4k timer (what we use) - * - * We handle the IRQ according to _our_ priority which is: - * - * Highest ---- R4k Timer - * Local IRQ zero - * Local IRQ one - * Bus Error - * 8254 Timer zero - * Lowest ---- 8254 Timer one - * - * then we just return, if multiple IRQs are pending then - * we will just take another exception, big deal. - */ - - .text - .set noreorder - .set noat - .align 5 - NESTED(indyIRQ, PT_SIZE, sp) - SAVE_ALL - CLI - .set at - mfc0 s0, CP0_CAUSE # get irq mask - - /* First we check for r4k counter/timer IRQ. */ - andi a0, s0, CAUSEF_IP7 - beq a0, zero, 1f - andi a0, s0, CAUSEF_IP2 # delay slot, check local level zero - - /* Wheee, a timer interrupt. */ - move a0, sp - jal indy_r4k_timer_interrupt - nop # delay slot - - j ret_from_irq - nop # delay slot - -1: - beq a0, zero, 1f - andi a0, s0, CAUSEF_IP3 # delay slot, check local level one - - /* Wheee, local level zero interrupt. */ - jal indy_local0_irqdispatch - move a0, sp # delay slot - - j ret_from_irq - nop # delay slot - -1: - beq a0, zero, 1f - andi a0, s0, CAUSEF_IP6 # delay slot, check bus error - - /* Wheee, local level one interrupt. */ - move a0, sp - jal indy_local1_irqdispatch - nop - - j ret_from_irq - nop - -1: - beq a0, zero, 1f - nop - - /* Wheee, an asynchronous bus error... */ - move a0, sp - jal indy_buserror_irq - nop - - j ret_from_irq - nop - -1: - /* Here by mistake? This is possible, what can happen - * is that by the time we take the exception the IRQ - * pin goes low, so just leave if this is the case. - */ - andi a0, s0, (CAUSEF_IP4 | CAUSEF_IP5) - beq a0, zero, 1f - - /* Must be one of the 8254 timers... */ - move a0, sp - jal indy_8254timer_irq - nop -1: - j ret_from_irq - nop - END(indyIRQ) diff -Nru a/arch/mips/sgi/kernel/indy_hpc.c b/arch/mips/sgi/kernel/indy_hpc.c --- a/arch/mips/sgi/kernel/indy_hpc.c Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,106 +0,0 @@ -/* $Id: indy_hpc.c,v 1.9 1999/12/04 03:59:00 ralf Exp $ - * - * indy_hpc.c: Routines for generic manipulation of the HPC controllers. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * Copyright (C) 1998 Ralf Baechle - */ -#include -#include - -#include -#include -#include -#include -#include - -/* #define DEBUG_SGIHPC */ - -struct hpc3_regs *hpc3c0, *hpc3c1; -struct hpc3_miscregs *hpc3mregs; - -/* We need software copies of these because they are write only. */ -unsigned int sgi_hpc_write1, sgi_hpc_write2; - -/* Machine specific identifier knobs. */ -int sgi_has_ioc2 = 0; -int sgi_guiness = 0; -int sgi_boardid; - -void __init sgihpc_init(void) -{ - unsigned long sid, crev, brev; - - hpc3c0 = (struct hpc3_regs *) (KSEG1 + HPC3_CHIP0_PBASE); - hpc3c1 = (struct hpc3_regs *) (KSEG1 + HPC3_CHIP1_PBASE); - hpc3mregs = (struct hpc3_miscregs *) (KSEG1 + HPC3_MREGS_PBASE); - sid = hpc3mregs->sysid; - - sid &= 0xff; - crev = (sid & 0xe0) >> 5; - brev = (sid & 0x1e) >> 1; - -#ifdef DEBUG_SGIHPC - prom_printf("sgihpc_init: crev<%2x> brev<%2x>\n", crev, brev); - prom_printf("sgihpc_init: "); -#endif - - /* This test works now thanks to William J. Earl */ - if ((sid & 1) == 0 ) { -#ifdef DEBUG_SGIHPC - prom_printf("GUINESS "); -#endif - sgi_guiness = 1; - mips_machtype = MACH_SGI_INDY; - } else { -#ifdef DEBUG_SGIHPC - prom_printf("FULLHOUSE "); -#endif - mips_machtype = MACH_SGI_INDIGO2; - sgi_guiness = 0; - } - sgi_boardid = brev; - -#ifdef DEBUG_SGIHPC - prom_printf("sgi_boardid<%d> ", sgi_boardid); -#endif - - if(crev == 1) { - if((sid & 1) || (brev >= 2)) { -#ifdef DEBUG_SGIHPC - prom_printf("IOC2 "); -#endif - sgi_has_ioc2 = 1; - } else { -#ifdef DEBUG_SGIHPC - prom_printf("IOC1 revision 1 "); -#endif - } - } else { -#ifdef DEBUG_SGIHPC - prom_printf("IOC1 revision 0 "); -#endif - } -#ifdef DEBUG_SGIHPC - prom_printf("\n"); -#endif - - sgi_hpc_write1 = (HPC3_WRITE1_PRESET | - HPC3_WRITE1_KMRESET | - HPC3_WRITE1_ERESET | - HPC3_WRITE1_LC0OFF); - - sgi_hpc_write2 = (HPC3_WRITE2_EASEL | - HPC3_WRITE2_NTHRESH | - HPC3_WRITE2_TPSPEED | - HPC3_WRITE2_EPSEL | - HPC3_WRITE2_U0AMODE | - HPC3_WRITE2_U1AMODE); - - if(!sgi_guiness) - sgi_hpc_write1 |= HPC3_WRITE1_GRESET; - hpc3mregs->write1 = sgi_hpc_write1; - hpc3mregs->write2 = sgi_hpc_write2; - - hpc3c0->pbus_piocfgs[0][6] |= HPC3_PIOPCFG_HW; -} diff -Nru a/arch/mips/sgi/kernel/indy_int.c b/arch/mips/sgi/kernel/indy_int.c --- a/arch/mips/sgi/kernel/indy_int.c Tue Jul 1 18:44:31 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,528 +0,0 @@ -/* - * indy_int.c: Routines for generic manipulation of the INT[23] ASIC - * found on INDY workstations.. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * Copyright (C) 1997, 1998 Ralf Baechle (ralf@gnu.org) - * Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu) - * - Indigo2 changes - * - Interrupt handling fixes - */ -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -/* - * Linux has a controller-independent x86 interrupt architecture. - * every controller has a 'controller-template', that is used - * by the main code to do the right thing. Each driver-visible - * interrupt source is transparently wired to the apropriate - * controller. Thus drivers need not be aware of the - * interrupt-controller. - * - * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC, - * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC. - * (IO-APICs assumed to be messaging to Pentium local-APICs) - * - * the code is designed to be easily extended with new/different - * interrupt controllers, without having to do assembly magic. - */ - -/* #define DEBUG_SGINT */ - -struct sgi_int2_regs *sgi_i2regs; -struct sgi_int3_regs *sgi_i3regs; -struct sgi_ioc_ints *ioc_icontrol; -struct sgi_ioc_timers *ioc_timers; -volatile unsigned char *ioc_tclear; - -static char lc0msk_to_irqnr[256]; -static char lc1msk_to_irqnr[256]; -static char lc2msk_to_irqnr[256]; -static char lc3msk_to_irqnr[256]; - -extern asmlinkage void indyIRQ(void); - -/* Local IRQ's are layed out logically like this: - * - * 0 --> 7 == local 0 interrupts - * 8 --> 15 == local 1 interrupts - * 16 --> 23 == vectored level 2 interrupts - * 24 --> 31 == vectored level 3 interrupts (not used) - */ -static void enable_local0_irq(unsigned int irq) -{ - unsigned long flags; - - save_and_cli(flags); - ioc_icontrol->imask0 |= (1 << (irq - SGINT_LOCAL0)); - restore_flags(flags); -} - -static unsigned int startup_local0_irq(unsigned int irq) -{ - enable_local0_irq(irq); - - return 0; /* Never anything pending */ -} - -static void disable_local0_irq(unsigned int irq) -{ - unsigned long flags; - - save_and_cli(flags); - ioc_icontrol->imask0 &= ~(1 << (irq - SGINT_LOCAL0)); - restore_flags(flags); -} - -#define shutdown_local0_irq disable_local0_irq -#define mask_and_ack_local0_irq disable_local0_irq - -static void end_local0_irq (unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_local0_irq(irq); -} - -static struct hw_interrupt_type ip22_local0_irq_type = { - "IP22 local 0", - startup_local0_irq, - shutdown_local0_irq, - enable_local0_irq, - disable_local0_irq, - mask_and_ack_local0_irq, - end_local0_irq, - NULL -}; - -static void enable_local1_irq(unsigned int irq) -{ - unsigned long flags; - - save_and_cli(flags); - ioc_icontrol->imask1 |= (1 << (irq - SGINT_LOCAL1)); - restore_flags(flags); -} - -static unsigned int startup_local1_irq(unsigned int irq) -{ - enable_local1_irq(irq); - - return 0; /* Never anything pending */ -} - -void disable_local1_irq(unsigned int irq) -{ - unsigned long flags; - - save_and_cli(flags); - ioc_icontrol->imask1 &= ~(1 << (irq- SGINT_LOCAL1)); - restore_flags(flags); -} - -#define shutdown_local1_irq disable_local1_irq -#define mask_and_ack_local1_irq disable_local1_irq - -static void end_local1_irq (unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_local1_irq(irq); -} - -static struct hw_interrupt_type ip22_local1_irq_type = { - "IP22 local 1", - startup_local1_irq, - shutdown_local1_irq, - enable_local1_irq, - disable_local1_irq, - mask_and_ack_local1_irq, - end_local1_irq, - NULL -}; - -static void enable_local2_irq(unsigned int irq) -{ - unsigned long flags; - - save_and_cli(flags); - enable_local0_irq(7); - ioc_icontrol->cmeimask0 |= (1 << (irq - SGINT_LOCAL2)); - restore_flags(flags); -} - -static unsigned int startup_local2_irq(unsigned int irq) -{ - enable_local2_irq(irq); - - return 0; /* Never anything pending */ -} - -void disable_local2_irq(unsigned int irq) -{ - unsigned long flags; - - save_and_cli(flags); - ioc_icontrol->cmeimask0 &= ~(1 << (irq - SGINT_LOCAL2)); - restore_flags(flags); -} - -#define shutdown_local2_irq disable_local2_irq -#define mask_and_ack_local2_irq disable_local2_irq - -static void end_local2_irq (unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_local2_irq(irq); -} - -static struct hw_interrupt_type ip22_local2_irq_type = { - "IP22 local 2", - startup_local2_irq, - shutdown_local2_irq, - enable_local2_irq, - disable_local2_irq, - mask_and_ack_local2_irq, - end_local2_irq, - NULL -}; - -static void enable_local3_irq(unsigned int irq) -{ - unsigned long flags; - - save_and_cli(flags); - printk("Yeeee, got passed irq_nr %d at enable_local3_irq\n", irq); - panic("INVALID IRQ level!"); - restore_flags(flags); -} - -static unsigned int startup_local3_irq(unsigned int irq) -{ - enable_local3_irq(irq); - - return 0; /* Never anything pending */ -} - -void disable_local3_irq(unsigned int irq) -{ - unsigned long flags; - - save_and_cli(flags); - /* - * This way we'll see if anyone would ever want vectored level 3 - * interrupts. Highly unlikely. - */ - printk("Yeeee, got passed irq_nr %d at disable_local3_irq\n", irq); - panic("INVALID IRQ level!"); - restore_flags(flags); -} - -#define shutdown_local3_irq disable_local3_irq -#define mask_and_ack_local3_irq disable_local3_irq - -static void end_local3_irq (unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_local3_irq(irq); -} - -static struct hw_interrupt_type ip22_local3_irq_type = { - "IP22 local 3", - startup_local3_irq, - shutdown_local3_irq, - enable_local3_irq, - disable_local3_irq, - mask_and_ack_local3_irq, - end_local3_irq, - NULL -}; - -void enable_gio_irq(unsigned int irq) -{ - /* XXX TODO XXX */ -} - -static unsigned int startup_gio_irq(unsigned int irq) -{ - enable_gio_irq(irq); - - return 0; /* Never anything pending */ -} - -void disable_gio_irq(unsigned int irq) -{ - /* XXX TODO XXX */ -} - -#define shutdown_gio_irq disable_gio_irq -#define mask_and_ack_gio_irq disable_gio_irq - -static void end_gio_irq (unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_gio_irq(irq); -} - -static struct hw_interrupt_type ip22_gio_irq_type = { - "IP22 GIO", - startup_gio_irq, - shutdown_gio_irq, - enable_gio_irq, - disable_gio_irq, - mask_and_ack_gio_irq, - end_gio_irq, - NULL -}; - -void enable_hpcdma_irq(unsigned int irq) -{ - /* XXX TODO XXX */ -} - -static unsigned int startup_hpcdma_irq(unsigned int irq) -{ - enable_hpcdma_irq(irq); - - return 0; /* Never anything pending */ -} - -void disable_hpcdma_irq(unsigned int irq) -{ - /* XXX TODO XXX */ -} - -#define shutdown_hpcdma_irq disable_hpcdma_irq -#define mask_and_ack_hpcdma_irq disable_hpcdma_irq - -static void end_hpcdma_irq (unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_hpcdma_irq(irq); -} - -static struct hw_interrupt_type ip22_hpcdma_irq_type = { - "IP22 HPC DMA", - startup_hpcdma_irq, - shutdown_hpcdma_irq, - enable_hpcdma_irq, - disable_hpcdma_irq, - mask_and_ack_hpcdma_irq, - end_hpcdma_irq, - NULL -}; - -static struct irqaction r4ktimer_action = { - NULL, 0, 0, "R4000 timer/counter", NULL, NULL, -}; - -static struct irqaction indy_berr_action = { - NULL, 0, 0, "IP22 Bus Error", NULL, NULL, -}; - -static struct irqaction *irq_action[16] = { - NULL, NULL, NULL, NULL, - NULL, NULL, &indy_berr_action, &r4ktimer_action, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL -}; - -void indy_local0_irqdispatch(struct pt_regs *regs) -{ - unsigned char mask = ioc_icontrol->istat0; - unsigned char mask2 = 0; - int irq; - - mask &= ioc_icontrol->imask0; - if (mask & ISTAT0_LIO2) { - mask2 = ioc_icontrol->vmeistat; - mask2 &= ioc_icontrol->cmeimask0; - irq = lc2msk_to_irqnr[mask2]; - } else { - irq = lc0msk_to_irqnr[mask]; - } - - /* if irq == 0, then the interrupt has already been cleared */ - if (irq == 0) - goto end; - - do_IRQ(irq, regs); - goto end; - -no_handler: - printk("No handler for local0 irq: %i\n", irq); - -end: - return; -} - -void indy_local1_irqdispatch(struct pt_regs *regs) -{ - unsigned char mask = ioc_icontrol->istat1; - unsigned char mask2 = 0; - int irq; - - mask &= ioc_icontrol->imask1; - if (mask & ISTAT1_LIO3) { - printk("WHee: Got an LIO3 irq, winging it...\n"); - mask2 = ioc_icontrol->vmeistat; - mask2 &= ioc_icontrol->cmeimask1; - irq = lc3msk_to_irqnr[ioc_icontrol->vmeistat]; - } else { - irq = lc1msk_to_irqnr[mask]; - } - - /* if irq == 0, then the interrupt has already been cleared */ - /* not sure if it is needed here, but it is needed for local0 */ - if (irq == 0) - goto end; - - do_IRQ(irq, regs); - goto end; - -no_handler: - printk("No handler for local1 irq: %i\n", irq); - -end: - return; -} - -void indy_buserror_irq(struct pt_regs *regs) -{ - int cpu = smp_processor_id(); - int irq = 6; - - irq_enter(cpu, irq); - kstat_cpu(0).irqs[irq]++; - printk("Got a bus error IRQ, shouldn't happen yet\n"); - show_regs(regs); - printk("Spinning...\n"); - while(1); - irq_exit(cpu, irq); -} - -void __init init_IRQ(void) -{ - int i; - - sgi_i2regs = (struct sgi_int2_regs *) (KSEG1 + SGI_INT2_BASE); - sgi_i3regs = (struct sgi_int3_regs *) (KSEG1 + SGI_INT3_BASE); - - /* Init local mask --> irq tables. */ - for (i = 0; i < 256; i++) { - if (i & 0x80) { - lc0msk_to_irqnr[i] = 7; - lc1msk_to_irqnr[i] = 15; - lc2msk_to_irqnr[i] = 23; - lc3msk_to_irqnr[i] = 31; - } else if (i & 0x40) { - lc0msk_to_irqnr[i] = 6; - lc1msk_to_irqnr[i] = 14; - lc2msk_to_irqnr[i] = 22; - lc3msk_to_irqnr[i] = 30; - } else if (i & 0x20) { - lc0msk_to_irqnr[i] = 5; - lc1msk_to_irqnr[i] = 13; - lc2msk_to_irqnr[i] = 21; - lc3msk_to_irqnr[i] = 29; - } else if (i & 0x10) { - lc0msk_to_irqnr[i] = 4; - lc1msk_to_irqnr[i] = 12; - lc2msk_to_irqnr[i] = 20; - lc3msk_to_irqnr[i] = 28; - } else if (i & 0x08) { - lc0msk_to_irqnr[i] = 3; - lc1msk_to_irqnr[i] = 11; - lc2msk_to_irqnr[i] = 19; - lc3msk_to_irqnr[i] = 27; - } else if (i & 0x04) { - lc0msk_to_irqnr[i] = 2; - lc1msk_to_irqnr[i] = 10; - lc2msk_to_irqnr[i] = 18; - lc3msk_to_irqnr[i] = 26; - } else if (i & 0x02) { - lc0msk_to_irqnr[i] = 1; - lc1msk_to_irqnr[i] = 9; - lc2msk_to_irqnr[i] = 17; - lc3msk_to_irqnr[i] = 25; - } else if (i & 0x01) { - lc0msk_to_irqnr[i] = 0; - lc1msk_to_irqnr[i] = 8; - lc2msk_to_irqnr[i] = 16; - lc3msk_to_irqnr[i] = 24; - } else { - lc0msk_to_irqnr[i] = 0; - lc1msk_to_irqnr[i] = 0; - lc2msk_to_irqnr[i] = 0; - lc3msk_to_irqnr[i] = 0; - } - } - - /* Indy uses an INT3, Indigo2 uses an INT2 */ - if (sgi_guiness) { - ioc_icontrol = &sgi_i3regs->ints; - ioc_timers = &sgi_i3regs->timers; - ioc_tclear = &sgi_i3regs->tclear; - } else { - ioc_icontrol = &sgi_i2regs->ints; - ioc_timers = &sgi_i2regs->timers; - ioc_tclear = &sgi_i2regs->tclear; - } - - /* Mask out all interrupts. */ - ioc_icontrol->imask0 = 0; - ioc_icontrol->imask1 = 0; - ioc_icontrol->cmeimask0 = 0; - ioc_icontrol->cmeimask1 = 0; - - set_except_vector(0, indyIRQ); - - init_generic_irq(); - - for (i = SGINT_LOCAL0; i < SGINT_END; i++) { - hw_irq_controller *handler; - - if (i < SGINT_LOCAL1) - handler = &ip22_local0_irq_type; - else if (i < SGINT_LOCAL2) - handler = &ip22_local1_irq_type; - else if (i < SGINT_LOCAL3) - handler = &ip22_local2_irq_type; - else if (i < SGINT_GIO) - handler = &ip22_local3_irq_type; - else if (i < SGINT_HPCDMA) - handler = &ip22_gio_irq_type; - else if (i < SGINT_END) - handler = &ip22_hpcdma_irq_type; - - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = 0; - irq_desc[i].depth = 1; - irq_desc[i].handler = handler; - } -} diff -Nru a/arch/mips/sgi/kernel/indy_mc.c b/arch/mips/sgi/kernel/indy_mc.c --- a/arch/mips/sgi/kernel/indy_mc.c Tue Jul 1 18:44:37 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,159 +0,0 @@ -/* - * indy_mc.c: Routines for manipulating the INDY memory controller. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu) - Indigo2 changes - * - * $Id: indy_mc.c,v 1.7 1999/12/04 03:59:00 ralf Exp $ - */ -#include -#include - -#include -#include -#include -#include -#include - -/* #define DEBUG_SGIMC */ - -struct sgimc_misc_ctrl *mcmisc_regs; -u32 *rpsscounter; -struct sgimc_dma_ctrl *dmactrlregs; - -static inline char *mconfig_string(unsigned long val) -{ - switch(val & SGIMC_MCONFIG_RMASK) { - case SGIMC_MCONFIG_FOURMB: - return "4MB"; - - case SGIMC_MCONFIG_EIGHTMB: - return "8MB"; - - case SGIMC_MCONFIG_SXTEENMB: - return "16MB"; - - case SGIMC_MCONFIG_TTWOMB: - return "32MB"; - - case SGIMC_MCONFIG_SFOURMB: - return "64MB"; - - case SGIMC_MCONFIG_OTEIGHTMB: - return "128MB"; - - default: - return "wheee, unknown"; - }; -} - -void __init sgimc_init(void) -{ - unsigned long tmpreg; - - mcmisc_regs = (struct sgimc_misc_ctrl *)(KSEG1+0x1fa00000); - rpsscounter = (unsigned int *) (KSEG1 + 0x1fa01004); - dmactrlregs = (struct sgimc_dma_ctrl *) (KSEG1+0x1fa02000); - - printk("MC: SGI memory controller Revision %d\n", - (int) mcmisc_regs->systemid & SGIMC_SYSID_MASKREV); - -#if 0 /* XXX Until I figure out what this bit really indicates XXX */ - /* XXX Is this systemid bit reliable? */ - if(mcmisc_regs->systemid & SGIMC_SYSID_EPRESENT) { - EISA_bus = 1; - printk("with EISA\n"); - } else { - EISA_bus = 0; - printk("no EISA\n"); - } -#endif - -#ifdef DEBUG_SGIMC - prom_printf("sgimc_init: memconfig0<%s> mconfig1<%s>\n", - mconfig_string(mcmisc_regs->mconfig0), - mconfig_string(mcmisc_regs->mconfig1)); - - prom_printf("mcdump: cpuctrl0<%08lx> cpuctrl1<%08lx>\n", - mcmisc_regs->cpuctrl0, mcmisc_regs->cpuctrl1); - prom_printf("mcdump: divider<%08lx>, gioparm<%04x>\n", - mcmisc_regs->divider, mcmisc_regs->gioparm); -#endif - - /* Place the MC into a known state. This must be done before - * interrupts are first enabled etc. - */ - - /* Step 1: The CPU/GIO error status registers will not latch - * up a new error status until the register has been - * cleared by the cpu. These status registers are - * cleared by writing any value to them. - */ - mcmisc_regs->cstat = mcmisc_regs->gstat = 0; - - /* Step 2: Enable all parity checking in cpu control register - * zero. - */ - tmpreg = mcmisc_regs->cpuctrl0; - tmpreg |= (SGIMC_CCTRL0_EPERRGIO | SGIMC_CCTRL0_EPERRMEM | - SGIMC_CCTRL0_R4KNOCHKPARR); - mcmisc_regs->cpuctrl0 = tmpreg; - - /* Step 3: Setup the MC write buffer depth, this is controlled - * in cpu control register 1 in the lower 4 bits. - */ - tmpreg = mcmisc_regs->cpuctrl1; - tmpreg &= ~0xf; - tmpreg |= 0xd; - mcmisc_regs->cpuctrl1 = tmpreg; - - /* Step 4: Initialize the RPSS divider register to run as fast - * as it can correctly operate. The register is laid - * out as follows: - * - * ---------------------------------------- - * | RESERVED | INCREMENT | DIVIDER | - * ---------------------------------------- - * 31 16 15 8 7 0 - * - * DIVIDER determines how often a 'tick' happens, - * INCREMENT determines by how the RPSS increment - * registers value increases at each 'tick'. Thus, - * for IP22 we get INCREMENT=1, DIVIDER=1 == 0x101 - */ - mcmisc_regs->divider = 0x101; - - /* Step 5: Initialize GIO64 arbitrator configuration register. - * - * NOTE: If you dork with startup code the HPC init code in - * sgihpc_init() must run before us because of how we - * need to know Guiness vs. FullHouse and the board - * revision on this machine. You have been warned. - */ - - /* First the basic invariants across all gio64 implementations. */ - tmpreg = SGIMC_GIOPARM_HPC64; /* All 1st HPC's interface at 64bits. */ - tmpreg |= SGIMC_GIOPARM_ONEBUS; /* Only one physical GIO bus exists. */ - - if(sgi_guiness) { - /* Guiness specific settings. */ - tmpreg |= SGIMC_GIOPARM_EISA64; /* MC talks to EISA at 64bits */ - tmpreg |= SGIMC_GIOPARM_MASTEREISA; /* EISA bus can act as master */ - } else { - /* Fullhouse specific settings. */ - if(sgi_boardid < 2) { - tmpreg |= SGIMC_GIOPARM_HPC264; /* 2nd HPC at 64bits */ - tmpreg |= SGIMC_GIOPARM_PLINEEXP0; /* exp0 pipelines */ - tmpreg |= SGIMC_GIOPARM_MASTEREXP1;/* exp1 masters */ - tmpreg |= SGIMC_GIOPARM_RTIMEEXP0; /* exp0 is realtime */ - } else { - tmpreg |= SGIMC_GIOPARM_HPC264; /* 2nd HPC 64bits */ - tmpreg |= SGIMC_GIOPARM_PLINEEXP0; /* exp[01] pipelined */ - tmpreg |= SGIMC_GIOPARM_PLINEEXP1; - tmpreg |= SGIMC_GIOPARM_MASTEREISA;/* EISA masters */ - /* someone forgot this poor little guy... */ - tmpreg |= SGIMC_GIOPARM_GFX64; /* GFX at 64 bits */ - } - } - mcmisc_regs->gioparm = tmpreg; /* poof */ -} diff -Nru a/arch/mips/sgi/kernel/indy_rtc.c b/arch/mips/sgi/kernel/indy_rtc.c --- a/arch/mips/sgi/kernel/indy_rtc.c Tue Jul 1 18:44:33 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,36 +0,0 @@ -/* - * 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. - * - * RTC routines for Indy style attached Dallas chip. - * - * Copyright (C) 1998, 2001 by Ralf Baechle - */ -#include -#include - -static unsigned char indy_rtc_read_data(unsigned long addr) -{ - volatile unsigned int *rtcregs = (void *)INDY_CLOCK_REGS; - - return rtcregs[addr]; -} - -static void indy_rtc_write_data(unsigned char data, unsigned long addr) -{ - volatile unsigned int *rtcregs = (void *)INDY_CLOCK_REGS; - - rtcregs[addr] = data; -} - -static int indy_rtc_bcd_mode(void) -{ - return 0; -} - -struct rtc_ops indy_rtc_ops = { - &indy_rtc_read_data, - &indy_rtc_write_data, - &indy_rtc_bcd_mode -}; diff -Nru a/arch/mips/sgi/kernel/indy_sc.c b/arch/mips/sgi/kernel/indy_sc.c --- a/arch/mips/sgi/kernel/indy_sc.c Tue Jul 1 18:44:37 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,226 +0,0 @@ -/* - * indy_sc.c: Indy cache management functions. - * - * Copyright (C) 1997, 2001 Ralf Baechle (ralf@gnu.org), - * derived from r4xx0.c by David S. Miller (dm@engr.sgi.com). - */ -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Secondary cache size in bytes, if present. */ -static unsigned long scache_size; - -#undef DEBUG_CACHE - -#define SC_SIZE 0x00080000 -#define SC_LINE 32 -#define CI_MASK (SC_SIZE - SC_LINE) -#define SC_INDEX(n) ((n) & CI_MASK) - -static inline void indy_sc_wipe(unsigned long first, unsigned long last) -{ - unsigned long tmp; - - __asm__ __volatile__( - ".set\tnoreorder\t\t\t# indy_sc_wipe\n\t" - ".set\tmips3\n\t" - ".set\tnoat\n\t" - "mfc0\t%2, $12\n\t" - "li\t$1, 0x80\t\t\t# Go 64 bit\n\t" - "mtc0\t$1, $12\n\t" - - "dli\t$1, 0x9000000080000000\n\t" - "or\t%0, $1\t\t\t# first line to flush\n\t" - "or\t%1, $1\t\t\t# last line to flush\n\t" - ".set\tat\n\t" - - "1:\tsw\t$0, 0(%0)\n\t" - "bne\t%0, %1, 1b\n\t" - "daddu\t%0, 32\n\t" - - "mtc0\t%2, $12\t\t\t# Back to 32 bit\n\t" - "nop; nop; nop; nop;\n\t" - ".set\tmips0\n\t" - ".set\treorder" - : "=r" (first), "=r" (last), "=&r" (tmp) - : "0" (first), "1" (last) - : "$1"); -} - -static void indy_sc_wback_invalidate(unsigned long addr, unsigned long size) -{ - unsigned long first_line, last_line; - unsigned int flags; - -#ifdef DEBUG_CACHE - printk("indy_sc_wback_invalidate[%08lx,%08lx]", addr, size); -#endif - - if (!size) - return; - - /* Which lines to flush? */ - first_line = SC_INDEX(addr); - last_line = SC_INDEX(addr + size - 1); - - local_irq_save(flags); - if (first_line <= last_line) { - indy_sc_wipe(first_line, last_line); - goto out; - } - - indy_sc_wipe(first_line, SC_SIZE - SC_LINE); - indy_sc_wipe(0, last_line); -out: - local_irq_restore(flags); -} - -static void indy_sc_enable(void) -{ - unsigned long addr, tmp1, tmp2; - - /* This is really cool... */ -#ifdef DEBUG_CACHE - printk("Enabling R4600 SCACHE\n"); -#endif - __asm__ __volatile__( - ".set\tpush\n\t" - ".set\tnoreorder\n\t" - ".set\tmips3\n\t" - "mfc0\t%2, $12\n\t" - "nop; nop; nop; nop;\n\t" - "li\t%1, 0x80\n\t" - "mtc0\t%1, $12\n\t" - "nop; nop; nop; nop;\n\t" - "li\t%0, 0x1\n\t" - "dsll\t%0, 31\n\t" - "lui\t%1, 0x9000\n\t" - "dsll32\t%1, 0\n\t" - "or\t%0, %1, %0\n\t" - "sb\t$0, 0(%0)\n\t" - "mtc0\t$0, $12\n\t" - "nop; nop; nop; nop;\n\t" - "mtc0\t%2, $12\n\t" - "nop; nop; nop; nop;\n\t" - ".set\tpop" - : "=r" (tmp1), "=r" (tmp2), "=r" (addr)); -} - -static void indy_sc_disable(void) -{ - unsigned long tmp1, tmp2, tmp3; - -#ifdef DEBUG_CACHE - printk("Disabling R4600 SCACHE\n"); -#endif - __asm__ __volatile__( - ".set\tpush\n\t" - ".set\tnoreorder\n\t" - ".set\tmips3\n\t" - "li\t%0, 0x1\n\t" - "dsll\t%0, 31\n\t" - "lui\t%1, 0x9000\n\t" - "dsll32\t%1, 0\n\t" - "or\t%0, %1, %0\n\t" - "mfc0\t%2, $12\n\t" - "nop; nop; nop; nop\n\t" - "li\t%1, 0x80\n\t" - "mtc0\t%1, $12\n\t" - "nop; nop; nop; nop\n\t" - "sh\t$0, 0(%0)\n\t" - "mtc0\t$0, $12\n\t" - "nop; nop; nop; nop\n\t" - "mtc0\t%2, $12\n\t" - "nop; nop; nop; nop\n\t" - ".set\tpop" - : "=r" (tmp1), "=r" (tmp2), "=r" (tmp3)); -} - -static inline int __init indy_sc_probe(void) -{ - volatile unsigned int *cpu_control; - unsigned short cmd = 0xc220; - unsigned long data = 0; - int i, n; - -#ifdef __MIPSEB__ - cpu_control = (volatile unsigned int *) KSEG1ADDR(0x1fa00034); -#else - cpu_control = (volatile unsigned int *) KSEG1ADDR(0x1fa00030); -#endif -#define DEASSERT(bit) (*(cpu_control) &= (~(bit))) -#define ASSERT(bit) (*(cpu_control) |= (bit)) -#define DELAY for(n = 0; n < 100000; n++) __asm__ __volatile__("") - DEASSERT(SGIMC_EEPROM_PRE); - DEASSERT(SGIMC_EEPROM_SDATAO); - DEASSERT(SGIMC_EEPROM_SECLOCK); - DEASSERT(SGIMC_EEPROM_PRE); - DELAY; - ASSERT(SGIMC_EEPROM_CSEL); ASSERT(SGIMC_EEPROM_SECLOCK); - for(i = 0; i < 11; i++) { - if(cmd & (1<<15)) - ASSERT(SGIMC_EEPROM_SDATAO); - else - DEASSERT(SGIMC_EEPROM_SDATAO); - DEASSERT(SGIMC_EEPROM_SECLOCK); - ASSERT(SGIMC_EEPROM_SECLOCK); - cmd <<= 1; - } - DEASSERT(SGIMC_EEPROM_SDATAO); - for(i = 0; i < (sizeof(unsigned short) * 8); i++) { - unsigned int tmp; - - DEASSERT(SGIMC_EEPROM_SECLOCK); - DELAY; - ASSERT(SGIMC_EEPROM_SECLOCK); - DELAY; - data <<= 1; - tmp = *cpu_control; - if(tmp & SGIMC_EEPROM_SDATAI) - data |= 1; - } - DEASSERT(SGIMC_EEPROM_SECLOCK); - DEASSERT(SGIMC_EEPROM_CSEL); - ASSERT(SGIMC_EEPROM_PRE); - ASSERT(SGIMC_EEPROM_SECLOCK); - - data <<= PAGE_SHIFT; - if (data == 0) - return 0; - - scache_size = data; - - printk("R4600/R5000 SCACHE size %ldK, linesize 32 bytes.\n", - scache_size >> 10); - - return 1; -} - -/* XXX Check with wje if the Indy caches can differenciate between - writeback + invalidate and just invalidate. */ -struct bcache_ops indy_sc_ops = { - indy_sc_enable, - indy_sc_disable, - indy_sc_wback_invalidate, - indy_sc_wback_invalidate -}; - -void __init indy_sc_init(void) -{ - if (indy_sc_probe()) { - indy_sc_enable(); - bcops = &indy_sc_ops; - } -} diff -Nru a/arch/mips/sgi/kernel/reset.c b/arch/mips/sgi/kernel/reset.c --- a/arch/mips/sgi/kernel/reset.c Tue Jul 1 18:44:32 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,241 +0,0 @@ -/* - * 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) 1997, 1998, 2001 by Ralf Baechle - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Just powerdown if init hasn't done after POWERDOWN_TIMEOUT seconds. - * I'm not shure if this feature is a good idea, for now it's here just to - * make the power button make behave just like under IRIX. - */ -#define POWERDOWN_TIMEOUT 120 - -/* - * Blink frequency during reboot grace period and when paniced. - */ -#define POWERDOWN_FREQ (HZ / 4) -#define PANIC_FREQ (HZ / 8) - -static unsigned char sgi_volume; - -static struct timer_list power_timer, blink_timer, debounce_timer, volume_timer; -static int shuting_down, has_paniced; - -static void sgi_machine_restart(char *command) __attribute__((noreturn)); -static void sgi_machine_halt(void) __attribute__((noreturn)); -static void sgi_machine_power_off(void) __attribute__((noreturn)); - -/* XXX How to pass the reboot command to the firmware??? */ -static void sgi_machine_restart(char *command) -{ - if (shuting_down) - sgi_machine_power_off(); - prom_reboot(); -} - -static void sgi_machine_halt(void) -{ - if (shuting_down) - sgi_machine_power_off(); - ArcEnterInteractiveMode(); -} - -static void sgi_machine_power_off(void) -{ - struct indy_clock *clock = (struct indy_clock *)INDY_CLOCK_REGS; - - cli(); - - clock->cmd |= 0x08; /* Disable watchdog */ - clock->whsec = 0; - clock->wsec = 0; - - while(1) { - hpc3mregs->panel=0xfe; - /* Good bye cruel world ... */ - - /* If we're still running, we probably got sent an alarm - interrupt. Read the flag to clear it. */ - clock->halarm; - } -} - -static void power_timeout(unsigned long data) -{ - sgi_machine_power_off(); -} - -static void blink_timeout(unsigned long data) -{ - /* XXX fix this for fullhouse */ - sgi_hpc_write1 ^= (HPC3_WRITE1_LC0OFF|HPC3_WRITE1_LC1OFF); - hpc3mregs->write1 = sgi_hpc_write1; - - mod_timer(&blink_timer, jiffies+data); -} - -static void debounce(unsigned long data) -{ - del_timer(&debounce_timer); - if (ioc_icontrol->istat1 & 2) { /* Interrupt still being sent. */ - debounce_timer.expires = jiffies + 5; /* 0.05s */ - add_timer(&debounce_timer); - - hpc3mregs->panel = 0xf3; - - return; - } - - if (has_paniced) - prom_reboot(); - - enable_irq(SGI_PANEL_IRQ); -} - -static inline void power_button(void) -{ - if (has_paniced) - return; - - if (shuting_down || kill_proc(1, SIGINT, 1)) { - /* No init process or button pressed twice. */ - sgi_machine_power_off(); - } - - shuting_down = 1; - blink_timer.data = POWERDOWN_FREQ; - blink_timeout(POWERDOWN_FREQ); - - init_timer(&power_timer); - power_timer.function = power_timeout; - power_timer.expires = jiffies + POWERDOWN_TIMEOUT * HZ; - add_timer(&power_timer); -} - -inline void sgi_volume_set(unsigned char volume) -{ - sgi_volume = volume; - - hpc3c0->pbus_extregs[2][0] = sgi_volume; - hpc3c0->pbus_extregs[2][1] = sgi_volume; -} - -inline void sgi_volume_get(unsigned char *volume) -{ - *volume = sgi_volume; -} - -static inline void volume_up_button(unsigned long data) -{ - del_timer(&volume_timer); - - if (sgi_volume < 0xff) - sgi_volume++; - - hpc3c0->pbus_extregs[2][0] = sgi_volume; - hpc3c0->pbus_extregs[2][1] = sgi_volume; - - if (ioc_icontrol->istat1 & 2) { - volume_timer.expires = jiffies + 1; - add_timer(&volume_timer); - } - -} - -static inline void volume_down_button(unsigned long data) -{ - del_timer(&volume_timer); - - if (sgi_volume > 0) - sgi_volume--; - - hpc3c0->pbus_extregs[2][0] = sgi_volume; - hpc3c0->pbus_extregs[2][1] = sgi_volume; - - if (ioc_icontrol->istat1 & 2) { - volume_timer.expires = jiffies + 1; - add_timer(&volume_timer); - } -} - -static void panel_int(int irq, void *dev_id, struct pt_regs *regs) -{ - unsigned int buttons; - - buttons = hpc3mregs->panel; - hpc3mregs->panel = 3; /* power_interrupt | power_supply_on */ - - if (ioc_icontrol->istat1 & 2) { /* Wait until interrupt goes away */ - disable_irq(SGI_PANEL_IRQ); - init_timer(&debounce_timer); - debounce_timer.function = debounce; - debounce_timer.expires = jiffies + 5; - add_timer(&debounce_timer); - } - - if (!(buttons & 2)) /* Power button was pressed */ - power_button(); - if (!(buttons & 0x40)) { /* Volume up button was pressed */ - init_timer(&volume_timer); - volume_timer.function = volume_up_button; - volume_timer.expires = jiffies + 1; - add_timer(&volume_timer); - } - if (!(buttons & 0x10)) { /* Volume down button was pressed */ - init_timer(&volume_timer); - volume_timer.function = volume_down_button; - volume_timer.expires = jiffies + 1; - add_timer(&volume_timer); - } -} - -static int panic_event(struct notifier_block *this, unsigned long event, - void *ptr) -{ - if (has_paniced) - return NOTIFY_DONE; - has_paniced = 1; - - blink_timer.data = PANIC_FREQ; - blink_timeout(PANIC_FREQ); - - return NOTIFY_DONE; -} - -static struct notifier_block panic_block = { - panic_event, - NULL, - 0 -}; - -void indy_reboot_setup(void) -{ - static int setup_done; - - if (setup_done) - return; - setup_done = 1; - - _machine_restart = sgi_machine_restart; - _machine_halt = sgi_machine_halt; - _machine_power_off = sgi_machine_power_off; - - request_irq(SGI_PANEL_IRQ, panel_int, 0, "Front Panel", NULL); - init_timer(&blink_timer); - blink_timer.function = blink_timeout; - notifier_chain_register(&panic_notifier_list, &panic_block); -} diff -Nru a/arch/mips/sgi/kernel/setup.c b/arch/mips/sgi/kernel/setup.c --- a/arch/mips/sgi/kernel/setup.c Tue Jul 1 18:44:35 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,308 +0,0 @@ -/* - * setup.c: SGI specific setup, including init of the feature struct. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * Copyright (C) 1997, 1998 Ralf Baechle (ralf@gnu.org) - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_REMOTE_DEBUG -extern void rs_kgdb_hook(int); -extern void breakpoint(void); -static int remote_debug = 0; -#endif - -#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_ARC_CONSOLE) -extern void console_setup(char *); -#endif - -extern unsigned long r4k_interval; /* Cycle counter ticks per 1/HZ seconds */ - -extern struct rtc_ops indy_rtc_ops; -void indy_reboot_setup(void); -void sgi_volume_set(unsigned char); - -#define sgi_kh ((struct hpc_keyb *) (KSEG1 + 0x1fbd9800 + 64)) - -#define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */ - -static void sgi_request_region(void) -{ - /* No I/O ports are being used on the Indy. */ -} - -static int sgi_request_irq(void (*handler)(int, void *, struct pt_regs *)) -{ - /* Dirty hack, this get's called as a callback from the keyboard - driver. We piggyback the initialization of the front panel - button handling on it even though they're technically not - related with the keyboard driver in any way. Doing it from - indy_setup wouldn't work since kmalloc isn't initialized yet. */ - indy_reboot_setup(); - - return request_irq(SGI_KEYBOARD_IRQ, handler, 0, "keyboard", NULL); -} - -static int sgi_aux_request_irq(void (*handler)(int, void *, struct pt_regs *)) -{ - /* Nothing to do, interrupt is shared with the keyboard hw */ - return 0; -} - -static void sgi_aux_free_irq(void) -{ - /* Nothing to do, interrupt is shared with the keyboard hw */ -} - -static unsigned char sgi_read_input(void) -{ - return sgi_kh->data; -} - -static void sgi_write_output(unsigned char val) -{ - int status; - - do { - status = sgi_kh->command; - } while (status & KBD_STAT_IBF); - sgi_kh->data = val; -} - -static void sgi_write_command(unsigned char val) -{ - int status; - - do { - status = sgi_kh->command; - } while (status & KBD_STAT_IBF); - sgi_kh->command = val; -} - -static unsigned char sgi_read_status(void) -{ - return sgi_kh->command; -} - -struct kbd_ops sgi_kbd_ops = { - sgi_request_region, - sgi_request_irq, - - sgi_aux_request_irq, - sgi_aux_free_irq, - - sgi_read_input, - sgi_write_output, - sgi_write_command, - sgi_read_status -}; - -static unsigned long dosample(volatile unsigned char *tcwp, - volatile unsigned char *tc2p) -{ - unsigned long ct0, ct1; - unsigned char msb, lsb; - - /* Start the counter. */ - *tcwp = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CALL | SGINT_TCWORD_MRGEN); - *tc2p = (SGINT_TCSAMP_COUNTER & 0xff); - *tc2p = (SGINT_TCSAMP_COUNTER >> 8); - - /* Get initial counter invariant */ - ct0 = read_32bit_cp0_register(CP0_COUNT); - - /* Latch and spin until top byte of counter2 is zero */ - do { - *tcwp = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CLAT); - lsb = *tc2p; - msb = *tc2p; - ct1 = read_32bit_cp0_register(CP0_COUNT); - } while(msb); - - /* Stop the counter. */ - *tcwp = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CALL | SGINT_TCWORD_MSWST); - - /* - * Return the difference, this is how far the r4k counter increments - * for every 1/HZ seconds. We round off the nearest 1 MHz of master - * clock (= 1000000 / 100 / 2 = 5000 count). - */ - - return ((ct1 - ct0) / 5000) * 5000; -} - -#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5) - -void sgi_time_init (struct irqaction *irq) { - /* Here we need to calibrate the cycle counter to at least be close. - * We don't need to actually register the irq handler because that's - * all done in indyIRQ.S. - */ - struct sgi_ioc_timers *p; - volatile unsigned char *tcwp, *tc2p; - unsigned long r4k_ticks[3]; - unsigned long r4k_next; - - /* Figure out the r4k offset, the algorithm is very simple - * and works in _all_ cases as long as the 8254 counter - * register itself works ok (as an interrupt driving timer - * it does not because of bug, this is why we are using - * the onchip r4k counter/compare register to serve this - * purpose, but for r4k_offset calculation it will work - * ok for us). There are other very complicated ways - * of performing this calculation but this one works just - * fine so I am not going to futz around. ;-) - */ - p = ioc_timers; - tcwp = &p->tcword; - tc2p = &p->tcnt2; - - printk("Calibrating system timer... "); - dosample(tcwp, tc2p); /* Prime cache. */ - dosample(tcwp, tc2p); /* Prime cache. */ - /* Zero is NOT an option. */ - do { - r4k_ticks[0] = dosample (tcwp, tc2p); - } while (!r4k_ticks[0]); - do { - r4k_ticks[1] = dosample (tcwp, tc2p); - } while (!r4k_ticks[1]); - - if (r4k_ticks[0] != r4k_ticks[1]) { - printk ("warning: timer counts differ, retrying..."); - r4k_ticks[2] = dosample (tcwp, tc2p); - if (r4k_ticks[2] == r4k_ticks[0] - || r4k_ticks[2] == r4k_ticks[1]) - r4k_interval = r4k_ticks[2]; - else { - printk ("disagreement, using average..."); - r4k_interval = (r4k_ticks[0] + r4k_ticks[1] - + r4k_ticks[2]) / 3; - } - } else - r4k_interval = r4k_ticks[0]; - - printk("%d [%d.%02d MHz CPU]\n", (int) r4k_interval, - (int) (r4k_interval / 5000), (int) (r4k_interval % 5000) / 50); - - /* Set ourselves up for future interrupts */ - r4k_next = (read_32bit_cp0_register(CP0_COUNT) + r4k_interval); - write_32bit_cp0_register(CP0_COMPARE, r4k_next); - change_cp0_status(ST0_IM, ALLINTS); - sti (); -} - -void __init sgi_setup(void) -{ -#ifdef CONFIG_SERIAL_CONSOLE - char *ctype; -#endif -#ifdef CONFIG_REMOTE_DEBUG - char *kgdb_ttyd; -#endif - - board_time_init = sgi_time_init; - - /* Init the INDY HPC I/O controller. Need to call this before - * fucking with the memory controller because it needs to know the - * boardID and whether this is a Guiness or a FullHouse machine. - */ - sgihpc_init(); - - /* Init INDY memory controller. */ - sgimc_init(); - - /* Now enable boardcaches, if any. */ - indy_sc_init(); - -#ifdef CONFIG_SERIAL_CONSOLE - /* ARCS console environment variable is set to "g?" for - * graphics console, it is set to "d" for the first serial - * line and "d2" for the second serial line. - */ - ctype = ArcGetEnvironmentVariable("console"); - if(*ctype == 'd') { - if(*(ctype+1)=='2') - console_setup ("ttyS1"); - else - console_setup ("ttyS0"); - } -#endif - -#ifdef CONFIG_REMOTE_DEBUG - kgdb_ttyd = prom_getcmdline(); - if ((kgdb_ttyd = strstr(kgdb_ttyd, "kgdb=ttyd")) != NULL) { - int line; - kgdb_ttyd += strlen("kgdb=ttyd"); - if (*kgdb_ttyd != '1' && *kgdb_ttyd != '2') - printk("KGDB: Uknown serial line /dev/ttyd%c, " - "falling back to /dev/ttyd1\n", *kgdb_ttyd); - line = *kgdb_ttyd == '2' ? 0 : 1; - printk("KGDB: Using serial line /dev/ttyd%d for session\n", - line ? 1 : 2); - rs_kgdb_hook(line); - - printk("KGDB: Using serial line /dev/ttyd%d for session, " - "please connect your debugger\n", line ? 1 : 2); - - remote_debug = 1; - /* Breakpoints and stuff are in sgi_irq_setup() */ - } -#endif - -#ifdef CONFIG_ARC_CONSOLE - console_setup("ttyS0"); -#endif - - sgi_volume_set(simple_strtoul(ArcGetEnvironmentVariable("volume"), NULL, 10)); - -#ifdef CONFIG_VT -#ifdef CONFIG_SGI_NEWPORT_CONSOLE - conswitchp = &newport_con; - - screen_info = (struct screen_info) { - 0, 0, /* orig-x, orig-y */ - 0, /* unused */ - 0, /* orig_video_page */ - 0, /* orig_video_mode */ - 160, /* orig_video_cols */ - 0, 0, 0, /* unused, ega_bx, unused */ - 64, /* orig_video_lines */ - 0, /* orig_video_isVGA */ - 16 /* orig_video_points */ - }; -#else - conswitchp = &dummy_con; -#endif -#endif - - rtc_ops = &indy_rtc_ops; - kbd_ops = &sgi_kbd_ops; -#ifdef CONFIG_PSMOUSE - aux_device_present = 0xaa; -#endif -#ifdef CONFIG_VIDEO_VINO - init_vino(); -#endif -} diff -Nru a/arch/mips/sgi/kernel/system.c b/arch/mips/sgi/kernel/system.c --- a/arch/mips/sgi/kernel/system.c Tue Jul 1 18:44:36 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,132 +0,0 @@ -/* - * system.c: Probe the system type using ARCS prom interface library. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * - * $Id: system.c,v 1.8 1999/10/09 00:00:59 ralf Exp $ - */ -#include -#include -#include -#include - -#include -#include -#include - -enum sgi_mach sgimach; - -struct smatch { - char *name; - int type; -}; - -static struct smatch sgi_cputable[] = { - { "MIPS-R2000", CPU_R2000 }, - { "MIPS-R3000", CPU_R3000 }, - { "MIPS-R3000A", CPU_R3000A }, - { "MIPS-R4000", CPU_R4000SC }, - { "MIPS-R4400", CPU_R4400SC }, - { "MIPS-R4600", CPU_R4600 }, - { "MIPS-R8000", CPU_R8000 }, - { "MIPS-R5000", CPU_R5000 }, - { "MIPS-R5000A", CPU_R5000A } -}; - -#define NUM_CPUS 9 /* for now */ - -static int __init string_to_cpu(char *s) -{ - int i; - - for(i = 0; i < NUM_CPUS; i++) { - if(!strcmp(s, sgi_cputable[i].name)) - return sgi_cputable[i].type; - } - prom_printf("\nYeee, could not determine MIPS cpu type <%s>\n", s); - prom_printf("press a key to reboot\n"); - prom_getchar(); - romvec->imode(); - return 0; -} - -/* - * We' call this early before loadmmu(). If we do the other way around - * the firmware will crash and burn. - */ -void __init sgi_sysinit(void) -{ - pcomponent *p, *toplev, *cpup = 0; - int cputype = -1; - - - /* The root component tells us what machine architecture we - * have here. - */ - p = prom_getchild(PROM_NULL_COMPONENT); - - /* Now scan for cpu(s). */ - toplev = p = prom_getchild(p); - while(p) { - int ncpus = 0; - - if(p->type == Cpu) { - if(++ncpus > 1) { - prom_printf("\nYeee, SGI MP not ready yet\n"); - prom_printf("press a key to reboot\n"); - prom_getchar(); - romvec->imode(); - } - printk("CPU: %s ", p->iname); - cpup = p; - cputype = string_to_cpu(cpup->iname); - } - p = prom_getsibling(p); - } - if(cputype == -1) { - prom_printf("\nYeee, could not find cpu ARCS component\n"); - prom_printf("press a key to reboot\n"); - prom_getchar(); - romvec->imode(); - } - p = prom_getchild(cpup); - while(p) { - switch(p->class) { - case processor: - switch(p->type) { - case Fpu: - printk("FPU<%s> ", p->iname); - break; - - default: - break; - }; - break; - - case cache: - switch(p->type) { - case picache: - printk("ICACHE "); - break; - - case pdcache: - printk("DCACHE "); - break; - - case sccache: - printk("SCACHE "); - break; - - default: - break; - - }; - break; - - default: - break; - }; - p = prom_getsibling(p); - } - printk("\n"); -} diff -Nru a/arch/mips/sgi/kernel/time.c b/arch/mips/sgi/kernel/time.c --- a/arch/mips/sgi/kernel/time.c Tue Jul 1 18:44:32 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,21 +0,0 @@ -/* - * time.c: Generic SGI handler for (spurious) 8254 interrupts - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - */ -#include -#include -#include - -void indy_8254timer_irq(void) -{ - int cpu = smp_processor_id(); - int irq = 4; - - irq_enter(cpu, irq); - kstat_cpu(0).irqs[irq]++; - printk("indy_8254timer_irq: Whoops, should not have gotten this IRQ\n"); - prom_getchar(); - ArcEnterInteractiveMode(); - irq_exit(cpu, irq); -} diff -Nru a/arch/mips/sgi-ip22/Makefile b/arch/mips/sgi-ip22/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sgi-ip22/Makefile Tue Jul 1 18:44:40 2003 @@ -0,0 +1,12 @@ +# +# Makefile for the SGI specific kernel interface routines +# under Linux. +# + +obj-y += ip22-mc.o ip22-hpc.o ip22-int.o ip22-irq.o ip22-berr.o \ + ip22-time.o ip22-rtc.o ip22-nvram.o ip22-reset.o \ + ip22-setup.o ip22-ksyms.o + +obj-$(CONFIG_EISA) += ip22-eisa.o + +EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips/sgi-ip22/ip22-berr.c b/arch/mips/sgi-ip22/ip22-berr.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sgi-ip22/ip22-berr.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,91 @@ +/* + * ip22-berr.c: Bus error handling. + * + * Copyright (C) 2002 Ladislav Michl + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +static unsigned int cpu_err_stat; /* Status reg for CPU */ +static unsigned int gio_err_stat; /* Status reg for GIO */ +static unsigned int cpu_err_addr; /* Error address reg for CPU */ +static unsigned int gio_err_addr; /* Error address reg for GIO */ + +static void save_and_clear_buserr(void) +{ + /* save memory controler's error status registers */ + cpu_err_addr = sgimc->cerr; + cpu_err_stat = sgimc->cstat; + gio_err_addr = sgimc->gerr; + gio_err_stat = sgimc->gstat; + + sgimc->cstat = sgimc->gstat = 0; +} + +#define GIO_ERRMASK 0xff00 +#define CPU_ERRMASK 0x3f00 + +static void print_buserr(void) +{ + if (cpu_err_stat & CPU_ERRMASK) + printk(KERN_ALERT "CPU error 0x%x<%s%s%s%s%s%s> @ 0x%08x\n", + cpu_err_stat, + cpu_err_stat & SGIMC_CSTAT_RD ? "RD " : "", + cpu_err_stat & SGIMC_CSTAT_PAR ? "PAR " : "", + cpu_err_stat & SGIMC_CSTAT_ADDR ? "ADDR " : "", + cpu_err_stat & SGIMC_CSTAT_SYSAD_PAR ? "SYSAD " : "", + cpu_err_stat & SGIMC_CSTAT_SYSCMD_PAR ? "SYSCMD " : "", + cpu_err_stat & SGIMC_CSTAT_BAD_DATA ? "BAD_DATA " : "", + cpu_err_addr); + if (gio_err_stat & GIO_ERRMASK) + printk(KERN_ALERT "GIO error 0x%x:<%s%s%s%s%s%s%s%s> @ 0x08%x\n", + gio_err_stat, + gio_err_stat & SGIMC_GSTAT_RD ? "RD " : "", + gio_err_stat & SGIMC_GSTAT_WR ? "WR " : "", + gio_err_stat & SGIMC_GSTAT_TIME ? "TIME " : "", + gio_err_stat & SGIMC_GSTAT_PROM ? "PROM " : "", + gio_err_stat & SGIMC_GSTAT_ADDR ? "ADDR " : "", + gio_err_stat & SGIMC_GSTAT_BC ? "BC " : "", + gio_err_stat & SGIMC_GSTAT_PIO_RD ? "PIO_RD " : "", + gio_err_stat & SGIMC_GSTAT_PIO_WR ? "PIO_WR " : "", + gio_err_addr); +} + +/* + * MC sends an interrupt whenever bus or parity errors occur. In addition, + * if the error happened during a CPU read, it also asserts the bus error + * pin on the R4K. Code in bus error handler save the MC bus error registers + * and then clear the interrupt when this happens. + */ + +void ip22_be_interrupt(int irq, struct pt_regs *regs) +{ + save_and_clear_buserr(); + print_buserr(); + panic("Bus error, epc == %08lx, ra == %08lx", + regs->cp0_epc, regs->regs[31]); +} + +int ip22_be_handler(struct pt_regs *regs, int is_fixup) +{ + save_and_clear_buserr(); + if (is_fixup) + return MIPS_BE_FIXUP; + print_buserr(); + return MIPS_BE_FATAL; +} + +void __init ip22_be_init(void) +{ + board_be_handler = ip22_be_handler; +} diff -Nru a/arch/mips/sgi-ip22/ip22-eisa.c b/arch/mips/sgi-ip22/ip22-eisa.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sgi-ip22/ip22-eisa.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,307 @@ +/* + * Basic EISA bus support for the SGI Indigo-2. + * + * (C) 2002 Pascal Dameme + * and Marc Zyngier + * + * This code is released under both the GPL version 2 and BSD + * licenses. Either license may be used. + * + * This code offers a very basic support for this EISA bus present in + * the SGI Indigo-2. It currently only supports PIO (forget about DMA + * for the time being). This is enough for a low-end ethernet card, + * but forget about your favorite SCSI card... + * + * TODO : + * - Fix bugs... + * - Add ISA support + * - Add DMA (yeah, right...). + * - Fix more bugs. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define EISA_MAX_SLOTS 4 +#define EISA_MAX_IRQ 16 + +#define EISA_TO_PHYS(x) (0x00080000 | (x)) +#define EISA_TO_KSEG1(x) ((void *) KSEG1ADDR(EISA_TO_PHYS((x)))) + +#define EIU_MODE_REG 0x0009ffc0 +#define EIU_STAT_REG 0x0009ffc4 +#define EIU_PREMPT_REG 0x0009ffc8 +#define EIU_QUIET_REG 0x0009ffcc +#define EIU_INTRPT_ACK 0x00090004 + +#define EISA_DMA1_STATUS 8 +#define EISA_INT1_CTRL 0x20 +#define EISA_INT1_MASK 0x21 +#define EISA_INT2_CTRL 0xA0 +#define EISA_INT2_MASK 0xA1 +#define EISA_DMA2_STATUS 0xD0 +#define EISA_DMA2_WRITE_SINGLE 0xD4 +#define EISA_EXT_NMI_RESET_CTRL 0x461 +#define EISA_INT1_EDGE_LEVEL 0x4D0 +#define EISA_INT2_EDGE_LEVEL 0x4D1 +#define EISA_VENDOR_ID_OFFSET 0xC80 + +#define EIU_WRITE_32(x,y) { *((u32 *) KSEG1ADDR(x)) = (u32) (y); mb(); } +#define EIU_READ_8(x) *((u8 *) KSEG1ADDR(x)) +#define EISA_WRITE_8(x,y) { *((u8 *) EISA_TO_KSEG1(x)) = (u8) (y); mb(); } +#define EISA_READ_8(x) *((u8 *) EISA_TO_KSEG1(x)) + +static char *decode_eisa_sig(u8 * sig) +{ + static char sig_str[8]; + u16 rev; + + if (sig[0] & 0x80) + return NULL; + + sig_str[0] = ((sig[0] >> 2) & 0x1f) + ('A' - 1); + sig_str[1] = (((sig[0] & 3) << 3) | (sig[1] >> 5)) + ('A' - 1); + sig_str[2] = (sig[1] & 0x1f) + ('A' - 1); + rev = (sig[2] << 8) | sig[3]; + sprintf(sig_str + 3, "%04X", rev); + + return sig_str; +} + +static void ip22_eisa_intr(int irq, void *dev_id, struct pt_regs *regs) +{ + u8 eisa_irq; + u8 dma1, dma2; + + eisa_irq = EIU_READ_8(EIU_INTRPT_ACK); + dma1 = EISA_READ_8(EISA_DMA1_STATUS); + dma2 = EISA_READ_8(EISA_DMA2_STATUS); + + if (eisa_irq >= EISA_MAX_IRQ) { + /* Oops, Bad Stuff Happened... */ + printk(KERN_ERR "eisa_irq %d out of bound\n", eisa_irq); + + EISA_WRITE_8(EISA_INT2_CTRL, 0x20); + EISA_WRITE_8(EISA_INT1_CTRL, 0x20); + } else + do_IRQ(eisa_irq, regs); +} + +static void enable_eisa1_irq(unsigned int irq) +{ + unsigned long flags; + u8 mask; + + local_irq_save(flags); + + mask = EISA_READ_8(EISA_INT1_MASK); + mask &= ~((u8) (1 << irq)); + EISA_WRITE_8(EISA_INT1_MASK, mask); + + local_irq_restore(flags); +} + +static unsigned int startup_eisa1_irq(unsigned int irq) +{ + u8 edge; + + /* Only use edge interrupts for EISA */ + + edge = EISA_READ_8(EISA_INT1_EDGE_LEVEL); + edge &= ~((u8) (1 << irq)); + EISA_WRITE_8(EISA_INT1_EDGE_LEVEL, edge); + + enable_eisa1_irq(irq); + return 0; +} + +static void disable_eisa1_irq(unsigned int irq) +{ + u8 mask; + + mask = EISA_READ_8(EISA_INT1_MASK); + mask |= ((u8) (1 << irq)); + EISA_WRITE_8(EISA_INT1_MASK, mask); +} + +#define shutdown_eisa1_irq disable_eisa1_irq + +static void mask_and_ack_eisa1_irq(unsigned int irq) +{ + disable_eisa1_irq(irq); + + EISA_WRITE_8(EISA_INT1_CTRL, 0x20); +} + +static void end_eisa1_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + enable_eisa1_irq(irq); +} + +static struct hw_interrupt_type ip22_eisa1_irq_type = { + .typename = "IP22 EISA", + .startup = startup_eisa1_irq, + .shutdown = shutdown_eisa1_irq, + .enable = enable_eisa1_irq, + .disable = disable_eisa1_irq, + .ack = mask_and_ack_eisa1_irq, + .end = end_eisa1_irq, +}; + +static void enable_eisa2_irq(unsigned int irq) +{ + unsigned long flags; + u8 mask; + + local_irq_save(flags); + + mask = EISA_READ_8(EISA_INT2_MASK); + mask &= ~((u8) (1 << (irq - 8))); + EISA_WRITE_8(EISA_INT2_MASK, mask); + + local_irq_restore(flags); +} + +static unsigned int startup_eisa2_irq(unsigned int irq) +{ + u8 edge; + + /* Only use edge interrupts for EISA */ + + edge = EISA_READ_8(EISA_INT2_EDGE_LEVEL); + edge &= ~((u8) (1 << (irq - 8))); + EISA_WRITE_8(EISA_INT2_EDGE_LEVEL, edge); + + enable_eisa2_irq(irq); + return 0; +} + +static void disable_eisa2_irq(unsigned int irq) +{ + u8 mask; + + mask = EISA_READ_8(EISA_INT2_MASK); + mask |= ((u8) (1 << (irq - 8))); + EISA_WRITE_8(EISA_INT2_MASK, mask); +} + +#define shutdown_eisa2_irq disable_eisa2_irq + +static void mask_and_ack_eisa2_irq(unsigned int irq) +{ + disable_eisa2_irq(irq); + + EISA_WRITE_8(EISA_INT2_CTRL, 0x20); + EISA_WRITE_8(EISA_INT1_CTRL, 0x20); +} + +static void end_eisa2_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + enable_eisa2_irq(irq); +} + +static struct hw_interrupt_type ip22_eisa2_irq_type = { + .typename = "IP22 EISA", + .startup = startup_eisa2_irq, + .shutdown = shutdown_eisa2_irq, + .enable = enable_eisa2_irq, + .disable = disable_eisa2_irq, + .ack = mask_and_ack_eisa2_irq, + .end = end_eisa2_irq, +}; + +static struct irqaction eisa_action = { + .handler = ip22_eisa_intr, + .name = "EISA", +}; + +static struct irqaction cascade_action = { + .handler = no_action, + .name = "EISA cascade", +}; + +int __init ip22_eisa_init(void) +{ + int i, c; + char *str; + u8 *slot_addr; + + if (!(sgimc->systemid & SGIMC_SYSID_EPRESENT)) { + printk(KERN_INFO "EISA: bus not present.\n"); + return 1; + } + + printk(KERN_INFO "EISA: Probing bus...\n"); + for (c = 0, i = 1; i <= EISA_MAX_SLOTS; i++) { + slot_addr = + (u8 *) EISA_TO_KSEG1((0x1000 * i) + + EISA_VENDOR_ID_OFFSET); + if ((str = decode_eisa_sig(slot_addr))) { + printk(KERN_INFO "EISA: slot %d : %s detected.\n", + i, str); + c++; + } + } + printk(KERN_INFO "EISA: Detected %d card%s.\n", c, c < 2 ? "" : "s"); +#ifdef CONFIG_ISA + printk(KERN_INFO "ISA support compiled in.\n"); +#endif + + /* Warning : BlackMagicAhead(tm). + Please wave your favorite dead chicken over the busses */ + + /* First say hello to the EIU */ + EIU_WRITE_32(EIU_PREMPT_REG, 0x0000FFFF); + EIU_WRITE_32(EIU_QUIET_REG, 1); + EIU_WRITE_32(EIU_MODE_REG, 0x40f3c07F); + + /* Now be nice to the EISA chipset */ + EISA_WRITE_8(EISA_EXT_NMI_RESET_CTRL, 1); + for (i = 0; i < 10000; i++); /* Wait long enough for the dust to settle */ + EISA_WRITE_8(EISA_EXT_NMI_RESET_CTRL, 0); + EISA_WRITE_8(EISA_INT1_CTRL, 0x11); + EISA_WRITE_8(EISA_INT2_CTRL, 0x11); + EISA_WRITE_8(EISA_INT1_MASK, 0); + EISA_WRITE_8(EISA_INT2_MASK, 8); + EISA_WRITE_8(EISA_INT1_MASK, 4); + EISA_WRITE_8(EISA_INT2_MASK, 2); + EISA_WRITE_8(EISA_INT1_MASK, 1); + EISA_WRITE_8(EISA_INT2_MASK, 1); + EISA_WRITE_8(EISA_INT1_MASK, 0xfb); + EISA_WRITE_8(EISA_INT2_MASK, 0xff); + EISA_WRITE_8(EISA_DMA2_WRITE_SINGLE, 0); + + for (i = SGINT_EISA; i < (SGINT_EISA + EISA_MAX_IRQ); i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = 1; + if (i < (SGINT_EISA + 8)) + irq_desc[i].handler = &ip22_eisa1_irq_type; + else + irq_desc[i].handler = &ip22_eisa2_irq_type; + } + + /* Cannot use request_irq because of kmalloc not being ready at such + * an early stage. Yes, I've been bitten... */ + setup_irq(SGI_EISA_IRQ, &eisa_action); + setup_irq(SGINT_EISA + 2, &cascade_action); + + EISA_bus = 1; + return 0; +} diff -Nru a/arch/mips/sgi-ip22/ip22-hpc.c b/arch/mips/sgi-ip22/ip22-hpc.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sgi-ip22/ip22-hpc.c Tue Jul 1 18:44:39 2003 @@ -0,0 +1,53 @@ +/* + * ip22-hpc.c: Routines for generic manipulation of the HPC controllers. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * Copyright (C) 1998 Ralf Baechle + */ + +#include +#include + +#include +#include +#include +#include + +struct hpc3_regs *hpc3c0, *hpc3c1; +struct sgioc_regs *sgioc; + +/* We need software copies of these because they are write only. */ +u8 sgi_ioc_reset, sgi_ioc_write; + +extern char *system_type; + +void __init sgihpc_init(void) +{ + hpc3c0 = (struct hpc3_regs *)(KSEG1 + HPC3_CHIP0_BASE); + hpc3c1 = (struct hpc3_regs *)(KSEG1 + HPC3_CHIP1_BASE); + /* IOC lives in PBUS PIO channel 6 */ + sgioc = (struct sgioc_regs *)hpc3c0->pbus_extregs[6]; + + hpc3c0->pbus_piocfg[6][0] |= HPC3_PIOCFG_DS16; + if (ip22_is_fullhouse()) { + /* Full House comes with INT2 which lives in PBUS PIO + * channel 4 */ + sgint = (struct sgint_regs *)hpc3c0->pbus_extregs[4]; + system_type = "SGI Indigo2"; + } else { + /* Guiness comes with INT3 which is part of IOC */ + sgint = &sgioc->int3; + system_type = "SGI Indy"; + } + + sgi_ioc_reset = (SGIOC_RESET_PPORT | SGIOC_RESET_KBDMOUSE | + SGIOC_RESET_EISA | SGIOC_RESET_ISDN | + SGIOC_RESET_LC0OFF); + + sgi_ioc_write = (SGIOC_WRITE_EASEL | SGIOC_WRITE_NTHRESH | + SGIOC_WRITE_TPSPEED | SGIOC_WRITE_EPSEL | + SGIOC_WRITE_U0AMODE | SGIOC_WRITE_U1AMODE); + + sgioc->reset = sgi_ioc_reset; + sgioc->write = sgi_ioc_write; +} diff -Nru a/arch/mips/sgi-ip22/ip22-int.c b/arch/mips/sgi-ip22/ip22-int.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sgi-ip22/ip22-int.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,412 @@ +/* + * ip22-int.c: Routines for generic manipulation of the INT[23] ASIC + * found on INDY and Indigo2 workstations. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * Copyright (C) 1997, 1998 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu) + * - Indigo2 changes + * - Interrupt handling fixes + * Copyright (C) 2001, 2003 Ladislav Michl (ladis@linux-mips.org) + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +/* #define DEBUG_SGINT */ + +/* So far nothing hangs here */ +#undef USE_LIO3_IRQ + +struct sgint_regs *sgint; + +static char lc0msk_to_irqnr[256]; +static char lc1msk_to_irqnr[256]; +static char lc2msk_to_irqnr[256]; +static char lc3msk_to_irqnr[256]; + +extern asmlinkage void indyIRQ(void); +extern int ip22_eisa_init(void); + +static void enable_local0_irq(unsigned int irq) +{ + unsigned long flags; + + local_irq_save(flags); + /* don't allow mappable interrupt to be enabled from setup_irq, + * we have our own way to do so */ + if (irq != SGI_MAP_0_IRQ) + sgint->imask0 |= (1 << (irq - SGINT_LOCAL0)); + local_irq_restore(flags); +} + +static unsigned int startup_local0_irq(unsigned int irq) +{ + enable_local0_irq(irq); + return 0; /* Never anything pending */ +} + +static void disable_local0_irq(unsigned int irq) +{ + unsigned long flags; + + local_irq_save(flags); + sgint->imask0 &= ~(1 << (irq - SGINT_LOCAL0)); + local_irq_restore(flags); +} + +#define shutdown_local0_irq disable_local0_irq +#define mask_and_ack_local0_irq disable_local0_irq + +static void end_local0_irq (unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_local0_irq(irq); +} + +static struct hw_interrupt_type ip22_local0_irq_type = { + .typename = "IP22 local 0", + .startup = startup_local0_irq, + .shutdown = shutdown_local0_irq, + .enable = enable_local0_irq, + .disable = disable_local0_irq, + .ack = mask_and_ack_local0_irq, + .end = end_local0_irq, +}; + +static void enable_local1_irq(unsigned int irq) +{ + unsigned long flags; + + local_irq_save(flags); + /* don't allow mappable interrupt to be enabled from setup_irq, + * we have our own way to do so */ + if (irq != SGI_MAP_1_IRQ) + sgint->imask1 |= (1 << (irq - SGINT_LOCAL1)); + local_irq_restore(flags); +} + +static unsigned int startup_local1_irq(unsigned int irq) +{ + enable_local1_irq(irq); + return 0; /* Never anything pending */ +} + +void disable_local1_irq(unsigned int irq) +{ + unsigned long flags; + + local_irq_save(flags); + sgint->imask1 &= ~(1 << (irq - SGINT_LOCAL1)); + local_irq_restore(flags); +} + +#define shutdown_local1_irq disable_local1_irq +#define mask_and_ack_local1_irq disable_local1_irq + +static void end_local1_irq (unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_local1_irq(irq); +} + +static struct hw_interrupt_type ip22_local1_irq_type = { + .typename = "IP22 local 1", + .startup = startup_local1_irq, + .shutdown = shutdown_local1_irq, + .enable = enable_local1_irq, + .disable = disable_local1_irq, + .ack = mask_and_ack_local1_irq, + .end = end_local1_irq, +}; + +static void enable_local2_irq(unsigned int irq) +{ + unsigned long flags; + + local_irq_save(flags); + sgint->imask0 |= (1 << (SGI_MAP_0_IRQ - SGINT_LOCAL0)); + sgint->cmeimask0 |= (1 << (irq - SGINT_LOCAL2)); + local_irq_restore(flags); +} + +static unsigned int startup_local2_irq(unsigned int irq) +{ + enable_local2_irq(irq); + return 0; /* Never anything pending */ +} + +void disable_local2_irq(unsigned int irq) +{ + unsigned long flags; + + local_irq_save(flags); + sgint->cmeimask0 &= ~(1 << (irq - SGINT_LOCAL2)); + if (!sgint->cmeimask0) + sgint->imask0 &= ~(1 << (SGI_MAP_0_IRQ - SGINT_LOCAL0)); + local_irq_restore(flags); +} + +#define shutdown_local2_irq disable_local2_irq +#define mask_and_ack_local2_irq disable_local2_irq + +static void end_local2_irq (unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_local2_irq(irq); +} + +static struct hw_interrupt_type ip22_local2_irq_type = { + .typename = "IP22 local 2", + .startup = startup_local2_irq, + .shutdown = shutdown_local2_irq, + .enable = enable_local2_irq, + .disable = disable_local2_irq, + .ack = mask_and_ack_local2_irq, + .end = end_local2_irq, +}; + +static void enable_local3_irq(unsigned int irq) +{ + unsigned long flags; + + local_irq_save(flags); + sgint->imask1 |= (1 << (SGI_MAP_1_IRQ - SGINT_LOCAL1)); + sgint->cmeimask1 |= (1 << (irq - SGINT_LOCAL3)); + local_irq_restore(flags); +} + +static unsigned int startup_local3_irq(unsigned int irq) +{ + enable_local3_irq(irq); + return 0; /* Never anything pending */ +} + +void disable_local3_irq(unsigned int irq) +{ + unsigned long flags; + + local_irq_save(flags); + sgint->cmeimask1 &= ~(1 << (irq - SGINT_LOCAL3)); + if (!sgint->cmeimask1) + sgint->imask1 &= ~(1 << (SGI_MAP_1_IRQ - SGINT_LOCAL1)); + local_irq_restore(flags); +} + +#define shutdown_local3_irq disable_local3_irq +#define mask_and_ack_local3_irq disable_local3_irq + +static void end_local3_irq (unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_local3_irq(irq); +} + +static struct hw_interrupt_type ip22_local3_irq_type = { + .typename = "IP22 local 3", + .startup = startup_local3_irq, + .shutdown = shutdown_local3_irq, + .enable = enable_local3_irq, + .disable = disable_local3_irq, + .ack = mask_and_ack_local3_irq, + .end = end_local3_irq, +}; + +void indy_local0_irqdispatch(struct pt_regs *regs) +{ + u8 mask = sgint->istat0 & sgint->imask0; + u8 mask2; + int irq; + + if (mask & SGINT_ISTAT0_LIO2) { + mask2 = sgint->vmeistat & sgint->cmeimask0; + irq = lc2msk_to_irqnr[mask2]; + } else + irq = lc0msk_to_irqnr[mask]; + + /* if irq == 0, then the interrupt has already been cleared */ + if (irq) + do_IRQ(irq, regs); + return; +} + +void indy_local1_irqdispatch(struct pt_regs *regs) +{ + u8 mask = sgint->istat1 & sgint->imask1; + u8 mask2; + int irq; + + if (mask & SGINT_ISTAT1_LIO3) { + mask2 = sgint->vmeistat & sgint->cmeimask1; + irq = lc3msk_to_irqnr[mask2]; + } else + irq = lc1msk_to_irqnr[mask]; + + /* if irq == 0, then the interrupt has already been cleared */ + if (irq) + do_IRQ(irq, regs); + return; +} + +extern void ip22_be_interrupt(int irq, struct pt_regs *regs); + +void indy_buserror_irq(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + int irq = SGI_BUSERR_IRQ; + + irq_enter(); + kstat_cpu(cpu).irqs[irq]++; + ip22_be_interrupt(irq, regs); + irq_exit(); +} + +static struct irqaction local0_cascade = { + .handler = no_action, + .flags = SA_INTERRUPT, + .name = "local0 cascade", +}; + +static struct irqaction local1_cascade = { + .handler = no_action, + .flags = SA_INTERRUPT, + .name = "local1 cascade", +}; + +static struct irqaction buserr = { + .handler = no_action, + .flags = SA_INTERRUPT, + .name = "Bus Error", +}; + +static struct irqaction map0_cascade = { + .handler = no_action, + .flags = SA_INTERRUPT, + .name = "mapable0 cascade", +}; + +#ifdef USE_LIO3_IRQ +static struct irqaction map1_cascade = { + .handler = no_action, + .flags = SA_INTERRUPT, + .name = "mapable1 cascade", +}; +#define SGI_INTERRUPTS SGINT_END +#else +#define SGI_INTERRUPTS SGINT_LOCAL3 +#endif + +extern void mips_cpu_irq_init(unsigned int irq_base); + +void __init init_IRQ(void) +{ + int i; + + /* Init local mask --> irq tables. */ + for (i = 0; i < 256; i++) { + if (i & 0x80) { + lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 7; + lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 7; + lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 7; + lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 7; + } else if (i & 0x40) { + lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 6; + lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 6; + lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 6; + lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 6; + } else if (i & 0x20) { + lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 5; + lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 5; + lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 5; + lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 5; + } else if (i & 0x10) { + lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 4; + lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 4; + lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 4; + lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 4; + } else if (i & 0x08) { + lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 3; + lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 3; + lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 3; + lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 3; + } else if (i & 0x04) { + lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 2; + lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 2; + lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 2; + lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 2; + } else if (i & 0x02) { + lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 1; + lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 1; + lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 1; + lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 1; + } else if (i & 0x01) { + lc0msk_to_irqnr[i] = SGINT_LOCAL0 + 0; + lc1msk_to_irqnr[i] = SGINT_LOCAL1 + 0; + lc2msk_to_irqnr[i] = SGINT_LOCAL2 + 0; + lc3msk_to_irqnr[i] = SGINT_LOCAL3 + 0; + } else { + lc0msk_to_irqnr[i] = 0; + lc1msk_to_irqnr[i] = 0; + lc2msk_to_irqnr[i] = 0; + lc3msk_to_irqnr[i] = 0; + } + } + + /* Mask out all interrupts. */ + sgint->imask0 = 0; + sgint->imask1 = 0; + sgint->cmeimask0 = 0; + sgint->cmeimask1 = 0; + + set_except_vector(0, indyIRQ); + + init_generic_irq(); + /* init CPU irqs */ + mips_cpu_irq_init(SGINT_CPU); + + for (i = SGINT_LOCAL0; i < SGI_INTERRUPTS; i++) { + hw_irq_controller *handler; + + if (i < SGINT_LOCAL1) + handler = &ip22_local0_irq_type; + else if (i < SGINT_LOCAL2) + handler = &ip22_local1_irq_type; + else if (i < SGINT_LOCAL3) + handler = &ip22_local2_irq_type; + else + handler = &ip22_local3_irq_type; + + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = 1; + irq_desc[i].handler = handler; + } + + /* vector handler. this register the IRQ as non-sharable */ + setup_irq(SGI_LOCAL_0_IRQ, &local0_cascade); + setup_irq(SGI_LOCAL_1_IRQ, &local1_cascade); + setup_irq(SGI_BUSERR_IRQ, &buserr); + + /* cascade in cascade. i love Indy ;-) */ + setup_irq(SGI_MAP_0_IRQ, &map0_cascade); +#ifdef USE_LIO3_IRQ + setup_irq(SGI_MAP_1_IRQ, &map1_cascade); +#endif + +#ifdef CONFIG_EISA + if (ip22_is_fullhouse()) /* Only Indigo-2 has EISA stuff */ + ip22_eisa_init (); +#endif +} diff -Nru a/arch/mips/sgi-ip22/ip22-irq.S b/arch/mips/sgi-ip22/ip22-irq.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sgi-ip22/ip22-irq.S Tue Jul 1 18:44:40 2003 @@ -0,0 +1,118 @@ +/* + * ip22-irq.S: Interrupt exception dispatch code for FullHouse and + * Guiness. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + */ + +#include +#include +#include +#include + +/* A lot of complication here is taken away because: + * + * 1) We handle one interrupt and return, sitting in a loop and moving across + * all the pending IRQ bits in the cause register is _NOT_ the answer, the + * common case is one pending IRQ so optimize in that direction. + * + * 2) We need not check against bits in the status register IRQ mask, that + * would make this routine slow as hell. + * + * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in + * between like BSD spl() brain-damage. + * + * Furthermore, the IRQs on the INDY look basically (barring software IRQs + * which we don't use at all) like: + * + * MIPS IRQ Source + * -------- ------ + * 0 Software (ignored) + * 1 Software (ignored) + * 2 Local IRQ level zero + * 3 Local IRQ level one + * 4 8254 Timer zero + * 5 8254 Timer one + * 6 Bus Error + * 7 R4k timer (what we use) + * + * We handle the IRQ according to _our_ priority which is: + * + * Highest ---- R4k Timer + * Local IRQ zero + * Local IRQ one + * Bus Error + * 8254 Timer zero + * Lowest ---- 8254 Timer one + * + * then we just return, if multiple IRQs are pending then we will just take + * another exception, big deal. + */ + + .text + .set noreorder + .set noat + .align 5 + NESTED(indyIRQ, PT_SIZE, sp) + SAVE_ALL + CLI + .set at + mfc0 s0, CP0_CAUSE # get irq mask + + /* First we check for r4k counter/timer IRQ. */ + andi a0, s0, CAUSEF_IP7 + beq a0, zero, 1f + andi a0, s0, CAUSEF_IP2 # delay slot, check local level zero + + /* Wheee, a timer interrupt. */ + jal indy_r4k_timer_interrupt + move a0, sp # delay slot + j ret_from_irq + nop # delay slot + +1: + beq a0, zero, 1f + andi a0, s0, CAUSEF_IP3 # delay slot, check local level one + + /* Wheee, local level zero interrupt. */ + jal indy_local0_irqdispatch + move a0, sp # delay slot + + j ret_from_irq + nop # delay slot + +1: + beq a0, zero, 1f + andi a0, s0, CAUSEF_IP6 # delay slot, check bus error + + /* Wheee, local level one interrupt. */ + jal indy_local1_irqdispatch + move a0, sp # delay slot + j ret_from_irq + nop # delay slot + +1: + beq a0, zero, 1f + andi a0, s0, (CAUSEF_IP4 | CAUSEF_IP5) # delay slot + + /* Wheee, an asynchronous bus error... */ + jal indy_buserror_irq + move a0, sp # delay slot + j ret_from_irq + nop # delay slot + +1: + /* Here by mistake? It is possible, that by the time we take + * the exception the IRQ pin goes low, so just leave if this + * is the case. + */ + beq a0, zero, 1f + nop # delay slot + + /* Must be one of the 8254 timers... */ + jal indy_8254timer_irq + move a0, sp # delay slot +1: + j ret_from_irq + nop # delay slot + END(indyIRQ) diff -Nru a/arch/mips/sgi-ip22/ip22-ksyms.c b/arch/mips/sgi-ip22/ip22-ksyms.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sgi-ip22/ip22-ksyms.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,21 @@ +/* + * ip22-ksyms.c: IP22 specific exports + */ + +#include + +#include +#include +#include +#include + +EXPORT_SYMBOL(sgimc); +EXPORT_SYMBOL(hpc3c0); +EXPORT_SYMBOL(hpc3c1); +EXPORT_SYMBOL(sgioc); + +extern void (*indy_volume_button)(int); +EXPORT_SYMBOL(indy_volume_button); + +EXPORT_SYMBOL(ip22_eeprom_read); +EXPORT_SYMBOL(ip22_nvram_read); diff -Nru a/arch/mips/sgi-ip22/ip22-mc.c b/arch/mips/sgi-ip22/ip22-mc.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sgi-ip22/ip22-mc.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,201 @@ +/* + * ip22-mc.c: Routines for manipulating SGI Memory Controller. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu) - Indigo2 changes + * Copyright (C) 2003 Ladislav Michl (ladis@linux-mips.org) + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +struct sgimc_regs *sgimc; + +static inline unsigned long get_bank_addr(unsigned int memconfig) +{ + return ((memconfig & SGIMC_MCONFIG_BASEADDR) << + ((sgimc->systemid & SGIMC_SYSID_MASKREV) >= 5 ? 24 : 22)); +} + +static inline unsigned long get_bank_size(unsigned int memconfig) +{ + return ((memconfig & SGIMC_MCONFIG_RMASK) + 0x0100) << + ((sgimc->systemid & SGIMC_SYSID_MASKREV) >= 5 ? 16 : 14); +} + +static inline unsigned int get_bank_config(int bank) +{ + unsigned int res = bank > 1 ? sgimc->mconfig1 : sgimc->mconfig0; + return bank % 2 ? res & 0xffff : res >> 16; +} + +struct mem { + unsigned long addr; + unsigned long size; +}; + +/* + * Detect installed memory, do some sanity checks and notify kernel about it + */ +static void probe_memory(void) +{ + int i, j, found, cnt = 0; + struct mem bank[4]; + struct mem space[2] = {{SGIMC_SEG0_BADDR, 0}, {SGIMC_SEG1_BADDR, 0}}; + + printk(KERN_INFO "MC: Probing memory configuration:\n"); + for (i = 0; i < ARRAY_SIZE(bank); i++) { + unsigned int tmp = get_bank_config(i); + if (!(tmp & SGIMC_MCONFIG_BVALID)) + continue; + + bank[cnt].size = get_bank_size(tmp); + bank[cnt].addr = get_bank_addr(tmp); + printk(KERN_INFO " bank%d: %3ldM @ %08lx\n", + i, bank[cnt].size / 1024 / 1024, bank[cnt].addr); + cnt++; + } + + /* And you thought bubble sort is dead algorithm... */ + do { + unsigned long addr, size; + + found = 0; + for (i = 1; i < cnt; i++) + if (bank[i-1].addr > bank[i].addr) { + addr = bank[i].addr; + size = bank[i].size; + bank[i].addr = bank[i-1].addr; + bank[i].size = bank[i-1].size; + bank[i-1].addr = addr; + bank[i-1].size = size; + found = 1; + } + } while (found); + + /* Figure out how are memory banks mapped into spaces */ + for (i = 0; i < cnt; i++) { + found = 0; + for (j = 0; j < ARRAY_SIZE(space) && !found; j++) + if (space[j].addr + space[j].size == bank[i].addr) { + space[j].size += bank[i].size; + found = 1; + } + /* There is either hole or overlapping memory */ + if (!found) + printk(KERN_CRIT "MC: Memory configuration mismatch " + "(%08lx), expect Bus Error soon\n", + bank[i].addr); + } + + for (i = 0; i < ARRAY_SIZE(space); i++) + if (space[i].size) + add_memory_region(space[i].addr, space[i].size, + BOOT_MEM_RAM); +} + +void __init sgimc_init(void) +{ + u32 tmp; + + sgimc = (struct sgimc_regs *)(KSEG1 + SGIMC_BASE); + + printk(KERN_INFO "MC: SGI memory controller Revision %d\n", + (int) sgimc->systemid & SGIMC_SYSID_MASKREV); + + /* Place the MC into a known state. This must be done before + * interrupts are first enabled etc. + */ + + /* Step 0: Make sure we turn off the watchdog in case it's + * still running (which might be the case after a + * soft reboot). + */ + tmp = sgimc->cpuctrl0; + tmp &= ~SGIMC_CCTRL0_WDOG; + sgimc->cpuctrl0 = tmp; + + /* Step 1: The CPU/GIO error status registers will not latch + * up a new error status until the register has been + * cleared by the cpu. These status registers are + * cleared by writing any value to them. + */ + sgimc->cstat = sgimc->gstat = 0; + + /* Step 2: Enable all parity checking in cpu control register + * zero. + */ + tmp = sgimc->cpuctrl0; + tmp |= (SGIMC_CCTRL0_EPERRGIO | SGIMC_CCTRL0_EPERRMEM | + SGIMC_CCTRL0_R4KNOCHKPARR); + sgimc->cpuctrl0 = tmp; + + /* Step 3: Setup the MC write buffer depth, this is controlled + * in cpu control register 1 in the lower 4 bits. + */ + tmp = sgimc->cpuctrl1; + tmp &= ~0xf; + tmp |= 0xd; + sgimc->cpuctrl1 = tmp; + + /* Step 4: Initialize the RPSS divider register to run as fast + * as it can correctly operate. The register is laid + * out as follows: + * + * ---------------------------------------- + * | RESERVED | INCREMENT | DIVIDER | + * ---------------------------------------- + * 31 16 15 8 7 0 + * + * DIVIDER determines how often a 'tick' happens, + * INCREMENT determines by how the RPSS increment + * registers value increases at each 'tick'. Thus, + * for IP22 we get INCREMENT=1, DIVIDER=1 == 0x101 + */ + sgimc->divider = 0x101; + + /* Step 5: Initialize GIO64 arbitrator configuration register. + * + * NOTE: HPC init code in sgihpc_init() must run before us because + * we need to know Guiness vs. FullHouse and the board + * revision on this machine. You have been warned. + */ + + /* First the basic invariants across all GIO64 implementations. */ + tmp = SGIMC_GIOPAR_HPC64; /* All 1st HPC's interface at 64bits */ + tmp |= SGIMC_GIOPAR_ONEBUS; /* Only one physical GIO bus exists */ + + if (ip22_is_fullhouse()) { + /* Fullhouse specific settings. */ + if (SGIOC_SYSID_BOARDREV(sgioc->sysid) < 2) { + tmp |= SGIMC_GIOPAR_HPC264; /* 2nd HPC at 64bits */ + tmp |= SGIMC_GIOPAR_PLINEEXP0; /* exp0 pipelines */ + tmp |= SGIMC_GIOPAR_MASTEREXP1; /* exp1 masters */ + tmp |= SGIMC_GIOPAR_RTIMEEXP0; /* exp0 is realtime */ + } else { + tmp |= SGIMC_GIOPAR_HPC264; /* 2nd HPC 64bits */ + tmp |= SGIMC_GIOPAR_PLINEEXP0; /* exp[01] pipelined */ + tmp |= SGIMC_GIOPAR_PLINEEXP1; + tmp |= SGIMC_GIOPAR_MASTEREISA; /* EISA masters */ + tmp |= SGIMC_GIOPAR_GFX64; /* GFX at 64 bits */ + } + } else { + /* Guiness specific settings. */ + tmp |= SGIMC_GIOPAR_EISA64; /* MC talks to EISA at 64bits */ + tmp |= SGIMC_GIOPAR_MASTEREISA; /* EISA bus can act as master */ + } + sgimc->giopar = tmp; /* poof */ + + probe_memory(); +} + +void __init prom_meminit(void) {} +void __init prom_free_prom_memory (void) {} diff -Nru a/arch/mips/sgi-ip22/ip22-nvram.c b/arch/mips/sgi-ip22/ip22-nvram.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sgi-ip22/ip22-nvram.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,114 @@ +/* + * ip22-nvram.c: NVRAM and serial EEPROM handling. + * + * Copyright (C) 2003 Ladislav Michl (ladis@linux-mips.org) + */ + +#include +#include + +/* Control opcode for serial eeprom */ +#define EEPROM_READ 0xc000 /* serial memory read */ +#define EEPROM_WEN 0x9800 /* write enable before prog modes */ +#define EEPROM_WRITE 0xa000 /* serial memory write */ +#define EEPROM_WRALL 0x8800 /* write all registers */ +#define EEPROM_WDS 0x8000 /* disable all programming */ +#define EEPROM_PRREAD 0xc000 /* read protect register */ +#define EEPROM_PREN 0x9800 /* enable protect register mode */ +#define EEPROM_PRCLEAR 0xffff /* clear protect register */ +#define EEPROM_PRWRITE 0xa000 /* write protect register */ +#define EEPROM_PRDS 0x8000 /* disable protect register, forever */ + +#define EEPROM_EPROT 0x01 /* Protect register enable */ +#define EEPROM_CSEL 0x02 /* Chip select */ +#define EEPROM_ECLK 0x04 /* EEPROM clock */ +#define EEPROM_DATO 0x08 /* Data out */ +#define EEPROM_DATI 0x10 /* Data in */ + +/* We need to use this functions early... */ +#define delay() ({ \ + int x; \ + for (x=0; x<100000; x++) __asm__ __volatile__(""); }) + +#define eeprom_cs_on(ptr) ({ \ + *ptr &= ~EEPROM_DATO; \ + *ptr &= ~EEPROM_ECLK; \ + *ptr &= ~EEPROM_EPROT; \ + delay(); \ + *ptr |= EEPROM_CSEL; \ + *ptr |= EEPROM_ECLK; }) + + +#define eeprom_cs_off(ptr) ({ \ + *ptr &= ~EEPROM_ECLK; \ + *ptr &= ~EEPROM_CSEL; \ + *ptr |= EEPROM_EPROT; \ + *ptr |= EEPROM_ECLK; }) + +#define BITS_IN_COMMAND 11 +/* + * clock in the nvram command and the register number. For the + * national semiconductor nv ram chip the op code is 3 bits and + * the address is 6/8 bits. + */ +static inline void eeprom_cmd(volatile unsigned int *ctrl, unsigned cmd, + unsigned reg) +{ + unsigned short ser_cmd; + int i; + + ser_cmd = cmd | (reg << (16 - BITS_IN_COMMAND)); + for (i = 0; i < BITS_IN_COMMAND; i++) { + if (ser_cmd & (1<<15)) /* if high order bit set */ + *ctrl |= EEPROM_DATO; + else + *ctrl &= ~EEPROM_DATO; + *ctrl &= ~EEPROM_ECLK; + *ctrl |= EEPROM_ECLK; + ser_cmd <<= 1; + } + *ctrl &= ~EEPROM_DATO; /* see data sheet timing diagram */ +} + +unsigned short ip22_eeprom_read(volatile unsigned int *ctrl, int reg) +{ + unsigned short res = 0; + int i; + + *ctrl &= ~EEPROM_EPROT; + eeprom_cs_on(ctrl); + eeprom_cmd(ctrl, EEPROM_READ, reg); + + /* clock the data ouf of serial mem */ + for (i = 0; i < 16; i++) { + *ctrl &= ~EEPROM_ECLK; + delay(); + *ctrl |= EEPROM_ECLK; + delay(); + res <<= 1; + if (*ctrl & EEPROM_DATI) + res |= 1; + } + + eeprom_cs_off(ctrl); + + return res; +} + +/* + * Read specified register from main NVRAM + */ +unsigned short ip22_nvram_read(int reg) +{ + if (ip22_is_fullhouse()) + /* IP22 (Indigo2 aka FullHouse) stores env variables into + * 93CS56 Microwire Bus EEPROM 2048 Bit (128x16) */ + return ip22_eeprom_read(&hpc3c0->eeprom, reg); + else { + unsigned short tmp; + /* IP24 (Indy aka Guiness) uses DS1386 8K version */ + reg <<= 1; + tmp = hpc3c0->bbram[reg++] & 0xff; + return (tmp << 8) | (hpc3c0->bbram[reg] & 0xff); + } +} diff -Nru a/arch/mips/sgi-ip22/ip22-reset.c b/arch/mips/sgi-ip22/ip22-reset.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sgi-ip22/ip22-reset.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,245 @@ +/* + * 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) 1997, 1998, 2001, 2003 by Ralf Baechle + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Just powerdown if init hasn't done after POWERDOWN_TIMEOUT seconds. + * I'm not sure if this feature is a good idea, for now it's here just to + * make the power button make behave just like under IRIX. + */ +#define POWERDOWN_TIMEOUT 120 + +/* + * Blink frequency during reboot grace period and when paniced. + */ +#define POWERDOWN_FREQ (HZ / 4) +#define PANIC_FREQ (HZ / 8) + +static struct timer_list power_timer, blink_timer, debounce_timer, volume_timer; + +#define MACHINE_PANICED 1 +#define MACHINE_SHUTTING_DOWN 2 +static int machine_state = 0; + +static void sgi_machine_restart(char *command) __attribute__((noreturn)); +static void sgi_machine_halt(void) __attribute__((noreturn)); +static void sgi_machine_power_off(void) __attribute__((noreturn)); + +/* XXX How to pass the reboot command to the firmware??? */ +static void sgi_machine_restart(char *command) +{ + if (machine_state & MACHINE_SHUTTING_DOWN) + sgi_machine_power_off(); + ArcReboot(); +} + +static void sgi_machine_halt(void) +{ + if (machine_state & MACHINE_SHUTTING_DOWN) + sgi_machine_power_off(); + ArcEnterInteractiveMode(); +} + +static void sgi_machine_power_off(void) +{ + unsigned char val; + + local_irq_disable(); + + /* Disable watchdog */ + val = CMOS_READ(RTC_CMD); + CMOS_WRITE(val | RTC_WAM, RTC_CMD); + CMOS_WRITE(0, RTC_WSEC); + CMOS_WRITE(0, RTC_WHSEC); + + while(1) { + sgioc->panel = ~SGIOC_PANEL_POWERON; + /* Good bye cruel world ... */ + + /* If we're still running, we probably got sent an alarm + interrupt. Read the flag to clear it. */ + val = CMOS_READ(RTC_HOURS_ALARM); + } +} + +static void power_timeout(unsigned long data) +{ + sgi_machine_power_off(); +} + +static void blink_timeout(unsigned long data) +{ + /* XXX fix this for fullhouse */ + sgi_ioc_reset ^= (SGIOC_RESET_LC0OFF|SGIOC_RESET_LC1OFF); + sgioc->reset = sgi_ioc_reset; + + mod_timer(&blink_timer, jiffies+data); +} + +static void debounce(unsigned long data) +{ + del_timer(&debounce_timer); + if (sgint->istat1 & SGINT_ISTAT1_PWR) { + /* Interrupt still being sent. */ + debounce_timer.expires = jiffies + 5; /* 0.05s */ + add_timer(&debounce_timer); + + sgioc->panel = SGIOC_PANEL_POWERON | SGIOC_PANEL_POWERINTR | + SGIOC_PANEL_VOLDNINTR | SGIOC_PANEL_VOLDNHOLD | + SGIOC_PANEL_VOLUPINTR | SGIOC_PANEL_VOLUPHOLD; + + return; + } + + if (machine_state & MACHINE_PANICED) + ArcReboot(); + + enable_irq(SGI_PANEL_IRQ); +} + +static inline void power_button(void) +{ + if (machine_state & MACHINE_PANICED) + return; + + if ((machine_state & MACHINE_SHUTTING_DOWN) || kill_proc(1,SIGINT,1)) { + /* No init process or button pressed twice. */ + sgi_machine_power_off(); + } + + machine_state |= MACHINE_SHUTTING_DOWN; + blink_timer.data = POWERDOWN_FREQ; + blink_timeout(POWERDOWN_FREQ); + + init_timer(&power_timer); + power_timer.function = power_timeout; + power_timer.expires = jiffies + POWERDOWN_TIMEOUT * HZ; + add_timer(&power_timer); +} + +void (*indy_volume_button)(int) = NULL; + +static inline void volume_up_button(unsigned long data) +{ + del_timer(&volume_timer); + + if (indy_volume_button) + indy_volume_button(1); + + if (sgint->istat1 & SGINT_ISTAT1_PWR) { + volume_timer.expires = jiffies + 1; + add_timer(&volume_timer); + } +} + +static inline void volume_down_button(unsigned long data) +{ + del_timer(&volume_timer); + + if (indy_volume_button) + indy_volume_button(-1); + + if (sgint->istat1 & SGINT_ISTAT1_PWR) { + volume_timer.expires = jiffies + 1; + add_timer(&volume_timer); + } +} + +static irqreturn_t panel_int(int irq, void *dev_id, struct pt_regs *regs) +{ + unsigned int buttons; + + buttons = sgioc->panel; + sgioc->panel = SGIOC_PANEL_POWERON | SGIOC_PANEL_POWERINTR; + + if (sgint->istat1 & SGINT_ISTAT1_PWR) { + /* Wait until interrupt goes away */ + disable_irq(SGI_PANEL_IRQ); + init_timer(&debounce_timer); + debounce_timer.function = debounce; + debounce_timer.expires = jiffies + 5; + add_timer(&debounce_timer); + } + + /* Power button was pressed + * + * ioc.ps page 22: "The Panel Register is called Power Control by Full + * House. Only lowest 2 bits are used. Guiness uses upper four bits + * for volume control". This is not true, all bits are pulled high + * on fullhouse + */ + if (ip22_is_fullhouse() || !(buttons & SGIOC_PANEL_POWERINTR)) { + power_button(); + return IRQ_HANDLED; + } + /* TODO: mute/unmute */ + /* Volume up button was pressed */ + if (!(buttons & SGIOC_PANEL_VOLUPINTR)) { + init_timer(&volume_timer); + volume_timer.function = volume_up_button; + volume_timer.expires = jiffies + 1; + add_timer(&volume_timer); + } + /* Volume down button was pressed */ + if (!(buttons & SGIOC_PANEL_VOLDNINTR)) { + init_timer(&volume_timer); + volume_timer.function = volume_down_button; + volume_timer.expires = jiffies + 1; + add_timer(&volume_timer); + } + + return IRQ_HANDLED; +} + +static int panic_event(struct notifier_block *this, unsigned long event, + void *ptr) +{ + if (machine_state & MACHINE_PANICED) + return NOTIFY_DONE; + machine_state |= MACHINE_PANICED; + + blink_timer.data = PANIC_FREQ; + blink_timeout(PANIC_FREQ); + + return NOTIFY_DONE; +} + +static struct notifier_block panic_block = { + .notifier_call = panic_event, +}; + +static int __init reboot_setup(void) +{ + _machine_restart = sgi_machine_restart; + _machine_halt = sgi_machine_halt; + _machine_power_off = sgi_machine_power_off; + + request_irq(SGI_PANEL_IRQ, panel_int, 0, "Front Panel", NULL); + init_timer(&blink_timer); + blink_timer.function = blink_timeout; + notifier_chain_register(&panic_notifier_list, &panic_block); + + return 0; +} + +subsys_initcall(reboot_setup); diff -Nru a/arch/mips/sgi-ip22/ip22-rtc.c b/arch/mips/sgi-ip22/ip22-rtc.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sgi-ip22/ip22-rtc.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,32 @@ +/* + * 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. + * + * RTC routines for Indy style attached Dallas chip. + * + * Copyright (C) 1998, 2001 by Ralf Baechle + */ +#include +#include + +static unsigned char ip22_rtc_read_data(unsigned long addr) +{ + return hpc3c0->rtcregs[addr]; +} + +static void ip22_rtc_write_data(unsigned char data, unsigned long addr) +{ + hpc3c0->rtcregs[addr] = data; +} + +static int ip22_rtc_bcd_mode(void) +{ + return 0; +} + +struct rtc_ops ip22_rtc_ops = { + &ip22_rtc_read_data, + &ip22_rtc_write_data, + &ip22_rtc_bcd_mode +}; diff -Nru a/arch/mips/sgi-ip22/ip22-setup.c b/arch/mips/sgi-ip22/ip22-setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sgi-ip22/ip22-setup.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,181 @@ +/* + * ip22-setup.c: SGI specific setup, including init of the feature struct. + * + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * Copyright (C) 1997, 1998 Ralf Baechle (ralf@gnu.org) + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_KGDB +extern void rs_kgdb_hook(int); +extern void breakpoint(void); +static int remote_debug = 0; +#endif + +#if defined(CONFIG_IP22_SERIAL_CONSOLE) || defined(CONFIG_ARC_CONSOLE) +extern void console_setup(char *); +#endif + +extern struct rtc_ops ip22_rtc_ops; + +#define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */ + +unsigned long sgi_gfxaddr; + +/* + * Stop-A is originally a Sun thing that isn't standard on IP22 so to avoid + * accidents it's disabled by default on IP22. + * + * FIXME: provide a mechanism to change the value of stop_a_enabled. + */ +int serial_console; +int stop_a_enabled; + +void ip22_do_break(void) +{ + if (!stop_a_enabled) + return; + + printk("\n"); + ArcEnterInteractiveMode(); +} + +extern void ip22_be_init(void) __init; +extern void ip22_time_init(void) __init; + +void __init ip22_setup(void) +{ + char *ctype; +#ifdef CONFIG_KGDB + char *kgdb_ttyd; +#endif + + board_be_init = ip22_be_init; + ip22_time_init(); + + /* Init the INDY HPC I/O controller. Need to call this before + * fucking with the memory controller because it needs to know the + * boardID and whether this is a Guiness or a FullHouse machine. + */ + sgihpc_init(); + + /* Init INDY memory controller. */ + sgimc_init(); + +#ifdef CONFIG_BOARD_SCACHE + /* Now enable boardcaches, if any. */ + indy_sc_init(); +#endif +#ifdef CONFIG_VT + conswitchp = NULL; +#endif + /* Set the IO space to some sane value */ + set_io_port_base (KSEG1ADDR (0x00080000)); + + /* ARCS console environment variable is set to "g?" for + * graphics console, it is set to "d" for the first serial + * line and "d2" for the second serial line. + */ + ctype = ArcGetEnvironmentVariable("console"); + if (ctype && *ctype == 'd') { +#ifdef CONFIG_IP22_SERIAL_CONSOLE + if (*(ctype + 1) == '2') + console_setup("ttyS1"); + else + console_setup("ttyS0"); +#endif + } +#ifdef CONFIG_ARC_CONSOLE + else if (!ctype || *ctype != 'g') { + /* Use ARC if we don't want serial ('d') or Newport ('g'). */ + prom_flags |= PROM_FLAG_USE_AS_CONSOLE; + console_setup("arc"); + } +#endif + +#ifdef CONFIG_KGDB + kgdb_ttyd = prom_getcmdline(); + if ((kgdb_ttyd = strstr(kgdb_ttyd, "kgdb=ttyd")) != NULL) { + int line; + kgdb_ttyd += strlen("kgdb=ttyd"); + if (*kgdb_ttyd != '1' && *kgdb_ttyd != '2') + printk(KERN_INFO "KGDB: Uknown serial line /dev/ttyd%c" + ", falling back to /dev/ttyd1\n", *kgdb_ttyd); + line = *kgdb_ttyd == '2' ? 0 : 1; + printk(KERN_INFO "KGDB: Using serial line /dev/ttyd%d for " + "session\n", line ? 1 : 2); + rs_kgdb_hook(line); + + printk(KERN_INFO "KGDB: Using serial line /dev/ttyd%d for " + "session, please connect your debugger\n", line ? 1:2); + + remote_debug = 1; + /* Breakpoints and stuff are in sgi_irq_setup() */ + } +#endif + +#ifdef CONFIG_VT +#ifdef CONFIG_SGI_NEWPORT_CONSOLE + if (ctype && *ctype == 'g'){ + unsigned long *gfxinfo; + long (*__vec)(void) = + (void *) *(long *)(long)((PROMBLOCK)->pvector + 0x20); + + gfxinfo = (unsigned long *)__vec(); + sgi_gfxaddr = ((gfxinfo[1] >= 0xa0000000 + && gfxinfo[1] <= 0xc0000000) + ? gfxinfo[1] - 0xa0000000 : 0); + + /* newport addresses? */ + if (sgi_gfxaddr == 0x1f0f0000 || sgi_gfxaddr == 0x1f4f0000) { + conswitchp = &newport_con; + + screen_info = (struct screen_info) { + 0, 0, /* orig-x, orig-y */ + 0, /* unused */ + 0, /* orig_video_page */ + 0, /* orig_video_mode */ + 160, /* orig_video_cols */ + 0, 0, 0, /* unused, ega_bx, unused */ + 64, /* orig_video_lines */ + 0, /* orig_video_isVGA */ + 16 /* orig_video_points */ + }; + } + } +#endif +#ifdef CONFIG_DUMMY_CONSOLE + /* Either if newport console wasn't used or failed to initialize. */ +#ifdef CONFIG_SGI_NEWPORT_CONSOLE + if(conswitchp != &newport_con) +#endif + conswitchp = &dummy_con; +#endif +#endif + rtc_ops = &ip22_rtc_ops; +#ifdef CONFIG_PSMOUSE + aux_device_present = 0xaa; +#endif +} diff -Nru a/arch/mips/sgi-ip22/ip22-time.c b/arch/mips/sgi-ip22/ip22-time.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sgi-ip22/ip22-time.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,219 @@ +/* + * 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. + * + * Time operations for IP22 machines. Original code may come from + * Ralf Baechle or David S. Miller (sorry guys, i'm really not sure) + * + * Copyright (C) 2001 by Ladislav Michl + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * note that mktime uses month from 1 to 12 while to_tm + * uses 0 to 11. + */ +static unsigned long indy_rtc_get_time(void) +{ + unsigned int yrs, mon, day, hrs, min, sec; + unsigned int save_control; + + save_control = hpc3c0->rtcregs[RTC_CMD] & 0xff; + hpc3c0->rtcregs[RTC_CMD] = save_control | RTC_TE; + + sec = BCD2BIN(hpc3c0->rtcregs[RTC_SECONDS] & 0xff); + min = BCD2BIN(hpc3c0->rtcregs[RTC_MINUTES] & 0xff); + hrs = BCD2BIN(hpc3c0->rtcregs[RTC_HOURS] & 0x1f); + day = BCD2BIN(hpc3c0->rtcregs[RTC_DATE] & 0xff); + mon = BCD2BIN(hpc3c0->rtcregs[RTC_MONTH] & 0x1f); + yrs = BCD2BIN(hpc3c0->rtcregs[RTC_YEAR] & 0xff); + + hpc3c0->rtcregs[RTC_CMD] = save_control; + + if (yrs < 45) + yrs += 30; + if ((yrs += 40) < 70) + yrs += 100; + + return mktime(yrs + 1900, mon, day, hrs, min, sec); +} + +static int indy_rtc_set_time(unsigned long tim) +{ + struct rtc_time tm; + unsigned int save_control; + + to_tm(tim, &tm); + + tm.tm_mon += 1; /* tm_mon starts at zero */ + tm.tm_year -= 1940; + if (tm.tm_year >= 100) + tm.tm_year -= 100; + + save_control = hpc3c0->rtcregs[RTC_CMD] & 0xff; + hpc3c0->rtcregs[RTC_CMD] = save_control | RTC_TE; + + hpc3c0->rtcregs[RTC_YEAR] = BIN2BCD(tm.tm_sec); + hpc3c0->rtcregs[RTC_MONTH] = BIN2BCD(tm.tm_mon); + hpc3c0->rtcregs[RTC_DATE] = BIN2BCD(tm.tm_mday); + hpc3c0->rtcregs[RTC_HOURS] = BIN2BCD(tm.tm_hour); + hpc3c0->rtcregs[RTC_MINUTES] = BIN2BCD(tm.tm_min); + hpc3c0->rtcregs[RTC_SECONDS] = BIN2BCD(tm.tm_sec); + hpc3c0->rtcregs[RTC_HUNDREDTH_SECOND] = 0; + + hpc3c0->rtcregs[RTC_CMD] = save_control; + + return 0; +} + +static unsigned long dosample(void) +{ + u32 ct0, ct1; + volatile u8 msb, lsb; + + /* Start the counter. */ + sgint->tcword = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CALL | + SGINT_TCWORD_MRGEN); + sgint->tcnt2 = (SGINT_TCSAMP_COUNTER & 0xff); + sgint->tcnt2 = (SGINT_TCSAMP_COUNTER >> 8); + + /* Get initial counter invariant */ + ct0 = read_c0_count(); + + /* Latch and spin until top byte of counter2 is zero */ + do { + sgint->tcword = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CLAT); + lsb = sgint->tcnt2; + msb = sgint->tcnt2; + ct1 = read_c0_count(); + } while (msb); + + /* Stop the counter. */ + sgint->tcword = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CALL | + SGINT_TCWORD_MSWST); + /* + * Return the difference, this is how far the r4k counter increments + * for every 1/HZ seconds. We round off the nearest 1 MHz of master + * clock (= 1000000 / 100 / 2 = 5000 count). + */ + return ((ct1 - ct0) / 5000) * 5000; +} + +/* + * Here we need to calibrate the cycle counter to at least be close. + */ +static __init void indy_time_init(void) +{ + unsigned long r4k_ticks[3]; + unsigned long r4k_tick; + + /* + * Figure out the r4k offset, the algorithm is very simple + * and works in _all_ cases as long as the 8254 counter + * register itself works ok (as an interrupt driving timer + * it does not because of bug, this is why we are using + * the onchip r4k counter/compare register to serve this + * purpose, but for r4k_offset calculation it will work + * ok for us). There are other very complicated ways + * of performing this calculation but this one works just + * fine so I am not going to futz around. ;-) + */ + printk(KERN_INFO "Calibrating system timer... "); + dosample(); /* Prime cache. */ + dosample(); /* Prime cache. */ + /* Zero is NOT an option. */ + do { + r4k_ticks[0] = dosample(); + } while (!r4k_ticks[0]); + do { + r4k_ticks[1] = dosample(); + } while (!r4k_ticks[1]); + + if (r4k_ticks[0] != r4k_ticks[1]) { + printk("warning: timer counts differ, retrying... "); + r4k_ticks[2] = dosample(); + if (r4k_ticks[2] == r4k_ticks[0] + || r4k_ticks[2] == r4k_ticks[1]) + r4k_tick = r4k_ticks[2]; + else { + printk("disagreement, using average... "); + r4k_tick = (r4k_ticks[0] + r4k_ticks[1] + + r4k_ticks[2]) / 3; + } + } else + r4k_tick = r4k_ticks[0]; + + printk("%d [%d.%02d MHz CPU]\n", (int) r4k_tick, + (int) (r4k_tick / 5000), (int) (r4k_tick % 5000) / 50); + + mips_counter_frequency = r4k_tick * HZ; +} + +/* Generic SGI handler for (spurious) 8254 interrupts */ +void indy_8254timer_irq(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + int irq = SGI_8254_0_IRQ; + ULONG cnt; + char c; + + irq_enter(); + kstat_cpu(cpu).irqs[irq]++; + printk(KERN_ALERT "Oops, got 8254 interrupt.\n"); + ArcRead(0, &c, 1, &cnt); + ArcEnterInteractiveMode(); + irq_exit(); +} + +void indy_r4k_timer_interrupt(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + int irq = SGI_TIMER_IRQ; + + irq_enter(); + kstat_cpu(cpu).irqs[irq]++; + timer_interrupt(irq, NULL, regs); + irq_exit(); + + if (softirq_pending(cpu)) + do_softirq(); +} + +extern int setup_irq(unsigned int irq, struct irqaction *irqaction); + +static void indy_timer_setup(struct irqaction *irq) +{ + /* over-write the handler, we use our own way */ + irq->handler = no_action; + + /* setup irqaction */ + setup_irq(SGI_TIMER_IRQ, irq); +} + +void __init ip22_time_init(void) +{ + /* setup hookup functions */ + rtc_get_time = indy_rtc_get_time; + rtc_set_time = indy_rtc_set_time; + + board_time_init = indy_time_init; + board_timer_setup = indy_timer_setup; +} diff -Nru a/arch/mips/sgi-ip27/Makefile b/arch/mips/sgi-ip27/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sgi-ip27/Makefile Tue Jul 1 18:44:38 2003 @@ -0,0 +1,9 @@ +# +# Makefile for the IP27 specific kernel interface routines under Linux. +# + +obj-y := ip27-berr.o ip27-console.o ip27-irq.o ip27-init.o ip27-irq-glue.o \ + ip27-klconfig.o ip27-klnuma.o ip27-memory.o ip27-nmi.o ip27-reset.o \ + ip27-setup.o ip27-timer.o + +EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips/sgi-ip27/TODO b/arch/mips/sgi-ip27/TODO --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sgi-ip27/TODO Tue Jul 1 18:44:36 2003 @@ -0,0 +1,23 @@ +1. Need to figure out why PCI writes to the IOC3 hang, and if it is okay +not to write to the IOC3 ever. +2. Need to figure out RRB allocation in bridge_startup(). +3. Need to figure out why address swaizzling is needed in inw/outw for +Qlogic scsi controllers. +4. Need to integrate ip27-klconfig.c:find_lboard and +ip27-init.c:find_lbaord_real. DONE +5. Is it okay to set calias space on all nodes as 0, instead of 8k as +in irix? +6. Investigate why things do not work without the setup_test() call +being invoked on all nodes in ip27-memory.c. +7. Too many CLIs in the locore handlers : +For the low level handlers set up by set_except_vector(), +__tlb_refill_debug_tramp, __xtlb_refill_debug_tramp and cacheerror, +investigate whether the code should do CLI, STI or KMODE. +8. Too many do_page_faults invoked - investigate. +9. start_thread must turn off UX64 ... and define tlb_refill_debug. +10. Need a bad pmd table, bad pte table. __bad_pmd_table/__bad_pagetable +does not agree with pgd_bad/pmd_bad. +11. All intrs (ip27_do_irq handlers) are targetted at cpu A on the node. +This might need to change later. Only the timer intr is set up to be +received on both Cpu A and B. (ip27_do_irq()/bridge_startup()) +13. Cache flushing (specially the SMP version) has to be investigated. diff -Nru a/arch/mips/sgi-ip27/ip27-berr.c b/arch/mips/sgi-ip27/ip27-berr.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sgi-ip27/ip27-berr.c Tue Jul 1 18:44:33 2003 @@ -0,0 +1,94 @@ +/* + * 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, 1995, 1996, 1999, 2000 by Ralf Baechle + * Copyright (C) 1999, 2000 by Silicon Graphics + * Copyright (C) 2002 Maciej W. Rozycki + */ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +extern void dump_tlb_addr(unsigned long addr); +extern void dump_tlb_all(void); + +static void dump_hub_information(unsigned long errst0, unsigned long errst1) +{ + static char *err_type[2][8] = { + { NULL, "Uncached Partial Read PRERR", "DERR", "Read Timeout", + NULL, NULL, NULL, NULL }, + { "WERR", "Uncached Partial Write", "PWERR", "Write Timeout", + NULL, NULL, NULL, NULL } + }; + int wrb = errst1 & PI_ERR_ST1_WRBRRB_MASK; + + if (!(errst0 & PI_ERR_ST0_VALID_MASK)) { + printk("Hub does not contain valid error information\n"); + return; + } + + + printk("Hub has valid error information:\n"); + if (errst0 & PI_ERR_ST0_OVERRUN_MASK) + printk("Overrun is set. Error stack may contain additional " + "information.\n"); + printk("Hub error address is %08lx\n", + (errst0 & PI_ERR_ST0_ADDR_MASK) >> (PI_ERR_ST0_ADDR_SHFT - 3)); + printk("Incoming message command 0x%lx\n", + (errst0 & PI_ERR_ST0_CMD_MASK) >> PI_ERR_ST0_CMD_SHFT); + printk("Supplemental field of incoming message is 0x%lx\n", + (errst0 & PI_ERR_ST0_SUPPL_MASK) >> PI_ERR_ST0_SUPPL_SHFT); + printk("T5 Rn (for RRB only) is 0x%lx\n", + (errst0 & PI_ERR_ST0_REQNUM_MASK) >> PI_ERR_ST0_REQNUM_SHFT); + printk("Error type is %s\n", err_type[wrb] + [(errst0 & PI_ERR_ST0_TYPE_MASK) >> PI_ERR_ST0_TYPE_SHFT] + ? : "invalid"); +} + +int ip27_be_handler(struct pt_regs *regs, int is_fixup) +{ + unsigned long errst0, errst1; + int data = regs->cp0_cause & 4; + int cpu = LOCAL_HUB_L(PI_CPU_NUM); + + if (is_fixup) + return MIPS_BE_FIXUP; + + printk("Slice %c got %cbe at 0x%lx\n", 'A' + cpu, data ? 'd' : 'i', + regs->cp0_epc); + printk("Hub information:\n"); + printk("ERR_INT_PEND = 0x%06lx\n", LOCAL_HUB_L(PI_ERR_INT_PEND)); + errst0 = LOCAL_HUB_L(cpu ? PI_ERR_STATUS0_B : PI_ERR_STATUS0_A); + errst1 = LOCAL_HUB_L(cpu ? PI_ERR_STATUS1_B : PI_ERR_STATUS1_A); + dump_hub_information(errst0, errst1); + show_regs(regs); + dump_tlb_all(); + while(1); + force_sig(SIGBUS, current); +} + +void __init ip27_be_init(void) +{ + /* XXX Initialize all the Hub & Bridge error handling here. */ + int cpu = LOCAL_HUB_L(PI_CPU_NUM); + int cpuoff = cpu << 8; + + board_be_handler = ip27_be_handler; + + LOCAL_HUB_S(PI_ERR_INT_PEND, + cpu ? PI_ERR_CLEAR_ALL_B : PI_ERR_CLEAR_ALL_A); + LOCAL_HUB_S(PI_ERR_INT_MASK_A + cpuoff, 0); + LOCAL_HUB_S(PI_ERR_STACK_ADDR_A + cpuoff, 0); + LOCAL_HUB_S(PI_ERR_STACK_SIZE, 0); /* Disable error stack */ + LOCAL_HUB_S(PI_SYSAD_ERRCHK_EN, PI_SYSAD_CHECK_ALL); +} diff -Nru a/arch/mips/sgi-ip27/ip27-console.c b/arch/mips/sgi-ip27/ip27-console.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sgi-ip27/ip27-console.c Tue Jul 1 18:44:36 2003 @@ -0,0 +1,65 @@ +/* + * 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) 2001, 2002 Ralf Baechle + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IOC3_BAUD (22000000 / (3*16)) +#define IOC3_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) + +static inline struct ioc3_uartregs *console_uart(void) +{ + struct ioc3 *ioc3; + + ioc3 = (struct ioc3 *)KL_CONFIG_CH_CONS_INFO(get_nasid())->memory_base; + + return &ioc3->sregs.uarta; +} + +void prom_putchar(char c) +{ + struct ioc3_uartregs *uart = console_uart(); + + while ((uart->iu_lsr & 0x20) == 0); + uart->iu_thr = c; +} + +char __init prom_getchar(void) +{ + return 0; +} + +static void inline ioc3_console_probe(void) +{ + struct serial_struct req; + + /* Register to interrupt zero because we share the interrupt with + the serial driver which we don't properly support yet. */ + memset(&req, 0, sizeof(req)); + req.irq = 0; + req.flags = IOC3_COM_FLAGS; + req.io_type = SERIAL_IO_MEM; + req.iomem_reg_shift = 0; + req.baud_base = IOC3_BAUD; + + req.iomem_base = (unsigned char *) console_uart(); + register_serial(&req); +} + +__init void ip27_setup_console(void) +{ + ioc3_console_probe(); +} diff -Nru a/arch/mips/sgi-ip27/ip27-init.c b/arch/mips/sgi-ip27/ip27-init.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sgi-ip27/ip27-init.c Tue Jul 1 18:44:38 2003 @@ -0,0 +1,821 @@ +/* + * 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) 2000 - 2001 by Kanoj Sarcar (kanoj@sgi.com) + * Copyright (C) 2000 - 2001 by Silicon Graphics, Inc. + */ + +#include +#include +#include +#include +#include /* for numnodes */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CPU_NONE (cpuid_t)-1 + +/* + * The following should work till 64 nodes, ie 128p SN0s. + */ +#define CNODEMASK_CLRALL(p) (p) = 0 +#define CNODEMASK_TSTB(p, bit) ((p) & (1ULL << (bit))) +#define CNODEMASK_SETB(p, bit) ((p) |= 1ULL << (bit)) + +cpumask_t boot_cpumask; +hubreg_t region_mask; +static int fine_mode; +int maxcpus; +static spinlock_t hub_mask_lock = SPIN_LOCK_UNLOCKED; +static cnodemask_t hub_init_mask; +static atomic_t numstarted = ATOMIC_INIT(1); +static int router_distance; +nasid_t master_nasid = INVALID_NASID; + +cnodeid_t nasid_to_compact_node[MAX_NASIDS]; +nasid_t compact_to_nasid_node[MAX_COMPACT_NODES]; +cnodeid_t cpuid_to_compact_node[MAXCPUS]; +char node_distances[MAX_COMPACT_NODES][MAX_COMPACT_NODES]; + +hubreg_t get_region(cnodeid_t cnode) +{ + if (fine_mode) + return COMPACT_TO_NASID_NODEID(cnode) >> NASID_TO_FINEREG_SHFT; + else + return COMPACT_TO_NASID_NODEID(cnode) >> NASID_TO_COARSEREG_SHFT; +} + +static void gen_region_mask(hubreg_t *region_mask, int maxnodes) +{ + cnodeid_t cnode; + + (*region_mask) = 0; + for (cnode = 0; cnode < maxnodes; cnode++) { + (*region_mask) |= 1ULL << get_region(cnode); + } +} + +int is_fine_dirmode(void) +{ + return (((LOCAL_HUB_L(NI_STATUS_REV_ID) & NSRI_REGIONSIZE_MASK) + >> NSRI_REGIONSIZE_SHFT) & REGIONSIZE_FINE); +} + +nasid_t get_actual_nasid(lboard_t *brd) +{ + klhub_t *hub; + + if (!brd) + return INVALID_NASID; + + /* find out if we are a completely disabled brd. */ + hub = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB); + if (!hub) + return INVALID_NASID; + if (!(hub->hub_info.flags & KLINFO_ENABLE)) /* disabled node brd */ + return hub->hub_info.physid; + else + return brd->brd_nasid; +} + +/* Tweak this for maximum number of CPUs to activate */ +static int max_cpus = NR_CPUS; + +int do_cpumask(cnodeid_t cnode, nasid_t nasid, cpumask_t *boot_cpumask, + int *highest) +{ + static int tot_cpus_found = 0; + lboard_t *brd; + klcpu_t *acpu; + int cpus_found = 0; + cpuid_t cpuid; + + brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27); + + do { + acpu = (klcpu_t *)find_first_component(brd, KLSTRUCT_CPU); + while (acpu) { + cpuid = acpu->cpu_info.virtid; + /* cnode is not valid for completely disabled brds */ + if (get_actual_nasid(brd) == brd->brd_nasid) + cpuid_to_compact_node[cpuid] = cnode; + if (cpuid > *highest) + *highest = cpuid; + /* Only let it join in if it's marked enabled */ + if ((acpu->cpu_info.flags & KLINFO_ENABLE) && + (tot_cpus_found != max_cpus)) { + CPUMASK_SETB(*boot_cpumask, cpuid); + cpus_found++; + tot_cpus_found++; + } + acpu = (klcpu_t *)find_component(brd, (klinfo_t *)acpu, + KLSTRUCT_CPU); + } + brd = KLCF_NEXT(brd); + if (brd) + brd = find_lboard(brd,KLTYPE_IP27); + else + break; + } while (brd); + + return cpus_found; +} + +cpuid_t cpu_node_probe(cpumask_t *boot_cpumask, int *numnodes) +{ + int i, cpus = 0, highest = 0; + gda_t *gdap = GDA; + nasid_t nasid; + + /* + * Initialize the arrays to invalid nodeid (-1) + */ + for (i = 0; i < MAX_COMPACT_NODES; i++) + compact_to_nasid_node[i] = INVALID_NASID; + for (i = 0; i < MAX_NASIDS; i++) + nasid_to_compact_node[i] = INVALID_CNODEID; + for (i = 0; i < MAXCPUS; i++) + cpuid_to_compact_node[i] = INVALID_CNODEID; + + *numnodes = 0; + for (i = 0; i < MAX_COMPACT_NODES; i++) { + if ((nasid = gdap->g_nasidtable[i]) == INVALID_NASID) { + break; + } else { + compact_to_nasid_node[i] = nasid; + nasid_to_compact_node[nasid] = i; + (*numnodes)++; + cpus += do_cpumask(i, nasid, boot_cpumask, &highest); + } + } + + /* + * Cpus are numbered in order of cnodes. Currently, disabled + * cpus are not numbered. + */ + + return highest + 1; +} + +int cpu_enabled(cpuid_t cpu) +{ + if (cpu == CPU_NONE) + return 0; + return CPUMASK_TSTB(boot_cpumask, cpu) != 0; +} + +void mlreset(void) +{ + int i; + void init_topology_matrix(void); + void dump_topology(void); + + + master_nasid = get_nasid(); + fine_mode = is_fine_dirmode(); + + /* + * Probe for all CPUs - this creates the cpumask and + * sets up the mapping tables. + */ + CPUMASK_CLRALL(boot_cpumask); + maxcpus = cpu_node_probe(&boot_cpumask, &numnodes); + printk("Discovered %d cpus on %d nodes\n", maxcpus, numnodes); + + init_topology_matrix(); + dump_topology(); + + gen_region_mask(®ion_mask, numnodes); + CNODEMASK_CLRALL(hub_init_mask); + + setup_replication_mask(numnodes); + + /* + * Set all nodes' calias sizes to 8k + */ + for (i = 0; i < numnodes; i++) { + nasid_t nasid; + + nasid = COMPACT_TO_NASID_NODEID(i); + + /* + * Always have node 0 in the region mask, otherwise + * CALIAS accesses get exceptions since the hub + * thinks it is a node 0 address. + */ + REMOTE_HUB_S(nasid, PI_REGION_PRESENT, (region_mask | 1)); +#ifdef CONFIG_REPLICATE_EXHANDLERS + REMOTE_HUB_S(nasid, PI_CALIAS_SIZE, PI_CALIAS_SIZE_8K); +#else + REMOTE_HUB_S(nasid, PI_CALIAS_SIZE, PI_CALIAS_SIZE_0); +#endif + +#ifdef LATER + /* + * Set up all hubs to have a big window pointing at + * widget 0. Memory mode, widget 0, offset 0 + */ + REMOTE_HUB_S(nasid, IIO_ITTE(SWIN0_BIGWIN), + ((HUB_PIO_MAP_TO_MEM << IIO_ITTE_IOSP_SHIFT) | + (0 << IIO_ITTE_WIDGET_SHIFT))); +#endif + } +} + + +void intr_clear_bits(nasid_t nasid, volatile hubreg_t *pend, int base_level, + char *name) +{ + volatile hubreg_t bits; + int i; + + /* Check pending interrupts */ + if ((bits = HUB_L(pend)) != 0) + for (i = 0; i < N_INTPEND_BITS; i++) + if (bits & (1 << i)) + LOCAL_HUB_CLR_INTR(base_level + i); +} + +void intr_clear_all(nasid_t nasid) +{ + REMOTE_HUB_S(nasid, PI_INT_MASK0_A, 0); + REMOTE_HUB_S(nasid, PI_INT_MASK0_B, 0); + REMOTE_HUB_S(nasid, PI_INT_MASK1_A, 0); + REMOTE_HUB_S(nasid, PI_INT_MASK1_B, 0); + intr_clear_bits(nasid, REMOTE_HUB_ADDR(nasid, PI_INT_PEND0), + INT_PEND0_BASELVL, "INT_PEND0"); + intr_clear_bits(nasid, REMOTE_HUB_ADDR(nasid, PI_INT_PEND1), + INT_PEND1_BASELVL, "INT_PEND1"); +} + +void sn_mp_setup(void) +{ + cnodeid_t cnode; +#if 0 + cpuid_t cpu; +#endif + + for (cnode = 0; cnode < numnodes; cnode++) { +#if 0 + init_platform_nodepda(); +#endif + intr_clear_all(COMPACT_TO_NASID_NODEID(cnode)); + } +#if 0 + for (cpu = 0; cpu < maxcpus; cpu++) { + init_platform_pda(); + } +#endif +} + +void per_hub_init(cnodeid_t cnode) +{ + extern void pcibr_setup(cnodeid_t); + cnodemask_t done; + nasid_t nasid; + + nasid = COMPACT_TO_NASID_NODEID(cnode); + + spin_lock(&hub_mask_lock); + /* Test our bit. */ + if (!(done = CNODEMASK_TSTB(hub_init_mask, cnode))) { + /* Turn our bit on in the mask. */ + CNODEMASK_SETB(hub_init_mask, cnode); + /* + * Do the actual initialization if it hasn't been done yet. + * We don't need to hold a lock for this work. + */ + /* + * Set CRB timeout at 5ms, (< PI timeout of 10ms) + */ + REMOTE_HUB_S(nasid, IIO_ICTP, 0x800); + REMOTE_HUB_S(nasid, IIO_ICTO, 0xff); + hub_rtc_init(cnode); + pcibr_setup(cnode); +#ifdef CONFIG_REPLICATE_EXHANDLERS + /* + * If this is not a headless node initialization, + * copy over the caliased exception handlers. + */ + if (get_compact_nodeid() == cnode) { + extern char except_vec0, except_vec1_r10k; + extern char except_vec2_generic, except_vec3_generic; + + memcpy((void *)(KSEG0 + 0x100), &except_vec2_generic, + 0x80); + memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, + 0x80); + memcpy((void *)KSEG0, &except_vec0, 0x80); + memcpy((void *)KSEG0 + 0x080, &except_vec1_r10k, 0x80); + memcpy((void *)(KSEG0 + 0x100), (void *) KSEG0, 0x80); + memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, + 0x100); + __flush_cache_all(); + } +#endif + } + spin_unlock(&hub_mask_lock); +} + +/* + * This is similar to hard_smp_processor_id(). + */ +cpuid_t getcpuid(void) +{ + klcpu_t *klcpu; + + klcpu = nasid_slice_to_cpuinfo(get_nasid(),LOCAL_HUB_L(PI_CPU_NUM)); + return klcpu->cpu_info.virtid; +} + +void per_cpu_init(void) +{ + extern void install_cpu_nmi_handler(int slice); + extern void load_mmu(void); + static int is_slave = 0; + int cpu = smp_processor_id(); + cnodeid_t cnode = get_compact_nodeid(); + + TLBMISS_HANDLER_SETUP(); +#if 0 + intr_init(); +#endif + clear_c0_status(ST0_IM); + per_hub_init(cnode); + cpu_time_init(); + if (smp_processor_id()) /* master can't do this early, no kmalloc */ + install_cpuintr(cpu); + /* Install our NMI handler if symmon hasn't installed one. */ + install_cpu_nmi_handler(cputoslice(cpu)); +#if 0 + install_tlbintr(cpu); +#endif + set_c0_status(SRB_DEV0 | SRB_DEV1); + if (is_slave) { + clear_c0_status(ST0_BEV); + if (current_cpu_data.isa_level == MIPS_CPU_ISA_IV) + set_c0_status(ST0_XX); + set_c0_status(ST0_KX|ST0_SX|ST0_UX); + local_irq_enable(); + load_mmu(); + atomic_inc(&numstarted); + } else { + is_slave = 1; + } +} + +cnodeid_t get_compact_nodeid(void) +{ + nasid_t nasid; + + nasid = get_nasid(); + /* + * Map the physical node id to a virtual node id (virtual node ids + * are contiguous). + */ + return NASID_TO_COMPACT_NODEID(nasid); +} + +#ifdef CONFIG_SMP + +/* + * Takes as first input the PROM assigned cpu id, and the kernel + * assigned cpu id as the second. + */ +static void alloc_cpupda(cpuid_t cpu, int cpunum) +{ + cnodeid_t node; + nasid_t nasid; + + node = get_cpu_cnode(cpu); + nasid = COMPACT_TO_NASID_NODEID(node); + + cputonasid(cpunum) = nasid; + cputocnode(cpunum) = node; + cputoslice(cpunum) = get_cpu_slice(cpu); + cpu_data[cpunum].p_cpuid = cpu; +} + +static struct task_struct * __init fork_by_hand(void) +{ + struct pt_regs regs; + /* + * don't care about the eip and regs settings since + * we'll never reschedule the forked task. + */ + return copy_process(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL); +} + +static int __init do_boot_cpu(int cpu, int num_cpus) +{ + extern void smp_bootstrap(void); + cpuid_t mycpuid = getcpuid(); + struct task_struct *idle; + + if (cpu == mycpuid) { + alloc_cpupda(cpu, num_cpus); + return 1; + } + + /* Skip holes in CPU space */ + if (!CPUMASK_TSTB(boot_cpumask, cpu)) + return 0; + + /* + * The following code is purely to make sure + * Linux can schedule processes on this slave. + */ + idle = fork_by_hand(); + if (IS_ERR(idle)) + panic("failed fork for CPU %d", cpu); + + /* + * We remove it from the pidhash and the runqueue + * once we got the process: + */ + init_idle(idle, cpu); + + alloc_cpupda(cpu, num_cpus); + + unhash_process(idle); + + /* + * Launch a slave into smp_bootstrap(). It doesn't take an + * argument, and we set sp to the kernel stack of the newly + * created idle process, gp to the proc struct so that + * current_thread_info() will work. + */ + LAUNCH_SLAVE(cputonasid(num_cpus),cputoslice(num_cpus), + (launch_proc_t)MAPPED_KERN_RW_TO_K0(smp_bootstrap), + 0, (void *)((unsigned long)idle->thread_info + + KERNEL_STACK_SIZE - 32), (void *)idle); + + /* + * Now optimistically set the mapping arrays. We + * need to wait here, verify the cpu booted up, then + * fire up the next cpu. + */ + __cpu_number_map[cpu] = num_cpus; + __cpu_logical_map[num_cpus] = cpu; + CPUMASK_SETB(cpu_online_map, cpu); + + /* + * Wait this cpu to start up and initialize its hub, + * and discover the io devices it will control. + * + * XXX: We really want to fire up launch all the CPUs + * at once. We have to preserve the order of the + * devices on the bridges first though. + */ + while (atomic_read(&numstarted) != num_cpus); + + return 1; +} + +void __init smp_boot_cpus(void) +{ + int num_cpus = 0; + cpuid_t cpu; + cnodeid_t cnode; + + init_new_context(current, &init_mm); + current_thread_info()->cpu = 0; + smp_tune_scheduling(); + + sn_mp_setup(); + /* Master has already done per_cpu_init() */ + install_cpuintr(smp_processor_id()); +#if 0 + bte_lateinit(); + ecc_init(); +#endif + + replicate_kernel_text(numnodes); + /* Launch slaves. */ + for (cpu = 0; cpu < maxcpus; cpu++) { + num_cpus += do_boot_cpu(cpu, num_cpus); + } + +#ifdef LATER + Wait logic goes here. +#endif + for (cnode = 0; cnode < numnodes; cnode++) { +#if 0 + if (cnodetocpu(cnode) == -1) { + printk("Initializing headless hub,cnode %d", cnode); + per_hub_init(cnode); + } +#endif + } +#if 0 + cpu_io_setup(); + init_mfhi_war(); +#endif +} + +#else /* CONFIG_SMP */ +void __init start_secondary(void) +{ + /* XXX Why do we need this empty definition at all? */ +} +#endif /* CONFIG_SMP */ + + +#define rou_rflag rou_flags + +void router_recurse(klrou_t *router_a, klrou_t *router_b, int depth) +{ + klrou_t *router; + lboard_t *brd; + int port; + + if (router_a->rou_rflag == 1) + return; + + if (depth >= router_distance) + return; + + router_a->rou_rflag = 1; + + for (port = 1; port <= MAX_ROUTER_PORTS; port++) { + if (router_a->rou_port[port].port_nasid == INVALID_NASID) + continue; + + brd = (lboard_t *)NODE_OFFSET_TO_K0( + router_a->rou_port[port].port_nasid, + router_a->rou_port[port].port_offset); + + if (brd->brd_type == KLTYPE_ROUTER) { + router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd), brd->brd_compts[0]); + if (router == router_b) { + if (depth < router_distance) + router_distance = depth; + } + else + router_recurse(router, router_b, depth + 1); + } + } + + router_a->rou_rflag = 0; +} + +int node_distance(nasid_t nasid_a, nasid_t nasid_b) +{ + nasid_t nasid; + cnodeid_t cnode; + lboard_t *brd, *dest_brd; + int port; + klrou_t *router, *router_a = NULL, *router_b = NULL; + + /* Figure out which routers nodes in question are connected to */ + for (cnode = 0; cnode < numnodes; cnode++) { + nasid = COMPACT_TO_NASID_NODEID(cnode); + + if (nasid == -1) continue; + + brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid), + KLTYPE_ROUTER); + + if (!brd) + continue; + + do { + if (brd->brd_flags & DUPLICATE_BOARD) + continue; + + router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd), brd->brd_compts[0]); + router->rou_rflag = 0; + + for (port = 1; port <= MAX_ROUTER_PORTS; port++) { + if (router->rou_port[port].port_nasid == INVALID_NASID) + continue; + + dest_brd = (lboard_t *)NODE_OFFSET_TO_K0( + router->rou_port[port].port_nasid, + router->rou_port[port].port_offset); + + if (dest_brd->brd_type == KLTYPE_IP27) { + if (dest_brd->brd_nasid == nasid_a) + router_a = router; + if (dest_brd->brd_nasid == nasid_b) + router_b = router; + } + } + + } while ( (brd = find_lboard_class(KLCF_NEXT(brd), KLTYPE_ROUTER)) ); + } + + if (router_a == NULL) { + printk("node_distance: router_a NULL\n"); + return -1; + } + if (router_b == NULL) { + printk("node_distance: router_b NULL\n"); + return -1; + } + + if (nasid_a == nasid_b) + return 0; + + if (router_a == router_b) + return 1; + + router_distance = 100; + router_recurse(router_a, router_b, 2); + + return router_distance; +} + +void init_topology_matrix(void) +{ + nasid_t nasid, nasid2; + cnodeid_t row, col; + + for (row = 0; row < MAX_COMPACT_NODES; row++) + for (col = 0; col < MAX_COMPACT_NODES; col++) + node_distances[row][col] = -1; + + for (row = 0; row < numnodes; row++) { + nasid = COMPACT_TO_NASID_NODEID(row); + for (col = 0; col < numnodes; col++) { + nasid2 = COMPACT_TO_NASID_NODEID(col); + node_distances[row][col] = node_distance(nasid, nasid2); + } + } +} + +void dump_topology(void) +{ + nasid_t nasid; + cnodeid_t cnode; + lboard_t *brd, *dest_brd; + int port; + int router_num = 0; + klrou_t *router; + cnodeid_t row, col; + + printk("************** Topology ********************\n"); + + printk(" "); + for (col = 0; col < numnodes; col++) + printk("%02d ", col); + printk("\n"); + for (row = 0; row < numnodes; row++) { + printk("%02d ", row); + for (col = 0; col < numnodes; col++) + printk("%2d ", node_distances[row][col]); + printk("\n"); + } + + for (cnode = 0; cnode < numnodes; cnode++) { + nasid = COMPACT_TO_NASID_NODEID(cnode); + + if (nasid == -1) continue; + + brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid), + KLTYPE_ROUTER); + + if (!brd) + continue; + + do { + if (brd->brd_flags & DUPLICATE_BOARD) + continue; + printk("Router %d:", router_num); + router_num++; + + router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd), brd->brd_compts[0]); + + for (port = 1; port <= MAX_ROUTER_PORTS; port++) { + if (router->rou_port[port].port_nasid == INVALID_NASID) + continue; + + dest_brd = (lboard_t *)NODE_OFFSET_TO_K0( + router->rou_port[port].port_nasid, + router->rou_port[port].port_offset); + + if (dest_brd->brd_type == KLTYPE_IP27) + printk(" %d", dest_brd->brd_nasid); + if (dest_brd->brd_type == KLTYPE_ROUTER) + printk(" r"); + } + printk("\n"); + + } while ( (brd = find_lboard_class(KLCF_NEXT(brd), KLTYPE_ROUTER)) ); + } +} + +#if 0 +#define brd_widgetnum brd_slot +#define NODE_OFFSET_TO_KLINFO(n,off) ((klinfo_t*) TO_NODE_CAC(n,off)) +void +dump_klcfg(void) +{ + cnodeid_t cnode; + int i; + nasid_t nasid; + lboard_t *lbptr; + gda_t *gdap; + + gdap = (gda_t *)GDA_ADDR(get_nasid()); + if (gdap->g_magic != GDA_MAGIC) { + printk("dumpklcfg_cmd: Invalid GDA MAGIC\n"); + return; + } + + for (cnode = 0; cnode < MAX_COMPACT_NODES; cnode ++) { + nasid = gdap->g_nasidtable[cnode]; + + if (nasid == INVALID_NASID) + continue; + + printk("\nDumpping klconfig Nasid %d:\n", nasid); + + lbptr = KL_CONFIG_INFO(nasid); + + while (lbptr) { + printk(" %s, Nasid %d, Module %d, widget 0x%x, partition %d, NIC 0x%x lboard 0x%lx", + "board name here", /* BOARD_NAME(lbptr->brd_type), */ + lbptr->brd_nasid, lbptr->brd_module, + lbptr->brd_widgetnum, + lbptr->brd_partition, + (lbptr->brd_nic), lbptr); + if (lbptr->brd_flags & DUPLICATE_BOARD) + printk(" -D"); + printk("\n"); + for (i = 0; i < lbptr->brd_numcompts; i++) { + klinfo_t *kli; + kli = NODE_OFFSET_TO_KLINFO(NASID_GET(lbptr), lbptr->brd_compts[i]); + printk(" type %2d, flags 0x%04x, diagval %3d, physid %4d, virtid %2d: %s\n", + kli->struct_type, + kli->flags, + kli->diagval, + kli->physid, + kli->virtid, + "comp. name here"); + /* COMPONENT_NAME(kli->struct_type)); */ + } + lbptr = KLCF_NEXT(lbptr); + } + } + printk("\n"); + + /* Useful to print router maps also */ + + for (cnode = 0; cnode < MAX_COMPACT_NODES; cnode ++) { + klrou_t *kr; + int i; + + nasid = gdap->g_nasidtable[cnode]; + if (nasid == INVALID_NASID) + continue; + lbptr = KL_CONFIG_INFO(nasid); + + while (lbptr) { + + lbptr = find_lboard_class(lbptr, KLCLASS_ROUTER); + if(!lbptr) + break; + if (!KL_CONFIG_DUPLICATE_BOARD(lbptr)) { + printk("%llx -> \n", lbptr->brd_nic); + kr = (klrou_t *)find_first_component(lbptr, + KLSTRUCT_ROU); + for (i = 1; i <= MAX_ROUTER_PORTS; i++) { + printk("[%d, %llx]; ", + kr->rou_port[i].port_nasid, + kr->rou_port[i].port_offset); + } + printk("\n"); + } + lbptr = KLCF_NEXT(lbptr); + } + printk("\n"); + } + + dump_topology(); +} +#endif diff -Nru a/arch/mips/sgi-ip27/ip27-irq-glue.S b/arch/mips/sgi-ip27/ip27-irq-glue.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sgi-ip27/ip27-irq-glue.S Tue Jul 1 18:44:33 2003 @@ -0,0 +1,64 @@ +/* + * 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) 1999 Ralf Baechle + * Copyright (C) 1999 Silicon Graphics, Inc. + */ +#include +#include +#include +#include + + .text + .set noat + .align 5 +NESTED(ip27_irq, PT_SIZE, sp) + SAVE_ALL + CLI + .set at + + /* IP27 may signal interrupt which we're not interested in. + Mask them out. */ + mfc0 s0, CP0_CAUSE + mfc0 t0, CP0_STATUS + and s0, t0 + + /* First check for RT interrupt. */ + andi a0, s0, CAUSEF_IP4 + beqz a0, 1f + + /* Ok, a timer interrupt. */ + move a0, sp + jal rt_timer_interrupt + + j ret_from_irq + +1: andi a0, s0, (CAUSEF_IP2 | CAUSEF_IP3) + beqz a0, 1f + + /* ... a device interrupt ... */ + move a0, sp + jal ip27_do_irq + + j ret_from_irq + +1: +#if 1 + mfc0 a1, CP0_STATUS + srl a1, a1, 8 + andi a1, 0xff + + mfc0 a2, CP0_CAUSE + srl a2, a2, 8 + andi a2, 0xff + + move a3, s0 + PRINT("Spurious interrupt, c0_status = %02x, c0_cause = %02x, pending %02x.\n") + ld a1, PT_EPC(sp) +0: b 0b +#endif + + j ret_from_irq + END(ip27_irq) diff -Nru a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sgi-ip27/ip27-irq.c Tue Jul 1 18:44:35 2003 @@ -0,0 +1,488 @@ +/* + * ip27-irq.c: Highlevel interrupt handling for IP27 architecture. + * + * Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + * Copyright (C) 1999 - 2001 Kanoj Sarcar + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#undef DEBUG_IRQ +#ifdef DEBUG_IRQ +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +/* These should die */ +unsigned char bus_to_wid[256]; /* widget id for linux pci bus */ +unsigned char bus_to_nid[256]; /* nasid for linux pci bus */ +unsigned char num_bridges; /* number of bridges in the system */ + +/* + * Linux has a controller-independent x86 interrupt architecture. + * every controller has a 'controller-template', that is used + * by the main code to do the right thing. Each driver-visible + * interrupt source is transparently wired to the apropriate + * controller. Thus drivers need not be aware of the + * interrupt-controller. + * + * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC, + * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC. + * (IO-APICs assumed to be messaging to Pentium local-APICs) + * + * the code is designed to be easily extended with new/different + * interrupt controllers, without having to do assembly magic. + */ + +extern asmlinkage void ip27_irq(void); + +extern int irq_to_bus[], irq_to_slot[], bus_to_cpu[]; +int intr_connect_level(int cpu, int bit); +int intr_disconnect_level(int cpu, int bit); + +/* + * There is a single intpend register per node, and we want to have + * distinct levels for intercpu intrs for both cpus A and B on a node. + */ +int node_level_to_irq[MAX_COMPACT_NODES][PERNODE_LEVELS]; + +/* + * use these macros to get the encoded nasid and widget id + * from the irq value + */ +#define IRQ_TO_BUS(i) irq_to_bus[(i)] +#define IRQ_TO_CPU(i) bus_to_cpu[IRQ_TO_BUS(i)] +#define NASID_FROM_PCI_IRQ(i) bus_to_nid[IRQ_TO_BUS(i)] +#define WID_FROM_PCI_IRQ(i) bus_to_wid[IRQ_TO_BUS(i)] +#define SLOT_FROM_PCI_IRQ(i) irq_to_slot[i] + +static inline int alloc_level(cpuid_t cpunum, int irq) +{ + cnodeid_t nodenum = CPUID_TO_COMPACT_NODEID(cpunum); + int j = LEAST_LEVEL + 3; /* resched & crosscall entries taken */ + + while (++j < PERNODE_LEVELS) { + if (node_level_to_irq[nodenum][j] == -1) { + node_level_to_irq[nodenum][j] = irq; + return j; + } + } + printk("Cpu %ld flooded with devices\n", cpunum); + while(1); + return -1; +} + +static inline int find_level(cpuid_t *cpunum, int irq) +{ + int j; + cnodeid_t nodenum = INVALID_CNODEID; + + while (++nodenum < MAX_COMPACT_NODES) { + j = LEAST_LEVEL + 3; /* resched & crosscall entries taken */ + while (++j < PERNODE_LEVELS) + if (node_level_to_irq[nodenum][j] == irq) { + *cpunum = 0; /* XXX Fixme */ + return(j); + } + } + printk("Could not identify cpu/level for irq %d\n", irq); + while(1); + return(-1); +} + +/* + * Find first bit set + */ +static int ms1bit(unsigned long x) +{ + int b = 0, s; + + s = 16; if (x >> 16 == 0) s = 0; b += s; x >>= s; + s = 8; if (x >> 8 == 0) s = 0; b += s; x >>= s; + s = 4; if (x >> 4 == 0) s = 0; b += s; x >>= s; + s = 2; if (x >> 2 == 0) s = 0; b += s; x >>= s; + s = 1; if (x >> 1 == 0) s = 0; b += s; + + return b; +} + +/* + * This code is unnecessarily complex, because we do SA_INTERRUPT + * intr enabling. Basically, once we grab the set of intrs we need + * to service, we must mask _all_ these interrupts; firstly, to make + * sure the same intr does not intr again, causing recursion that + * can lead to stack overflow. Secondly, we can not just mask the + * one intr we are do_IRQing, because the non-masked intrs in the + * first set might intr again, causing multiple servicings of the + * same intr. This effect is mostly seen for intercpu intrs. + * Kanoj 05.13.00 + */ +void ip27_do_irq(struct pt_regs *regs) +{ + int irq, swlevel; + hubreg_t pend0, mask0; + cpuid_t thiscpu = smp_processor_id(); + int pi_int_mask0 = ((cputoslice(thiscpu) == 0) ? + PI_INT_MASK0_A : PI_INT_MASK0_B); + + /* copied from Irix intpend0() */ + while (((pend0 = LOCAL_HUB_L(PI_INT_PEND0)) & + (mask0 = LOCAL_HUB_L(pi_int_mask0))) != 0) { + pend0 &= mask0; /* Pick intrs we should look at */ + if (pend0) { + /* Prevent any of the picked intrs from recursing */ + LOCAL_HUB_S(pi_int_mask0, mask0 & ~(pend0)); + do { + swlevel = ms1bit(pend0); + LOCAL_HUB_CLR_INTR(swlevel); + /* "map" swlevel to irq */ + irq = LEVEL_TO_IRQ(thiscpu, swlevel); + do_IRQ(irq, regs); + /* clear bit in pend0 */ + pend0 ^= 1ULL << swlevel; + } while(pend0); + /* Now allow the set of serviced intrs again */ + LOCAL_HUB_S(pi_int_mask0, mask0); + LOCAL_HUB_L(PI_INT_PEND0); + } + } +} + + +/* Startup one of the (PCI ...) IRQs routes over a bridge. */ +static unsigned int startup_bridge_irq(unsigned int irq) +{ + bridgereg_t device; + bridge_t *bridge; + int pin, swlevel; + cpuid_t cpu; + nasid_t master = NASID_FROM_PCI_IRQ(irq); + + if (irq < BASE_PCI_IRQ) + return 0; + + bridge = (bridge_t *) NODE_SWIN_BASE(master, WID_FROM_PCI_IRQ(irq)); + pin = SLOT_FROM_PCI_IRQ(irq); + cpu = IRQ_TO_CPU(irq); + + DBG("bridge_startup(): irq= 0x%x pin=%d\n", irq, pin); + /* + * "map" irq to a swlevel greater than 6 since the first 6 bits + * of INT_PEND0 are taken + */ + swlevel = alloc_level(cpu, irq); + intr_connect_level(cpu, swlevel); + + bridge->b_int_addr[pin].addr = (0x20000 | swlevel | (master << 8)); + bridge->b_int_enable |= (1 << pin); + /* more stuff in int_enable reg */ + bridge->b_int_enable |= 0x7ffffe00; + + /* + * XXX This only works if b_int_device is initialized to 0! + * We program the bridge to have a 1:1 mapping between devices + * (slots) and intr pins. + */ + device = bridge->b_int_device; + device |= (pin << (pin*3)); + bridge->b_int_device = device; + + bridge->b_widget.w_tflush; /* Flush */ + + return 0; /* Never anything pending. */ +} + +/* Shutdown one of the (PCI ...) IRQs routes over a bridge. */ +static unsigned int shutdown_bridge_irq(unsigned int irq) +{ + bridge_t *bridge; + int pin, swlevel; + cpuid_t cpu; + + if (irq < BASE_PCI_IRQ) + return 0; + + bridge = (bridge_t *) NODE_SWIN_BASE(NASID_FROM_PCI_IRQ(irq), + WID_FROM_PCI_IRQ(irq)); + DBG("bridge_shutdown: irq 0x%x\n", irq); + pin = SLOT_FROM_PCI_IRQ(irq); + + /* + * map irq to a swlevel greater than 6 since the first 6 bits + * of INT_PEND0 are taken + */ + swlevel = find_level(&cpu, irq); + intr_disconnect_level(cpu, swlevel); + LEVEL_TO_IRQ(cpu, swlevel) = -1; + + bridge->b_int_enable &= ~(1 << pin); + bridge->b_widget.w_tflush; /* Flush */ + + return 0; /* Never anything pending. */ +} + +static inline void enable_bridge_irq(unsigned int irq) +{ + /* All the braindamage happens magically for us in ip27_do_irq */ +} + +static void disable_bridge_irq(unsigned int irq) +{ + /* All the braindamage happens magically for us in ip27_do_irq */ +} + +static void mask_and_ack_bridge_irq(unsigned int irq) +{ + /* All the braindamage happens magically for us in ip27_do_irq */ +} + +static void end_bridge_irq (unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_bridge_irq(irq); +} + +static struct hw_interrupt_type bridge_irq_type = { + "bridge", + startup_bridge_irq, + shutdown_bridge_irq, + enable_bridge_irq, + disable_bridge_irq, + mask_and_ack_bridge_irq, + end_bridge_irq +}; + +void irq_debug(void) +{ + bridge_t *bridge = (bridge_t *) 0x9200000008000000; + + printk("bridge->b_int_status = 0x%x\n", bridge->b_int_status); + printk("bridge->b_int_enable = 0x%x\n", bridge->b_int_enable); + printk("PI_INT_PEND0 = 0x%lx\n", LOCAL_HUB_L(PI_INT_PEND0)); + printk("PI_INT_MASK0_A = 0x%lx\n", LOCAL_HUB_L(PI_INT_MASK0_A)); +} + +void __init init_IRQ(void) +{ + int i; + + set_except_vector(0, ip27_irq); + + /* + * Right now the bridge irq is our kitchen sink interrupt type + */ + for (i = 0; i <= NR_IRQS; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = 1; + irq_desc[i].handler = &bridge_irq_type; + } +} + +/* + * Get values that vary depending on which CPU and bit we're operating on. + */ +static hub_intmasks_t *intr_get_ptrs(cpuid_t cpu, int bit, int *new_bit, + hubreg_t **intpend_masks, int *ip) +{ + hub_intmasks_t *hub_intmasks; + + hub_intmasks = &cpu_data[cpu].p_intmasks; + if (bit < N_INTPEND_BITS) { + *intpend_masks = hub_intmasks->intpend0_masks; + *ip = 0; + *new_bit = bit; + } else { + *intpend_masks = hub_intmasks->intpend1_masks; + *ip = 1; + *new_bit = bit - N_INTPEND_BITS; + } + return hub_intmasks; +} + +int intr_connect_level(int cpu, int bit) +{ + int ip; + int slice = cputoslice(cpu); + volatile hubreg_t *mask_reg; + hubreg_t *intpend_masks; + nasid_t nasid = COMPACT_TO_NASID_NODEID(cputocnode(cpu)); + + (void)intr_get_ptrs(cpu, bit, &bit, &intpend_masks, &ip); + + /* Make sure it's not already pending when we connect it. */ + REMOTE_HUB_CLR_INTR(nasid, bit + ip * N_INTPEND_BITS); + + intpend_masks[0] |= (1ULL << (u64)bit); + + if (ip == 0) { + mask_reg = REMOTE_HUB_ADDR(nasid, PI_INT_MASK0_A + + PI_INT_MASK_OFFSET * slice); + } else { + mask_reg = REMOTE_HUB_ADDR(nasid, PI_INT_MASK1_A + + PI_INT_MASK_OFFSET * slice); + } + HUB_S(mask_reg, intpend_masks[0]); + return(0); +} + +int intr_disconnect_level(int cpu, int bit) +{ + int ip; + int slice = cputoslice(cpu); + volatile hubreg_t *mask_reg; + hubreg_t *intpend_masks; + nasid_t nasid = COMPACT_TO_NASID_NODEID(cputocnode(cpu)); + + (void)intr_get_ptrs(cpu, bit, &bit, &intpend_masks, &ip); + intpend_masks[0] &= ~(1ULL << (u64)bit); + if (ip == 0) { + mask_reg = REMOTE_HUB_ADDR(nasid, PI_INT_MASK0_A + + PI_INT_MASK_OFFSET * slice); + } else { + mask_reg = REMOTE_HUB_ADDR(nasid, PI_INT_MASK1_A + + PI_INT_MASK_OFFSET * slice); + } + HUB_S(mask_reg, intpend_masks[0]); + return(0); +} + + +irqreturn_t handle_resched_intr(int irq, void *dev_id, struct pt_regs *regs) +{ + /* Nothing, the return from intr will work for us */ + return IRQ_NONE; +} + +#ifdef CONFIG_SMP + +void core_send_ipi(int destid, unsigned int action) +{ + int irq; + +#if (CPUS_PER_NODE == 2) + switch (action) { + case SMP_RESCHEDULE_YOURSELF: + irq = CPU_RESCHED_A_IRQ; + break; + case SMP_CALL_FUNCTION: + irq = CPU_CALL_A_IRQ; + break; + default: + panic("sendintr"); + } + irq += cputoslice(destid); + + /* + * Convert the compact hub number to the NASID to get the correct + * part of the address space. Then set the interrupt bit associated + * with the CPU we want to send the interrupt to. + */ + REMOTE_HUB_SEND_INTR(COMPACT_TO_NASID_NODEID(cputocnode(destid)), + FAST_IRQ_TO_LEVEL(irq)); +#else + << Bomb! Must redefine this for more than 2 CPUS. >> +#endif +} + +#endif + +extern irqreturn_t smp_call_function_interrupt(int irq, void *dev, + struct pt_regs *regs); + +void install_cpuintr(int cpu) +{ +#ifdef CONFIG_SMP +#if (CPUS_PER_NODE == 2) + static int done = 0; + + /* + * This is a hack till we have a pernode irqlist. Currently, + * just have the master cpu set up the handlers for the per + * cpu irqs. + */ + if (done == 0) { + int j; + + if (request_irq(CPU_RESCHED_A_IRQ, handle_resched_intr, + 0, "resched", 0)) + panic("intercpu intr unconnectible"); + if (request_irq(CPU_RESCHED_B_IRQ, handle_resched_intr, + 0, "resched", 0)) + panic("intercpu intr unconnectible"); + if (request_irq(CPU_CALL_A_IRQ, smp_call_function_interrupt, + 0, "callfunc", 0)) + panic("intercpu intr unconnectible"); + if (request_irq(CPU_CALL_B_IRQ, smp_call_function_interrupt, + 0, "callfunc", 0)) + panic("intercpu intr unconnectible"); + + for (j = 0; j < PERNODE_LEVELS; j++) + LEVEL_TO_IRQ(0, j) = -1; + LEVEL_TO_IRQ(0, FAST_IRQ_TO_LEVEL(CPU_RESCHED_A_IRQ)) = + CPU_RESCHED_A_IRQ; + LEVEL_TO_IRQ(0, FAST_IRQ_TO_LEVEL(CPU_RESCHED_B_IRQ)) = + CPU_RESCHED_B_IRQ; + LEVEL_TO_IRQ(0, FAST_IRQ_TO_LEVEL(CPU_CALL_A_IRQ)) = + CPU_CALL_A_IRQ; + LEVEL_TO_IRQ(0, FAST_IRQ_TO_LEVEL(CPU_CALL_B_IRQ)) = + CPU_CALL_B_IRQ; + for (j = 1; j < MAX_COMPACT_NODES; j++) + memcpy(&node_level_to_irq[j][0], + &node_level_to_irq[0][0], + sizeof(node_level_to_irq[0][0])*PERNODE_LEVELS); + + done = 1; + } + + intr_connect_level(cpu, FAST_IRQ_TO_LEVEL(CPU_RESCHED_A_IRQ + + cputoslice(cpu))); + intr_connect_level(cpu, FAST_IRQ_TO_LEVEL(CPU_CALL_A_IRQ + + cputoslice(cpu))); +#else /* CPUS_PER_NODE */ +#error Must redefine this for more than 2 CPUS. +#endif /* CPUS_PER_NODE */ +#endif /* CONFIG_SMP */ +} + +void install_tlbintr(int cpu) +{ +#if 0 + int intr_bit = N_INTPEND_BITS + TLB_INTR_A + cputoslice(cpu); + + intr_connect_level(cpu, intr_bit); +#endif +} diff -Nru a/arch/mips/sgi-ip27/ip27-klconfig.c b/arch/mips/sgi-ip27/ip27-klconfig.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sgi-ip27/ip27-klconfig.c Tue Jul 1 18:44:36 2003 @@ -0,0 +1,135 @@ +/* + * Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +klinfo_t *find_component(lboard_t *brd, klinfo_t *kli, unsigned char struct_type) +{ + int index, j; + + if (kli == (klinfo_t *)NULL) { + index = 0; + } else { + for (j = 0; j < KLCF_NUM_COMPS(brd); j++) + if (kli == KLCF_COMP(brd, j)) + break; + index = j; + if (index == KLCF_NUM_COMPS(brd)) { + printk("find_component: Bad pointer: 0x%p\n", kli); + return (klinfo_t *)NULL; + } + index++; /* next component */ + } + + for (; index < KLCF_NUM_COMPS(brd); index++) { + kli = KLCF_COMP(brd, index); + if (KLCF_COMP_TYPE(kli) == struct_type) + return kli; + } + + /* Didn't find it. */ + return (klinfo_t *)NULL; +} + +klinfo_t *find_first_component(lboard_t *brd, unsigned char struct_type) +{ + return find_component(brd, (klinfo_t *)NULL, struct_type); +} + +lboard_t * find_lboard(lboard_t *start, unsigned char brd_type) +{ + /* Search all boards stored on this node. */ + while (start) { + if (start->brd_type == brd_type) + return start; + start = KLCF_NEXT(start); + } + /* Didn't find it. */ + return (lboard_t *)NULL; +} + +lboard_t * find_lboard_class(lboard_t *start, unsigned char brd_type) +{ + /* Search all boards stored on this node. */ + while (start) { + if (KLCLASS(start->brd_type) == KLCLASS(brd_type)) + return start; + start = KLCF_NEXT(start); + } + + /* Didn't find it. */ + return (lboard_t *)NULL; +} + +cnodeid_t get_cpu_cnode(cpuid_t cpu) +{ + return CPUID_TO_COMPACT_NODEID(cpu); +} + +klcpu_t * nasid_slice_to_cpuinfo(nasid_t nasid, int slice) +{ + lboard_t *brd; + klcpu_t *acpu; + + if (!(brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27))) + return (klcpu_t *)NULL; + + if (!(acpu = (klcpu_t *)find_first_component(brd, KLSTRUCT_CPU))) + return (klcpu_t *)NULL; + + do { + if ((acpu->cpu_info.physid) == slice) + return acpu; + } while ((acpu = (klcpu_t *)find_component(brd, (klinfo_t *)acpu, + KLSTRUCT_CPU))); + return (klcpu_t *)NULL; +} + +klcpu_t * sn_get_cpuinfo(cpuid_t cpu) +{ + nasid_t nasid; + int slice; + klcpu_t *acpu; + gda_t *gdap = GDA; + cnodeid_t cnode; + + if (!(cpu < MAXCPUS)) { + printk("sn_get_cpuinfo: illegal cpuid 0x%lx\n", cpu); + return NULL; + } + + cnode = get_cpu_cnode(cpu); + if (cnode == INVALID_CNODEID) + return NULL; + + if ((nasid = gdap->g_nasidtable[cnode]) == INVALID_NASID) + return NULL; + + for (slice = 0; slice < CPUS_PER_NODE; slice++) { + acpu = nasid_slice_to_cpuinfo(nasid, slice); + if (acpu && acpu->cpu_info.virtid == cpu) + return acpu; + } + return NULL; +} + +int get_cpu_slice(cpuid_t cpu) +{ + klcpu_t *acpu; + + if ((acpu = sn_get_cpuinfo(cpu)) == NULL) + return -1; + return acpu->cpu_info.physid; +} diff -Nru a/arch/mips/sgi-ip27/ip27-klnuma.c b/arch/mips/sgi-ip27/ip27-klnuma.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sgi-ip27/ip27-klnuma.c Tue Jul 1 18:44:34 2003 @@ -0,0 +1,143 @@ +/* + * Ported from IRIX to Linux by Kanoj Sarcar, 06/08/00. + * Copyright 2000 - 2001 Silicon Graphics, Inc. + * Copyright 2000 - 2001 Kanoj Sarcar (kanoj@sgi.com) + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern char _end; +static cpumask_t ktext_repmask; + +/* + * XXX - This needs to be much smarter about where it puts copies of the + * kernel. For example, we should never put a copy on a headless node, + * and we should respect the topology of the machine. + */ +void __init setup_replication_mask(int maxnodes) +{ + static int numa_kernel_replication_ratio; + cnodeid_t cnode; + + /* Set only the master cnode's bit. The master cnode is always 0. */ + CPUMASK_CLRALL(ktext_repmask); + CPUMASK_SETB(ktext_repmask, 0); + + numa_kernel_replication_ratio = 0; +#ifdef CONFIG_REPLICATE_KTEXT +#ifndef CONFIG_MAPPED_KERNEL +#error Kernel replication works with mapped kernel support. No calias support. +#endif + numa_kernel_replication_ratio = 1; +#endif + + for (cnode = 1; cnode < numnodes; cnode++) { + /* See if this node should get a copy of the kernel */ + if (numa_kernel_replication_ratio && + !(cnode % numa_kernel_replication_ratio)) { + + /* Advertise that we have a copy of the kernel */ + CPUMASK_SETB(ktext_repmask, cnode); + } + } + + /* Set up a GDA pointer to the replication mask. */ + GDA->g_ktext_repmask = &ktext_repmask; +} + + +static __init void set_ktext_source(nasid_t client_nasid, nasid_t server_nasid) +{ + kern_vars_t *kvp; + cnodeid_t client_cnode; + + client_cnode = NASID_TO_COMPACT_NODEID(client_nasid); + + kvp = &(PLAT_NODE_DATA(client_cnode)->kern_vars); + + KERN_VARS_ADDR(client_nasid) = (unsigned long)kvp; + + kvp->kv_magic = KV_MAGIC; + + kvp->kv_ro_nasid = server_nasid; + kvp->kv_rw_nasid = master_nasid; + kvp->kv_ro_baseaddr = NODE_CAC_BASE(server_nasid); + kvp->kv_rw_baseaddr = NODE_CAC_BASE(master_nasid); + printk("REPLICATION: ON nasid %d, ktext from nasid %d, kdata from nasid %d\n", client_nasid, server_nasid, master_nasid); +} + +/* XXX - When the BTE works, we should use it instead of this. */ +static __init void copy_kernel(nasid_t dest_nasid) +{ + extern char _stext, _etext; + unsigned long dest_kern_start, source_start, source_end, kern_size; + + source_start = (unsigned long)&_stext; + source_end = (unsigned long)&_etext; + kern_size = source_end - source_start; + + dest_kern_start = CHANGE_ADDR_NASID(MAPPED_KERN_RO_TO_K0(source_start), + dest_nasid); + memcpy((void *)dest_kern_start, (void *)source_start, kern_size); +} + +void __init replicate_kernel_text(int maxnodes) +{ + cnodeid_t cnode; + nasid_t client_nasid; + nasid_t server_nasid; + + server_nasid = master_nasid; + + /* Record where the master node should get its kernel text */ + set_ktext_source(master_nasid, master_nasid); + + for (cnode = 1; cnode < maxnodes; cnode++) { + client_nasid = COMPACT_TO_NASID_NODEID(cnode); + + /* Check if this node should get a copy of the kernel */ + if (CPUMASK_TSTB(ktext_repmask, cnode)) { + server_nasid = client_nasid; + copy_kernel(server_nasid); + } + + /* Record where this node should get its kernel text */ + set_ktext_source(client_nasid, server_nasid); + } +} + +/* + * Return pfn of first free page of memory on a node. PROM may allocate + * data structures on the first couple of pages of the first slot of each + * node. If this is the case, getfirstfree(node) > getslotstart(node, 0). + */ +pfn_t node_getfirstfree(cnodeid_t cnode) +{ + unsigned long loadbase = CKSEG0; + nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode); + unsigned long offset; + +#ifdef CONFIG_MAPPED_KERNEL + loadbase = CKSSEG + 16777216; +#endif + offset = PAGE_ALIGN((unsigned long)(&_end)) - loadbase; + if ((cnode == 0) || (CPUMASK_TSTB(ktext_repmask, cnode))) + return (TO_NODE(nasid, offset) >> PAGE_SHIFT); + else + return (KDM_TO_PHYS(PAGE_ALIGN(SYMMON_STK_ADDR(nasid, 0))) >> + PAGE_SHIFT); +} + diff -Nru a/arch/mips/sgi-ip27/ip27-memory.c b/arch/mips/sgi-ip27/ip27-memory.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sgi-ip27/ip27-memory.c Tue Jul 1 18:44:33 2003 @@ -0,0 +1,337 @@ +/* + * 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) 2000 by Ralf Baechle + * Copyright (C) 2000 by Silicon Graphics, Inc. + * + * On SGI IP27 the ARC memory configuration data is completly bogus but + * alternate easier to use mechanisms are available. + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* ip27-klnuma.c */ +extern pfn_t node_getfirstfree(cnodeid_t cnode); + +#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) +#define SLOT_IGNORED 0xffff + +short slot_lastfilled_cache[MAX_COMPACT_NODES]; +unsigned short slot_psize_cache[MAX_COMPACT_NODES][MAX_MEM_SLOTS]; +static pfn_t numpages; + +plat_pg_data_t *plat_node_data[MAX_COMPACT_NODES]; +bootmem_data_t plat_node_bdata[MAX_COMPACT_NODES]; + +int numa_debug(void) +{ + printk("NUMA debug\n"); + *(int *)0 = 0; + return(0); +} + +/* + * Return the number of pages of memory provided by the given slot + * on the specified node. + */ +pfn_t slot_getsize(cnodeid_t node, int slot) +{ + return (pfn_t) slot_psize_cache[node][slot]; +} + +/* + * Return highest slot filled + */ +int node_getlastslot(cnodeid_t node) +{ + return (int) slot_lastfilled_cache[node]; +} + +/* + * Return the pfn of the last free page of memory on a node. + */ +pfn_t node_getmaxclick(cnodeid_t node) +{ + pfn_t slot_psize; + int slot; + + /* + * Start at the top slot. When we find a slot with memory in it, + * that's the winner. + */ + for (slot = (node_getnumslots(node) - 1); slot >= 0; slot--) { + if ((slot_psize = slot_getsize(node, slot))) { + if (slot_psize == SLOT_IGNORED) + continue; + /* Return the basepfn + the slot size, minus 1. */ + return slot_getbasepfn(node, slot) + slot_psize - 1; + } + } + + /* + * If there's no memory on the node, return 0. This is likely + * to cause problems. + */ + return (pfn_t)0; +} + +static pfn_t slot_psize_compute(cnodeid_t node, int slot) +{ + nasid_t nasid; + lboard_t *brd; + klmembnk_t *banks; + unsigned long size; + + nasid = COMPACT_TO_NASID_NODEID(node); + /* Find the node board */ + brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27); + if (!brd) + return 0; + + /* Get the memory bank structure */ + banks = (klmembnk_t *)find_first_component(brd, KLSTRUCT_MEMBNK); + if (!banks) + return 0; + + /* Size in _Megabytes_ */ + size = (unsigned long)banks->membnk_bnksz[slot/4]; + + /* hack for 128 dimm banks */ + if (size <= 128) { + if (slot%4 == 0) { + size <<= 20; /* size in bytes */ + return(size >> PAGE_SHIFT); + } else { + return 0; + } + } else { + size /= 4; + size <<= 20; + return(size >> PAGE_SHIFT); + } +} + +pfn_t szmem(pfn_t fpage, pfn_t maxpmem) +{ + cnodeid_t node; + int slot, numslots; + pfn_t num_pages = 0, slot_psize; + pfn_t slot0sz = 0, nodebytes; /* Hack to detect problem configs */ + int ignore; + + for (node = 0; node < numnodes; node++) { + numslots = node_getnumslots(node); + ignore = nodebytes = 0; + for (slot = 0; slot < numslots; slot++) { + slot_psize = slot_psize_compute(node, slot); + if (slot == 0) slot0sz = slot_psize; + /* + * We need to refine the hack when we have replicated + * kernel text. + */ + nodebytes += SLOT_SIZE; + if ((nodebytes >> PAGE_SHIFT) * (sizeof(struct page)) > + (slot0sz << PAGE_SHIFT)) + ignore = 1; + if (ignore && slot_psize) { + printk("Ignoring slot %d onwards on node %d\n", + slot, node); + slot_psize_cache[node][slot] = SLOT_IGNORED; + slot = numslots; + continue; + } + num_pages += slot_psize; + slot_psize_cache[node][slot] = + (unsigned short) slot_psize; + if (slot_psize) + slot_lastfilled_cache[node] = slot; + } + } + if (maxpmem) + return((maxpmem > num_pages) ? num_pages : maxpmem); + else + return num_pages; +} + +/* + * Currently, the intranode memory hole support assumes that each slot + * contains at least 32 MBytes of memory. We assume all bootmem data + * fits on the first slot. + */ +void __init prom_meminit(void) +{ + extern void mlreset(void); + cnodeid_t node; + pfn_t slot_firstpfn, slot_lastpfn, slot_freepfn; + unsigned long bootmap_size; + int node_datasz; + + node_datasz = PFN_UP(sizeof(plat_pg_data_t)); + mlreset(); + numpages = szmem(0, 0); + for (node = (numnodes - 1); node >= 0; node--) { + slot_firstpfn = slot_getbasepfn(node, 0); + slot_lastpfn = slot_firstpfn + slot_getsize(node, 0); + slot_freepfn = node_getfirstfree(node); + /* Foll line hack for non discontigmem; remove once discontigmem + * becomes the default. */ + max_low_pfn = (slot_lastpfn - slot_firstpfn); + + /* + * Allocate the node data structure on the node first. + */ + plat_node_data[node] = (plat_pg_data_t *)(__va(slot_freepfn \ + << PAGE_SHIFT)); + NODE_DATA(node)->bdata = plat_node_bdata + node; + slot_freepfn += node_datasz; + bootmap_size = init_bootmem_node(NODE_DATA(node), slot_freepfn, + slot_firstpfn, slot_lastpfn); + free_bootmem_node(NODE_DATA(node), slot_firstpfn << PAGE_SHIFT, + (slot_lastpfn - slot_firstpfn) << PAGE_SHIFT); + reserve_bootmem_node(NODE_DATA(node), slot_firstpfn << PAGE_SHIFT, + ((slot_freepfn - slot_firstpfn) << PAGE_SHIFT) + bootmap_size); + } + printk("Total memory probed : 0x%lx pages\n", numpages); +} + +int __init page_is_ram(unsigned long pagenr) +{ + return 1; +} + +void __init +prom_free_prom_memory (void) +{ + /* We got nothing to free here ... */ +} + +#ifdef CONFIG_DISCONTIGMEM + +static pfn_t pagenr; + +void __init paging_init(void) +{ + pmd_t *pmd = kpmdtbl; + pte_t *pte = kptbl; + + cnodeid_t node; + unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0}; + int i; + + /* Initialize the entire pgd. */ + pgd_init((unsigned long)swapper_pg_dir); + pmd_init((unsigned long)invalid_pmd_table, (unsigned long)invalid_pte_table); + memset((void *)invalid_pte_table, 0, sizeof(pte_t) * PTRS_PER_PTE); + + /* This is for vmalloc */ + memset((void *)kptbl, 0, PAGE_SIZE << PGD_ORDER); + memset((void *)kpmdtbl, 0, PAGE_SIZE); + set_pgd(swapper_pg_dir, __pgd(kpmdtbl)); + for (i = 0; i < (1 << PGD_ORDER); pmd++,i++,pte+=PTRS_PER_PTE) + pmd_val(*pmd) = (unsigned long)pte; + + for (node = 0; node < numnodes; node++) { + pfn_t start_pfn = slot_getbasepfn(node, 0); + pfn_t end_pfn = node_getmaxclick(node); + + zones_size[ZONE_DMA] = end_pfn + 1 - start_pfn; + free_area_init_node(node, NODE_DATA(node), 0, zones_size, + start_pfn, 0); + } +} + +void __init mem_init(void) +{ + extern char _stext, _etext, _fdata, _edata; + extern char __init_begin, __init_end; + extern unsigned long setup_zero_pages(void); + cnodeid_t nid; + unsigned long tmp; + unsigned long codesize, datasize, initsize; + int slot, numslots; + struct page *pg, *pslot; + + num_physpages = numpages; /* memory already sized by szmem */ + max_mapnr = pagenr; /* already found during paging_init */ + high_memory = (void *) __va(max_mapnr << PAGE_SHIFT); + + for (nid = 0; nid < numnodes; nid++) { + + /* + * Hack till free_area_init_core() zeroes free_pages + */ + for (tmp = 0; tmp < MAX_NR_ZONES; tmp++) + PLAT_NODE_DATA(nid)->gendata.node_zones[tmp].free_pages=0; + /* + * This will free up the bootmem, ie, slot 0 memory. + */ + totalram_pages += free_all_bootmem_node(NODE_DATA(nid)); + + /* + * We need to manually do the other slots. + */ + pg = NODE_DATA(nid)->node_mem_map + slot_getsize(nid, 0); + numslots = node_getlastslot(nid); + for (slot = 1; slot <= numslots; slot++) { + pslot = NODE_DATA(nid)->node_mem_map + + slot_getbasepfn(nid, slot) - slot_getbasepfn(nid, 0); + + /* + * Mark holes in previous slot. May also want to + * free up the pages that hold the memmap entries. + */ + while (pg < pslot) { + pg++; + } + + /* + * Free valid memory in current slot. + */ + pslot += slot_getsize(nid, slot); + while (pg < pslot) { + /* if (!page_is_ram(pgnr)) continue; */ + /* commented out until page_is_ram works */ + ClearPageReserved(pg); + atomic_set(&pg->count, 1); + __free_page(pg); + totalram_pages++; + pg++; pgnr++; + } + } + } + + totalram_pages -= setup_zero_pages(); /* This comes from node 0 */ + + codesize = (unsigned long) &_etext - (unsigned long) &_stext; + datasize = (unsigned long) &_edata - (unsigned long) &_fdata; + initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin; + + tmp = (unsigned long) nr_free_pages(); + printk("Memory: %luk/%luk available (%ldk kernel code, %ldk reserved, " + "%ldk data, %ldk init)\n", + tmp << (PAGE_SHIFT-10), + num_physpages << (PAGE_SHIFT-10), + codesize >> 10, + (num_physpages - tmp) << (PAGE_SHIFT-10), + datasize >> 10, + initsize >> 10); +} + +#endif /* CONFIG_DISCONTIGMEM */ diff -Nru a/arch/mips/sgi-ip27/ip27-nmi.c b/arch/mips/sgi-ip27/ip27-nmi.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sgi-ip27/ip27-nmi.c Tue Jul 1 18:44:31 2003 @@ -0,0 +1,168 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if 0 +#define NODE_NUM_CPUS(n) CNODE_NUM_CPUS(n) +#else +#define NODE_NUM_CPUS(n) CPUS_PER_NODE +#endif + +#define CNODEID_NONE (cnodeid_t)-1 +#define enter_panic_mode() spin_lock(&nmi_lock) + +typedef unsigned long machreg_t; + +spinlock_t nmi_lock = SPIN_LOCK_UNLOCKED; + +/* + * Lets see what else we need to do here. Set up sp, gp? + */ +void nmi_dump(void) +{ + void cont_nmi_dump(void); + + cont_nmi_dump(); +} + +void install_cpu_nmi_handler(int slice) +{ + nmi_t *nmi_addr; + + nmi_addr = (nmi_t *)NMI_ADDR(get_nasid(), slice); + if (nmi_addr->call_addr) + return; + nmi_addr->magic = NMI_MAGIC; + nmi_addr->call_addr = (void *)nmi_dump; + nmi_addr->call_addr_c = + (void *)(~((unsigned long)(nmi_addr->call_addr))); + nmi_addr->call_parm = 0; +} + +/* + * Copy the cpu registers which have been saved in the IP27prom format + * into the eframe format for the node under consideration. + */ + +void +nmi_cpu_eframe_save(nasid_t nasid, + int slice) +{ + int i, numberof_nmi_cpu_regs; + machreg_t *prom_format; + + /* Get the total number of registers being saved by the prom */ + numberof_nmi_cpu_regs = sizeof(struct reg_struct) / sizeof(machreg_t); + + /* Get the pointer to the current cpu's register set. */ + prom_format = + (machreg_t *)(TO_UNCAC(TO_NODE(nasid, IP27_NMI_KREGS_OFFSET)) + + slice * IP27_NMI_KREGS_CPU_SIZE); + + printk("NMI nasid %d: slice %d\n", nasid, slice); + for (i = 0; i < numberof_nmi_cpu_regs; i++) + printk("0x%lx ", prom_format[i]); + printk("\n\n"); +} + +/* + * Copy the cpu registers which have been saved in the IP27prom format + * into the eframe format for the node under consideration. + */ +void +nmi_node_eframe_save(cnodeid_t cnode) +{ + int cpu; + nasid_t nasid; + + /* Make sure that we have a valid node */ + if (cnode == CNODEID_NONE) + return; + + nasid = COMPACT_TO_NASID_NODEID(cnode); + if (nasid == INVALID_NASID) + return; + + /* Save the registers into eframe for each cpu */ + for(cpu = 0; cpu < NODE_NUM_CPUS(cnode); cpu++) + nmi_cpu_eframe_save(nasid, cpu); +} + +/* + * Save the nmi cpu registers for all cpus in the system. + */ +void +nmi_eframes_save(void) +{ + cnodeid_t cnode; + + for(cnode = 0 ; cnode < numnodes; cnode++) + nmi_node_eframe_save(cnode); +} + +void +cont_nmi_dump(void) +{ +#ifndef REAL_NMI_SIGNAL + static atomic_t nmied_cpus = ATOMIC_INIT(0); + + atomic_inc(&nmied_cpus); +#endif + /* + * Use enter_panic_mode to allow only 1 cpu to proceed + */ + enter_panic_mode(); + +#ifdef REAL_NMI_SIGNAL + /* + * Wait up to 15 seconds for the other cpus to respond to the NMI. + * If a cpu has not responded after 10 sec, send it 1 additional NMI. + * This is for 2 reasons: + * - sometimes a MMSC fail to NMI all cpus. + * - on 512p SN0 system, the MMSC will only send NMIs to + * half the cpus. Unfortunately, we don't know which cpus may be + * NMIed - it depends on how the site chooses to configure. + * + * Note: it has been measure that it takes the MMSC up to 2.3 secs to + * send NMIs to all cpus on a 256p system. + */ + for (i=0; i < 1500; i++) { + for (node=0; node < numnodes; node++) + if (NODEPDA(node)->dump_count == 0) + break; + if (node == numnodes) + break; + if (i == 1000) { + for (node=0; node < numnodes; node++) + if (NODEPDA(node)->dump_count == 0) { + cpu = CNODE_TO_CPU_BASE(node); + for (n=0; n < CNODE_NUM_CPUS(node); cpu++, n++) { + CPUMASK_SETB(nmied_cpus, cpu); + /* + * cputonasid, cputoslice + * needs kernel cpuid + */ + SEND_NMI((cputonasid(cpu)), (cputoslice(cpu))); + } + } + + } + udelay(10000); + } +#else + while (atomic_read(&nmied_cpus) != num_online_cpus()); +#endif + + /* + * Save the nmi cpu registers for all cpu in the eframe format. + */ + nmi_eframes_save(); + LOCAL_HUB_S(NI_PORT_RESET, NPR_PORTRESET | NPR_LOCALRESET); +} diff -Nru a/arch/mips/sgi-ip27/ip27-reset.c b/arch/mips/sgi-ip27/ip27-reset.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sgi-ip27/ip27-reset.c Tue Jul 1 18:44:35 2003 @@ -0,0 +1,80 @@ +/* + * 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. + * + * Reset an IP27. + * + * Copyright (C) 1997, 1998, 1999, 2000 by Ralf Baechle + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void machine_restart(char *command) __attribute__((noreturn)); +void machine_halt(void) __attribute__((noreturn)); +void machine_power_off(void) __attribute__((noreturn)); + +#define noreturn while(1); /* Silence gcc. */ + +/* XXX How to pass the reboot command to the firmware??? */ +static void ip27_machine_restart(char *command) +{ +#if 0 + int i; +#endif + + printk("Reboot started from CPU %d\n", smp_processor_id()); +#ifdef CONFIG_SMP + smp_send_stop(); +#endif +#if 0 + for (i = 0; i < numnodes; i++) + REMOTE_HUB_S(COMPACT_TO_NASID_NODEID(i), PROMOP_REG, + PROMOP_REBOOT); +#else + LOCAL_HUB_S(NI_PORT_RESET, NPR_PORTRESET | NPR_LOCALRESET); +#endif + noreturn; +} + +static void ip27_machine_halt(void) +{ + int i; + +#ifdef CONFIG_SMP + smp_send_stop(); +#endif + for (i = 0; i < numnodes; i++) + REMOTE_HUB_S(COMPACT_TO_NASID_NODEID(i), PROMOP_REG, + PROMOP_RESTART); + LOCAL_HUB_S(NI_PORT_RESET, NPR_PORTRESET | NPR_LOCALRESET); + noreturn; +} + +static void ip27_machine_power_off(void) +{ + /* To do ... */ + noreturn; +} + +void ip27_reboot_setup(void) +{ + _machine_restart = ip27_machine_restart; + _machine_halt = ip27_machine_halt; + _machine_power_off = ip27_machine_power_off; +} diff -Nru a/arch/mips/sgi-ip27/ip27-setup.c b/arch/mips/sgi-ip27/ip27-setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sgi-ip27/ip27-setup.c Tue Jul 1 18:44:34 2003 @@ -0,0 +1,319 @@ +/* + * 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. + * + * SGI IP27 specific setup. + * + * Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 1999, 2000 Silcon Graphics, Inc. + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Check against user dumbness. */ +#ifdef CONFIG_VT +#error CONFIG_VT not allowed for IP27. +#endif + +#undef DEBUG_SETUP +#ifdef DEBUG_SETUP +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +extern void ip27_be_init(void) __init; + +/* + * get_nasid() returns the physical node id number of the caller. + */ +nasid_t +get_nasid(void) +{ + return (nasid_t)((LOCAL_HUB_L(NI_STATUS_REV_ID) & NSRI_NODEID_MASK) + >> NSRI_NODEID_SHFT); +} + +/* Extracted from the IOC3 meta driver. FIXME. */ +static inline void ioc3_sio_init(void) +{ + struct ioc3 *ioc3; + nasid_t nid; + long loops; + + nid = get_nasid(); + ioc3 = (struct ioc3 *) KL_CONFIG_CH_CONS_INFO(nid)->memory_base; + + ioc3->sscr_a = 0; /* PIO mode for uarta. */ + ioc3->sscr_b = 0; /* PIO mode for uartb. */ + ioc3->sio_iec = ~0; + ioc3->sio_ies = (SIO_IR_SA_INT | SIO_IR_SB_INT); + + loops=1000000; while(loops--); + ioc3->sregs.uarta.iu_fcr = 0; + ioc3->sregs.uartb.iu_fcr = 0; + loops=1000000; while(loops--); +} + +static inline void ioc3_eth_init(void) +{ + struct ioc3 *ioc3; + nasid_t nid; + + nid = get_nasid(); + ioc3 = (struct ioc3 *) KL_CONFIG_CH_CONS_INFO(nid)->memory_base; + + ioc3->eier = 0; +} + +/* Try to catch kernel missconfigurations and give user an indication what + option to select. */ +static void __init verify_mode(void) +{ + int n_mode; + + n_mode = LOCAL_HUB_L(NI_STATUS_REV_ID) & NSRI_MORENODES_MASK; + printk("Machine is in %c mode.\n", n_mode ? 'N' : 'M'); +#ifdef CONFIG_SGI_SN0_N_MODE + if (!n_mode) + panic("Kernel compiled for M mode."); +#else + if (n_mode) + panic("Kernel compiled for N mode."); +#endif +} + +#define XBOW_WIDGET_PART_NUM 0x0 +#define XXBOW_WIDGET_PART_NUM 0xd000 /* Xbridge */ +#define BASE_XBOW_PORT 8 /* Lowest external port */ + +unsigned int bus_to_cpu[256]; +unsigned long bus_to_baddr[256]; + +void __init pcibr_setup(cnodeid_t nid) +{ + int i, start, num; + unsigned long masterwid; + bridge_t *bridge; + volatile u64 hubreg; + nasid_t nasid, masternasid; + xwidget_part_num_t partnum; + widgetreg_t widget_id; + static spinlock_t pcibr_setup_lock = SPIN_LOCK_UNLOCKED; + + /* + * If the master is doing this for headless node, nothing to do. + * This is because currently we require at least one of the hubs + * (master hub) connected to the xbow to have at least one enabled + * cpu to receive intrs. Else we need an array bus_to_intrnasid[] + * that bridge_startup() needs to use to target intrs. All dma is + * routed thru the widget of the master hub. The master hub wid + * is selectable by WIDGET_A below. + */ + if (nid != get_compact_nodeid()) + return; + /* + * find what's on our local node + */ + spin_lock(&pcibr_setup_lock); + start = num_bridges; /* Remember where we start from */ + nasid = COMPACT_TO_NASID_NODEID(nid); + hubreg = REMOTE_HUB_L(nasid, IIO_LLP_CSR); + if (hubreg & IIO_LLP_CSR_IS_UP) { + /* link is up */ + widget_id = *(volatile widgetreg_t *) + (RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID); + partnum = XWIDGET_PART_NUM(widget_id); + printk("Cpu %d, Nasid 0x%x, pcibr_setup(): found partnum= 0x%x", + smp_processor_id(), nasid, partnum); + if (partnum == BRIDGE_WIDGET_PART_NUM) { + /* + * found direct connected bridge so must be Origin200 + */ + printk("...is bridge\n"); + num_bridges = 1; + bus_to_wid[0] = 0x8; + bus_to_nid[0] = 0; + masterwid = 0xa; + bus_to_baddr[0] = 0xa100000000000000UL; + } else if (partnum == XBOW_WIDGET_PART_NUM) { + lboard_t *brd; + klxbow_t *xbow_p; + /* + * found xbow, so may have multiple bridges + * need to probe xbow + */ + printk("...is xbow\n"); + + if ((brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), + KLTYPE_MIDPLANE8)) == NULL) + printk("argh\n"); + else + printk("brd = 0x%lx\n", (unsigned long) brd); + if ((xbow_p = (klxbow_t *) + find_component(brd, NULL, KLSTRUCT_XBOW)) == NULL) + printk("argh\n"); + else { + /* + * Okay, here's a xbow. Lets arbitrate and find + * out if we should initialize it. Set enabled + * hub connected at highest or lowest widget as + * master. + */ +#ifdef WIDGET_A + i = HUB_WIDGET_ID_MAX + 1; + do { + i--; + } while ((!XBOW_PORT_TYPE_HUB(xbow_p, i)) || + (!XBOW_PORT_IS_ENABLED(xbow_p, i))); +#else + i = HUB_WIDGET_ID_MIN - 1; + do { + i++; + } while ((!XBOW_PORT_TYPE_HUB(xbow_p, i)) || + (!XBOW_PORT_IS_ENABLED(xbow_p, i))); +#endif + masterwid = i; + masternasid = XBOW_PORT_NASID(xbow_p, i); + if (nasid == masternasid) + for (i=HUB_WIDGET_ID_MIN; i<=HUB_WIDGET_ID_MAX; i++) { + if (!XBOW_PORT_IS_ENABLED(xbow_p, i)) + continue; + if (XBOW_PORT_TYPE_IO(xbow_p, i)) { + widget_id = *(volatile widgetreg_t *) + (RAW_NODE_SWIN_BASE(nasid, i) + WIDGET_ID); + partnum = XWIDGET_PART_NUM(widget_id); + if (partnum == BRIDGE_WIDGET_PART_NUM) { + printk("widget 0x%x is a bridge\n", i); + bus_to_wid[num_bridges] = i; + bus_to_nid[num_bridges] = nasid; + bus_to_baddr[num_bridges] = ((masterwid << 60) | (1UL << 56)); /* Barrier set */ + num_bridges++; + } + } + } + } + } else if (partnum == XXBOW_WIDGET_PART_NUM) { + /* + * found xbridge, assume ibrick for now + */ + printk("...is xbridge\n"); + bus_to_wid[0] = 0xb; + bus_to_wid[1] = 0xe; + bus_to_wid[2] = 0xf; + + bus_to_nid[0] = 0; + bus_to_nid[1] = 0; + bus_to_nid[2] = 0; + + bus_to_baddr[0] = 0xa100000000000000UL; + bus_to_baddr[1] = 0xa100000000000000UL; + bus_to_baddr[2] = 0xa100000000000000UL; + masterwid = 0xa; + num_bridges = 3; + } + } + num = num_bridges - start; + spin_unlock(&pcibr_setup_lock); + /* + * set bridge registers + */ + for (i = start; i < (start + num); i++) { + + DBG("pcibr_setup: bus= %d bus_to_wid[%2d]= %d bus_to_nid[%2d]= %d\n", + i, i, bus_to_wid[i], i, bus_to_nid[i]); + + bus_to_cpu[i] = smp_processor_id(); + /* + * point to this bridge + */ + bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[i],bus_to_wid[i]); + /* + * Clear all pending interrupts. + */ + bridge->b_int_rst_stat = (BRIDGE_IRR_ALL_CLR); + /* + * Until otherwise set up, assume all interrupts are from slot 0 + */ + bridge->b_int_device = (u32) 0x0; + /* + * swap pio's to pci mem and io space (big windows) + */ + bridge->b_wid_control |= BRIDGE_CTRL_IO_SWAP; + bridge->b_wid_control |= BRIDGE_CTRL_MEM_SWAP; + + /* + * Hmm... IRIX sets additional bits in the address which + * are documented as reserved in the bridge docs. + */ + bridge->b_int_mode = 0x0; /* Don't clear ints */ + bridge->b_wid_int_upper = 0x8000 | (masterwid << 16); + bridge->b_wid_int_lower = 0x01800090; /* PI_INT_PEND_MOD off*/ + bridge->b_dir_map = (masterwid << 20); /* DMA */ + bridge->b_int_enable = 0; + + bridge->b_wid_tflush; /* wait until Bridge PIO complete */ + } +} + +extern void ip27_setup_console(void); +extern void ip27_time_init(void); +extern void ip27_reboot_setup(void); + +void __init ip27_setup(void) +{ + nasid_t nid; + hubreg_t p, e; + + ip27_setup_console(); + ip27_reboot_setup(); + + num_bridges = 0; + /* + * hub_rtc init and cpu clock intr enabled for later calibrate_delay. + */ + DBG("ip27_setup(): Entered.\n"); + nid = get_nasid(); + printk("IP27: Running on node %d.\n", nid); + + p = LOCAL_HUB_L(PI_CPU_PRESENT_A) & 1; + e = LOCAL_HUB_L(PI_CPU_ENABLE_A) & 1; + printk("Node %d has %s primary CPU%s.\n", nid, + p ? "a" : "no", + e ? ", CPU is running" : ""); + + p = LOCAL_HUB_L(PI_CPU_PRESENT_B) & 1; + e = LOCAL_HUB_L(PI_CPU_ENABLE_B) & 1; + printk("Node %d has %s secondary CPU%s.\n", nid, + p ? "a" : "no", + e ? ", CPU is running" : ""); + + verify_mode(); + ioc3_sio_init(); + ioc3_eth_init(); + per_cpu_init(); + + mips_io_port_base = IO_BASE; + board_time_init = ip27_time_init; +} diff -Nru a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sgi-ip27/ip27-timer.c Tue Jul 1 18:44:34 2003 @@ -0,0 +1,238 @@ +/* + * Copytight (C) 1999, 2000 Ralf Baechle (ralf@gnu.org) + * Copytight (C) 1999, 2000 Silicon Graphics, Inc. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * This is a hack; we really need to figure these values out dynamically + * + * Since 800 ns works very well with various HUB frequencies, such as + * 360, 380, 390 and 400 MHZ, we use 800 ns rtc cycle time. + * + * Ralf: which clock rate is used to feed the counter? + */ +#define NSEC_PER_CYCLE 800 +#define CYCLES_PER_SEC (NSEC_PER_SEC/NSEC_PER_CYCLE) +#define CYCLES_PER_JIFFY (CYCLES_PER_SEC/HZ) + +#define TICK_SIZE (tick_nsec / 1000) + +static unsigned long ct_cur[NR_CPUS]; /* What counter should be at next timer irq */ +static long last_rtc_update; /* Last time the rtc clock got updated */ + +extern volatile unsigned long wall_jiffies; + + +static int set_rtc_mmss(unsigned long nowtime) +{ + int retval = 0; + int real_seconds, real_minutes, cmos_minutes; + struct m48t35_rtc *rtc; + nasid_t nid; + + nid = get_nasid(); + rtc = (struct m48t35_rtc *)(KL_CONFIG_CH_CONS_INFO(nid)->memory_base + + IOC3_BYTEBUS_DEV0); + + rtc->control |= M48T35_RTC_READ; + cmos_minutes = BCD2BIN(rtc->min); + rtc->control &= ~M48T35_RTC_READ; + + /* + * Since we're only adjusting minutes and seconds, don't interfere with + * hour overflow. This avoids messing with unknown time zones but + * requires your RTC not to be off by more than 15 minutes + */ + real_seconds = nowtime % 60; + real_minutes = nowtime / 60; + if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) + real_minutes += 30; /* correct for half hour time zone */ + real_minutes %= 60; + + if (abs(real_minutes - cmos_minutes) < 30) { + real_seconds = BIN2BCD(real_seconds); + real_minutes = BIN2BCD(real_minutes); + rtc->control |= M48T35_RTC_SET; + rtc->sec = real_seconds; + rtc->min = real_minutes; + rtc->control &= ~M48T35_RTC_SET; + } else { + printk(KERN_WARNING + "set_rtc_mmss: can't update from %d to %d\n", + cmos_minutes, real_minutes); + retval = -1; + } + + return retval; +} + +void rt_timer_interrupt(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + int cpuA = ((cputoslice(cpu)) == 0); + int irq = 9; /* XXX Assign number */ + + irq_enter(); + write_seqlock(&xtime_lock); + +again: + LOCAL_HUB_S(cpuA ? PI_RT_PEND_A : PI_RT_PEND_B, 0); /* Ack */ + ct_cur[cpu] += CYCLES_PER_JIFFY; + LOCAL_HUB_S(cpuA ? PI_RT_COMPARE_A : PI_RT_COMPARE_B, ct_cur[cpu]); + + if (LOCAL_HUB_L(PI_RT_COUNT) >= ct_cur[cpu]) + goto again; + + kstat_cpu(cpu).irqs[irq]++; /* kstat only for bootcpu? */ + + if (cpu == 0) + do_timer(regs); + +#ifdef CONFIG_SMP + update_process_times(user_mode(regs)); +#endif /* CONFIG_SMP */ + + /* + * If we have an externally synchronized Linux clock, then update + * RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be + * called as close as possible to when a second starts. + */ + if ((time_status & STA_UNSYNC) == 0 && + xtime.tv_sec > last_rtc_update + 660 && + (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 && + (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) { + if (rtc_set_time(xtime.tv_sec) == 0) { + last_rtc_update = xtime.tv_sec; + } else { + last_rtc_update = xtime.tv_sec - 600; + /* do it again in 60 s */ + } + } + + write_sequnlock(&xtime_lock); + irq_exit(); + + if (softirq_pending(cpu)) + do_softirq(); +} + +unsigned long ip27_do_gettimeoffset(void) +{ + unsigned long ct_cur1; + ct_cur1 = REMOTE_HUB_L(cputonasid(0), PI_RT_COUNT) + CYCLES_PER_JIFFY; + return (ct_cur1 - ct_cur[0]) * NSEC_PER_CYCLE / 1000; +} + +/* Includes for ioc3_init(). */ +#include +#include +#include +#include +#include + +static __init unsigned long get_m48t35_time(void) +{ + unsigned int year, month, date, hour, min, sec; + struct m48t35_rtc *rtc; + nasid_t nid; + + nid = get_nasid(); + rtc = (struct m48t35_rtc *)(KL_CONFIG_CH_CONS_INFO(nid)->memory_base + + IOC3_BYTEBUS_DEV0); + + rtc->control |= M48T35_RTC_READ; + sec = rtc->sec; + min = rtc->min; + hour = rtc->hour; + date = rtc->date; + month = rtc->month; + year = rtc->year; + rtc->control &= ~M48T35_RTC_READ; + + sec = BCD2BIN(sec); + min = BCD2BIN(min); + hour = BCD2BIN(hour); + date = BCD2BIN(date); + month = BCD2BIN(month); + year = BCD2BIN(year); + + year += 1970; + + return mktime(year, month, date, hour, min, sec); +} + +void __init ip27_time_init(void) +{ + xtime.tv_sec = get_m48t35_time(); + xtime.tv_nsec = 0; + + do_gettimeoffset = ip27_do_gettimeoffset; +} + +void __init cpu_time_init(void) +{ + lboard_t *board; + klcpu_t *cpu; + int cpuid; + + /* Don't use ARCS. ARCS is fragile. Klconfig is simple and sane. */ + board = find_lboard(KL_CONFIG_INFO(get_nasid()), KLTYPE_IP27); + if (!board) + panic("Can't find board info for myself."); + + cpuid = LOCAL_HUB_L(PI_CPU_NUM) ? IP27_CPU0_INDEX : IP27_CPU1_INDEX; + cpu = (klcpu_t *) KLCF_COMP(board, cpuid); + if (!cpu) + panic("No information about myself?"); + + printk("CPU %d clock is %dMHz.\n", smp_processor_id(), cpu->cpu_speed); + + set_c0_status(SRB_TIMOCLK); +} + +void __init hub_rtc_init(cnodeid_t cnode) +{ + /* + * We only need to initialize the current node. + * If this is not the current node then it is a cpuless + * node and timeouts will not happen there. + */ + if (get_compact_nodeid() == cnode) { + int cpu = smp_processor_id(); + LOCAL_HUB_S(PI_RT_EN_A, 1); + LOCAL_HUB_S(PI_RT_EN_B, 1); + LOCAL_HUB_S(PI_PROF_EN_A, 0); + LOCAL_HUB_S(PI_PROF_EN_B, 0); + ct_cur[cpu] = CYCLES_PER_JIFFY; + LOCAL_HUB_S(PI_RT_COMPARE_A, ct_cur[cpu]); + LOCAL_HUB_S(PI_RT_COUNT, 0); + LOCAL_HUB_S(PI_RT_PEND_A, 0); + LOCAL_HUB_S(PI_RT_COMPARE_B, ct_cur[cpu]); + LOCAL_HUB_S(PI_RT_COUNT, 0); + LOCAL_HUB_S(PI_RT_PEND_B, 0); + } +} diff -Nru a/arch/mips/sgi-ip32/Makefile b/arch/mips/sgi-ip32/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sgi-ip32/Makefile Tue Jul 1 18:44:35 2003 @@ -0,0 +1,9 @@ +# +# Makefile for the SGI specific kernel interface routines +# under Linux. +# + +obj-y += ip32-berr.o ip32-rtc.o ip32-setup.o ip32-irq.o ip32-irq-glue.o \ + ip32-timer.o crime.o ip32-reset.o + +EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips/sgi-ip32/crime.c b/arch/mips/sgi-ip32/crime.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sgi-ip32/crime.c Tue Jul 1 18:44:32 2003 @@ -0,0 +1,49 @@ +/* + * 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) 2001 Keith M Wesolowski + */ +#include +#include +#include +#include +#include + +void __init crime_init (void) +{ + u64 id = crime_read_64 (CRIME_ID); + u64 rev = id & CRIME_ID_REV; + + id = (id & CRIME_ID_IDBITS) >> 4; + + printk ("CRIME id %1lx rev %ld detected at %016lx\n", id, rev, + (unsigned long) CRIME_BASE); +} + +/* XXX Like on Sun, these give us various useful information to printk. */ +void crime_memerr_intr (unsigned int irq, void *dev_id, struct pt_regs *regs) +{ + u64 memerr = crime_read_64 (CRIME_MEM_ERROR_STAT); + u64 addr = crime_read_64 (CRIME_MEM_ERROR_ADDR); + memerr &= CRIME_MEM_ERROR_STAT_MASK; + + printk ("CRIME memory error at physaddr 0x%08lx status %08lx\n", + addr << 2, memerr); + + crime_write_64 (CRIME_MEM_ERROR_STAT, 0); +} + +void crime_cpuerr_intr (unsigned int irq, void *dev_id, struct pt_regs *regs) +{ + u64 cpuerr = crime_read_64 (CRIME_CPU_ERROR_STAT); + u64 addr = crime_read_64 (CRIME_CPU_ERROR_ADDR); + cpuerr &= CRIME_CPU_ERROR_MASK; + addr <<= 2UL; + + printk ("CRIME CPU interface error detected at %09lx status %08lx\n", + addr, cpuerr); + + crime_write_64 (CRIME_CPU_ERROR_STAT, 0); +} diff -Nru a/arch/mips/sgi-ip32/ip32-berr.c b/arch/mips/sgi-ip32/ip32-berr.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sgi-ip32/ip32-berr.c Tue Jul 1 18:44:36 2003 @@ -0,0 +1,35 @@ +/* + * 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, 1995, 1996, 1999, 2000 by Ralf Baechle + * Copyright (C) 1999, 2000 by Silicon Graphics + * Copyright (C) 2002 Maciej W. Rozycki + */ +#include +#include +#include +#include +#include +#include +#include + +int ip32_be_handler(struct pt_regs *regs, int is_fixup) +{ + int data = regs->cp0_cause & 4; + + if (is_fixup) + return MIPS_BE_FIXUP; + + printk("Got %cbe at 0x%lx\n", data ? 'd' : 'i', regs->cp0_epc); + show_regs(regs); + dump_tlb_all(); + while(1); + force_sig(SIGBUS, current); +} + +void __init ip32_be_init(void) +{ + board_be_handler = ip32_be_handler; +} diff -Nru a/arch/mips/sgi-ip32/ip32-irq-glue.S b/arch/mips/sgi-ip32/ip32-irq-glue.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sgi-ip32/ip32-irq-glue.S Tue Jul 1 18:44:34 2003 @@ -0,0 +1,87 @@ +/* + * Low level interrupt handler for the SGI O2 aka IP32 aka Moosehead + * + * 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) 2000 Harald Koerfgen + * Copyright (C) 2001 Keith M Wesolowski + */ +#include +#include +#include +#include +#include +#include + + .text + .set noreorder + .set noat + .align 5 + NESTED(ip32_handle_int, PT_SIZE, ra) + .set noat + SAVE_ALL + CLI # TEST: interrupts should be off + .set at + .set noreorder + + mfc0 s0,CP0_CAUSE + + andi t1, s0, IE_IRQ0 + bnez t1, handle_irq0 + andi t1, s0, IE_IRQ1 + bnez t1, handle_irq1 + andi t1, s0, IE_IRQ2 + bnez t1, handle_irq2 + andi t1, s0, IE_IRQ3 + bnez t1, handle_irq3 + andi t1, s0, IE_IRQ4 + bnez t1, handle_irq4 + andi t1, s0, IE_IRQ5 + bnez t1, handle_irq5 + nop + + /* Either someone has triggered the "software interrupts" + * or we lost an interrupt somehow. Ignore it. + */ + j ret_from_irq + nop + +handle_irq0: + jal ip32_irq0 + move a0, sp + j ret_from_irq + nop + +handle_irq1: + jal ip32_irq1 + move a0, sp + j ret_from_irq + nop + +handle_irq2: + jal ip32_irq2 + move a0, sp + j ret_from_irq + nop + +handle_irq3: + jal ip32_irq3 + move a0, sp + j ret_from_irq + nop + +handle_irq4: + jal ip32_irq4 + move a0, sp + j ret_from_irq + nop + +handle_irq5: + jal ip32_irq5 + move a0, sp + j ret_from_irq + nop + + END(ip32_handle_int) diff -Nru a/arch/mips/sgi-ip32/ip32-irq.c b/arch/mips/sgi-ip32/ip32-irq.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sgi-ip32/ip32-irq.c Tue Jul 1 18:44:35 2003 @@ -0,0 +1,584 @@ +/* + * Code to handle IP32 IRQs + * + * 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) 2000 Harald Koerfgen + * Copyright (C) 2001 Keith M Wesolowski + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#undef DEBUG_IRQ +#ifdef DEBUG_IRQ +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +/* O2 irq map + * + * IP0 -> software (ignored) + * IP1 -> software (ignored) + * IP2 -> (irq0) C crime 1.1 all interrupts; crime 1.5 ??? + * IP3 -> (irq1) X unknown + * IP4 -> (irq2) X unknown + * IP5 -> (irq3) X unknown + * IP6 -> (irq4) X unknown + * IP7 -> (irq5) 0 CPU count/compare timer (system timer) + * + * crime: (C) + * + * CRIME_INT_STAT 31:0: + * + * 0 -> 1 Video in 1 + * 1 -> 2 Video in 2 + * 2 -> 3 Video out + * 3 -> 4 Mace ethernet + * 4 -> S SuperIO sub-interrupt + * 5 -> M Miscellaneous sub-interrupt + * 6 -> A Audio sub-interrupt + * 7 -> 8 PCI bridge errors + * 8 -> 9 PCI SCSI aic7xxx 0 + * 9 -> 10 PCI SCSI aic7xxx 1 + * 10 -> 11 PCI slot 0 + * 11 -> 12 unused (PCI slot 1) + * 12 -> 13 unused (PCI slot 2) + * 13 -> 14 unused (PCI shared 0) + * 14 -> 15 unused (PCI shared 1) + * 15 -> 16 unused (PCI shared 2) + * 16 -> 17 GBE0 (E) + * 17 -> 18 GBE1 (E) + * 18 -> 19 GBE2 (E) + * 19 -> 20 GBE3 (E) + * 20 -> 21 CPU errors + * 21 -> 22 Memory errors + * 22 -> 23 RE empty edge (E) + * 23 -> 24 RE full edge (E) + * 24 -> 25 RE idle edge (E) + * 25 -> 26 RE empty level + * 26 -> 27 RE full level + * 27 -> 28 RE idle level + * 28 -> 29 unused (software 0) (E) + * 29 -> 30 unused (software 1) (E) + * 30 -> 31 unused (software 2) - crime 1.5 CPU SysCorError (E) + * 31 -> 32 VICE + * + * S, M, A: Use the MACE ISA interrupt register + * MACE_ISA_INT_STAT 31:0 + * + * 0-7 -> 33-40 Audio + * 8 -> 41 RTC + * 9 -> 42 Keyboard + * 10 -> X Keyboard polled + * 11 -> 44 Mouse + * 12 -> X Mouse polled + * 13-15 -> 46-48 Count/compare timers + * 16-19 -> 49-52 Parallel (16 E) + * 20-25 -> 53-58 Serial 1 (22 E) + * 26-31 -> 59-64 Serial 2 (28 E) + * + * Note that this means IRQs 5-7, 43, and 45 do not exist. This is a + * different IRQ map than IRIX uses, but that's OK as Linux irq handling + * is quite different anyway. + */ + +/* Some initial interrupts to set up */ +extern void crime_memerr_intr (unsigned int irq, void *dev_id, + struct pt_regs *regs); +extern void crime_cpuerr_intr (unsigned int irq, void *dev_id, + struct pt_regs *regs); + +struct irqaction memerr_irq = { crime_memerr_intr, SA_INTERRUPT, + 0, "CRIME memory error", NULL, + NULL }; +struct irqaction cpuerr_irq = { crime_cpuerr_intr, SA_INTERRUPT, + 0, "CRIME CPU error", NULL, + NULL }; + +extern void ip32_handle_int (void); + +/* + * For interrupts wired from a single device to the CPU. Only the clock + * uses this it seems, which is IRQ 0 and IP7. + */ + +static void enable_cpu_irq(unsigned int irq) +{ + set_c0_status(STATUSF_IP7); +} + +static unsigned int startup_cpu_irq(unsigned int irq) +{ + enable_cpu_irq(irq); + return 0; +} + +static void disable_cpu_irq(unsigned int irq) +{ + clear_c0_status(STATUSF_IP7); +} + +static void end_cpu_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_cpu_irq (irq); +} + +#define shutdown_cpu_irq disable_cpu_irq +#define mask_and_ack_cpu_irq disable_cpu_irq + +static struct hw_interrupt_type ip32_cpu_interrupt = { + "IP32 CPU", + startup_cpu_irq, + shutdown_cpu_irq, + enable_cpu_irq, + disable_cpu_irq, + mask_and_ack_cpu_irq, + end_cpu_irq, + NULL +}; + +/* + * This is for pure CRIME interrupts - ie not MACE. The advantage? + * We get to split the register in half and do faster lookups. + */ + +static void enable_crime_irq(unsigned int irq) +{ + u64 crime_mask; + unsigned long flags; + + local_irq_save(flags); + crime_mask = crime_read_64(CRIME_INT_MASK); + crime_mask |= 1 << (irq - 1); + crime_write_64(CRIME_INT_MASK, crime_mask); + local_irq_restore(flags); +} + +static unsigned int startup_crime_irq(unsigned int irq) +{ + enable_crime_irq(irq); + return 0; /* This is probably not right; we could have pending irqs */ +} + +static void disable_crime_irq(unsigned int irq) +{ + u64 crime_mask; + unsigned long flags; + + local_irq_save(flags); + crime_mask = crime_read_64(CRIME_INT_MASK); + crime_mask &= ~(1 << (irq - 1)); + crime_write_64(CRIME_INT_MASK, crime_mask); + local_irq_restore(flags); +} + +static void mask_and_ack_crime_irq (unsigned int irq) +{ + u64 crime_mask; + unsigned long flags; + + /* Edge triggered interrupts must be cleared. */ + if ((irq >= CRIME_GBE0_IRQ && irq <= CRIME_GBE3_IRQ) + || (irq >= CRIME_RE_EMPTY_E_IRQ && irq <= CRIME_RE_IDLE_E_IRQ) + || (irq >= CRIME_SOFT0_IRQ && irq <= CRIME_SOFT2_IRQ)) { + local_irq_save(flags); + crime_mask = crime_read_64(CRIME_HARD_INT); + crime_mask &= ~(1 << (irq - 1)); + crime_write_64(CRIME_HARD_INT, crime_mask); + local_irq_restore(flags); + } + disable_crime_irq(irq); +} + +static void end_crime_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_crime_irq (irq); +} + +#define shutdown_crime_irq disable_crime_irq + +static struct hw_interrupt_type ip32_crime_interrupt = { + "IP32 CRIME", + startup_crime_irq, + shutdown_crime_irq, + enable_crime_irq, + disable_crime_irq, + mask_and_ack_crime_irq, + end_crime_irq, + NULL +}; + +/* + * This is for MACE PCI interrupts. We can decrease bus traffic by masking + * as close to the source as possible. This also means we can take the + * next chunk of the CRIME register in one piece. + */ + +static void enable_macepci_irq(unsigned int irq) +{ + u32 mace_mask; + u64 crime_mask; + unsigned long flags; + + local_irq_save(flags); + mace_mask = mace_read_32(MACEPCI_CONTROL); + mace_mask |= MACEPCI_CONTROL_INT(irq - 9); + mace_write_32(MACEPCI_CONTROL, mace_mask); + /* + * In case the CRIME interrupt isn't enabled, we must enable it; + * however, we never disable interrupts at that level. + */ + crime_mask = crime_read_64(CRIME_INT_MASK); + crime_mask |= 1 << (irq - 1); + crime_write_64(CRIME_INT_MASK, crime_mask); + local_irq_restore(flags); +} + +static unsigned int startup_macepci_irq(unsigned int irq) +{ + enable_macepci_irq (irq); + + return 0; /* XXX */ +} + +static void disable_macepci_irq(unsigned int irq) +{ + u32 mace_mask; + unsigned long flags; + + local_irq_save(flags); + mace_mask = mace_read_32(MACEPCI_CONTROL); + mace_mask &= ~MACEPCI_CONTROL_INT(irq - 9); + mace_write_32(MACEPCI_CONTROL, mace_mask); + local_irq_restore(flags); +} + +static void end_macepci_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_macepci_irq (irq); +} + +#define shutdown_macepci_irq disable_macepci_irq +#define mask_and_ack_macepci_irq disable_macepci_irq + +static struct hw_interrupt_type ip32_macepci_interrupt = { + "IP32 MACE PCI", + startup_macepci_irq, + shutdown_macepci_irq, + enable_macepci_irq, + disable_macepci_irq, + mask_and_ack_macepci_irq, + end_macepci_irq, + NULL +}; + +/* This is used for MACE ISA interrupts. That means bits 4-6 in the + * CRIME register. + */ + +static void enable_maceisa_irq (unsigned int irq) +{ + u64 crime_mask; + u32 mace_mask; + unsigned int crime_int = 0; + unsigned long flags; + + DBG ("maceisa enable: %u\n", irq); + + switch (irq) { + case MACEISA_AUDIO_SW_IRQ ... MACEISA_AUDIO3_MERR_IRQ: + crime_int = MACE_AUDIO_INT; + break; + case MACEISA_RTC_IRQ ... MACEISA_TIMER2_IRQ: + crime_int = MACE_MISC_INT; + break; + case MACEISA_PARALLEL_IRQ ... MACEISA_SERIAL2_RDMAOR_IRQ: + crime_int = MACE_SUPERIO_INT; + break; + } + DBG ("crime_int %016lx enabled\n", crime_int); + local_irq_save(flags); + crime_mask = crime_read_64(CRIME_INT_MASK); + crime_mask |= crime_int; + crime_write_64(CRIME_INT_MASK, crime_mask); + mace_mask = mace_read_32(MACEISA_INT_MASK); + mace_mask |= 1 << (irq - 33); + mace_write_32(MACEISA_INT_MASK, mace_mask); + local_irq_restore(flags); +} + +static unsigned int startup_maceisa_irq (unsigned int irq) +{ + enable_maceisa_irq(irq); + return 0; +} + +static void disable_maceisa_irq(unsigned int irq) +{ + u32 mace_mask; + unsigned long flags; + + local_irq_save(flags); + mace_mask = mace_read_32(MACEISA_INT_MASK); + mace_mask &= ~(1 << (irq - 33)); + mace_write_32(MACEISA_INT_MASK, mace_mask); + local_irq_restore(flags); +} + +static void mask_and_ack_maceisa_irq(unsigned int irq) +{ + u32 mace_mask; + unsigned long flags; + + switch (irq) { + case MACEISA_PARALLEL_IRQ: + case MACEISA_SERIAL1_TDMAPR_IRQ: + case MACEISA_SERIAL2_TDMAPR_IRQ: + local_irq_save(flags); + mace_mask = mace_read_32(MACEISA_INT_STAT); + mace_mask &= ~(1 << (irq - 33)); + mace_write_32(MACEISA_INT_STAT, mace_mask); + local_irq_restore(flags); + break; + } + disable_maceisa_irq(irq); +} + +static void end_maceisa_irq(unsigned irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_maceisa_irq (irq); +} + +#define shutdown_maceisa_irq disable_maceisa_irq + +static struct hw_interrupt_type ip32_maceisa_interrupt = { + "IP32 MACE ISA", + startup_maceisa_irq, + shutdown_maceisa_irq, + enable_maceisa_irq, + disable_maceisa_irq, + mask_and_ack_maceisa_irq, + end_maceisa_irq, + NULL +}; + +/* This is used for regular non-ISA, non-PCI MACE interrupts. That means + * bits 0-3 and 7 in the CRIME register. + */ + +static void enable_mace_irq(unsigned int irq) +{ + u64 crime_mask; + unsigned long flags; + + local_irq_save(flags); + crime_mask = crime_read_64 (CRIME_INT_MASK); + crime_mask |= 1 << (irq - 1); + crime_write_64 (CRIME_INT_MASK, crime_mask); + local_irq_restore (flags); +} + +static unsigned int startup_mace_irq(unsigned int irq) +{ + enable_mace_irq(irq); + return 0; +} + +static void disable_mace_irq(unsigned int irq) +{ + u64 crime_mask; + unsigned long flags; + + local_irq_save(flags); + crime_mask = crime_read_64 (CRIME_INT_MASK); + crime_mask &= ~(1 << (irq - 1)); + crime_write_64 (CRIME_INT_MASK, crime_mask); + local_irq_restore(flags); +} + +static void end_mace_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_mace_irq (irq); +} + +#define shutdown_mace_irq disable_mace_irq +#define mask_and_ack_mace_irq disable_mace_irq + +static struct hw_interrupt_type ip32_mace_interrupt = { + "IP32 MACE", + startup_mace_irq, + shutdown_mace_irq, + enable_mace_irq, + disable_mace_irq, + mask_and_ack_mace_irq, + end_mace_irq, + NULL +}; + +static void ip32_unknown_interrupt (struct pt_regs *regs) +{ + u64 crime; + u32 mace; + + printk ("Unknown interrupt occurred!\n"); + printk ("cp0_status: %08x\tcp0_cause: %08x\n", + read_c0_status(), + read_c0_cause()); + crime = crime_read_64 (CRIME_INT_MASK); + printk ("CRIME interrupt mask: %016lx\n", crime); + crime = crime_read_64 (CRIME_INT_STAT); + printk ("CRIME interrupt status: %016lx\n", crime); + crime = crime_read_64 (CRIME_HARD_INT); + printk ("CRIME hardware interrupt register: %016lx\n", crime); + mace = mace_read_32 (MACEISA_INT_MASK); + printk ("MACE ISA interrupt mask: %08x\n", mace); + mace = mace_read_32 (MACEISA_INT_STAT); + printk ("MACE ISA interrupt status: %08x\n", mace); + mace = mace_read_32 (MACEPCI_CONTROL); + printk ("MACE PCI control register: %08x\n", mace); + + printk("Register dump:\n"); + show_regs(regs); + + printk("Please mail this report to linux-mips@oss.sgi.com\n"); + printk("Spinning..."); + while(1) ; +} + +/* CRIME 1.1 appears to deliver all interrupts to this one pin. */ +void ip32_irq0(struct pt_regs *regs) +{ + u64 crime_int; + u64 crime_mask; + int irq = 0; + unsigned long flags; + + local_irq_save(flags); + /* disable crime interrupts */ + crime_mask = crime_read_64(CRIME_INT_MASK); + crime_write_64(CRIME_INT_MASK, 0); + + crime_int = crime_read_64(CRIME_INT_STAT); + + if (crime_int & CRIME_MACE_INT_MASK) { + crime_int &= CRIME_MACE_INT_MASK; + irq = ffs (crime_int); + } else if (crime_int & CRIME_MACEISA_INT_MASK) { + u32 mace_int; + mace_int = mace_read_32 (MACEISA_INT_STAT); + if (mace_int == 0) + irq = 0; + else + irq = ffs (mace_int) + 32; + } else if (crime_int & CRIME_MACEPCI_INT_MASK) { + crime_int &= CRIME_MACEPCI_INT_MASK; + crime_int >>= 8; + irq = ffs (crime_int) + 8; + } else if (crime_int & 0xffff0000) { + crime_int >>= 16; + irq = ffs (crime_int) + 16; + } + if (irq == 0) + ip32_unknown_interrupt(regs); + DBG("*irq %u*\n", irq); + do_IRQ(irq, regs); + + /* enable crime interrupts */ + crime_write_64(CRIME_INT_MASK, crime_mask); + local_irq_restore (flags); +} + +void ip32_irq1(struct pt_regs *regs) +{ + ip32_unknown_interrupt (regs); +} + +void ip32_irq2(struct pt_regs *regs) +{ + ip32_unknown_interrupt (regs); +} + +void ip32_irq3(struct pt_regs *regs) +{ + ip32_unknown_interrupt (regs); +} + +void ip32_irq4(struct pt_regs *regs) +{ + ip32_unknown_interrupt (regs); +} + +void ip32_irq5(struct pt_regs *regs) +{ + do_IRQ (CLOCK_IRQ, regs); +} + +void __init init_IRQ(void) +{ + unsigned int irq; + int i; + + /* Install our interrupt handler, then clear and disable all + * CRIME and MACE interrupts. + */ + crime_write_64(CRIME_INT_MASK, 0); + crime_write_64(CRIME_HARD_INT, 0); + crime_write_64(CRIME_SOFT_INT, 0); + mace_write_32(MACEISA_INT_STAT, 0); + mace_write_32(MACEISA_INT_MASK, 0); + set_except_vector(0, ip32_handle_int); + + for (i = 0; i < NR_IRQS; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = NULL; + irq_desc[i].depth = 1; + irq_desc[i].handler = &no_irq_type; + } + + for (irq = 0; irq <= IP32_IRQ_MAX; irq++) { + hw_irq_controller *controller; + + if (irq == CLOCK_IRQ) + controller = &ip32_cpu_interrupt; + else if (irq <= MACE_PCI_BRIDGE_IRQ && irq >= MACE_VID_IN1_IRQ) + controller = &ip32_mace_interrupt; + else if (irq <= MACEPCI_SHARED2_IRQ && irq >= MACEPCI_SCSI0_IRQ) + controller = &ip32_macepci_interrupt; + else if (irq <= CRIME_VICE_IRQ && irq >= CRIME_GBE0_IRQ) + controller = &ip32_crime_interrupt; + else + controller = &ip32_maceisa_interrupt; + + irq_desc[irq].status = IRQ_DISABLED; + irq_desc[irq].action = 0; + irq_desc[irq].depth = 0; + irq_desc[irq].handler = controller; + } + setup_irq(CRIME_MEMERR_IRQ, &memerr_irq); + setup_irq(CRIME_CPUERR_IRQ, &cpuerr_irq); +} diff -Nru a/arch/mips/sgi-ip32/ip32-reset.c b/arch/mips/sgi-ip32/ip32-reset.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sgi-ip32/ip32-reset.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,208 @@ +/* + * 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) 2001 Keith M Wesolowski + * Copyright (C) 2001 Paul Mundt + * Copyright (C) 2003 Guido Guenther + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#define POWERDOWN_TIMEOUT 120 +/* + * Blink frequency during reboot grace period and when paniced. + */ +#define POWERDOWN_FREQ (HZ / 4) +#define PANIC_FREQ (HZ / 8) + +static struct timer_list power_timer, blink_timer, debounce_timer; +static int shuting_down = 0, has_paniced = 0; + +static void ip32_machine_restart(char *command) __attribute__((noreturn)); +static void ip32_machine_halt(void) __attribute__((noreturn)); +static void ip32_machine_power_off(void) __attribute__((noreturn)); + +static void ip32_machine_restart(char *cmd) +{ + if (shuting_down) + ip32_machine_power_off(); + ArcReboot(); +} + +static inline void ip32_machine_halt(void) +{ + if (shuting_down) + ip32_machine_power_off(); + ArcEnterInteractiveMode(); +} + +static void ip32_machine_power_off(void) +{ + volatile unsigned char reg_a, xctrl_a, xctrl_b; + + disable_irq(MACEISA_RTC_IRQ); + reg_a = CMOS_READ(RTC_REG_A); + + /* setup for kickstart & wake-up (DS12287 Ref. Man. p. 19) */ + reg_a &= ~DS_REGA_DV2; + reg_a |= DS_REGA_DV1; + + CMOS_WRITE(reg_a | DS_REGA_DV0, RTC_REG_A); + wbflush(); + xctrl_b = CMOS_READ(DS_B1_XCTRL4B) + | DS_XCTRL4B_ABE | DS_XCTRL4B_KFE; + CMOS_WRITE(xctrl_b, DS_B1_XCTRL4B); + xctrl_a = CMOS_READ(DS_B1_XCTRL4A) & ~DS_XCTRL4A_IFS; + CMOS_WRITE(xctrl_a, DS_B1_XCTRL4A); + wbflush(); + /* adios amigos... */ + CMOS_WRITE(xctrl_a | DS_XCTRL4A_PAB, DS_B1_XCTRL4A); + CMOS_WRITE(reg_a, RTC_REG_A); + wbflush(); + + while(1) { + printk(KERN_DEBUG "Power off!\n"); + } +} + +static void power_timeout(unsigned long data) +{ + ip32_machine_power_off(); +} + +static void blink_timeout(unsigned long data) +{ + u64 mc_led = mace_read_64(MACEISA_FLASH_NIC_REG); + + mc_led ^= MACEISA_LED_RED; + mace_write_64(MACEISA_FLASH_NIC_REG, mc_led); + mod_timer(&blink_timer, jiffies+data); +} + +static void debounce(unsigned long data) +{ + volatile unsigned char reg_a,reg_c,xctrl_a; + + reg_c = CMOS_READ(RTC_INTR_FLAGS); + CMOS_WRITE(reg_a | DS_REGA_DV0, RTC_REG_A); + wbflush(); + xctrl_a = CMOS_READ(DS_B1_XCTRL4A); + if( (xctrl_a & DS_XCTRL4A_IFS ) || ( reg_c & RTC_IRQF ) ) { + /* Interrupt still being sent. */ + debounce_timer.expires = jiffies + 50; + add_timer(&debounce_timer); + + /* clear interrupt source */ + CMOS_WRITE( xctrl_a & ~DS_XCTRL4A_IFS, DS_B1_XCTRL4A); + CMOS_WRITE(reg_a & ~DS_REGA_DV0, RTC_REG_A); + return; + } + CMOS_WRITE(reg_a & ~DS_REGA_DV0, RTC_REG_A); + + if (has_paniced) + ArcReboot(); + + enable_irq(MACEISA_RTC_IRQ); +} + +static inline void ip32_power_button(void) +{ + if (has_paniced) + return; + + if (shuting_down || kill_proc(1, SIGINT, 1)) { + /* No init process or button pressed twice. */ + ip32_machine_power_off(); + } + + shuting_down = 1; + blink_timer.data = POWERDOWN_FREQ; + blink_timeout(POWERDOWN_FREQ); + + init_timer(&power_timer); + power_timer.function = power_timeout; + power_timer.expires = jiffies + POWERDOWN_TIMEOUT * HZ; + add_timer(&power_timer); +} + +static void ip32_rtc_int(int irq, void *dev_id, struct pt_regs *regs) +{ + volatile unsigned char reg_c; + + reg_c = CMOS_READ(RTC_INTR_FLAGS); + if( ! (reg_c & RTC_IRQF) ) { + printk(KERN_WARNING + "%s: RTC IRQ without RTC_IRQF\n", __FUNCTION__); + } + /* Wait until interrupt goes away */ + disable_irq(MACEISA_RTC_IRQ); + init_timer(&debounce_timer); + debounce_timer.function = debounce; + debounce_timer.expires = jiffies + 50; + add_timer(&debounce_timer); + + printk(KERN_DEBUG "Power button pressed\n"); + ip32_power_button(); +} + +static int panic_event(struct notifier_block *this, unsigned long event, + void *ptr) +{ + u64 mc_led; + + if (has_paniced) + return NOTIFY_DONE; + has_paniced = 1; + + /* turn off the green LED */ + mc_led = mace_read_64(MACEISA_FLASH_NIC_REG); + mc_led |= MACEISA_LED_GREEN; + mace_write_64(MACEISA_FLASH_NIC_REG, mc_led); + + blink_timer.data = PANIC_FREQ; + blink_timeout(PANIC_FREQ); + + return NOTIFY_DONE; +} + +static struct notifier_block panic_block = { + .notifier_call = panic_event, +}; + +static __init int ip32_reboot_setup(void) +{ + u64 mc_led = mace_read_64(MACEISA_FLASH_NIC_REG); + + _machine_restart = ip32_machine_restart; + _machine_halt = ip32_machine_halt; + _machine_power_off = ip32_machine_power_off; + request_irq(MACEISA_RTC_IRQ, ip32_rtc_int, 0, "rtc", NULL); + init_timer(&blink_timer); + blink_timer.function = blink_timeout; + notifier_chain_register(&panic_notifier_list, &panic_block); + + /* turn on the green led only */ + mc_led |= MACEISA_LED_RED; + mc_led &= ~MACEISA_LED_GREEN; + mace_write_64(MACEISA_FLASH_NIC_REG, mc_led); + + return 0; +} + +subsys_initcall(ip32_reboot_setup); diff -Nru a/arch/mips/sgi-ip32/ip32-rtc.c b/arch/mips/sgi-ip32/ip32-rtc.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sgi-ip32/ip32-rtc.c Tue Jul 1 18:44:36 2003 @@ -0,0 +1,32 @@ +/* + * RTC routines for IP32 style attached Dallas chip. + * + * 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) 2000 Harald Koerfgen + */ +#include +#include + +static unsigned char ip32_rtc_read_data(unsigned long addr) +{ + return (unsigned char) mace_read_8 (MACEISA_RTC_BASE + (addr << 8)); +} + +static void ip32_rtc_write_data(unsigned char data, unsigned long addr) +{ + mace_write_8 (MACEISA_RTC_BASE + (addr << 8), data); +} + +static int ip32_rtc_bcd_mode(void) +{ + return 0; +} + +struct rtc_ops ip32_rtc_ops = { + &ip32_rtc_read_data, + &ip32_rtc_write_data, + &ip32_rtc_bcd_mode +}; diff -Nru a/arch/mips/sgi-ip32/ip32-setup.c b/arch/mips/sgi-ip32/ip32-setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sgi-ip32/ip32-setup.c Tue Jul 1 18:44:37 2003 @@ -0,0 +1,105 @@ +/* + * IP32 basic setup + * + * 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) 2000 Harald Koerfgen + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern struct rtc_ops ip32_rtc_ops; +extern u32 cc_interval; + +#ifdef CONFIG_SGI_O2MACE_ETH + +/* + * This is taken care of in here 'cause they say using Arc later on is + * problematic + */ +extern char o2meth_eaddr[8]; +static inline unsigned char str2hexnum(unsigned char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + return 0; /* foo */ +} + +static inline void str2eaddr(unsigned char *ea, unsigned char *str) +{ + int i; + + for (i = 0; i < 6; i++) { + unsigned char num; + + if(*str == ':') + str++; + num = str2hexnum(*str++) << 4; + num |= (str2hexnum(*str++)); + ea[i] = num; + } +} +#endif + +extern void ip32_time_init(void); +extern void ip32_reboot_setup(void); + +void __init ip32_setup(void) +{ +#ifdef CONFIG_SERIAL_CONSOLE + char *ctype; +#endif + TLBMISS_HANDLER_SETUP (); + + mips_io_port_base = UNCACHEDADDR(MACEPCI_HI_IO);; + +#ifdef CONFIG_SERIAL_CONSOLE + ctype = ArcGetEnvironmentVariable("console"); + if (*ctype == 'd') { + if (ctype[1] == '2') + console_setup ("ttyS1"); + else + console_setup ("ttyS0"); + } +#endif +#ifdef CONFIG_SGI_O2MACE_ETH + { + char *mac=ArcGetEnvironmentVariable("eaddr"); + str2eaddr(o2meth_eaddr, mac); + } +#endif + +#ifdef CONFIG_VT + conswitchp = &dummy_con; +#endif + + rtc_ops = &ip32_rtc_ops; + board_be_init = ip32_be_init; + board_time_init = ip32_time_init; + + crime_init (); +} + +int __init page_is_ram (unsigned long pagenr) +{ + /* XXX: to do? */ + return 1; +} diff -Nru a/arch/mips/sgi-ip32/ip32-timer.c b/arch/mips/sgi-ip32/ip32-timer.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sgi-ip32/ip32-timer.c Tue Jul 1 18:44:37 2003 @@ -0,0 +1,238 @@ +/* + * IP32 timer calibration + * + * 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) 2001 Keith M Wesolowski + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern volatile unsigned long wall_jiffies; + +u32 cc_interval; + +/* Cycle counter value at the previous timer interrupt.. */ +static unsigned int timerhi, timerlo; + +/* An arbitrary time; this can be decreased if reliability looks good */ +#define WAIT_MS 10 +#define PER_MHZ (1000000 / 2 / HZ) +/* + * Change this if you have some constant time drift + */ +#define USECS_PER_JIFFY (1000000/HZ) + + +void __init ip32_timer_setup (struct irqaction *irq) +{ + u64 crime_time; + u32 cc_tick; + + printk("Calibrating system timer... "); + + crime_time = crime_read_64 (CRIME_TIME) & CRIME_TIME_MASK; + cc_tick = read_c0_count(); + + while ((crime_read_64 (CRIME_TIME) & CRIME_TIME_MASK) - crime_time + < WAIT_MS * 1000000 / CRIME_NS_PER_TICK) + ; + cc_tick = read_c0_count() - cc_tick; + cc_interval = cc_tick / HZ * (1000 / WAIT_MS); + /* The round-off seems unnecessary; in testing, the error of the + * above procedure is < 100 ticks, which means it gets filtered + * out by the HZ adjustment. + */ + cc_interval = (cc_interval / PER_MHZ) * PER_MHZ; + + printk("%d MHz CPU detected\n", (int) (cc_interval / PER_MHZ)); + + setup_irq (CLOCK_IRQ, irq); +} + +struct irqaction irq0 = { NULL, SA_INTERRUPT, 0, + "timer", NULL, NULL}; + +void cc_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) +{ + u32 count; + + /* + * The cycle counter is only 32 bit which is good for about + * a minute at current count rates of upto 150MHz or so. + */ + count = read_c0_count(); + timerhi += (count < timerlo); /* Wrap around */ + timerlo = count; + + write_c0_compare( + (u32) (count + cc_interval)); + kstat_cpu(0).irqs[irq]++; + do_timer (regs); + + if (!jiffies) + { + /* + * If jiffies has overflowed in this timer_interrupt we must + * update the timer[hi]/[lo] to make do_fast_gettimeoffset() + * quotient calc still valid. -arca + */ + timerhi = timerlo = 0; + } +} + +/* + * On MIPS only R4000 and better have a cycle counter. + * + * FIXME: Does playing with the RP bit in c0_status interfere with this code? + */ +static unsigned long do_gettimeoffset(void) +{ + u32 count; + unsigned long res, tmp; + + /* Last jiffy when do_fast_gettimeoffset() was called. */ + static unsigned long last_jiffies; + u32 quotient; + + /* + * Cached "1/(clocks per usec)*2^32" value. + * It has to be recalculated once each jiffy. + */ + static u32 cached_quotient; + + tmp = jiffies; + + quotient = cached_quotient; + + if (tmp && last_jiffies != tmp) { + last_jiffies = tmp; + __asm__(".set\tnoreorder\n\t" + ".set\tnoat\n\t" + ".set\tmips3\n\t" + "lwu\t%0,%2\n\t" + "dsll32\t$1,%1,0\n\t" + "or\t$1,$1,%0\n\t" + "ddivu\t$0,$1,%3\n\t" + "mflo\t$1\n\t" + "dsll32\t%0,%4,0\n\t" + "nop\n\t" + "ddivu\t$0,%0,$1\n\t" + "mflo\t%0\n\t" + ".set\tmips0\n\t" + ".set\tat\n\t" + ".set\treorder" + :"=&r" (quotient) + :"r" (timerhi), + "m" (timerlo), + "r" (tmp), + "r" (USECS_PER_JIFFY) + :"$1"); + cached_quotient = quotient; + } + + /* Get last timer tick in absolute kernel time */ + count = read_c0_count(); + + /* .. relative to previous jiffy (32 bits is enough) */ + count -= timerlo; + + __asm__("multu\t%1,%2\n\t" + "mfhi\t%0" + :"=r" (res) + :"r" (count), + "r" (quotient)); + + /* + * Due to possible jiffies inconsistencies, we need to check + * the result so that we'll get a timer that is monotonic. + */ + if (res >= USECS_PER_JIFFY) + res = USECS_PER_JIFFY-1; + + return res; +} + +void __init ip32_time_init(void) +{ + unsigned int epoch = 0, year, mon, day, hour, min, sec; + int i; + + /* The Linux interpretation of the CMOS clock register contents: + * When the Update-In-Progress (UIP) flag goes from 1 to 0, the + * RTC registers show the second which has precisely just started. + * Let's hope other operating systems interpret the RTC the same way. + */ + /* read RTC exactly on falling edge of update flag */ + for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */ + if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) + break; + for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */ + if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) + break; + do { /* Isn't this overkill ? UIP above should guarantee consistency */ + sec = CMOS_READ(RTC_SECONDS); + min = CMOS_READ(RTC_MINUTES); + hour = CMOS_READ(RTC_HOURS); + day = CMOS_READ(RTC_DAY_OF_MONTH); + mon = CMOS_READ(RTC_MONTH); + year = CMOS_READ(RTC_YEAR); + } while (sec != CMOS_READ(RTC_SECONDS)); + if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { + sec = BCD2BIN(sec); + min = BCD2BIN(min); + hour = BCD2BIN(hour); + day = BCD2BIN(day); + mon = BCD2BIN(mon); + year = BCD2BIN(year); + } + + /* Attempt to guess the epoch. This is the same heuristic as in + * rtc.c so no stupid things will happen to timekeeping. Who knows, + * maybe Ultrix also uses 1952 as epoch ... + */ + if (year > 10 && year < 44) + epoch = 1980; + else if (year < 96) + epoch = 1952; + year += epoch; + + write_seqlock_irq(&xtime_lock); + xtime.tv_sec = mktime(year, mon, day, hour, min, sec); + xtime.tv_nsec = 0; + write_sequnlock_irq(&xtime_lock); + + write_c0_count(0); + irq0.handler = cc_timer_interrupt; + + ip32_timer_setup (&irq0); + +#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5) + /* Set ourselves up for future interrupts */ + write_c0_compare( + read_c0_count() + + cc_interval); + change_c0_status(ST0_IM, ALLINTS); + sti (); +} diff -Nru a/arch/mips/sibyte/cfe/Makefile b/arch/mips/sibyte/cfe/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sibyte/cfe/Makefile Tue Jul 1 18:44:40 2003 @@ -0,0 +1,3 @@ +lib-y = cfe_api.o setup.o +lib-$(CONFIG_SMP) += smp.o +lib-$(CONFIG_SIBYTE_CFE_CONSOLE) += console.o diff -Nru a/arch/mips/sibyte/cfe/cfe_api.c b/arch/mips/sibyte/cfe/cfe_api.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sibyte/cfe/cfe_api.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,502 @@ +/* + * Copyright (C) 2000, 2001, 2002 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* ********************************************************************* + * + * Broadcom Common Firmware Environment (CFE) + * + * Device Function stubs File: cfe_api.c + * + * This module contains device function stubs (small routines to + * call the standard "iocb" interface entry point to CFE). + * There should be one routine here per iocb function call. + * + * Authors: Mitch Lichtenberg, Chris Demetriou + * + ********************************************************************* */ + +#include "cfe_api.h" +#include "cfe_api_int.h" + +/* Cast from a native pointer to a cfe_xptr_t and back. */ +#define XPTR_FROM_NATIVE(n) ((cfe_xptr_t) (intptr_t) (n)) +#define NATIVE_FROM_XPTR(x) ((void *) (intptr_t) (x)) + +#ifdef CFE_API_IMPL_NAMESPACE +#define cfe_iocb_dispatch(a) __cfe_iocb_dispatch(a) +#endif +int cfe_iocb_dispatch(cfe_xiocb_t * xiocb); + +#if defined(CFE_API_common) || defined(CFE_API_ALL) +/* + * Declare the dispatch function with args of "intptr_t". + * This makes sure whatever model we're compiling in + * puts the pointers in a single register. For example, + * combining -mlong64 and -mips1 or -mips2 would lead to + * trouble, since the handle and IOCB pointer will be + * passed in two registers each, and CFE expects one. + */ + +static int (*cfe_dispfunc) (intptr_t handle, intptr_t xiocb) = 0; +static cfe_xuint_t cfe_handle = 0; + +int cfe_init(cfe_xuint_t handle, cfe_xuint_t ept) +{ + cfe_dispfunc = NATIVE_FROM_XPTR(ept); + cfe_handle = handle; + return 0; +} + +int cfe_iocb_dispatch(cfe_xiocb_t * xiocb) +{ + if (!cfe_dispfunc) + return -1; + return (*cfe_dispfunc) ((intptr_t) cfe_handle, (intptr_t) xiocb); +} +#endif /* CFE_API_common || CFE_API_ALL */ + +#if defined(CFE_API_close) || defined(CFE_API_ALL) +int cfe_close(int handle) +{ + cfe_xiocb_t xiocb; + + xiocb.xiocb_fcode = CFE_CMD_DEV_CLOSE; + xiocb.xiocb_status = 0; + xiocb.xiocb_handle = handle; + xiocb.xiocb_flags = 0; + xiocb.xiocb_psize = 0; + + cfe_iocb_dispatch(&xiocb); + + return xiocb.xiocb_status; + +} +#endif /* CFE_API_close || CFE_API_ALL */ + +#if defined(CFE_API_cpu_start) || defined(CFE_API_ALL) +int cfe_cpu_start(int cpu, void (*fn) (void), long sp, long gp, long a1) +{ + cfe_xiocb_t xiocb; + + xiocb.xiocb_fcode = CFE_CMD_FW_CPUCTL; + xiocb.xiocb_status = 0; + xiocb.xiocb_handle = 0; + xiocb.xiocb_flags = 0; + xiocb.xiocb_psize = sizeof(xiocb_cpuctl_t); + xiocb.plist.xiocb_cpuctl.cpu_number = cpu; + xiocb.plist.xiocb_cpuctl.cpu_command = CFE_CPU_CMD_START; + xiocb.plist.xiocb_cpuctl.gp_val = gp; + xiocb.plist.xiocb_cpuctl.sp_val = sp; + xiocb.plist.xiocb_cpuctl.a1_val = a1; + xiocb.plist.xiocb_cpuctl.start_addr = (long) fn; + + cfe_iocb_dispatch(&xiocb); + + return xiocb.xiocb_status; +} +#endif /* CFE_API_cpu_start || CFE_API_ALL */ + +#if defined(CFE_API_cpu_stop) || defined(CFE_API_ALL) +int cfe_cpu_stop(int cpu) +{ + cfe_xiocb_t xiocb; + + xiocb.xiocb_fcode = CFE_CMD_FW_CPUCTL; + xiocb.xiocb_status = 0; + xiocb.xiocb_handle = 0; + xiocb.xiocb_flags = 0; + xiocb.xiocb_psize = sizeof(xiocb_cpuctl_t); + xiocb.plist.xiocb_cpuctl.cpu_number = cpu; + xiocb.plist.xiocb_cpuctl.cpu_command = CFE_CPU_CMD_STOP; + + cfe_iocb_dispatch(&xiocb); + + return xiocb.xiocb_status; +} +#endif /* CFE_API_cpu_stop || CFE_API_ALL */ + +#if defined(CFE_API_enumenv) || defined(CFE_API_ALL) +int cfe_enumenv(int idx, char *name, int namelen, char *val, int vallen) +{ + cfe_xiocb_t xiocb; + + xiocb.xiocb_fcode = CFE_CMD_ENV_SET; + xiocb.xiocb_status = 0; + xiocb.xiocb_handle = 0; + xiocb.xiocb_flags = 0; + xiocb.xiocb_psize = sizeof(xiocb_envbuf_t); + xiocb.plist.xiocb_envbuf.enum_idx = idx; + xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name); + xiocb.plist.xiocb_envbuf.name_length = namelen; + xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(val); + xiocb.plist.xiocb_envbuf.val_length = vallen; + + cfe_iocb_dispatch(&xiocb); + + return xiocb.xiocb_status; +} +#endif /* CFE_API_enumenv || CFE_API_ALL */ + +#if defined(CFE_API_enummem) || defined(CFE_API_ALL) +int +cfe_enummem(int idx, int flags, cfe_xuint_t * start, cfe_xuint_t * length, + cfe_xuint_t * type) +{ + cfe_xiocb_t xiocb; + + xiocb.xiocb_fcode = CFE_CMD_FW_MEMENUM; + xiocb.xiocb_status = 0; + xiocb.xiocb_handle = 0; + xiocb.xiocb_flags = flags; + xiocb.xiocb_psize = sizeof(xiocb_meminfo_t); + xiocb.plist.xiocb_meminfo.mi_idx = idx; + + cfe_iocb_dispatch(&xiocb); + + if (xiocb.xiocb_status < 0) + return xiocb.xiocb_status; + + *start = xiocb.plist.xiocb_meminfo.mi_addr; + *length = xiocb.plist.xiocb_meminfo.mi_size; + *type = xiocb.plist.xiocb_meminfo.mi_type; + + return 0; +} +#endif /* CFE_API_enummem || CFE_API_ALL */ + +#if defined(CFE_API_exit) || defined(CFE_API_ALL) +int cfe_exit(int warm, int status) +{ + cfe_xiocb_t xiocb; + + xiocb.xiocb_fcode = CFE_CMD_FW_RESTART; + xiocb.xiocb_status = 0; + xiocb.xiocb_handle = 0; + xiocb.xiocb_flags = warm ? CFE_FLG_WARMSTART : 0; + xiocb.xiocb_psize = sizeof(xiocb_exitstat_t); + xiocb.plist.xiocb_exitstat.status = status; + + cfe_iocb_dispatch(&xiocb); + + return xiocb.xiocb_status; +} +#endif /* CFE_API_exit || CFE_API_ALL */ + +#if defined(CFE_API_flushcache) || defined(CFE_API_ALL) +int cfe_flushcache(int flg) +{ + cfe_xiocb_t xiocb; + + xiocb.xiocb_fcode = CFE_CMD_FW_FLUSHCACHE; + xiocb.xiocb_status = 0; + xiocb.xiocb_handle = 0; + xiocb.xiocb_flags = flg; + xiocb.xiocb_psize = 0; + + cfe_iocb_dispatch(&xiocb); + + return xiocb.xiocb_status; +} +#endif /* CFE_API_flushcache || CFE_API_ALL */ + +#if defined(CFE_API_getdevinfo) || defined(CFE_API_ALL) +int cfe_getdevinfo(char *name) +{ + cfe_xiocb_t xiocb; + + xiocb.xiocb_fcode = CFE_CMD_DEV_GETINFO; + xiocb.xiocb_status = 0; + xiocb.xiocb_handle = 0; + xiocb.xiocb_flags = 0; + xiocb.xiocb_psize = sizeof(xiocb_buffer_t); + xiocb.plist.xiocb_buffer.buf_offset = 0; + xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(name); + xiocb.plist.xiocb_buffer.buf_length = cfe_strlen(name); + + cfe_iocb_dispatch(&xiocb); + + if (xiocb.xiocb_status < 0) + return xiocb.xiocb_status; + return xiocb.plist.xiocb_buffer.buf_devflags; +} +#endif /* CFE_API_getdevinfo || CFE_API_ALL */ + +#if defined(CFE_API_getenv) || defined(CFE_API_ALL) +int cfe_getenv(char *name, char *dest, int destlen) +{ + cfe_xiocb_t xiocb; + + *dest = 0; + + xiocb.xiocb_fcode = CFE_CMD_ENV_GET; + xiocb.xiocb_status = 0; + xiocb.xiocb_handle = 0; + xiocb.xiocb_flags = 0; + xiocb.xiocb_psize = sizeof(xiocb_envbuf_t); + xiocb.plist.xiocb_envbuf.enum_idx = 0; + xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name); + xiocb.plist.xiocb_envbuf.name_length = cfe_strlen(name); + xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(dest); + xiocb.plist.xiocb_envbuf.val_length = destlen; + + cfe_iocb_dispatch(&xiocb); + + return xiocb.xiocb_status; +} +#endif /* CFE_API_getenv || CFE_API_ALL */ + +#if defined(CFE_API_getfwinfo) || defined(CFE_API_ALL) +int cfe_getfwinfo(cfe_fwinfo_t * info) +{ + cfe_xiocb_t xiocb; + + xiocb.xiocb_fcode = CFE_CMD_FW_GETINFO; + xiocb.xiocb_status = 0; + xiocb.xiocb_handle = 0; + xiocb.xiocb_flags = 0; + xiocb.xiocb_psize = sizeof(xiocb_fwinfo_t); + + cfe_iocb_dispatch(&xiocb); + + if (xiocb.xiocb_status < 0) + return xiocb.xiocb_status; + + info->fwi_version = xiocb.plist.xiocb_fwinfo.fwi_version; + info->fwi_totalmem = xiocb.plist.xiocb_fwinfo.fwi_totalmem; + info->fwi_flags = xiocb.plist.xiocb_fwinfo.fwi_flags; + info->fwi_boardid = xiocb.plist.xiocb_fwinfo.fwi_boardid; + info->fwi_bootarea_va = xiocb.plist.xiocb_fwinfo.fwi_bootarea_va; + info->fwi_bootarea_pa = xiocb.plist.xiocb_fwinfo.fwi_bootarea_pa; + info->fwi_bootarea_size = + xiocb.plist.xiocb_fwinfo.fwi_bootarea_size; +#if 0 + info->fwi_reserved1 = xiocb.plist.xiocb_fwinfo.fwi_reserved1; + info->fwi_reserved2 = xiocb.plist.xiocb_fwinfo.fwi_reserved2; + info->fwi_reserved3 = xiocb.plist.xiocb_fwinfo.fwi_reserved3; +#endif + + return 0; +} +#endif /* CFE_API_getfwinfo || CFE_API_ALL */ + +#if defined(CFE_API_getstdhandle) || defined(CFE_API_ALL) +int cfe_getstdhandle(int flg) +{ + cfe_xiocb_t xiocb; + + xiocb.xiocb_fcode = CFE_CMD_DEV_GETHANDLE; + xiocb.xiocb_status = 0; + xiocb.xiocb_handle = 0; + xiocb.xiocb_flags = flg; + xiocb.xiocb_psize = 0; + + cfe_iocb_dispatch(&xiocb); + + if (xiocb.xiocb_status < 0) + return xiocb.xiocb_status; + return xiocb.xiocb_handle; +} +#endif /* CFE_API_getstdhandle || CFE_API_ALL */ + +#if defined(CFE_API_getticks) || defined(CFE_API_ALL) +int64_t +#ifdef CFE_API_IMPL_NAMESPACE +__cfe_getticks(void) +#else +cfe_getticks(void) +#endif +{ + cfe_xiocb_t xiocb; + + xiocb.xiocb_fcode = CFE_CMD_FW_GETTIME; + xiocb.xiocb_status = 0; + xiocb.xiocb_handle = 0; + xiocb.xiocb_flags = 0; + xiocb.xiocb_psize = sizeof(xiocb_time_t); + xiocb.plist.xiocb_time.ticks = 0; + + cfe_iocb_dispatch(&xiocb); + + return xiocb.plist.xiocb_time.ticks; + +} +#endif /* CFE_API_getticks || CFE_API_ALL */ + +#if defined(CFE_API_inpstat) || defined(CFE_API_ALL) +int cfe_inpstat(int handle) +{ + cfe_xiocb_t xiocb; + + xiocb.xiocb_fcode = CFE_CMD_DEV_INPSTAT; + xiocb.xiocb_status = 0; + xiocb.xiocb_handle = handle; + xiocb.xiocb_flags = 0; + xiocb.xiocb_psize = sizeof(xiocb_inpstat_t); + xiocb.plist.xiocb_inpstat.inp_status = 0; + + cfe_iocb_dispatch(&xiocb); + + if (xiocb.xiocb_status < 0) + return xiocb.xiocb_status; + return xiocb.plist.xiocb_inpstat.inp_status; +} +#endif /* CFE_API_inpstat || CFE_API_ALL */ + +#if defined(CFE_API_ioctl) || defined(CFE_API_ALL) +int +cfe_ioctl(int handle, unsigned int ioctlnum, unsigned char *buffer, + int length, int *retlen, cfe_xuint_t offset) +{ + cfe_xiocb_t xiocb; + + xiocb.xiocb_fcode = CFE_CMD_DEV_IOCTL; + xiocb.xiocb_status = 0; + xiocb.xiocb_handle = handle; + xiocb.xiocb_flags = 0; + xiocb.xiocb_psize = sizeof(xiocb_buffer_t); + xiocb.plist.xiocb_buffer.buf_offset = offset; + xiocb.plist.xiocb_buffer.buf_ioctlcmd = ioctlnum; + xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer); + xiocb.plist.xiocb_buffer.buf_length = length; + + cfe_iocb_dispatch(&xiocb); + + if (retlen) + *retlen = xiocb.plist.xiocb_buffer.buf_retlen; + return xiocb.xiocb_status; +} +#endif /* CFE_API_ioctl || CFE_API_ALL */ + +#if defined(CFE_API_open) || defined(CFE_API_ALL) +int cfe_open(char *name) +{ + cfe_xiocb_t xiocb; + + xiocb.xiocb_fcode = CFE_CMD_DEV_OPEN; + xiocb.xiocb_status = 0; + xiocb.xiocb_handle = 0; + xiocb.xiocb_flags = 0; + xiocb.xiocb_psize = sizeof(xiocb_buffer_t); + xiocb.plist.xiocb_buffer.buf_offset = 0; + xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(name); + xiocb.plist.xiocb_buffer.buf_length = cfe_strlen(name); + + cfe_iocb_dispatch(&xiocb); + + if (xiocb.xiocb_status < 0) + return xiocb.xiocb_status; + return xiocb.xiocb_handle; +} +#endif /* CFE_API_open || CFE_API_ALL */ + +#if defined(CFE_API_read) || defined(CFE_API_ALL) +int cfe_read(int handle, unsigned char *buffer, int length) +{ + return cfe_readblk(handle, 0, buffer, length); +} +#endif /* CFE_API_read || CFE_API_ALL */ + +#if defined(CFE_API_readblk) || defined(CFE_API_ALL) +int +cfe_readblk(int handle, cfe_xint_t offset, unsigned char *buffer, + int length) +{ + cfe_xiocb_t xiocb; + + xiocb.xiocb_fcode = CFE_CMD_DEV_READ; + xiocb.xiocb_status = 0; + xiocb.xiocb_handle = handle; + xiocb.xiocb_flags = 0; + xiocb.xiocb_psize = sizeof(xiocb_buffer_t); + xiocb.plist.xiocb_buffer.buf_offset = offset; + xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer); + xiocb.plist.xiocb_buffer.buf_length = length; + + cfe_iocb_dispatch(&xiocb); + + if (xiocb.xiocb_status < 0) + return xiocb.xiocb_status; + return xiocb.plist.xiocb_buffer.buf_retlen; +} +#endif /* CFE_API_readblk || CFE_API_ALL */ + +#if defined(CFE_API_setenv) || defined(CFE_API_ALL) +int cfe_setenv(char *name, char *val) +{ + cfe_xiocb_t xiocb; + + xiocb.xiocb_fcode = CFE_CMD_ENV_SET; + xiocb.xiocb_status = 0; + xiocb.xiocb_handle = 0; + xiocb.xiocb_flags = 0; + xiocb.xiocb_psize = sizeof(xiocb_envbuf_t); + xiocb.plist.xiocb_envbuf.enum_idx = 0; + xiocb.plist.xiocb_envbuf.name_ptr = XPTR_FROM_NATIVE(name); + xiocb.plist.xiocb_envbuf.name_length = cfe_strlen(name); + xiocb.plist.xiocb_envbuf.val_ptr = XPTR_FROM_NATIVE(val); + xiocb.plist.xiocb_envbuf.val_length = cfe_strlen(val); + + cfe_iocb_dispatch(&xiocb); + + return xiocb.xiocb_status; +} +#endif /* CFE_API_setenv || CFE_API_ALL */ + +#if (defined(CFE_API_strlen) || defined(CFE_API_ALL)) \ + && !defined(CFE_API_STRLEN_CUSTOM) +int cfe_strlen(char *name) +{ + int count = 0; + + while (*name++) + count++; + + return count; +} +#endif /* CFE_API_strlen || CFE_API_ALL */ + +#if defined(CFE_API_write) || defined(CFE_API_ALL) +int cfe_write(int handle, unsigned char *buffer, int length) +{ + return cfe_writeblk(handle, 0, buffer, length); +} +#endif /* CFE_API_write || CFE_API_ALL */ + +#if defined(CFE_API_writeblk) || defined(CFE_API_ALL) +int +cfe_writeblk(int handle, cfe_xint_t offset, unsigned char *buffer, + int length) +{ + cfe_xiocb_t xiocb; + + xiocb.xiocb_fcode = CFE_CMD_DEV_WRITE; + xiocb.xiocb_status = 0; + xiocb.xiocb_handle = handle; + xiocb.xiocb_flags = 0; + xiocb.xiocb_psize = sizeof(xiocb_buffer_t); + xiocb.plist.xiocb_buffer.buf_offset = offset; + xiocb.plist.xiocb_buffer.buf_ptr = XPTR_FROM_NATIVE(buffer); + xiocb.plist.xiocb_buffer.buf_length = length; + + cfe_iocb_dispatch(&xiocb); + + if (xiocb.xiocb_status < 0) + return xiocb.xiocb_status; + return xiocb.plist.xiocb_buffer.buf_retlen; +} +#endif /* CFE_API_writeblk || CFE_API_ALL */ diff -Nru a/arch/mips/sibyte/cfe/cfe_api.h b/arch/mips/sibyte/cfe/cfe_api.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sibyte/cfe/cfe_api.h Tue Jul 1 18:44:40 2003 @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2000, 2001, 2002 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* ********************************************************************* + * + * Broadcom Common Firmware Environment (CFE) + * + * Device function prototypes File: cfe_api.h + * + * This file contains declarations for doing callbacks to + * cfe from an application. It should be the only header + * needed by the application to use this library + * + * Authors: Mitch Lichtenberg, Chris Demetriou + * + ********************************************************************* */ + +#ifndef CFE_API_H +#define CFE_API_H + +/* + * Apply customizations here for different OSes. These need to: + * * typedef uint64_t, int64_t, intptr_t, uintptr_t. + * * define cfe_strlen() if use of an existing function is desired. + * * define CFE_API_IMPL_NAMESPACE if API functions are to use + * names in the implementation namespace. + * Also, optionally, if the build environment does not do so automatically, + * CFE_API_* can be defined here as desired. + */ +/* Begin customization. */ +#include +#include + +typedef long intptr_t; + +#define cfe_strlen strlen + +#define CFE_API_ALL +#define CFE_API_STRLEN_CUSTOM +/* End customization. */ + + +/* ********************************************************************* + * Constants + ********************************************************************* */ + +/* Seal indicating CFE's presence, passed to user program. */ +#define CFE_EPTSEAL 0x43464531 + +#define CFE_MI_RESERVED 0 /* memory is reserved, do not use */ +#define CFE_MI_AVAILABLE 1 /* memory is available */ + +#define CFE_FLG_WARMSTART 0x00000001 +#define CFE_FLG_FULL_ARENA 0x00000001 +#define CFE_FLG_ENV_PERMANENT 0x00000001 + +#define CFE_CPU_CMD_START 1 +#define CFE_CPU_CMD_STOP 0 + +#define CFE_STDHANDLE_CONSOLE 0 + +#define CFE_DEV_NETWORK 1 +#define CFE_DEV_DISK 2 +#define CFE_DEV_FLASH 3 +#define CFE_DEV_SERIAL 4 +#define CFE_DEV_CPU 5 +#define CFE_DEV_NVRAM 6 +#define CFE_DEV_CLOCK 7 +#define CFE_DEV_OTHER 8 +#define CFE_DEV_MASK 0x0F + +#define CFE_CACHE_FLUSH_D 1 +#define CFE_CACHE_INVAL_I 2 +#define CFE_CACHE_INVAL_D 4 +#define CFE_CACHE_INVAL_L2 8 + +#define CFE_FWI_64BIT 0x00000001 +#define CFE_FWI_32BIT 0x00000002 +#define CFE_FWI_RELOC 0x00000004 +#define CFE_FWI_UNCACHED 0x00000008 +#define CFE_FWI_MULTICPU 0x00000010 +#define CFE_FWI_FUNCSIM 0x00000020 +#define CFE_FWI_RTLSIM 0x00000040 + +typedef struct { + int64_t fwi_version; /* major, minor, eco version */ + int64_t fwi_totalmem; /* total installed mem */ + int64_t fwi_flags; /* various flags */ + int64_t fwi_boardid; /* board ID */ + int64_t fwi_bootarea_va; /* VA of boot area */ + int64_t fwi_bootarea_pa; /* PA of boot area */ + int64_t fwi_bootarea_size; /* size of boot area */ +} cfe_fwinfo_t; + + +/* + * cfe_strlen is handled specially: If already defined, it has been + * overridden in this environment with a standard strlen-like function. + */ +#ifdef cfe_strlen +# define CFE_API_STRLEN_CUSTOM +#else +# ifdef CFE_API_IMPL_NAMESPACE +# define cfe_strlen(a) __cfe_strlen(a) +# endif +int cfe_strlen(char *name); +#endif + +/* + * Defines and prototypes for functions which take no arguments. + */ +#ifdef CFE_API_IMPL_NAMESPACE +int64_t __cfe_getticks(void); +#define cfe_getticks() __cfe_getticks() +#else +int64_t cfe_getticks(void); +#endif + +/* + * Defines and prototypes for the rest of the functions. + */ +#ifdef CFE_API_IMPL_NAMESPACE +#define cfe_close(a) __cfe_close(a) +#define cfe_cpu_start(a,b,c,d,e) __cfe_cpu_start(a,b,c,d,e) +#define cfe_cpu_stop(a) __cfe_cpu_stop(a) +#define cfe_enumenv(a,b,d,e,f) __cfe_enumenv(a,b,d,e,f) +#define cfe_enummem(a,b,c,d,e) __cfe_enummem(a,b,c,d,e) +#define cfe_exit(a,b) __cfe_exit(a,b) +#define cfe_flushcache(a) __cfe_cacheflush(a) +#define cfe_getdevinfo(a) __cfe_getdevinfo(a) +#define cfe_getenv(a,b,c) __cfe_getenv(a,b,c) +#define cfe_getfwinfo(a) __cfe_getfwinfo(a) +#define cfe_getstdhandle(a) __cfe_getstdhandle(a) +#define cfe_init(a,b) __cfe_init(a,b) +#define cfe_inpstat(a) __cfe_inpstat(a) +#define cfe_ioctl(a,b,c,d,e,f) __cfe_ioctl(a,b,c,d,e,f) +#define cfe_open(a) __cfe_open(a) +#define cfe_read(a,b,c) __cfe_read(a,b,c) +#define cfe_readblk(a,b,c,d) __cfe_readblk(a,b,c,d) +#define cfe_setenv(a,b) __cfe_setenv(a,b) +#define cfe_write(a,b,c) __cfe_write(a,b,c) +#define cfe_writeblk(a,b,c,d) __cfe_writeblk(a,b,c,d) +#endif /* CFE_API_IMPL_NAMESPACE */ + +int cfe_close(int handle); +int cfe_cpu_start(int cpu, void (*fn) (void), long sp, long gp, long a1); +int cfe_cpu_stop(int cpu); +int cfe_enumenv(int idx, char *name, int namelen, char *val, int vallen); +int cfe_enummem(int idx, int flags, uint64_t * start, uint64_t * length, + uint64_t * type); +int cfe_exit(int warm, int status); +int cfe_flushcache(int flg); +int cfe_getdevinfo(char *name); +int cfe_getenv(char *name, char *dest, int destlen); +int cfe_getfwinfo(cfe_fwinfo_t * info); +int cfe_getstdhandle(int flg); +int cfe_init(uint64_t handle, uint64_t ept); +int cfe_inpstat(int handle); +int cfe_ioctl(int handle, unsigned int ioctlnum, unsigned char *buffer, + int length, int *retlen, uint64_t offset); +int cfe_open(char *name); +int cfe_read(int handle, unsigned char *buffer, int length); +int cfe_readblk(int handle, int64_t offset, unsigned char *buffer, + int length); +int cfe_setenv(char *name, char *val); +int cfe_write(int handle, unsigned char *buffer, int length); +int cfe_writeblk(int handle, int64_t offset, unsigned char *buffer, + int length); + +#endif /* CFE_API_H */ diff -Nru a/arch/mips/sibyte/cfe/cfe_api_int.h b/arch/mips/sibyte/cfe/cfe_api_int.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sibyte/cfe/cfe_api_int.h Tue Jul 1 18:44:40 2003 @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2000, 2001, 2002 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* ********************************************************************* + * + * Broadcom Common Firmware Environment (CFE) + * + * Device function prototypes File: cfe_api_int.h + * + * This header defines all internal types and macros for the + * library. This is stuff that's not exported to an app + * using the library. + * + * Authors: Mitch Lichtenberg, Chris Demetriou + * + ********************************************************************* */ + +#ifndef CFE_API_INT_H +#define CFE_API_INT_H + +/* ********************************************************************* + * Constants + ********************************************************************* */ + +#define CFE_CMD_FW_GETINFO 0 +#define CFE_CMD_FW_RESTART 1 +#define CFE_CMD_FW_BOOT 2 +#define CFE_CMD_FW_CPUCTL 3 +#define CFE_CMD_FW_GETTIME 4 +#define CFE_CMD_FW_MEMENUM 5 +#define CFE_CMD_FW_FLUSHCACHE 6 + +#define CFE_CMD_DEV_GETHANDLE 9 +#define CFE_CMD_DEV_ENUM 10 +#define CFE_CMD_DEV_OPEN 11 +#define CFE_CMD_DEV_INPSTAT 12 +#define CFE_CMD_DEV_READ 13 +#define CFE_CMD_DEV_WRITE 14 +#define CFE_CMD_DEV_IOCTL 15 +#define CFE_CMD_DEV_CLOSE 16 +#define CFE_CMD_DEV_GETINFO 17 + +#define CFE_CMD_ENV_ENUM 20 +#define CFE_CMD_ENV_GET 22 +#define CFE_CMD_ENV_SET 23 +#define CFE_CMD_ENV_DEL 24 + +#define CFE_CMD_MAX 32 + +#define CFE_CMD_VENDOR_USE 0x8000 /* codes above this are for customer use */ + +/* ********************************************************************* + * Structures + ********************************************************************* */ + +typedef uint64_t cfe_xuint_t; +typedef int64_t cfe_xint_t; +typedef int64_t cfe_xptr_t; + +typedef struct xiocb_buffer_s { + cfe_xuint_t buf_offset; /* offset on device (bytes) */ + cfe_xptr_t buf_ptr; /* pointer to a buffer */ + cfe_xuint_t buf_length; /* length of this buffer */ + cfe_xuint_t buf_retlen; /* returned length (for read ops) */ + cfe_xuint_t buf_ioctlcmd; /* IOCTL command (used only for IOCTLs) */ +} xiocb_buffer_t; + +#define buf_devflags buf_ioctlcmd /* returned device info flags */ + +typedef struct xiocb_inpstat_s { + cfe_xuint_t inp_status; /* 1 means input available */ +} xiocb_inpstat_t; + +typedef struct xiocb_envbuf_s { + cfe_xint_t enum_idx; /* 0-based enumeration index */ + cfe_xptr_t name_ptr; /* name string buffer */ + cfe_xint_t name_length; /* size of name buffer */ + cfe_xptr_t val_ptr; /* value string buffer */ + cfe_xint_t val_length; /* size of value string buffer */ +} xiocb_envbuf_t; + +typedef struct xiocb_cpuctl_s { + cfe_xuint_t cpu_number; /* cpu number to control */ + cfe_xuint_t cpu_command; /* command to issue to CPU */ + cfe_xuint_t start_addr; /* CPU start address */ + cfe_xuint_t gp_val; /* starting GP value */ + cfe_xuint_t sp_val; /* starting SP value */ + cfe_xuint_t a1_val; /* starting A1 value */ +} xiocb_cpuctl_t; + +typedef struct xiocb_time_s { + cfe_xint_t ticks; /* current time in ticks */ +} xiocb_time_t; + +typedef struct xiocb_exitstat_s { + cfe_xint_t status; +} xiocb_exitstat_t; + +typedef struct xiocb_meminfo_s { + cfe_xint_t mi_idx; /* 0-based enumeration index */ + cfe_xint_t mi_type; /* type of memory block */ + cfe_xuint_t mi_addr; /* physical start address */ + cfe_xuint_t mi_size; /* block size */ +} xiocb_meminfo_t; + +typedef struct xiocb_fwinfo_s { + cfe_xint_t fwi_version; /* major, minor, eco version */ + cfe_xint_t fwi_totalmem; /* total installed mem */ + cfe_xint_t fwi_flags; /* various flags */ + cfe_xint_t fwi_boardid; /* board ID */ + cfe_xint_t fwi_bootarea_va; /* VA of boot area */ + cfe_xint_t fwi_bootarea_pa; /* PA of boot area */ + cfe_xint_t fwi_bootarea_size; /* size of boot area */ + cfe_xint_t fwi_reserved1; + cfe_xint_t fwi_reserved2; + cfe_xint_t fwi_reserved3; +} xiocb_fwinfo_t; + +typedef struct cfe_xiocb_s { + cfe_xuint_t xiocb_fcode; /* IOCB function code */ + cfe_xint_t xiocb_status; /* return status */ + cfe_xint_t xiocb_handle; /* file/device handle */ + cfe_xuint_t xiocb_flags; /* flags for this IOCB */ + cfe_xuint_t xiocb_psize; /* size of parameter list */ + union { + xiocb_buffer_t xiocb_buffer; /* buffer parameters */ + xiocb_inpstat_t xiocb_inpstat; /* input status parameters */ + xiocb_envbuf_t xiocb_envbuf; /* environment function parameters */ + xiocb_cpuctl_t xiocb_cpuctl; /* CPU control parameters */ + xiocb_time_t xiocb_time; /* timer parameters */ + xiocb_meminfo_t xiocb_meminfo; /* memory arena info parameters */ + xiocb_fwinfo_t xiocb_fwinfo; /* firmware information */ + xiocb_exitstat_t xiocb_exitstat; /* Exit Status */ + } plist; +} cfe_xiocb_t; + +#endif /* CFE_API_INT_H */ diff -Nru a/arch/mips/sibyte/cfe/cfe_error.h b/arch/mips/sibyte/cfe/cfe_error.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sibyte/cfe/cfe_error.h Tue Jul 1 18:44:40 2003 @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2000, 2001, 2002 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* ********************************************************************* + * + * Broadcom Common Firmware Environment (CFE) + * + * Error codes File: cfe_error.h + * + * CFE's global error code list is here. + * + * Author: Mitch Lichtenberg + * + ********************************************************************* */ + + +#define CFE_OK 0 +#define CFE_ERR -1 /* generic error */ +#define CFE_ERR_INV_COMMAND -2 +#define CFE_ERR_EOF -3 +#define CFE_ERR_IOERR -4 +#define CFE_ERR_NOMEM -5 +#define CFE_ERR_DEVNOTFOUND -6 +#define CFE_ERR_DEVOPEN -7 +#define CFE_ERR_INV_PARAM -8 +#define CFE_ERR_ENVNOTFOUND -9 +#define CFE_ERR_ENVREADONLY -10 + +#define CFE_ERR_NOTELF -11 +#define CFE_ERR_NOT32BIT -12 +#define CFE_ERR_WRONGENDIAN -13 +#define CFE_ERR_BADELFVERS -14 +#define CFE_ERR_NOTMIPS -15 +#define CFE_ERR_BADELFFMT -16 +#define CFE_ERR_BADADDR -17 + +#define CFE_ERR_FILENOTFOUND -18 +#define CFE_ERR_UNSUPPORTED -19 + +#define CFE_ERR_HOSTUNKNOWN -20 + +#define CFE_ERR_TIMEOUT -21 + +#define CFE_ERR_PROTOCOLERR -22 + +#define CFE_ERR_NETDOWN -23 +#define CFE_ERR_NONAMESERVER -24 + +#define CFE_ERR_NOHANDLES -25 +#define CFE_ERR_ALREADYBOUND -26 + +#define CFE_ERR_CANNOTSET -27 +#define CFE_ERR_NOMORE -28 +#define CFE_ERR_BADFILESYS -29 +#define CFE_ERR_FSNOTAVAIL -30 + +#define CFE_ERR_INVBOOTBLOCK -31 +#define CFE_ERR_WRONGDEVTYPE -32 +#define CFE_ERR_BBCHECKSUM -33 +#define CFE_ERR_BOOTPROGCHKSUM -34 + +#define CFE_ERR_LDRNOTAVAIL -35 + +#define CFE_ERR_NOTREADY -36 + +#define CFE_ERR_GETMEM -37 +#define CFE_ERR_SETMEM -38 + +#define CFE_ERR_NOTCONN -39 +#define CFE_ERR_ADDRINUSE -40 diff -Nru a/arch/mips/sibyte/cfe/console.c b/arch/mips/sibyte/cfe/console.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sibyte/cfe/console.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,91 @@ +#include +#include +#include +#include + +#include + +#include "cfe_api.h" +#include "cfe_error.h" + +extern int cfe_cons_handle; +static kdev_t cfe_consdev; + +#define SB1250_DUART_MINOR_BASE 192 + +static void cfe_console_write(struct console *cons, const char *str, + unsigned int count) +{ + int i, last, written; + + for (i=0,last=0; i MAX_RAM_SIZE) + || (initrd_pend > MAX_RAM_SIZE))) { + panic("initrd out of addressable memory"); + } + +#endif /* INITRD */ + + for (idx = 0; cfe_enummem(idx, mem_flags, &addr, &size, &type) != CFE_ERR_NOMORE; + idx++) { + rd_flag = 0; + if (type == CFE_MI_AVAILABLE) { + /* + * See if this block contains (any portion of) the + * ramdisk + */ +#ifdef CONFIG_BLK_DEV_INITRD + if (initrd_start) { + if ((initrd_pstart > addr) && + (initrd_pstart < (addr + size))) { + add_memory_region(addr, + initrd_pstart - addr, + BOOT_MEM_RAM); + rd_flag = 1; + } + if ((initrd_pend > addr) && + (initrd_pend < (addr + size))) { + add_memory_region(initrd_pend, + (addr + size) - initrd_pend, + BOOT_MEM_RAM); + rd_flag = 1; + } + } +#endif + if (!rd_flag) { + if (addr > MAX_RAM_SIZE) + continue; + if (addr+size > MAX_RAM_SIZE) + size = MAX_RAM_SIZE - (addr+size) + 1; + /* + * memcpy/__copy_user prefetch, which + * will cause a bus error for + * KSEG/KUSEG addrs not backed by RAM. + * Hence, reserve some padding for the + * prefetch distance. + */ + if (size > 512) + size -= 512; + add_memory_region(addr, size, BOOT_MEM_RAM); + } + board_mem_region_addrs[board_mem_region_count] = addr; + board_mem_region_sizes[board_mem_region_count] = size; + board_mem_region_count++; + if (board_mem_region_count == + SIBYTE_MAX_MEM_REGIONS) { + /* + * Too many regions. Need to configure more + */ + while(1); + } + } + } +#ifdef CONFIG_BLK_DEV_INITRD + if (initrd_start) { + add_memory_region(initrd_pstart, initrd_pend - initrd_pstart, + BOOT_MEM_RESERVED); + } +#endif +} + +#ifdef CONFIG_BLK_DEV_INITRD +static int __init initrd_setup(char *str) +{ + /* + *Initrd location comes in the form "@" + * e.g. initrd=3abfd@80010000. This is set up by the loader. + */ + char *tmp, *endptr; + unsigned long initrd_size; + for (tmp = str; *tmp != '@'; tmp++) { + if (!*tmp) { + goto fail; + } + } + *tmp = 0; + tmp++; + if (!*tmp) { + goto fail; + } + initrd_size = simple_strtoul(str, &endptr, 16); + if (*endptr) { + *(tmp-1) = '@'; + goto fail; + } + *(tmp-1) = '@'; + initrd_start = simple_strtoul(tmp, &endptr, 16); + if (*endptr) { + goto fail; + } + initrd_end = initrd_start + initrd_size; + printk("Found initrd of %lx@%lx\n", initrd_size, initrd_start); + return 1; + fail: + printk("Bad initrd argument. Disabling initrd\n"); + initrd_start = 0; + initrd_end = 0; + return 1; +} + +#endif + +/* + * prom_init is called just after the cpu type is determined, from init_arch() + */ +__init int prom_init(int argc, char **argv, char **envp, int *prom_vec) +{ + uint64_t cfe_ept, cfe_handle; + unsigned int cfe_eptseal; + + _machine_restart = (void (*)(char *))cfe_linux_exit; + _machine_halt = cfe_linux_exit; + _machine_power_off = cfe_linux_exit; + + /* + * Check if a loader was used; if NOT, the 4 arguments are + * what CFE gives us (handle, 0, EPT and EPTSEAL) + */ + if (argc < 0) { + cfe_handle = (uint64_t)(long)argc; + cfe_ept = (long)envp; + cfe_eptseal = (uint32_t)(unsigned long)prom_vec; + } else { + if ((int32_t)(long)prom_vec < 0) { + /* + * Old loader; all it gives us is the handle, + * so use the "known" entrypoint and assume + * the seal. + */ + cfe_handle = (uint64_t)(long)prom_vec; + cfe_ept = (uint64_t)((int32_t)0x9fc00500); + cfe_eptseal = CFE_EPTSEAL; + } else { + /* + * Newer loaders bundle the handle/ept/eptseal + * Note: prom_vec is in the loader's useg + * which is still alive in the TLB. + */ + cfe_handle = (uint64_t)((int32_t *)prom_vec)[0]; + cfe_ept = (uint64_t)((int32_t *)prom_vec)[2]; + cfe_eptseal = (unsigned int)((uint32_t *)prom_vec)[3]; + } + } + if (cfe_eptseal != CFE_EPTSEAL) { + /* XXXKW what? way too early to panic... */ + } + cfe_init(cfe_handle, cfe_ept); + /* + * Get the handle for (at least) prom_putchar, possibly for + * boot console + */ + cfe_cons_handle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE); + if (cfe_getenv("LINUX_CMDLINE", arcs_cmdline, CL_SIZE) < 0) { + if (argc < 0) { + /* + * It's OK for direct boot to not provide a + * command line + */ + strcpy(arcs_cmdline, "root=/dev/ram0 "); +#ifdef CONFIG_SIBYTE_PTSWARM + strcat(arcs_cmdline, "console=ttyS0,115200 "); +#endif + } else { + /* The loader should have set the command line */ + panic("LINUX_CMDLINE not defined in cfe."); + } + } + +#ifdef CONFIG_BLK_DEV_INITRD + { + char *ptr; + /* Need to find out early whether we've got an initrd. So scan + the list looking now */ + for (ptr = arcs_cmdline; *ptr; ptr++) { + while (*ptr == ' ') { + ptr++; + } + if (!strncmp(ptr, "initrd=", 7)) { + initrd_setup(ptr+7); + break; + } else { + while (*ptr && (*ptr != ' ')) { + ptr++; + } + } + } + } +#endif /* CONFIG_BLK_DEV_INITRD */ + + /* Not sure this is needed, but it's the safe way. */ + arcs_cmdline[CL_SIZE-1] = 0; + + mips_machgroup = MACH_GROUP_SIBYTE; + prom_meminit(); + + return 0; +} + +void prom_free_prom_memory(void) +{ + /* Not sure what I'm supposed to do here. Nothing, I think */ +} + +int page_is_ram(unsigned long pagenr) +{ + phys_t addr = pagenr << PAGE_SHIFT; + int i; + for (i = 0; i < board_mem_region_count; i++) { + if ((addr >= board_mem_region_addrs[i]) + && (addr < (board_mem_region_addrs[i] + board_mem_region_sizes[i]))) { + return 1; + } + } + return 0; +} + +void prom_putchar(char c) +{ + int ret; + + while ((ret = cfe_write(cfe_cons_handle, &c, 1)) == 0) + ; +} diff -Nru a/arch/mips/sibyte/cfe/smp.c b/arch/mips/sibyte/cfe/smp.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sibyte/cfe/smp.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2000, 2001 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include + +#include + +#include "cfe_api.h" +#include "cfe_error.h" + +extern void asmlinkage smp_bootstrap(void); + +/* Boot all other cpus in the system, initialize them, and + bring them into the boot fn */ +int prom_boot_secondary(int cpu, unsigned long sp, unsigned long gp) +{ + int retval; + + retval = cfe_cpu_start(cpu, &smp_bootstrap, sp, gp, 0); + if (retval != 0) { + printk("cfe_start_cpu(%i) returned %i\n" , cpu, retval); + return 0; + } else { + return 1; + } +} + +void prom_init_secondary(void) +{ + /* Set up kseg0 to be cachable coherent */ + clear_c0_config(CONF_CM_CMASK); + set_c0_config(0x5); + + /* Enable interrupts for lines 0-4 */ + clear_c0_status(0xe000); + set_c0_status(0x1f01); +} + +/* + * Set up state, return the total number of cpus in the system, including + * the master + */ +void prom_setup_smp(void) +{ + int i; + + /* Use CFE to find out how many CPUs are available */ + for (i=1; i +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct sbprof_tb sbp; + +#define TB_FULL (sbp.next_tb_sample == MAX_TB_SAMPLES) + +/************************************************************************ + * Support for ZBbus sampling using the trace buffer + * + * We use the SCD performance counter interrupt, caused by a Zclk counter + * overflow, to trigger the start of tracing. + * + * We set the trace buffer to sample everything and freeze on + * overflow. + * + * We map the interrupt for trace_buffer_freeze to handle it on CPU 0. + * + ************************************************************************/ + +/* 100 samples per second on a 500 Mhz 1250 (default) */ +static u_int64_t tb_period = 2500000ULL; + +static void arm_tb(void) +{ + u_int64_t scdperfcnt; + u_int64_t next = (1ULL << 40) - tb_period; + /* Generate an SCD_PERFCNT interrupt in TB_PERIOD Zclks to + trigger start of trace. XXX vary sampling period */ + out64(0, KSEG1 + A_SCD_PERF_CNT_1); + scdperfcnt = in64(KSEG1 + A_SCD_PERF_CNT_CFG); + /* Unfortunately, in Pass 2 we must clear all counters to knock down + a previous interrupt request. This means that bus profiling + requires ALL of the SCD perf counters. */ + out64((scdperfcnt & ~M_SPC_CFG_SRC1) | // keep counters 0,2,3 as is + M_SPC_CFG_ENABLE | // enable counting + M_SPC_CFG_CLEAR | // clear all counters + V_SPC_CFG_SRC1(1), // counter 1 counts cycles + KSEG1 + A_SCD_PERF_CNT_CFG); + out64(next, KSEG1 + A_SCD_PERF_CNT_1); + /* Reset the trace buffer */ + out64(M_SCD_TRACE_CFG_RESET, KSEG1 + A_SCD_TRACE_CFG); + out64(M_SCD_TRACE_CFG_FREEZE_FULL +#if 0 && defined(M_SCD_TRACE_CFG_FORCECNT) + /* XXXKW may want to expose control to the data-collector */ + | M_SCD_TRACE_CFG_FORCECNT +#endif + , KSEG1 + A_SCD_TRACE_CFG); + sbp.tb_armed = 1; +} + +static void sbprof_tb_intr(int irq, void *dev_id, struct pt_regs *regs) +{ + int i; + DBG(printk(DEVNAME ": tb_intr\n")); + if (sbp.next_tb_sample < MAX_TB_SAMPLES) { + /* XXX should use XKPHYS to make writes bypass L2 */ + u_int64_t *p = sbp.sbprof_tbbuf[sbp.next_tb_sample++]; + /* Read out trace */ + out64(M_SCD_TRACE_CFG_START_READ, KSEG1 + A_SCD_TRACE_CFG); + __asm__ __volatile__ ("sync" : : : "memory"); + /* Loop runs backwards because bundles are read out in reverse order */ + for (i = 256 * 6; i > 0; i -= 6) { + // Subscripts decrease to put bundle in the order + // t0 lo, t0 hi, t1 lo, t1 hi, t2 lo, t2 hi + p[i-1] = in64(KSEG1 + A_SCD_TRACE_READ); // read t2 hi + p[i-2] = in64(KSEG1 + A_SCD_TRACE_READ); // read t2 lo + p[i-3] = in64(KSEG1 + A_SCD_TRACE_READ); // read t1 hi + p[i-4] = in64(KSEG1 + A_SCD_TRACE_READ); // read t1 lo + p[i-5] = in64(KSEG1 + A_SCD_TRACE_READ); // read t0 hi + p[i-6] = in64(KSEG1 + A_SCD_TRACE_READ); // read t0 lo + } + if (!sbp.tb_enable) { + DBG(printk(DEVNAME ": tb_intr shutdown\n")); + out64(M_SCD_TRACE_CFG_RESET, KSEG1 + A_SCD_TRACE_CFG); + sbp.tb_armed = 0; + wake_up(&sbp.tb_sync); + } else { + arm_tb(); // knock down current interrupt and get another one later + } + } else { + /* No more trace buffer samples */ + DBG(printk(DEVNAME ": tb_intr full\n")); + out64(M_SCD_TRACE_CFG_RESET, KSEG1 + A_SCD_TRACE_CFG); + sbp.tb_armed = 0; + if (!sbp.tb_enable) { + wake_up(&sbp.tb_sync); + } + wake_up(&sbp.tb_read); + } +} + +static void sbprof_pc_intr(int irq, void *dev_id, struct pt_regs *regs) +{ + printk(DEVNAME ": unexpected pc_intr"); +} + +static int sbprof_zbprof_start(struct file *filp) +{ + u_int64_t scdperfcnt; + + if (sbp.tb_enable) + return -EBUSY; + + DBG(printk(DEVNAME ": starting\n")); + + sbp.tb_enable = 1; + sbp.next_tb_sample = 0; + filp->f_pos = 0; + + if (request_irq + (K_INT_TRACE_FREEZE, sbprof_tb_intr, 0, DEVNAME " trace freeze", &sbp)) { + return -EBUSY; + } + /* Make sure there isn't a perf-cnt interrupt waiting */ + scdperfcnt = in64(KSEG1 + A_SCD_PERF_CNT_CFG); + /* Disable and clear counters, override SRC_1 */ + out64((scdperfcnt & ~(M_SPC_CFG_SRC1 | M_SPC_CFG_ENABLE)) | + M_SPC_CFG_ENABLE | + M_SPC_CFG_CLEAR | + V_SPC_CFG_SRC1(1), + KSEG1 + A_SCD_PERF_CNT_CFG); + + /* We grab this interrupt to prevent others from trying to use + it, even though we don't want to service the interrupts + (they only feed into the trace-on-interrupt mechanism) */ + if (request_irq + (K_INT_PERF_CNT, sbprof_pc_intr, 0, DEVNAME " scd perfcnt", &sbp)) { + free_irq(K_INT_TRACE_FREEZE, &sbp); + return -EBUSY; + } + + /* I need the core to mask these, but the interrupt mapper to + pass them through. I am exploiting my knowledge that + cp0_status masks out IP[5]. krw */ + out64(K_INT_MAP_I3, + KSEG1 + A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) + (K_INT_PERF_CNT<<3)); + + /* Initialize address traps */ + out64(0, KSEG1 + A_ADDR_TRAP_UP_0); + out64(0, KSEG1 + A_ADDR_TRAP_UP_1); + out64(0, KSEG1 + A_ADDR_TRAP_UP_2); + out64(0, KSEG1 + A_ADDR_TRAP_UP_3); + + out64(0, KSEG1 + A_ADDR_TRAP_DOWN_0); + out64(0, KSEG1 + A_ADDR_TRAP_DOWN_1); + out64(0, KSEG1 + A_ADDR_TRAP_DOWN_2); + out64(0, KSEG1 + A_ADDR_TRAP_DOWN_3); + + out64(0, KSEG1 + A_ADDR_TRAP_CFG_0); + out64(0, KSEG1 + A_ADDR_TRAP_CFG_1); + out64(0, KSEG1 + A_ADDR_TRAP_CFG_2); + out64(0, KSEG1 + A_ADDR_TRAP_CFG_3); + + /* Initialize Trace Event 0-7 */ + // when interrupt + out64(M_SCD_TREVT_INTERRUPT, KSEG1 + A_SCD_TRACE_EVENT_0); + out64(0, KSEG1 + A_SCD_TRACE_EVENT_1); + out64(0, KSEG1 + A_SCD_TRACE_EVENT_2); + out64(0, KSEG1 + A_SCD_TRACE_EVENT_3); + out64(0, KSEG1 + A_SCD_TRACE_EVENT_4); + out64(0, KSEG1 + A_SCD_TRACE_EVENT_5); + out64(0, KSEG1 + A_SCD_TRACE_EVENT_6); + out64(0, KSEG1 + A_SCD_TRACE_EVENT_7); + + /* Initialize Trace Sequence 0-7 */ + // Start on event 0 (interrupt) + out64(V_SCD_TRSEQ_FUNC_START|0x0fff, + KSEG1 + A_SCD_TRACE_SEQUENCE_0); + // dsamp when d used | asamp when a used + out64(M_SCD_TRSEQ_ASAMPLE|M_SCD_TRSEQ_DSAMPLE|K_SCD_TRSEQ_TRIGGER_ALL, + KSEG1 + A_SCD_TRACE_SEQUENCE_1); + out64(0, KSEG1 + A_SCD_TRACE_SEQUENCE_2); + out64(0, KSEG1 + A_SCD_TRACE_SEQUENCE_3); + out64(0, KSEG1 + A_SCD_TRACE_SEQUENCE_4); + out64(0, KSEG1 + A_SCD_TRACE_SEQUENCE_5); + out64(0, KSEG1 + A_SCD_TRACE_SEQUENCE_6); + out64(0, KSEG1 + A_SCD_TRACE_SEQUENCE_7); + + /* Now indicate the PERF_CNT interrupt as a trace-relevant interrupt */ + out64((1ULL << K_INT_PERF_CNT), KSEG1 + A_IMR_REGISTER(0, R_IMR_INTERRUPT_TRACE)); + + arm_tb(); + + DBG(printk(DEVNAME ": done starting\n")); + + return 0; +} + +static int sbprof_zbprof_stop(void) +{ + DBG(printk(DEVNAME ": stopping\n")); + + if (sbp.tb_enable) { + sbp.tb_enable = 0; + /* XXXKW there is a window here where the intr handler + may run, see the disable, and do the wake_up before + this sleep happens. */ + if (sbp.tb_armed) { + DBG(printk(DEVNAME ": wait for disarm\n")); + interruptible_sleep_on(&sbp.tb_sync); + DBG(printk(DEVNAME ": disarm complete\n")); + } + free_irq(K_INT_TRACE_FREEZE, &sbp); + free_irq(K_INT_PERF_CNT, &sbp); + } + + DBG(printk(DEVNAME ": done stopping\n")); + + return 0; +} + +static int sbprof_tb_open(struct inode *inode, struct file *filp) +{ + int minor; + + minor = MINOR(inode->i_rdev); + if (minor != 0) { + return -ENODEV; + } + if (sbp.open) { + return -EBUSY; + } + + memset(&sbp, 0, sizeof(struct sbprof_tb)); + sbp.sbprof_tbbuf = vmalloc(MAX_TBSAMPLE_BYTES); + if (!sbp.sbprof_tbbuf) { + return -ENOMEM; + } + memset(sbp.sbprof_tbbuf, 0, MAX_TBSAMPLE_BYTES); + init_waitqueue_head(&sbp.tb_sync); + init_waitqueue_head(&sbp.tb_read); + sbp.open = 1; + + return 0; +} + +static int sbprof_tb_release(struct inode *inode, struct file *filp) +{ + int minor; + + minor = MINOR(inode->i_rdev); + if (minor != 0 || !sbp.open) { + return -ENODEV; + } + + if (sbp.tb_armed || sbp.tb_enable) { + sbprof_zbprof_stop(); + } + + vfree(sbp.sbprof_tbbuf); + sbp.open = 0; + + return 0; +} + +static ssize_t sbprof_tb_read(struct file *filp, char *buf, + size_t size, loff_t *offp) +{ + int cur_sample, sample_off, cur_count, sample_left; + char *src; + int count = 0; + char *dest = buf; + long cur_off = *offp; + + count = 0; + cur_sample = cur_off / TB_SAMPLE_SIZE; + sample_off = cur_off % TB_SAMPLE_SIZE; + sample_left = TB_SAMPLE_SIZE - sample_off; + while (size && (cur_sample < sbp.next_tb_sample)) { + cur_count = size < sample_left ? size : sample_left; + src = (char *)(((long)sbp.sbprof_tbbuf[cur_sample])+sample_off); + copy_to_user(dest, src, cur_count); + DBG(printk(DEVNAME ": read from sample %d, %d bytes\n", cur_sample, cur_count)); + size -= cur_count; + sample_left -= cur_count; + if (!sample_left) { + cur_sample++; + sample_off = 0; + sample_left = TB_SAMPLE_SIZE; + } else { + sample_off += cur_count; + } + cur_off += cur_count; + dest += cur_count; + count += cur_count; + } + *offp = cur_off; + + return count; +} + +static int sbprof_tb_ioctl(struct inode *inode, + struct file *filp, + unsigned int command, + unsigned long arg) +{ + int error = 0; + + switch (command) { + case SBPROF_ZBSTART: + error = sbprof_zbprof_start(filp); + break; + case SBPROF_ZBSTOP: + error = sbprof_zbprof_stop(); + break; + case SBPROF_ZBWAITFULL: + interruptible_sleep_on(&sbp.tb_read); + /* XXXKW check if interrupted? */ + return put_user(TB_FULL, (int *) arg); + default: + error = -EINVAL; + break; + } + + return error; +} + +static struct file_operations sbprof_tb_fops = { + .owner = THIS_MODULE, + .open = sbprof_tb_open, + .release = sbprof_tb_release, + .read = sbprof_tb_read, + .ioctl = sbprof_tb_ioctl, + .mmap = NULL, +}; + +static devfs_handle_t devfs_handle; + +#define UNDEF 0 +static unsigned long long pll_div_to_mhz[32] = { + UNDEF, + UNDEF, + UNDEF, + UNDEF, + 200, + 250, + 300, + 350, + 400, + 450, + 500, + 550, + 600, + 650, + 700, + 750, + 800, + 850, + 900, + 950, + 1000, + 1050, + 1100, + UNDEF, + UNDEF, + UNDEF, + UNDEF, + UNDEF, + UNDEF, + UNDEF, + UNDEF, + UNDEF +}; + +static int __init sbprof_tb_init(void) +{ + unsigned int pll_div; + + if (devfs_register_chrdev(SBPROF_TB_MAJOR, DEVNAME, &sbprof_tb_fops)) { + printk(KERN_WARNING DEVNAME ": initialization failed (dev %d)\n", + SBPROF_TB_MAJOR); + return -EIO; + } + devfs_handle = devfs_register(NULL, DEVNAME, + DEVFS_FL_DEFAULT, SBPROF_TB_MAJOR, 0, + S_IFCHR | S_IRUGO | S_IWUGO, + &sbprof_tb_fops, NULL); + sbp.open = 0; + pll_div = pll_div_to_mhz[G_SYS_PLL_DIV(in64(KSEG1 + A_SCD_SYSTEM_CFG))]; + if (pll_div != UNDEF) { + tb_period = (pll_div / 2) * 10000; + } else { + printk(KERN_INFO DEVNAME ": strange PLL divide\n"); + } + printk(KERN_INFO DEVNAME ": initialized - tb_period = %lld\n", tb_period); + return 0; +} + +static void __exit sbprof_tb_cleanup(void) +{ + devfs_unregister_chrdev(SBPROF_TB_MAJOR, DEVNAME); + devfs_unregister(devfs_handle); +} + +module_init(sbprof_tb_init); +module_exit(sbprof_tb_cleanup); diff -Nru a/arch/mips/sibyte/sb1250/bus_watcher.c b/arch/mips/sibyte/sb1250/bus_watcher.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sibyte/sb1250/bus_watcher.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,232 @@ +/* + * Copyright (C) 2002,2003 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * The Bus Watcher monitors internal bus transactions and maintains + * counts of transactions with error status, logging details and + * causing one of several interrupts. This driver provides a handler + * for those interrupts which aggregates the counts (to avoid + * saturating the 8-bit counters) and provides a presence in + * /proc/bus_watcher if PROC_FS is on. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +struct bw_stats_struct { + uint64_t status; + uint32_t l2_err; + uint32_t memio_err; + int status_printed; + unsigned long l2_cor_d; + unsigned long l2_bad_d; + unsigned long l2_cor_t; + unsigned long l2_bad_t; + unsigned long mem_cor_d; + unsigned long mem_bad_d; + unsigned long bus_error; +} bw_stats; + + +static void print_summary(uint32_t status, uint32_t l2_err, + uint32_t memio_err) +{ + printk("Bus watcher error counters: %08x %08x\n", l2_err, memio_err); + printk("\nLast recorded signature:\n"); + printk("Request %02x from %d, answered by %d with Dcode %d\n", + (unsigned int)(G_SCD_BERR_TID(status) & 0x3f), + (int)(G_SCD_BERR_TID(status) >> 6), + (int)G_SCD_BERR_RID(status), + (int)G_SCD_BERR_DCODE(status)); +} + +/* + * check_bus_watcher is exported for use in situations where we want + * to see the most recent status of the bus watcher, which might have + * already been destructively read out of the registers. + * + * notes: this is currently used by the cache error handler + * should provide locking against the interrupt handler + */ +void check_bus_watcher(void) +{ + u32 status, l2_err, memio_err; + +#ifdef CONFIG_SB1_PASS_1_WORKAROUNDS + /* Destructive read, clears register and interrupt */ + status = csr_in32(IO_SPACE_BASE | A_SCD_BUS_ERR_STATUS); +#else + /* Use non-destructive register */ + status = csr_in32(IO_SPACE_BASE | A_SCD_BUS_ERR_STATUS_DEBUG); +#endif + if (!(status & 0x7fffffff)) { + printk("Using last values reaped by bus watcher driver\n"); + status = bw_stats.status; + l2_err = bw_stats.l2_err; + memio_err = bw_stats.memio_err; + } else { + l2_err = csr_in32(IO_SPACE_BASE | A_BUS_L2_ERRORS); + memio_err = csr_in32(IO_SPACE_BASE | A_BUS_MEM_IO_ERRORS); + } + if (status & ~(1UL << 31)) + print_summary(status, l2_err, memio_err); + else + printk("Bus watcher indicates no error\n"); +} + +static int bw_print_buffer(char *page, struct bw_stats_struct *stats) +{ + int len; + + len = sprintf(page, "SiByte Bus Watcher statistics\n"); + len += sprintf(page+len, "-----------------------------\n"); + len += sprintf(page+len, "L2-d-cor %8ld\nL2-d-bad %8ld\n", + stats->l2_cor_d, stats->l2_bad_d); + len += sprintf(page+len, "L2-t-cor %8ld\nL2-t-bad %8ld\n", + stats->l2_cor_t, stats->l2_bad_t); + len += sprintf(page+len, "MC-d-cor %8ld\nMC-d-bad %8ld\n", + stats->mem_cor_d, stats->mem_bad_d); + len += sprintf(page+len, "IO-err %8ld\n", stats->bus_error); + len += sprintf(page+len, "\nLast recorded signature:\n"); + len += sprintf(page+len, "Request %02x from %d, answered by %d with Dcode %d\n", + (unsigned int)(G_SCD_BERR_TID(stats->status) & 0x3f), + (int)(G_SCD_BERR_TID(stats->status) >> 6), + (int)G_SCD_BERR_RID(stats->status), + (int)G_SCD_BERR_DCODE(stats->status)); + /* XXXKW indicate multiple errors between printings, or stats + collection (or both)? */ + if (stats->status & M_SCD_BERR_MULTERRS) + len += sprintf(page+len, "Multiple errors observed since last check.\n"); + if (stats->status_printed) { + len += sprintf(page+len, "(no change since last printing)\n"); + } else { + stats->status_printed = 1; + } + + return len; +} + +#ifdef CONFIG_PROC_FS + +/* For simplicity, I want to assume a single read is required each + time */ +static int bw_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len; + + if (off == 0) { + len = bw_print_buffer(page, data); + *start = page; + } else { + len = 0; + *eof = 1; + } + return len; +} + +static void create_proc_decoder(struct bw_stats_struct *stats) +{ + struct proc_dir_entry *ent; + + ent = create_proc_read_entry("bus_watcher", S_IWUSR | S_IRUGO, NULL, + bw_read_proc, stats); + if (!ent) { + printk(KERN_INFO "Unable to initialize bus_watcher /proc entry\n"); + return; + } +} + +#endif /* CONFIG_PROC_FS */ + +/* + * sibyte_bw_int - handle bus watcher interrupts and accumulate counts + * + * notes: possible re-entry due to multiple sources + * should check/indicate saturation + */ +static void sibyte_bw_int(int irq, void *data, struct pt_regs *regs) +{ + struct bw_stats_struct *stats = data; + unsigned long cntr; +#ifndef CONFIG_PROC_FS + char bw_buf[1024]; +#endif + + /* Destructive read, clears register and interrupt */ + stats->status = csr_in32(IO_SPACE_BASE | A_SCD_BUS_ERR_STATUS); + stats->status_printed = 0; + + stats->l2_err = cntr = csr_in32(IO_SPACE_BASE | A_BUS_L2_ERRORS); + stats->l2_cor_d += G_SCD_L2ECC_CORR_D(cntr); + stats->l2_bad_d += G_SCD_L2ECC_BAD_D(cntr); + stats->l2_cor_t += G_SCD_L2ECC_CORR_T(cntr); + stats->l2_bad_t += G_SCD_L2ECC_BAD_T(cntr); + csr_out32(0, IO_SPACE_BASE | A_BUS_L2_ERRORS); + + stats->memio_err = cntr = csr_in32(IO_SPACE_BASE | A_BUS_MEM_IO_ERRORS); + stats->mem_cor_d += G_SCD_MEM_ECC_CORR(cntr); + stats->mem_bad_d += G_SCD_MEM_ECC_BAD(cntr); + stats->bus_error += G_SCD_MEM_BUSERR(cntr); + csr_out32(0, IO_SPACE_BASE | A_BUS_MEM_IO_ERRORS); + +#ifndef CONFIG_PROC_FS + bw_print_buffer(bw_buf, stats); + printk(bw_buf); +#endif +} + +int __init sibyte_bus_watcher(void) +{ + memset(&bw_stats, 0, sizeof(struct bw_stats_struct)); + bw_stats.status_printed = 1; + + if (request_irq(K_INT_BAD_ECC, sibyte_bw_int, 0, "Bus watcher", &bw_stats)) { + printk("Failed to register bus watcher BAD_ECC irq\n"); + return -1; + } + if (request_irq(K_INT_COR_ECC, sibyte_bw_int, 0, "Bus watcher", &bw_stats)) { + free_irq(K_INT_BAD_ECC, &bw_stats); + printk("Failed to register bus watcher COR_ECC irq\n"); + return -1; + } + if (request_irq(K_INT_IO_BUS, sibyte_bw_int, 0, "Bus watcher", &bw_stats)) { + free_irq(K_INT_BAD_ECC, &bw_stats); + free_irq(K_INT_COR_ECC, &bw_stats); + printk("Failed to register bus watcher IO_BUS irq\n"); + return -1; + } + +#ifdef CONFIG_PROC_FS + create_proc_decoder(&bw_stats); +#endif + + return 0; +} + +__initcall(sibyte_bus_watcher); diff -Nru a/arch/mips/sibyte/sb1250/irq.c b/arch/mips/sibyte/sb1250/irq.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sibyte/sb1250/irq.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,419 @@ +/* + * Copyright (C) 2000, 2001 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* + * These are the routines that handle all the low level interrupt stuff. + * Actions handled here are: initialization of the interrupt map, requesting of + * interrupt lines by handlers, dispatching if interrupts to handlers, probing + * for interrupt lines + */ + + +#define shutdown_sb1250_irq disable_sb1250_irq +static void end_sb1250_irq(unsigned int irq); +static void enable_sb1250_irq(unsigned int irq); +static void disable_sb1250_irq(unsigned int irq); +static unsigned int startup_sb1250_irq(unsigned int irq); +static void ack_sb1250_irq(unsigned int irq); +#ifdef CONFIG_SMP +static void sb1250_set_affinity(unsigned int irq, unsigned long mask); +#endif + +#ifdef CONFIG_SIBYTE_HAS_LDT +extern unsigned long ldt_eoi_space; +#endif + +#ifdef CONFIG_KGDB +extern void breakpoint(void); +extern void set_debug_traps(void); + +/* kgdb is on when configured. Pass "nokgdb" kernel arg to turn it off */ +static int kgdb_flag = 1; +static int __init nokgdb(char *str) +{ + kgdb_flag = 0; +} +__setup("nokgdb", nokgdb); +#endif + +static struct hw_interrupt_type sb1250_irq_type = { + "SB1250-IMR", + startup_sb1250_irq, + shutdown_sb1250_irq, + enable_sb1250_irq, + disable_sb1250_irq, + ack_sb1250_irq, + end_sb1250_irq, +#ifdef CONFIG_SMP + sb1250_set_affinity +#else + NULL +#endif +}; + +/* Store the CPU id (not the logical number) */ +int sb1250_irq_owner[SB1250_NR_IRQS]; + +spinlock_t sb1250_imr_lock = SPIN_LOCK_UNLOCKED; + +void sb1250_mask_irq(int cpu, int irq) +{ + unsigned long flags; + u64 cur_ints; + + spin_lock_irqsave(&sb1250_imr_lock, flags); + cur_ints = __in64(KSEG1 + A_IMR_MAPPER(cpu) + R_IMR_INTERRUPT_MASK); + cur_ints |= (((u64) 1) << irq); + __out64(cur_ints, KSEG1 + A_IMR_MAPPER(cpu) + R_IMR_INTERRUPT_MASK); + spin_unlock_irqrestore(&sb1250_imr_lock, flags); +} + +void sb1250_unmask_irq(int cpu, int irq) +{ + unsigned long flags; + u64 cur_ints; + + spin_lock_irqsave(&sb1250_imr_lock, flags); + cur_ints = __in64(KSEG1 + A_IMR_MAPPER(cpu) + R_IMR_INTERRUPT_MASK); + cur_ints &= ~(((u64) 1) << irq); + __out64(cur_ints, KSEG1 + A_IMR_MAPPER(cpu) + R_IMR_INTERRUPT_MASK); + spin_unlock_irqrestore(&sb1250_imr_lock, flags); +} + +#ifdef CONFIG_SMP +static void sb1250_set_affinity(unsigned int irq, unsigned long mask) +{ + int i = 0, old_cpu, cpu, int_on; + u64 cur_ints; + irq_desc_t *desc = irq_desc + irq; + unsigned int flags; + + while (mask) { + if (mask & 1) { + mask >>= 1; + break; + } + mask >>= 1; + i++; + } + + if (mask) { + printk("attempted to set irq affinity for irq %d to multiple CPUs\n", irq); + return; + } + + /* Convert logical CPU to physical CPU */ + cpu = cpu_logical_map(i); + + /* Protect against other affinity changers and IMR manipulation */ + spin_lock_irqsave(&desc->lock, flags); + spin_lock(&sb1250_imr_lock); + + /* Swizzle each CPU's IMR (but leave the IP selection alone) */ + old_cpu = sb1250_irq_owner[irq]; + cur_ints = __in64(KSEG1 + A_IMR_MAPPER(old_cpu) + R_IMR_INTERRUPT_MASK); + int_on = !(cur_ints & (((u64) 1) << irq)); + if (int_on) { + /* If it was on, mask it */ + cur_ints |= (((u64) 1) << irq); + __out64(cur_ints, KSEG1 + A_IMR_MAPPER(old_cpu) + R_IMR_INTERRUPT_MASK); + } + sb1250_irq_owner[irq] = cpu; + if (int_on) { + /* unmask for the new CPU */ + cur_ints = __in64(KSEG1 + A_IMR_MAPPER(cpu) + R_IMR_INTERRUPT_MASK); + cur_ints &= ~(((u64) 1) << irq); + __out64(cur_ints, KSEG1 + A_IMR_MAPPER(cpu) + R_IMR_INTERRUPT_MASK); + } + spin_unlock(&sb1250_imr_lock); + spin_unlock_irqrestore(&desc->lock, flags); +} +#endif + + +/* Defined in arch/mips/sibyte/sb1250/irq_handler.S */ +extern void sb1250_irq_handler(void); + +/*****************************************************************************/ + +static unsigned int startup_sb1250_irq(unsigned int irq) +{ + sb1250_unmask_irq(sb1250_irq_owner[irq], irq); + + return 0; /* never anything pending */ +} + + +static void disable_sb1250_irq(unsigned int irq) +{ + sb1250_mask_irq(sb1250_irq_owner[irq], irq); +} + +static void enable_sb1250_irq(unsigned int irq) +{ + sb1250_unmask_irq(sb1250_irq_owner[irq], irq); +} + + +static void ack_sb1250_irq(unsigned int irq) +{ +#ifdef CONFIG_SIBYTE_HAS_LDT + u64 pending; + + /* + * If the interrupt was an HT interrupt, now is the time to + * clear it. NOTE: we assume the HT bridge was set up to + * deliver the interrupts to all CPUs (which makes affinity + * changing easier for us) + */ + pending = in64(KSEG1 + A_IMR_REGISTER(sb1250_irq_owner[irq], + R_IMR_LDT_INTERRUPT)); + pending &= ((u64)1 << (irq)); + if (pending) { + int i; + for (i=0; i= SB1250_NR_IRQS) + return -EINVAL; + + spin_lock_irqsave(&desc->lock,flags); + /* Don't allow sharing at all for these */ + if (desc->action != NULL) + retval = -EBUSY; + else { + desc->action = &sb1250_dummy_action; + desc->depth = 0; + } + spin_unlock_irqrestore(&desc->lock,flags); + return 0; +} + +/* + * init_IRQ is called early in the boot sequence from init/main.c. It + * is responsible for setting up the interrupt mapper and installing the + * handler that will be responsible for dispatching interrupts to the + * "right" place. + */ +/* + * For now, map all interrupts to IP[2]. We could save + * some cycles by parceling out system interrupts to different + * IP lines, but keep it simple for bringup. We'll also direct + * all interrupts to a single CPU; we should probably route + * PCI and LDT to one cpu and everything else to the other + * to balance the load a bit. + * + * On the second cpu, everything is set to IP5, which is + * ignored, EXCEPT the mailbox interrupt. That one is + * set to IP[2] so it is handled. This is needed so we + * can do cross-cpu function calls, as requred by SMP + */ + +#define IMR_IP2_VAL K_INT_MAP_I0 +#define IMR_IP3_VAL K_INT_MAP_I1 +#define IMR_IP4_VAL K_INT_MAP_I2 +#define IMR_IP5_VAL K_INT_MAP_I3 +#define IMR_IP6_VAL K_INT_MAP_I4 + +void __init init_IRQ(void) +{ + + unsigned int i; + u64 tmp; + unsigned int imask = STATUSF_IP4 | STATUSF_IP3 | STATUSF_IP2 | + STATUSF_IP1 | STATUSF_IP0; + + /* Default everything to IP2 */ + for (i = 0; i < SB1250_NR_IRQS; i++) { /* was I0 */ + out64(IMR_IP2_VAL, + KSEG1 + A_IMR_REGISTER(0, + R_IMR_INTERRUPT_MAP_BASE) + + (i << 3)); + out64(IMR_IP2_VAL, + KSEG1 + A_IMR_REGISTER(1, + R_IMR_INTERRUPT_MAP_BASE) + + (i << 3)); + } + + init_sb1250_irqs(); + + /* + * Map the high 16 bits of the mailbox registers to IP[3], for + * inter-cpu messages + */ + /* Was I1 */ + out64(IMR_IP3_VAL, KSEG1 + A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) + + (K_INT_MBOX_0 << 3)); + out64(IMR_IP3_VAL, KSEG1 + A_IMR_REGISTER(1, R_IMR_INTERRUPT_MAP_BASE) + + (K_INT_MBOX_0 << 3)); + + /* Clear the mailboxes. The firmware may leave them dirty */ + out64(0xffffffffffffffff, + KSEG1 + A_IMR_REGISTER(0, R_IMR_MAILBOX_CLR_CPU)); + out64(0xffffffffffffffff, + KSEG1 + A_IMR_REGISTER(1, R_IMR_MAILBOX_CLR_CPU)); + + /* Mask everything except the mailbox registers for both cpus */ + tmp = ~((u64) 0) ^ (((u64) 1) << K_INT_MBOX_0); + out64(tmp, KSEG1 + A_IMR_REGISTER(0, R_IMR_INTERRUPT_MASK)); + out64(tmp, KSEG1 + A_IMR_REGISTER(1, R_IMR_INTERRUPT_MASK)); + + sb1250_steal_irq(K_INT_MBOX_0); + + /* + * Note that the timer interrupts are also mapped, but this is + * done in sb1250_time_init() + */ + +#ifdef CONFIG_BCM1250_PROF + imask |= STATUSF_IP7; +#endif +#ifdef CONFIG_KGDB + imask |= STATUSF_IP6; +#endif + /* Enable necessary IPs, disable the rest */ + change_c0_status(ST0_IM, imask); + set_except_vector(0, sb1250_irq_handler); + +#ifdef CONFIG_KGDB + if (kgdb_flag) { + /* Setup uart 1 settings, mapper */ + out64(M_DUART_IMR_BRK, KSEG1 + A_DUART + R_DUART_IMR_B); + + out64(IMR_IP6_VAL, + KSEG1 + A_IMR_REGISTER(0, R_IMR_INTERRUPT_MAP_BASE) + (K_INT_UART_1<<3)); + tmp = in64(KSEG1 + A_IMR_REGISTER(0, R_IMR_INTERRUPT_MASK)); + tmp &= ~(1< + +extern void set_async_breakpoint(unsigned int epc); + +#define duart_out(reg, val) out64(val, KSEG1 + A_DUART_CHANREG(1,reg)) +#define duart_in(reg) in64(KSEG1 + A_DUART_CHANREG(1,reg)) + +void sb1250_kgdb_interrupt(struct pt_regs *regs) +{ + /* + * Clear break-change status (allow some time for the remote + * host to stop the break, since we would see another + * interrupt on the end-of-break too) + */ + mdelay(500); + duart_out(R_DUART_CMD, V_DUART_MISC_CMD_RESET_BREAK_INT | + M_DUART_RX_EN | M_DUART_TX_EN); + if (!user_mode(regs)) + set_async_breakpoint(regs->cp0_epc); +} +#endif /* CONFIG_KGDB */ diff -Nru a/arch/mips/sibyte/sb1250/irq_handler.S b/arch/mips/sibyte/sb1250/irq_handler.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sibyte/sb1250/irq_handler.S Tue Jul 1 18:44:40 2003 @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2000, 2001 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * sb1250_handle_int() is the routine that is actually called when an interrupt + * occurs. It is installed as the exception vector handler in init_IRQ() in + * arch/mips/sibyte/sb1250/irq.c + * + * In the handle we figure out which interrupts need handling, and use that to + * call the dispatcher, which will take care of actually calling registered + * handlers + * + * Note that we take care of all raised interrupts in one go at the handler. + * This is more BSDish than the Indy code, and also, IMHO, more sane. + */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * What a pain. We have to be really careful saving the upper 32 bits of any + * register across function calls if we don't want them trashed--since were + * running in -o32, the calling routing never saves the full 64 bits of a + * register across a function call. Being the interrupt handler, we're + * guaranteed that interrupts are disabled during this code so we don't have + * to worry about random interrupts blasting the high 32 bits. + */ + + .text + .set push + .set noreorder + .set noat + #.set mips64 + .set mips4 + .align 5 + NESTED(sb1250_irq_handler, PT_SIZE, sp) + SAVE_ALL + CLI + +#ifdef CONFIG_SIBYTE_SB1250_PROF + /* Set compare to count to silence count/compare timer interrupts */ + mfc0 t1, CP0_COUNT + mtc0 t1, CP0_COMPARE /* pause to clear IP[7] bit of cause ? */ +#endif + /* Read cause */ + mfc0 s0, CP0_CAUSE + +#ifdef CONFIG_SIBYTE_SB1250_PROF + /* Cpu performance counter interrupt is routed to IP[7] */ + andi t1, s0, CAUSEF_IP7 + beqz t1, 0f + srl t1, s0, (CAUSEB_BD-2) /* Shift BD bit to bit 2 */ + and t1, t1, 0x4 /* mask to get just BD bit */ + mfc0 a0, CP0_EPC + jal sbprof_cpu_intr + addu a0, a0, t1 /* a0 = EPC + (BD ? 4 : 0) */ + /* Re-enable interrupts here so that events due to sbprof_cpu_intr + get charged to ret_from_irq (via a recursive interrupt) + rather than the restart pc. */ + mfc0 t0, CP0_STATUS + or t0, ST0_IE + j ret_from_irq + mtc0 t0, CP0_STATUS # delay slot +0: +#endif + /* Timer interrupt is routed to IP[4] */ + andi t1, s0, CAUSEF_IP4 + beqz t1, 1f + nop + jal sb1250_timer_interrupt + move a0, sp /* Pass the registers along */ + j ret_from_irq + nop # delay slot +1: + +#ifdef CONFIG_SMP + /* Mailbox interrupt is routed to IP[3] */ + andi t1, s0, CAUSEF_IP3 + beqz t1, 2f + nop + jal sb1250_mailbox_interrupt + move a0, sp + j ret_from_irq + nop # delay slot +2: +#endif + +#ifdef CONFIG_KGDB + /* KGDB (uart 1) interrupt is routed to IP[6] */ + andi t1, s0, CAUSEF_IP6 + beqz t1, 1f + nop # delay slot + jal sb1250_kgdb_interrupt + move a0, sp + j ret_from_irq + nop # delay slot +1: +#endif + + and t1, s0, CAUSEF_IP2 + beqz t1, 4f + nop + + /* + * Default...we've hit an IP[2] interrupt, which means we've got to + * check the 1250 interrupt registers to figure out what to do + * Need to detect which CPU we're on, now that smp_affinity is supported. + */ + la v0, KSEG1 + A_IMR_CPU0_BASE +#ifdef CONFIG_SMP + lw t1, TI_CPU($28) + sll t1, IMR_REGISTER_SPACING_SHIFT + addu v0, t1 +#endif + ld s0, R_IMR_INTERRUPT_STATUS_BASE(v0) /* read IP[2] status */ + + beqz s0, 4f /* No interrupts. Return */ + move a1, sp + +3: #dclz s1, s0 /* Find the next interrupt */ + .word 0x72118824 # dclz s1, s0 + dsubu a0, zero, s1 + daddiu a0, a0, 63 + jal do_IRQ + nop + +4: j ret_from_irq + nop + + .set pop + END(sb1250_irq_handler) diff -Nru a/arch/mips/sibyte/sb1250/prom.c b/arch/mips/sibyte/sb1250/prom.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sibyte/sb1250/prom.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2000, 2001 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +extern char arcs_cmdline[]; + +#ifdef CONFIG_EMBEDDED_RAMDISK +/* These are symbols defined by the ramdisk linker script */ +extern unsigned char __rd_start; +extern unsigned char __rd_end; +#endif + +#define MAX_RAM_SIZE ((CONFIG_SIBYTE_STANDALONE_RAM_SIZE * 1024 * 1024) - 1) + +static __init void prom_meminit(void) +{ +#ifdef CONFIG_BLK_DEV_INITRD + unsigned long initrd_pstart; + unsigned long initrd_pend; + +#ifdef CONFIG_EMBEDDED_RAMDISK + /* If we're using an embedded ramdisk, then __rd_start and __rd_end + are defined by the linker to be on either side of the ramdisk + area. Otherwise, initrd_start should be defined by kernel command + line arguments */ + if (initrd_start == 0) { + initrd_start = (unsigned long)&__rd_start; + initrd_end = (unsigned long)&__rd_end; + } +#endif + + initrd_pstart = __pa(initrd_start); + initrd_pend = __pa(initrd_end); + if (initrd_start && + ((initrd_pstart > MAX_RAM_SIZE) + || (initrd_pend > MAX_RAM_SIZE))) { + panic("initrd out of addressable memory"); + } + + add_memory_region(0, initrd_pstart, + BOOT_MEM_RAM); + add_memory_region(initrd_pstart, initrd_pend - initrd_pstart, + BOOT_MEM_RESERVED); + add_memory_region(initrd_pend, + (CONFIG_SIBYTE_STANDALONE_RAM_SIZE * 1024 * 1024) - initrd_pend, + BOOT_MEM_RAM); +#else + add_memory_region(0, CONFIG_SIBYTE_STANDALONE_RAM_SIZE * 1024 * 1024, + BOOT_MEM_RAM); +#endif +} + +void prom_cpu0_exit(void *unused) +{ + while (1) ; +} + +static void prom_linux_exit(void) +{ +#ifdef CONFIG_SMP + if (smp_processor_id()) { + smp_call_function(prom_cpu0_exit,NULL,1,1); + } +#endif + while(1); +} + +/* + * prom_init is called just after the cpu type is determined, from init_arch() + */ +__init int prom_init(int argc, char **argv, char **envp, int *prom_vec) +{ + _machine_restart = (void (*)(char *))prom_linux_exit; + _machine_halt = prom_linux_exit; + _machine_power_off = prom_linux_exit; + + strcpy(arcs_cmdline, "root=/dev/ram0 "); + + mips_machgroup = MACH_GROUP_SIBYTE; + prom_meminit(); + + return 0; +} + +void prom_free_prom_memory(void) +{ + /* Not sure what I'm supposed to do here. Nothing, I think */ +} + +int page_is_ram(unsigned long pagenr) +{ + phys_t addr = pagenr << PAGE_SHIFT; + return (addr < (CONFIG_SIBYTE_STANDALONE_RAM_SIZE * 1024 * 1024)); +} + +void prom_putchar(char c) +{ +} diff -Nru a/arch/mips/sibyte/sb1250/setup.c b/arch/mips/sibyte/sb1250/setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sibyte/sb1250/setup.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,198 @@ +/* + * Copyright (C) 2000, 2001, 2002, 2003 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +unsigned int sb1_pass; +unsigned int soc_pass; +unsigned int soc_type; +unsigned int periph_rev; + +static char *soc_str; +static char *pass_str; +static unsigned int war_pass; /* XXXKW don't overload PASS defines? */ + +static inline int setup_bcm1250(void); +static inline int setup_bcm112x(void); + +/* Setup code likely to be common to all SiByte platforms */ + +static inline int sys_rev_decode(void) +{ + int ret = 0; + + war_pass = soc_pass; + switch (soc_type) { + case K_SYS_SOC_TYPE_BCM1250: + case K_SYS_SOC_TYPE_BCM1250_ALT: + case K_SYS_SOC_TYPE_BCM1250_ALT2: + soc_str = "BCM1250"; + ret = setup_bcm1250(); + break; + case K_SYS_SOC_TYPE_BCM1120: + soc_str = "BCM1120"; + ret = setup_bcm112x(); + break; + case K_SYS_SOC_TYPE_BCM1125: + soc_str = "BCM1125"; + ret = setup_bcm112x(); + break; + case K_SYS_SOC_TYPE_BCM1125H: + soc_str = "BCM1125H"; + ret = setup_bcm112x(); + break; + default: + prom_printf("Unknown SOC type %x\n", soc_type); + ret = 1; + break; + } + return ret; +} + +static inline int setup_bcm1250(void) +{ + int ret = 0; + + switch (soc_pass) { + case K_SYS_REVISION_BCM1250_PASS1: + periph_rev = 1; + pass_str = "Pass 1"; + break; + case K_SYS_REVISION_BCM1250_A10: + periph_rev = 2; + pass_str = "A8/A10"; + /* XXXKW different war_pass? */ + war_pass = K_SYS_REVISION_BCM1250_PASS2; + break; + case K_SYS_REVISION_BCM1250_PASS2_2: + periph_rev = 2; + pass_str = "B1"; + break; + case K_SYS_REVISION_BCM1250_B2: + periph_rev = 2; + pass_str = "B2"; + war_pass = K_SYS_REVISION_BCM1250_PASS2_2; + break; + case K_SYS_REVISION_BCM1250_PASS3: + periph_rev = 3; + pass_str = "C0"; + break; + default: + if (soc_pass < K_SYS_REVISION_BCM1250_PASS2_2) { + periph_rev = 2; + pass_str = "A0-A6"; + war_pass = K_SYS_REVISION_BCM1250_PASS2; + } else { + prom_printf("Unknown BCM1250 rev %x\n", soc_pass); + ret = 1; + } + break; + } + return ret; +} + +static inline int setup_bcm112x(void) +{ + int ret = 0; + + switch (soc_pass) { + case 0: + /* Early build didn't have revid set */ + periph_rev = 3; + pass_str = "A1"; + war_pass = K_SYS_REVISION_BCM112x_A1; + break; + case K_SYS_REVISION_BCM112x_A1: + periph_rev = 3; + pass_str = "A1"; + break; + case K_SYS_REVISION_BCM112x_A2: + periph_rev = 3; + pass_str = "A2"; + break; + default: + prom_printf("Unknown %s rev %x\n", soc_str, soc_pass); + ret = 1; + } + return ret; +} + +void sb1250_setup(void) +{ + uint64_t sys_rev; + int bad_config = 0; + + sb1_pass = read_c0_prid() & 0xff; + sys_rev = in64(IO_SPACE_BASE | A_SCD_SYSTEM_REVISION); + soc_type = SYS_SOC_TYPE(sys_rev); + soc_pass = G_SYS_REVISION(sys_rev); + + if (sys_rev_decode()) { + prom_printf("Restart after failure to identify SiByte chip\n"); + machine_restart(NULL); + } + + prom_printf("SiByte %s %s (SB1 rev %d)\n", + soc_str, pass_str, sb1_pass); + prom_printf("Board type: %s\n", get_system_type()); + + switch(war_pass) { + case K_SYS_REVISION_BCM1250_PASS1: +#ifndef CONFIG_SB1_PASS_1_WORKAROUNDS + prom_printf("@@@@ This is a BCM1250 A0-A2 (Pass 1) board, and the kernel doesn't have the proper workarounds compiled in. @@@@\n"); + bad_config = 1; +#endif + break; + case K_SYS_REVISION_BCM1250_PASS2: + /* Pass 2 - easiest as default for now - so many numbers */ +#if !defined(CONFIG_SB1_PASS_2_WORKAROUNDS) || !defined(CONFIG_SB1_PASS_2_1_WORKAROUNDS) + prom_printf("@@@@ This is a BCM1250 A3-A10 board, and the kernel doesn't have the proper workarounds compiled in. @@@@\n"); + bad_config = 1; +#endif +#ifdef CONFIG_CPU_HAS_PREFETCH + prom_printf("@@@@ Prefetches may be enabled in this kernel, but are buggy on this board. @@@@\n"); + bad_config = 1; +#endif + break; + case K_SYS_REVISION_BCM1250_PASS2_2: +#ifndef CONFIG_SB1_PASS_2_WORKAROUNDS + prom_printf("@@@@ This is a BCM1250 B1/B2. board, and the kernel doesn't have the proper workarounds compiled in. @@@@\n"); + bad_config = 1; +#endif +#if defined(CONFIG_SB1_PASS_2_1_WORKAROUNDS) || !defined(CONFIG_CPU_HAS_PREFETCH) + prom_printf("@@@@ This is a BCM1250 B1/B2, but the kernel is conservatively configured for an 'A' stepping. @@@@\n"); +#endif + break; + default: + break; + } + if (bad_config) { + prom_printf("Invalid configuration for this chip.\n"); + machine_restart(NULL); + } +} diff -Nru a/arch/mips/sibyte/sb1250/smp.c b/arch/mips/sibyte/sb1250/smp.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sibyte/sb1250/smp.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2001 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +extern irqreturn_t smp_call_function_interrupt(int irq, void *dev, + struct pt_regs *regs); +extern void smp_tune_scheduling(void); + +/* + * These are routines for dealing with the sb1250 smp capabilities + * independent of board/firmware + */ + +static u64 mailbox_set_regs[] = { + KSEG1 + A_IMR_CPU0_BASE + R_IMR_MAILBOX_SET_CPU, + KSEG1 + A_IMR_CPU1_BASE + R_IMR_MAILBOX_SET_CPU +}; + +static u64 mailbox_clear_regs[] = { + KSEG1 + A_IMR_CPU0_BASE + R_IMR_MAILBOX_CLR_CPU, + KSEG1 + A_IMR_CPU1_BASE + R_IMR_MAILBOX_CLR_CPU +}; + +static u64 mailbox_regs[] = { + KSEG1 + A_IMR_CPU0_BASE + R_IMR_MAILBOX_CPU, + KSEG1 + A_IMR_CPU1_BASE + R_IMR_MAILBOX_CPU +}; + + +/* + * Simple enough; everything is set up, so just poke the appropriate mailbox + * register, and we should be set + */ +void core_send_ipi(int cpu, unsigned int action) +{ + out64((((u64)action)<< 48), mailbox_set_regs[cpu]); +} + + +void sb1250_smp_finish(void) +{ + extern void sb1_sanitize_tlb(void); + + sb1_sanitize_tlb(); + sb1250_time_init(); +} + +void sb1250_mailbox_interrupt(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + unsigned int action; + + kstat_cpu(cpu).irqs[K_INT_MBOX_0]++; + /* Load the mailbox register to figure out what we're supposed to do */ + action = (in64(mailbox_regs[cpu]) >> 48) & 0xffff; + + /* Clear the mailbox to clear the interrupt */ + out64(((u64)action)<<48, mailbox_clear_regs[cpu]); + + /* + * Nothing to do for SMP_RESCHEDULE_YOURSELF; returning from the + * interrupt will do the reschedule for us + */ + + if (action & SMP_CALL_FUNCTION) { + smp_call_function_interrupt(0, NULL, regs); + } +} + +extern atomic_t cpus_booted; +extern void prom_setup_smp(void); +extern int prom_boot_secondary(int cpu, unsigned long sp, unsigned long gp); + +void __init smp_boot_cpus(void) +{ + int cur_cpu = 0; + int cpu; + + prom_setup_smp(); + init_new_context(current, &init_mm); + current_thread_info()->cpu = 0; + cpu_data[0].udelay_val = loops_per_jiffy; + cpu_data[0].asid_cache = ASID_FIRST_VERSION; + CPUMASK_CLRALL(cpu_online_map); + CPUMASK_SETB(cpu_online_map, 0); + atomic_set(&cpus_booted, 1); /* Master CPU is already booted... */ + smp_tune_scheduling(); + + /* + * This loop attempts to compensate for "holes" in the CPU + * numbering. It's overkill, but general. + */ + for (cpu = 1; cpu < num_online_cpus(); ) { + struct task_struct *idle; + struct pt_regs regs; + int retval; + printk("Starting CPU %d... ", cpu); + + /* Spawn a new process normally. Grab a pointer to + its task struct so we can mess with it */ + idle = copy_process(CLONE_VM | CLONE_IDLETASK, 0, ®s, 0, + NULL, NULL); + if (IS_ERR(idle)) + panic("failed fork for CPU %d", cpu); + + /* + * We remove it from the pidhash and the runqueue + * once we got the process: + */ + init_idle(idle, cpu); + + unhash_process(idle); + + do { + /* Iterate until we find a CPU that comes up */ + cur_cpu++; + retval = prom_boot_secondary(cur_cpu, + (unsigned long)idle + KERNEL_STACK_SIZE - 32, + (unsigned long)idle); + } while (!retval && (cur_cpu < NR_CPUS)); + if (retval) { + cpu++; + } else { + panic("CPU discovery disaster"); + } + } + + /* Wait for everyone to come up */ + while (atomic_read(&cpus_booted) != num_online_cpus()); + smp_threads_ready = 1; +} diff -Nru a/arch/mips/sibyte/sb1250/time.c b/arch/mips/sibyte/sb1250/time.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sibyte/sb1250/time.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2000, 2001 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * These are routines to set up and handle interrupts from the + * sb1250 general purpose timer 0. We're using the timer as a + * system clock, so we set it up to run at 100 Hz. On every + * interrupt, we update our idea of what the time of day is, + * then call do_timer() in the architecture-independent kernel + * code to do general bookkeeping (e.g. update jiffies, run + * bottom halves, etc.) + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +#define IMR_IP2_VAL K_INT_MAP_I0 +#define IMR_IP3_VAL K_INT_MAP_I1 +#define IMR_IP4_VAL K_INT_MAP_I2 + +extern int sb1250_steal_irq(int irq); + +void sb1250_time_init(void) +{ + int cpu = smp_processor_id(); + int irq = K_INT_TIMER_0+cpu; + + /* Only have 4 general purpose timers */ + if (cpu > 3) { + BUG(); + } + + if (!cpu) { + /* Use our own gettimeoffset() routine */ + do_gettimeoffset = sb1250_gettimeoffset; + } + + sb1250_mask_irq(cpu, irq); + + /* Map the timer interrupt to ip[4] of this cpu */ + out64(IMR_IP4_VAL, KSEG1 + A_IMR_REGISTER(cpu, R_IMR_INTERRUPT_MAP_BASE) + + (irq<<3)); + + /* the general purpose timer ticks at 1 Mhz independent if the rest of the system */ + /* Disable the timer and set up the count */ + out64(0, KSEG1 + A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); + out64( +#ifndef CONFIG_SIMULATION + 1000000/HZ +#else + 50000/HZ +#endif + , KSEG1 + A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_INIT)); + + /* Set the timer running */ + out64(M_SCD_TIMER_ENABLE|M_SCD_TIMER_MODE_CONTINUOUS, + KSEG1 + A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); + + sb1250_unmask_irq(cpu, irq); + sb1250_steal_irq(irq); + /* + * This interrupt is "special" in that it doesn't use the request_irq + * way to hook the irq line. The timer interrupt is initialized early + * enough to make this a major pain, and it's also firing enough to + * warrant a bit of special case code. sb1250_timer_interrupt is + * called directly from irq_handler.S when IP[4] is set during an + * interrupt + */ +} + +void sb1250_timer_interrupt(struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + int irq = K_INT_TIMER_0 + cpu; + + kstat_cpu(cpu).irqs[irq]++; + /* Reset the timer */ + out64(M_SCD_TIMER_ENABLE|M_SCD_TIMER_MODE_CONTINUOUS, + KSEG1 + A_SCD_TIMER_REGISTER(cpu, R_SCD_TIMER_CFG)); + + /* + * CPU 0 handles the global timer interrupt job + */ + if (cpu == 0) { + ll_timer_interrupt(irq, regs); + } + + /* + * every CPU should do profiling and process accouting + */ + ll_local_timer_interrupt(irq, regs); +} + +/* + * We use our own do_gettimeoffset() instead of the generic one, + * because the generic one does not work for SMP case. + * In addition, since we use general timer 0 for system time, + * we can get accurate intra-jiffy offset without calibration. + */ +unsigned long sb1250_gettimeoffset(void) +{ + unsigned long count = + in64(KSEG1 + A_SCD_TIMER_REGISTER(0, R_SCD_TIMER_CNT)); + + return 1000000/HZ - count; + } diff -Nru a/arch/mips/sibyte/swarm/Makefile b/arch/mips/sibyte/swarm/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sibyte/swarm/Makefile Tue Jul 1 18:44:40 2003 @@ -0,0 +1,3 @@ +lib-y = setup.o cmdline.o rtc_xicor1241.o rtc_m41t81.o + +lib-$(CONFIG_KGDB) += dbg_io.o diff -Nru a/arch/mips/sibyte/swarm/cmdline.c b/arch/mips/sibyte/swarm/cmdline.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sibyte/swarm/cmdline.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2000, 2001 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#include + +/* + * The naming of this variable is a remnant of the initial mips port to + * ARC-firmware based SGI consoles. We don't really need to do anything for + * the variable other than provide an instantiation. Everything about + * arcs_cmdline seems more than a little bit hackish... + */ +char arcs_cmdline[CL_SIZE]; diff -Nru a/arch/mips/sibyte/swarm/dbg_io.c b/arch/mips/sibyte/swarm/dbg_io.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sibyte/swarm/dbg_io.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,78 @@ +/* + * kgdb debug routines for swarm board. + * + * Copyright (C) 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +/* -------------------- BEGINNING OF CONFIG --------------------- */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * We use the second serial port for kgdb traffic. + * 115200, 8, N, 1. + */ + +#define BAUD_RATE 115200 +#define CLK_DIVISOR V_DUART_BAUD_RATE(BAUD_RATE) +#define DATA_BITS V_DUART_BITS_PER_CHAR_8 /* or 7 */ +#define PARITY V_DUART_PARITY_MODE_NONE /* or even */ +#define STOP_BITS M_DUART_STOP_BIT_LEN_1 /* or 2 */ + +static int duart_initialized = 0; /* 0: need to be init'ed by kgdb */ + +/* -------------------- END OF CONFIG --------------------- */ + + +#define duart_out(reg, val) out64(val, KSEG1 + A_DUART_CHANREG(1,reg)) +#define duart_in(reg) in64(KSEG1 + A_DUART_CHANREG(1,reg)) + +extern void set_async_breakpoint(unsigned int epc); + +void putDebugChar(unsigned char c); +unsigned char getDebugChar(void); +static void +duart_init(int clk_divisor, int data, int parity, int stop) +{ + duart_out(R_DUART_MODE_REG_1, data | parity); + duart_out(R_DUART_MODE_REG_2, stop); + duart_out(R_DUART_CLK_SEL, clk_divisor); + + duart_out(R_DUART_CMD, M_DUART_RX_EN | M_DUART_TX_EN); /* enable rx and tx */ +} + +void +putDebugChar(unsigned char c) +{ + if (!duart_initialized) { + duart_initialized = 1; + duart_init(CLK_DIVISOR, DATA_BITS, PARITY, STOP_BITS); + } + while ((duart_in(R_DUART_STATUS) & M_DUART_TX_RDY) == 0); + duart_out(R_DUART_TX_HOLD, c); +} + +unsigned char +getDebugChar(void) +{ + if (!duart_initialized) { + duart_initialized = 1; + duart_init(CLK_DIVISOR, DATA_BITS, PARITY, STOP_BITS); + } + while ((duart_in(R_DUART_STATUS) & M_DUART_RX_RDY) == 0) ; + return duart_in(R_DUART_RX_HOLD); +} + diff -Nru a/arch/mips/sibyte/swarm/rtc.c b/arch/mips/sibyte/swarm/rtc.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sibyte/swarm/rtc.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2000, 2001 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * Not really sure what is supposed to be here, yet + */ + +#include +#include + +static unsigned char swarm_rtc_read_data(unsigned long addr) +{ + return 0; +} + +static void swarm_rtc_write_data(unsigned char data, unsigned long addr) +{ +} + +static int swarm_rtc_bcd_mode(void) +{ + return 0; +} + +struct rtc_ops swarm_rtc_ops = { + &swarm_rtc_read_data, + &swarm_rtc_write_data, + &swarm_rtc_bcd_mode +}; diff -Nru a/arch/mips/sibyte/swarm/rtc_m41t81.c b/arch/mips/sibyte/swarm/rtc_m41t81.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sibyte/swarm/rtc_m41t81.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,222 @@ +/* + * Copyright (C) 2000, 2001 Broadcom Corporation + * + * Copyright (C) 2002 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + + +/* M41T81 definitions */ + +/* + * Register bits + */ + +#define M41T81REG_SC_ST 0x80 /* stop bit */ +#define M41T81REG_HR_CB 0x40 /* century bit */ +#define M41T81REG_HR_CEB 0x80 /* century enable bit */ +#define M41T81REG_CTL_S 0x20 /* sign bit */ +#define M41T81REG_CTL_FT 0x40 /* frequency test bit */ +#define M41T81REG_CTL_OUT 0x80 /* output level */ +#define M41T81REG_WD_RB0 0x01 /* watchdog resolution bit 0 */ +#define M41T81REG_WD_RB1 0x02 /* watchdog resolution bit 1 */ +#define M41T81REG_WD_BMB0 0x04 /* watchdog multiplier bit 0 */ +#define M41T81REG_WD_BMB1 0x08 /* watchdog multiplier bit 1 */ +#define M41T81REG_WD_BMB2 0x10 /* watchdog multiplier bit 2 */ +#define M41T81REG_WD_BMB3 0x20 /* watchdog multiplier bit 3 */ +#define M41T81REG_WD_BMB4 0x40 /* watchdog multiplier bit 4 */ +#define M41T81REG_AMO_ABE 0x20 /* alarm in "battery back-up mode" enable bit */ +#define M41T81REG_AMO_SQWE 0x40 /* square wave enable */ +#define M41T81REG_AMO_AFE 0x80 /* alarm flag enable flag */ +#define M41T81REG_ADT_RPT5 0x40 /* alarm repeat mode bit 5 */ +#define M41T81REG_ADT_RPT4 0x80 /* alarm repeat mode bit 4 */ +#define M41T81REG_AHR_RPT3 0x80 /* alarm repeat mode bit 3 */ +#define M41T81REG_AHR_HT 0x40 /* halt update bit */ +#define M41T81REG_AMN_RPT2 0x80 /* alarm repeat mode bit 2 */ +#define M41T81REG_ASC_RPT1 0x80 /* alarm repeat mode bit 1 */ +#define M41T81REG_FLG_AF 0x40 /* alarm flag (read only) */ +#define M41T81REG_FLG_WDF 0x80 /* watchdog flag (read only) */ +#define M41T81REG_SQW_RS0 0x10 /* sqw frequency bit 0 */ +#define M41T81REG_SQW_RS1 0x20 /* sqw frequency bit 1 */ +#define M41T81REG_SQW_RS2 0x40 /* sqw frequency bit 2 */ +#define M41T81REG_SQW_RS3 0x80 /* sqw frequency bit 3 */ + + +/* + * Register numbers + */ + +#define M41T81REG_TSC 0x00 /* tenths/hundredths of second */ +#define M41T81REG_SC 0x01 /* seconds */ +#define M41T81REG_MN 0x02 /* minute */ +#define M41T81REG_HR 0x03 /* hour/century */ +#define M41T81REG_DY 0x04 /* day of week */ +#define M41T81REG_DT 0x05 /* date of month */ +#define M41T81REG_MO 0x06 /* month */ +#define M41T81REG_YR 0x07 /* year */ +#define M41T81REG_CTL 0x08 /* control */ +#define M41T81REG_WD 0x09 /* watchdog */ +#define M41T81REG_AMO 0x0A /* alarm: month */ +#define M41T81REG_ADT 0x0B /* alarm: date */ +#define M41T81REG_AHR 0x0C /* alarm: hour */ +#define M41T81REG_AMN 0x0D /* alarm: minute */ +#define M41T81REG_ASC 0x0E /* alarm: second */ +#define M41T81REG_FLG 0x0F /* flags */ +#define M41T81REG_SQW 0x13 /* square wave register */ + +#define M41T81_CCR_ADDRESS 0x68 +#define SMB_CSR(reg) (KSEG1 | A_SMB_REGISTER(1, reg)) + +static int m41t81_read(uint8_t addr) +{ + while (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) + ; + + out64(addr & 0xff, SMB_CSR(R_SMB_CMD)); + out64((V_SMB_ADDR(M41T81_CCR_ADDRESS) | V_SMB_TT_WR1BYTE), SMB_CSR(R_SMB_START)); + + while (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) + ; + + out64((V_SMB_ADDR(M41T81_CCR_ADDRESS) | V_SMB_TT_RD1BYTE), SMB_CSR(R_SMB_START)); + + while (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) + ; + + if (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) { + /* Clear error bit by writing a 1 */ + out64(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS)); + return -1; + } + + return (in64(SMB_CSR(R_SMB_DATA)) & 0xff); +} + +static int m41t81_write(uint8_t addr, int b) +{ + while (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) + ; + + out64((addr & 0xFF), SMB_CSR(R_SMB_CMD)); + out64((b & 0xff), SMB_CSR(R_SMB_DATA)); + out64(V_SMB_ADDR(M41T81_CCR_ADDRESS) | V_SMB_TT_WR2BYTE, + SMB_CSR(R_SMB_START)); + + while (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) + ; + + if (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) { + /* Clear error bit by writing a 1 */ + out64(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS)); + return -1; + } + + /* read the same byte again to make sure it is written */ + out64(V_SMB_ADDR(M41T81_CCR_ADDRESS) | V_SMB_TT_RD1BYTE, + SMB_CSR(R_SMB_START)); + + while (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) + ; + + return 0; +} + +int m41t81_set_time(unsigned long t) +{ + struct rtc_time tm; + + to_tm(t, &tm); + + /* + * Note the write order matters as it ensures the correctness. + * When we write sec, 10th sec is clear. It is reasonable to + * believe we should finish writing min within a second. + */ + + tm.tm_sec = BIN2BCD(tm.tm_sec); + m41t81_write(M41T81REG_SC, tm.tm_sec); + + tm.tm_min = BIN2BCD(tm.tm_min); + m41t81_write(M41T81REG_MN, tm.tm_min); + + tm.tm_hour = BIN2BCD(tm.tm_hour); + tm.tm_hour = (tm.tm_hour & 0x3f) | (m41t81_read(M41T81REG_HR) & 0xc0); + m41t81_write(M41T81REG_HR, tm.tm_hour); + + /* tm_wday starts from 0 to 6 */ + if (tm.tm_wday == 0) tm.tm_wday = 7; + tm.tm_wday = BIN2BCD(tm.tm_wday); + m41t81_write(M41T81REG_DY, tm.tm_wday); + + tm.tm_mday = BIN2BCD(tm.tm_mday); + m41t81_write(M41T81REG_DT, tm.tm_mday); + + /* tm_mon starts from 0, *ick* */ + tm.tm_mon ++; + tm.tm_mon = BIN2BCD(tm.tm_mon); + m41t81_write(M41T81REG_MO, tm.tm_mon); + + /* we don't do century, everything is beyond 2000 */ + tm.tm_year %= 100; + tm.tm_year = BIN2BCD(tm.tm_year); + m41t81_write(M41T81REG_YR, tm.tm_year); + + return 0; +} + +unsigned long m41t81_get_time(void) +{ + unsigned int year, mon, day, hour, min, sec; + + /* + * min is valid if two reads of sec are the same. + */ + for (;;) { + sec = m41t81_read(M41T81REG_SC); + min = m41t81_read(M41T81REG_MN); + if (sec == m41t81_read(M41T81REG_SC)) break; + } + hour = m41t81_read(M41T81REG_HR) & 0x3f; + day = m41t81_read(M41T81REG_DT); + mon = m41t81_read(M41T81REG_MO); + year = m41t81_read(M41T81REG_YR); + + sec = BCD2BIN(sec); + min = BCD2BIN(min); + hour = BCD2BIN(hour); + day = BCD2BIN(day); + mon = BCD2BIN(mon); + year = BCD2BIN(year); + + year += 2000; + + return mktime(year, mon, day, hour, min, sec); +} + +int m41t81_probe(void) +{ + unsigned int tmp; + + /* enable chip if it is not enabled yet */ + tmp = m41t81_read(M41T81REG_SC); + m41t81_write(M41T81REG_SC, tmp & 0x7f); + + return (m41t81_read(M41T81REG_SC) != -1); +} diff -Nru a/arch/mips/sibyte/swarm/rtc_xicor1241.c b/arch/mips/sibyte/swarm/rtc_xicor1241.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sibyte/swarm/rtc_xicor1241.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2000, 2001 Broadcom Corporation + * + * Copyright (C) 2002 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + + +/* Xicor 1241 definitions */ + +/* + * Register bits + */ + +#define X1241REG_SR_BAT 0x80 /* currently on battery power */ +#define X1241REG_SR_RWEL 0x04 /* r/w latch is enabled, can write RTC */ +#define X1241REG_SR_WEL 0x02 /* r/w latch is unlocked, can enable r/w now */ +#define X1241REG_SR_RTCF 0x01 /* clock failed */ +#define X1241REG_BL_BP2 0x80 /* block protect 2 */ +#define X1241REG_BL_BP1 0x40 /* block protect 1 */ +#define X1241REG_BL_BP0 0x20 /* block protect 0 */ +#define X1241REG_BL_WD1 0x10 +#define X1241REG_BL_WD0 0x08 +#define X1241REG_HR_MIL 0x80 /* military time format */ + +/* + * Register numbers + */ + +#define X1241REG_BL 0x10 /* block protect bits */ +#define X1241REG_INT 0x11 /* */ +#define X1241REG_SC 0x30 /* Seconds */ +#define X1241REG_MN 0x31 /* Minutes */ +#define X1241REG_HR 0x32 /* Hours */ +#define X1241REG_DT 0x33 /* Day of month */ +#define X1241REG_MO 0x34 /* Month */ +#define X1241REG_YR 0x35 /* Year */ +#define X1241REG_DW 0x36 /* Day of Week */ +#define X1241REG_Y2K 0x37 /* Year 2K */ +#define X1241REG_SR 0x3F /* Status register */ + +#define X1241_CCR_ADDRESS 0x6F + +#define SMB_CSR(reg) (KSEG1 | A_SMB_REGISTER(1, reg)) + +static int xicor_read(uint8_t addr) +{ + while (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) + ; + + out64((addr >> 8) & 0x7, SMB_CSR(R_SMB_CMD)); + out64((addr & 0xff), SMB_CSR(R_SMB_DATA)); + out64((V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR2BYTE), SMB_CSR(R_SMB_START)); + + while (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) + ; + + out64((V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_RD1BYTE), SMB_CSR(R_SMB_START)); + + while (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) + ; + + if (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) { + /* Clear error bit by writing a 1 */ + out64(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS)); + return -1; + } + + return (in64(SMB_CSR(R_SMB_DATA)) & 0xff); +} + +static int xicor_write(uint8_t addr, int b) +{ + while (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) + ; + + out64(addr, SMB_CSR(R_SMB_CMD)); + out64((addr & 0xff) | ((b & 0xff) << 8), SMB_CSR(R_SMB_DATA)); + out64(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR3BYTE, + SMB_CSR(R_SMB_START)); + + while (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) + ; + + if (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) { + /* Clear error bit by writing a 1 */ + out64(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS)); + return -1; + } else { + return 0; + } +} + +int xicor_set_time(unsigned long t) +{ + struct rtc_time tm; + int tmp; + + to_tm(t, &tm); + + /* unlock writes to the CCR */ + xicor_write(X1241REG_SR, X1241REG_SR_WEL); + xicor_write(X1241REG_SR, X1241REG_SR_WEL | X1241REG_SR_RWEL); + + /* trivial ones */ + tm.tm_sec = BIN2BCD(tm.tm_sec); + xicor_write(X1241REG_SC, tm.tm_sec); + + tm.tm_min = BIN2BCD(tm.tm_min); + xicor_write(X1241REG_MN, tm.tm_min); + + tm.tm_mday = BIN2BCD(tm.tm_mday); + xicor_write(X1241REG_DT, tm.tm_mday); + + /* tm_mon starts from 0, *ick* */ + tm.tm_mon ++; + tm.tm_mon = BIN2BCD(tm.tm_mon); + xicor_write(X1241REG_MO, tm.tm_mon); + + /* year is split */ + tmp = tm.tm_year / 100; + tm.tm_year %= 100; + xicor_write(X1241REG_YR, tm.tm_year); + xicor_write(X1241REG_Y2K, tmp); + + /* hour is the most tricky one */ + tmp = xicor_read(X1241REG_HR); + if (tmp & X1241REG_HR_MIL) { + /* 24 hour format */ + tm.tm_hour = BIN2BCD(tm.tm_hour); + tmp = (tmp & ~0x3f) | (tm.tm_hour & 0x3f); + } else { + /* 12 hour format, with 0x2 for pm */ + tmp = tmp & ~0x3f; + if (tm.tm_hour >= 12) { + tmp |= 0x20; + tm.tm_hour -= 12; + } + tm.tm_hour = BIN2BCD(tm.tm_hour); + tmp |= tm.tm_hour; + } + xicor_write(X1241REG_HR, tmp); + + xicor_write(X1241REG_SR, 0); + + return 0; +} + +unsigned long xicor_get_time(void) +{ + unsigned int year, mon, day, hour, min, sec, y2k; + + sec = xicor_read(X1241REG_SC); + min = xicor_read(X1241REG_MN); + hour = xicor_read(X1241REG_HR); + + if (hour & X1241REG_HR_MIL) { + hour &= 0x3f; + } else { + if (hour & 0x20) + hour = (hour & 0xf) + 0x12; + } + + day = xicor_read(X1241REG_DT); + mon = xicor_read(X1241REG_MO); + year = xicor_read(X1241REG_YR); + y2k = xicor_read(X1241REG_Y2K); + + sec = BCD2BIN(sec); + min = BCD2BIN(min); + hour = BCD2BIN(hour); + day = BCD2BIN(day); + mon = BCD2BIN(mon); + year = BCD2BIN(year); + y2k = BCD2BIN(y2k); + + year += (y2k * 100); + + return mktime(year, mon, day, hour, min, sec); +} + +int xicor_probe(void) +{ + return (xicor_read(X1241REG_SC) != -1); +} diff -Nru a/arch/mips/sibyte/swarm/setup.c b/arch/mips/sibyte/swarm/setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sibyte/swarm/setup.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2000, 2001 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * Setup code for the SWARM board + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern struct rtc_ops *rtc_ops; +extern struct rtc_ops swarm_rtc_ops; + +#ifdef CONFIG_BLK_DEV_IDE +extern struct ide_ops sibyte_ide_ops; +#endif + +extern void sb1250_setup(void); + +extern int xicor_probe(void); +extern int xicor_set_time(unsigned long); +extern unsigned long xicor_get_time(void); + +extern int m41t81_probe(void); +extern int m41t81_set_time(unsigned long); +extern unsigned long m41t81_get_time(void); + +const char *get_system_type(void) +{ + return "SiByte " SIBYTE_BOARD_NAME; +} + +void __init swarm_timer_setup(struct irqaction *irq) +{ + /* + * we don't set up irqaction, because we will deliver timer + * interrupts through low-level (direct) meachanism. + */ + + /* We only need to setup the generic timer */ + sb1250_time_init(); +} + +int swarm_be_handler(struct pt_regs *regs, int is_fixup) +{ + if (!is_fixup && (regs->cp0_cause & 4)) { + /* Data bus error - print PA */ +#ifdef CONFIG_MIPS64 + printk("DBE physical address: %010lx\n", + __read_64bit_c0_register($26, 1)); +#else + printk("DBE physical address: %010llx\n", + __read_64bit_c0_split($26, 1)); +#endif + } + return (is_fixup ? MIPS_BE_FIXUP : MIPS_BE_FATAL); +} + +void __init swarm_setup(void) +{ + extern int panic_timeout; + + sb1250_setup(); + + panic_timeout = 5; /* For debug. */ + + board_timer_setup = swarm_timer_setup; + board_be_handler = swarm_be_handler; + + if (xicor_probe()) { + printk("swarm setup: Xicor 1241 RTC detected.\n"); + rtc_get_time = xicor_get_time; + rtc_set_time = xicor_set_time; + } + + if (m41t81_probe()) { + printk("swarm setup: M41T81 RTC detected.\n"); + rtc_get_time = m41t81_get_time; + rtc_set_time = m41t81_set_time; + } + + printk("This kernel optimized for " +#ifdef CONFIG_SIMULATION + "simulation" +#else + "board" +#endif + " runs " +#ifdef CONFIG_SIBYTE_CFE + "with" +#else + "without" +#endif + " CFE\n"); + +#ifdef CONFIG_BLK_DEV_IDE + ide_ops = &sibyte_ide_ops; +#endif + +#ifdef CONFIG_VT +#ifdef CONFIG_DUMMY_CONSOLE + conswitchp = &dummy_con; +#endif + screen_info = (struct screen_info) { + 0, 0, /* orig-x, orig-y */ + 0, /* unused */ + 52, /* orig_video_page */ + 3, /* orig_video_mode */ + 80, /* orig_video_cols */ + 4626, 3, 9, /* unused, ega_bx, unused */ + 25, /* orig_video_lines */ + 0x22, /* orig_video_isVGA */ + 16 /* orig_video_points */ + }; + /* XXXKW for CFE, get lines/cols from environment */ +#endif +} + +#ifdef LEDS_PHYS + +#ifdef CONFIG_SIBYTE_CARMEL +/* XXXKW need to detect Monterey/LittleSur/etc */ +#undef LEDS_PHYS +#define LEDS_PHYS MLEDS_PHYS +#endif + +#define setled(index, c) \ + ((unsigned char *)(LEDS_PHYS|IO_SPACE_BASE|0x20))[(3-(index))<<3] = (c) +void setleds(char *str) +{ + int i; + for (i = 0; i < 4; i++) { + if (!str[i]) { + setled(i, ' '); + } else { + setled(i, str[i]); + } + } +} +#endif diff -Nru a/arch/mips/sibyte/swarm/time.c b/arch/mips/sibyte/swarm/time.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/sibyte/swarm/time.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,242 @@ +/* + * Copyright (C) 2000, 2001 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + * Time routines for the swarm board. We pass all the hard stuff + * through to the sb1250 handling code. Only thing we really keep + * track of here is what time of day we think it is. And we don't + * really even do a good job of that... + */ + + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static unsigned long long sec_bias = 0; +static unsigned int usec_bias = 0; + +/* Xicor 1241 definitions */ + +/* + * Register bits + */ + +#define X1241REG_SR_BAT 0x80 /* currently on battery power */ +#define X1241REG_SR_RWEL 0x04 /* r/w latch is enabled, can write RTC */ +#define X1241REG_SR_WEL 0x02 /* r/w latch is unlocked, can enable r/w now */ +#define X1241REG_SR_RTCF 0x01 /* clock failed */ +#define X1241REG_BL_BP2 0x80 /* block protect 2 */ +#define X1241REG_BL_BP1 0x40 /* block protect 1 */ +#define X1241REG_BL_BP0 0x20 /* block protect 0 */ +#define X1241REG_BL_WD1 0x10 +#define X1241REG_BL_WD0 0x08 +#define X1241REG_HR_MIL 0x80 /* military time format */ + +/* + * Register numbers + */ + +#define X1241REG_BL 0x10 /* block protect bits */ +#define X1241REG_INT 0x11 /* */ +#define X1241REG_SC 0x30 /* Seconds */ +#define X1241REG_MN 0x31 /* Minutes */ +#define X1241REG_HR 0x32 /* Hours */ +#define X1241REG_DT 0x33 /* Day of month */ +#define X1241REG_MO 0x34 /* Month */ +#define X1241REG_YR 0x35 /* Year */ +#define X1241REG_DW 0x36 /* Day of Week */ +#define X1241REG_Y2K 0x37 /* Year 2K */ +#define X1241REG_SR 0x3F /* Status register */ + +#define X1241_CCR_ADDRESS 0x6F + +#define SMB_CSR(reg) (KSEG1 | A_SMB_REGISTER(1, reg)) + +static int xicor_read(uint8_t addr) +{ + while (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) + ; + + out64((addr >> 8) & 0x7, SMB_CSR(R_SMB_CMD)); + out64((addr & 0xff), SMB_CSR(R_SMB_DATA)); + out64((V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR2BYTE), SMB_CSR(R_SMB_START)); + + while (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) + ; + + out64((V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_RD1BYTE), SMB_CSR(R_SMB_START)); + + while (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) + ; + + if (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) { + /* Clear error bit by writing a 1 */ + out64(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS)); + return -1; + } + + return (in64(SMB_CSR(R_SMB_DATA)) & 0xff); +} + +static int xicor_write(uint8_t addr, int b) +{ + while (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) + ; + + out64(addr, SMB_CSR(R_SMB_CMD)); + out64((addr & 0xff) | ((b & 0xff) << 8), SMB_CSR(R_SMB_DATA)); + out64(V_SMB_ADDR(X1241_CCR_ADDRESS) | V_SMB_TT_WR3BYTE, + SMB_CSR(R_SMB_START)); + + while (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_BUSY) + ; + + if (in64(SMB_CSR(R_SMB_STATUS)) & M_SMB_ERROR) { + /* Clear error bit by writing a 1 */ + out64(M_SMB_ERROR, SMB_CSR(R_SMB_STATUS)); + return -1; + } else { + return 0; + } +} + +/* + * In order to set the CMOS clock precisely, set_rtc_mmss has to be + * called 500 ms after the second nowtime has started, because when + * nowtime is written into the registers of the CMOS clock, it will + * jump to the next second precisely 500 ms later. Check the Motorola + * MC146818A or Dallas DS12887 data sheet for details. + * + * BUG: This routine does not handle hour overflow properly; it just + * sets the minutes. Usually you'll only notice that after reboot! + */ +int set_rtc_mmss(unsigned long nowtime) +{ + int retval = 0; + int real_seconds, real_minutes, cmos_minutes; + + cmos_minutes = xicor_read(X1241REG_MN); + cmos_minutes = BCD2BIN(cmos_minutes); + + /* + * since we're only adjusting minutes and seconds, + * don't interfere with hour overflow. This avoids + * messing with unknown time zones but requires your + * RTC not to be off by more than 15 minutes + */ + real_seconds = nowtime % 60; + real_minutes = nowtime / 60; + if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) + real_minutes += 30; /* correct for half hour time zone */ + real_minutes %= 60; + + /* unlock writes to the CCR */ + xicor_write(X1241REG_SR, X1241REG_SR_WEL); + xicor_write(X1241REG_SR, X1241REG_SR_WEL | X1241REG_SR_RWEL); + + if (abs(real_minutes - cmos_minutes) < 30) { + real_seconds = BIN2BCD(real_seconds); + real_minutes = BIN2BCD(real_minutes); + xicor_write(X1241REG_SC, real_seconds); + xicor_write(X1241REG_MN, real_minutes); + } else { + printk(KERN_WARNING + "set_rtc_mmss: can't update from %d to %d\n", + cmos_minutes, real_minutes); + retval = -1; + } + + xicor_write(X1241REG_SR, 0); + + printk("set_rtc_mmss: %02d:%02d\n", real_minutes, real_seconds); + + return retval; +} + +static unsigned long __init get_swarm_time(void) +{ + unsigned int year, mon, day, hour, min, sec, y2k; + + sec = xicor_read(X1241REG_SC); + min = xicor_read(X1241REG_MN); + hour = xicor_read(X1241REG_HR); + + if (hour & X1241REG_HR_MIL) { + hour &= 0x3f; + } else { + if (hour & 0x20) + hour = (hour & 0xf) + 0x12; + } + + sec = BCD2BIN(sec); + min = BCD2BIN(min); + hour = BCD2BIN(hour); + + day = xicor_read(X1241REG_DT); + mon = xicor_read(X1241REG_MO); + year = xicor_read(X1241REG_YR); + y2k = xicor_read(X1241REG_Y2K); + + day = BCD2BIN(day); + mon = BCD2BIN(mon); + year = BCD2BIN(year); + y2k = BCD2BIN(y2k); + + year += (y2k * 100); + + return mktime(year, mon, day, hour, min, sec); +} + +/* + * Bring up the timer at 100 Hz. + */ +void __init swarm_time_init(void) +{ + unsigned int flags; + int status; + + /* Set up the scd general purpose timer 0 to cpu 0 */ + sb1250_time_init(); + + /* Establish communication with the Xicor 1241 RTC */ + /* XXXKW how do I share the SMBus with the I2C subsystem? */ + + out64(K_SMB_FREQ_400KHZ, SMB_CSR(R_SMB_FREQ)); + out64(0, SMB_CSR(R_SMB_CONTROL)); + + if ((status = xicor_read(X1241REG_SR_RTCF)) < 0) { + printk("x1241: couldn't detect on SWARM SMBus 1\n"); + } else { + if (status & X1241REG_SR_RTCF) + printk("x1241: battery failed -- time is probably wrong\n"); + write_seqlock_irqsave(&xtime_lock, flags); + xtime.tv_sec = get_swarm_time(); + xtime.tv_nsec = 0; + write_sequnlock_irqrestore(&xtime_lock, flags); + } +} diff -Nru a/arch/mips/tools/Makefile b/arch/mips/tools/Makefile --- a/arch/mips/tools/Makefile Tue Jul 1 18:44:32 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,23 +0,0 @@ -# Makefile for MIPS kernel build tools. -# -# Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) -# Copyright (C) 1997 Ralf Baechle (ralf@gnu.ai.mit.edu) -# -# $Id: Makefile,v 1.2 1997/09/23 06:23:49 ralf Exp $ -# -TARGET := $(TOPDIR)/include/asm-$(ARCH)/offset.h - -$(TARGET): offset.h - cmp -s $^ $@ || (cp $^ $(TARGET).new && mv $(TARGET).new $(TARGET)) - -offset.h: offset.s - sed -n '/^@@@/s///p' $^ >$@ - -offset.s: offset.c $(TOPDIR)/include/linux/autoconf.h - -clean: - rm -f offset.[hs] $(TARGET).new - -mrproper: - rm -f offset.[hs] $(TARGET).new - rm -f $(TARGET) diff -Nru a/arch/mips/tools/offset.c b/arch/mips/tools/offset.c --- a/arch/mips/tools/offset.c Tue Jul 1 18:44:33 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,157 +0,0 @@ -/* - * offset.c: Calculate pt_regs and task_struct offsets. - * - * Copyright (C) 1996 David S. Miller - * Copyright (C) 1997, 1998, 1999 Ralf Baechle - * Copyright (C) 1999 Silicon Graphics, Inc. - * - * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. - */ -#include -#include - -#include -#include - -#define text(t) __asm__("\n@@@" t) -#define _offset(type, member) (&(((type *)NULL)->member)) - -#define offset(string, ptr, member) \ - __asm__("\n@@@" string "%0" : : "i" (_offset(ptr, member))) -#define size(string, size) \ - __asm__("\n@@@" string "%0" : : "i" (sizeof(size))) -#define linefeed text("") - -text("/* DO NOT TOUCH, AUTOGENERATED BY OFFSET.C */"); -linefeed; -text("#ifndef _MIPS_OFFSET_H"); -text("#define _MIPS_OFFSET_H"); -linefeed; - -void output_ptreg_defines(void) -{ - text("/* MIPS pt_regs offsets. */"); - offset("#define PT_R0 ", struct pt_regs, regs[0]); - offset("#define PT_R1 ", struct pt_regs, regs[1]); - offset("#define PT_R2 ", struct pt_regs, regs[2]); - offset("#define PT_R3 ", struct pt_regs, regs[3]); - offset("#define PT_R4 ", struct pt_regs, regs[4]); - offset("#define PT_R5 ", struct pt_regs, regs[5]); - offset("#define PT_R6 ", struct pt_regs, regs[6]); - offset("#define PT_R7 ", struct pt_regs, regs[7]); - offset("#define PT_R8 ", struct pt_regs, regs[8]); - offset("#define PT_R9 ", struct pt_regs, regs[9]); - offset("#define PT_R10 ", struct pt_regs, regs[10]); - offset("#define PT_R11 ", struct pt_regs, regs[11]); - offset("#define PT_R12 ", struct pt_regs, regs[12]); - offset("#define PT_R13 ", struct pt_regs, regs[13]); - offset("#define PT_R14 ", struct pt_regs, regs[14]); - offset("#define PT_R15 ", struct pt_regs, regs[15]); - offset("#define PT_R16 ", struct pt_regs, regs[16]); - offset("#define PT_R17 ", struct pt_regs, regs[17]); - offset("#define PT_R18 ", struct pt_regs, regs[18]); - offset("#define PT_R19 ", struct pt_regs, regs[19]); - offset("#define PT_R20 ", struct pt_regs, regs[20]); - offset("#define PT_R21 ", struct pt_regs, regs[21]); - offset("#define PT_R22 ", struct pt_regs, regs[22]); - offset("#define PT_R23 ", struct pt_regs, regs[23]); - offset("#define PT_R24 ", struct pt_regs, regs[24]); - offset("#define PT_R25 ", struct pt_regs, regs[25]); - offset("#define PT_R26 ", struct pt_regs, regs[26]); - offset("#define PT_R27 ", struct pt_regs, regs[27]); - offset("#define PT_R28 ", struct pt_regs, regs[28]); - offset("#define PT_R29 ", struct pt_regs, regs[29]); - offset("#define PT_R30 ", struct pt_regs, regs[30]); - offset("#define PT_R31 ", struct pt_regs, regs[31]); - offset("#define PT_LO ", struct pt_regs, lo); - offset("#define PT_HI ", struct pt_regs, hi); - offset("#define PT_EPC ", struct pt_regs, cp0_epc); - offset("#define PT_BVADDR ", struct pt_regs, cp0_badvaddr); - offset("#define PT_STATUS ", struct pt_regs, cp0_status); - offset("#define PT_CAUSE ", struct pt_regs, cp0_cause); - size("#define PT_SIZE ", struct pt_regs); - linefeed; -} - -void output_task_defines(void) -{ - text("/* MIPS task_struct offsets. */"); - offset("#define TASK_STATE ", struct task_struct, state); - offset("#define TASK_FLAGS ", struct task_struct, flags); -#error offset("#define TASK_SIGPENDING ", struct task_struct, work.sigpending); -#error offset("#define TASK_NEED_RESCHED ", struct task_struct, work.need_resched); -#error offset("#define TASK_PTRACE ", struct task_struct, ptrace); - offset("#define TASK_COUNTER ", struct task_struct, counter); - offset("#define TASK_NICE ", struct task_struct, nice); - offset("#define TASK_MM ", struct task_struct, mm); - offset("#define TASK_PID ", struct task_struct, pid); - size("#define TASK_STRUCT_SIZE ", struct task_struct); - linefeed; -} - -void output_thread_defines(void) -{ - text("/* MIPS specific thread_struct offsets. */"); - offset("#define THREAD_REG16 ", struct task_struct, thread.reg16); - offset("#define THREAD_REG17 ", struct task_struct, thread.reg17); - offset("#define THREAD_REG18 ", struct task_struct, thread.reg18); - offset("#define THREAD_REG19 ", struct task_struct, thread.reg19); - offset("#define THREAD_REG20 ", struct task_struct, thread.reg20); - offset("#define THREAD_REG21 ", struct task_struct, thread.reg21); - offset("#define THREAD_REG22 ", struct task_struct, thread.reg22); - offset("#define THREAD_REG23 ", struct task_struct, thread.reg23); - offset("#define THREAD_REG29 ", struct task_struct, thread.reg29); - offset("#define THREAD_REG30 ", struct task_struct, thread.reg30); - offset("#define THREAD_REG31 ", struct task_struct, thread.reg31); - offset("#define THREAD_STATUS ", struct task_struct, \ - thread.cp0_status); - offset("#define THREAD_FPU ", struct task_struct, thread.fpu); - offset("#define THREAD_BVADDR ", struct task_struct, \ - thread.cp0_badvaddr); - offset("#define THREAD_BUADDR ", struct task_struct, \ - thread.cp0_baduaddr); - offset("#define THREAD_ECODE ", struct task_struct, \ - thread.error_code); - offset("#define THREAD_TRAPNO ", struct task_struct, thread.trap_no); - offset("#define THREAD_MFLAGS ", struct task_struct, thread.mflags); - offset("#define THREAD_CURDS ", struct task_struct, \ - thread.current_ds); - offset("#define THREAD_TRAMP ", struct task_struct, \ - thread.irix_trampoline); - offset("#define THREAD_OLDCTX ", struct task_struct, \ - thread.irix_oldctx); - offset("#define THREAD_DSEEPC ", struct task_struct, \ - thread.dsemul_epc); - offset("#define THREAD_DSEAERPC ", struct task_struct, \ - thread.dsemul_aerpc); - linefeed; -} - -void output_mm_defines(void) -{ - text("/* Linux mm_struct offsets. */"); - offset("#define MM_USERS ", struct mm_struct, mm_users); - offset("#define MM_PGD ", struct mm_struct, pgd); - offset("#define MM_CONTEXT ", struct mm_struct, context); - linefeed; -} - -void output_sc_defines(void) -{ - text("/* Linux sigcontext offsets. */"); - offset("#define SC_REGS ", struct sigcontext, sc_regs); - offset("#define SC_FPREGS ", struct sigcontext, sc_fpregs); - offset("#define SC_MDHI ", struct sigcontext, sc_mdhi); - offset("#define SC_MDLO ", struct sigcontext, sc_mdlo); - offset("#define SC_PC ", struct sigcontext, sc_pc); - offset("#define SC_STATUS ", struct sigcontext, sc_status); - offset("#define SC_OWNEDFP ", struct sigcontext, sc_ownedfp); - offset("#define SC_FPC_CSR ", struct sigcontext, sc_fpc_csr); - offset("#define SC_FPC_EIR ", struct sigcontext, sc_fpc_eir); - offset("#define SC_CAUSE ", struct sigcontext, sc_cause); - offset("#define SC_BADVADDR ", struct sigcontext, sc_badvaddr); - linefeed; -} - -text("#endif /* !(_MIPS_OFFSET_H) */"); diff -Nru a/arch/mips/tx4927/common/Makefile b/arch/mips/tx4927/common/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/tx4927/common/Makefile Tue Jul 1 18:44:40 2003 @@ -0,0 +1,14 @@ +# +# Makefile for common code for Toshiba TX4927 based systems +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# + +obj-y := tx4927_prom.o +obj-y += tx4927_setup.o +obj-y += tx4927_irq.o +obj-y += tx4927_irq_handler.o + +obj-$(CONFIG_KGDB) += tx4927_dbgio.o diff -Nru a/arch/mips/tx4927/common/tx4927_dbgio.c b/arch/mips/tx4927/common/tx4927_dbgio.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/tx4927/common/tx4927_dbgio.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,47 @@ +/* + * linux/arch/mips/tx4927/common/tx4927_dbgio.c + * + * kgdb interface for gdb + * + * Author: MontaVista Software, Inc. + * source@mvista.com + * + * Copyright 2001-2002 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include + +u8 getDebugChar(void) +{ + extern u8 txx9_sio_kdbg_rd(void); + return (txx9_sio_kdbg_rd()); +} + + +int putDebugChar(u8 byte) +{ + extern int txx9_sio_kdbg_wr( u8 ch ); + return (txx9_sio_kdbg_wr(byte)); +} diff -Nru a/arch/mips/tx4927/common/tx4927_irq.c b/arch/mips/tx4927/common/tx4927_irq.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/tx4927/common/tx4927_irq.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,705 @@ +/* + * Common tx4927 irq handler + * + * Author: MontaVista Software, Inc. + * source@mvista.com + * + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * DEBUG + */ +#define TX4927_IRQ_CHECK_CP0 +#define TX4927_IRQ_CHECK_PIC + +#undef TX4927_IRQ_DEBUG + +#ifdef TX4927_IRQ_DEBUG +#define TX4927_IRQ_NONE 0x00000000 + +#define TX4927_IRQ_INFO ( 1 << 0 ) +#define TX4927_IRQ_WARN ( 1 << 1 ) +#define TX4927_IRQ_EROR ( 1 << 2 ) + +#define TX4927_IRQ_INIT ( 1 << 5 ) +#define TX4927_IRQ_NEST1 ( 1 << 6 ) +#define TX4927_IRQ_NEST2 ( 1 << 7 ) +#define TX4927_IRQ_NEST3 ( 1 << 8 ) +#define TX4927_IRQ_NEST4 ( 1 << 9 ) + +#define TX4927_IRQ_CP0_INIT ( 1 << 10 ) +#define TX4927_IRQ_CP0_STARTUP ( 1 << 11 ) +#define TX4927_IRQ_CP0_SHUTDOWN ( 1 << 12 ) +#define TX4927_IRQ_CP0_ENABLE ( 1 << 13 ) +#define TX4927_IRQ_CP0_DISABLE ( 1 << 14 ) +#define TX4927_IRQ_CP0_MASK ( 1 << 15 ) +#define TX4927_IRQ_CP0_ENDIRQ ( 1 << 16 ) + +#define TX4927_IRQ_PIC_INIT ( 1 << 20 ) +#define TX4927_IRQ_PIC_STARTUP ( 1 << 21 ) +#define TX4927_IRQ_PIC_SHUTDOWN ( 1 << 22 ) +#define TX4927_IRQ_PIC_ENABLE ( 1 << 23 ) +#define TX4927_IRQ_PIC_DISABLE ( 1 << 24 ) +#define TX4927_IRQ_PIC_MASK ( 1 << 25 ) +#define TX4927_IRQ_PIC_ENDIRQ ( 1 << 26 ) + +#define TX4927_IRQ_ALL 0xffffffff +#endif + +#ifdef TX4927_IRQ_DEBUG +static const u32 tx4927_irq_debug_flag = (TX4927_IRQ_NONE + | TX4927_IRQ_INFO + | TX4927_IRQ_WARN | TX4927_IRQ_EROR +// | TX4927_IRQ_CP0_INIT +// | TX4927_IRQ_CP0_STARTUP +// | TX4927_IRQ_CP0_SHUTDOWN +// | TX4927_IRQ_CP0_ENABLE +// | TX4927_IRQ_CP0_DISABLE +// | TX4927_IRQ_CP0_MASK +// | TX4927_IRQ_CP0_ENDIRQ +// | TX4927_IRQ_PIC_INIT +// | TX4927_IRQ_PIC_STARTUP +// | TX4927_IRQ_PIC_SHUTDOWN +// | TX4927_IRQ_PIC_ENABLE +// | TX4927_IRQ_PIC_DISABLE +// | TX4927_IRQ_PIC_MASK +// | TX4927_IRQ_PIC_ENDIRQ +// | TX4927_IRQ_INIT +// | TX4927_IRQ_NEST1 +// | TX4927_IRQ_NEST2 +// | TX4927_IRQ_NEST3 +// | TX4927_IRQ_NEST4 + ); +#endif + +#ifdef TX4927_IRQ_DEBUG +#define TX4927_IRQ_DPRINTK(flag,str...) \ + if ( (tx4927_irq_debug_flag) & (flag) ) \ + { \ + char tmp[100]; \ + sprintf( tmp, str ); \ + printk( "%s(%s:%u)::%s", __FUNCTION__, __FILE__, __LINE__, tmp ); \ + } +#else +#define TX4927_IRQ_DPRINTK(flag,str...) +#endif + +/* + * Forwad definitions for all pic's + */ + +static unsigned int tx4927_irq_cp0_startup(unsigned int irq); +static void tx4927_irq_cp0_shutdown(unsigned int irq); +static void tx4927_irq_cp0_enable(unsigned int irq); +static void tx4927_irq_cp0_disable(unsigned int irq); +static void tx4927_irq_cp0_mask_and_ack(unsigned int irq); +static void tx4927_irq_cp0_end(unsigned int irq); + +static unsigned int tx4927_irq_pic_startup(unsigned int irq); +static void tx4927_irq_pic_shutdown(unsigned int irq); +static void tx4927_irq_pic_enable(unsigned int irq); +static void tx4927_irq_pic_disable(unsigned int irq); +static void tx4927_irq_pic_mask_and_ack(unsigned int irq); +static void tx4927_irq_pic_end(unsigned int irq); + +/* + * Kernel structs for all pic's + */ + +static spinlock_t tx4927_cp0_lock = SPIN_LOCK_UNLOCKED; +static spinlock_t tx4927_pic_lock = SPIN_LOCK_UNLOCKED; + +#define TX4927_CP0_NAME "TX4927-CP0" +static struct hw_interrupt_type tx4927_irq_cp0_type = { + typename: TX4927_CP0_NAME, + startup: tx4927_irq_cp0_startup, + shutdown: tx4927_irq_cp0_shutdown, + enable: tx4927_irq_cp0_enable, + disable: tx4927_irq_cp0_disable, + ack: tx4927_irq_cp0_mask_and_ack, + end: tx4927_irq_cp0_end, + set_affinity: NULL +}; + +#define TX4927_PIC_NAME "TX4927-PIC" +static struct hw_interrupt_type tx4927_irq_pic_type = { + typename: TX4927_PIC_NAME, + startup: tx4927_irq_pic_startup, + shutdown: tx4927_irq_pic_shutdown, + enable: tx4927_irq_pic_enable, + disable: tx4927_irq_pic_disable, + ack: tx4927_irq_pic_mask_and_ack, + end: tx4927_irq_pic_end, + set_affinity: NULL +}; + +#define TX4927_PIC_ACTION(s) { no_action, 0, 0, s, NULL, NULL } +static struct irqaction tx4927_irq_pic_action = +TX4927_PIC_ACTION(TX4927_PIC_NAME); + +#define CCP0_STATUS 12 +#define CCP0_CAUSE 13 + +/* + * Functions for cp0 + */ + +#define tx4927_irq_cp0_mask(irq) ( 1 << ( irq-TX4927_IRQ_CP0_BEG+8 ) ) + +static void +tx4927_irq_cp0_modify(unsigned cp0_reg, unsigned clr_bits, unsigned set_bits) +{ + unsigned long val = 0; + + switch (cp0_reg) { + case CCP0_STATUS: + val = read_c0_status(); + break; + + case CCP0_CAUSE: + val = read_c0_cause(); + break; + + } + + val &= (~clr_bits); + val |= (set_bits); + + switch (cp0_reg) { + case CCP0_STATUS:{ + write_c0_status(val); + break; + } + case CCP0_CAUSE:{ + write_c0_cause(val); + break; + } + } + + return; +} + +static void __init tx4927_irq_cp0_init(void) +{ + int i; + + TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_INIT, "beg=%d end=%d\n", + TX4927_IRQ_CP0_BEG, TX4927_IRQ_CP0_END); + + for (i = TX4927_IRQ_CP0_BEG; i <= TX4927_IRQ_CP0_END; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = 1; + irq_desc[i].handler = &tx4927_irq_cp0_type; + } + + return; +} + +static unsigned int tx4927_irq_cp0_startup(unsigned int irq) +{ + TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_STARTUP, "irq=%d \n", irq); + +#ifdef TX4927_IRQ_CHECK_CP0 + { + if (irq < TX4927_IRQ_CP0_BEG || irq > TX4927_IRQ_CP0_END) { + TX4927_IRQ_DPRINTK(TX4927_IRQ_EROR, + "bad irq=%d \n", irq); + panic("\n"); + } + } +#endif + + tx4927_irq_cp0_enable(irq); + + return (0); +} + +static void tx4927_irq_cp0_shutdown(unsigned int irq) +{ + TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_SHUTDOWN, "irq=%d \n", irq); + +#ifdef TX4927_IRQ_CHECK_CP0 + { + if (irq < TX4927_IRQ_CP0_BEG || irq > TX4927_IRQ_CP0_END) { + TX4927_IRQ_DPRINTK(TX4927_IRQ_EROR, + "bad irq=%d \n", irq); + panic("\n"); + } + } +#endif + + tx4927_irq_cp0_disable(irq); + + return; +} + +static void tx4927_irq_cp0_enable(unsigned int irq) +{ + unsigned long flags; + + TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_ENABLE, "irq=%d \n", irq); + +#ifdef TX4927_IRQ_CHECK_CP0 + { + if (irq < TX4927_IRQ_CP0_BEG || irq > TX4927_IRQ_CP0_END) { + TX4927_IRQ_DPRINTK(TX4927_IRQ_EROR, + "bad irq=%d \n", irq); + panic("\n"); + } + } +#endif + + spin_lock_irqsave(&tx4927_cp0_lock, flags); + + tx4927_irq_cp0_modify(CCP0_STATUS, 0, tx4927_irq_cp0_mask(irq)); + + spin_unlock_irqrestore(&tx4927_cp0_lock, flags); + + return; +} + +static void tx4927_irq_cp0_disable(unsigned int irq) +{ + unsigned long flags; + + TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_DISABLE, "irq=%d \n", irq); + +#ifdef TX4927_IRQ_CHECK_CP0 + { + if (irq < TX4927_IRQ_CP0_BEG || irq > TX4927_IRQ_CP0_END) { + TX4927_IRQ_DPRINTK(TX4927_IRQ_EROR, + "bad irq=%d \n", irq); + panic("\n"); + } + } +#endif + + spin_lock_irqsave(&tx4927_cp0_lock, flags); + + tx4927_irq_cp0_modify(CCP0_STATUS, tx4927_irq_cp0_mask(irq), 0); + + spin_unlock_irqrestore(&tx4927_cp0_lock, flags); + + return; +} + +static void tx4927_irq_cp0_mask_and_ack(unsigned int irq) +{ + TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_MASK, "irq=%d \n", irq); + +#ifdef TX4927_IRQ_CHECK_CP0 + { + if (irq < TX4927_IRQ_CP0_BEG || irq > TX4927_IRQ_CP0_END) { + TX4927_IRQ_DPRINTK(TX4927_IRQ_EROR, + "bad irq=%d \n", irq); + panic("\n"); + } + } +#endif + + tx4927_irq_cp0_disable(irq); + + return; +} + +static void tx4927_irq_cp0_end(unsigned int irq) +{ + TX4927_IRQ_DPRINTK(TX4927_IRQ_CP0_ENDIRQ, "irq=%d \n", irq); + +#ifdef TX4927_IRQ_CHECK_CP0 + { + if (irq < TX4927_IRQ_CP0_BEG || irq > TX4927_IRQ_CP0_END) { + TX4927_IRQ_DPRINTK(TX4927_IRQ_EROR, + "bad irq=%d \n", irq); + panic("\n"); + } + } +#endif + + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { + tx4927_irq_cp0_enable(irq); + } + + return; +} + +/* + * Functions for pic + */ +u32 tx4927_irq_pic_addr(int irq) +{ + /* MVMCP -- need to formulize this */ + irq -= TX4927_IRQ_PIC_BEG; + switch (irq) { + case 17: + case 16: + case 1: + case 0: + return (0xff1ff610); + + case 19: + case 18: + case 3: + case 2: + return (0xff1ff614); + + case 21: + case 20: + case 5: + case 4: + return (0xff1ff618); + + case 23: + case 22: + case 7: + case 6: + return (0xff1ff61c); + + case 25: + case 24: + case 9: + case 8: + return (0xff1ff620); + + case 27: + case 26: + case 11: + case 10: + return (0xff1ff624); + + case 29: + case 28: + case 13: + case 12: + return (0xff1ff628); + + case 31: + case 30: + case 15: + case 14: + return (0xff1ff62c); + + } + return (0); +} + +u32 tx4927_irq_pic_mask(int irq) +{ + /* MVMCP -- need to formulize this */ + irq -= TX4927_IRQ_PIC_BEG; + switch (irq) { + case 31: + case 29: + case 27: + case 25: + case 23: + case 21: + case 19: + case 17:{ + return (0x07000000); + } + case 30: + case 28: + case 26: + case 24: + case 22: + case 20: + case 18: + case 16:{ + return (0x00070000); + } + case 15: + case 13: + case 11: + case 9: + case 7: + case 5: + case 3: + case 1:{ + return (0x00000700); + } + case 14: + case 12: + case 10: + case 8: + case 6: + case 4: + case 2: + case 0:{ + return (0x00000007); + } + } + return (0x00000000); +} + +static void tx4927_irq_pic_modify(unsigned pic_reg, unsigned clr_bits, + unsigned set_bits) +{ + unsigned long val = 0; + + val = TX4927_RD(pic_reg); + val &= (~clr_bits); + val |= (set_bits); + TX4927_WR(pic_reg, val); + + return; +} + +static void __init tx4927_irq_pic_init(void) +{ + unsigned long flags; + int i; + + TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_INIT, "beg=%d end=%d\n", + TX4927_IRQ_PIC_BEG, TX4927_IRQ_PIC_END); + + for (i = TX4927_IRQ_PIC_BEG; i <= TX4927_IRQ_PIC_END; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = 2; + irq_desc[i].handler = &tx4927_irq_pic_type; + } + + setup_irq(TX4927_IRQ_NEST_PIC_ON_CP0, &tx4927_irq_pic_action); + + spin_lock_irqsave(&tx4927_pic_lock, flags); + + TX4927_WR(0xff1ff640, 0x6); /* irq level mask -- only accept hightest */ + TX4927_WR(0xff1ff600, TX4927_RD(0xff1ff600) | 0x1); /* irq enable */ + + spin_unlock_irqrestore(&tx4927_pic_lock, flags); + + return; +} + +static unsigned int tx4927_irq_pic_startup(unsigned int irq) +{ + TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_STARTUP, "irq=%d\n", irq); + +#ifdef TX4927_IRQ_CHECK_PIC + { + if (irq < TX4927_IRQ_PIC_BEG || irq > TX4927_IRQ_PIC_END) { + TX4927_IRQ_DPRINTK(TX4927_IRQ_EROR, + "bad irq=%d \n", irq); + panic("\n"); + } + } +#endif + + tx4927_irq_pic_enable(irq); + + return (0); +} + +static void tx4927_irq_pic_shutdown(unsigned int irq) +{ + TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_SHUTDOWN, "irq=%d\n", irq); + +#ifdef TX4927_IRQ_CHECK_PIC + { + if (irq < TX4927_IRQ_PIC_BEG || irq > TX4927_IRQ_PIC_END) { + TX4927_IRQ_DPRINTK(TX4927_IRQ_EROR, + "bad irq=%d \n", irq); + panic("\n"); + } + } +#endif + + tx4927_irq_pic_disable(irq); + + return; +} + +static void tx4927_irq_pic_enable(unsigned int irq) +{ + unsigned long flags; + + TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_ENABLE, "irq=%d\n", irq); + +#ifdef TX4927_IRQ_CHECK_PIC + { + if (irq < TX4927_IRQ_PIC_BEG || irq > TX4927_IRQ_PIC_END) { + TX4927_IRQ_DPRINTK(TX4927_IRQ_EROR, + "bad irq=%d \n", irq); + panic("\n"); + } + } +#endif + + spin_lock_irqsave(&tx4927_pic_lock, flags); + + tx4927_irq_pic_modify(tx4927_irq_pic_addr(irq), 0, + tx4927_irq_pic_mask(irq)); + + spin_unlock_irqrestore(&tx4927_pic_lock, flags); + + return; +} + +static void tx4927_irq_pic_disable(unsigned int irq) +{ + unsigned long flags; + + TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_DISABLE, "irq=%d\n", irq); + +#ifdef TX4927_IRQ_CHECK_PIC + { + if (irq < TX4927_IRQ_PIC_BEG || irq > TX4927_IRQ_PIC_END) { + TX4927_IRQ_DPRINTK(TX4927_IRQ_EROR, + "bad irq=%d \n", irq); + panic("\n"); + } + } +#endif + + spin_lock_irqsave(&tx4927_pic_lock, flags); + + tx4927_irq_pic_modify(tx4927_irq_pic_addr(irq), + tx4927_irq_pic_mask(irq), 0); + + spin_unlock_irqrestore(&tx4927_pic_lock, flags); + + return; +} + +static void tx4927_irq_pic_mask_and_ack(unsigned int irq) +{ + TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_MASK, "irq=%d\n", irq); + +#ifdef TX4927_IRQ_CHECK_PIC + { + if (irq < TX4927_IRQ_PIC_BEG || irq > TX4927_IRQ_PIC_END) { + TX4927_IRQ_DPRINTK(TX4927_IRQ_EROR, + "bad irq=%d \n", irq); + panic("\n"); + } + } +#endif + + tx4927_irq_pic_disable(irq); + + return; +} + +static void tx4927_irq_pic_end(unsigned int irq) +{ + TX4927_IRQ_DPRINTK(TX4927_IRQ_PIC_ENDIRQ, "irq=%d\n", irq); + +#ifdef TX4927_IRQ_CHECK_PIC + { + if (irq < TX4927_IRQ_PIC_BEG || irq > TX4927_IRQ_PIC_END) { + TX4927_IRQ_DPRINTK(TX4927_IRQ_EROR, + "bad irq=%d \n", irq); + panic("\n"); + } + } +#endif + + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { + tx4927_irq_pic_enable(irq); + } + + return; +} + +/* + * Main init functions + */ +void __init tx4927_irq_init(void) +{ + extern asmlinkage void tx4927_irq_handler(void); + + TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "-\n"); + + TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "=Calling tx4927_irq_cp0_init()\n"); + tx4927_irq_cp0_init(); + + TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "=Calling tx4927_irq_pic_init()\n"); + tx4927_irq_pic_init(); + + TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, + "=Calling set_except_vector(tx4927_irq_handler)\n"); + set_except_vector(0, tx4927_irq_handler); + + TX4927_IRQ_DPRINTK(TX4927_IRQ_INIT, "+\n"); + + return; +} + +int tx4927_irq_nested(void) +{ + int sw_irq = 0; + u32 level2; + + TX4927_IRQ_DPRINTK(TX4927_IRQ_NEST1, "-\n"); + + level2 = TX4927_RD(0xff1ff6a0); + TX4927_IRQ_DPRINTK(TX4927_IRQ_NEST2, "=level2a=0x%x\n", level2); + + if ((level2 & 0x10000) == 0) { + level2 &= 0x1f; + TX4927_IRQ_DPRINTK(TX4927_IRQ_NEST3, "=level2b=0x%x\n", level2); + + sw_irq = TX4927_IRQ_PIC_BEG + level2; + TX4927_IRQ_DPRINTK(TX4927_IRQ_NEST3, "=sw_irq=%d\n", sw_irq); + + if (sw_irq == 27) { + TX4927_IRQ_DPRINTK(TX4927_IRQ_NEST4, "=irq-%d\n", + sw_irq); + +#ifdef CONFIG_TOSHIBA_RBTX4927 + { + sw_irq = toshiba_rbtx4927_irq_nested(sw_irq); + } +#endif + + TX4927_IRQ_DPRINTK(TX4927_IRQ_NEST4, "=irq+%d\n", + sw_irq); + } + } + + TX4927_IRQ_DPRINTK(TX4927_IRQ_NEST2, "=sw_irq=%d\n", sw_irq); + + TX4927_IRQ_DPRINTK(TX4927_IRQ_NEST1, "+\n"); + + return (sw_irq); +} diff -Nru a/arch/mips/tx4927/common/tx4927_irq_handler.S b/arch/mips/tx4927/common/tx4927_irq_handler.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/tx4927/common/tx4927_irq_handler.S Tue Jul 1 18:44:40 2003 @@ -0,0 +1,104 @@ +/* + * linux/arch/mips/tx4927/common/tx4927_irq_handler.S + * + * Primary interrupt handler for tx4927 based systems + * + * Author: MontaVista Software, Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * source@mvista.com + * + * Copyright 2001-2002 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include + + .align 5 + NESTED(tx4927_irq_handler, PT_SIZE, sp) + SAVE_ALL + CLI + .set at + + mfc0 t0, CP0_CAUSE + mfc0 t1, CP0_STATUS + and t0, t1 + + andi t1, t0, STATUSF_IP7 /* cpu timer */ + bnez t1, ll_ip7 + + /* IP6..IP3 multiplexed -- do not use */ + + andi t1, t0, STATUSF_IP2 /* tx4927 pic */ + bnez t1, ll_ip2 + + andi t1, t0, STATUSF_IP0 /* user line 0 */ + bnez t1, ll_ip0 + + andi t1, t0, STATUSF_IP1 /* user line 1 */ + bnez t1, ll_ip1 + + .set reorder + + /* wrong alarm or masked ... */ + j spurious_interrupt + nop + END(tx4927_irq_handler) + + .align 5 + + +ll_ip7: + li a0, TX4927_IRQ_CPU_TIMER + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_ip2: + jal tx4927_irq_nested + nop + beqz v0, goto_spurious_interrupt + nop + move a0, v0 + move a1, sp + jal do_IRQ + j ret_from_irq + +goto_spurious_interrupt: + j spurious_interrupt + nop + +ll_ip1: + li a0, TX4927_IRQ_USER1 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_ip0: + li a0, TX4927_IRQ_USER0 + move a1, sp + jal do_IRQ + j ret_from_irq diff -Nru a/arch/mips/tx4927/common/tx4927_prom.c b/arch/mips/tx4927/common/tx4927_prom.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/tx4927/common/tx4927_prom.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,146 @@ +/* + * linux/arch/mips/tx4927/common/tx4927_prom.c + * + * common tx4927 memory interface + * + * Author: MontaVista Software, Inc. + * source@mvista.com + * + * Copyright 2001-2002 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include + +#include +#include +#include + +static unsigned int __init tx4927_process_sdccr(u64 * addr) +{ + u64 val; + unsigned int sdccr_ce; + unsigned int sdccr_bs; + unsigned int sdccr_rs; + unsigned int sdccr_cs; + unsigned int sdccr_mw; + unsigned int bs = 0; + unsigned int rs = 0; + unsigned int cs = 0; + unsigned int mw = 0; + unsigned int msize = 0; + + val = (*((vu64 *) (addr))); + + /* MVMCP -- need #defs for these bits masks */ + sdccr_ce = ((val & (1 << 10)) >> 10); + sdccr_bs = ((val & (1 << 8)) >> 8); + sdccr_rs = ((val & (3 << 5)) >> 5); + sdccr_cs = ((val & (3 << 2)) >> 2); + sdccr_mw = ((val & (1 << 0)) >> 0); + + if (sdccr_ce) { + switch (sdccr_bs) { + case 0:{ + bs = 2; + break; + } + case 1:{ + bs = 4; + break; + } + } + switch (sdccr_rs) { + case 0:{ + rs = 2048; + break; + } + case 1:{ + rs = 4096; + break; + } + case 2:{ + rs = 8192; + break; + } + case 3:{ + rs = 0; + break; + } + } + switch (sdccr_cs) { + case 0:{ + cs = 256; + break; + } + case 1:{ + cs = 512; + break; + } + case 2:{ + cs = 1024; + break; + } + case 3:{ + cs = 2048; + break; + } + } + switch (sdccr_mw) { + case 0:{ + mw = 8; + break; + } /* 8 bytes = 64 bits */ + case 1:{ + mw = 4; + break; + } /* 4 bytes = 32 bits */ + } + } + + /* bytes per chip MB per chip num chips */ + msize = (((rs * cs * mw) / (1024 * 1024)) * bs); + + return (msize); +} + + +unsigned int __init tx4927_get_mem_size(void) +{ + unsigned int c0; + unsigned int c1; + unsigned int c2; + unsigned int c3; + unsigned int total; + + /* MVMCP -- need #defs for these registers */ + c0 = tx4927_process_sdccr((u64 *) 0xff1f8000); + c1 = tx4927_process_sdccr((u64 *) 0xff1f8008); + c2 = tx4927_process_sdccr((u64 *) 0xff1f8010); + c3 = tx4927_process_sdccr((u64 *) 0xff1f8018); + total = c0 + c1 + c2 + c3; + + return (total); +} diff -Nru a/arch/mips/tx4927/common/tx4927_setup.c b/arch/mips/tx4927/common/tx4927_setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/tx4927/common/tx4927_setup.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,251 @@ +/* + * linux/arch/mips/tx4927/common/tx4927_setup.c + * + * common tx4927 setup stuff + * + * Author: MontaVista Software, Inc. + * source@mvista.com + * + * Copyright 2001-2002 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#undef DEBUG + +void __init tx4927_setup(void); +void __init tx4927_time_init(void); +void __init tx4927_timer_setup(struct irqaction *irq); +void dump_cp0(char *key); + + +void (*__wbflush) (void); + +static void tx4927_write_buffer_flush(void) +{ + __asm__ __volatile__ + ("sync\n\t" "nop\n\t" "loop: bc0f loop\n\t" "nop\n\t"); +} + + +void __init tx4927_setup(void) +{ + board_time_init = tx4927_time_init; + board_timer_setup = tx4927_timer_setup; + __wbflush = tx4927_write_buffer_flush; + +#ifdef CONFIG_TOSHIBA_RBTX4927 + { + extern void toshiba_rbtx4927_setup(void); + toshiba_rbtx4927_setup(); + } +#endif + + return; +} + + +void __init tx4927_time_init(void) +{ + +#ifdef CONFIG_TOSHIBA_RBTX4927 + { + extern void toshiba_rbtx4927_time_init(void); + toshiba_rbtx4927_time_init(); + } +#endif + +#ifdef CONFIG_KGDB + { + printk("Calling breakpoint() -- start remote kgdb\n"); + set_debug_traps(); + breakpoint(); + printk("Calling breakpoint() -- done\n"); + } +#endif + + return; +} + + +void __init tx4927_timer_setup(struct irqaction *irq) +{ + u32 count; + u32 c1; + u32 c2; + + setup_irq(TX4927_IRQ_CPU_TIMER, irq); + + /* to generate the first timer interrupt */ + c1 = read_c0_count(); + count = c1 + (mips_counter_frequency / HZ); + write_c0_compare(count); + c2 = read_c0_count(); + +#ifdef CONFIG_TOSHIBA_RBTX4927 + { + extern void toshiba_rbtx4927_timer_setup(struct irqaction + *irq); + toshiba_rbtx4927_timer_setup(irq); + } +#endif + + return; +} + + +#ifdef DEBUG +void print_cp0(char *key, int num, char *name, u32 val) +{ + printk("%s cp0:%02d:%s=0x%08x\n", key, num, name, val); + return; +} + +indent: Standard input:25: Error:Unexpected end of file + +void +dump_cp0(char *key) +{ + if (key == NULL) + key = ""; + + print_cp0(key, 0, "INDEX ", read_c0_index()); + print_cp0(key, 2, "ENTRYLO1", read_c0_entrylo0()); + print_cp0(key, 3, "ENTRYLO2", read_c0_entrylo1()); + print_cp0(key, 4, "CONTEXT ", read_c0_context()); + print_cp0(key, 5, "PAGEMASK", read_c0_pagemask()); + print_cp0(key, 6, "WIRED ", read_c0_wired()); + //print_cp0(key, 8, "BADVADDR", read_c0_badvaddr()); + print_cp0(key, 9, "COUNT ", read_c0_count()); + print_cp0(key, 10, "ENTRYHI ", read_c0_entryhi()); + print_cp0(key, 11, "COMPARE ", read_c0_compare()); + print_cp0(key, 12, "STATUS ", read_c0_status()); + print_cp0(key, 13, "CAUSE ", read_c0_cause() & 0xffff87ff); + print_cp0(key, 16, "CONFIG ", read_c0_config()); + return; +} + +void print_pic(char *key, u32 reg, char *name) +{ + printk("%s pic:0x%08x:%s=0x%08x\n", key, reg, name, + TX4927_RD(reg)); + return; +} + + +void dump_pic(char *key) +{ + if (key == NULL) + key = ""; + + print_pic(key, 0xff1ff600, "IRDEN "); + print_pic(key, 0xff1ff604, "IRDM0 "); + print_pic(key, 0xff1ff608, "IRDM1 "); + + print_pic(key, 0xff1ff610, "IRLVL0 "); + print_pic(key, 0xff1ff614, "IRLVL1 "); + print_pic(key, 0xff1ff618, "IRLVL2 "); + print_pic(key, 0xff1ff61c, "IRLVL3 "); + print_pic(key, 0xff1ff620, "IRLVL4 "); + print_pic(key, 0xff1ff624, "IRLVL5 "); + print_pic(key, 0xff1ff628, "IRLVL6 "); + print_pic(key, 0xff1ff62c, "IRLVL7 "); + + print_pic(key, 0xff1ff640, "IRMSK "); + print_pic(key, 0xff1ff660, "IREDC "); + print_pic(key, 0xff1ff680, "IRPND "); + print_pic(key, 0xff1ff6a0, "IRCS "); + + print_pic(key, 0xff1ff514, "IRFLAG1 "); /* don't read IRLAG0 -- it hangs system */ + + print_pic(key, 0xff1ff518, "IRPOL "); + print_pic(key, 0xff1ff51c, "IRRCNT "); + print_pic(key, 0xff1ff520, "IRMASKINT"); + print_pic(key, 0xff1ff524, "IRMASKEXT"); + + return; +} + + +void print_addr(char *hdr, char *key, u32 addr) +{ + printk("%s %s:0x%08x=0x%08x\n", hdr, key, addr, TX4927_RD(addr)); + return; +} + + +void dump_180(char *key) +{ + u32 i; + + for (i = 0x80000180; i < 0x80000180 + 0x80; i += 4) { + print_addr("180", key, i); + } + return; +} + + +void dump_eh0(char *key) +{ + int i; + extern unsigned long exception_handlers[]; + + for (i = (int) exception_handlers; + i < (int) (exception_handlers + 20); i += 4) { + print_addr("eh0", key, i); + } + + return; +} + +void pk0(void) +{ + volatile u32 val; + + __asm__ __volatile__("ori %0, $26, 0":"=r"(val) + ); + printk("k0=[0x%08x]\n", val); +} +#endif diff -Nru a/arch/mips/tx4927/toshiba_rbtx4927/Makefile b/arch/mips/tx4927/toshiba_rbtx4927/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/tx4927/toshiba_rbtx4927/Makefile Tue Jul 1 18:44:40 2003 @@ -0,0 +1,8 @@ +obj-y += toshiba_rbtx4927_prom.o +obj-y += toshiba_rbtx4927_setup.o +obj-y += toshiba_rbtx4927_irq.o + +obj-$(CONFIG_PCI) += toshiba_rbtx4927_pci_fixup.o +obj-$(CONFIG_PCI) += toshiba_rbtx4927_pci_ops.o + +EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,795 @@ +/* + * linux/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_irq.c + * + * Toshiba RBTX4927 specific interrupt handlers + * + * Author: MontaVista Software, Inc. + * source@mvista.com + * + * Copyright 2001-2002 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +/* +IRQ Device +00 RBTX4927-ISA/00 +01 RBTX4927-ISA/01 PS2/Keyboard +02 RBTX4927-ISA/02 Cascade RBTX4927-ISA (irqs 8-15) +03 RBTX4927-ISA/03 +04 RBTX4927-ISA/04 +05 RBTX4927-ISA/05 +06 RBTX4927-ISA/06 +07 RBTX4927-ISA/07 +08 RBTX4927-ISA/08 +09 RBTX4927-ISA/09 +10 RBTX4927-ISA/10 +11 RBTX4927-ISA/11 +12 RBTX4927-ISA/12 PS2/Mouse (not supported at this time) +13 RBTX4927-ISA/13 +14 RBTX4927-ISA/14 IDE +15 RBTX4927-ISA/15 + +16 TX4927-CP0/00 Software 0 +17 TX4927-CP0/01 Software 1 +18 TX4927-CP0/02 Cascade TX4927-CP0 +19 TX4927-CP0/03 Multiplexed -- do not use +20 TX4927-CP0/04 Multiplexed -- do not use +21 TX4927-CP0/05 Multiplexed -- do not use +22 TX4927-CP0/06 Multiplexed -- do not use +23 TX4927-CP0/07 CPU TIMER + +24 TX4927-PIC/00 +25 TX4927-PIC/01 +26 TX4927-PIC/02 +27 TX4927-PIC/03 Cascade RBTX4927-IOC +28 TX4927-PIC/04 +29 TX4927-PIC/05 RBTX4927 RTL-8019AS ethernet +30 TX4927-PIC/06 +31 TX4927-PIC/07 +32 TX4927-PIC/08 TX4927 SerialIO Channel 0 +33 TX4927-PIC/09 TX4927 SerialIO Channel 1 +34 TX4927-PIC/10 +35 TX4927-PIC/11 +36 TX4927-PIC/12 +37 TX4927-PIC/13 +38 TX4927-PIC/14 +39 TX4927-PIC/15 +40 TX4927-PIC/16 TX4927 PCI PCI-C +41 TX4927-PIC/17 +42 TX4927-PIC/18 +43 TX4927-PIC/19 +44 TX4927-PIC/20 +45 TX4927-PIC/21 +46 TX4927-PIC/22 TX4927 PCI PCI-ERR +47 TX4927-PIC/23 TX4927 PCI PCI-PMA (not used) +48 TX4927-PIC/24 +49 TX4927-PIC/25 +50 TX4927-PIC/26 +51 TX4927-PIC/27 +52 TX4927-PIC/28 +53 TX4927-PIC/29 +54 TX4927-PIC/30 +55 TX4927-PIC/31 + +56 RBTX4927-IOC/00 FPCIB0 PCI-D PJ4/A PJ5/B SB/C PJ6/D PJ7/A (SouthBridge/NotUsed) [RTL-8139=PJ4] +57 RBTX4927-IOC/01 FPCIB0 PCI-C PJ4/D PJ5/A SB/B PJ6/C PJ7/D (SouthBridge/NotUsed) [RTL-8139=PJ5] +58 RBTX4927-IOC/02 FPCIB0 PCI-B PJ4/C PJ5/D SB/A PJ6/B PJ7/C (SouthBridge/IDE/pin=1,INTR) [RTL-8139=NotSupported] +59 RBTX4927-IOC/03 FPCIB0 PCI-A PJ4/B PJ5/C SB/D PJ6/A PJ7/B (SouthBridge/USB/pin=4) [RTL-8139=PJ6] +60 RBTX4927-IOC/04 +61 RBTX4927-IOC/05 +62 RBTX4927-IOC/06 +63 RBTX4927-IOC/07 + +NOTES: +SouthBridge/INTR is mapped to SouthBridge/A=PCI-B/#58 +SouthBridge/ISA/pin=0 no pci irq used by this device +SouthBridge/IDE/pin=1 no pci irq used by this device, using INTR via ISA IRQ14 +SouthBridge/USB/pin=4 using pci irq SouthBridge/D=PCI-A=#59 +SouthBridge/PMC/pin=0 no pci irq used by this device +SuperIO/PS2/Keyboard, using INTR via ISA IRQ1 +SuperIO/PS2/Mouse, using INTR via ISA IRQ12 (mouse not currently supported) +JP7 is not bus master -- do NOT use -- only 4 pci bus master's allowed -- SouthBridge, JP4, JP5, JP6 +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_RTC_DS1742 +#include +#endif +#ifdef CONFIG_TOSHIBA_FPCIB0 +#include +#endif +#include + + +#undef TOSHIBA_RBTX4927_IRQ_DEBUG + +#ifdef TOSHIBA_RBTX4927_IRQ_DEBUG +#define TOSHIBA_RBTX4927_IRQ_NONE 0x00000000 + +#define TOSHIBA_RBTX4927_IRQ_INFO ( 1 << 0 ) +#define TOSHIBA_RBTX4927_IRQ_WARN ( 1 << 1 ) +#define TOSHIBA_RBTX4927_IRQ_EROR ( 1 << 2 ) + +#define TOSHIBA_RBTX4927_IRQ_IOC_INIT ( 1 << 10 ) +#define TOSHIBA_RBTX4927_IRQ_IOC_STARTUP ( 1 << 11 ) +#define TOSHIBA_RBTX4927_IRQ_IOC_SHUTDOWN ( 1 << 12 ) +#define TOSHIBA_RBTX4927_IRQ_IOC_ENABLE ( 1 << 13 ) +#define TOSHIBA_RBTX4927_IRQ_IOC_DISABLE ( 1 << 14 ) +#define TOSHIBA_RBTX4927_IRQ_IOC_MASK ( 1 << 15 ) +#define TOSHIBA_RBTX4927_IRQ_IOC_ENDIRQ ( 1 << 16 ) + +#define TOSHIBA_RBTX4927_IRQ_ISA_INIT ( 1 << 20 ) +#define TOSHIBA_RBTX4927_IRQ_ISA_STARTUP ( 1 << 21 ) +#define TOSHIBA_RBTX4927_IRQ_ISA_SHUTDOWN ( 1 << 22 ) +#define TOSHIBA_RBTX4927_IRQ_ISA_ENABLE ( 1 << 23 ) +#define TOSHIBA_RBTX4927_IRQ_ISA_DISABLE ( 1 << 24 ) +#define TOSHIBA_RBTX4927_IRQ_ISA_MASK ( 1 << 25 ) +#define TOSHIBA_RBTX4927_IRQ_ISA_ENDIRQ ( 1 << 26 ) + +#define TOSHIBA_RBTX4927_SETUP_ALL 0xffffffff +#endif + + +#ifdef TOSHIBA_RBTX4927_IRQ_DEBUG +static const u32 toshiba_rbtx4927_irq_debug_flag = + (TOSHIBA_RBTX4927_IRQ_NONE | TOSHIBA_RBTX4927_IRQ_INFO | + TOSHIBA_RBTX4927_IRQ_WARN | TOSHIBA_RBTX4927_IRQ_EROR +// | TOSHIBA_RBTX4927_IRQ_IOC_INIT +// | TOSHIBA_RBTX4927_IRQ_IOC_STARTUP +// | TOSHIBA_RBTX4927_IRQ_IOC_SHUTDOWN +// | TOSHIBA_RBTX4927_IRQ_IOC_ENABLE +// | TOSHIBA_RBTX4927_IRQ_IOC_DISABLE +// | TOSHIBA_RBTX4927_IRQ_IOC_MASK +// | TOSHIBA_RBTX4927_IRQ_IOC_ENDIRQ +// | TOSHIBA_RBTX4927_IRQ_ISA_INIT +// | TOSHIBA_RBTX4927_IRQ_ISA_STARTUP +// | TOSHIBA_RBTX4927_IRQ_ISA_SHUTDOWN +// | TOSHIBA_RBTX4927_IRQ_ISA_ENABLE +// | TOSHIBA_RBTX4927_IRQ_ISA_DISABLE +// | TOSHIBA_RBTX4927_IRQ_ISA_MASK +// | TOSHIBA_RBTX4927_IRQ_ISA_ENDIRQ + ); +#endif + + +#ifdef TOSHIBA_RBTX4927_IRQ_DEBUG +#define TOSHIBA_RBTX4927_IRQ_DPRINTK(flag,str...) \ + if ( (toshiba_rbtx4927_irq_debug_flag) & (flag) ) \ + { \ + char tmp[100]; \ + sprintf( tmp, str ); \ + printk( "%s(%s:%u)::%s", __FUNCTION__, __FILE__, __LINE__, tmp ); \ + } +#else +#define TOSHIBA_RBTX4927_IRQ_DPRINTK(flag,str...) +#endif + + + + +#define TOSHIBA_RBTX4927_IRQ_IOC_RAW_BEG 0 +#define TOSHIBA_RBTX4927_IRQ_IOC_RAW_END 7 + +#define TOSHIBA_RBTX4927_IRQ_IOC_BEG ((TX4927_IRQ_PIC_END+1)+TOSHIBA_RBTX4927_IRQ_IOC_RAW_BEG) /* 56 */ +#define TOSHIBA_RBTX4927_IRQ_IOC_END ((TX4927_IRQ_PIC_END+1)+TOSHIBA_RBTX4927_IRQ_IOC_RAW_END) /* 63 */ + + +#define TOSHIBA_RBTX4927_IRQ_ISA_BEG MI8259_IRQ_ISA_BEG +#define TOSHIBA_RBTX4927_IRQ_ISA_END MI8259_IRQ_ISA_END +#define TOSHIBA_RBTX4927_IRQ_ISA_MID ((TOSHIBA_RBTX4927_IRQ_ISA_BEG+TOSHIBA_RBTX4927_IRQ_ISA_END+1)/2) + + +#define TOSHIBA_RBTX4927_IRQ_NEST_IOC_ON_PIC TX4927_IRQ_NEST_EXT_ON_PIC +#define TOSHIBA_RBTX4927_IRQ_NEST_ISA_ON_IOC (TOSHIBA_RBTX4927_IRQ_IOC_BEG+2) +#define TOSHIBA_RBTX4927_IRQ_NEST_ISA_ON_ISA (TOSHIBA_RBTX4927_IRQ_ISA_BEG+2) + +extern int tx4927_using_backplane; + +#ifdef CONFIG_TOSHIBA_FPCIB0 +extern void enable_8259A_irq(unsigned int irq); +extern void disable_8259A_irq(unsigned int irq); +extern void mask_and_ack_8259A(unsigned int irq); +#endif + +static unsigned int toshiba_rbtx4927_irq_ioc_startup(unsigned int irq); +static void toshiba_rbtx4927_irq_ioc_shutdown(unsigned int irq); +static void toshiba_rbtx4927_irq_ioc_enable(unsigned int irq); +static void toshiba_rbtx4927_irq_ioc_disable(unsigned int irq); +static void toshiba_rbtx4927_irq_ioc_mask_and_ack(unsigned int irq); +static void toshiba_rbtx4927_irq_ioc_end(unsigned int irq); + +#ifdef CONFIG_TOSHIBA_FPCIB0 +static unsigned int toshiba_rbtx4927_irq_isa_startup(unsigned int irq); +static void toshiba_rbtx4927_irq_isa_shutdown(unsigned int irq); +static void toshiba_rbtx4927_irq_isa_enable(unsigned int irq); +static void toshiba_rbtx4927_irq_isa_disable(unsigned int irq); +static void toshiba_rbtx4927_irq_isa_mask_and_ack(unsigned int irq); +static void toshiba_rbtx4927_irq_isa_end(unsigned int irq); +#endif + +static spinlock_t toshiba_rbtx4927_ioc_lock = SPIN_LOCK_UNLOCKED; + + +#define TOSHIBA_RBTX4927_IOC_NAME "RBTX4927-IOC" +static struct hw_interrupt_type toshiba_rbtx4927_irq_ioc_type = { + typename:TOSHIBA_RBTX4927_IOC_NAME, + startup:toshiba_rbtx4927_irq_ioc_startup, + shutdown:toshiba_rbtx4927_irq_ioc_shutdown, + enable:toshiba_rbtx4927_irq_ioc_enable, + disable:toshiba_rbtx4927_irq_ioc_disable, + ack:toshiba_rbtx4927_irq_ioc_mask_and_ack, + end:toshiba_rbtx4927_irq_ioc_end, + set_affinity:NULL +}; +#define TOSHIBA_RBTX4927_IOC_INTR_ENAB 0xbc002000 +#define TOSHIBA_RBTX4927_IOC_INTR_STAT 0xbc002006 + + +#ifdef CONFIG_TOSHIBA_FPCIB0 +#define TOSHIBA_RBTX4927_ISA_NAME "RBTX4927-ISA" +static struct hw_interrupt_type toshiba_rbtx4927_irq_isa_type = { + typename:TOSHIBA_RBTX4927_ISA_NAME, + startup:toshiba_rbtx4927_irq_isa_startup, + shutdown:toshiba_rbtx4927_irq_isa_shutdown, + enable:toshiba_rbtx4927_irq_isa_enable, + disable:toshiba_rbtx4927_irq_isa_disable, + ack:toshiba_rbtx4927_irq_isa_mask_and_ack, + end:toshiba_rbtx4927_irq_isa_end, + set_affinity:NULL +}; +#endif + + +u32 bit2num(u32 num) +{ + u32 i; + + for (i = 0; i < (sizeof(num) * 8); i++) { + if (num & (1 << i)) { + return (i); + } + } + return (0); +} + +int toshiba_rbtx4927_irq_nested(int sw_irq) +{ + u32 level3; + u32 level4; + u32 level5; + + level3 = reg_rd08(TOSHIBA_RBTX4927_IOC_INTR_STAT) & 0x1f; + if (level3) { + sw_irq = TOSHIBA_RBTX4927_IRQ_IOC_BEG + bit2num(level3); + if (sw_irq != TOSHIBA_RBTX4927_IRQ_NEST_ISA_ON_IOC) { + goto RETURN; + } + } +#ifdef CONFIG_TOSHIBA_FPCIB0 + { + if (tx4927_using_backplane) { + outb(0x0A, 0x20); + level4 = inb(0x20) & 0xff; + if (level4) { + sw_irq = + TOSHIBA_RBTX4927_IRQ_ISA_BEG + + bit2num(level4); + if (sw_irq != + TOSHIBA_RBTX4927_IRQ_NEST_ISA_ON_ISA) { + goto RETURN; + } + } + + outb(0x0A, 0xA0); + level5 = inb(0xA0) & 0xff; + if (level5) { + sw_irq = + TOSHIBA_RBTX4927_IRQ_ISA_MID + + bit2num(level5); + goto RETURN; + } + } + } +#endif + + RETURN: + return (sw_irq); +} + +//#define TOSHIBA_RBTX4927_PIC_ACTION(s) { no_action, 0, 0, s, NULL, NULL } +#define TOSHIBA_RBTX4927_PIC_ACTION(s) { no_action, SA_SHIRQ, 0, s, NULL, NULL } +static struct irqaction toshiba_rbtx4927_irq_ioc_action = +TOSHIBA_RBTX4927_PIC_ACTION(TOSHIBA_RBTX4927_IOC_NAME); +#ifdef CONFIG_TOSHIBA_FPCIB0 +static struct irqaction toshiba_rbtx4927_irq_isa_master = +TOSHIBA_RBTX4927_PIC_ACTION(TOSHIBA_RBTX4927_ISA_NAME "/M"); +static struct irqaction toshiba_rbtx4927_irq_isa_slave = +TOSHIBA_RBTX4927_PIC_ACTION(TOSHIBA_RBTX4927_ISA_NAME "/S"); +#endif + + +/**********************************************************************************/ +/* Functions for ioc */ +/**********************************************************************************/ + + +static void __init toshiba_rbtx4927_irq_ioc_init(void) +{ + int i; + + TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_IOC_INIT, + "beg=%d end=%d\n", + TOSHIBA_RBTX4927_IRQ_IOC_BEG, + TOSHIBA_RBTX4927_IRQ_IOC_END); + + for (i = TOSHIBA_RBTX4927_IRQ_IOC_BEG; + i <= TOSHIBA_RBTX4927_IRQ_IOC_END; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = 3; + irq_desc[i].handler = &toshiba_rbtx4927_irq_ioc_type; + } + + setup_irq(TOSHIBA_RBTX4927_IRQ_NEST_IOC_ON_PIC, + &toshiba_rbtx4927_irq_ioc_action); + + return; +} + +static unsigned int toshiba_rbtx4927_irq_ioc_startup(unsigned int irq) +{ + TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_IOC_STARTUP, + "irq=%d\n", irq); + + if (irq < TOSHIBA_RBTX4927_IRQ_IOC_BEG + || irq > TOSHIBA_RBTX4927_IRQ_IOC_END) { + TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR, + "bad irq=%d\n", irq); + panic("\n"); + } + + toshiba_rbtx4927_irq_ioc_enable(irq); + + return (0); +} + + +static void toshiba_rbtx4927_irq_ioc_shutdown(unsigned int irq) +{ + TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_IOC_SHUTDOWN, + "irq=%d\n", irq); + + if (irq < TOSHIBA_RBTX4927_IRQ_IOC_BEG + || irq > TOSHIBA_RBTX4927_IRQ_IOC_END) { + TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR, + "bad irq=%d\n", irq); + panic("\n"); + } + + toshiba_rbtx4927_irq_ioc_disable(irq); + + return; +} + + +static void toshiba_rbtx4927_irq_ioc_enable(unsigned int irq) +{ + unsigned long flags; + volatile unsigned char v; + + TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_IOC_ENABLE, + "irq=%d\n", irq); + + if (irq < TOSHIBA_RBTX4927_IRQ_IOC_BEG + || irq > TOSHIBA_RBTX4927_IRQ_IOC_END) { + TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR, + "bad irq=%d\n", irq); + panic("\n"); + } + + spin_lock_irqsave(&toshiba_rbtx4927_ioc_lock, flags); + + v = TX4927_RD08(TOSHIBA_RBTX4927_IOC_INTR_ENAB); + v |= (1 << (irq - TOSHIBA_RBTX4927_IRQ_IOC_BEG)); + TOSHIBA_RBTX4927_WR08(TOSHIBA_RBTX4927_IOC_INTR_ENAB, v); + + spin_unlock_irqrestore(&toshiba_rbtx4927_ioc_lock, flags); + + return; +} + + +static void toshiba_rbtx4927_irq_ioc_disable(unsigned int irq) +{ + unsigned long flags; + volatile unsigned char v; + + TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_IOC_DISABLE, + "irq=%d\n", irq); + + if (irq < TOSHIBA_RBTX4927_IRQ_IOC_BEG + || irq > TOSHIBA_RBTX4927_IRQ_IOC_END) { + TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR, + "bad irq=%d\n", irq); + panic("\n"); + } + + spin_lock_irqsave(&toshiba_rbtx4927_ioc_lock, flags); + + v = TX4927_RD08(TOSHIBA_RBTX4927_IOC_INTR_ENAB); + v &= ~(1 << (irq - TOSHIBA_RBTX4927_IRQ_IOC_BEG)); + TOSHIBA_RBTX4927_WR08(TOSHIBA_RBTX4927_IOC_INTR_ENAB, v); + + spin_unlock_irqrestore(&toshiba_rbtx4927_ioc_lock, flags); + + return; +} + + +static void toshiba_rbtx4927_irq_ioc_mask_and_ack(unsigned int irq) +{ + TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_IOC_MASK, + "irq=%d\n", irq); + + if (irq < TOSHIBA_RBTX4927_IRQ_IOC_BEG + || irq > TOSHIBA_RBTX4927_IRQ_IOC_END) { + TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR, + "bad irq=%d\n", irq); + panic("\n"); + } + + toshiba_rbtx4927_irq_ioc_disable(irq); + + return; +} + + +static void toshiba_rbtx4927_irq_ioc_end(unsigned int irq) +{ + TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_IOC_ENDIRQ, + "irq=%d\n", irq); + + if (irq < TOSHIBA_RBTX4927_IRQ_IOC_BEG + || irq > TOSHIBA_RBTX4927_IRQ_IOC_END) { + TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR, + "bad irq=%d\n", irq); + panic("\n"); + } + + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { + toshiba_rbtx4927_irq_ioc_enable(irq); + } + + return; +} + + +/**********************************************************************************/ +/* Functions for isa */ +/**********************************************************************************/ + + +#ifdef CONFIG_TOSHIBA_FPCIB0 +static void __init toshiba_rbtx4927_irq_isa_init(void) +{ + int i; + + TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_ISA_INIT, + "beg=%d end=%d\n", + TOSHIBA_RBTX4927_IRQ_ISA_BEG, + TOSHIBA_RBTX4927_IRQ_ISA_END); + + for (i = TOSHIBA_RBTX4927_IRQ_ISA_BEG; + i <= TOSHIBA_RBTX4927_IRQ_ISA_END; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = + ((i < TOSHIBA_RBTX4927_IRQ_ISA_MID) ? (4) : (5)); + irq_desc[i].handler = &toshiba_rbtx4927_irq_isa_type; + } + + setup_irq(TOSHIBA_RBTX4927_IRQ_NEST_ISA_ON_IOC, + &toshiba_rbtx4927_irq_isa_master); + setup_irq(TOSHIBA_RBTX4927_IRQ_NEST_ISA_ON_ISA, + &toshiba_rbtx4927_irq_isa_slave); + + /* make sure we are looking at IRR (not ISR) */ + outb(0x0A, 0x20); + outb(0x0A, 0xA0); + + return; +} +#endif + + +#ifdef CONFIG_TOSHIBA_FPCIB0 +static unsigned int toshiba_rbtx4927_irq_isa_startup(unsigned int irq) +{ + TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_ISA_STARTUP, + "irq=%d\n", irq); + + if (irq < TOSHIBA_RBTX4927_IRQ_ISA_BEG + || irq > TOSHIBA_RBTX4927_IRQ_ISA_END) { + TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR, + "bad irq=%d\n", irq); + panic("\n"); + } + + toshiba_rbtx4927_irq_isa_enable(irq); + + return (0); +} +#endif + + +#ifdef CONFIG_TOSHIBA_FPCIB0 +static void toshiba_rbtx4927_irq_isa_shutdown(unsigned int irq) +{ + TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_ISA_SHUTDOWN, + "irq=%d\n", irq); + + if (irq < TOSHIBA_RBTX4927_IRQ_ISA_BEG + || irq > TOSHIBA_RBTX4927_IRQ_ISA_END) { + TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR, + "bad irq=%d\n", irq); + panic("\n"); + } + + toshiba_rbtx4927_irq_isa_disable(irq); + + return; +} +#endif + + +#ifdef CONFIG_TOSHIBA_FPCIB0 +static void toshiba_rbtx4927_irq_isa_enable(unsigned int irq) +{ + TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_ISA_ENABLE, + "irq=%d\n", irq); + + if (irq < TOSHIBA_RBTX4927_IRQ_ISA_BEG + || irq > TOSHIBA_RBTX4927_IRQ_ISA_END) { + TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR, + "bad irq=%d\n", irq); + panic("\n"); + } + + enable_8259A_irq(irq); + + return; +} +#endif + + +#ifdef CONFIG_TOSHIBA_FPCIB0 +static void toshiba_rbtx4927_irq_isa_disable(unsigned int irq) +{ + TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_ISA_DISABLE, + "irq=%d\n", irq); + + if (irq < TOSHIBA_RBTX4927_IRQ_ISA_BEG + || irq > TOSHIBA_RBTX4927_IRQ_ISA_END) { + TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR, + "bad irq=%d\n", irq); + panic("\n"); + } + + disable_8259A_irq(irq); + + return; +} +#endif + + +#ifdef CONFIG_TOSHIBA_FPCIB0 +static void toshiba_rbtx4927_irq_isa_mask_and_ack(unsigned int irq) +{ + TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_ISA_MASK, + "irq=%d\n", irq); + + if (irq < TOSHIBA_RBTX4927_IRQ_ISA_BEG + || irq > TOSHIBA_RBTX4927_IRQ_ISA_END) { + TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR, + "bad irq=%d\n", irq); + panic("\n"); + } + + mask_and_ack_8259A(irq); + + return; +} +#endif + + +#ifdef CONFIG_TOSHIBA_FPCIB0 +static void toshiba_rbtx4927_irq_isa_end(unsigned int irq) +{ + TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_ISA_ENDIRQ, + "irq=%d\n", irq); + + if (irq < TOSHIBA_RBTX4927_IRQ_ISA_BEG + || irq > TOSHIBA_RBTX4927_IRQ_ISA_END) { + TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_EROR, + "bad irq=%d\n", irq); + panic("\n"); + } + + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { + toshiba_rbtx4927_irq_isa_enable(irq); + } + + return; +} +#endif + + +void __init init_IRQ(void) +{ + extern void tx4927_irq_init(void); + + cli(); + + tx4927_irq_init(); + toshiba_rbtx4927_irq_ioc_init(); +#ifdef CONFIG_TOSHIBA_FPCIB0 + { + if (tx4927_using_backplane) { + toshiba_rbtx4927_irq_isa_init(); + } + } +#endif + +#ifdef CONFIG_PCI + { + extern void toshiba_rbtx4927_pci_irq_init(void); + toshiba_rbtx4927_pci_irq_init(); + } +#endif + + wbflush(); + + return; +} + +void toshiba_rbtx4927_irq_dump(char *key) +{ +#ifdef TOSHIBA_RBTX4927_IRQ_DEBUG + { + u32 i, j = 0; + for (i = 0; i < NR_IRQS; i++) { + if (strcmp(irq_desc[i].handler->typename, "none") + == 0) + continue; + + if ((i >= 1) + && (irq_desc[i - 1].handler->typename == + irq_desc[i].handler->typename)) { + j++; + } else { + j = 0; + } + TOSHIBA_RBTX4927_IRQ_DPRINTK + (TOSHIBA_RBTX4927_IRQ_INFO, + "%s irq=0x%02x/%3d s=0x%08x h=0x%08x a=0x%08x ah=0x%08x d=%1d n=%s/%02d\n", + key, i, i, irq_desc[i].status, + (u32) irq_desc[i].handler, + (u32) irq_desc[i].action, + (u32) (irq_desc[i].action ? irq_desc[i]. + action->handler : 0), + irq_desc[i].depth, + irq_desc[i].handler->typename, j); + } + } +#endif + return; +} + +void toshiba_rbtx4927_irq_dump_pics(char *s) +{ + u32 level0_m; + u32 level0_s; + u32 level1_m; + u32 level1_s; + u32 level2; + u32 level2_p; + u32 level2_s; + u32 level3_m; + u32 level3_s; + u32 level4_m; + u32 level4_s; + u32 level5_m; + u32 level5_s; + + if (s == NULL) + s = "null"; + + level0_m = (read_c0_status() & 0x0000ff00) >> 8; + level0_s = (read_c0_cause() & 0x0000ff00) >> 8; + + level1_m = level0_m; + level1_s = level0_s & 0x87; + + level2 = TX4927_RD(0xff1ff6a0); + level2_p = (((level2 & 0x10000)) ? 0 : 1); + level2_s = (((level2 & 0x1f) == 0x1f) ? 0 : (level2 & 0x1f)); + + level3_m = reg_rd08(TOSHIBA_RBTX4927_IOC_INTR_ENAB) & 0x1f; + level3_s = reg_rd08(TOSHIBA_RBTX4927_IOC_INTR_STAT) & 0x1f; + + level4_m = inb(0x21); + outb(0x0A, 0x20); + level4_s = inb(0x20); + + level5_m = inb(0xa1); + outb(0x0A, 0xa0); + level5_s = inb(0xa0); + + TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_INFO, + "dump_raw_pic() "); + TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_INFO, + "cp0:m=0x%02x/s=0x%02x ", level0_m, + level0_s); + TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_INFO, + "cp0:m=0x%02x/s=0x%02x ", level1_m, + level1_s); + TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_INFO, + "pic:e=0x%02x/s=0x%02x ", level2_p, + level2_s); + TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_INFO, + "ioc:m=0x%02x/s=0x%02x ", level3_m, + level3_s); + TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_INFO, + "sbm:m=0x%02x/s=0x%02x ", level4_m, + level4_s); + TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_INFO, + "sbs:m=0x%02x/s=0x%02x ", level5_m, + level5_s); + TOSHIBA_RBTX4927_IRQ_DPRINTK(TOSHIBA_RBTX4927_IRQ_INFO, "[%s]\n", + s); + + return; +} diff -Nru a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_pci_fixup.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_pci_fixup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_pci_fixup.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,329 @@ +/* + * + * BRIEF MODULE DESCRIPTION + * Board specific pci fixups for the Toshiba rbtx4927 + * + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * Copyright (C) 2000-2001 Toshiba Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include + +#include +#include + +#undef DEBUG +#ifdef DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +void __init pcibios_fixup_resources(struct pci_dev *dev) +{ + /* will need to fixup IO resources */ +} + +void __init pcibios_fixup(void) +{ + /* nothing to do here */ +} + +/* look up table for backplane pci irq for slots 17-20 by pin # */ +static unsigned char backplane_pci_irq[4][4] = { + /* PJ6 SLOT: 17, PIN: 1 */ {TX4927_IRQ_IOC_PCIA, + /* PJ6 SLOT: 17, PIN: 2 */ + TX4927_IRQ_IOC_PCIB, + /* PJ6 SLOT: 17, PIN: 3 */ + TX4927_IRQ_IOC_PCIC, + /* PJ6 SLOT: 17, PIN: 4 */ + TX4927_IRQ_IOC_PCID}, + /* SB SLOT: 18, PIN: 1 */ {TX4927_IRQ_IOC_PCIB, + /* SB SLOT: 18, PIN: 2 */ + TX4927_IRQ_IOC_PCIC, + /* SB SLOT: 18, PIN: 3 */ + TX4927_IRQ_IOC_PCID, + /* SB SLOT: 18, PIN: 4 */ + TX4927_IRQ_IOC_PCIA}, + /* PJ5 SLOT: 19, PIN: 1 */ {TX4927_IRQ_IOC_PCIC, + /* PJ5 SLOT: 19, PIN: 2 */ + TX4927_IRQ_IOC_PCID, + /* PJ5 SLOT: 19, PIN: 3 */ + TX4927_IRQ_IOC_PCIA, + /* PJ5 SLOT: 19, PIN: 4 */ + TX4927_IRQ_IOC_PCIB}, + /* PJ4 SLOT: 20, PIN: 1 */ {TX4927_IRQ_IOC_PCID, + /* PJ4 SLOT: 20, PIN: 2 */ + TX4927_IRQ_IOC_PCIA, + /* PJ4 SLOT: 20, PIN: 3 */ + TX4927_IRQ_IOC_PCIB, + /* PJ4 SLOT: 20, PIN: 4 */ + TX4927_IRQ_IOC_PCIC} +}; + +int pci_get_irq(struct pci_dev *dev, int pin) +{ + unsigned char irq = pin; + + DBG("pci_get_irq: pin is %d\n", pin); + /* IRQ rotation */ + irq--; /* 0-3 */ + if (dev->bus->parent == NULL && + PCI_SLOT(dev->devfn) == TX4927_PCIC_IDSEL_AD_TO_SLOT(23)) { + printk("Onboard PCI_SLOT(dev->devfn) is %d\n", + PCI_SLOT(dev->devfn)); + /* IDSEL=A23 is tx4927 onboard pci slot */ + irq = (irq + PCI_SLOT(dev->devfn)) % 4; + irq++; /* 1-4 */ + DBG("irq is now %d\n", irq); + + switch (irq) { + case 1: + irq = TX4927_IRQ_IOC_PCIA; + break; + case 2: + irq = TX4927_IRQ_IOC_PCIB; + break; + case 3: + irq = TX4927_IRQ_IOC_PCIC; + break; + case 4: + irq = TX4927_IRQ_IOC_PCID; + break; + } + } else { + /* PCI Backplane */ + DBG("PCI Backplane PCI_SLOT(dev->devfn) is %d\n", + PCI_SLOT(dev->devfn)); + irq = backplane_pci_irq[PCI_SLOT(dev->devfn) - 17][irq]; + } + DBG("assigned irq %d\n", irq); + return irq; +} + + +#ifdef TX4927_SUPPORT_PCI_66 +extern int tx4927_pci66; +extern void tx4927_pci66_setup(void); +#endif +extern void tx4927_pci_setup(void); + +#ifdef TX4927_SUPPORT_PCI_66 +int tx4927_pci66_check(void) +{ + struct pci_dev *dev; + unsigned short stat; + int cap66 = 1; + + if (tx4927_pci66 < 0) + return 0; + + /* check 66MHz capability */ + pci_for_each_dev(dev) { + if (cap66) { + pci_read_config_word(dev, PCI_STATUS, &stat); + if (!(stat & PCI_STATUS_66MHZ)) { + printk(KERN_INFO + "PCI: %02x:%02x not 66MHz capable.\n", + dev->bus->number, dev->devfn); + cap66 = 0; + } + } + } + return cap66; +} +#endif + +#ifdef DEBUG +void do_it(u32 offset, u32 reg) +{ + volatile u32 a1; + volatile u32 a2; + volatile u32 v1; + volatile u32 v2; + + a1 = 0xff1f0000 + offset + reg; + a2 = a1 + 4; + + v1 = *(volatile u32 *) a1; + v2 = *(volatile u32 *) a2; + + if (v1) + printk("TX4927 0x%08x 0x%08x\n", a1, v1); + if (v2) + printk("TX4927 0x%08x 0x%08x\n", a2, v2); +} + +void do_it1(u32 base, u32 r) +{ + do_it(base, r); +} + +void do_it2(u32 base, u32 start, u32 stop) +{ + u32 r; + + for (r = start; r <= stop; r += 8) { + do_it(base, r); + } +} +void dump_config(void) +{ + unsigned long id; + unsigned long j; + struct pci_dev *dev; + + printk("----------------------pci\n"); + pci_for_each_dev(dev) { + for (j = 0; j < 64; j++) { + pci_read_config_dword(dev, j * 4, &id); + if (id == 0) + continue; + printk + ("dev 0x%02x 0x%02x:0x%02x -- 0x%02x-0x%02x 0x%08x\n", + dev->devfn, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), (j * 4) + 3, (j * 4), + id); + } + printk("dev 0x%02x \n", dev->devfn); + } + printk("----------------------sdram\n"); + do_it2(0x8000, 0x00, 0x18); + do_it1(0x8000, 0x40); + do_it1(0x8000, 0x58); + printk("----------------------ebus\n"); + do_it2(0x9000, 0x00, 0x38); + printk("----------------------ecc\n"); + do_it2(0xa000, 0x00, 0x08); + printk("----------------------dmac\n"); + do_it2(0xb000, 0x00, 0xf8); + /* b1xx */ + printk("----------------------pci\n"); + /* d */ + printk("----------------------cfg\n"); + do_it2(0xe000, 0x00, 0x20); + do_it1(0xe000, 0x30); + do_it1(0xe000, 0x48); + printk("----------------------timers\n"); + do_it2(0xf000, 0x00, 0xf0); + do_it2(0xf100, 0x00, 0xf0); + do_it2(0xf200, 0x00, 0xf0); + printk("----------------------serial\n"); + do_it2(0xf300, 0x00, 0x20); + do_it2(0xf400, 0x00, 0x20); + printk("----------------------parallel\n"); + do_it2(0xf500, 0x00, 0x0c); + printk("----------------------pic\n"); + do_it2(0xf500, 0x10, 0x24); + do_it2(0xf600, 0x00, 0x2c); + do_it1(0xf600, 0x40); + do_it1(0xf600, 0x60); + do_it1(0xf600, 0x80); + do_it1(0xf600, 0xa0); + printk("----------------------aclink\n"); + do_it2(0xf700, 0x00, 0xfc); + printk("----------------------done\n"); +} +#endif + + +void __init pcibios_fixup_irqs(void) +{ + unsigned char pin; + unsigned char irq; + struct pci_dev *dev; + unsigned int id; + +#ifdef TX4927_SUPPORT_PCI_66 + { + if (tx4927_pci66_check()) { + tx4927_pci66_setup(); + tx4927_pci_setup(); /* Reinitialize PCIC */ + } + } +#endif + + pci_for_each_dev(dev) { + DBG("FIXUP:\n"); + DBG(" devfn=0x%02x (0x%02x:0x%02x)\n", + dev->devfn, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn)); + + pci_read_config_dword(dev, PCI_VENDOR_ID, &id); + DBG(" id=0x%08x\n", id); + + pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); + DBG(" line=0x%02x/%d\n", irq, irq); + + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); + DBG(" pin=%d\n", pin); + +#ifdef DEBUG + { + unsigned int tmp; + pci_read_config_dword(dev, 0x10, &tmp); + DBG(" bar0:0x10=0x%08x\n", tmp); + pci_read_config_dword(dev, 0x14, &tmp); + DBG(" bar1:0x14=0x%08x\n", tmp); + pci_read_config_dword(dev, 0x1c, &tmp); + DBG(" bar2:0x1c=0x%08x\n", tmp); + pci_read_config_dword(dev, 0x20, &tmp); + DBG(" bar3:0x20=0x%08x\n", tmp); + pci_read_config_dword(dev, 0x24, &tmp); + DBG(" bar4:0x24=0x%08x\n", tmp); + } +#endif + + irq = 0; + + if (id == 0x91301055) { /* ide */ + irq = 14; + } + + if (pin == 0) { + DBG(" auto irq (now=%d) -- skipping pin=0\n", irq); + } else if (irq) { + DBG(" auto irq (now=%d) -- skipping hardcoded irq\n", irq); + } else { + DBG(" auto irq (was=%d)\n", irq); + irq = pci_get_irq(dev, pin); + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, + irq); + dev->irq = irq; + DBG(" auto irq (now=%d)\n", irq); + } + + pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); + printk(KERN_INFO + "PCI: 0x%02x:0x%02x(0x%02x,0x%02x) IRQ=%d\n", + dev->bus->number, dev->devfn, PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn), irq); + + } + +} diff -Nru a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_pci_ops.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_pci_ops.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_pci_ops.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,317 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ahennessy@mvista.com + * + * Copyright (C) 2000-2001 Toshiba Corporation + * + * Based on arch/mips/ddb5xxx/ddb5477/pci_ops.c + * + * Define the pci_ops for the Toshiba rbtx4927 + * + * Much of the code is derived from the original DDB5074 port by + * Geert Uytterhoeven + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include + +#include +#include +#include +#include + +/* initialize in setup */ +struct resource pci_io_resource = { + "pci IO space", + (PCIBIOS_MIN_IO), + ((PCIBIOS_MIN_IO) + (TX4927_PCIIO_SIZE)) - 1, + IORESOURCE_IO +}; + +/* initialize in setup */ +struct resource pci_mem_resource = { + "pci memory space", + TX4927_PCIMEM, + TX4927_PCIMEM + TX4927_PCIMEM_SIZE - 1, + IORESOURCE_MEM +}; + +extern struct pci_ops tx4927_pci_ops; + +struct pci_channel mips_pci_channels[] = { + /* h/w only supports devices 0x00 to 0x14 */ + {&tx4927_pci_ops, &pci_io_resource, &pci_mem_resource, + PCI_DEVFN(0x00, 0), PCI_DEVFN(0x14, 7)}, + {NULL, NULL, NULL, 0, 0} +}; + +unsigned int pcibios_assign_all_busses(void) +{ + return 1; +} + +static int +mkaddr(unsigned char bus, unsigned char dev_fn, unsigned char where, + int *flagsp) +{ + if (bus > 0) { + /* Type 1 configuration */ + tx4927_pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) | + ((dev_fn & 0xff) << 0x08) | (where & 0xfc) | 1; + } else { + if (dev_fn >= PCI_DEVFN(TX4927_PCIC_MAX_DEVNU, 0)) + return -1; + + /* Type 0 configuration */ + tx4927_pcicptr->g2pcfgadrs = ((bus & 0xff) << 0x10) | + ((dev_fn & 0xff) << 0x08) | (where & 0xfc); + } + /* clear M_ABORT and Disable M_ABORT Int. */ + tx4927_pcicptr->pcistatus = + (tx4927_pcicptr->pcistatus & 0x0000ffff) | + (PCI_STATUS_REC_MASTER_ABORT << 16); + tx4927_pcicptr->pcimask &= ~PCI_STATUS_REC_MASTER_ABORT; + return 0; +} + +static int check_abort(int flags) +{ + int code = PCIBIOS_SUCCESSFUL; + if (tx4927_pcicptr-> + pcistatus & (PCI_STATUS_REC_MASTER_ABORT << 16)) { + tx4927_pcicptr->pcistatus = + (tx4927_pcicptr-> + pcistatus & 0x0000ffff) | (PCI_STATUS_REC_MASTER_ABORT + << 16); + tx4927_pcicptr->pcimask |= PCI_STATUS_REC_MASTER_ABORT; + code = PCIBIOS_DEVICE_NOT_FOUND; + // printk("returning PCIBIOS_DEVICE_NOT_FOUND\n"); + } + return code; +} + +/* + * We can't address 8 and 16 bit words directly. Instead we have to + * read/write a 32bit word and mask/modify the data we actually want. + */ +static int tx4927_pcibios_read_config_byte(struct pci_dev *dev, + int where, unsigned char *val) +{ + int flags, retval; + unsigned char bus, func_num; + + db_assert((where & 3) == 0); + db_assert(where < (1 << 8)); + + /* check if the bus is top-level */ + if (dev->bus->parent != NULL) { + bus = dev->bus->number; + db_assert(bus != 0); + } else { + bus = 0; + } + + func_num = PCI_FUNC(dev->devfn); + if (mkaddr(bus, dev->devfn, where, &flags)) + return -1; +#ifdef __BIG_ENDIAN + *val = + *(volatile u8 *) ((ulong) & tx4927_pcicptr-> + g2pcfgdata | ((where & 3) ^ 3)); +#else + *val = + *(volatile u8 *) ((ulong) & tx4927_pcicptr-> + g2pcfgdata | (where & 3)); +#endif + retval = check_abort(flags); + if (retval == PCIBIOS_DEVICE_NOT_FOUND) + *val = 0xff; +//printk("CFG R1 0x%02x 0x%02x 0x%08x\n", dev->devfn, where, *val ); + return retval; +} + +static int tx4927_pcibios_read_config_word(struct pci_dev *dev, + int where, unsigned short *val) +{ + int flags, retval; + unsigned char bus, func_num; + + if (where & 1) + return PCIBIOS_BAD_REGISTER_NUMBER; + + db_assert((where & 3) == 0); + db_assert(where < (1 << 8)); + + /* check if the bus is top-level */ + if (dev->bus->parent != NULL) { + bus = dev->bus->number; + db_assert(bus != 0); + } else { + bus = 0; + } + + func_num = PCI_FUNC(dev->devfn); + if (mkaddr(bus, dev->devfn, where, &flags)) + return -1; +#ifdef __BIG_ENDIAN + *val = + *(volatile u16 *) ((ulong) & tx4927_pcicptr-> + g2pcfgdata | ((where & 3) ^ 2)); +#else + *val = + *(volatile u16 *) ((ulong) & tx4927_pcicptr-> + g2pcfgdata | (where & 3)); +#endif + retval = check_abort(flags); + if (retval == PCIBIOS_DEVICE_NOT_FOUND) + *val = 0xffff; +//printk("CFG R2 0x%02x 0x%02x 0x%08x\n", dev->devfn, where, *val ); + return retval; +} + +static int tx4927_pcibios_read_config_dword(struct pci_dev *dev, + int where, unsigned int *val) +{ + int flags, retval; + unsigned char bus, func_num; + + if (where & 3) + return PCIBIOS_BAD_REGISTER_NUMBER; + + db_assert((where & 3) == 0); + db_assert(where < (1 << 8)); + + /* check if the bus is top-level */ + if (dev->bus->parent != NULL) { + bus = dev->bus->number; + db_assert(bus != 0); + } else { + bus = 0; + } + + func_num = PCI_FUNC(dev->devfn); + if (mkaddr(bus, dev->devfn, where, &flags)) + return -1; + *val = tx4927_pcicptr->g2pcfgdata; + retval = check_abort(flags); + if (retval == PCIBIOS_DEVICE_NOT_FOUND) + *val = 0xffffffff; + +//printk("CFG R4 0x%02x 0x%02x 0x%08x\n", dev->devfn, where, *val ); + return retval; +} + +static int tx4927_pcibios_write_config_byte(struct pci_dev *dev, + int where, unsigned char val) +{ + int flags; + unsigned char bus, func_num; + + /* check if the bus is top-level */ + if (dev->bus->parent != NULL) { + bus = dev->bus->number; + db_assert(bus != 0); + } else { + bus = 0; + } + + func_num = PCI_FUNC(dev->devfn); + if (mkaddr(bus, dev->devfn, where, &flags)) + return -1; +#ifdef __BIG_ENDIAN + *(volatile u8 *) ((ulong) & tx4927_pcicptr-> + g2pcfgdata | ((where & 3) ^ 3)) = val; +#else + *(volatile u8 *) ((ulong) & tx4927_pcicptr-> + g2pcfgdata | (where & 3)) = val; +#endif +//printk("CFG W1 0x%02x 0x%02x 0x%08x\n", dev->devfn, where, val ); + return check_abort(flags); +} + +static int tx4927_pcibios_write_config_word(struct pci_dev *dev, + int where, unsigned short val) +{ + int flags; + unsigned char bus, func_num; + + if (where & 1) + return PCIBIOS_BAD_REGISTER_NUMBER; + + /* check if the bus is top-level */ + if (dev->bus->parent != NULL) { + bus = dev->bus->number; + db_assert(bus != 0); + } else { + bus = 0; + } + + func_num = PCI_FUNC(dev->devfn); + if (mkaddr(bus, dev->devfn, where, &flags)) + return -1; +#ifdef __BIG_ENDIAN + *(volatile u16 *) ((ulong) & tx4927_pcicptr-> + g2pcfgdata | ((where & 3) ^ 2)) = val; +#else + *(volatile u16 *) ((ulong) & tx4927_pcicptr-> + g2pcfgdata | (where & 3)) = val; +#endif +//printk("CFG W2 0x%02x 0x%02x 0x%08x\n", dev->devfn, where, val ); + return check_abort(flags); +} + +static int tx4927_pcibios_write_config_dword(struct pci_dev *dev, + int where, unsigned int val) +{ + int flags; + unsigned char bus, func_num; + + if (where & 3) + return PCIBIOS_BAD_REGISTER_NUMBER; + + /* check if the bus is top-level */ + if (dev->bus->parent != NULL) { + bus = dev->bus->number; + db_assert(bus != 0); + } else { + bus = 0; + } + + func_num = PCI_FUNC(dev->devfn); + if (mkaddr(bus, dev->devfn, where, &flags)) + return -1; + tx4927_pcicptr->g2pcfgdata = val; +//printk("CFG W4 0x%02x 0x%02x 0x%08x\n", dev->devfn, where, val ); + return check_abort(flags); +} + +struct pci_ops tx4927_pci_ops = { + tx4927_pcibios_read_config_byte, + tx4927_pcibios_read_config_word, + tx4927_pcibios_read_config_dword, + tx4927_pcibios_write_config_byte, + tx4927_pcibios_write_config_word, + tx4927_pcibios_write_config_dword +}; diff -Nru a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_prom.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,96 @@ +/* + * rbtx4927 specific prom routines + * + * Author: MontaVista Software, Inc. + * source@mvista.com + * + * Copyright 2001-2002 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifndef COMMAND_LINE_SIZE +#define COMMAND_LINE_SIZE CL_SIZE +#endif + +char arcs_cmdline[COMMAND_LINE_SIZE] = "console=ttyS0,38400 ip=any root=nfs rw"; + +void __init prom_init_cmdline(int argc, char **argv) +{ + int i; /* Always ignore the "-c" at argv[0] */ + + /* ignore all built-in args if any f/w args given */ + if (argc > 1) { + *arcs_cmdline = '\0'; + } + + for (i = 1; i < argc; i++) { + if (i != 1) { + strcat(arcs_cmdline, " "); + } + strcat(arcs_cmdline, argv[i]); + } +} + +void __init prom_init(int argc, char **argv, char **envp, int *pvec) +{ + extern int tx4927_get_mem_size(void); + int msize; + const char* toshiba_name_list[] = GROUP_TOSHIBA_NAMES; + extern char* toshiba_name; + + prom_init_cmdline(argc, argv); + + mips_machgroup = MACH_GROUP_TOSHIBA; + + if ((read_c0_prid() & 0xff) == PRID_REV_TX4927) + mips_machtype = MACH_TOSHIBA_RBTX4927; + else + mips_machtype = MACH_TOSHIBA_RBTX4937; + + toshiba_name = toshiba_name_list[mips_machtype]; + + msize = tx4927_get_mem_size(); + add_memory_region(0, msize << 20, BOOT_MEM_RAM); +} + +void __init prom_free_prom_memory(void) +{ +} + + +void __init prom_fixup_mem_map(unsigned long start, unsigned long end) +{ +} + +const char *get_system_type(void) +{ + return "Toshiba RBTX4927/RBTX4937"; +} diff -Nru a/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/tx4927/toshiba_rbtx4927/toshiba_rbtx4927_setup.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,1218 @@ +/* + * Toshiba rbtx4927 specific setup + * + * Author: MontaVista Software, Inc. + * source@mvista.com + * + * Copyright 2001-2002 MontaVista Software Inc. + * + * Copyright (C) 1996, 1997, 2001 Ralf Baechle + * Copyright (C) 2000 RidgeRun, Inc. + * Author: RidgeRun, Inc. + * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com + * + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + * + * Copyright 2002 MontaVista Software Inc. + * Author: Michael Pruznick, michael_pruznick@mvista.com + * + * Copyright (C) 2000-2001 Toshiba Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_RTC_DS1742 +#include +#endif +#ifdef CONFIG_TOSHIBA_FPCIB0 +#include +#endif +#include +#ifdef CONFIG_PCI +#include +#include +#include +#include +#include +#include +#endif +#ifdef CONFIG_PC_KEYB +#include +#endif +#ifdef CONFIG_BLK_DEV_IDEPCI +#include +#include +#include +extern struct ide_ops std_ide_ops; +#endif + +#undef TOSHIBA_RBTX4927_SETUP_DEBUG + +#ifdef TOSHIBA_RBTX4927_SETUP_DEBUG +#define TOSHIBA_RBTX4927_SETUP_NONE 0x00000000 + +#define TOSHIBA_RBTX4927_SETUP_INFO ( 1 << 0 ) +#define TOSHIBA_RBTX4927_SETUP_WARN ( 1 << 1 ) +#define TOSHIBA_RBTX4927_SETUP_EROR ( 1 << 2 ) + +#define TOSHIBA_RBTX4927_SETUP_EFWFU ( 1 << 3 ) +#define TOSHIBA_RBTX4927_SETUP_SETUP ( 1 << 4 ) +#define TOSHIBA_RBTX4927_SETUP_TIME_INIT ( 1 << 5 ) +#define TOSHIBA_RBTX4927_SETUP_TIMER_SETUP ( 1 << 6 ) +#define TOSHIBA_RBTX4927_SETUP_PCIBIOS ( 1 << 7 ) +#define TOSHIBA_RBTX4927_SETUP_PCI1 ( 1 << 8 ) +#define TOSHIBA_RBTX4927_SETUP_PCI2 ( 1 << 9 ) +#define TOSHIBA_RBTX4927_SETUP_PCI66 ( 1 << 10 ) + +#define TOSHIBA_RBTX4927_SETUP_ALL 0xffffffff +#endif + +#ifdef TOSHIBA_RBTX4927_SETUP_DEBUG +static const u32 toshiba_rbtx4927_setup_debug_flag = + (TOSHIBA_RBTX4927_SETUP_NONE | TOSHIBA_RBTX4927_SETUP_INFO | + TOSHIBA_RBTX4927_SETUP_WARN | TOSHIBA_RBTX4927_SETUP_EROR | + TOSHIBA_RBTX4927_SETUP_EFWFU | TOSHIBA_RBTX4927_SETUP_SETUP | + TOSHIBA_RBTX4927_SETUP_TIME_INIT | TOSHIBA_RBTX4927_SETUP_TIMER_SETUP + | TOSHIBA_RBTX4927_SETUP_PCIBIOS | TOSHIBA_RBTX4927_SETUP_PCI1 | + TOSHIBA_RBTX4927_SETUP_PCI2 | TOSHIBA_RBTX4927_SETUP_PCI66); +#endif + +#ifdef TOSHIBA_RBTX4927_SETUP_DEBUG +#define TOSHIBA_RBTX4927_SETUP_DPRINTK(flag,str...) \ + if ( (toshiba_rbtx4927_setup_debug_flag) & (flag) ) \ + { \ + char tmp[100]; \ + sprintf( tmp, str ); \ + printk( "%s(%s:%u)::%s", __FUNCTION__, __FILE__, __LINE__, tmp ); \ + } +#else +#define TOSHIBA_RBTX4927_SETUP_DPRINTK(flag,str...) +#endif + +/* These functions are used for rebooting or halting the machine*/ +extern void toshiba_rbtx4927_restart(char *command); +extern void toshiba_rbtx4927_halt(void); +extern void toshiba_rbtx4927_power_off(void); + +int tx4927_using_backplane = 0; + +extern void gt64120_time_init(void); +extern void toshiba_rbtx4927_irq_setup(void); + +#ifdef CONFIG_PCI +#define CONFIG_TX4927BUG_WORKAROUND +#undef TX4927_SUPPORT_COMMAND_IO +#undef TX4927_SUPPORT_PCI_66 +int tx4927_cpu_clock = 100000000; /* 100MHz */ +unsigned long mips_pci_io_base; +unsigned long mips_pci_io_size; +unsigned long mips_pci_mem_base; +unsigned long mips_pci_mem_size; +/* for legacy I/O, PCI I/O PCI Bus address must be 0 */ +unsigned long mips_pci_io_pciaddr = 0; +unsigned long mips_memory_upper; +static int tx4927_ccfg_toeon = 1; +static int tx4927_pcic_trdyto = 0; /* default: disabled */ +unsigned long tx4927_ce_base[8]; +void tx4927_pci_setup(void); +void tx4927_reset_pci_pcic(void); +#ifdef TX4927_SUPPORT_PCI_66 +void tx4927_pci66_setup(void); +extern int tx4927_pci66_check(void); +#endif +int tx4927_pci66 = 0; /* 0:auto */ +#endif + +char *toshiba_name = ""; + +#ifdef CONFIG_PCI +void tx4927_dump_pcic_settings(void) +{ + printk("%s pcic settings:",toshiba_name); + { + int i; + unsigned long *preg = (unsigned long *) tx4927_pcicptr; + for (i = 0; i < sizeof(struct tx4927_pcic_reg); i += 4) { + if (i % 32 == 0) + printk("\n%04x:", i); + if (preg == &tx4927_pcicptr->g2pintack + || preg == &tx4927_pcicptr->g2pspc +#ifdef CONFIG_TX4927BUG_WORKAROUND + || preg == &tx4927_pcicptr->g2pcfgadrs + || preg == &tx4927_pcicptr->g2pcfgdata +#endif + ) { + printk(" XXXXXXXX"); + preg++; + continue; + } + printk(" %08lx", *preg++); + if (preg == &tx4927_pcicptr->g2pcfgadrs) + break; + } + printk("\n"); + } +} + +static void tx4927_pcierr_interrupt(int irq, void *dev_id, + struct pt_regs *regs) +{ + extern void tx4927_dump_pcic_settings(void); + +#ifdef CONFIG_BLK_DEV_IDEPCI + /* ignore MasterAbort for ide probing... */ + if (irq == TX4927_IRQ_IRC_PCIERR && + ((tx4927_pcicptr->pcistatus >> 16) & 0xf900) == + PCI_STATUS_REC_MASTER_ABORT) { + tx4927_pcicptr->pcistatus = + (tx4927_pcicptr-> + pcistatus & 0x0000ffff) | (PCI_STATUS_REC_MASTER_ABORT + << 16); + + return; + } +#endif + printk("PCI error interrupt (irq 0x%x).\n", irq); + printk("pcistat:%04x, g2pstatus:%08lx, pcicstatus:%08lx\n", + (unsigned short) (tx4927_pcicptr->pcistatus >> 16), + tx4927_pcicptr->g2pstatus, tx4927_pcicptr->pcicstatus); + printk("ccfg:%08lx, tear:%02lx_%08lx\n", + (unsigned long) tx4927_ccfgptr->ccfg, + (unsigned long) (tx4927_ccfgptr->tear >> 32), + (unsigned long) tx4927_ccfgptr->tear); + show_regs(regs); + //tx4927_dump_pcic_settings(); + panic("PCI error at PC:%08lx.", regs->cp0_epc); +} + +static struct irqaction pcic_action = { + tx4927_pcierr_interrupt, 0, 0, "PCI-C", NULL, NULL +}; + +static struct irqaction pcierr_action = { + tx4927_pcierr_interrupt, 0, 0, "PCI-ERR", NULL, NULL +}; + + +void __init toshiba_rbtx4927_pci_irq_init(void) +{ + setup_irq(TX4927_IRQ_IRC_PCIC, &pcic_action); + setup_irq(TX4927_IRQ_IRC_PCIERR, &pcierr_action); + return; +} + +void tx4927_reset_pci_pcic(void) +{ + /* Reset PCI Bus */ + *tx4927_pcireset_ptr = 1; + /* Reset PCIC */ + tx4927_ccfgptr->clkctr |= TX4927_CLKCTR_PCIRST; + udelay(10000); + /* clear PCIC reset */ + tx4927_ccfgptr->clkctr &= ~TX4927_CLKCTR_PCIRST; + *tx4927_pcireset_ptr = 0; +} +#endif /* CONFIG_PCI */ + +#ifdef CONFIG_PCI +#ifdef TX4927_SUPPORT_PCI_66 +void tx4927_pci66_setup(void) +{ + int pciclk, pciclkin = 1; + + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI66, + "-\n"); + + if (tx4927_ccfgptr->ccfg & TX4927_CCFG_PCI66) + return; + + tx4927_reset_pci_pcic(); + + /* Assert M66EN */ + tx4927_ccfgptr->ccfg |= TX4927_CCFG_PCI66; + /* set PCICLK 66MHz */ + if (tx4927_ccfgptr->pcfg & TX4927_PCFG_PCICLKEN_ALL) { + unsigned int pcidivmode = 0; + pcidivmode = + (unsigned long) tx4927_ccfgptr-> + ccfg & TX4927_CCFG_PCIDIVMODE_MASK; + if (tx4927_cpu_clock >= 170000000) { + /* CPU 200MHz */ + pcidivmode = TX4927_CCFG_PCIDIVMODE_3; + pciclk = tx4927_cpu_clock / 3; + } else { + /* CPU 166MHz */ + pcidivmode = TX4927_CCFG_PCIDIVMODE_2_5; + pciclk = tx4927_cpu_clock * 2 / 5; + } + tx4927_ccfgptr->ccfg = + (tx4927_ccfgptr->ccfg & ~TX4927_CCFG_PCIDIVMODE_MASK) + | pcidivmode; + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_PCI66, + ":PCICLK: ccfg:0x%08lx\n", + (unsigned long) tx4927_ccfgptr->ccfg); + } else { + int pciclk_setting = *tx4927_pci_clk_ptr; + pciclkin = 0; + pciclk = 66666666; + pciclk_setting &= ~TX4927_PCI_CLK_MASK; + pciclk_setting |= TX4927_PCI_CLK_66; + *tx4927_pci_clk_ptr = pciclk_setting; + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_PCI66, + "PCICLK: pci_clk:%02x\n", *tx4927_pci_clk_ptr); + } + + udelay(10000); + + /* clear PCIC reset */ + tx4927_ccfgptr->clkctr &= ~TX4927_CLKCTR_PCIRST; + /* clear PCI reset */ + *tx4927_pcireset_ptr = 0; + + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI66, + "+\n"); + return; +} +#endif /* TX4927_SUPPORT_PCI_66 */ + +void print_pci_status(void) +{ + printk("PCI STATUS %lx\n", tx4927_pcicptr->pcistatus); + printk("PCIC STATUS %lx\n", tx4927_pcicptr->pcicstatus); +} + +static struct pci_dev *fake_pci_dev(struct pci_channel *hose, + int top_bus, int busnr, int devfn) +{ + static struct pci_dev dev; + static struct pci_bus bus; + + dev.bus = &bus; + dev.sysdata = hose; + dev.devfn = devfn; + bus.number = busnr; + bus.ops = hose->pci_ops; + + if (busnr != top_bus) + /* Fake a parent bus structure. */ + bus.parent = &bus; + else + bus.parent = NULL; + + return &dev; +} + +#define EARLY_PCI_OP(rw, size, type) \ +static int early_##rw##_config_##size(struct pci_channel *hose, \ + int top_bus, int bus, int devfn, int offset, type value) \ +{ \ + return pci_##rw##_config_##size( \ + fake_pci_dev(hose, top_bus, bus, devfn), \ + offset, value); \ +} + +EARLY_PCI_OP(read, byte, u8 *) +EARLY_PCI_OP(read, word, u16 *) +EARLY_PCI_OP(read, dword, u32 *) +EARLY_PCI_OP(write, byte, u8) +EARLY_PCI_OP(write, word, u16) +EARLY_PCI_OP(write, dword, u32) + +static int __init tx4927_pcibios_init(int busno, struct pci_channel *hose) +{ + u32 pci_devfn; + int devfn_start = 0; + int devfn_stop = 0xff; + unsigned int id; + + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCIBIOS, + "-\n"); + + if (hose->first_devfn) + devfn_start = hose->first_devfn; + if (hose->last_devfn) + devfn_stop = hose->last_devfn; + + for (pci_devfn = devfn_start; pci_devfn < devfn_stop; pci_devfn++) { + early_read_config_dword(hose, busno, busno, pci_devfn, + PCI_VENDOR_ID, &id); + + if (id == 0xffffffff) { + continue; + } + + if (id == 0x94601055) { + u8 v08_64; + u32 v32_b0; + u8 v08_e1; + char *s = " sb/isa --"; + + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_PCIBIOS, ":%s beg\n", + s); + + early_read_config_byte(hose, busno, busno, + pci_devfn, 0x64, &v08_64); + early_read_config_dword(hose, busno, busno, + pci_devfn, 0xb0, &v32_b0); + early_read_config_byte(hose, busno, busno, + pci_devfn, 0xe1, &v08_e1); + + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_PCIBIOS, + ":%s beg 0x64 = 0x%02x\n", s, v08_64); + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_PCIBIOS, + ":%s beg 0xb0 = 0x%02x\n", s, v32_b0); + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_PCIBIOS, + ":%s beg 0xe1 = 0x%02x\n", s, v08_e1); + + /* serial irq control */ + v08_64 = 0xd0; + + /* serial irq pin */ + v32_b0 |= 0x00010000; + + /* ide irq on isa14 */ + v08_e1 &= 0xf0; + v08_e1 |= 0x0d; + + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_PCIBIOS, + ":%s mid 0x64 = 0x%02x\n", s, v08_64); + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_PCIBIOS, + ":%s mid 0xb0 = 0x%02x\n", s, v32_b0); + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_PCIBIOS, + ":%s mid 0xe1 = 0x%02x\n", s, v08_e1); + + early_write_config_byte(hose, busno, busno, + pci_devfn, 0x64, v08_64); + early_write_config_dword(hose, busno, busno, + pci_devfn, 0xb0, v32_b0); + early_write_config_byte(hose, busno, busno, + pci_devfn, 0xe1, v08_e1); + +#ifdef TOSHIBA_RBTX4927_SETUP_DEBUG + { + early_read_config_byte(hose, busno, busno, + pci_devfn, 0x64, + &v08_64); + early_read_config_dword(hose, busno, busno, + pci_devfn, 0xb0, + &v32_b0); + early_read_config_byte(hose, busno, busno, + pci_devfn, 0xe1, + &v08_e1); + + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_PCIBIOS, + ":%s end 0x64 = 0x%02x\n", s, v08_64); + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_PCIBIOS, + ":%s end 0xb0 = 0x%02x\n", s, v32_b0); + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_PCIBIOS, + ":%s end 0xe1 = 0x%02x\n", s, v08_e1); + } +#endif + + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_PCIBIOS, ":%s end\n", + s); + } + + if (id == 0x91301055) { + u8 v08_04; + u8 v08_09; + u8 v08_41; + u8 v08_43; + u8 v08_5c; + char *s = " sb/ide --"; + + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_PCIBIOS, ":%s beg\n", + s); + + early_read_config_byte(hose, busno, busno, + pci_devfn, 0x04, &v08_04); + early_read_config_byte(hose, busno, busno, + pci_devfn, 0x09, &v08_09); + early_read_config_byte(hose, busno, busno, + pci_devfn, 0x41, &v08_41); + early_read_config_byte(hose, busno, busno, + pci_devfn, 0x43, &v08_43); + early_read_config_byte(hose, busno, busno, + pci_devfn, 0x5c, &v08_5c); + + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_PCIBIOS, + ":%s beg 0x04 = 0x%02x\n", s, v08_04); + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_PCIBIOS, + ":%s beg 0x09 = 0x%02x\n", s, v08_09); + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_PCIBIOS, + ":%s beg 0x41 = 0x%02x\n", s, v08_41); + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_PCIBIOS, + ":%s beg 0x43 = 0x%02x\n", s, v08_43); + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_PCIBIOS, + ":%s beg 0x5c = 0x%02x\n", s, v08_5c); + + /* enable ide master/io */ + v08_04 |= (PCI_COMMAND_MASTER | PCI_COMMAND_IO); + + /* enable ide native mode */ + v08_09 |= 0x05; + + /* enable primary ide */ + v08_41 |= 0x80; + + /* enable secondary ide */ + v08_43 |= 0x80; + + /* + * !!! DO NOT REMOVE THIS COMMENT IT IS REQUIRED BY SMSC !!! + * + * This line of code is intended to provide the user with a work + * around solution to the anomalies cited in SMSC's anomaly sheet + * entitled, "SLC90E66 Functional Rev.J_0.1 Anomalies"". + * + * !!! DO NOT REMOVE THIS COMMENT IT IS REQUIRED BY SMSC !!! + */ + v08_5c |= 0x01; + + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_PCIBIOS, + ":%s mid 0x04 = 0x%02x\n", s, v08_04); + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_PCIBIOS, + ":%s mid 0x09 = 0x%02x\n", s, v08_09); + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_PCIBIOS, + ":%s mid 0x41 = 0x%02x\n", s, v08_41); + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_PCIBIOS, + ":%s mid 0x43 = 0x%02x\n", s, v08_43); + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_PCIBIOS, + ":%s mid 0x5c = 0x%02x\n", s, v08_5c); + + early_write_config_byte(hose, busno, busno, + pci_devfn, 0x5c, v08_5c); + early_write_config_byte(hose, busno, busno, + pci_devfn, 0x04, v08_04); + early_write_config_byte(hose, busno, busno, + pci_devfn, 0x09, v08_09); + early_write_config_byte(hose, busno, busno, + pci_devfn, 0x41, v08_41); + early_write_config_byte(hose, busno, busno, + pci_devfn, 0x43, v08_43); + +#ifdef TOSHIBA_RBTX4927_SETUP_DEBUG + { + early_read_config_byte(hose, busno, busno, + pci_devfn, 0x04, + &v08_04); + early_read_config_byte(hose, busno, busno, + pci_devfn, 0x09, + &v08_09); + early_read_config_byte(hose, busno, busno, + pci_devfn, 0x41, + &v08_41); + early_read_config_byte(hose, busno, busno, + pci_devfn, 0x43, + &v08_43); + early_read_config_byte(hose, busno, busno, + pci_devfn, 0x5c, + &v08_5c); + + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_PCIBIOS, + ":%s end 0x04 = 0x%02x\n", s, v08_04); + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_PCIBIOS, + ":%s end 0x09 = 0x%02x\n", s, v08_09); + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_PCIBIOS, + ":%s end 0x41 = 0x%02x\n", s, v08_41); + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_PCIBIOS, + ":%s end 0x43 = 0x%02x\n", s, v08_43); + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_PCIBIOS, + ":%s end 0x5c = 0x%02x\n", s, v08_5c); + } +#endif + + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_PCIBIOS, ":%s end\n", + s); + } + + } + + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCIBIOS, + "+\n"); + + return (busno); +} + +extern struct resource pci_io_resource; +extern struct resource pci_mem_resource; + +void tx4927_pci_setup(void) +{ + static int called = 0; + extern unsigned int tx4927_get_mem_size(void); + + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2, "-\n"); + +#ifndef TX4927_SUPPORT_PCI_66 + if (tx4927_ccfgptr->ccfg & TX4927_CCFG_PCI66) + printk("PCI 66 current unsupported\n"); +#endif + + mips_memory_upper = tx4927_get_mem_size() << 20; + mips_memory_upper += KSEG0; + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2, + "0x%08lx=mips_memory_upper\n", + mips_memory_upper); + mips_pci_io_base = TX4927_PCIIO; + mips_pci_io_size = TX4927_PCIIO_SIZE; + mips_pci_mem_base = TX4927_PCIMEM; + mips_pci_mem_size = TX4927_PCIMEM_SIZE; + + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2, + "0x%08lx=mips_pci_io_base\n", + mips_pci_io_base); + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2, + "0x%08lx=mips_pci_io_size\n", + mips_pci_io_size); + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2, + "0x%08lx=mips_pci_mem_base\n", + mips_pci_mem_base); + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2, + "0x%08lx=mips_pci_mem_size\n", + mips_pci_mem_size); + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2, + "0x%08lx=pci_io_resource.start\n", + pci_io_resource.start); + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2, + "0x%08lx=pci_io_resource.end\n", + pci_io_resource.end); + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2, + "0x%08lx=pci_mem_resource.start\n", + pci_mem_resource.start); + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2, + "0x%08lx=pci_mem_resource.end\n", + pci_mem_resource.end); + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2, + "0x%08lx=mips_io_port_base", + mips_io_port_base); + + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2, + "setup pci_io_resource to 0x%08lx 0x%08lx\n", + pci_io_resource.start, + pci_io_resource.end); + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2, + "setup pci_mem_resource to 0x%08lx 0x%08lx\n", + pci_mem_resource.start, + pci_mem_resource.end); + + if (!called) { + printk + ("TX4927 PCIC -- DID:%04x VID:%04x RID:%02x Arbiter:%s\n", + (unsigned short) (tx4927_pcicptr->pciid >> 16), + (unsigned short) (tx4927_pcicptr->pciid & 0xffff), + (unsigned short) (tx4927_pcicptr->pciccrev & 0xff), + (!(tx4927_ccfgptr-> + ccfg & TX4927_CCFG_PCIXARB)) ? "External" : + "Internal"); + called = 1; + } + printk("%s PCIC --%s PCICLK:",toshiba_name, + (tx4927_ccfgptr->ccfg & TX4927_CCFG_PCI66) ? " PCI66" : ""); + if (tx4927_ccfgptr->pcfg & TX4927_PCFG_PCICLKEN_ALL) { + int pciclk = 0; + switch ((unsigned long) tx4927_ccfgptr-> + ccfg & TX4927_CCFG_PCIDIVMODE_MASK) { + case TX4927_CCFG_PCIDIVMODE_2_5: + pciclk = tx4927_cpu_clock * 2 / 5; + break; + case TX4927_CCFG_PCIDIVMODE_3: + pciclk = tx4927_cpu_clock / 3; + break; + case TX4927_CCFG_PCIDIVMODE_5: + pciclk = tx4927_cpu_clock / 5; + break; + case TX4927_CCFG_PCIDIVMODE_6: + pciclk = tx4927_cpu_clock / 6; + break; + } + printk("Internal(%dMHz)", pciclk / 1000000); + } else { + int pciclk = 0; + int pciclk_setting = *tx4927_pci_clk_ptr; + switch (pciclk_setting & TX4927_PCI_CLK_MASK) { + case TX4927_PCI_CLK_33: + pciclk = 33333333; + break; + case TX4927_PCI_CLK_25: + pciclk = 25000000; + break; + case TX4927_PCI_CLK_66: + pciclk = 66666666; + break; + case TX4927_PCI_CLK_50: + pciclk = 50000000; + break; + } + printk("External(%dMHz)", pciclk / 1000000); + } + printk("\n"); + + + + /* GB->PCI mappings */ + tx4927_pcicptr->g2piomask = (mips_pci_io_size - 1) >> 4; + tx4927_pcicptr->g2piogbase = mips_pci_io_base | +#ifdef __BIG_ENDIAN + TX4927_PCIC_G2PIOGBASE_ECHG +#else + TX4927_PCIC_G2PIOGBASE_BSDIS +#endif + ; + + tx4927_pcicptr->g2piopbase = 0; + + tx4927_pcicptr->g2pmmask[0] = (mips_pci_mem_size - 1) >> 4; + tx4927_pcicptr->g2pmgbase[0] = mips_pci_mem_base | +#ifdef __BIG_ENDIAN + TX4927_PCIC_G2PMnGBASE_ECHG +#else + TX4927_PCIC_G2PMnGBASE_BSDIS +#endif + ; + tx4927_pcicptr->g2pmpbase[0] = mips_pci_mem_base; + + tx4927_pcicptr->g2pmmask[1] = 0; + tx4927_pcicptr->g2pmgbase[1] = 0; + tx4927_pcicptr->g2pmpbase[1] = 0; + tx4927_pcicptr->g2pmmask[2] = 0; + tx4927_pcicptr->g2pmgbase[2] = 0; + tx4927_pcicptr->g2pmpbase[2] = 0; + + + /* PCI->GB mappings (I/O 256B) */ + tx4927_pcicptr->p2giopbase = 0; /* 256B */ + + +#ifdef TX4927_SUPPORT_COMMAND_IO + tx4927_pcicptr->p2giogbase = 0 | TX4927_PCIC_P2GIOGBASE_TIOEN | +#ifdef __BIG_ENDIAN + TX4927_PCIC_P2GIOGBASE_TECHG +#else + TX4927_PCIC_P2GIOGBASE_TBSDIS +#endif + ; +#else + tx4927_pcicptr->p2giogbase = 0; +#endif + + /* PCI->GB mappings (MEM 512MB) M0 gets all of memory */ + tx4927_pcicptr->p2gm0plbase = 0; + tx4927_pcicptr->p2gm0pubase = 0; + tx4927_pcicptr->p2gmgbase[0] = 0 | TX4927_PCIC_P2GMnGBASE_TMEMEN | +#ifdef __BIG_ENDIAN + TX4927_PCIC_P2GMnGBASE_TECHG +#else + TX4927_PCIC_P2GMnGBASE_TBSDIS +#endif + ; + + /* PCI->GB mappings (MEM 16MB) -not used */ + tx4927_pcicptr->p2gm1plbase = 0xffffffff; +#ifdef CONFIG_TX4927BUG_WORKAROUND + /* + * TX4927-PCIC-BUG: P2GM1PUBASE must be 0 + * if P2GM0PUBASE was 0. + */ + tx4927_pcicptr->p2gm1pubase = 0; +#else + tx4927_pcicptr->p2gm1pubase = 0xffffffff; +#endif + tx4927_pcicptr->p2gmgbase[1] = 0; + + /* PCI->GB mappings (MEM 1MB) -not used */ + tx4927_pcicptr->p2gm2pbase = 0xffffffff; + tx4927_pcicptr->p2gmgbase[2] = 0; + + + /* Enable Initiator Memory 0 Space, I/O Space, Config */ + tx4927_pcicptr->pciccfg &= TX4927_PCIC_PCICCFG_LBWC_MASK; + tx4927_pcicptr->pciccfg |= + TX4927_PCIC_PCICCFG_IMSE0 | TX4927_PCIC_PCICCFG_IISE | + TX4927_PCIC_PCICCFG_ICAE | TX4927_PCIC_PCICCFG_ATR; + + + /* Do not use MEMMUL, MEMINF: YMFPCI card causes M_ABORT. */ + tx4927_pcicptr->pcicfg1 = 0; + + if (tx4927_pcic_trdyto >= 0) { + tx4927_pcicptr->g2ptocnt &= ~0xff; + tx4927_pcicptr->g2ptocnt |= (tx4927_pcic_trdyto & 0xff); + //printk("%s PCIC -- TRDYTO:%02lx\n",toshiba_name, + // tx4927_pcicptr->g2ptocnt & 0xff); + } + + /* Clear All Local Bus Status */ + tx4927_pcicptr->pcicstatus = TX4927_PCIC_PCICSTATUS_ALL; + /* Enable All Local Bus Interrupts */ + tx4927_pcicptr->pcicmask = TX4927_PCIC_PCICSTATUS_ALL; + /* Clear All Initiator Status */ + tx4927_pcicptr->g2pstatus = TX4927_PCIC_G2PSTATUS_ALL; + /* Enable All Initiator Interrupts */ + tx4927_pcicptr->g2pmask = TX4927_PCIC_G2PSTATUS_ALL; + /* Clear All PCI Status Error */ + tx4927_pcicptr->pcistatus = + (tx4927_pcicptr->pcistatus & 0x0000ffff) | + (TX4927_PCIC_PCISTATUS_ALL << 16); + /* Enable All PCI Status Error Interrupts */ + tx4927_pcicptr->pcimask = TX4927_PCIC_PCISTATUS_ALL; + + /* PCIC Int => IRC IRQ16 */ + tx4927_pcicptr->pcicfg2 = + (tx4927_pcicptr->pcicfg2 & 0xffffff00) | TX4927_IR_PCIC; + + if (!(tx4927_ccfgptr->ccfg & TX4927_CCFG_PCIXARB)) { + /* XXX */ + } else { + /* Reset Bus Arbiter */ + tx4927_pcicptr->pbacfg = TX4927_PCIC_PBACFG_RPBA; + /* Enable Bus Arbiter */ + tx4927_pcicptr->pbacfg = TX4927_PCIC_PBACFG_PBAEN; + } + + tx4927_pcicptr->pcistatus = PCI_COMMAND_MASTER | + PCI_COMMAND_MEMORY | +#ifdef TX4927_SUPPORT_COMMAND_IO + PCI_COMMAND_IO | +#endif + PCI_COMMAND_PARITY | PCI_COMMAND_SERR; + + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2, + ":pci setup complete:\n"); + //tx4927_dump_pcic_settings(); + + { + struct pci_channel *p; + int busno; + + busno = 0; + for (p = mips_pci_channels; p->pci_ops != NULL; p++) { + busno = tx4927_pcibios_init(busno, p) + 1; + } + } + + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI2, "+\n"); +} + +#endif /* CONFIG_PCI */ + +void toshiba_rbtx4927_restart(char *command) +{ + printk(KERN_NOTICE "System Rebooting...\n"); + + /* enable the s/w reset register */ + reg_wr08(RBTX4927_SW_RESET_ENABLE, RBTX4927_SW_RESET_ENABLE_SET); + + /* wait for enable to be seen */ + while ((reg_rd08(RBTX4927_SW_RESET_ENABLE) & + RBTX4927_SW_RESET_ENABLE_SET) == 0x00); + + /* do a s/w reset */ + reg_wr08(RBTX4927_SW_RESET_DO, RBTX4927_SW_RESET_DO_SET); + + /* do something passive while waiting for reset */ + cli(); + while (1) + asm_wait(); + + /* no return */ +} + + +void toshiba_rbtx4927_halt(void) +{ + printk(KERN_NOTICE "System Halted\n"); + cli(); + while (1) { + asm_wait(); + } + /* no return */ +} + +void toshiba_rbtx4927_power_off(void) +{ + toshiba_rbtx4927_halt(); + /* no return */ +} + +void __init toshiba_rbtx4927_setup(void) +{ + vu32 cp0_config; + + printk("CPU is %s\n", toshiba_name); + + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_SETUP, + "-\n"); + + /* f/w leaves this on at startup */ + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_SETUP, + ":Clearing STO_ERL.\n"); + clear_c0_status(ST0_ERL); + + /* enable caches -- HCP5 does this, pmon does not */ + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_SETUP, + ":Enabling TX49_CONF_IC,TX49_CONF_DC.\n"); + cp0_config = read_c0_config(); + cp0_config = cp0_config & ~(TX49_CONF_IC | TX49_CONF_DC); + write_c0_config(cp0_config); + +#ifdef TOSHIBA_RBTX4927_SETUP_DEBUG + { + extern void dump_cp0(char *); + dump_cp0("toshiba_rbtx4927_early_fw_fixup"); + } +#endif + + /* setup irq stuff */ + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_SETUP, + ":Setting up tx4927 pic.\n"); + TX4927_WR(0xff1ff604, 0x00000400); /* irq trigger */ + TX4927_WR(0xff1ff608, 0x00000000); /* irq trigger */ + + /* setup serial stuff */ + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_SETUP, + ":Setting up tx4927 sio.\n"); + TX4927_WR(0xff1ff314, 0x00000000); /* h/w flow control off */ + TX4927_WR(0xff1ff414, 0x00000000); /* h/w flow control off */ + + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_SETUP, + "+\n"); + + + + mips_io_port_base = KSEG1 + TBTX4927_ISA_IO_OFFSET; + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_SETUP, + ":mips_io_port_base=0x%08lx\n", + mips_io_port_base); + + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_SETUP, + ":Resource\n"); + ioport_resource.start = 0; + ioport_resource.end = 0xffffffff; + iomem_resource.start = 0; + iomem_resource.end = 0xffffffff; + + + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_SETUP, + ":ResetRoutines\n"); + _machine_restart = toshiba_rbtx4927_restart; + _machine_halt = toshiba_rbtx4927_halt; + _machine_power_off = toshiba_rbtx4927_power_off; + + +#ifdef CONFIG_BLK_DEV_IDEPCI + { + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_SETUP, + ":ide_ops=&std_ide_ops(modified)\n"); + ide_ops = &std_ide_ops; + } +#else + { + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_SETUP, + ":ide_ops=\n"); + } +#endif + +#ifdef CONFIG_FB + { + conswitchp = &dummy_con; + } +#endif + + + + +#ifdef CONFIG_PCI + + /* PCIC */ + /* + * ASSUMPTION: PCIDIVMODE is configured for PCI 33MHz or 66MHz. + * PCIDIVMODE[12:11]'s initial value are given by S9[4:3] (ON:0, OFF:1). + * CPU 166MHz: PCI 66MHz : PCIDIVMODE: 00 (1/2.5) + * CPU 200MHz: PCI 66MHz : PCIDIVMODE: 01 (1/3) + * CPU 166MHz: PCI 33MHz : PCIDIVMODE: 10 (1/5) + * CPU 200MHz: PCI 33MHz : PCIDIVMODE: 11 (1/6) + * i.e. S9[3]: ON (83MHz), OFF (100MHz) + */ + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI1, + "ccfg is %lx, DIV is %x\n", + (unsigned long) tx4927_ccfgptr-> + ccfg, TX4927_CCFG_PCIDIVMODE_MASK); + + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI1, + "PCI66 mode is %lx, PCI mode is %lx, pci arb is %lx\n", + (unsigned long) tx4927_ccfgptr-> + ccfg & TX4927_CCFG_PCI66, + (unsigned long) tx4927_ccfgptr-> + ccfg & TX4927_CCFG_PCIMIDE, + (unsigned long) tx4927_ccfgptr-> + ccfg & TX4927_CCFG_PCIXARB); + + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_PCI1, + "PCIDIVMODE is %lx\n", + (unsigned long) tx4927_ccfgptr-> + ccfg & TX4927_CCFG_PCIDIVMODE_MASK); + + switch ((unsigned long) tx4927_ccfgptr-> + ccfg & TX4927_CCFG_PCIDIVMODE_MASK) { + case TX4927_CCFG_PCIDIVMODE_2_5: + case TX4927_CCFG_PCIDIVMODE_5: + tx4927_cpu_clock = 166000000; /* 166MHz */ + break; + default: + tx4927_cpu_clock = 200000000; /* 200MHz */ + } + + /* CCFG */ + /* enable Timeout BusError */ + if (tx4927_ccfg_toeon) + tx4927_ccfgptr->ccfg |= TX4927_CCFG_TOE; + + /* SDRAMC fixup */ +#ifdef CONFIG_TX4927BUG_WORKAROUND + /* + * TX4927-BUG: INF 01-01-18/ BUG 01-01-22 + * G-bus timeout error detection is incorrect + */ + if (tx4927_ccfg_toeon) + tx4927_sdramcptr->tr |= 0x02000000; /* RCD:3tck */ +#endif + +#ifdef TX4927_SUPPORT_PCI_66 + tx4927_pci66_setup(); +#endif + + tx4927_pci_setup(); +#endif + + + { + u32 id = 0; + early_read_config_dword(&mips_pci_channels[0], 0, 0, 0x90, + PCI_VENDOR_ID, &id); + if (id == 0x94601055) { + tx4927_using_backplane = 1; + printk("backplane board IS installed\n"); + } else { + printk("backplane board NOT installed\n"); + } + } + + + /* this is only done if backplane board installed, so must wait for pci */ +#ifdef CONFIG_PC_KEYB + { + if (tx4927_using_backplane) { + extern struct kbd_ops std_kbd_ops; + kbd_ops = &std_kbd_ops; + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_SETUP, + ":kbd_ops=&std_kbd_ops\n"); + } else { + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_SETUP, + ":kbd_ops=\n"); + } + } +#else + { + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_SETUP, + ":kbd_ops=\n"); + } +#endif + + /* this is on ISA bus behind PCI bus, so need PCI up first */ +#ifdef CONFIG_TOSHIBA_FPCIB0 + { + if (tx4927_using_backplane) { + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_SETUP, + ":fpcibo=yes\n"); + + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_SETUP, + ":smsc_fdc37m81x_init()\n"); + smsc_fdc37m81x_init(0x3f0); + + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_SETUP, + ":smsc_fdc37m81x_config_beg()\n"); + smsc_fdc37m81x_config_beg(); + + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_SETUP, + ":smsc_fdc37m81x_config_set(KBD)\n"); + smsc_fdc37m81x_config_set(SMSC_FDC37M81X_DNUM, + SMSC_FDC37M81X_KBD); + smsc_fdc37m81x_config_set(SMSC_FDC37M81X_INT, 1); + smsc_fdc37m81x_config_set(SMSC_FDC37M81X_INT2, 12); + smsc_fdc37m81x_config_set(SMSC_FDC37M81X_ACTIVE, + 1); + + smsc_fdc37m81x_config_end(); + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_SETUP, + ":smsc_fdc37m81x_config_end()\n"); + } else { + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_SETUP, + ":fpcibo=not_found\n"); + } + } +#else + { + TOSHIBA_RBTX4927_SETUP_DPRINTK + (TOSHIBA_RBTX4927_SETUP_SETUP, ":fpcibo=no\n"); + } +#endif + + + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_SETUP, + "+\n"); +} + +void __init +toshiba_rbtx4927_time_init(void) +{ + u32 c1; + u32 c2; + + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT, "-\n"); + +#ifdef CONFIG_RTC_DS1742 + + rtc_get_time = rtc_ds1742_get_time; + rtc_set_time = rtc_ds1742_set_time; + + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT, + ":rtc_ds1742_init()-\n"); + rtc_ds1742_init(0xbc010000); + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT, + ":rtc_ds1742_init()+\n"); + + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT, + ":Calibrate mips_counter_frequency-\n"); + rtc_ds1742_wait(); + + /* get the count */ + c1 = read_c0_count(); + + /* wait for the seconds to change again */ + rtc_ds1742_wait(); + + /* get the count again */ + c2 = read_c0_count(); + + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT, + ":Calibrate mips_counter_frequency+\n"); + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT, + ":c1=%12u\n", c1); + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT, + ":c2=%12u\n", c2); + + /* this diff is as close as we are going to get to counter ticks per sec */ + mips_counter_frequency = abs(c2 - c1); + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT, + ":f1=%12u\n", mips_counter_frequency); + + /* round to 1/10th of a MHz */ + mips_counter_frequency /= (100 * 1000); + mips_counter_frequency *= (100 * 1000); + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT, + ":f2=%12u\n", mips_counter_frequency); + + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_INFO, + ":mips_counter_frequency=%uHz (%uMHz)\n", + mips_counter_frequency, + mips_counter_frequency / 1000000); +#else + mips_counter_frequency = 100000000; +#endif + + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIME_INIT, "+\n"); + +} + +void __init toshiba_rbtx4927_timer_setup(struct irqaction *irq) +{ + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIMER_SETUP, + "-\n"); + TOSHIBA_RBTX4927_SETUP_DPRINTK(TOSHIBA_RBTX4927_SETUP_TIMER_SETUP, + "+\n"); +} diff -Nru a/arch/mips/vmlinux.lds.S b/arch/mips/vmlinux.lds.S --- a/arch/mips/vmlinux.lds.S Tue Jul 1 18:44:34 2003 +++ b/arch/mips/vmlinux.lds.S Tue Jul 1 18:44:34 2003 @@ -2,19 +2,20 @@ OUTPUT_ARCH(mips) ENTRY(kernel_entry) +jiffies = JIFFIES32; SECTIONS { - /* Read-only sections, merged into text segment: */ . = LOADADDR; - .init : { *(.init) } =0 - .text : - { - _ftext = . ; + /* read-only */ + _text = .; /* Text and read-only data */ + .text : { *(.text) - /* .gnu.warning sections are handled specially by elf32.em. */ + *(.fixup) *(.gnu.warning) } =0 + _etext = .; /* End of text section */ + . = ALIGN(16); /* Exception table */ __start___ex_table = .; __ex_table : { *(__ex_table) } @@ -25,29 +26,73 @@ __stop___dbe_table = .; RODATA - - _etext = .; - . = ALIGN(8192); - .data.init_task : { *(.data.init_task) } + . = ALIGN(64); + + /* writeable */ + .data : { /* Data */ + *(.data) + + /* Align the initial ramdisk image (INITRD) on page boundaries. */ + . = ALIGN(4096); + __rd_start = .; + *(.initrd) + . = ALIGN(4096); + __rd_end = .; + + CONSTRUCTORS + } + _gp = . + 0x8000; + .lit8 : { *(.lit8) } + .lit4 : { *(.lit4) } + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata : { *(.sdata) } + + . = ALIGN(4096); + __nosave_begin = .; + .data_nosave : { *(.data.nosave) } + . = ALIGN(4096); + __nosave_end = .; - /* Startup code */ . = ALIGN(4096); + .data.page_aligned : { *(.data.idt) } + + . = ALIGN(32); + .data.cacheline_aligned : { *(.data.cacheline_aligned) } + + _edata = .; /* End of data section */ + + . = ALIGN(8192); /* init_task */ + .data.init_task : { *(.data.init_task) } + + /* will be freed after init */ + . = ALIGN(4096); /* Init code and data */ __init_begin = .; - .text.init : { *(.text.init) } - .data.init : { *(.data.init) } + /* /DISCARD/ doesn't work for .reginfo */ + .reginfo : { *(.reginfo) } + .init.text : { + _sinittext = .; + *(.init.text) + _einittext = .; + } + .init.data : { *(.init.data) } . = ALIGN(16); __setup_start = .; - .setup.init : { *(.setup.init) } + .init.setup : { *(.init.setup) } __setup_end = .; + __start___param = .; + __param : { *(__param) } + __stop___param = .; __initcall_start = .; .initcall.init : { - *(.initcall1.init) - *(.initcall2.init) - *(.initcall3.init) - *(.initcall4.init) - *(.initcall5.init) - *(.initcall6.init) + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) *(.initcall7.init) } __initcall_end = .; @@ -55,80 +100,35 @@ .con_initcall.init : { *(.con_initcall.init) } __con_initcall_end = .; SECURITY_INIT - . = ALIGN(4096); /* Align double page for init_task_union */ - __init_end = .; - . = ALIGN(4096); - .data.page_aligned : { *(.data.idt) } - + __initramfs_start = .; + .init.ramfs : { *(.init.ramfs) } + __initramfs_end = .; . = ALIGN(32); - .data.cacheline_aligned : { *(.data.cacheline_aligned) } - - .fini : { *(.fini) } =0 - .reginfo : { *(.reginfo) } - /* Adjust the address for the data segment. We want to adjust up to - the same address within the page on the next page up. It would - be more correct to do this: - . = .; - The current expression does not correctly handle the case of a - text segment ending precisely at the end of a page; it causes the - data segment to skip a page. The above expression does not have - this problem, but it will currently (2/95) cause BFD to allocate - a single segment, combining both text and data, for this case. - This will prevent the text segment from being shared among - multiple executions of the program; I think that is more - important than losing a page of the virtual address space (note - that no actual memory is lost; the page which is skipped can not - be referenced). */ - . = .; - .data : - { - _fdata = . ; - *(.data) - - /* Align the initial ramdisk image (INITRD) on page boundaries. */ - . = ALIGN(4096); - __rd_start = .; - *(.initrd) - __rd_end = .; - . = ALIGN(4096); + __per_cpu_start = .; + .data.percpu : { *(.data.percpu) } + __per_cpu_end = .; + . = ALIGN(4096); + __init_end = .; + /* freed after init ends here */ - CONSTRUCTORS + __bss_start = .; /* BSS */ + .sbss : { + *(.sbss) + *(.scommon) } - .data1 : { *(.data1) } - _gp = . + 0x8000; - .lit8 : { *(.lit8) } - .lit4 : { *(.lit4) } - .ctors : { *(.ctors) } - .dtors : { *(.dtors) } - .got : { *(.got.plt) *(.got) } - .dynamic : { *(.dynamic) } - /* We want the small data sections together, so single-instruction offsets - can access them all, and initialized data all before uninitialized, so - we can shorten the on-disk segment size. */ - .sdata : { *(.sdata) } - . = ALIGN(4); - _edata = .; - PROVIDE (edata = .); - - __bss_start = .; - _fbss = .; - .sbss : { *(.sbss) *(.scommon) } - .bss : - { - *(.dynbss) - *(.bss) - *(COMMON) - . = ALIGN(4); - _end = . ; - PROVIDE (end = .); + .bss : { + *(.bss) + *(COMMON) } + __bss_stop = .; + + _end = . ; /* Sections to be discarded */ - /DISCARD/ : - { - *(.text.exit) - *(.data.exit) + /DISCARD/ : { + *(.exit.text) + *(.exit.data) *(.exitcall.exit) } diff -Nru a/arch/mips/vr41xx/casio-e55/Makefile b/arch/mips/vr41xx/casio-e55/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/casio-e55/Makefile Tue Jul 1 18:44:40 2003 @@ -0,0 +1,7 @@ +# +# Makefile for the CASIO CASSIOPEIA E-55/65 specific parts of the kernel +# + +obj-y += init.o setup.o + +obj-$(CONFIG_IDE) += ide-e55.o diff -Nru a/arch/mips/vr41xx/casio-e55/ide-e55.c b/arch/mips/vr41xx/casio-e55/ide-e55.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/casio-e55/ide-e55.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,99 @@ +/* + * 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. + * + * IDE routines for typical pc-like standard configurations + * for the CASIO CASSIOPEIA E-55/65. + * + * Copyright (C) 1998, 1999, 2001 by Ralf Baechle + */ +/* + * Changes: + * Yoichi Yuasa Sun, 24 Feb 2002 + * - Added CASIO CASSIOPEIA E-55/65 support. + */ +#include +#include +#include +#include +#include +#include + +static int e55_ide_default_irq(ide_ioreg_t base) +{ + return 40; +} + +static ide_ioreg_t e55_ide_default_io_base(int index) +{ + switch (index) { + case 0: return 0xc1f0; + case 1: return 0xc170; + case 2: return 0xc1e8; + case 3: return 0xc168; + case 4: return 0xc1e0; + case 5: return 0xc160; + } + return 0; +} + +static void e55_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, + ide_ioreg_t ctrl_port, int *irq) +{ + ide_ioreg_t reg = data_port; + int i; + + for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { + hw->io_ports[i] = reg; + reg += 1; + } + if (ctrl_port) { + hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port; + } else { + hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206; + } + if (irq != NULL) + *irq = 0; + hw->io_ports[IDE_IRQ_OFFSET] = 0; +} + +static int e55_ide_request_irq(unsigned int irq, + void (*handler)(int,void *, struct pt_regs *), + unsigned long flags, const char *device, + void *dev_id) +{ + return request_irq(irq, handler, flags, device, dev_id); +} + +static void e55_ide_free_irq(unsigned int irq, void *dev_id) +{ + free_irq(irq, dev_id); +} + +static int e55_ide_check_region(ide_ioreg_t from, unsigned int extent) +{ + return check_region(from, extent); +} + +static void e55_ide_request_region(ide_ioreg_t from, unsigned int extent, + const char *name) +{ + request_region(from, extent, name); +} + +static void e55_ide_release_region(ide_ioreg_t from, unsigned int extent) +{ + release_region(from, extent); +} + +struct ide_ops e55_ide_ops = { + &e55_ide_default_irq, + &e55_ide_default_io_base, + &e55_ide_init_hwif_ports, + &e55_ide_request_irq, + &e55_ide_free_irq, + &e55_ide_check_region, + &e55_ide_request_region, + &e55_ide_release_region +}; diff -Nru a/arch/mips/vr41xx/casio-e55/init.c b/arch/mips/vr41xx/casio-e55/init.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/casio-e55/init.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,49 @@ +/* + * FILE NAME + * arch/mips/vr41xx/casio-e55/init.c + * + * BRIEF MODULE DESCRIPTION + * Initialisation code for the CASIO CASSIOPEIA E-55/65. + * + * Copyright 2002 Yoichi Yuasa + * yuasa@hh.iij4u.or.jp + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include +#include + +#include + +char arcs_cmdline[CL_SIZE]; + +const char *get_system_type(void) +{ + return "CASIO CASSIOPEIA E-11/15/55/65"; +} + +void __init prom_init(int argc, char **argv, unsigned long magic, int *prom_vec) +{ + int i; + + /* + * collect args and prepare cmd_line + */ + for (i = 1; i < argc; i++) { + strcat(arcs_cmdline, argv[i]); + if (i < (argc - 1)) + strcat(arcs_cmdline, " "); + } + + mips_machgroup = MACH_GROUP_NEC_VR41XX; + mips_machtype = MACH_CASIO_E55; +} + +void __init prom_free_prom_memory (void) +{ +} diff -Nru a/arch/mips/vr41xx/casio-e55/setup.c b/arch/mips/vr41xx/casio-e55/setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/casio-e55/setup.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,74 @@ +/* + * FILE NAME + * arch/mips/vr41xx/casio-e55/setup.c + * + * BRIEF MODULE DESCRIPTION + * Setup for the CASIO CASSIOPEIA E-11/15/55/65. + * + * Copyright 2002 Yoichi Yuasa + * yuasa@hh.iij4u.or.jp + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef CONFIG_BLK_DEV_INITRD +extern unsigned long initrd_start, initrd_end; +extern void * __rd_start, * __rd_end; +#endif + +#ifdef CONFIG_BLK_DEV_IDE +extern struct ide_ops e55_ide_ops; +#endif + +void __init casio_e55_setup(void) +{ + set_io_port_base(IO_PORT_BASE); + ioport_resource.start = IO_PORT_RESOURCE_START; + ioport_resource.end = IO_PORT_RESOURCE_END; + iomem_resource.start = IO_MEM_RESOURCE_START; + iomem_resource.end = IO_MEM_RESOURCE_END; + +#ifdef CONFIG_BLK_DEV_INITRD + ROOT_DEV = Root_RAM0; + initrd_start = (unsigned long)&__rd_start; + initrd_end = (unsigned long)&__rd_end; +#endif + + _machine_restart = vr41xx_restart; + _machine_halt = vr41xx_halt; + _machine_power_off = vr41xx_power_off; + + board_time_init = vr41xx_time_init; + board_timer_setup = vr41xx_timer_setup; + +#ifdef CONFIG_FB + conswitchp = &dummy_con; +#endif + +#ifdef CONFIG_BLK_DEV_IDE + ide_ops = &e55_ide_ops; +#endif + + vr41xx_bcu_init(); + + vr41xx_cmu_init(0); + +#ifdef CONFIG_SERIAL_8250 + vr41xx_siu_init(SIU_RS232C, 0); +#endif +} diff -Nru a/arch/mips/vr41xx/common/Makefile b/arch/mips/vr41xx/common/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/common/Makefile Tue Jul 1 18:44:40 2003 @@ -0,0 +1,10 @@ +# +# Makefile for common code of the NEC VR4100 series. +# + +obj-y += bcu.o cmu.o giu.o icu.o int-handler.o reset.o +obj-$(CONFIG_SERIAL_8250) += serial.o +obj-$(CONFIG_VR41XX_TIME_C) += time.o +obj-$(CONFIG_VRC4173) += vrc4173.o + +EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips/vr41xx/common/bcu.c b/arch/mips/vr41xx/common/bcu.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/common/bcu.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,206 @@ +/* + * FILE NAME + * arch/mips/vr41xx/common/bcu.c + * + * BRIEF MODULE DESCRIPTION + * Bus Control Unit routines for the NEC VR4100 series. + * + * Author: Yoichi Yuasa + * yyuasa@mvista.com or source@mvista.com + * + * Copyright 2002 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * Changes: + * MontaVista Software Inc. or + * - Added support for NEC VR4111 and VR4121. + * + * Paul Mundt + * - Calculate mips_counter_frequency properly on VR4131. + * + * MontaVista Software Inc. or + * - New creation, NEC VR4122 and VR4131 are supported. + */ +#include +#include + +#include +#include +#include +#include +#include + +#define VR4111_CLKSPEEDREG KSEG1ADDR(0x0b000014) +#define VR4122_CLKSPEEDREG KSEG1ADDR(0x0f000014) +#define VR4131_CLKSPEEDREG VR4122_CLKSPEEDREG + #define CLKSP(x) ((x) & 0x001f) + + #define DIV2B 0x8000 + #define DIV3B 0x4000 + #define DIV4B 0x2000 + + #define DIVT(x) (((x) & 0xf000) >> 12) + #define DIVVT(x) (((x) & 0x0f00) >> 8) + + #define TDIVMODE(x) (2 << (((x) & 0x1000) >> 12)) + #define VTDIVMODE(x) (((x) & 0x0700) >> 8) + +unsigned long vr41xx_vtclock = 0; + +static inline u16 read_clkspeed(void) +{ + switch (current_cpu_data.cputype) { + case CPU_VR4111: + case CPU_VR4121: return readw(VR4111_CLKSPEEDREG); + case CPU_VR4122: return readw(VR4122_CLKSPEEDREG); + case CPU_VR4131: return readw(VR4131_CLKSPEEDREG); + default: + printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n"); + break; + } + + return 0; +} + +static inline unsigned long calculate_pclock(u16 clkspeed) +{ + unsigned long pclock = 0; + + switch (current_cpu_data.cputype) { + case CPU_VR4111: + case CPU_VR4121: + pclock = 18432000 * 64; + break; + case CPU_VR4122: + pclock = 18432000 * 98; + break; + case CPU_VR4131: + pclock = 18432000 * 108; + break; + default: + printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n"); + break; + } + + pclock /= CLKSP(clkspeed); + printk(KERN_INFO "PClock: %ldHz\n", pclock); + + return pclock; +} + +static inline unsigned long calculate_vtclock(u16 clkspeed, unsigned long pclock) +{ + switch (current_cpu_data.cputype) { + case CPU_VR4111: + /* The NEC VR4111 doesn't have the VTClock. */ + break; + case CPU_VR4121: + vr41xx_vtclock = pclock; + /* DIVVT == 9 Divide by 1.5 . VTClock = (PClock * 6) / 9 */ + if (DIVVT(clkspeed) == 9) + vr41xx_vtclock = pclock * 6; + /* DIVVT == 10 Divide by 2.5 . VTClock = (PClock * 4) / 10 */ + else if (DIVVT(clkspeed) == 10) + vr41xx_vtclock = pclock * 4; + vr41xx_vtclock /= DIVVT(clkspeed); + printk(KERN_INFO "VTClock: %ldHz\n", vr41xx_vtclock); + break; + case CPU_VR4122: + if(VTDIVMODE(clkspeed) == 7) + vr41xx_vtclock = pclock / 1; + else if(VTDIVMODE(clkspeed) == 1) + vr41xx_vtclock = pclock / 2; + else + vr41xx_vtclock = pclock / VTDIVMODE(clkspeed); + printk(KERN_INFO "VTClock: %ldHz\n", vr41xx_vtclock); + break; + case CPU_VR4131: + vr41xx_vtclock = pclock / VTDIVMODE(clkspeed); + printk(KERN_INFO "VTClock: %ldHz\n", vr41xx_vtclock); + break; + default: + printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n"); + break; + } + + return vr41xx_vtclock; +} + +static inline unsigned long calculate_tclock(u16 clkspeed, unsigned long pclock, + unsigned long vtclock) +{ + unsigned long tclock = 0; + + switch (current_cpu_data.cputype) { + case CPU_VR4111: + if (!(clkspeed & DIV2B)) + tclock = pclock / 2; + else if (!(clkspeed & DIV3B)) + tclock = pclock / 3; + else if (!(clkspeed & DIV4B)) + tclock = pclock / 4; + break; + case CPU_VR4121: + tclock = pclock / DIVT(clkspeed); + break; + case CPU_VR4122: + case CPU_VR4131: + tclock = vtclock / TDIVMODE(clkspeed); + break; + default: + printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n"); + break; + } + + printk(KERN_INFO "TClock: %ldHz\n", tclock); + + return tclock; +} + +static inline unsigned long calculate_mips_counter_frequency(unsigned long tclock) +{ + /* + * VR4131 Revision 2.0 and 2.1 use a value of (tclock / 2). + */ + if ((current_cpu_data.processor_id == PRID_VR4131_REV2_0) || + (current_cpu_data.processor_id == PRID_VR4131_REV2_1)) + tclock /= 2; + else + tclock /= 4; + + return tclock; +} + +void __init vr41xx_bcu_init(void) +{ + unsigned long pclock, vtclock, tclock; + u16 clkspeed; + + clkspeed = read_clkspeed(); + + pclock = calculate_pclock(clkspeed); + vtclock = calculate_vtclock(clkspeed, pclock); + tclock = calculate_tclock(clkspeed, pclock, vtclock); + + mips_counter_frequency = calculate_mips_counter_frequency(tclock); +} diff -Nru a/arch/mips/vr41xx/common/cmu.c b/arch/mips/vr41xx/common/cmu.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/common/cmu.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,84 @@ +/* + * FILE NAME + * arch/mips/vr41xx/common/cmu.c + * + * BRIEF MODULE DESCRIPTION + * Clock Mask Unit routines for the NEC VR4100 series. + * + * Author: Yoichi Yuasa + * yyuasa@mvista.com or source@mvista.com + * + * Copyright 2001,2002 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * Changes: + * MontaVista Software Inc. or + * - Added support for NEC VR4111 and VR4121. + * + * MontaVista Software Inc. or + * - New creation, NEC VR4122 and VR4131 are supported. + */ +#include +#include + +#include +#include + +#define VR4111_CMUCLKMSK KSEG1ADDR(0x0b000060) +#define VR4122_CMUCLKMSK KSEG1ADDR(0x0f000060) + +static u32 vr41xx_cmu_base = 0; +static u16 cmuclkmsk = 0; + +#define write_cmu(mask) writew((mask), vr41xx_cmu_base) + +void vr41xx_clock_supply(u16 mask) +{ + cmuclkmsk |= mask; + write_cmu(cmuclkmsk); +} + +void vr41xx_clock_mask(u16 mask) +{ + cmuclkmsk &= ~mask; + write_cmu(cmuclkmsk); +} + +void __init vr41xx_cmu_init(u16 mask) +{ + switch (current_cpu_data.cputype) { + case CPU_VR4111: + case CPU_VR4121: + vr41xx_cmu_base = VR4111_CMUCLKMSK; + break; + case CPU_VR4122: + case CPU_VR4131: + vr41xx_cmu_base = VR4122_CMUCLKMSK; + break; + default: + panic("Unexpected CPU of NEC VR4100 series"); + break; + } + + cmuclkmsk = mask; +} diff -Nru a/arch/mips/vr41xx/common/giu.c b/arch/mips/vr41xx/common/giu.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/common/giu.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,267 @@ +/* + * FILE NAME + * arch/mips/vr41xx/common/giu.c + * + * BRIEF MODULE DESCRIPTION + * General-purpose I/O Unit Interrupt routines for NEC VR4100 series. + * + * Author: Yoichi Yuasa + * yyuasa@mvista.com or source@mvista.com + * + * Copyright 2002 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * Changes: + * MontaVista Software Inc. or + * - New creation, NEC VR4111, VR4121, VR4122 and VR4131 are supported. + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define VR4111_GIUIOSELL KSEG1ADDR(0x0b000100) +#define VR4122_GIUIOSELL KSEG1ADDR(0x0f000140) + +#define GIUIOSELL 0x00 +#define GIUIOSELH 0x02 +#define GIUINTSTATL 0x08 +#define GIUINTSTATH 0x0a +#define GIUINTENL 0x0c +#define GIUINTENH 0x0e +#define GIUINTTYPL 0x10 +#define GIUINTTYPH 0x12 +#define GIUINTALSELL 0x14 +#define GIUINTALSELH 0x16 +#define GIUINTHTSELL 0x18 +#define GIUINTHTSELH 0x1a + +u32 vr41xx_giu_base = 0; + +#define read_giuint(offset) readw(vr41xx_giu_base + (offset)) +#define write_giuint(val, offset) writew((val), vr41xx_giu_base + (offset)) + +static inline u16 set_giuint(u16 offset, u16 set) +{ + u16 res; + + res = read_giuint(offset); + res |= set; + write_giuint(res, offset); + + return res; +} + +static inline u16 clear_giuint(u16 offset, u16 clear) +{ + u16 res; + + res = read_giuint(offset); + res &= ~clear; + write_giuint(res, offset); + + return res; +} + +void vr41xx_enable_giuint(int pin) +{ + if (pin < 16) + set_giuint(GIUINTENL, (u16)1 << pin); + else + set_giuint(GIUINTENH, (u16)1 << (pin - 16)); +} + +void vr41xx_disable_giuint(int pin) +{ + if (pin < 16) + clear_giuint(GIUINTENL, (u16)1 << pin); + else + clear_giuint(GIUINTENH, (u16)1 << (pin - 16)); +} + +void vr41xx_clear_giuint(int pin) +{ + if (pin < 16) + write_giuint((u16)1 << pin, GIUINTSTATL); + else + write_giuint((u16)1 << (pin - 16), GIUINTSTATH); +} + +void vr41xx_set_irq_trigger(int pin, int trigger, int hold) +{ + u16 mask; + + if (pin < 16) { + mask = (u16)1 << pin; + if (trigger == TRIGGER_EDGE) { + set_giuint(GIUINTTYPL, mask); + if (hold == SIGNAL_HOLD) + set_giuint(GIUINTHTSELL, mask); + else + clear_giuint(GIUINTHTSELL, mask); + } else { + clear_giuint(GIUINTTYPL, mask); + clear_giuint(GIUINTHTSELL, mask); + } + } else { + mask = (u16)1 << (pin - 16); + if (trigger == TRIGGER_EDGE) { + set_giuint(GIUINTTYPH, mask); + if (hold == SIGNAL_HOLD) + set_giuint(GIUINTHTSELH, mask); + else + clear_giuint(GIUINTHTSELH, mask); + } else { + clear_giuint(GIUINTTYPH, mask); + clear_giuint(GIUINTHTSELH, mask); + } + } + + vr41xx_clear_giuint(pin); +} + +void vr41xx_set_irq_level(int pin, int level) +{ + u16 mask; + + if (pin < 16) { + mask = (u16)1 << pin; + if (level == LEVEL_HIGH) + set_giuint(GIUINTALSELL, mask); + else + clear_giuint(GIUINTALSELL, mask); + } else { + mask = (u16)1 << (pin - 16); + if (level == LEVEL_HIGH) + set_giuint(GIUINTALSELH, mask); + else + clear_giuint(GIUINTALSELH, mask); + } + + vr41xx_clear_giuint(pin); +} + +#define GIUINT_NR_IRQS 32 + +enum { + GIUINT_NO_CASCADE, + GIUINT_CASCADE +}; + +struct vr41xx_giuint_cascade { + unsigned int flag; + int (*get_irq_number)(int irq); +}; + +static struct vr41xx_giuint_cascade giuint_cascade[GIUINT_NR_IRQS]; +static struct irqaction giu_cascade = {no_action, 0, 0, "cascade", NULL, NULL}; + +static int no_irq_number(int irq) +{ + return -EINVAL; +} + +int vr41xx_cascade_irq(unsigned int irq, int (*get_irq_number)(int irq)) +{ + unsigned int pin; + int retval; + + if (irq < GIU_IRQ(0) || irq > GIU_IRQ(31)) + return -EINVAL; + + if(!get_irq_number) + return -EINVAL; + + pin = irq - GIU_IRQ(0); + giuint_cascade[pin].flag = GIUINT_CASCADE; + giuint_cascade[pin].get_irq_number = get_irq_number; + + retval = setup_irq(irq, &giu_cascade); + if (retval) { + giuint_cascade[pin].flag = GIUINT_NO_CASCADE; + giuint_cascade[pin].get_irq_number = no_irq_number; + } + + return retval; +} + +unsigned int giuint_do_IRQ(int pin, struct pt_regs *regs) +{ + struct vr41xx_giuint_cascade *cascade; + unsigned int retval = 0; + int giuint_irq, cascade_irq; + + disable_irq(GIUINT_CASCADE_IRQ); + cascade = &giuint_cascade[pin]; + giuint_irq = pin + GIU_IRQ(0); + if (cascade->flag == GIUINT_CASCADE) { + cascade_irq = cascade->get_irq_number(giuint_irq); + disable_irq(giuint_irq); + if (cascade_irq > 0) + retval = do_IRQ(cascade_irq, regs); + enable_irq(giuint_irq); + } else + retval = do_IRQ(giuint_irq, regs); + enable_irq(GIUINT_CASCADE_IRQ); + + return retval; +} + +void (*board_irq_init)(void) = NULL; + +void __init vr41xx_giuint_init(void) +{ + int i; + + switch (current_cpu_data.cputype) { + case CPU_VR4111: + case CPU_VR4121: + vr41xx_giu_base = VR4111_GIUIOSELL; + break; + case CPU_VR4122: + case CPU_VR4131: + vr41xx_giu_base = VR4122_GIUIOSELL; + break; + default: + panic("GIU: Unexpected CPU of NEC VR4100 series"); + break; + } + + for (i = 0; i < GIUINT_NR_IRQS; i++) { + vr41xx_disable_giuint(i); + giuint_cascade[i].flag = GIUINT_NO_CASCADE; + giuint_cascade[i].get_irq_number = no_irq_number; + } + + if (setup_irq(GIUINT_CASCADE_IRQ, &giu_cascade)) + printk("GIUINT: Can not cascade IRQ %d.\n", GIUINT_CASCADE_IRQ); + + if (board_irq_init) + board_irq_init(); +} diff -Nru a/arch/mips/vr41xx/common/icu.c b/arch/mips/vr41xx/common/icu.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/common/icu.c Tue Jul 1 18:44:39 2003 @@ -0,0 +1,407 @@ +/* + * FILE NAME + * arch/mips/vr41xx/vr4122/common/icu.c + * + * BRIEF MODULE DESCRIPTION + * Interrupt Control Unit routines for the NEC VR4122 and VR4131. + * + * Author: Yoichi Yuasa + * yyuasa@mvista.com or source@mvista.com + * + * Copyright 2001,2002 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * Changes: + * MontaVista Software Inc. or + * - Added support for NEC VR4111 and VR4121. + * + * Paul Mundt + * - kgdb support. + * + * MontaVista Software Inc. or + * - New creation, NEC VR4122 and VR4131 are supported. + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +extern asmlinkage void vr41xx_handle_interrupt(void); + +extern void __init init_generic_irq(void); +extern void mips_cpu_irq_init(u32 irq_base); + +extern void vr41xx_giuint_init(void); +extern unsigned int giuint_do_IRQ(int pin, struct pt_regs *regs); + +static u32 vr41xx_icu1_base = 0; +static u32 vr41xx_icu2_base = 0; + +#define VR4111_SYSINT1REG KSEG1ADDR(0x0b000080) +#define VR4111_SYSINT2REG KSEG1ADDR(0x0b000200) + +#define VR4122_SYSINT1REG KSEG1ADDR(0x0f000080) +#define VR4122_SYSINT2REG KSEG1ADDR(0x0f0000a0) + +#define SYSINT1REG 0x00 +#define GIUINTLREG 0x08 +#define MSYSINT1REG 0x0c +#define MGIUINTLREG 0x14 +#define NMIREG 0x18 +#define SOFTREG 0x1a + +#define SYSINT2REG 0x00 +#define GIUINTHREG 0x02 +#define MSYSINT2REG 0x06 +#define MGIUINTHREG 0x08 + +#define read_icu1(offset) readw(vr41xx_icu1_base + (offset)) +#define write_icu1(val, offset) writew((val), vr41xx_icu1_base + (offset)) + +#define read_icu2(offset) readw(vr41xx_icu2_base + (offset)) +#define write_icu2(val, offset) writew((val), vr41xx_icu2_base + (offset)) + +static inline u16 set_icu1(u16 offset, u16 set) +{ + u16 res; + + res = read_icu1(offset); + res |= set; + write_icu1(res, offset); + + return res; +} + +static inline u16 clear_icu1(u16 offset, u16 clear) +{ + u16 res; + + res = read_icu1(offset); + res &= ~clear; + write_icu1(res, offset); + + return res; +} + +static inline u16 set_icu2(u16 offset, u16 set) +{ + u16 res; + + res = read_icu2(offset); + res |= set; + write_icu2(res, offset); + + return res; +} + +static inline u16 clear_icu2(u16 offset, u16 clear) +{ + u16 res; + + res = read_icu2(offset); + res &= ~clear; + write_icu2(res, offset); + + return res; +} + +/*=======================================================================*/ + +static void enable_sysint1_irq(unsigned int irq) +{ + set_icu1(MSYSINT1REG, (u16)1 << (irq - SYSINT1_IRQ_BASE)); +} + +static void disable_sysint1_irq(unsigned int irq) +{ + clear_icu1(MSYSINT1REG, (u16)1 << (irq - SYSINT1_IRQ_BASE)); +} + +static unsigned int startup_sysint1_irq(unsigned int irq) +{ + set_icu1(MSYSINT1REG, (u16)1 << (irq - SYSINT1_IRQ_BASE)); + + return 0; /* never anything pending */ +} + +#define shutdown_sysint1_irq disable_sysint1_irq +#define ack_sysint1_irq disable_sysint1_irq + +static void end_sysint1_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + set_icu1(MSYSINT1REG, (u16)1 << (irq - SYSINT1_IRQ_BASE)); +} + +static struct hw_interrupt_type sysint1_irq_type = { + "SYSINT1", + startup_sysint1_irq, + shutdown_sysint1_irq, + enable_sysint1_irq, + disable_sysint1_irq, + ack_sysint1_irq, + end_sysint1_irq, + NULL +}; + +/*=======================================================================*/ + +static void enable_sysint2_irq(unsigned int irq) +{ + set_icu2(MSYSINT2REG, (u16)1 << (irq - SYSINT2_IRQ_BASE)); +} + +static void disable_sysint2_irq(unsigned int irq) +{ + clear_icu2(MSYSINT2REG, (u16)1 << (irq - SYSINT2_IRQ_BASE)); +} + +static unsigned int startup_sysint2_irq(unsigned int irq) +{ + set_icu2(MSYSINT2REG, (u16)1 << (irq - SYSINT2_IRQ_BASE)); + + return 0; /* never anything pending */ +} + +#define shutdown_sysint2_irq disable_sysint2_irq +#define ack_sysint2_irq disable_sysint2_irq + +static void end_sysint2_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + set_icu2(MSYSINT2REG, (u16)1 << (irq - SYSINT2_IRQ_BASE)); +} + +static struct hw_interrupt_type sysint2_irq_type = { + "SYSINT2", + startup_sysint2_irq, + shutdown_sysint2_irq, + enable_sysint2_irq, + disable_sysint2_irq, + ack_sysint2_irq, + end_sysint2_irq, + NULL +}; + +/*=======================================================================*/ + +static void enable_giuint_irq(unsigned int irq) +{ + int pin; + + pin = irq - GIU_IRQ_BASE; + if (pin < 16) + set_icu1(MGIUINTLREG, (u16)1 << pin); + else + set_icu2(MGIUINTHREG, (u16)1 << (pin - 16)); + + vr41xx_enable_giuint(pin); +} + +static void disable_giuint_irq(unsigned int irq) +{ + int pin; + + pin = irq - GIU_IRQ_BASE; + vr41xx_disable_giuint(pin); + + if (pin < 16) + clear_icu1(MGIUINTLREG, (u16)1 << pin); + else + clear_icu2(MGIUINTHREG, (u16)1 << (pin - 16)); +} + +static unsigned int startup_giuint_irq(unsigned int irq) +{ + vr41xx_clear_giuint(irq - GIU_IRQ_BASE); + + enable_giuint_irq(irq); + + return 0; /* never anything pending */ +} + +#define shutdown_giuint_irq disable_giuint_irq + +static void ack_giuint_irq(unsigned int irq) +{ + disable_giuint_irq(irq); + + vr41xx_clear_giuint(irq - GIU_IRQ_BASE); +} + +static void end_giuint_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + enable_giuint_irq(irq); +} + +static struct hw_interrupt_type giuint_irq_type = { + "GIUINT", + startup_giuint_irq, + shutdown_giuint_irq, + enable_giuint_irq, + disable_giuint_irq, + ack_giuint_irq, + end_giuint_irq, + NULL +}; + +/*=======================================================================*/ + +static struct irqaction icu_cascade = {no_action, 0, 0, "cascade", NULL, NULL}; + +static void __init vr41xx_icu_init(void) +{ + int i; + + switch (current_cpu_data.cputype) { + case CPU_VR4111: + case CPU_VR4121: + vr41xx_icu1_base = VR4111_SYSINT1REG; + vr41xx_icu2_base = VR4111_SYSINT2REG; + break; + case CPU_VR4122: + case CPU_VR4131: + vr41xx_icu1_base = VR4122_SYSINT1REG; + vr41xx_icu2_base = VR4122_SYSINT2REG; + break; + default: + panic("Unexpected CPU of NEC VR4100 series"); + break; + } + + write_icu1(0, MSYSINT1REG); + write_icu1(0, MGIUINTLREG); + + write_icu2(0, MSYSINT2REG); + write_icu2(0, MGIUINTHREG); + + for (i = SYSINT1_IRQ_BASE; i <= GIU_IRQ_LAST; i++) { + if (i >= SYSINT1_IRQ_BASE && i <= SYSINT1_IRQ_LAST) + irq_desc[i].handler = &sysint1_irq_type; + else if (i >= SYSINT2_IRQ_BASE && i <= SYSINT2_IRQ_LAST) + irq_desc[i].handler = &sysint2_irq_type; + else if (i >= GIU_IRQ_BASE && i <= GIU_IRQ_LAST) + irq_desc[i].handler = &giuint_irq_type; + } + + setup_irq(ICU_CASCADE_IRQ, &icu_cascade); +} + +void __init init_IRQ(void) +{ + memset(irq_desc, 0, sizeof(irq_desc)); + + init_generic_irq(); + mips_cpu_irq_init(MIPS_CPU_IRQ_BASE); + vr41xx_icu_init(); + + vr41xx_giuint_init(); + + set_except_vector(0, vr41xx_handle_interrupt); + +#ifdef CONFIG_KGDB + printk("Setting debug traps - please connect the remote debugger.\n"); + set_debug_traps(); + breakpoint(); +#endif +} + +/*=======================================================================*/ + +static inline void giuint_irqdispatch(u16 pendl, u16 pendh, struct pt_regs *regs) +{ + int i; + + if (pendl) { + for (i = 0; i < 16; i++) { + if (pendl & (0x0001 << i)) { + giuint_do_IRQ(i, regs); + return; + } + } + } + else if (pendh) { + for (i = 0; i < 16; i++) { + if (pendh & (0x0001 << i)) { + giuint_do_IRQ(i + 16, regs); + return; + } + } + } +} + +asmlinkage void icu_irqdispatch(struct pt_regs *regs) +{ + u16 pend1, pend2, pendl, pendh; + u16 mask1, mask2, maskl, maskh; + int i; + + pend1 = read_icu1(SYSINT1REG); + mask1 = read_icu1(MSYSINT1REG); + + pend2 = read_icu2(SYSINT2REG); + mask2 = read_icu2(MSYSINT2REG); + + pendl = read_icu1(GIUINTLREG); + maskl = read_icu1(MGIUINTLREG); + + pendh = read_icu2(GIUINTHREG); + maskh = read_icu2(MGIUINTHREG); + + pend1 &= mask1; + pend2 &= mask2; + pendl &= maskl; + pendh &= maskh; + + if (pend1) { + if ((pend1 & 0x01ff) == 0x0100) { + giuint_irqdispatch(pendl, pendh, regs); + } + else { + for (i = 0; i < 16; i++) { + if (pend1 & (0x0001 << i)) { + do_IRQ(SYSINT1_IRQ_BASE + i, regs); + break; + } + } + } + return; + } + else if (pend2) { + for (i = 0; i < 16; i++) { + if (pend2 & (0x0001 << i)) { + do_IRQ(SYSINT2_IRQ_BASE + i, regs); + break; + } + } + } +} diff -Nru a/arch/mips/vr41xx/common/int-handler.S b/arch/mips/vr41xx/common/int-handler.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/common/int-handler.S Tue Jul 1 18:44:40 2003 @@ -0,0 +1,114 @@ +/* + * FILE NAME + * arch/mips/vr41xx/common/int-handler.S + * + * BRIEF MODULE DESCRIPTION + * Interrupt dispatcher for the NEC VR4100 series. + * + * Author: Yoichi Yuasa + * yyuasa@mvista.com or source@mvista.com + * + * Copyright 2001 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * Changes: + * MontaVista Software Inc. or + * - New creation, NEC VR4100 series are supported. + */ +#include +#include +#include +#include + + .text + .set noreorder + + .align 5 + NESTED(vr41xx_handle_interrupt, PT_SIZE, ra) + .set noat + SAVE_ALL + CLI + .set at + .set noreorder + + /* + * Get the pending interrupts + */ + mfc0 t0, CP0_CAUSE + mfc0 t1, CP0_STATUS + andi t0, 0xff00 + and t0, t0, t1 + + andi t1, t0, CAUSEF_IP7 # timer interrupt + beqz t1, 1f + li a0, 7 + jal ll_timer_interrupt + move a1, sp + j ret_from_irq + +1: + andi t1, t0, 0x7800 # check for IP3-6 + beqz t1, 2f + + andi t1, t0, CAUSEF_IP3 # check for IP3 + bnez t1, handle_it + li a0, 3 + + andi t1, t0, CAUSEF_IP4 # check for IP4 + bnez t1, handle_it + li a0, 4 + + andi t1, t0, CAUSEF_IP5 # check for IP5 + bnez t1, handle_it + li a0, 5 + + andi t1, t0, CAUSEF_IP6 # check for IP6 + bnez t1, handle_it + li a0, 6 + +2: + andi t1, t0, CAUSEF_IP2 # check for IP2 + beqz t1, 3f + move a0, sp + jal icu_irqdispatch + nop + j ret_from_irq + nop + +3: + andi t1, t0, CAUSEF_IP0 # check for IP0 + bnez t1, handle_it + li a0, 0 + + andi t1, t0, CAUSEF_IP1 # check for IP1 + bnez t1, handle_it + li a0, 1 + + j spurious_interrupt + nop + +handle_it: + jal do_IRQ + move a1, sp + j ret_from_irq + END(vr41xx_handle_interrupt) diff -Nru a/arch/mips/vr41xx/common/reset.c b/arch/mips/vr41xx/common/reset.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/common/reset.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,37 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * Copyright (C) 1997, 2001 Ralf Baechle + * Copyright 2001 MontaVista Software Inc. + * Author: jsun@mvista.com or jsun@junsun.net + */ +#include +#include +#include +#include +#include +#include +#include + +void vr41xx_restart(char *command) +{ + change_c0_status((ST0_BEV | ST0_ERL), (ST0_BEV | ST0_ERL)); + change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); + flush_cache_all(); + write_c0_wired(0); + __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); +} + +void vr41xx_halt(void) +{ + printk(KERN_NOTICE "\n** You can safely turn off the power\n"); + while (1); +} + +void vr41xx_power_off(void) +{ + vr41xx_halt(); +} diff -Nru a/arch/mips/vr41xx/common/serial.c b/arch/mips/vr41xx/common/serial.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/common/serial.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,177 @@ +/* + * FILE NAME + * arch/mips/vr41xx/common/serial.c + * + * BRIEF MODULE DESCRIPTION + * Serial Interface Unit routines for NEC VR4100 series. + * + * Author: Yoichi Yuasa + * yyuasa@mvista.com or source@mvista.com + * + * Copyright 2002 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * Changes: + * MontaVista Software Inc. or + * - Added support for NEC VR4111 and VR4121. + * + * MontaVista Software Inc. or + * - New creation, NEC VR4122 and VR4131 are supported. + */ +#include +#include +#include + +#include +#include +#include +#include + +/* VR4111 and VR4121 SIU Registers */ +#define VR4111_SIURB KSEG1ADDR(0x0c000000) +#define VR4111_SIUIRSEL KSEG1ADDR(0x0c000008) + +/* VR4122 and VR4131 SIU Registers */ +#define VR4122_SIURB KSEG1ADDR(0x0f000800) +#define VR4122_SIUIRSEL KSEG1ADDR(0x0f000808) + + #define USE_RS232C 0x00 + #define USE_IRDA 0x01 + #define SIU_USES_IRDA 0x00 + #define FIR_USES_IRDA 0x02 + #define IRDA_MODULE_SHARP 0x00 + #define IRDA_MODULE_TEMIC 0x04 + #define IRDA_MODULE_HP 0x08 + #define TMICTX 0x10 + #define TMICMODE 0x20 + +#define SIU_BASE_BAUD 1152000 +#define SIU_CLOCK 0x0102 + +/* VR4122 and VR4131 DSIU Registers */ +#define DSIURB KSEG1ADDR(0x0f000820) + +#define MDSIUINTREG KSEG1ADDR(0x0f000096) + #define INTDSIU 0x0800 + +#define DSIU_BASE_BAUD 1152000 +#define DSIU_CLOCK 0x0802 + +int vr41xx_serial_ports = 0; + +void vr41xx_siu_ifselect(int interface, int module) +{ + u16 val = USE_RS232C; /* Select RS-232C */ + + /* Select IrDA */ + if (interface == SIU_IRDA) { + switch (module) { + case IRDA_SHARP: + val = IRDA_MODULE_SHARP; + break; + case IRDA_TEMIC: + val = IRDA_MODULE_TEMIC; + break; + case IRDA_HP: + val = IRDA_MODULE_HP; + break; + } + val |= USE_IRDA | SIU_USES_IRDA; + } + + switch (current_cpu_data.cputype) { + case CPU_VR4111: + case CPU_VR4121: + writew(val, VR4111_SIUIRSEL); + break; + case CPU_VR4122: + case CPU_VR4131: + writew(val, VR4122_SIUIRSEL); + break; + default: + printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n"); + break; + } +} + +void __init vr41xx_siu_init(int interface, int module) +{ + struct serial_struct s; + + vr41xx_siu_ifselect(interface, module); + + memset(&s, 0, sizeof(s)); + + s.line = vr41xx_serial_ports; + s.baud_base = SIU_BASE_BAUD; + s.irq = SIU_IRQ; + s.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; + switch (current_cpu_data.cputype) { + case CPU_VR4111: + case CPU_VR4121: + s.iomem_base = (unsigned char *)VR4111_SIURB; + break; + case CPU_VR4122: + case CPU_VR4131: + s.iomem_base = (unsigned char *)VR4122_SIURB; + break; + default: + panic("Unexpected CPU of NEC VR4100 series"); + break; + } + s.iomem_reg_shift = 0; + s.io_type = SERIAL_IO_MEM; + if (early_serial_setup(&s) != 0) + printk(KERN_ERR "SIU setup failed!\n"); + + vr41xx_clock_supply(SIU_CLOCK); + + vr41xx_serial_ports++; +} + +void __init vr41xx_dsiu_init(void) +{ + struct serial_struct s; + + if (current_cpu_data.cputype != CPU_VR4122 && + current_cpu_data.cputype != CPU_VR4131) + return; + + memset(&s, 0, sizeof(s)); + + s.line = vr41xx_serial_ports; + s.baud_base = DSIU_BASE_BAUD; + s.irq = DSIU_IRQ; + s.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; + s.iomem_base = (unsigned char *)DSIURB; + s.iomem_reg_shift = 0; + s.io_type = SERIAL_IO_MEM; + if (early_serial_setup(&s) != 0) + printk(KERN_ERR "DSIU setup failed!\n"); + + vr41xx_clock_supply(DSIU_CLOCK); + + writew(INTDSIU, MDSIUINTREG); + + vr41xx_serial_ports++; +} diff -Nru a/arch/mips/vr41xx/common/time.c b/arch/mips/vr41xx/common/time.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/common/time.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,93 @@ +/* + * FILE NAME + * arch/mips/vr41xx/common/time.c + * + * BRIEF MODULE DESCRIPTION + * Timer routines for the NEC VR4100 series. + * + * Author: Yoichi Yuasa + * yyuasa@mvista.com or source@mvista.com + * + * Copyright 2001,2002 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * Changes: + * MontaVista Software Inc. or + * - Added support for NEC VR4100 series RTC Unit. + * + * MontaVista Software Inc. or + * - New creation, NEC VR4100 series are supported. + */ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define VR4111_ETIMELREG KSEG1ADDR(0x0b0000c0) +#define VR4122_ETIMELREG KSEG1ADDR(0x0f000100) + +u32 vr41xx_rtc_base = 0; + +#ifdef CONFIG_VR41XX_RTC +extern unsigned long vr41xx_rtc_get_time(void); +extern int vr41xx_rtc_set_time(unsigned long sec); +#endif + +void vr41xx_time_init(void) +{ + switch (current_cpu_data.cputype) { + case CPU_VR4111: + case CPU_VR4121: + vr41xx_rtc_base = VR4111_ETIMELREG; + break; + case CPU_VR4122: + case CPU_VR4131: + vr41xx_rtc_base = VR4122_ETIMELREG; + break; + default: + panic("Unexpected CPU of NEC VR4100 series"); + break; + } + +#ifdef CONFIG_VR41XX_RTC + rtc_get_time = vr41xx_rtc_get_time; + rtc_set_time = vr41xx_rtc_set_time; +#endif +} + +void vr41xx_timer_setup(struct irqaction *irq) +{ + u32 count; + + setup_irq(MIPS_COUNTER_IRQ, irq); + + count = read_c0_count(); + write_c0_compare(count + (mips_counter_frequency / HZ)); +} diff -Nru a/arch/mips/vr41xx/common/vrc4173.c b/arch/mips/vr41xx/common/vrc4173.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/common/vrc4173.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,279 @@ +/* + * FILE NAME + * drivers/char/vrc4173.c + * + * BRIEF MODULE DESCRIPTION + * NEC VRC4173 driver for NEC VR4122/VR4131. + * + * Author: Yoichi Yuasa + * yyuasa@mvista.com or source@mvista.com + * + * Copyright 2001,2002 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +MODULE_DESCRIPTION("NEC VRC4173 driver for NEC VR4122/4131"); +MODULE_AUTHOR("Yoichi Yuasa "); +MODULE_LICENSE("GPL"); + +#define VRC4173_CMUCLKMSK 0x040 +#define VRC4173_CMUSRST 0x042 + +#define VRC4173_SELECTREG 0x09e + +#define VRC4173_SYSINT1REG 0x060 +#define VRC4173_MSYSINT1REG 0x06c + +static struct pci_device_id vrc4173_table[] __devinitdata = { + {PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_VRC4173, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0, } +}; + +unsigned long vrc4173_io_offset = 0; + +EXPORT_SYMBOL(vrc4173_io_offset); + +static u16 vrc4173_cmuclkmsk; +static int vrc4173_initialized; + +void vrc4173_clock_supply(u16 mask) +{ + if (vrc4173_initialized) { + vrc4173_cmuclkmsk |= mask; + vrc4173_outw(vrc4173_cmuclkmsk, VRC4173_CMUCLKMSK); + } +} + +void vrc4173_clock_mask(u16 mask) +{ + if (vrc4173_initialized) { + vrc4173_cmuclkmsk &= ~mask; + vrc4173_outw(vrc4173_cmuclkmsk, VRC4173_CMUCLKMSK); + } +} + +static inline void vrc4173_cmu_init(void) +{ + vrc4173_cmuclkmsk = vrc4173_inw(VRC4173_CMUCLKMSK); +} + +EXPORT_SYMBOL(vrc4173_clock_supply); +EXPORT_SYMBOL(vrc4173_clock_mask); + +void vrc4173_select_function(int func) +{ + u16 val; + + if (vrc4173_initialized) { + val = vrc4173_inw(VRC4173_SELECTREG); + switch(func) { + case PS2CH1_SELECT: + val |= 0x0004; + break; + case PS2CH2_SELECT: + val |= 0x0002; + break; + case TOUCHPANEL_SELECT: + val &= 0x0007; + break; + case KIU8_SELECT: + val &= 0x000e; + break; + case KIU10_SELECT: + val &= 0x000c; + break; + case KIU12_SELECT: + val &= 0x0008; + break; + case GPIO_SELECT: + val |= 0x0008; + break; + } + vrc4173_outw(val, VRC4173_SELECTREG); + } +} + +EXPORT_SYMBOL(vrc4173_select_function); + +static void enable_vrc4173_irq(unsigned int irq) +{ + u16 val; + + val = vrc4173_inw(VRC4173_MSYSINT1REG); + val |= (u16)1 << (irq - VRC4173_IRQ_BASE); + vrc4173_outw(val, VRC4173_MSYSINT1REG); +} + +static void disable_vrc4173_irq(unsigned int irq) +{ + u16 val; + + val = vrc4173_inw(VRC4173_MSYSINT1REG); + val &= ~((u16)1 << (irq - VRC4173_IRQ_BASE)); + vrc4173_outw(val, VRC4173_MSYSINT1REG); +} + +static unsigned int startup_vrc4173_irq(unsigned int irq) +{ + enable_vrc4173_irq(irq); + return 0; /* never anything pending */ +} + +#define shutdown_vrc4173_irq disable_vrc4173_irq +#define ack_vrc4173_irq disable_vrc4173_irq + +static void end_vrc4173_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + enable_vrc4173_irq(irq); +} + +static struct hw_interrupt_type vrc4173_irq_type = { + "VRC4173", + startup_vrc4173_irq, + shutdown_vrc4173_irq, + enable_vrc4173_irq, + disable_vrc4173_irq, + ack_vrc4173_irq, + end_vrc4173_irq, + NULL +}; + +static int vrc4173_get_irq_number(int irq) +{ + u16 status, mask; + int i; + + status = vrc4173_inw(VRC4173_SYSINT1REG); + mask = vrc4173_inw(VRC4173_MSYSINT1REG); + + status &= mask; + if (status) { + for (i = 0; i < 16; i++) + if (status & (0x0001 << i)) + return VRC4173_IRQ_BASE + i; + } + + return -EINVAL; +} + +static inline void vrc4173_icu_init(int cascade_irq) +{ + int i; + + if (cascade_irq < GIU_IRQ(0) || cascade_irq > GIU_IRQ(15)) + return; + + vrc4173_outw(0, VRC4173_MSYSINT1REG); + + vr41xx_set_irq_trigger(cascade_irq - GIU_IRQ(0), TRIGGER_LEVEL, SIGNAL_THROUGH); + vr41xx_set_irq_level(cascade_irq - GIU_IRQ(0), LEVEL_LOW); + + for (i = VRC4173_IRQ_BASE; i <= VRC4173_IRQ_LAST; i++) + irq_desc[i].handler = &vrc4173_irq_type; +} + +static int __devinit vrc4173_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + unsigned long start, flags; + int err; + + if ((err = pci_enable_device(pdev)) < 0) { + printk(KERN_ERR "vrc4173: failed to enable device -- err=%d\n", err); + return err; + } + + pci_set_master(pdev); + + start = pci_resource_start(pdev, 0); + if (!start) { + printk(KERN_ERR "vrc4173:No PCI I/O resources, aborting\n"); + return -ENODEV; + } + + if (!start || (((flags = pci_resource_flags(pdev, 0)) & IORESOURCE_IO) == 0)) { + printk(KERN_ERR "vrc4173: No PCI I/O resources, aborting\n"); + return -ENODEV; + } + + if ((err = pci_request_regions(pdev, "NEC VRC4173")) < 0) { + printk(KERN_ERR "vrc4173: PCI resources are busy, aborting\n"); + return err; + } + + set_vrc4173_io_offset(start); + + vrc4173_cmu_init(); + + vrc4173_icu_init(pdev->irq); + + if ((err = vr41xx_cascade_irq(pdev->irq, vrc4173_get_irq_number)) < 0) { + printk(KERN_ERR + "vrc4173: IRQ resource %d is busy, aborting\n", pdev->irq); + return err; + } + + printk(KERN_INFO + "NEC VRC4173 at 0x%#08lx, IRQ is cascaded to %d\n", start, pdev->irq); + + return 0; +} + +static struct pci_driver vrc4173_driver = { + name: "NEC VRC4173", + probe: vrc4173_probe, + remove: NULL, + id_table: vrc4173_table, +}; + +static int __devinit vrc4173_init(void) +{ + int err; + + if ((err = pci_module_init(&vrc4173_driver)) < 0) + return err; + + vrc4173_initialized = 1; + + return 0; +} + +static void __devexit vrc4173_exit(void) +{ + vrc4173_initialized = 0; + + pci_unregister_driver(&vrc4173_driver); +} + +module_init(vrc4173_init); +module_exit(vrc4173_exit); diff -Nru a/arch/mips/vr41xx/ibm-workpad/Makefile b/arch/mips/vr41xx/ibm-workpad/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/ibm-workpad/Makefile Tue Jul 1 18:44:40 2003 @@ -0,0 +1,6 @@ +# +# Makefile for the IBM WorkPad z50 specific parts of the kernel +# + +obj-y += init.o setup.o +obj-$(CONFIG_IDE) += ide-workpad.o diff -Nru a/arch/mips/vr41xx/ibm-workpad/ide-workpad.c b/arch/mips/vr41xx/ibm-workpad/ide-workpad.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/ibm-workpad/ide-workpad.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,98 @@ +/* + * 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. + * + * IDE routines for typical pc-like standard configurations for the IBM WorkPad z50. + * + * Copyright (C) 1998, 1999, 2001 by Ralf Baechle + */ +/* + * Changes: + * Yoichi Yuasa Sun, 24 Feb 2002 + * - Added IBM WorkPad z50 support. + */ +#include +#include +#include +#include +#include +#include + +static int workpad_ide_default_irq(ide_ioreg_t base) +{ + return 49; +} + +static ide_ioreg_t workpad_ide_default_io_base(int index) +{ + switch (index) { + case 0: return 0x1f0; + case 1: return 0x170; + case 2: return 0x1e8; + case 3: return 0x168; + case 4: return 0x1e0; + case 5: return 0x160; + } + return 0; +} + +static void workpad_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, + ide_ioreg_t ctrl_port, int *irq) +{ + ide_ioreg_t reg = data_port; + int i; + + for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { + hw->io_ports[i] = reg; + reg += 1; + } + if (ctrl_port) { + hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port; + } else { + hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206; + } + if (irq != NULL) + *irq = 0; + hw->io_ports[IDE_IRQ_OFFSET] = 0; +} + +static int workpad_ide_request_irq(unsigned int irq, + void (*handler)(int,void *, struct pt_regs *), + unsigned long flags, const char *device, + void *dev_id) +{ + return request_irq(irq, handler, SA_SHIRQ, device, dev_id); +} + +static void workpad_ide_free_irq(unsigned int irq, void *dev_id) +{ + free_irq(irq, dev_id); +} + +static int workpad_ide_check_region(ide_ioreg_t from, unsigned int extent) +{ + return check_region(from, extent); +} + +static void workpad_ide_request_region(ide_ioreg_t from, unsigned int extent, + const char *name) +{ + request_region(from, extent, name); +} + +static void workpad_ide_release_region(ide_ioreg_t from, unsigned int extent) +{ + release_region(from, extent); +} + +struct ide_ops workpad_ide_ops = { + &workpad_ide_default_irq, + &workpad_ide_default_io_base, + &workpad_ide_init_hwif_ports, + &workpad_ide_request_irq, + &workpad_ide_free_irq, + &workpad_ide_check_region, + &workpad_ide_request_region, + &workpad_ide_release_region +}; diff -Nru a/arch/mips/vr41xx/ibm-workpad/init.c b/arch/mips/vr41xx/ibm-workpad/init.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/ibm-workpad/init.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,49 @@ +/* + * FILE NAME + * arch/mips/vr41xx/ibm-workpad/init.c + * + * BRIEF MODULE DESCRIPTION + * Initialisation code for the IBM WorkPad z50. + * + * Copyright 2002 Yoichi Yuasa + * yuasa@hh.iij4u.or.jp + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include +#include + +#include + +char arcs_cmdline[CL_SIZE]; + +const char *get_system_type(void) +{ + return "IBM WorkPad z50"; +} + +void __init prom_init(int argc, char **argv, unsigned long magic, int *prom_vec) +{ + int i; + + /* + * collect args and prepare cmd_line + */ + for (i = 1; i < argc; i++) { + strcat(arcs_cmdline, argv[i]); + if (i < (argc - 1)) + strcat(arcs_cmdline, " "); + } + + mips_machgroup = MACH_GROUP_NEC_VR41XX; + mips_machtype = MACH_IBM_WORKPAD; +} + +void __init prom_free_prom_memory (void) +{ +} diff -Nru a/arch/mips/vr41xx/ibm-workpad/setup.c b/arch/mips/vr41xx/ibm-workpad/setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/ibm-workpad/setup.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,74 @@ +/* + * FILE NAME + * arch/mips/vr41xx/workpad/setup.c + * + * BRIEF MODULE DESCRIPTION + * Setup for the IBM WorkPad z50. + * + * Copyright 2002 Yoichi Yuasa + * yuasa@hh.iij4u.or.jp + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef CONFIG_BLK_DEV_INITRD +extern unsigned long initrd_start, initrd_end; +extern void * __rd_start, * __rd_end; +#endif + +#ifdef CONFIG_BLK_DEV_IDE +extern struct ide_ops workpad_ide_ops; +#endif + +void __init ibm_workpad_setup(void) +{ + set_io_port_base(IO_PORT_BASE); + ioport_resource.start = IO_PORT_RESOURCE_START; + ioport_resource.end = IO_PORT_RESOURCE_END; + iomem_resource.start = IO_MEM_RESOURCE_START; + iomem_resource.end = IO_MEM_RESOURCE_END; + +#ifdef CONFIG_BLK_DEV_INITRD + ROOT_DEV = Root_RAM0; + initrd_start = (unsigned long)&__rd_start; + initrd_end = (unsigned long)&__rd_end; +#endif + + _machine_restart = vr41xx_restart; + _machine_halt = vr41xx_halt; + _machine_power_off = vr41xx_power_off; + + board_time_init = vr41xx_time_init; + board_timer_setup = vr41xx_timer_setup; + +#ifdef CONFIG_FB + conswitchp = &dummy_con; +#endif + +#ifdef CONFIG_BLK_DEV_IDE + ide_ops = &workpad_ide_ops; +#endif + + vr41xx_bcu_init(); + + vr41xx_cmu_init(0); + +#ifdef CONFIG_SERIAL_8250 + vr41xx_siu_init(SIU_RS232C, 0); +#endif +} diff -Nru a/arch/mips/vr41xx/nec-eagle/Makefile b/arch/mips/vr41xx/nec-eagle/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/nec-eagle/Makefile Tue Jul 1 18:44:40 2003 @@ -0,0 +1,11 @@ +# +# Makefile for the NEC Eagle/Hawk specific parts of the kernel +# +# Author: Yoichi Yuasa +# yyuasa@mvista.com or source@mvista.com +# +# Copyright 2001,2002 MontaVista Software Inc. +# + +obj-y += init.o irq.o setup.o +obj-$(CONFIG_IDE) += ide-eagle.o diff -Nru a/arch/mips/vr41xx/nec-eagle/ide-eagle.c b/arch/mips/vr41xx/nec-eagle/ide-eagle.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/nec-eagle/ide-eagle.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,96 @@ +/* + * 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. + * + * IDE routines for typical pc-like standard configurations + * for the NEC Eagle/Hawk board. + * + * Copyright (C) 1998, 1999, 2001 by Ralf Baechle + */ +/* + * Changes: + * MontaVista Software Inc. or + * Fri, 5 Apr 2002 + * - Added support for NEC Hawk. + * + * MontaVista Software Inc. or + * Fri, 1 Mar 2002 + * - Added support for NEC Eagle. + */ +#include +#include +#include +#include +#include +#include + +static int eagle_ide_default_irq(ide_ioreg_t base) +{ + return 0; +} + +static ide_ioreg_t eagle_ide_default_io_base(int index) +{ + return 0; +} + +static void eagle_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, + ide_ioreg_t ctrl_port, int *irq) +{ + ide_ioreg_t reg = data_port; + int i; + + for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { + hw->io_ports[i] = reg; + reg += 1; + } + if (ctrl_port) { + hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port; + } else { + hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206; + } + if (irq != NULL) + *irq = 0; + hw->io_ports[IDE_IRQ_OFFSET] = 0; +} + +static int eagle_ide_request_irq(unsigned int irq, + void (*handler)(int,void *, struct pt_regs *), + unsigned long flags, const char *device, + void *dev_id) +{ + return request_irq(irq, handler, SA_SHIRQ, device, dev_id); +} + +static void eagle_ide_free_irq(unsigned int irq, void *dev_id) +{ + free_irq(irq, dev_id); +} + +static int eagle_ide_check_region(ide_ioreg_t from, unsigned int extent) +{ + return check_region(from, extent); +} + +static void eagle_ide_request_region(ide_ioreg_t from, unsigned int extent, + const char *name) +{ + request_region(from, extent, name); +} + +static void eagle_ide_release_region(ide_ioreg_t from, unsigned int extent) +{ + release_region(from, extent); +} + +struct ide_ops eagle_ide_ops = { + &eagle_ide_default_irq, + &eagle_ide_default_io_base, + &eagle_ide_init_hwif_ports, + &eagle_ide_request_irq, + &eagle_ide_free_irq, + &eagle_ide_check_region, + &eagle_ide_request_region, + &eagle_ide_release_region +}; diff -Nru a/arch/mips/vr41xx/nec-eagle/init.c b/arch/mips/vr41xx/nec-eagle/init.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/nec-eagle/init.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,74 @@ +/* + * FILE NAME + * arch/mips/vr41xx/nec-eagle/init.c + * + * BRIEF MODULE DESCRIPTION + * Initialisation code for the NEC Eagle/Hawk board. + * + * Author: Yoichi Yuasa + * yyuasa@mvista.com or source@mvista.com + * + * Copyright 2001,2002 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * Changes: + * MontaVista Software Inc. or + * - Added support for NEC Hawk. + * + * MontaVista Software Inc. or + * - New creation, NEC Eagle is supported. + */ +#include +#include +#include +#include + +#include + +char arcs_cmdline[CL_SIZE]; + +const char *get_system_type(void) +{ + return "NEC Eagle/Hawk"; +} + +void __init prom_init(int argc, char **argv, unsigned long magic, int *prom_vec) +{ + int i; + + /* + * collect args and prepare cmd_line + */ + for (i = 1; i < argc; i++) { + strcat(arcs_cmdline, argv[i]); + if (i < (argc - 1)) + strcat(arcs_cmdline, " "); + } + + mips_machgroup = MACH_GROUP_NEC_VR41XX; + mips_machtype = MACH_NEC_EAGLE; +} + +void __init prom_free_prom_memory (void) +{ +} diff -Nru a/arch/mips/vr41xx/nec-eagle/irq.c b/arch/mips/vr41xx/nec-eagle/irq.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/nec-eagle/irq.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,183 @@ +/* + * FILE NAME + * arch/mips/vr41xx/nec-eagle/irq.c + * + * BRIEF MODULE DESCRIPTION + * Interrupt routines for the NEC Eagle/Hawk board. + * + * Author: Yoichi Yuasa + * yyuasa@mvista.com or source@mvista.com + * + * Copyright 2002 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * Changes: + * MontaVista Software Inc. or + * - Added support for NEC Hawk. + * + * MontaVista Software Inc. or + * - New creation, NEC Eagle is supported. + */ +#include +#include + +#include +#include + +static void enable_pciint_irq(unsigned int irq) +{ + u8 val; + + val = readb(NEC_EAGLE_PCIINTMSKREG); + val |= (u8)1 << (irq - PCIINT_IRQ_BASE); + writeb(val, NEC_EAGLE_PCIINTMSKREG); +} + +static void disable_pciint_irq(unsigned int irq) +{ + u8 val; + + val = readb(NEC_EAGLE_PCIINTMSKREG); + val &= ~((u8)1 << (irq - PCIINT_IRQ_BASE)); + writeb(val, NEC_EAGLE_PCIINTMSKREG); +} + +static unsigned int startup_pciint_irq(unsigned int irq) +{ + enable_pciint_irq(irq); + return 0; /* never anything pending */ +} + +#define shutdown_pciint_irq disable_pciint_irq +#define ack_pciint_irq disable_pciint_irq + +static void end_pciint_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + enable_pciint_irq(irq); +} + +static struct hw_interrupt_type pciint_irq_type = { + "PCIINT", + startup_pciint_irq, + shutdown_pciint_irq, + enable_pciint_irq, + disable_pciint_irq, + ack_pciint_irq, + end_pciint_irq, + NULL +}; + +static void enable_sdbint_irq(unsigned int irq) +{ + u8 val; + + val = readb(NEC_EAGLE_SDBINTMSK); + val |= (u8)1 << (irq - SDBINT_IRQ_BASE); + writeb(val, NEC_EAGLE_SDBINTMSK); +} + +static void disable_sdbint_irq(unsigned int irq) +{ + u8 val; + + val = readb(NEC_EAGLE_SDBINTMSK); + val &= ~((u8)1 << (irq - SDBINT_IRQ_BASE)); + writeb(val, NEC_EAGLE_SDBINTMSK); +} + +static unsigned int startup_sdbint_irq(unsigned int irq) +{ + enable_sdbint_irq(irq); + return 0; /* never anything pending */ +} + +#define shutdown_sdbint_irq disable_sdbint_irq +#define ack_sdbint_irq disable_sdbint_irq + +static void end_sdbint_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + enable_sdbint_irq(irq); +} + +static struct hw_interrupt_type sdbint_irq_type = { + "SDBINT", + startup_sdbint_irq, + shutdown_sdbint_irq, + enable_sdbint_irq, + disable_sdbint_irq, + ack_sdbint_irq, + end_sdbint_irq, + NULL +}; + +static int eagle_get_irq_number(int irq) +{ + u8 sdbint, pciint; + int i; + + sdbint = readb(NEC_EAGLE_SDBINT); + sdbint &= (NEC_EAGLE_SDBINT_DEG | NEC_EAGLE_SDBINT_ENUM | + NEC_EAGLE_SDBINT_SIO1INT | NEC_EAGLE_SDBINT_SIO2INT | + NEC_EAGLE_SDBINT_PARINT); + pciint = readb(NEC_EAGLE_PCIINTREG); + pciint &= (NEC_EAGLE_PCIINT_CP_INTA | NEC_EAGLE_PCIINT_CP_INTB | + NEC_EAGLE_PCIINT_CP_INTC | NEC_EAGLE_PCIINT_CP_INTD | + NEC_EAGLE_PCIINT_LANINT); + + for (i = 1; i < 6; i++) + if (sdbint & (0x01 << i)) + return SDBINT_IRQ_BASE + i; + + for (i = 0; i < 5; i++) + if (pciint & (0x01 << i)) + return PCIINT_IRQ_BASE + i; + + return -EINVAL; +} + +void __init eagle_irq_init(void) +{ + int i; + + writeb(0, NEC_EAGLE_SDBINTMSK); + writeb(0, NEC_EAGLE_PCIINTMSKREG); + + vr41xx_set_irq_trigger(PCISLOT_PIN, TRIGGER_LEVEL, SIGNAL_THROUGH); + vr41xx_set_irq_level(PCISLOT_PIN, LEVEL_HIGH); + + vr41xx_set_irq_trigger(FPGA_PIN, TRIGGER_LEVEL, SIGNAL_THROUGH); + vr41xx_set_irq_level(FPGA_PIN, LEVEL_HIGH); + + vr41xx_set_irq_trigger(DCD_PIN, TRIGGER_EDGE, SIGNAL_HOLD); + vr41xx_set_irq_level(DCD_PIN, LEVEL_LOW); + + for (i = SDBINT_IRQ_BASE; i <= SDBINT_IRQ_LAST; i++) + irq_desc[i].handler = &sdbint_irq_type; + + for (i = PCIINT_IRQ_BASE; i <= PCIINT_IRQ_LAST; i++) + irq_desc[i].handler = &pciint_irq_type; + + vr41xx_cascade_irq(FPGA_CASCADE_IRQ, eagle_get_irq_number); +} diff -Nru a/arch/mips/vr41xx/nec-eagle/setup.c b/arch/mips/vr41xx/nec-eagle/setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/nec-eagle/setup.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,162 @@ +/* + * FILE NAME + * arch/mips/vr41xx/nec-eagle/setup.c + * + * BRIEF MODULE DESCRIPTION + * Setup for the NEC Eagle/Hawk board. + * + * Author: Yoichi Yuasa + * yyuasa@mvista.com or source@mvista.com + * + * Copyright 2001,2002 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* + * Changes: + * MontaVista Software Inc. or + * - Moved mips_pci_channels[] from arch/mips/vr41xx/vr4122/eagle/setup.c. + * - Added support for NEC Hawk. + * + * MontaVista Software Inc. or + * - New creation, NEC Eagle is supported. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifdef CONFIG_BLK_DEV_INITRD +extern unsigned long initrd_start, initrd_end; +extern void * __rd_start, * __rd_end; +#endif + +#ifdef CONFIG_BLK_DEV_IDE +extern struct ide_ops eagle_ide_ops; +#endif + +extern void eagle_irq_init(void); + +#ifdef CONFIG_PCI + +extern void vrc4173_preinit(void); + +static struct resource vr41xx_pci_io_resource = { + "PCI I/O space", + VR41XX_PCI_IO_START, + VR41XX_PCI_IO_END, + IORESOURCE_IO +}; + +static struct resource vr41xx_pci_mem_resource = { + "PCI memory space", + VR41XX_PCI_MEM_START, + VR41XX_PCI_MEM_END, + IORESOURCE_MEM +}; + +extern struct pci_ops vr41xx_pci_ops; + +struct pci_channel mips_pci_channels[] = { + {&vr41xx_pci_ops, &vr41xx_pci_io_resource, &vr41xx_pci_mem_resource, 0, 256}, + {NULL, NULL, NULL, 0, 0} +}; + +struct vr41xx_pci_address_space vr41xx_pci_mem1 = { + VR41XX_PCI_MEM1_BASE, + VR41XX_PCI_MEM1_MASK, + IO_MEM1_RESOURCE_START +}; + +struct vr41xx_pci_address_space vr41xx_pci_mem2 = { + VR41XX_PCI_MEM2_BASE, + VR41XX_PCI_MEM2_MASK, + IO_MEM2_RESOURCE_START +}; + +struct vr41xx_pci_address_space vr41xx_pci_io = { + VR41XX_PCI_IO_BASE, + VR41XX_PCI_IO_MASK, + IO_PORT_RESOURCE_START +}; + +static struct vr41xx_pci_address_map pci_address_map = { + &vr41xx_pci_mem1, + &vr41xx_pci_mem2, + &vr41xx_pci_io +}; +#endif + +void __init nec_eagle_setup(void) +{ + set_io_port_base(IO_PORT_BASE); + ioport_resource.start = IO_PORT_RESOURCE_START; + ioport_resource.end = IO_PORT_RESOURCE_END; + iomem_resource.start = IO_MEM1_RESOURCE_START; + iomem_resource.end = IO_MEM2_RESOURCE_END; + +#ifdef CONFIG_BLK_DEV_INITRD + ROOT_DEV = Root_RAM0; + initrd_start = (unsigned long)&__rd_start; + initrd_end = (unsigned long)&__rd_end; +#endif + + _machine_restart = vr41xx_restart; + _machine_halt = vr41xx_halt; + _machine_power_off = vr41xx_power_off; + + board_time_init = vr41xx_time_init; + board_timer_setup = vr41xx_timer_setup; + + board_irq_init = eagle_irq_init; + +#ifdef CONFIG_FB + conswitchp = &dummy_con; +#endif + +#ifdef CONFIG_BLK_DEV_IDE + ide_ops = &eagle_ide_ops; +#endif + + vr41xx_bcu_init(); + + vr41xx_cmu_init(0); + +#ifdef CONFIG_SERIAL_8250 + vr41xx_dsiu_init(); + vr41xx_siu_init(SIU_RS232C, 0); +#endif + +#ifdef CONFIG_PCI + vr41xx_pciu_init(&pci_address_map); + + vrc4173_preinit(); +#endif +} diff -Nru a/arch/mips/vr41xx/tanbac-tb0226/Makefile b/arch/mips/vr41xx/tanbac-tb0226/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/tanbac-tb0226/Makefile Tue Jul 1 18:44:40 2003 @@ -0,0 +1,5 @@ +# +# Makefile for the TANBAC TB0226 specific parts of the kernel +# + +obj-y += init.o setup.o diff -Nru a/arch/mips/vr41xx/tanbac-tb0226/init.c b/arch/mips/vr41xx/tanbac-tb0226/init.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/tanbac-tb0226/init.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,64 @@ +/* + * FILE NAME + * arch/mips/vr41xx/tanbac-tb0226/init.c + * + * BRIEF MODULE DESCRIPTION + * Initialisation code for the TANBAC TB0226. + * + * Copyright 2002,2003 Yoichi Yuasa + * yuasa@hh.iij4u.or.jp + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include +#include + +#include +#include +#include +#include + +char arcs_cmdline[CL_SIZE]; + +const char *get_system_type(void) +{ + return "TANBAC TB0226"; +} + +void __init prom_init(int argc, char **argv, unsigned long magic, int *prom_vec) +{ + u32 config; + int i; + + /* + * collect args and prepare cmd_line + */ + for (i = 1; i < argc; i++) { + strcat(arcs_cmdline, argv[i]); + if (i < (argc - 1)) + strcat(arcs_cmdline, " "); + } + + mips_machgroup = MACH_GROUP_NEC_VR41XX; + mips_machtype = MACH_TANBAC_TB0226; + + switch (current_cpu_data.processor_id) { + case PRID_VR4131_REV1_2: + config = read_c0_config(); + config &= ~0x00000030UL; + config |= 0x00410000UL; + write_c0_config(config); + break; + default: + break; + } +} + +void __init prom_free_prom_memory (void) +{ +} diff -Nru a/arch/mips/vr41xx/tanbac-tb0226/setup.c b/arch/mips/vr41xx/tanbac-tb0226/setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/tanbac-tb0226/setup.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,121 @@ +/* + * FILE NAME + * arch/mips/vr41xx/tanbac-tb0226/setup.c + * + * BRIEF MODULE DESCRIPTION + * Setup for the TANBAC TB0226. + * + * Copyright 2002,2003 Yoichi Yuasa + * yuasa@hh.iij4u.or.jp + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifdef CONFIG_BLK_DEV_INITRD +extern unsigned long initrd_start, initrd_end; +extern void * __rd_start, * __rd_end; +#endif + +#ifdef CONFIG_PCI +static struct resource vr41xx_pci_io_resource = { + .name = "PCI I/O space", + .start = VR41XX_PCI_IO_START, + .end = VR41XX_PCI_IO_END, + .flags = IORESOURCE_IO, +}; + +static struct resource vr41xx_pci_mem_resource = { + .name = "PCI memory space", + .start = VR41XX_PCI_MEM_START, + .end = VR41XX_PCI_MEM_END, + .flags = IORESOURCE_MEM, +}; + +extern struct pci_ops vr41xx_pci_ops; + +struct pci_channel mips_pci_channels[] = { + { .pci_ops = &vr41xx_pci_ops, + .io_resource = &vr41xx_pci_io_resource, + .mem_resource = &vr41xx_pci_mem_resource, + .first_devfn = 0, + .last_devfn = 256, }, + { .pci_ops = NULL, + .io_resource = NULL, + .mem_resource = NULL, + .first_devfn = 0, + .last_devfn = 0, }, +}; + +struct vr41xx_pci_address_space vr41xx_pci_mem1 = { + .internal_base = VR41XX_PCI_MEM1_BASE, + .address_mask = VR41XX_PCI_MEM1_MASK, + .pci_base = IO_MEM1_RESOURCE_START, +}; + +struct vr41xx_pci_address_space vr41xx_pci_mem2 = { + .internal_base = VR41XX_PCI_MEM2_BASE, + .address_mask = VR41XX_PCI_MEM2_MASK, + .pci_base = IO_MEM2_RESOURCE_START, +}; + +struct vr41xx_pci_address_space vr41xx_pci_io = { + .internal_base = VR41XX_PCI_IO_BASE, + .address_mask = VR41XX_PCI_IO_MASK, + .pci_base = IO_PORT_RESOURCE_START, +}; + +static struct vr41xx_pci_address_map pci_address_map = { + .mem1 = &vr41xx_pci_mem1, + .mem2 = &vr41xx_pci_mem2, + .io = &vr41xx_pci_io, +}; +#endif + +void __init tanbac_tb0226_setup(void) +{ + set_io_port_base(IO_PORT_BASE); + ioport_resource.start = IO_PORT_RESOURCE_START; + ioport_resource.end = IO_PORT_RESOURCE_END; + iomem_resource.start = IO_MEM1_RESOURCE_START; + iomem_resource.end = IO_MEM2_RESOURCE_END; + +#ifdef CONFIG_BLK_DEV_INITRD + ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); + initrd_start = (unsigned long)&__rd_start; + initrd_end = (unsigned long)&__rd_end; +#endif + + _machine_restart = vr41xx_restart; + _machine_halt = vr41xx_halt; + _machine_power_off = vr41xx_power_off; + + board_time_init = vr41xx_time_init; + board_timer_setup = vr41xx_timer_setup; + +#ifdef CONFIG_FB + conswitchp = &dummy_con; +#endif + + vr41xx_bcu_init(); + + vr41xx_cmu_init(0); + + vr41xx_siu_init(SIU_RS232C, 0); + +#ifdef CONFIG_PCI + vr41xx_pciu_init(&pci_address_map); +#endif +} diff -Nru a/arch/mips/vr41xx/tanbac-tb0229/Makefile b/arch/mips/vr41xx/tanbac-tb0229/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/tanbac-tb0229/Makefile Tue Jul 1 18:44:40 2003 @@ -0,0 +1,5 @@ +# +# Makefile for the TANBAC TB0229(VR4131DIMM) specific parts of the kernel +# + +obj-y := init.o reboot.o setup.o diff -Nru a/arch/mips/vr41xx/tanbac-tb0229/init.c b/arch/mips/vr41xx/tanbac-tb0229/init.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/tanbac-tb0229/init.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,69 @@ +/* + * FILE NAME + * arch/mips/vr41xx/tanbac-tb0229/init.c + * + * BRIEF MODULE DESCRIPTION + * Initialisation code for the TANBAC TB0229(VR4131DIMM) + * + * Copyright 2002,2003 Yoichi Yuasa + * yuasa@hh.iij4u.or.jp + * + * Modified for TANBAC TB0229: + * Copyright 2003 Megasolution Inc. + * matsu@megasolution.jp + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +char arcs_cmdline[CL_SIZE]; + +const char *get_system_type(void) +{ + return "TANBAC TB0229"; +} + +void __init prom_init(int argc, char **argv, unsigned long magic, int *prom_vec) +{ + u32 config; + int i; + + /* + * collect args and prepare cmd_line + */ + for (i = 1; i < argc; i++) { + strcat(arcs_cmdline, argv[i]); + if (i < (argc - 1)) + strcat(arcs_cmdline, " "); + } + + mips_machgroup = MACH_GROUP_NEC_VR41XX; + mips_machtype = MACH_TANBAC_TB0229; + + switch (current_cpu_data.processor_id) { + case PRID_VR4131_REV1_2: + config = read_c0_config(); + config &= ~0x00000030UL; + config |= 0x00410000UL; + write_c0_config(config); + break; + default: + break; + } +} + +void __init prom_free_prom_memory (void) +{ +} diff -Nru a/arch/mips/vr41xx/tanbac-tb0229/reboot.c b/arch/mips/vr41xx/tanbac-tb0229/reboot.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/tanbac-tb0229/reboot.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,30 @@ +/* + * FILE NAME + * arch/mips/vr41xx/tanbac-tb0229/reboot.c + * + * BRIEF MODULE DESCRIPTION + * Depending on TANBAC TB0229(VR4131DIMM) of reboot system call. + * + * Copyright 2003 Megasolution Inc. + * matsu@megasolution.jp + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include + +#define tb0229_hard_reset() writew(0, TB0219_RESET_REGS) + +void tanbac_tb0229_restart(char *command) +{ +#ifdef CONFIG_TANBAC_TB0219 + local_irq_disable(); + tb0229_hard_reset(); + while (1); +#else + vr41xx_restart(command); +#endif +} diff -Nru a/arch/mips/vr41xx/tanbac-tb0229/setup.c b/arch/mips/vr41xx/tanbac-tb0229/setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/tanbac-tb0229/setup.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,127 @@ +/* + * FILE NAME + * arch/mips/vr41xx/tanbac-tb0229/setup.c + * + * BRIEF MODULE DESCRIPTION + * Setup for the TANBAC TB0229 (VR4131DIMM) + * + * Copyright 2002,2003 Yoichi Yuasa + * yuasa@hh.iij4u.or.jp + * + * Modified for TANBAC TB0229: + * Copyright 2003 Megasolution Inc. + * matsu@megasolution.jp + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifdef CONFIG_BLK_DEV_INITRD +extern void * __rd_start, * __rd_end; +#endif + +#ifdef CONFIG_PCI +static struct resource vr41xx_pci_io_resource = { + .name = "PCI I/O space", + .start = VR41XX_PCI_IO_START, + .end = VR41XX_PCI_IO_END, + .flags = IORESOURCE_IO, +}; + +static struct resource vr41xx_pci_mem_resource = { + .name = "PCI memory space", + .start = VR41XX_PCI_MEM_START, + .end = VR41XX_PCI_MEM_END, + .flags = IORESOURCE_MEM, +}; + +extern struct pci_ops vr41xx_pci_ops; + +struct pci_channel mips_pci_channels[] = { + { .pci_ops = &vr41xx_pci_ops, + .io_resource = &vr41xx_pci_io_resource, + .mem_resource = &vr41xx_pci_mem_resource, + .first_devfn = 0, + .last_devfn = 256, }, + { .pci_ops = NULL, + .io_resource = NULL, + .mem_resource = NULL, + .first_devfn = 0, + .last_devfn = 0, } +}; + +struct vr41xx_pci_address_space vr41xx_pci_mem1 = { + .internal_base = VR41XX_PCI_MEM1_BASE, + .address_mask = VR41XX_PCI_MEM1_MASK, + .pci_base = IO_MEM1_RESOURCE_START, +}; + +struct vr41xx_pci_address_space vr41xx_pci_mem2 = { + .internal_base = VR41XX_PCI_MEM2_BASE, + .address_mask = VR41XX_PCI_MEM2_MASK, + .pci_base = IO_MEM2_RESOURCE_START, +}; + +struct vr41xx_pci_address_space vr41xx_pci_io = { + .internal_base = VR41XX_PCI_IO_BASE, + .address_mask = VR41XX_PCI_IO_MASK, + .pci_base = IO_PORT_RESOURCE_START +}; + +static struct vr41xx_pci_address_map pci_address_map = { + .mem1 = &vr41xx_pci_mem1, + .mem2 = &vr41xx_pci_mem2, + .io = &vr41xx_pci_io, +}; +#endif + +void __init tanbac_tb0229_setup(void) +{ + set_io_port_base(IO_PORT_BASE); + ioport_resource.start = IO_PORT_RESOURCE_START; + ioport_resource.end = IO_PORT_RESOURCE_END; + iomem_resource.start = IO_MEM1_RESOURCE_START; + iomem_resource.end = IO_MEM2_RESOURCE_END; + +#ifdef CONFIG_BLK_DEV_INITRD + ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); + initrd_start = (unsigned long)&__rd_start; + initrd_end = (unsigned long)&__rd_end; +#endif + + _machine_restart = tanbac_tb0229_restart; + _machine_halt = vr41xx_halt; + _machine_power_off = vr41xx_power_off; + + board_time_init = vr41xx_time_init; + board_timer_setup = vr41xx_timer_setup; + +#ifdef CONFIG_FB + conswitchp = &dummy_con; +#endif + + vr41xx_bcu_init(); + + vr41xx_cmu_init(0); + + vr41xx_siu_init(SIU_RS232C, 0); + vr41xx_dsiu_init(); + +#ifdef CONFIG_PCI + vr41xx_pciu_init(&pci_address_map); +#endif +} + diff -Nru a/arch/mips/vr41xx/victor-mpc30x/Makefile b/arch/mips/vr41xx/victor-mpc30x/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/victor-mpc30x/Makefile Tue Jul 1 18:44:40 2003 @@ -0,0 +1,6 @@ +# +# Makefile for the Victor MP-C303/304 specific parts of the kernel +# + +obj-y += init.o setup.o +obj-$(CONFIG_IDE) += ide-mpc30x.o diff -Nru a/arch/mips/vr41xx/victor-mpc30x/ide-mpc30x.c b/arch/mips/vr41xx/victor-mpc30x/ide-mpc30x.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/victor-mpc30x/ide-mpc30x.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,91 @@ +/* + * 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. + * + * IDE routines for typical pc-like standard configurations + * for the ZAO Networks Capcella. + * + * Copyright (C) 1998, 1999, 2001 by Ralf Baechle + */ +/* + * Changes: + * Yoichi Yuasa Fri, 23 Aug 2002 + * - Added Victor MP-C303/304 support. + */ +#include +#include +#include +#include +#include +#include + +static int mpc30x_ide_default_irq(ide_ioreg_t base) +{ + return 0; +} + +static ide_ioreg_t mpc30x_ide_default_io_base(int index) +{ + return 0; +} + +static void mpc30x_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, + ide_ioreg_t ctrl_port, int *irq) +{ + ide_ioreg_t reg = data_port; + int i; + + for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { + hw->io_ports[i] = reg; + reg += 1; + } + if (ctrl_port) { + hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port; + } else { + hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206; + } + if (irq != NULL) + *irq = 0; + hw->io_ports[IDE_IRQ_OFFSET] = 0; +} + +static int mpc30x_ide_request_irq(unsigned int irq, + void (*handler)(int,void *, struct pt_regs *), + unsigned long flags, const char *device, + void *dev_id) +{ + return request_irq(irq, handler, flags, device, dev_id); +} + +static void mpc30x_ide_free_irq(unsigned int irq, void *dev_id) +{ + free_irq(irq, dev_id); +} + +static int mpc30x_ide_check_region(ide_ioreg_t from, unsigned int extent) +{ + return check_region(from, extent); +} + +static void mpc30x_ide_request_region(ide_ioreg_t from, unsigned int extent, + const char *name) +{ + request_region(from, extent, name); +} + +static void mpc30x_ide_release_region(ide_ioreg_t from, unsigned int extent) +{ + release_region(from, extent); +} + +struct ide_ops mpc30x_ide_ops = { + &mpc30x_ide_default_irq, + &mpc30x_ide_default_io_base, + &mpc30x_ide_init_hwif_ports, + &mpc30x_ide_request_irq, + &mpc30x_ide_free_irq, + &mpc30x_ide_check_region, + &mpc30x_ide_request_region, + &mpc30x_ide_release_region +}; diff -Nru a/arch/mips/vr41xx/victor-mpc30x/init.c b/arch/mips/vr41xx/victor-mpc30x/init.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/victor-mpc30x/init.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,54 @@ +/* + * FILE NAME + * arch/mips/vr41xx/victor-mpc30x/init.c + * + * BRIEF MODULE DESCRIPTION + * Initialisation code for the Victor MP-C303/304. + * + * Copyright 2002 Yoichi Yuasa + * yuasa@hh.iij4u.or.jp + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include +#include + +#include +#include +#include +#include + +char arcs_cmdline[CL_SIZE]; + +const char *get_system_type(void) +{ + return "Victor MP-C303/304"; +} + +void __init prom_init(int argc, char **argv, unsigned long magic, int *prom_vec) +{ + int i; + + /* + * collect args and prepare cmd_line + */ + for (i = 1; i < argc; i++) { + strcat(arcs_cmdline, argv[i]); + if (i < (argc - 1)) + strcat(arcs_cmdline, " "); + } + + mips_machgroup = MACH_GROUP_NEC_VR41XX; + mips_machtype = MACH_VICTOR_MPC30X; + + add_memory_region(0, 32 << 20, BOOT_MEM_RAM); +} + +void __init prom_free_prom_memory (void) +{ +} diff -Nru a/arch/mips/vr41xx/victor-mpc30x/setup.c b/arch/mips/vr41xx/victor-mpc30x/setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/victor-mpc30x/setup.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,126 @@ +/* + * FILE NAME + * arch/mips/vr41xx/victor-mpc30x/setup.c + * + * BRIEF MODULE DESCRIPTION + * Setup for the Victor MP-C303/304. + * + * Copyright 2002 Yoichi Yuasa + * yuasa@hh.iij4u.or.jp + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifdef CONFIG_BLK_DEV_INITRD +extern unsigned long initrd_start, initrd_end; +extern void * __rd_start, * __rd_end; +#endif + +#ifdef CONFIG_BLK_DEV_IDE +extern struct ide_ops mpc30x_ide_ops; +#endif + +#ifdef CONFIG_PCI +static struct resource vr41xx_pci_io_resource = { + "PCI I/O space", + VR41XX_PCI_IO_START, + VR41XX_PCI_IO_END, + IORESOURCE_IO +}; + +static struct resource vr41xx_pci_mem_resource = { + "PCI memory space", + VR41XX_PCI_MEM_START, + VR41XX_PCI_MEM_END, + IORESOURCE_MEM +}; + +extern struct pci_ops vr41xx_pci_ops; + +struct pci_channel mips_pci_channels[] = { + {&vr41xx_pci_ops, &vr41xx_pci_io_resource, &vr41xx_pci_mem_resource, 0, 256}, + {NULL, NULL, NULL, 0, 0} +}; + +struct vr41xx_pci_address_space vr41xx_pci_mem1 = { + VR41XX_PCI_MEM1_BASE, + VR41XX_PCI_MEM1_MASK, + IO_MEM1_RESOURCE_START +}; + +struct vr41xx_pci_address_space vr41xx_pci_mem2 = { + VR41XX_PCI_MEM2_BASE, + VR41XX_PCI_MEM2_MASK, + IO_MEM2_RESOURCE_START +}; + +struct vr41xx_pci_address_space vr41xx_pci_io = { + VR41XX_PCI_IO_BASE, + VR41XX_PCI_IO_MASK, + IO_PORT_RESOURCE_START +}; + +static struct vr41xx_pci_address_map pci_address_map = { + &vr41xx_pci_mem1, + &vr41xx_pci_mem2, + &vr41xx_pci_io +}; +#endif + +void __init victor_mpc30x_setup(void) +{ + set_io_port_base(IO_PORT_BASE); + ioport_resource.start = IO_PORT_RESOURCE_START; + ioport_resource.end = IO_PORT_RESOURCE_END; + iomem_resource.start = IO_MEM1_RESOURCE_START; + iomem_resource.end = IO_MEM2_RESOURCE_END; + +#ifdef CONFIG_BLK_DEV_INITRD + ROOT_DEV = Root_RAM0; + initrd_start = (unsigned long)&__rd_start; + initrd_end = (unsigned long)&__rd_end; +#endif + + _machine_restart = vr41xx_restart; + _machine_halt = vr41xx_halt; + _machine_power_off = vr41xx_power_off; + + board_time_init = vr41xx_time_init; + board_timer_setup = vr41xx_timer_setup; + +#ifdef CONFIG_FB + conswitchp = &dummy_con; +#endif + +#ifdef CONFIG_BLK_DEV_IDE + ide_ops = &mpc30x_ide_ops; +#endif + + vr41xx_bcu_init(); + + vr41xx_cmu_init(0); + +#ifdef CONFIG_SERIAL_8250 + vr41xx_siu_init(SIU_RS232C, 0); +#endif + +#ifdef CONFIG_PCI + vr41xx_pciu_init(&pci_address_map); +#endif +} diff -Nru a/arch/mips/vr41xx/zao-capcella/Makefile b/arch/mips/vr41xx/zao-capcella/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/zao-capcella/Makefile Tue Jul 1 18:44:40 2003 @@ -0,0 +1,6 @@ +# +# Makefile for the ZAO Networks Capcella specific parts of the kernel +# + +obj-y += init.o setup.o +obj-$(CONFIG_IDE) += ide-capcella.o diff -Nru a/arch/mips/vr41xx/zao-capcella/ide-capcella.c b/arch/mips/vr41xx/zao-capcella/ide-capcella.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/zao-capcella/ide-capcella.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,99 @@ +/* + * 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. + * + * IDE routines for typical pc-like standard configurations + * for the ZAO Networks Capcella. + * + * Copyright (C) 1998, 1999, 2001 by Ralf Baechle + */ +/* + * Changes: + * Yoichi Yuasa Sun, 24 Feb 2002 + * - Added ZAO Networks Capcella support. + */ +#include +#include +#include +#include +#include +#include + +static int capcella_ide_default_irq(ide_ioreg_t base) +{ + switch (base) { + case 0x8300: return 42; + } + + return 0; +} + +static ide_ioreg_t capcella_ide_default_io_base(int index) +{ + switch (index) { + case 0: return 0x8300; + } + + return 0; +} + +static void capcella_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, + ide_ioreg_t ctrl_port, int *irq) +{ + ide_ioreg_t reg = data_port; + int i; + + for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { + hw->io_ports[i] = reg; + reg += 1; + } + if (ctrl_port) { + hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port; + } else { + hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206; + } + if (irq != NULL) + *irq = 0; + hw->io_ports[IDE_IRQ_OFFSET] = 0; +} + +static int capcella_ide_request_irq(unsigned int irq, + void (*handler)(int,void *, struct pt_regs *), + unsigned long flags, const char *device, + void *dev_id) +{ + return request_irq(irq, handler, flags, device, dev_id); +} + +static void capcella_ide_free_irq(unsigned int irq, void *dev_id) +{ + free_irq(irq, dev_id); +} + +static int capcella_ide_check_region(ide_ioreg_t from, unsigned int extent) +{ + return check_region(from, extent); +} + +static void capcella_ide_request_region(ide_ioreg_t from, unsigned int extent, + const char *name) +{ + request_region(from, extent, name); +} + +static void capcella_ide_release_region(ide_ioreg_t from, unsigned int extent) +{ + release_region(from, extent); +} + +struct ide_ops capcella_ide_ops = { + &capcella_ide_default_irq, + &capcella_ide_default_io_base, + &capcella_ide_init_hwif_ports, + &capcella_ide_request_irq, + &capcella_ide_free_irq, + &capcella_ide_check_region, + &capcella_ide_request_region, + &capcella_ide_release_region +}; diff -Nru a/arch/mips/vr41xx/zao-capcella/init.c b/arch/mips/vr41xx/zao-capcella/init.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/zao-capcella/init.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,64 @@ +/* + * FILE NAME + * arch/mips/vr41xx/zao-capcella/init.c + * + * BRIEF MODULE DESCRIPTION + * Initialisation code for the ZAO Networks Capcella. + * + * Copyright 2002 Yoichi Yuasa + * yuasa@hh.iij4u.or.jp + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include +#include + +#include +#include +#include +#include + +char arcs_cmdline[CL_SIZE]; + +const char *get_system_type(void) +{ + return "ZAO Networks Capcella"; +} + +void __init prom_init(int argc, char **argv, unsigned long magic, int *prom_vec) +{ + u32 config; + int i; + + /* + * collect args and prepare cmd_line + */ + for (i = 1; i < argc; i++) { + strcat(arcs_cmdline, argv[i]); + if (i < (argc - 1)) + strcat(arcs_cmdline, " "); + } + + mips_machgroup = MACH_GROUP_NEC_VR41XX; + mips_machtype = MACH_ZAO_CAPCELLA; + + switch (current_cpu_data.processor_id) { + case PRID_VR4131_REV1_2: + config = read_c0_config(); + config &= ~0x00000030UL; + config |= 0x00410000UL; + write_c0_config(config); + break; + default: + break; + } +} + +void __init prom_free_prom_memory (void) +{ +} diff -Nru a/arch/mips/vr41xx/zao-capcella/setup.c b/arch/mips/vr41xx/zao-capcella/setup.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips/vr41xx/zao-capcella/setup.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,127 @@ +/* + * FILE NAME + * arch/mips/vr41xx/zao-capcella/setup.c + * + * BRIEF MODULE DESCRIPTION + * Setup for the ZAO Networks Capcella. + * + * Copyright 2002 Yoichi Yuasa + * yuasa@hh.iij4u.or.jp + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifdef CONFIG_BLK_DEV_INITRD +extern unsigned long initrd_start, initrd_end; +extern void * __rd_start, * __rd_end; +#endif + +#ifdef CONFIG_BLK_DEV_IDE +extern struct ide_ops capcella_ide_ops; +#endif + +#ifdef CONFIG_PCI +static struct resource vr41xx_pci_io_resource = { + "PCI I/O space", + VR41XX_PCI_IO_START, + VR41XX_PCI_IO_END, + IORESOURCE_IO +}; + +static struct resource vr41xx_pci_mem_resource = { + "PCI memory space", + VR41XX_PCI_MEM_START, + VR41XX_PCI_MEM_END, + IORESOURCE_MEM +}; + +extern struct pci_ops vr41xx_pci_ops; + +struct pci_channel mips_pci_channels[] = { + {&vr41xx_pci_ops, &vr41xx_pci_io_resource, &vr41xx_pci_mem_resource, 0, 256}, + {NULL, NULL, NULL, 0, 0} +}; + +struct vr41xx_pci_address_space vr41xx_pci_mem1 = { + VR41XX_PCI_MEM1_BASE, + VR41XX_PCI_MEM1_MASK, + IO_MEM1_RESOURCE_START +}; + +struct vr41xx_pci_address_space vr41xx_pci_mem2 = { + VR41XX_PCI_MEM2_BASE, + VR41XX_PCI_MEM2_MASK, + IO_MEM2_RESOURCE_START +}; + +struct vr41xx_pci_address_space vr41xx_pci_io = { + VR41XX_PCI_IO_BASE, + VR41XX_PCI_IO_MASK, + IO_PORT_RESOURCE_START +}; + +static struct vr41xx_pci_address_map pci_address_map = { + &vr41xx_pci_mem1, + &vr41xx_pci_mem2, + &vr41xx_pci_io +}; +#endif + +void __init zao_capcella_setup(void) +{ + set_io_port_base(IO_PORT_BASE); + ioport_resource.start = IO_PORT_RESOURCE_START; + ioport_resource.end = IO_PORT_RESOURCE_END; + iomem_resource.start = IO_MEM1_RESOURCE_START; + iomem_resource.end = IO_MEM2_RESOURCE_END; + +#ifdef CONFIG_BLK_DEV_INITRD + ROOT_DEV = Root_RAM0; + initrd_start = (unsigned long)&__rd_start; + initrd_end = (unsigned long)&__rd_end; +#endif + + _machine_restart = vr41xx_restart; + _machine_halt = vr41xx_halt; + _machine_power_off = vr41xx_power_off; + + board_time_init = vr41xx_time_init; + board_timer_setup = vr41xx_timer_setup; + +#ifdef CONFIG_FB + conswitchp = &dummy_con; +#endif + +#ifdef CONFIG_BLK_DEV_IDE + ide_ops = &capcella_ide_ops; +#endif + + vr41xx_bcu_init(); + + vr41xx_cmu_init(0x0102); + +#ifdef CONFIG_SERIAL_8250 + vr41xx_siu_init(SIU_RS232C, 0); + vr41xx_dsiu_init(); +#endif + +#ifdef CONFIG_PCI + vr41xx_pciu_init(&pci_address_map); +#endif +} diff -Nru a/arch/mips64/Kconfig b/arch/mips64/Kconfig --- a/arch/mips64/Kconfig Tue Jul 1 18:44:34 2003 +++ b/arch/mips64/Kconfig Tue Jul 1 18:44:34 2003 @@ -2,586 +2,16 @@ # For a description of the syntax of this configuration file, # see Documentation/kbuild/kconfig-language.txt. # - -mainmenu "Linux Kernel Configuration" - -config MIPS64 - bool - default y - -config MMU - bool - default y - -source "init/Kconfig" - - -menu "Machine selection" - -choice - prompt "Machine type" - default SGI_IP27 - -config SGI_IP22 - bool "SGI-IP22,Indy/Indigo2" - help - This are the SGI Indy, Challenge S and Indigo2, as well as certain - OEM variants like the Tandem CMN B006S. To compile a Linux kernel - that runs on these, say Y here. - -config SGI_IP27 - bool "SGI-IP27,Origin200/2000" - help - This are the SGI Origin 200, Origin 2000 and Onyx 2 Graphics - workstations. To compile a Linux kernel that runs on these, say Y - here. - -endchoice - -config SGI_SN0_N_MODE - bool "IP27 N-Mode" - depends on SGI_IP27 - help - The nodes of Origin 200, Origin 2000 and Onyx 2 systems can be - configured in either N-Modes which allows for more nodes or M-Mode - which allows for more memory. Your system is most probably - running in M-Mode, so you should say N here. - -config DISCONTIGMEM - bool "Discontiguous Memory Support" - depends on SGI_IP27 - help - Say Y to upport efficient handling of discontiguous physical memory, - for architectures which are either NUMA (Non-Uniform Memory Access) - or have huge holes in the physical address space for other reasons. - See for more. - -config NUMA - bool "NUMA Support" - depends on SGI_IP27 - help - Say Y to compile the kernel to support NUMA (Non-Uniform Memory - Access). This option is for configuring high-end multiprocessor - server machines. If in doubt, say N. - -config MAPPED_KERNEL - bool "Mapped kernel support" - depends on SGI_IP27 - help - Change the way a Linux kernel is loaded unto memory on a MIPS64 - machine. This is required in order to support text replication and - NUMA. If you need to undersatand it, read the source code. - -config REPLICATE_KTEXT - bool "Kernel text replication support" - depends on SGI_IP27 - help - Say Y here to enable replicating the kernel text across multiple - nodes in a NUMA cluster. This trades memory for speed. - -config REPLICATE_EXHANDLERS - bool "Exception handler replication support" - depends on SGI_IP27 - help - Say Y here to enable replicating the kernel exception handlers - across multiple nodes in a NUMA cluster. This trades memory for - speed. - -config SMP - bool "Multi-Processing support" - depends on SGI_IP27 - ---help--- - This enables support for systems with more than one CPU. If you have - a system with only one CPU, like most personal computers, say N. If - you have a system with more than one CPU, say Y. - - If you say N here, the kernel will run on single and multiprocessor - machines, but will use only one CPU of a multiprocessor machine. If - you say Y here, the kernel will run on many, but not all, - singleprocessor machines. On a singleprocessor machine, the kernel - will run faster if you say N here. - - Note that if you say Y here and choose architecture "586" or - "Pentium" under "Processor family", the kernel will not work on 486 - architectures. Similarly, multiprocessor kernels for the "PPro" - architecture may not work on all Pentium based boards. - - People using multiprocessor machines who say Y here should also say - Y to "Enhanced Real Time Clock Support", below. The "Advanced Power - Management" code will be disabled if you say Y here. - - See also the , - , , - and the SMP-HOWTO available at - . - - If you don't know what to do here, say N. - -#bool ' IP27 XXL' CONFIG_SGI_SN0_XXL -endmenu - -# -# Select some configuration options automatically based on user selections -# -config RWSEM_GENERIC_SPINLOCK - bool - default y - -config RWSEM_XCHGADD_ALGORITHM - bool - -config GENERIC_ISA_DMA - bool - default y - -config PCI - bool - depends on SGI_IP27 - default y - help - Find out whether you have a PCI motherboard. PCI is the name of a - bus system, i.e. the way the CPU talks to the other stuff inside - your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or - VESA. If you have PCI, say Y, otherwise N. - - The PCI-HOWTO, available from - , contains valuable - information about which PCI hardware does work under Linux and which - doesn't. - -config ISA - bool - help - Find out whether you have ISA slots on your motherboard. ISA is the - name of a bus system, i.e. the way the CPU talks to the other stuff - inside your box. Other bus systems are PCI, EISA, MicroChannel - (MCA) or VESA. ISA is an older system, now being displaced by PCI; - newer boards don't support it. If you have ISA, say Y, otherwise N. - -config EISA - bool - depends on ISA - default y - ---help--- - The Extended Industry Standard Architecture (EISA) bus was - developed as an open alternative to the IBM MicroChannel bus. - - The EISA bus provided some of the features of the IBM MicroChannel - bus while maintaining backward compatibility with cards made for - the older ISA bus. The EISA bus saw limited use between 1988 and - 1995 when it was made obsolete by the PCI bus. - - Say Y here if you are building a kernel for an EISA-based machine. - - Otherwise, say N. - -config BOOT_ELF32 - bool - depends on SGI_IP22 - default y - -config ARC32 - bool - depends on SGI_IP22 - default y - -config BOARD_SCACHE - bool - depends on SGI_IP22 - default y - -config ARC_MEMORY - bool - depends on SGI_IP22 - default y - -config SGI - bool - depends on SGI_IP22 - default y - -config L1_CACHE_SHIFT - int - default "7" if SGI_IP27 - default "5" if SGI_IP22 - -config BOOT_ELF64 - bool - depends on SGI_IP27 - default y - -config ARC64 - bool - depends on SGI_IP27 - default y - -config COHERENT_IO - bool - depends on SGI_IP27 - default y - -config MAPPED_PCI_IO - bool - depends on SGI_IP27 - default y - -config QL_ISP_A64 - bool - depends on SGI_IP27 - default y - -config MCA - bool - help - MicroChannel Architecture is found in some IBM PS/2 machines and - laptops. It is a bus system similar to PCI or ISA. See - (and especially the web page given - there) before attempting to build an MCA bus kernel. - -config SBUS - bool - - -menu "CPU selection" - -choice - prompt "CPU type" - default CPU_R4X00 - -config CPU_R4300 - bool "R4300" - help - MIPS Technologies R4300-series processors. - -config CPU_R4X00 - bool "R4x00" - help - MIPS Technologies R4000-series processors other than 4300, including - the 4640, 4650, and 4700. - -config CPU_R5000 - bool "R5000" - help - MIPS Technologies R5000-series processors other than the Nevada. - -config CPU_NEVADA - bool "R52x0" - help - MIPS Technologies R52x0-series ("Nevada") processors. - -config CPU_R8000 - bool "R8000" - help - MIPS Technologies R8000-series processors. - -config CPU_R10000 - bool "R10000" - help - MIPS Technologies R10000-series processors. - -endchoice - -endmenu - - -menu "General setup" - -config MIPS_INSANE_LARGE - bool "Support for large 64-bit configurations" - depends on CPU_R10000 - help - MIPS R10000 does support a 44 bit / 16TB address space as opposed to - previous 64-bit processors which only supported 40 bit / 1TB. If you - need processes of more than 1TB virtual address space, say Y here. - This will result in additional memory usage, so it is not - recommended for normal users. - -config CPU_LITTLE_ENDIAN - bool "Generate little endian code" - help - Some MIPS machines can be configured for either little or big endian - byte order. These modes require different kernels. Say Y if your - machine is little endian, N if it's a big endian machine. - -config MIPS_FPU_EMULATOR - bool "Kernel floating-point emulation" - depends on EXPERIMENTAL - help - This option enables the MIPS software floatingpoint support. Due to - the way floating point works you should always enable this option - unless you exactly know what you're doing. - -config HOTPLUG - bool "Support for hot-pluggable devices" - ---help--- - Say Y here if you want to plug devices into your computer while - the system is running, and be able to use them quickly. In many - cases, the devices can likewise be unplugged at any time too. - - One well known example of this is PCMCIA- or PC-cards, credit-card - size devices such as network cards, modems or hard drives which are - plugged into slots found on all modern laptop computers. Another - example, used on modern desktops as well as laptops, is USB. - - Enable HOTPLUG and KMOD, and build a modular kernel. Get agent - software (at ) and install it. - Then your kernel will automatically call out to a user mode "policy - agent" (/sbin/hotplug) to load modules and set up software needed - to use devices as you hotplug them. - -source "drivers/pcmcia/Kconfig" - -config ARC_CONSOLE - bool "ARC console support" - depends on ARC32 - -source "fs/Kconfig.binfmt" - -config MIPS32_COMPAT - bool "Kernel support for Linux/MIPS 32-bit binary compatibility" - help - Select this option if you want Linux/MIPS 32-bit binary - compatibility. Since all software available for Linux/MIPS is - currently 32-bit you should say Y here. - -config COMPAT +config MIPS bool - depends on MIPS32_COMPAT default y -config BINFMT_ELF32 +config MIPS32 bool - depends on BINFMT_ELF && MIPS32_COMPAT - default y - help - This allows you to run 32-bit Linux/ELF binaries on your Ultra. - Everybody wants this; say Y. - -endmenu - -source "drivers/pci/Kconfig" - -source "drivers/base/Kconfig" - -source "drivers/mtd/Kconfig" - -source "drivers/parport/Kconfig" - -source "drivers/block/Kconfig" - -source "drivers/md/Kconfig" - -source "drivers/ide/Kconfig" - - -menu "SCSI support" - -config SCSI - tristate "SCSI support" - ---help--- - If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or - any other SCSI device under Linux, say Y and make sure that you know - the name of your SCSI host adapter (the card inside your computer - that "speaks" the SCSI protocol, also called SCSI controller), - because you will be asked for it. - - You also need to say Y here if you want support for the parallel - port version of the 100 MB IOMEGA ZIP drive. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called scsi_mod. If you want to compile it as - a module, say M here and read and - . However, do not compile this as a - module if your root file system (the one containing the directory /) - is located on a SCSI device. - -source "drivers/scsi/Kconfig" - -endmenu - -#source drivers/message/i2o/Config.in -source "net/Kconfig" - -source "net/ax25/Kconfig" - -source "net/irda/Kconfig" + default n -source "drivers/isdn/Kconfig" - -source "drivers/telephony/Kconfig" - - -menu "Old CD-ROM drivers (not SCSI, not IDE)" - -config CD_NO_IDESCSI - bool "Support non-SCSI/IDE/ATAPI CDROM drives" - ---help--- - If you have a CD-ROM drive that is neither SCSI nor IDE/ATAPI, say Y - here, otherwise N. Read the CD-ROM-HOWTO, available from - . - - Note that the answer to this question doesn't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about these CD-ROM drives. If you are unsure what you - have, say Y and find out whether you have one of the following - drives. - - For each of these drivers, a file Documentation/cdrom/{driver_name} - exists. Especially in cases where you do not know exactly which kind - of drive you have you should read there. Most of these drivers use a - file drivers/cdrom/{driver_name}.h where you can define your - interface parameters and switch some internal goodies. - - All these CD-ROM drivers are also usable as a module ( = code which - can be inserted in and removed from the running kernel whenever you - want). If you want to compile them as module, say M instead of Y and - read . - - If you want to use any of these CD-ROM drivers, you also have to - answer Y or M to "ISO 9660 CD-ROM file system support" below (this - answer will get "defaulted" for you if you enable any of the Linux - CD-ROM drivers). - -source "drivers/cdrom/Kconfig" - -endmenu - -source "drivers/input/Kconfig" - -source "drivers/char/Kconfig" - -#source drivers/misc/Config.in -source "drivers/media/Kconfig" - -source "fs/Kconfig" - -source "drivers/video/Kconfig" - -config KCORE_ELF +config MIPS64 bool - depends on PROC_FS default y - ---help--- - If you enabled support for /proc file system then the file - /proc/kcore will contain the kernel core image. This can be used - in gdb: - - $ cd /usr/src/linux ; gdb vmlinux /proc/kcore - - You have two choices here: ELF and A.OUT. Selecting ELF will make - /proc/kcore appear in ELF core format as defined by the Executable - and Linking Format specification. Selecting A.OUT will choose the - old "a.out" format which may be necessary for some old versions - of binutils or on some architectures. - - This is especially useful if you have compiled the kernel with the - "-g" option to preserve debugging information. It is mainly used - for examining kernel data structures on the live kernel so if you - don't understand what this means or are not a kernel hacker, just - leave it at its default value ELF. - - -menu "Sound" - -config SOUND - tristate "Sound card support" - ---help--- - If you have a sound card in your computer, i.e. if it can say more - than an occasional beep, say Y. Be sure to have all the information - about your sound card and its configuration down (I/O port, - interrupt and DMA channel), because you will be asked for it. - - You want to read the Sound-HOWTO, available from - . General information about - the modular sound system is contained in the files - . The file - contains some slightly - outdated but still useful information as well. - - If you have a PnP sound card and you want to configure it at boot - time using the ISA PnP tools (read - ), then you need to - compile the sound card support as a module ( = code which can be - inserted in and removed from the running kernel whenever you want) - and load that module after the PnP configuration is finished. To do - this, say M here and read as well - as ; the module will be - called soundcore. - - I'm told that even without a sound card, you can make your computer - say more than an occasional beep, by programming the PC speaker. - Kernel patches and supporting utilities to do that are in the pcsp - package, available at . - -source "sound/Kconfig" - -endmenu - -source "drivers/sgi/Kconfig" - -source "drivers/usb/Kconfig" - - -menu "Kernel hacking" - -#bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC -config CROSSCOMPILE - bool "Are you using a crosscompiler" - help - Say Y here if you are compiling the kernel on a different - architecture than the one it is intended to run on. - -config MIPS_FPE_MODULE - bool "Build fp exception handler module" - depends on MODULES - help - Build the floating point exception handler module. This option is - only useful for people working on the floating point exception - handler. If you don't, say N. - -config REMOTE_DEBUG - bool "Remote GDB kernel debugging" - help - If you say Y here, it will be possible to remotely debug the MIPS - kernel using gdb. This enlarges your kernel image disk size by - several megabytes and requires a machine with more than 16 MB, - better 32 MB RAM to avoid excessive linking time. This is only - useful for kernel hackers. If unsure, say N. - -config MAGIC_SYSRQ - bool "Magic SysRq key" - help - If you say Y here, you will have some control over the system even - if the system crashes for example during kernel debugging (e.g., you - will be able to flush the buffer cache to disk, reboot the system - immediately or dump some status information). This is accomplished - by pressing various keys while holding SysRq (Alt+PrintScreen). It - also works on a serial console (on PC hardware at least), if you - send a BREAK and then within 5 seconds a command keypress. The - keys are documented in . Don't say Y - unless you really know what this hack does. - -config MIPS_UNCACHED - bool "Run uncached" - depends on !SMP - help - If you say Y here there kernel will disable all CPU caches. This will - reduce the system's performance dramatically but can help finding - otherwise hard to track bugs. It can also useful if you're doing - hardware debugging with a logic analyzer and need to see all traffic - on the bus. - -config NR_CPUS - int "Maximum number of CPUs (2-64)" - depends on SMP - default "64" - -endmenu - -source "security/Kconfig" - -source "crypto/Kconfig" - -source "lib/Kconfig" +source "arch/mips/Kconfig-shared" diff -Nru a/arch/mips64/Makefile b/arch/mips64/Makefile --- a/arch/mips64/Makefile Tue Jul 1 18:44:33 2003 +++ b/arch/mips64/Makefile Tue Jul 1 18:44:33 2003 @@ -3,10 +3,11 @@ # License. See the file "COPYING" in the main directory of this archive # for more details. # +# Copyright (C) 2002 Maciej W. Rozycki +# # This file is included by the global makefile so that you can add your own # architecture-specific flags and dependencies. Remember to do have actions -# for "archclean" and "archdep" for cleaning up and making dependencies for -# this architecture +# for "archclean" cleaning up for this architecture. # # @@ -14,16 +15,20 @@ # ifdef CONFIG_CPU_LITTLE_ENDIAN tool-prefix = mips64el-linux- +32bit-bfd = elf32-tradlittlemips +64bit-bfd = elf64-tradlittlemips else tool-prefix = mips64-linux- +32bit-bfd = elf32-tradbigmips +64bit-bfd = elf64-tradbigmips endif ifdef CONFIG_CROSSCOMPILE -CROSS_COMPILE = $(tool-prefix) +CROSS_COMPILE := $(tool-prefix) endif # -# The ELF GCC uses -G0 -mabicalls -fpic as default. We don't need PIC +# The ELF GCC uses -G 0 -mabicalls -fpic as default. We don't need PIC # code in the kernel since it only slows down the whole thing. For the # old GCC these options are just the defaults. At some point we might # make use of global pointer optimizations. @@ -32,117 +37,235 @@ # machines may also. Since BFD is incredibly buggy with respect to # crossformat linking we rely on the elf2ecoff tool for format conversion. # -CFLAGS += -I $(TOPDIR)/include/asm/gcc $(CFLAGS) -CFLAGS += -mabi=64 -G 0 -mno-abicalls -fno-pic -Wa,--trap -pipe -LDFLAGS_vmlinux += -G 0 -static # -N -MODFLAGS += -mlong-calls +cflags-y := -I $(TOPDIR)/include/asm/gcc +cflags-y += -mabi=64 -G 0 -mno-abicalls -fno-pic -Wa,--trap -pipe +LDFLAGS_vmlinux += -G 0 -static # -N +MODFLAGS += -mlong-calls -ifdef CONFIG_REMOTE_DEBUG -CFLAGS := $(CFLAGS) -g -endif +cflags-$(CONFIG_KGDB) += -g +cflags-$(CONFIG_SB1XXX_CORELIS) += -mno-sched-prolog -fno-omit-frame-pointer + +check_gcc = $(shell if $(AS) $(1) -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi) +check_warning = $(shell if $(CC) $(1) -c -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi) # # CPU-dependent compiler/assembler options for optimization. # -ifdef CONFIG_CPU_R4300 -CFLAGS := $(CFLAGS) -mcpu=r4300 -mips3 -endif -ifdef CONFIG_CPU_R4X00 -CFLAGS := $(CFLAGS) -mcpu=r4600 -mips3 -endif -ifdef CONFIG_CPU_R5000 -CFLAGS := $(CFLAGS) -mcpu=r8000 -mips4 +cflags-$(CONFIG_CPU_R4300) += -mcpu=r4300 -mips3 +cflags-$(CONFIG_CPU_R4X00) += -mcpu=r4600 -mips3 +cflags-$(CONFIG_CPU_R5000) += -mcpu=r8000 -mips4 +cflags-$(CONFIG_CPU_NEVADA) += -mcpu=r8000 -mips3 -mmad +cflags-$(CONFIG_CPU_RM7000) += $(call check_gcc, -mcpu=r7000, -mcpu=r5000) \ + -mips4 +cflags-$(CONFIG_CPU_SB1) += $(call check_gcc, -mcpu=sb1, -mcpu=r8000) \ + $(call check_gcc, -mips64, -mips4) +cflags-$(CONFIG_CPU_R8000) += -mcpu=r8000 -mips4 +cflags-$(CONFIG_CPU_R10000) += -mcpu=r8000 -mips4 +ifdef CONFIG_CPU_SB1 +ifdef CONFIG_SB1_PASS_1_WORKAROUNDS +MODFLAGS += -msb1-pass1-workarounds endif -ifdef CONFIG_CPU_NEVADA -CFLAGS := $(CFLAGS) -mcpu=r8000 -mips3 -mmad endif -ifdef CONFIG_CPU_R8000 -CFLAGS := $(CFLAGS) -mcpu=r8000 -mips4 -endif -ifdef CONFIG_CPU_R10000 -CFLAGS := $(CFLAGS) -mcpu=r8000 -mips4 +# Should be used then we get a MIPS64 compiler +#cflags-$(CONFIG_CPU_MIPS64) += -mips64 +cflags-$(CONFIG_CPU_MIPS64) += -mcpu=r8000 -mips4 + +# +# ramdisk/initrd support +# You need a compressed ramdisk image, named ramdisk.gz in +# arch/mips/ramdisk +# +ifdef CONFIG_EMBEDDED_RAMDISK +CORE_FILES += arch/mips/ramdisk/ramdisk.o +SUBDIRS += arch/mips/ramdisk endif -core-$(CONFIG_MIPS_FPU_EMULATOR) += arch/mips64/math-emu/ +# +# Firmware support +# +libs-$(CONFIG_ARC) += arch/mips/arc/ +libs-$(CONFIG_SIBYTE_CFE) += arch/mips/sibyte/cfe/ # # Board-dependent options and extra files # -ifdef CONFIG_SGI_IP22 -libs-y += arch/mips64/sgi-ip22/ \ - arch/mips64/arc/ -# -# Set LOADADDR to >= 0x88069000 if you want to leave space for symmon, -# 0x88004000 for production kernels. Note that the value must be -# 16kb aligned or the handling of the current variable will break. # -LOADADDR += 0x88004000 +# DECstation family +# +ifdef CONFIG_DECSTATION +CORE_FILES += arch/mips/dec/dec.o +SUBDIRS += arch/mips/dec arch/mips/dec/prom +LIBS += arch/mips/dec/prom/rexlib.a +LOADADDR := 0x80040000 endif -ifdef CONFIG_SGI_IP27 -core-y += arch/mips64/sgi-ip27/ -libs-y += arch/mips64/arc/ # -# Set LOADADDR to >= 0xc000000000300000 if you want to leave space for +# MIPS Atlas board +# +core-$(CONFIG_MIPS_BOARDS_GEN) += arch/mips/mips-boards/generic/ +core-$(CONFIG_MIPS_ATLAS) += arch/mips/mips-boards/atlas/ +load-$(CONFIG_MIPS_ATLAS) += 0x80100000 + +# +# MIPS Malta board +# +core-$(CONFIG_MIPS_MALTA) += arch/mips/mips-boards/malta/ +load-$(CONFIG_MIPS_MALTA) += 0x80100000 + +# +# MIPS SEAD board +# +core-$(CONFIG_MIPS_SEAD) += arch/mips/mips-boards/sead/ +load-$(CONFIG_MIPS_SEAD) += 0x80100000 + +# +# Momentum Ocelot board +# +# The Ocelot setup.o must be linked early - it does the ioremap() for the +# mips_io_port_base. +# +core-$(CONFIG_MOMENCO_OCELOT) += arch/mips/gt64120/common/ \ + arch/mips/gt64120/momenco_ocelot/ +load-$(CONFIG_MOMENCO_OCELOT) += 0x80100000 + +# +# Momentum Ocelot-G board +# +# The Ocelot-G setup.o must be linked early - it does the ioremap() for the +# mips_io_port_base. +# +core-$(CONFIG_MOMENCO_OCELOT_G) += arch/mips/momentum/ocelot_g/ +load-$(CONFIG_MOMENCO_OCELOT_G) += 0x80100000 + +# +# Momentum Ocelot-C and -CS boards +# +# The Ocelot-C[S] setup.o must be linked early - it does the ioremap() for the +# mips_io_port_base. +core-$(CONFIG_MOMENCO_OCELOT_C) += arch/mips/momentum/ocelot_c/ +load-$(CONFIG_MOMENCO_OCELOT_C) += 0x80100000 + +# +# SGI IP22 (Indy/Indigo2) +# +# Set the load address to >= 0x88069000 if you want to leave space for symmon, +# 0x88004000 for production kernels. Note that the value must be 16kb aligned +# or the handling of the current variable will break. +# +core-$(CONFIG_SGI_IP22) += arch/mips/sgi-ip22/ +load-$(CONFIG_SGI_IP22) += 0x88004000 + +# +# SGI-IP27 (Origin200/2000) +# +# Set the load address to >= 0xc000000000300000 if you want to leave space for # symmon, 0xc00000000001c000 for production kernels. Note that the value # must be 16kb aligned or the handling of the current variable will break. # -#LOADADDR += 0xa80000000001c000 +ifdef CONFIG_SGI_IP27 +core-$(CONFIG_SGI_IP27) += arch/mips/sgi-ip27/ +#load-$(CONFIG_SGI_IP27) += 0xa80000000001c000 ifdef CONFIG_MAPPED_KERNEL -LOADADDR += 0xc001c000 +load-$(CONFIG_SGI_IP27) += 0xc001c000 else -LOADADDR += 0x8001c000 +load-$(CONFIG_SGI_IP27) += 0x8001c000 endif endif -ifdef CONFIG_SGI_IP32 -libs-y += arch/mips64/sgi-ip32/ - arch/mips64/arc/ # -# Set LOADADDR to >= 0x????????? if you want to leave space for symmon, -# 0x80002000 for production kernels. Note that the value must be -# 16kb aligned or the handling of the current variable will break. +# SGI-IP32 (O2) # -LOADADDR += 0x80002000 +# Set the load address to >= 0x????????? if you want to leave space for symmon, +# 0x80002000 for production kernels. Note that the value must be 16kb aligned +# or the handling of the current variable will break. +# +core-$(CONFIG_SGI_IP32) += arch/mips/sgi-ip32/ +load-$(CONFIG_SGI_IP32) += 0x80002000 + +# +# Sibyte SB1250 SOC +# +# This is a LIB so that it links at the end, and initcalls are later +# the sequence; but it is built as an object so that modules don't get +# removed (as happens, even if they have __initcall/module_init) +# +core-$(CONFIG_SIBYTE_SB1250) += arch/mips/sibyte/sb1250/ +ifdef CONFIG_SIBYTE_BCM112X +ifdef CONFIG_MIPS_UNCACHED +load-y += 0xa0100000 +else +load-y += 0x80100000 +endif +endif +ifdef CONFIG_SIBYTE_SB1250 +ifdef CONFIG_MIPS_UNCACHED +load-y += 0xa0100000 +else +load-y += 0x80100000 +endif endif # +# Sibyte BCM91120x (Carmel) board +# Sibyte BCM91120C (CRhine) board +# Sibyte BCM91125C (CRhone) board +# Sibyte BCM91125E (Rhone) board +# Sibyte SWARM board +# +libs-$(CONFIG_SIBYTE_CARMEL) += arch/mips/sibyte/swarm/ +load-$(CONFIG_SIBYTE_CARMEL) := 0x80100000 +libs-$(CONFIG_SIBYTE_CRHINE) += arch/mips/sibyte/swarm/ +load-$(CONFIG_SIBYTE_CRHINE) := 0x80100000 +libs-$(CONFIG_SIBYTE_CRHONE) += arch/mips/sibyte/swarm/ +load-$(CONFIG_SIBYTE_CRHONE) := 0x80100000 +libs-$(CONFIG_SIBYTE_RHONE) += arch/mips/sibyte/swarm/ +load-$(CONFIG_SIBYTE_RHONE) := 0x80100000 +libs-$(CONFIG_SIBYTE_SENTOSA) += arch/mips/sibyte/swarm/ +load-$(CONFIG_SIBYTE_SENTOSA) := 0x80100000 +libs-$(CONFIG_SIBYTE_SWARM) += arch/mips/sibyte/swarm/ +load-$(CONFIG_SIBYTE_SWARM) := 0x80100000 + +# +# SNI RM200 PCI +# +core-$(CONFIG_SNI_RM200_PCI) += arch/mips/sni/ +load-$(CONFIG_SNI_RM200_PCI) += 0x80080000 + +drivers-$(CONFIG_PCI) += arch/mips/pci/ + +# # Some machines like the Indy need 32-bit ELF binaries for booting purposes. # Other need ECOFF, so we build a 32-bit ELF binary for them which we then # convert to ECOFF using elf2ecoff. # -ifdef CONFIG_BOOT_ELF32 -CFLAGS += -Wa,-32 -endif -# # The 64-bit ELF tools are pretty broken so at this time we generate 64-bit # ELF files from 32-bit files by conversion. # -ifdef CONFIG_BOOT_ELF64 -CFLAGS += -Wa,-32 #AS += -64 #LDFLAGS += -m elf64bmip -#LDFLAGS_vmlinux += -T arch/mips64/ld.script.elf64 -endif +cflags-$(CONFIG_BOOT_ELF32) += -Wa,-32 +cflags-$(CONFIG_BOOT_ELF64) += -Wa,-32 -LDFLAGS_vmlinux += -Ttext $(LOADADDR) +GRRR=-Wa,-mgp64 +cflags-$(CONFIG_BOOT_ELF32) += -Wa,-32 $(call check_warning, $(GRRR),) +cflags-$(CONFIG_BOOT_ELF64) += -Wa,-32 $(call check_warning, $(GRRR),) -head-y := arch/mips64/kernel/head.o arch/mips64/kernel/init_task.o +AFLAGS_vmlinux.lds.o := -imacros $(srctree)/include/asm-mips64/sn/mapped_kernel.h \ + -D"LOADADDR=$(load-y)" -SUBDIRS := arch/mips64/tools $(SUBDIRS) -core-y += arch/mips64/kernel/ arch/mips64/mm/ -libs-y += arch/mips64/lib/lib.a +AFLAGS += $(cflags-y) +CFLAGS += $(cflags-y) -MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot +LDFLAGS += --oformat $(32bit-bfd) +LDFLAGS_BLOB := --format binary --oformat $(64bit-bfd) -ifdef CONFIG_CPU_LITTLE_ENDIAN -64bit-bfd = elf64-littlemips -else -64bit-bfd = elf64-bigmips -endif +head-y := arch/mips64/kernel/head.o arch/mips64/kernel/init_task.o + +libs-y += arch/mips64/lib/ +core-y += arch/mips64/kernel/ arch/mips64/mm/ arch/mips/math-emu/ -AFLAGS_vmlinux.lds.o := -imacros $(srctree)/include/asm-mips64/sn/mapped_kernel.h +MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot ifdef CONFIG_MAPPED_KERNEL vmlinux.64: vmlinux @@ -152,18 +275,59 @@ $(OBJCOPY) -O $(64bit-bfd) --change-addresses=0xa7ffffff80000000 $< $@ endif -zImage: vmlinux - @$(MAKEBOOT) zImage +makeboot =$(Q)$(MAKE) -f scripts/Makefile.build obj=arch/mips/boot $(1) -compressed: zImage +# +# SNI firmware is f*cked in interesting ways ... +# +ifdef CONFIG_SNI_RM200_PCI +all: vmlinux.rm200 +endif + +vmlinux.ecoff vmlinux.rm200: vmlinux + +@$(call makeboot,$@) -zdisk: vmlinux - @$(MAKEBOOT) zdisk +CLEAN_FILES += vmlinux.ecoff \ + vmlinux.rm200.tmp \ + vmlinux.rm200 archclean: - @$(MAKEBOOT) clean - $(MAKE) -C arch/$(ARCH)/tools clean + @$(MAKE) -f scripts/Makefile.clean obj=arch/mips/boot + @$(MAKE) -f scripts/Makefile.clean obj=arch/mips/baget + @$(MAKE) -f scripts/Makefile.clean obj=arch/mips/lasat archmrproper: @$(MAKEBOOT) mrproper - $(MAKE) -C arch/$(ARCH)/tools mrproper + +# Generate -#include -#include -#include -#include -#include - -#include - -extern void prom_printf (char *, ...); - -void prom_putchar(char c) -{ - ULONG cnt; - CHAR it = c; - - ArcWrite(1, &it, 1, &cnt); -} - -static void prom_console_write(struct console *co, const char *s, - unsigned count) -{ - unsigned i; - - /* - * Now, do each character - */ - for (i = 0; i < count; i++) { - if (*s == 10) - prom_printf("%c", 13); - prom_printf("%c", *s++); - } -} - -static int prom_console_wait_key(struct console *co) -{ - return 0; -} - -static int __init prom_console_setup(struct console *co, char *options) -{ - return 0; -} - -static kdev_t prom_console_device(struct console *c) -{ - return MKDEV(TTY_MAJOR, 64 + c->index); -} - -static struct console arc_cons = { - "ttyS", - prom_console_write, - NULL, - prom_console_device, - prom_console_wait_key, - NULL, - prom_console_setup, - CON_PRINTBUFFER, - -1, - 0, - NULL -}; - -/* - * Register console. - */ - -void __init arc_console_init(void) -{ - register_console(&arc_cons); -} diff -Nru a/arch/mips64/arc/cmdline.c b/arch/mips64/arc/cmdline.c --- a/arch/mips64/arc/cmdline.c Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,111 +0,0 @@ -/* - * 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. - * - * cmdline.c: Kernel command line creation using ARCS argc/argv. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - */ -#include -#include -#include - -#include -#include - -/* #define DEBUG_CMDLINE */ - -char arcs_cmdline[CL_SIZE]; - -char * __init prom_getcmdline(void) -{ - return &(arcs_cmdline[0]); -} - -static char *ignored[] = { - "ConsoleIn=", - "ConsoleOut=", - "SystemPartition=", - "OSLoader=", - "OSLoadPartition=", - "OSLoadFilename=", - "OSLoadOptions=" -}; -#define NENTS(foo) ((sizeof((foo)) / (sizeof((foo[0]))))) - -static char *used_arc[][2] = { - { "OSLoadPartition=", "root=" }, - { "OSLoadOptions=", "" } -}; - -static char * __init move_firmware_args(char* cp) -{ - char *s; - int actr, i; - - actr = 1; /* Always ignore argv[0] */ - - while (actr < prom_argc) { - for(i = 0; i < NENTS(used_arc); i++) { - int len = strlen(used_arc[i][0]); - - if (!strncmp(prom_argv(actr), used_arc[i][0], len)) { - /* Ok, we want it. First append the replacement... */ - strcat(cp, used_arc[i][1]); - cp += strlen(used_arc[i][1]); - /* ... and now the argument */ - s = strstr(prom_argv(actr), "="); - if (s) { - s++; - strcpy(cp, s); - cp += strlen(s); - } - *cp++ = ' '; - break; - } - } - actr++; - } - - return cp; -} - - -void __init prom_init_cmdline(void) -{ - char *cp; - int actr, i; - - actr = 1; /* Always ignore argv[0] */ - - cp = &(arcs_cmdline[0]); - /* - * Move ARC variables to the beginning to make sure they can be - * overridden by later arguments. - */ - cp = move_firmware_args(cp); - - while (actr < prom_argc) { - for (i = 0; i < NENTS(ignored); i++) { - int len = strlen(ignored[i]); - - if (!strncmp(prom_argv(actr), ignored[i], len)) - goto pic_cont; - } - /* Ok, we want it. */ - strcpy(cp, prom_argv(actr)); - cp += strlen(prom_argv(actr)); - *cp++ = ' '; - - pic_cont: - actr++; - } - if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */ - --cp; - *cp = '\0'; - -#ifdef DEBUG_CMDLINE - prom_printf("prom_init_cmdline: %s\n", &(arcs_cmdline[0])); -#endif -} diff -Nru a/arch/mips64/arc/console.c b/arch/mips64/arc/console.c --- a/arch/mips64/arc/console.c Tue Jul 1 18:44:37 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,33 +0,0 @@ -/* - * 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) 1996 David S. Miller (dm@sgi.com) - */ -#include -#include -#include - -static char ppbuf[1024]; - -void prom_printf(char *fmt, ...) -{ - va_list args; - char ch, *bptr; - int i; - - va_start(args, fmt); - i = vsprintf(ppbuf, fmt, args); - - bptr = ppbuf; - - while((ch = *(bptr++)) != 0) { - if(ch == '\n') - prom_putchar('\r'); - - prom_putchar(ch); - } - va_end(args); - return; -} diff -Nru a/arch/mips64/arc/env.c b/arch/mips64/arc/env.c --- a/arch/mips64/arc/env.c Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,27 +0,0 @@ -/* - * 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. - * - * env.c: ARCS environment variable routines. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - */ -#include -#include -#include - -#include -#include - -PCHAR __init -ArcGetEnvironmentVariable(CHAR *name) -{ - return (CHAR *) ARC_CALL1(get_evar, name); -} - -LONG __init -ArcSetEnvironmentVariable(PCHAR name, PCHAR value) -{ - return ARC_CALL2(set_evar, name, value); -} diff -Nru a/arch/mips64/arc/file.c b/arch/mips64/arc/file.c --- a/arch/mips64/arc/file.c Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,75 +0,0 @@ -/* - * 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. - * - * ARC firmware interface. - * - * Copyright (C) 1994, 1995, 1996, 1999 Ralf Baechle - * Copyright (C) 1999 Silicon Graphics, Inc. - */ -#include - -#include -#include - -LONG __init -ArcGetDirectoryEntry(ULONG FileID, struct linux_vdirent *Buffer, - ULONG N, ULONG *Count) -{ - return ARC_CALL4(get_vdirent, FileID, Buffer, N, Count); -} - -LONG __init -ArcOpen(CHAR *Path, enum linux_omode OpenMode, ULONG *FileID) -{ - return ARC_CALL3(open, Path, OpenMode, FileID); -} - -LONG __init -ArcClose(ULONG FileID) -{ - return ARC_CALL1(close, FileID); -} - -LONG __init -ArcRead(ULONG FileID, VOID *Buffer, ULONG N, ULONG *Count) -{ - return ARC_CALL4(read, FileID, Buffer, N, Count); -} - -LONG __init -ArcGetReadStatus(ULONG FileID) -{ - return ARC_CALL1(get_rstatus, FileID); -} - -LONG __init -ArcWrite(ULONG FileID, PVOID Buffer, ULONG N, PULONG Count) -{ - return ARC_CALL4(write, FileID, Buffer, N, Count); -} - -LONG __init -ArcSeek(ULONG FileID, struct linux_bigint *Position, enum linux_seekmode SeekMode) -{ - return ARC_CALL3(seek, FileID, Position, SeekMode); -} - -LONG __init -ArcMount(char *name, enum linux_mountops op) -{ - return ARC_CALL2(mount, name, op); -} - -LONG __init -ArcGetFileInformation(ULONG FileID, struct linux_finfo *Information) -{ - return ARC_CALL2(get_finfo, FileID, Information); -} - -LONG __init ArcSetFileInformation(ULONG FileID, ULONG AttributeFlags, - ULONG AttributeMask) -{ - return ARC_CALL3(set_finfo, FileID, AttributeFlags, AttributeMask); -} diff -Nru a/arch/mips64/arc/identify.c b/arch/mips64/arc/identify.c --- a/arch/mips64/arc/identify.c Tue Jul 1 18:44:33 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,79 +0,0 @@ -/* - * 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. - * - * identify.c: identify machine by looking up system identifier - * - * Copyright (C) 1998 Thomas Bogendoerfer - * - * This code is based on arch/mips/sgi/kernel/system.c, which is - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - */ -#include -#include -#include -#include -#include - -#include -#include - -struct smatch { - char *name; - int group; - int type; - int flags; -}; - -static struct smatch mach_table[] = { - { "SGI-IP22", MACH_GROUP_SGI, MACH_SGI_INDY, PROM_FLAG_ARCS }, - { "SGI-IP27", MACH_GROUP_SGI, MACH_SGI_IP27, PROM_FLAG_ARCS }, - { "Microsoft-Jazz", MACH_GROUP_JAZZ, MACH_MIPS_MAGNUM_4000, 0 }, - { "PICA-61", MACH_GROUP_JAZZ, MACH_ACER_PICA_61, 0 }, - { "RM200PCI", MACH_GROUP_SNI_RM, MACH_SNI_RM200_PCI, 0 } -}; - -int prom_flags; - -static struct smatch * __init -string_to_mach(const char *s) -{ - int i; - - for (i = 0; i < (sizeof (mach_table) / sizeof (mach_table[0])); i++) { - if(!strcmp(s, mach_table[i].name)) - return &mach_table[i]; - } - panic("\nYeee, could not determine architecture type <%s>", s); - - return NULL; -} - -void __init -prom_identify_arch(void) -{ - pcomponent *p; - struct smatch *mach; - const char *iname; - - /* The root component tells us what machine architecture we - have here. */ - p = ArcGetChild(PROM_NULL_COMPONENT); - if (p == NULL) { -#ifdef CONFIG_SGI_IP27 - /* IP27 PROM bisbehaves, seems to not implement ARC - GetChild(). So we just assume it's an IP27. */ - iname = "SGI-IP27"; -#endif - } else - iname = (char *) (long) p->iname; - - printk("ARCH: %s\n", iname); - mach = string_to_mach(iname); - - mips_machgroup = mach->group; - mips_machtype = mach->type; - prom_flags = mach->flags; -} diff -Nru a/arch/mips64/arc/init.c b/arch/mips64/arc/init.c --- a/arch/mips64/arc/init.c Tue Jul 1 18:44:37 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,60 +0,0 @@ -/* - * 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. - * - * PROM library initialisation code. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - */ -#include -#include - -#include - -#undef DEBUG_PROM_INIT - -/* Master romvec interface. */ -struct linux_romvec *romvec; -PSYSTEM_PARAMETER_BLOCK sgi_pblock; -int prom_argc; -LONG *_prom_argv, *_prom_envp; -unsigned short prom_vers, prom_rev; - -extern void prom_testtree(void); - -int __init -prom_init(int argc, char **argv, char **envp) -{ - PSYSTEM_PARAMETER_BLOCK pb; - - romvec = ROMVECTOR; - pb = sgi_pblock = PROMBLOCK; - prom_argc = argc; - _prom_argv = (LONG *) argv; - _prom_envp = (LONG *) envp; - - if(pb->magic != 0x53435241) { - prom_printf("Aieee, bad prom vector magic %08lx\n", pb->magic); - while(1) - ; - } - - prom_init_cmdline(); - - prom_vers = pb->ver; - prom_rev = pb->rev; - prom_identify_arch(); - printk("PROMLIB: ARC firmware Version %d Revision %d\n", - prom_vers, prom_rev); - prom_meminit(); - -#ifdef DEBUG_PROM_INIT - { - prom_printf("Press a key to reboot\n"); - (void) prom_getchar(); - ArcEnterInteractiveMode(); - } -#endif - return 0; -} diff -Nru a/arch/mips64/arc/memory.c b/arch/mips64/arc/memory.c --- a/arch/mips64/arc/memory.c Tue Jul 1 18:44:35 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,163 +0,0 @@ -/* - * memory.c: PROM library functions for acquiring/using memory descriptors - * given to us from the ARCS firmware. - * - * Copyright (C) 1996 by David S. Miller - * Copyright (C) 1999, 2000, 2001 by Ralf Baechle - * Copyright (C) 1999, 2000 by Silicon Graphics, Inc. - * - * PROM library functions for acquiring/using memory descriptors given to us - * from the ARCS firmware. This is only used when CONFIG_ARC_MEMORY is set - * because on some machines like SGI IP27 the ARC memory configuration data - * completly bogus and alternate easier to use mechanisms are available. - */ -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#undef DEBUG - -struct linux_mdesc * __init -ArcGetMemoryDescriptor(struct linux_mdesc *Current) -{ - return (struct linux_mdesc *) ARC_CALL1(get_mdesc, Current); -} - -#ifdef DEBUG /* convenient for debugging */ -static char *arcs_mtypes[8] = { - "Exception Block", - "ARCS Romvec Page", - "Free/Contig RAM", - "Generic Free RAM", - "Bad Memory", - "Standalone Program Pages", - "ARCS Temp Storage Area", - "ARCS Permanent Storage Area" -}; - -static char *arc_mtypes[8] = { - "Exception Block", - "SystemParameterBlock", - "FreeMemory", - "Bad Memory", - "LoadedProgram", - "FirmwareTemporary", - "FirmwarePermanent", - "FreeContiguous" -}; -#define mtypes(a) (prom_flags & PROM_FLAG_ARCS) ? arcs_mtypes[a.arcs] \ - : arc_mtypes[a.arc] -#endif - -static inline int memtype_classify_arcs (union linux_memtypes type) -{ - switch (type.arcs) { - case arcs_fcontig: - case arcs_free: - return BOOT_MEM_RAM; - case arcs_atmp: - return BOOT_MEM_ROM_DATA; - case arcs_eblock: - case arcs_rvpage: - case arcs_bmem: - case arcs_prog: - case arcs_aperm: - return BOOT_MEM_RESERVED; - default: - BUG(); - } - while(1); /* Nuke warning. */ -} - -static inline int memtype_classify_arc (union linux_memtypes type) -{ - switch (type.arc) { - case arc_free: - case arc_fcontig: - return BOOT_MEM_RAM; - case arc_atmp: - return BOOT_MEM_ROM_DATA; - case arc_eblock: - case arc_rvpage: - case arc_bmem: - case arc_prog: - case arc_aperm: - return BOOT_MEM_RESERVED; - default: - BUG(); - } - while(1); /* Nuke warning. */ -} - -static int __init prom_memtype_classify (union linux_memtypes type) -{ - if (prom_flags & PROM_FLAG_ARCS) /* SGI is ``different'' ... */ - return memtype_classify_arcs(type); - - return memtype_classify_arc(type); -} - -void __init prom_meminit(void) -{ - struct linux_mdesc *p; - -#ifdef DEBUG - int i = 0; - - prom_printf("ARCS MEMORY DESCRIPTOR dump:\n"); - i=0; - prom_printf ("i=%d\n", i); - p = ArcGetMemoryDescriptor(PROM_NULL_MDESC); - prom_printf ("i=%d\n", i); - while(p) { - prom_printf("[%d,%p]: base<%08lx> pages<%08lx> type<%s>\n", - i, p, p->base, p->pages, mtypes(p->type)); - p = ArcGetMemoryDescriptor(p); - i++; - } -#endif - - p = PROM_NULL_MDESC; - while ((p = ArcGetMemoryDescriptor(p))) { - unsigned long base, size; - long type; - - base = p->base << PAGE_SHIFT; - size = p->pages << PAGE_SHIFT; - type = prom_memtype_classify(p->type); - - add_memory_region(base, size, type); - } -} - -void __init prom_free_prom_memory (void) -{ - unsigned long freed = 0; - unsigned long addr; - int i; - - for (i = 0; i < boot_mem_map.nr_map; i++) { - if (boot_mem_map.map[i].type != BOOT_MEM_ROM_DATA) - continue; - - addr = boot_mem_map.map[i].addr; - while (addr < boot_mem_map.map[i].addr - + boot_mem_map.map[i].size) { - ClearPageReserved(virt_to_page(__va(addr))); - set_page_count(virt_to_page(__va(addr)), 1); - free_page((unsigned long)__va(addr)); - addr += PAGE_SIZE; - freed += PAGE_SIZE; - } - } - printk(KERN_INFO "Freeing prom memory: %ldkb freed\n", freed >> 10); -} diff -Nru a/arch/mips64/arc/misc.c b/arch/mips64/arc/misc.c --- a/arch/mips64/arc/misc.c Tue Jul 1 18:44:36 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,104 +0,0 @@ -/* - * 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. - * - * Miscellaneous ARCS PROM routines. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * Copyright (C) 1999 Ralf Baechle (ralf@gnu.org) - * Copyright (C) 1999 Silicon Graphics, Inc. - */ -#include -#include -#include - -#include - -#include -#include -#include -#include - -extern unsigned long mips_cputype; -extern void *sgiwd93_host; -extern void reset_wd33c93(void *instance); - -VOID -ArcHalt(VOID) -{ - bc_disable(); - cli(); -#ifdef CONFIG_SCSI_SGIWD93 - reset_wd33c93(sgiwd93_host); -#endif - ARC_CALL0(halt); -never: goto never; -} - -VOID -ArcPowerDown(VOID) -{ - bc_disable(); - cli(); -#ifdef CONFIG_SCSI_SGIWD93 - reset_wd33c93(sgiwd93_host); -#endif - ARC_CALL0(pdown); -never: goto never; -} - -/* XXX is this a soft reset basically? XXX */ -VOID -ArcRestart(VOID) -{ - bc_disable(); - cli(); -#ifdef CONFIG_SCSI_SGIWD93 - reset_wd33c93(sgiwd93_host); -#endif - ARC_CALL0(restart); -never: goto never; -} - -VOID -ArcReboot(VOID) -{ - bc_disable(); - cli(); -#ifdef CONFIG_SCSI_SGIWD93 - reset_wd33c93(sgiwd93_host); -#endif - ARC_CALL0(reboot); -never: goto never; -} - -VOID -ArcEnterInteractiveMode(VOID) -{ - bc_disable(); - cli(); -#ifdef CONFIG_SCSI_SGIWD93 - reset_wd33c93(sgiwd93_host); -#endif - ARC_CALL0(imode); -never: goto never; -} - -LONG -ArcSaveConfiguration(VOID) -{ - return ARC_CALL0(cfg_save); -} - -struct linux_sysid * -ArcGetSystemId(VOID) -{ - return (struct linux_sysid *) ARC_CALL0(get_sysid); -} - -VOID __init -ArcFlushAllCaches(VOID) -{ - ARC_CALL0(cache_flush); -} diff -Nru a/arch/mips64/arc/salone.c b/arch/mips64/arc/salone.c --- a/arch/mips64/arc/salone.c Tue Jul 1 18:44:35 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,27 +0,0 @@ -/* - * Routines to load into memory and execute stand-along program images using - * ARCS PROM firmware. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - */ -#include -#include - -LONG __init -ArcLoad(CHAR *Path, ULONG TopAddr, ULONG *ExecAddr, ULONG *LowAddr) -{ - return ARC_CALL4(load, Path, TopAddr, ExecAddr, LowAddr); -} - -LONG __init -ArcInvoke(ULONG ExecAddr, ULONG StackAddr, ULONG Argc, CHAR *Argv[], - CHAR *Envp[]) -{ - return ARC_CALL5(invoke, ExecAddr, StackAddr, Argc, Argv, Envp); -} - -LONG __init -ArcExecute(CHAR *Path, LONG Argc, CHAR *Argv[], CHAR *Envp[]) -{ - return ARC_CALL4(exec, Path, Argc, Argv, Envp); -} diff -Nru a/arch/mips64/arc/time.c b/arch/mips64/arc/time.c --- a/arch/mips64/arc/time.c Tue Jul 1 18:44:31 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,25 +0,0 @@ -/* - * 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. - * - * Extracting time information from ARCS prom. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - */ -#include - -#include -#include - -struct linux_tinfo * __init -ArcGetTime(VOID) -{ - return (struct linux_tinfo *) ARC_CALL0(get_tinfo); -} - -ULONG __init -ArcGetRelativeTime(VOID) -{ - return ARC_CALL0(get_rtime); -} diff -Nru a/arch/mips64/arc/tree.c b/arch/mips64/arc/tree.c --- a/arch/mips64/arc/tree.c Tue Jul 1 18:44:37 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,127 +0,0 @@ -/* - * 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. - * - * PROM component device tree code. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * Copyright (C) 1999 Ralf Baechle (ralf@gnu.org) - * Copyright (C) 1999 Silicon Graphics, Inc. - */ -#include -#include -#include - -#undef DEBUG_PROM_TREE - -pcomponent * __init -ArcGetPeer(pcomponent *Current) -{ - if (Current == PROM_NULL_COMPONENT) - return PROM_NULL_COMPONENT; - - return (pcomponent *) ARC_CALL1(next_component, Current); -} - -pcomponent * __init -ArcGetChild(pcomponent *Current) -{ - return (pcomponent *) ARC_CALL1(child_component, Current); -} - -pcomponent * __init -ArcGetParent(pcomponent *Current) -{ - if (Current == PROM_NULL_COMPONENT) - return PROM_NULL_COMPONENT; - - return (pcomponent *) ARC_CALL1(parent_component, Current); -} - -LONG __init -ArcGetConfigurationData(VOID *Buffer, pcomponent *Current) -{ - return ARC_CALL2(component_data, Buffer, Current); -} - -pcomponent * __init -ArcAddChild(pcomponent *Current, pcomponent *Template, VOID *ConfigurationData) -{ - return (pcomponent *) - ARC_CALL3(child_add, Current, Template, ConfigurationData); -} - -LONG __init -ArcDeleteComponent(pcomponent *ComponentToDelete) -{ - return ARC_CALL1(comp_del, ComponentToDelete); -} - -pcomponent * __init -ArcGetComponent(CHAR *Path) -{ - return (pcomponent *)ARC_CALL1(component_by_path, Path); -} - -#ifdef DEBUG_PROM_TREE - -static char *classes[] = { - "system", "processor", "cache", "adapter", "controller", "peripheral", - "memory" -}; - -static char *types[] = { - "arc", "cpu", "fpu", "picache", "pdcache", "sicache", "sdcache", - "sccache", "memdev", "eisa adapter", "tc adapter", "scsi adapter", - "dti adapter", "multi-func adapter", "disk controller", - "tp controller", "cdrom controller", "worm controller", - "serial controller", "net controller", "display controller", - "parallel controller", "pointer controller", "keyboard controller", - "audio controller", "misc controller", "disk peripheral", - "floppy peripheral", "tp peripheral", "modem peripheral", - "monitor peripheral", "printer peripheral", "pointer peripheral", - "keyboard peripheral", "terminal peripheral", "line peripheral", - "net peripheral", "misc peripheral", "anonymous" -}; - -static char *iflags[] = { - "bogus", "read only", "removable", "console in", "console out", - "input", "output" -}; - -static void __init -dump_component(pcomponent *p) -{ - prom_printf("[%p]:class<%s>type<%s>flags<%s>ver<%d>rev<%d>", - p, classes[p->class], types[p->type], - iflags[p->iflags], p->vers, p->rev); - prom_printf("key<%08lx>\n\tamask<%08lx>cdsize<%d>ilen<%d>iname<%s>\n", - p->key, p->amask, (int)p->cdsize, (int)p->ilen, p->iname); -} - -static void __init -traverse(pcomponent *p, int op) -{ - dump_component(p); - if(ArcGetChild(p)) - traverse(ArcGetChild(p), 1); - if(ArcGetPeer(p) && op) - traverse(ArcGetPeer(p), 1); -} - -void __init -prom_testtree(void) -{ - pcomponent *p; - - p = ArcGetChild(PROM_NULL_COMPONENT); - dump_component(p); - p = ArcGetChild(p); - while(p) { - dump_component(p); - p = ArcGetPeer(p); - } -} - -#endif /* DEBUG_PROM_TREE */ diff -Nru a/arch/mips64/boot/Makefile b/arch/mips64/boot/Makefile --- a/arch/mips64/boot/Makefile Tue Jul 1 18:44:37 2003 +++ b/arch/mips64/boot/Makefile Tue Jul 1 18:44:37 2003 @@ -15,16 +15,30 @@ E2EFLAGS = endif +# +# Drop some uninteresting sections in the kernel. +# This is only relevant for ELF kernels but doesn't hurt a.out +# +drop-sections = .reginfo .mdebug .comment .note +strip-flags = $(addprefix --remove-section=,$(drop-sections)) + all: vmlinux.ecoff addinitrd +vmlinux.rm200: vmlinux + $(OBJCOPY) \ + --change-addresses=0xfffffffc \ + -O elf32-littlemips \ + $(strip-flags) \ + $< $@ + vmlinux.ecoff: elf2ecoff $(TOPDIR)/vmlinux ./elf2ecoff $(TOPDIR)/vmlinux vmlinux.ecoff $(E2EFLAGS) -elf2ecoff: elf2ecoff.c - $(HOSTCC) -o $@ $^ +elf2ecoff: $(TOPDIR)/arch/mips/boot/elf2ecoff.c + $(HOSTCC) -I$(TOPDIR)/arch/mips/boot -I- -o $@ $^ -addinitrd: addinitrd.c - $(HOSTCC) -o $@ $^ +addinitrd: $(TOPDIR)/arch/mips/boot/addinitrd.c + $(HOSTCC) -I$(TOPDIR)/arch/mips/boot -I- -o $@ $^ clean: rm -f vmlinux.ecoff diff -Nru a/arch/mips64/defconfig b/arch/mips64/defconfig --- a/arch/mips64/defconfig Tue Jul 1 18:44:36 2003 +++ b/arch/mips64/defconfig Tue Jul 1 18:44:36 2003 @@ -1,71 +1,133 @@ # # Automatically generated make config: don't edit # +CONFIG_MIPS=y +# CONFIG_MIPS32 is not set +CONFIG_MIPS64=y # # Code maturity level options # -# CONFIG_EXPERIMENTAL is not set +CONFIG_EXPERIMENTAL=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=15 +# CONFIG_EMBEDDED is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y + +# +# Loadable module support +# +# CONFIG_MODULES is not set # # Machine selection # +# CONFIG_ACER_PICA_61 is not set +# CONFIG_CASIO_E55 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_IBM_WORKPAD is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_NEC_EAGLE is not set +# CONFIG_OLIVETTI_M700 is not set # CONFIG_SGI_IP22 is not set CONFIG_SGI_IP27=y # CONFIG_SGI_SN0_N_MODE is not set -CONFIG_DISCONTIGMEM=y -CONFIG_NUMA=y +# CONFIG_DISCONTIGMEM is not set +# CONFIG_NUMA is not set # CONFIG_MAPPED_KERNEL is not set # CONFIG_REPLICATE_KTEXT is not set # CONFIG_REPLICATE_EXHANDLERS is not set -CONFIG_SMP=y +# CONFIG_SGI_IP32 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TANBAC_TB0226 is not set +# CONFIG_TANBAC_TB0229 is not set +# CONFIG_VICTOR_MPC30X is not set +# CONFIG_ZAO_CAPCELLA is not set CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set -CONFIG_BOOT_ELF64=y +CONFIG_ARC=y +CONFIG_GENERIC_ISA_DMA=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_L1_CACHE_SHIFT=7 +# CONFIG_FB is not set CONFIG_ARC64=y -CONFIG_COHERENT_IO=y -CONFIG_MAPPED_PCI_IO=y -CONFIG_PCI=y +CONFIG_BOOT_ELF64=y CONFIG_QL_ISP_A64=y -CONFIG_L1_CACHE_SHIFT=7 -# CONFIG_ISA is not set -# CONFIG_EISA is not set -# CONFIG_MCA is not set -# CONFIG_SBUS is not set -CONFIG_NR_CPUS=64 # # CPU selection # +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set # CONFIG_CPU_R4300 is not set # CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set # CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set # CONFIG_CPU_NEVADA is not set # CONFIG_CPU_R8000 is not set CONFIG_CPU_R10000=y +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_SMP=y +CONFIG_NR_CPUS=4 +# CONFIG_PREEMPT is not set +CONFIG_KALLSYMS=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_MIPS_INSANE_LARGE is not set # -# General setup +# Bus options (PCI, PCMCIA, EISA, ISA, TC) # -# CONFIG_MIPS_INSANE_LARGE is not set -# CONFIG_CPU_LITTLE_ENDIAN is not set -CONFIG_NET=y +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y CONFIG_PCI_NAMES=y +CONFIG_MMU=y # CONFIG_HOTPLUG is not set -# CONFIG_PCMCIA is not set -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_BINFMT_ELF=y -CONFIG_MIPS32_COMPAT=y -CONFIG_BINFMT_ELF32=y -# CONFIG_BINFMT_MISC is not set # -# Loadable module support +# Executable file formats # -# CONFIG_MODULES is not set -CONFIG_PCI_NAMES=y +CONFIG_KCORE_ELF=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_MIPS32_COMPAT=y +CONFIG_COMPAT=y +CONFIG_MIPS32_O32=y +# CONFIG_MIPS32_N32 is not set +CONFIG_BINFMT_ELF32=y # # Memory Technology Devices (MTD) @@ -78,83 +140,35 @@ # CONFIG_PARPORT is not set # +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# # Block devices # # CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_RAM is not set # CONFIG_BLK_DEV_INITRD is not set # -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_BLK_DEV_LVM is not set - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_NETLINK=y -CONFIG_RTNETLINK=y -CONFIG_NETLINK_DEV=y -# CONFIG_NETFILTER is not set -# CONFIG_FILTER is not set -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -# CONFIG_IP_PNP_BOOTP is not set -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set - -# -# -# -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set -# CONFIG_PHONE_IXJ is not set -# CONFIG_PHONE_IXJ_PCMCIA is not set - -# -# ATA/IDE/MFM/RLL support +# ATA/ATAPI/MFM/RLL support # # CONFIG_IDE is not set -# CONFIG_BLK_DEV_IDE_MODES is not set -# CONFIG_BLK_DEV_HD is not set # -# SCSI support +# SCSI device support # CONFIG_SCSI=y @@ -162,7 +176,6 @@ # SCSI support type (disk, tape, CD-ROM) # CONFIG_BLK_DEV_SD=y -CONFIG_SD_EXTRA_DEVS=40 CONFIG_CHR_DEV_ST=y # CONFIG_CHR_DEV_OSST is not set # CONFIG_BLK_DEV_SR is not set @@ -171,8 +184,8 @@ # # Some SCSI devices (e.g. CD jukebox) support multiple LUNs # -# CONFIG_SCSI_DEBUG_QUEUES is not set # CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_REPORT_LUNS is not set CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y @@ -180,52 +193,116 @@ # SCSI low-level drivers # # CONFIG_BLK_DEV_3W_XXXX_RAID is not set -# CONFIG_SCSI_7000FASST is not set # CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AHA152X is not set -# CONFIG_SCSI_AHA1542 is not set -# CONFIG_SCSI_AHA1740 is not set +# CONFIG_SCSI_AACRAID is not set # CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set # CONFIG_SCSI_DPT_I2O is not set # CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_AM53C974 is not set # CONFIG_SCSI_MEGARAID is not set # CONFIG_SCSI_BUSLOGIC is not set # CONFIG_SCSI_CPQFCTS is not set # CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_DTC3280 is not set # CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_DMA is not set # CONFIG_SCSI_EATA_PIO is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_GDTH is not set -# CONFIG_SCSI_GENERIC_NCR5380 is not set # CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_NCR_D700 is not set -# CONFIG_SCSI_NCR53C7xx is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set # CONFIG_SCSI_NCR53C8XX is not set # CONFIG_SCSI_SYM53C8XX is not set -# CONFIG_SCSI_PAS16 is not set # CONFIG_SCSI_PCI2000 is not set # CONFIG_SCSI_PCI2220I is not set -# CONFIG_SCSI_PSI240I is not set -# CONFIG_SCSI_QLOGIC_FAS is not set -CONFIG_SCSI_QLOGIC_ISP=y +# CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set -# CONFIG_SCSI_SIM710 is not set -# CONFIG_SCSI_SYM53C416 is not set +# CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set # -# Network device support +# IEEE 1394 (FireWire) support (EXPERIMENTAL) # +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_NETLINK_DEV=y +# CONFIG_NETFILTER is not set +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set CONFIG_NETDEVICES=y # @@ -236,39 +313,44 @@ # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set CONFIG_SGI_IOC3_ETH=y -# CONFIG_SUNLANCE is not set # CONFIG_HAPPYMEAL is not set -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set -# CONFIG_SUNLANCE is not set # CONFIG_SUNGEM is not set # CONFIG_NET_VENDOR_3COM is not set -# CONFIG_LANCE is not set -# CONFIG_NET_VENDOR_SMC is not set -# CONFIG_NET_VENDOR_RACAL is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set # CONFIG_HP100 is not set -# CONFIG_NET_ISA is not set # CONFIG_NET_PCI is not set -# CONFIG_NET_POCKET is not set # # Ethernet (1000 Mbit) # # CONFIG_ACENIC is not set # CONFIG_DL2K is not set -# CONFIG_MYRI_SBUS is not set +# CONFIG_E1000 is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set # CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set # CONFIG_FDDI is not set -# CONFIG_PLIP is not set +# CONFIG_HIPPI is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -278,10 +360,11 @@ # CONFIG_NET_RADIO is not set # -# Token Ring devices +# Token Ring devices (depends on LLC=y) # -# CONFIG_TR is not set # CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set # # Wan interfaces @@ -301,21 +384,69 @@ # # ISDN subsystem # -# CONFIG_ISDN is not set +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set # -# Old CD-ROM drivers (not SCSI, not IDE) +# Input Device Drivers # -# CONFIG_CD_NO_IDESCSI is not set +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set # # Character devices # # CONFIG_VT is not set -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y -# CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +# CONFIG_SERIAL_8250_CONSOLE is not set +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_MULTIPORT is not set +# CONFIG_SERIAL_8250_RSA is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y CONFIG_UNIX98_PTYS=y CONFIG_UNIX98_PTY_COUNT=256 @@ -325,32 +456,33 @@ # CONFIG_I2C is not set # -# Mice +# I2C Hardware Sensors Mainboard support # -# CONFIG_BUSMOUSE is not set -# CONFIG_MOUSE is not set # -# Joysticks +# I2C Hardware Sensors Chip support # -# CONFIG_INPUT_GAMEPORT is not set +# CONFIG_I2C_SENSOR is not set # -# Input core support is needed for gameports +# Mice # +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set # -# Input core support is needed for joysticks +# IPMI # -# CONFIG_QIC02_TAPE is not set +# CONFIG_IPMI_HANDLER is not set # # Watchdog Cards # # CONFIG_WATCHDOG is not set -# CONFIG_INTEL_RNG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +CONFIG_SGI_IP27_RTC=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set @@ -361,6 +493,8 @@ # CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HANGCHECK_TIMER is not set # # Multimedia devices @@ -368,79 +502,92 @@ # CONFIG_VIDEO_DEV is not set # +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# # File systems # +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=y +CONFIG_JBD_DEBUG=y +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set CONFIG_AUTOFS_FS=y # CONFIG_AUTOFS4_FS is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# # CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set -# CONFIG_CMS_FS is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_JBD_DEBUG is not set -# CONFIG_FAT_FS is not set -# CONFIG_MSDOS_FS is not set -# CONFIG_UMSDOS_FS is not set -# CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -# CONFIG_JFFS2_FS is not set # CONFIG_CRAMFS is not set -# CONFIG_TMPFS is not set -# CONFIG_RAMFS is not set -# CONFIG_ISO9660_FS is not set -# CONFIG_JOLIET is not set -# CONFIG_MINIX_FS is not set -# CONFIG_FREEVXFS_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_DEBUG is not set -# CONFIG_NTFS_RW is not set +# CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set # # Network File Systems # -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=y CONFIG_NFS_V3=y -CONFIG_ROOT_NFS=y +# CONFIG_NFS_V4 is not set # CONFIG_NFSD is not set -# CONFIG_NFSD_V3 is not set -CONFIG_SUNRPC=y +CONFIG_ROOT_NFS=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set # CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set # CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set # # Partition Types @@ -457,12 +604,15 @@ # CONFIG_SOLARIS_X86_PARTITION is not set # CONFIG_UNIXWARE_DISKLABEL is not set # CONFIG_LDM_PARTITION is not set +# CONFIG_NEC98_PARTITION is not set CONFIG_SGI_PARTITION=y # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set -# CONFIG_SMB_NLS is not set -# CONFIG_NLS is not set -CONFIG_KCORE_ELF=y +# CONFIG_EFI_PARTITION is not set + +# +# Graphics support +# # # Sound @@ -473,113 +623,30 @@ # USB support # # CONFIG_USB is not set +# CONFIG_USB_GADGET is not set # -# USB Controllers +# Bluetooth support # -# CONFIG_USB_UHCI is not set -# CONFIG_USB_UHCI_ALT is not set -# CONFIG_USB_OHCI is not set +# CONFIG_BT is not set # -# USB Device Class drivers -# -# CONFIG_USB_AUDIO is not set -# CONFIG_USB_BLUETOOTH is not set -# CONFIG_USB_STORAGE is not set -# CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set -# CONFIG_USB_STORAGE_DPCM is not set -# CONFIG_USB_STORAGE_SDDR09 is not set -# CONFIG_USB_ACM is not set -# CONFIG_USB_PRINTER is not set - -# -# USB Human Interface Devices (HID) -# - -# -# Input core support is needed for USB HID -# - -# -# USB Imaging devices -# -# CONFIG_USB_DC2XX is not set -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_SCANNER is not set -# CONFIG_USB_MICROTEK is not set -# CONFIG_USB_HPUSBSCSI is not set - -# -# USB Multimedia devices -# - -# -# Video4Linux support is needed for USB Multimedia device support -# -# CONFIG_USB_DABUSB is not set - -# -# USB Network adaptors -# -# CONFIG_USB_PLUSB is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_CATC is not set -# CONFIG_USB_CDCETHER is not set -# CONFIG_USB_USBNET is not set - -# -# USB port drivers -# -# CONFIG_USB_USS720 is not set - -# -# USB Serial Converter support +# Kernel hacking # -# CONFIG_USB_SERIAL is not set -# CONFIG_USB_SERIAL_GENERIC is not set -# CONFIG_USB_SERIAL_BELKIN is not set -# CONFIG_USB_SERIAL_WHITEHEAT is not set -# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set -# CONFIG_USB_SERIAL_EMPEG is not set -# CONFIG_USB_SERIAL_FTDI_SIO is not set -# CONFIG_USB_SERIAL_VISOR is not set -# CONFIG_USB_SERIAL_EDGEPORT is not set -# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set -# CONFIG_USB_SERIAL_KEYSPAN is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set -# CONFIG_USB_SERIAL_MCT_U232 is not set -# CONFIG_USB_SERIAL_PL2303 is not set -# CONFIG_USB_SERIAL_CYBERJACK is not set -# CONFIG_USB_SERIAL_OMNINET is not set +CONFIG_CROSSCOMPILE=y +# CONFIG_DEBUG_KERNEL is not set # -# Miscellaneous USB drivers +# Security options # -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_ID75 is not set +# CONFIG_SECURITY is not set # -# Input core support +# Cryptographic options # -# CONFIG_INPUT is not set -# CONFIG_INPUT_KEYBDEV is not set -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_EVDEV is not set +# CONFIG_CRYPTO is not set # -# Kernel hacking +# Library routines # -CONFIG_CROSSCOMPILE=y -# CONFIG_REMOTE_DEBUG is not set -# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_CRC32 is not set diff -Nru a/arch/mips64/defconfig-atlas b/arch/mips64/defconfig-atlas --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips64/defconfig-atlas Tue Jul 1 18:44:40 2003 @@ -0,0 +1,547 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS32 is not set +CONFIG_MIPS64=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_EMBEDDED is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# Machine selection +# +# CONFIG_ACER_PICA_61 is not set +# CONFIG_CASIO_E55 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_IBM_WORKPAD is not set +# CONFIG_MIPS_ITE8172 is not set +CONFIG_MIPS_ATLAS=y +# CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_NEC_EAGLE is not set +# CONFIG_OLIVETTI_M700 is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP27 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TANBAC_TB0226 is not set +# CONFIG_TANBAC_TB0229 is not set +# CONFIG_VICTOR_MPC30X is not set +# CONFIG_ZAO_CAPCELLA is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_NONCOHERENT_IO=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_MIPS_BOARDS_GEN=y +CONFIG_SWAP_IO_SPACE=y +CONFIG_BOOT_ELF32=y +CONFIG_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +CONFIG_CPU_R5000=y +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +CONFIG_KALLSYMS=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +# CONFIG_PCI is not set +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_KCORE_ELF=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_MIPS32_COMPAT=y +CONFIG_COMPAT=y +CONFIG_MIPS32_O32=y +# CONFIG_MIPS32_N32 is not set +CONFIG_BINFMT_ELF32=y + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_INITRD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_SCSI=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_REPORT_LUNS is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI low-level drivers +# +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# I2O device support +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_PACKET is not set +CONFIG_NETLINK_DEV=y +# CONFIG_NETFILTER is not set +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices (depends on LLC=y) +# +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# I2C Hardware Sensors Mainboard support +# + +# +# I2C Hardware Sensors Chip support +# +# CONFIG_I2C_SENSOR is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +CONFIG_RTC=y +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HANGCHECK_TIMER is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=y +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +CONFIG_EFS_FS=y +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_NFS_V4 is not set +# CONFIG_NFSD is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Graphics support +# + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB_GADGET is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set diff -Nru a/arch/mips64/defconfig-decstation b/arch/mips64/defconfig-decstation --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips64/defconfig-decstation Tue Jul 1 18:44:40 2003 @@ -0,0 +1,573 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS32 is not set +CONFIG_MIPS64=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_EMBEDDED is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# Machine selection +# +# CONFIG_ACER_PICA_61 is not set +# CONFIG_CASIO_E55 is not set +# CONFIG_MIPS_COBALT is not set +CONFIG_DECSTATION=y +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_IBM_WORKPAD is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_NEC_EAGLE is not set +# CONFIG_OLIVETTI_M700 is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP27 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TANBAC_TB0226 is not set +# CONFIG_TANBAC_TB0229 is not set +# CONFIG_VICTOR_MPC30X is not set +# CONFIG_ZAO_CAPCELLA is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_NONCOHERENT_IO=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_IRQ_CPU=y +CONFIG_BOOT_ELF32=y +CONFIG_L1_CACHE_SHIFT=4 +# CONFIG_FB is not set + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +CONFIG_CPU_R4X00=y +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +CONFIG_KALLSYMS=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_TC=y +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_KCORE_ELF=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_MIPS32_COMPAT=y +CONFIG_COMPAT=y +CONFIG_MIPS32_O32=y +# CONFIG_MIPS32_N32 is not set +CONFIG_BINFMT_ELF32=y + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_SCSI=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_REPORT_LUNS is not set +CONFIG_SCSI_CONSTANTS=y +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI low-level drivers +# +CONFIG_SCSI_DECNCR=y +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# I2O device support +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +# CONFIG_NETLINK_DEV is not set +# CONFIG_NETFILTER is not set +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +CONFIG_DECLANCE=y + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices (depends on LLC=y) +# +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +# CONFIG_SERIO_SERPORT is not set +# CONFIG_SERIO_CT82C710 is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +# CONFIG_VT is not set +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_COMPUTONE is not set +# CONFIG_ROCKETPORT is not set +# CONFIG_CYCLADES is not set +# CONFIG_DIGIEPCA is not set +# CONFIG_DIGI is not set +# CONFIG_MOXA_INTELLIO is not set +# CONFIG_MOXA_SMARTIO is not set +# CONFIG_SYNCLINK is not set +# CONFIG_SYNCLINKMP is not set +# CONFIG_N_HDLC is not set +# CONFIG_RISCOM8 is not set +# CONFIG_SPECIALIX is not set +# CONFIG_SX is not set +# CONFIG_RIO is not set +# CONFIG_STALDRV is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_DZ=y +CONFIG_SERIAL_DZ_CONSOLE=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# I2C Hardware Sensors Mainboard support +# + +# +# I2C Hardware Sensors Chip support +# +# CONFIG_I2C_SENSOR is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HANGCHECK_TIMER is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +# CONFIG_NFS_FS is not set +# CONFIG_NFSD is not set +# CONFIG_EXPORTFS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +CONFIG_OSF_PARTITION=y +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_NEC98_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +CONFIG_ULTRIX_PARTITION=y +# CONFIG_SUN_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Graphics support +# + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB_GADGET is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set diff -Nru a/arch/mips64/defconfig-ip22 b/arch/mips64/defconfig-ip22 --- a/arch/mips64/defconfig-ip22 Tue Jul 1 18:44:35 2003 +++ b/arch/mips64/defconfig-ip22 Tue Jul 1 18:44:35 2003 @@ -1,6 +1,9 @@ # # Automatically generated make config: don't edit # +CONFIG_MIPS=y +# CONFIG_MIPS32 is not set +CONFIG_MIPS64=y # # Code maturity level options @@ -8,57 +11,122 @@ CONFIG_EXPERIMENTAL=y # +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_EMBEDDED is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# # Machine selection # +# CONFIG_ACER_PICA_61 is not set +# CONFIG_CASIO_E55 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_IBM_WORKPAD is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_NEC_EAGLE is not set +# CONFIG_OLIVETTI_M700 is not set CONFIG_SGI_IP22=y # CONFIG_SGI_IP27 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TANBAC_TB0226 is not set +# CONFIG_TANBAC_TB0229 is not set +# CONFIG_VICTOR_MPC30X is not set +# CONFIG_ZAO_CAPCELLA is not set CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +CONFIG_ARC=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_NONCOHERENT_IO=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_IRQ_CPU=y +CONFIG_SWAP_IO_SPACE=y CONFIG_BOOT_ELF32=y +CONFIG_L1_CACHE_SHIFT=5 CONFIG_ARC32=y +# CONFIG_FB is not set +CONFIG_ARC_CONSOLE=y +CONFIG_ARC_PROMLIB=y CONFIG_BOARD_SCACHE=y -CONFIG_ARC_MEMORY=y -CONFIG_SGI=y -CONFIG_L1_CACHE_SHIFT=5 -# CONFIG_ISA is not set -# CONFIG_EISA is not set -# CONFIG_PCI is not set -# CONFIG_MCA is not set -# CONFIG_SBUS is not set # # CPU selection # +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set # CONFIG_CPU_R4300 is not set # CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set CONFIG_CPU_R5000=y +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set # CONFIG_CPU_NEVADA is not set # CONFIG_CPU_R8000 is not set # CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +CONFIG_KALLSYMS=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # -# General setup +# Bus options (PCI, PCMCIA, EISA, ISA, TC) # -# CONFIG_CPU_LITTLE_ENDIAN is not set -# CONFIG_MIPS_FPU_EMULATOR is not set -CONFIG_NET=y +# CONFIG_ISA is not set +CONFIG_MMU=y # CONFIG_HOTPLUG is not set -# CONFIG_PCMCIA is not set -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -# CONFIG_ARC_CONSOLE is not set -CONFIG_BINFMT_ELF=y -CONFIG_MIPS32_COMPAT=y -CONFIG_BINFMT_ELF32=y -# CONFIG_BINFMT_MISC is not set # -# Loadable module support +# Executable file formats # -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y +CONFIG_KCORE_ELF=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_MIPS32_COMPAT=y +CONFIG_COMPAT=y +CONFIG_MIPS32_O32=y +CONFIG_MIPS32_N32=y +CONFIG_BINFMT_ELF32=y # # Memory Technology Devices (MTD) @@ -71,41 +139,90 @@ # CONFIG_PARPORT is not set # +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# # Block devices # # CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_CPQ_CISS_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_RAM is not set # CONFIG_BLK_DEV_INITRD is not set # +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_SCSI=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_ST=y +# CONFIG_CHR_DEV_OSST is not set +CONFIG_BLK_DEV_SR=y +# CONFIG_BLK_DEV_SR_VENDOR is not set +# CONFIG_CHR_DEV_SG is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_REPORT_LUNS is not set +CONFIG_SCSI_CONSTANTS=y +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI low-level drivers +# +CONFIG_SGIWD93_SCSI=y +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_DEBUG is not set + +# # Multi-device support (RAID and LVM) # # CONFIG_MD is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_BLK_DEV_LVM is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# I2O device support +# + +# +# Networking support +# +CONFIG_NET=y # # Networking options # CONFIG_PACKET=y CONFIG_PACKET_MMAP=y -CONFIG_NETLINK=y -CONFIG_RTNETLINK=y CONFIG_NETLINK_DEV=y # CONFIG_NETFILTER is not set -# CONFIG_FILTER is not set CONFIG_UNIX=y +CONFIG_NET_KEY=y CONFIG_INET=y CONFIG_IP_MULTICAST=y # CONFIG_IP_ADVANCED_ROUTER is not set @@ -119,20 +236,24 @@ # CONFIG_ARPD is not set # CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_KHTTPD is not set -# CONFIG_ATM is not set +# CONFIG_XFRM_USER is not set # -# +# SCTP Configuration (EXPERIMENTAL) # -# CONFIG_IPX is not set -# CONFIG_ATALK is not set +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC is not set # CONFIG_DECNET is not set # CONFIG_BRIDGE is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_LLC is not set # CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -145,94 +266,10 @@ # CONFIG_NET_SCHED is not set # -# Telephony Support -# -# CONFIG_PHONE is not set -# CONFIG_PHONE_IXJ is not set -# CONFIG_PHONE_IXJ_PCMCIA is not set - -# -# ATA/IDE/MFM/RLL support -# -# CONFIG_IDE is not set -# CONFIG_BLK_DEV_IDE_MODES is not set -# CONFIG_BLK_DEV_HD is not set - -# -# SCSI support -# -CONFIG_SCSI=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=y -CONFIG_SD_EXTRA_DEVS=40 -CONFIG_CHR_DEV_ST=y -# CONFIG_CHR_DEV_OSST is not set -CONFIG_BLK_DEV_SR=y -# CONFIG_BLK_DEV_SR_VENDOR is not set -CONFIG_SR_EXTRA_DEVS=2 -# CONFIG_CHR_DEV_SG is not set - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -# CONFIG_SCSI_DEBUG_QUEUES is not set -# CONFIG_SCSI_MULTI_LUN is not set -CONFIG_SCSI_CONSTANTS=y -# CONFIG_SCSI_LOGGING is not set - -# -# SCSI low-level drivers -# -CONFIG_SGIWD93_SCSI=y -# CONFIG_SCSI_7000FASST is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AHA152X is not set -# CONFIG_SCSI_AHA1542 is not set -# CONFIG_SCSI_AHA1740 is not set -# CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_AM53C974 is not set -# CONFIG_SCSI_MEGARAID is not set -# CONFIG_SCSI_BUSLOGIC is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_DTC3280 is not set -# CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_DMA is not set -# CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -# CONFIG_SCSI_GDTH is not set -# CONFIG_SCSI_GENERIC_NCR5380 is not set -# CONFIG_SCSI_INITIO is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_NCR_D700 is not set -# CONFIG_SCSI_NCR53C7xx is not set -# CONFIG_SCSI_PAS16 is not set -# CONFIG_SCSI_PCI2000 is not set -# CONFIG_SCSI_PCI2220I is not set -# CONFIG_SCSI_PSI240I is not set -# CONFIG_SCSI_QLOGIC_FAS is not set -# CONFIG_SCSI_SIM710 is not set -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set -# CONFIG_SCSI_DEBUG is not set - -# -# Network device support +# Network testing # +# CONFIG_NET_PKTGEN is not set CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set @@ -243,33 +280,16 @@ # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y -# CONFIG_SUNLANCE is not set -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set -# CONFIG_SUNLANCE is not set -# CONFIG_SUNGEM is not set -# CONFIG_NET_VENDOR_3COM is not set -# CONFIG_LANCE is not set -# CONFIG_NET_VENDOR_SMC is not set -# CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_NET_ISA is not set -# CONFIG_NET_PCI is not set -# CONFIG_NET_POCKET is not set +# CONFIG_MII is not set CONFIG_SGISEEQ=y # # Ethernet (1000 Mbit) # -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_MYRI_SBUS is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_SK98LIN is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PLIP is not set + +# +# Ethernet (10000 Mbit) +# # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -279,11 +299,8 @@ # CONFIG_NET_RADIO is not set # -# Token Ring devices +# Token Ring devices (depends on LLC=y) # -# CONFIG_TR is not set -# CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set # CONFIG_SHAPER is not set # @@ -304,21 +321,69 @@ # # ISDN subsystem # -# CONFIG_ISDN is not set +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set # -# Old CD-ROM drivers (not SCSI, not IDE) +# Input I/O drivers # -# CONFIG_CD_NO_IDESCSI is not set +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set # # Character devices # CONFIG_VT=y CONFIG_VT_CONSOLE=y -# CONFIG_SERIAL is not set -# CONFIG_SERIAL_EXTENDED is not set +CONFIG_HW_CONSOLE=y # CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_IP22_ZILOG=y +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_UNIX98_PTY_COUNT=256 @@ -328,36 +393,58 @@ # CONFIG_I2C is not set # -# Mice +# I2C Hardware Sensors Mainboard support # -# CONFIG_BUSMOUSE is not set -# CONFIG_MOUSE is not set # -# Joysticks +# I2C Hardware Sensors Chip support # -# CONFIG_INPUT_GAMEPORT is not set +# CONFIG_I2C_SENSOR is not set # -# Input core support is needed for gameports +# Mice # +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set # -# Input core support is needed for joysticks +# IPMI # -# CONFIG_QIC02_TAPE is not set +# CONFIG_IPMI_HANDLER is not set # # Watchdog Cards # -# CONFIG_WATCHDOG is not set -# CONFIG_INTEL_RNG is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set +# CONFIG_SOFT_WATCHDOG is not set +# CONFIG_WDT is not set +# CONFIG_WDTPCI is not set +# CONFIG_PCWATCHDOG is not set +# CONFIG_ACQUIRE_WDT is not set +# CONFIG_ADVANTECH_WDT is not set +# CONFIG_EUROTECH_WDT is not set +# CONFIG_IB700_WDT is not set +# CONFIG_I810_TCO is not set +# CONFIG_MIXCOMWD is not set +# CONFIG_SCx200_WDT is not set +# CONFIG_60XX_WDT is not set +# CONFIG_W83877F_WDT is not set +# CONFIG_MACHZ_WDT is not set +CONFIG_INDYDOG=y +# CONFIG_SC520_WDT is not set +# CONFIG_AMD7XX_TCO is not set +# CONFIG_ALIM7101_WDT is not set +# CONFIG_SC1200_WDT is not set +# CONFIG_WAFER_WDT is not set +# CONFIG_CPU5_WDT is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +CONFIG_SGI_DS1286=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set -# CONFIG_SONYPI is not set # # Ftape, the floppy tape device driver @@ -365,6 +452,8 @@ # CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HANGCHECK_TIMER is not set # # Multimedia devices @@ -372,78 +461,92 @@ # CONFIG_VIDEO_DEV is not set # +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# # File systems # +# CONFIG_EXT2_FS is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set CONFIG_AUTOFS_FS=y CONFIG_AUTOFS4_FS=y -# CONFIG_REISERFS_FS is not set -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +# CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# # CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set -# CONFIG_CMS_FS is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_JBD_DEBUG is not set -# CONFIG_FAT_FS is not set -# CONFIG_MSDOS_FS is not set -# CONFIG_UMSDOS_FS is not set -# CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -# CONFIG_JFFS2_FS is not set # CONFIG_CRAMFS is not set -# CONFIG_TMPFS is not set -# CONFIG_RAMFS is not set -CONFIG_ISO9660_FS=y -# CONFIG_JOLIET is not set -# CONFIG_MINIX_FS is not set -# CONFIG_FREEVXFS_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_DEBUG is not set -# CONFIG_NTFS_RW is not set +# CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set # # Network File Systems # -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=y # CONFIG_NFS_V3 is not set -CONFIG_ROOT_NFS=y +# CONFIG_NFS_V4 is not set CONFIG_NFSD=y # CONFIG_NFSD_V3 is not set -CONFIG_SUNRPC=y +# CONFIG_NFSD_TCP is not set +CONFIG_ROOT_NFS=y CONFIG_LOCKD=y +CONFIG_EXPORTFS=y +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set # CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set # CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set # # Partition Types @@ -460,150 +563,82 @@ # CONFIG_SOLARIS_X86_PARTITION is not set # CONFIG_UNIXWARE_DISKLABEL is not set # CONFIG_LDM_PARTITION is not set +# CONFIG_NEC98_PARTITION is not set CONFIG_SGI_PARTITION=y # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set -# CONFIG_SMB_NLS is not set -# CONFIG_NLS is not set +# CONFIG_EFI_PARTITION is not set # -# Console drivers +# Graphics support # # -# Frame-buffer support +# Console display driver support # -# CONFIG_FB is not set +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set CONFIG_SGI_NEWPORT_CONSOLE=y +CONFIG_DUMMY_CONSOLE=y CONFIG_FONT_8x16=y -CONFIG_KCORE_ELF=y # -# Sound +# Logo configuration # -# CONFIG_SOUND is not set +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +# CONFIG_LOGO_LINUX_CLUT224 is not set +CONFIG_LOGO_SGI_CLUT224=y # -# SGI devices +# Sound # -CONFIG_SGI_SERIAL=y -# CONFIG_SERIAL_CONSOLE is not set -CONFIG_SGI_DS1286=y -# CONFIG_SGI_NEWPORT_GFX is not set +# CONFIG_SOUND is not set # # USB support # -# CONFIG_USB is not set +# CONFIG_USB_GADGET is not set # -# USB Controllers +# Bluetooth support # -# CONFIG_USB_UHCI is not set -# CONFIG_USB_UHCI_ALT is not set -# CONFIG_USB_OHCI is not set +# CONFIG_BT is not set # -# USB Device Class drivers -# -# CONFIG_USB_AUDIO is not set -# CONFIG_USB_BLUETOOTH is not set -# CONFIG_USB_STORAGE is not set -# CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set -# CONFIG_USB_STORAGE_DPCM is not set -# CONFIG_USB_STORAGE_SDDR09 is not set -# CONFIG_USB_ACM is not set -# CONFIG_USB_PRINTER is not set - -# -# USB Human Interface Devices (HID) -# - -# -# Input core support is needed for USB HID -# - -# -# USB Imaging devices -# -# CONFIG_USB_DC2XX is not set -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_SCANNER is not set -# CONFIG_USB_MICROTEK is not set -# CONFIG_USB_HPUSBSCSI is not set - -# -# USB Multimedia devices -# - -# -# Video4Linux support is needed for USB Multimedia device support -# -# CONFIG_USB_DABUSB is not set - -# -# USB Network adaptors -# -# CONFIG_USB_PLUSB is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_CATC is not set -# CONFIG_USB_CDCETHER is not set -# CONFIG_USB_USBNET is not set - -# -# USB port drivers -# -# CONFIG_USB_USS720 is not set - -# -# USB Serial Converter support +# Kernel hacking # -# CONFIG_USB_SERIAL is not set -# CONFIG_USB_SERIAL_GENERIC is not set -# CONFIG_USB_SERIAL_BELKIN is not set -# CONFIG_USB_SERIAL_WHITEHEAT is not set -# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set -# CONFIG_USB_SERIAL_EMPEG is not set -# CONFIG_USB_SERIAL_FTDI_SIO is not set -# CONFIG_USB_SERIAL_VISOR is not set -# CONFIG_USB_SERIAL_EDGEPORT is not set -# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set -# CONFIG_USB_SERIAL_KEYSPAN is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set -# CONFIG_USB_SERIAL_MCT_U232 is not set -# CONFIG_USB_SERIAL_PL2303 is not set -# CONFIG_USB_SERIAL_CYBERJACK is not set -# CONFIG_USB_SERIAL_OMNINET is not set +CONFIG_CROSSCOMPILE=y +# CONFIG_DEBUG_KERNEL is not set # -# Miscellaneous USB drivers +# Security options # -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_ID75 is not set +# CONFIG_SECURITY is not set # -# Input core support +# Cryptographic options # -# CONFIG_INPUT is not set -# CONFIG_INPUT_KEYBDEV is not set -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_EVDEV is not set +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_BLOWFISH=y +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_SERPENT=y +CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_TEST is not set # -# Kernel hacking +# Library routines # -CONFIG_CROSSCOMPILE=y -# CONFIG_MIPS_FPE_MODULE is not set -# CONFIG_REMOTE_DEBUG is not set -# CONFIG_MAGIC_SYSRQ is not set -# CONFIG_MIPS_UNCACHED is not set +# CONFIG_CRC32 is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff -Nru a/arch/mips64/defconfig-ip27 b/arch/mips64/defconfig-ip27 --- a/arch/mips64/defconfig-ip27 Tue Jul 1 18:44:35 2003 +++ b/arch/mips64/defconfig-ip27 Tue Jul 1 18:44:35 2003 @@ -1,70 +1,133 @@ # # Automatically generated make config: don't edit # +CONFIG_MIPS=y +# CONFIG_MIPS32 is not set +CONFIG_MIPS64=y # # Code maturity level options # -# CONFIG_EXPERIMENTAL is not set +CONFIG_EXPERIMENTAL=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=15 +# CONFIG_EMBEDDED is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y + +# +# Loadable module support +# +# CONFIG_MODULES is not set # # Machine selection # +# CONFIG_ACER_PICA_61 is not set +# CONFIG_CASIO_E55 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_IBM_WORKPAD is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_NEC_EAGLE is not set +# CONFIG_OLIVETTI_M700 is not set # CONFIG_SGI_IP22 is not set CONFIG_SGI_IP27=y # CONFIG_SGI_SN0_N_MODE is not set -CONFIG_DISCONTIGMEM=y -CONFIG_NUMA=y +# CONFIG_DISCONTIGMEM is not set +# CONFIG_NUMA is not set # CONFIG_MAPPED_KERNEL is not set # CONFIG_REPLICATE_KTEXT is not set # CONFIG_REPLICATE_EXHANDLERS is not set -CONFIG_SMP=y +# CONFIG_SGI_IP32 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TANBAC_TB0226 is not set +# CONFIG_TANBAC_TB0229 is not set +# CONFIG_VICTOR_MPC30X is not set +# CONFIG_ZAO_CAPCELLA is not set CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set -CONFIG_BOOT_ELF64=y +CONFIG_ARC=y +CONFIG_GENERIC_ISA_DMA=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_L1_CACHE_SHIFT=7 +# CONFIG_FB is not set CONFIG_ARC64=y -CONFIG_COHERENT_IO=y -CONFIG_MAPPED_PCI_IO=y -CONFIG_PCI=y +CONFIG_BOOT_ELF64=y CONFIG_QL_ISP_A64=y -CONFIG_L1_CACHE_SHIFT=7 -# CONFIG_ISA is not set -# CONFIG_EISA is not set -# CONFIG_MCA is not set -# CONFIG_SBUS is not set # # CPU selection # +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set # CONFIG_CPU_R4300 is not set # CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set # CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set # CONFIG_CPU_NEVADA is not set # CONFIG_CPU_R8000 is not set CONFIG_CPU_R10000=y +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_SMP=y +CONFIG_NR_CPUS=4 +# CONFIG_PREEMPT is not set +CONFIG_KALLSYMS=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_MIPS_INSANE_LARGE is not set # -# General setup +# Bus options (PCI, PCMCIA, EISA, ISA, TC) # -# CONFIG_MIPS_INSANE_LARGE is not set -# CONFIG_CPU_LITTLE_ENDIAN is not set -CONFIG_NET=y +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y CONFIG_PCI_NAMES=y +CONFIG_MMU=y # CONFIG_HOTPLUG is not set -# CONFIG_PCMCIA is not set -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_BINFMT_ELF=y -CONFIG_MIPS32_COMPAT=y -CONFIG_BINFMT_ELF32=y -# CONFIG_BINFMT_MISC is not set # -# Loadable module support +# Executable file formats # -# CONFIG_MODULES is not set -CONFIG_PCI_NAMES=y +CONFIG_KCORE_ELF=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_MIPS32_COMPAT=y +CONFIG_COMPAT=y +CONFIG_MIPS32_O32=y +# CONFIG_MIPS32_N32 is not set +CONFIG_BINFMT_ELF32=y # # Memory Technology Devices (MTD) @@ -77,83 +140,35 @@ # CONFIG_PARPORT is not set # +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# # Block devices # # CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_RAM is not set # CONFIG_BLK_DEV_INITRD is not set # -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_BLK_DEV_LVM is not set - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -CONFIG_NETLINK=y -CONFIG_RTNETLINK=y -CONFIG_NETLINK_DEV=y -# CONFIG_NETFILTER is not set -# CONFIG_FILTER is not set -CONFIG_UNIX=y -CONFIG_INET=y -CONFIG_IP_MULTICAST=y -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -# CONFIG_IP_PNP_BOOTP is not set -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_IP_MROUTE is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set - -# -# -# -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set -# CONFIG_PHONE_IXJ is not set -# CONFIG_PHONE_IXJ_PCMCIA is not set - -# -# ATA/IDE/MFM/RLL support +# ATA/ATAPI/MFM/RLL support # # CONFIG_IDE is not set -# CONFIG_BLK_DEV_IDE_MODES is not set -# CONFIG_BLK_DEV_HD is not set # -# SCSI support +# SCSI device support # CONFIG_SCSI=y @@ -161,7 +176,6 @@ # SCSI support type (disk, tape, CD-ROM) # CONFIG_BLK_DEV_SD=y -CONFIG_SD_EXTRA_DEVS=40 CONFIG_CHR_DEV_ST=y # CONFIG_CHR_DEV_OSST is not set # CONFIG_BLK_DEV_SR is not set @@ -170,8 +184,8 @@ # # Some SCSI devices (e.g. CD jukebox) support multiple LUNs # -# CONFIG_SCSI_DEBUG_QUEUES is not set # CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_REPORT_LUNS is not set CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y @@ -179,52 +193,116 @@ # SCSI low-level drivers # # CONFIG_BLK_DEV_3W_XXXX_RAID is not set -# CONFIG_SCSI_7000FASST is not set # CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AHA152X is not set -# CONFIG_SCSI_AHA1542 is not set -# CONFIG_SCSI_AHA1740 is not set +# CONFIG_SCSI_AACRAID is not set # CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set # CONFIG_SCSI_DPT_I2O is not set # CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_AM53C974 is not set # CONFIG_SCSI_MEGARAID is not set # CONFIG_SCSI_BUSLOGIC is not set # CONFIG_SCSI_CPQFCTS is not set # CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_DTC3280 is not set # CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_DMA is not set # CONFIG_SCSI_EATA_PIO is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_GDTH is not set -# CONFIG_SCSI_GENERIC_NCR5380 is not set # CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_NCR_D700 is not set -# CONFIG_SCSI_NCR53C7xx is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set # CONFIG_SCSI_NCR53C8XX is not set # CONFIG_SCSI_SYM53C8XX is not set -# CONFIG_SCSI_PAS16 is not set # CONFIG_SCSI_PCI2000 is not set # CONFIG_SCSI_PCI2220I is not set -# CONFIG_SCSI_PSI240I is not set -# CONFIG_SCSI_QLOGIC_FAS is not set -CONFIG_SCSI_QLOGIC_ISP=y +# CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set -# CONFIG_SCSI_SIM710 is not set -# CONFIG_SCSI_SYM53C416 is not set +# CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set # -# Network device support +# IEEE 1394 (FireWire) support (EXPERIMENTAL) # +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_NETLINK_DEV=y +# CONFIG_NETFILTER is not set +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set CONFIG_NETDEVICES=y # @@ -235,39 +313,44 @@ # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set CONFIG_SGI_IOC3_ETH=y -# CONFIG_SUNLANCE is not set # CONFIG_HAPPYMEAL is not set -# CONFIG_SUNBMAC is not set -# CONFIG_SUNQE is not set -# CONFIG_SUNLANCE is not set # CONFIG_SUNGEM is not set # CONFIG_NET_VENDOR_3COM is not set -# CONFIG_LANCE is not set -# CONFIG_NET_VENDOR_SMC is not set -# CONFIG_NET_VENDOR_RACAL is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set # CONFIG_HP100 is not set -# CONFIG_NET_ISA is not set # CONFIG_NET_PCI is not set -# CONFIG_NET_POCKET is not set # # Ethernet (1000 Mbit) # # CONFIG_ACENIC is not set # CONFIG_DL2K is not set -# CONFIG_MYRI_SBUS is not set +# CONFIG_E1000 is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set # CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set # CONFIG_FDDI is not set -# CONFIG_PLIP is not set +# CONFIG_HIPPI is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set @@ -277,10 +360,11 @@ # CONFIG_NET_RADIO is not set # -# Token Ring devices +# Token Ring devices (depends on LLC=y) # -# CONFIG_TR is not set # CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set # # Wan interfaces @@ -300,21 +384,69 @@ # # ISDN subsystem # -# CONFIG_ISDN is not set +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set # -# Old CD-ROM drivers (not SCSI, not IDE) +# Input Device Drivers # -# CONFIG_CD_NO_IDESCSI is not set +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set # # Character devices # # CONFIG_VT is not set -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y -# CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +# CONFIG_SERIAL_8250_CONSOLE is not set +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +# CONFIG_SERIAL_8250_DETECT_IRQ is not set +# CONFIG_SERIAL_8250_MULTIPORT is not set +# CONFIG_SERIAL_8250_RSA is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y CONFIG_UNIX98_PTYS=y CONFIG_UNIX98_PTY_COUNT=256 @@ -324,32 +456,33 @@ # CONFIG_I2C is not set # -# Mice +# I2C Hardware Sensors Mainboard support # -# CONFIG_BUSMOUSE is not set -# CONFIG_MOUSE is not set # -# Joysticks +# I2C Hardware Sensors Chip support # -# CONFIG_INPUT_GAMEPORT is not set +# CONFIG_I2C_SENSOR is not set # -# Input core support is needed for gameports +# Mice # +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set # -# Input core support is needed for joysticks +# IPMI # -# CONFIG_QIC02_TAPE is not set +# CONFIG_IPMI_HANDLER is not set # # Watchdog Cards # # CONFIG_WATCHDOG is not set -# CONFIG_INTEL_RNG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +CONFIG_SGI_IP27_RTC=y # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set @@ -360,6 +493,8 @@ # CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HANGCHECK_TIMER is not set # # Multimedia devices @@ -367,79 +502,92 @@ # CONFIG_VIDEO_DEV is not set # +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# # File systems # +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_JBD=y +CONFIG_JBD_DEBUG=y +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set CONFIG_AUTOFS_FS=y # CONFIG_AUTOFS4_FS is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_REISERFS_CHECK is not set -# CONFIG_REISERFS_PROC_INFO is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# # CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set -# CONFIG_CMS_FS is not set -# CONFIG_EXT3_FS is not set -# CONFIG_JBD is not set -# CONFIG_JBD_DEBUG is not set -# CONFIG_FAT_FS is not set -# CONFIG_MSDOS_FS is not set -# CONFIG_UMSDOS_FS is not set -# CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -# CONFIG_JFFS2_FS is not set # CONFIG_CRAMFS is not set -# CONFIG_TMPFS is not set -# CONFIG_RAMFS is not set -# CONFIG_ISO9660_FS is not set -# CONFIG_JOLIET is not set -# CONFIG_MINIX_FS is not set -# CONFIG_FREEVXFS_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_DEBUG is not set -# CONFIG_NTFS_RW is not set +# CONFIG_VXFS_FS is not set # CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set # # Network File Systems # -# CONFIG_CODA_FS is not set -# CONFIG_INTERMEZZO_FS is not set CONFIG_NFS_FS=y CONFIG_NFS_V3=y -CONFIG_ROOT_NFS=y +# CONFIG_NFS_V4 is not set # CONFIG_NFSD is not set -# CONFIG_NFSD_V3 is not set -CONFIG_SUNRPC=y +CONFIG_ROOT_NFS=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set # CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set # CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set # # Partition Types @@ -456,12 +604,15 @@ # CONFIG_SOLARIS_X86_PARTITION is not set # CONFIG_UNIXWARE_DISKLABEL is not set # CONFIG_LDM_PARTITION is not set +# CONFIG_NEC98_PARTITION is not set CONFIG_SGI_PARTITION=y # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set -# CONFIG_SMB_NLS is not set -# CONFIG_NLS is not set -CONFIG_KCORE_ELF=y +# CONFIG_EFI_PARTITION is not set + +# +# Graphics support +# # # Sound @@ -472,113 +623,30 @@ # USB support # # CONFIG_USB is not set +# CONFIG_USB_GADGET is not set # -# USB Controllers +# Bluetooth support # -# CONFIG_USB_UHCI is not set -# CONFIG_USB_UHCI_ALT is not set -# CONFIG_USB_OHCI is not set +# CONFIG_BT is not set # -# USB Device Class drivers -# -# CONFIG_USB_AUDIO is not set -# CONFIG_USB_BLUETOOTH is not set -# CONFIG_USB_STORAGE is not set -# CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_STORAGE_DATAFAB is not set -# CONFIG_USB_STORAGE_FREECOM is not set -# CONFIG_USB_STORAGE_JUMPSHOT is not set -# CONFIG_USB_STORAGE_DPCM is not set -# CONFIG_USB_STORAGE_SDDR09 is not set -# CONFIG_USB_ACM is not set -# CONFIG_USB_PRINTER is not set - -# -# USB Human Interface Devices (HID) -# - -# -# Input core support is needed for USB HID -# - -# -# USB Imaging devices -# -# CONFIG_USB_DC2XX is not set -# CONFIG_USB_MDC800 is not set -# CONFIG_USB_SCANNER is not set -# CONFIG_USB_MICROTEK is not set -# CONFIG_USB_HPUSBSCSI is not set - -# -# USB Multimedia devices -# - -# -# Video4Linux support is needed for USB Multimedia device support -# -# CONFIG_USB_DABUSB is not set - -# -# USB Network adaptors -# -# CONFIG_USB_PLUSB is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_CATC is not set -# CONFIG_USB_CDCETHER is not set -# CONFIG_USB_USBNET is not set - -# -# USB port drivers -# -# CONFIG_USB_USS720 is not set - -# -# USB Serial Converter support +# Kernel hacking # -# CONFIG_USB_SERIAL is not set -# CONFIG_USB_SERIAL_GENERIC is not set -# CONFIG_USB_SERIAL_BELKIN is not set -# CONFIG_USB_SERIAL_WHITEHEAT is not set -# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set -# CONFIG_USB_SERIAL_EMPEG is not set -# CONFIG_USB_SERIAL_FTDI_SIO is not set -# CONFIG_USB_SERIAL_VISOR is not set -# CONFIG_USB_SERIAL_EDGEPORT is not set -# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set -# CONFIG_USB_SERIAL_KEYSPAN is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set -# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set -# CONFIG_USB_SERIAL_MCT_U232 is not set -# CONFIG_USB_SERIAL_PL2303 is not set -# CONFIG_USB_SERIAL_CYBERJACK is not set -# CONFIG_USB_SERIAL_OMNINET is not set +CONFIG_CROSSCOMPILE=y +# CONFIG_DEBUG_KERNEL is not set # -# Miscellaneous USB drivers +# Security options # -# CONFIG_USB_RIO500 is not set -# CONFIG_USB_ID75 is not set +# CONFIG_SECURITY is not set # -# Input core support +# Cryptographic options # -# CONFIG_INPUT is not set -# CONFIG_INPUT_KEYBDEV is not set -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_EVDEV is not set +# CONFIG_CRYPTO is not set # -# Kernel hacking +# Library routines # -CONFIG_CROSSCOMPILE=y -# CONFIG_REMOTE_DEBUG is not set -# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_CRC32 is not set diff -Nru a/arch/mips64/defconfig-ip32 b/arch/mips64/defconfig-ip32 --- a/arch/mips64/defconfig-ip32 Tue Jul 1 18:44:38 2003 +++ b/arch/mips64/defconfig-ip32 Tue Jul 1 18:44:38 2003 @@ -1,6 +1,9 @@ # # Automatically generated make config: don't edit # +CONFIG_MIPS=y +# CONFIG_MIPS32 is not set +CONFIG_MIPS64=y # # Code maturity level options @@ -8,57 +11,118 @@ CONFIG_EXPERIMENTAL=y # +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_EMBEDDED is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# # Machine selection # +# CONFIG_ACER_PICA_61 is not set +# CONFIG_CASIO_E55 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_IBM_WORKPAD is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_NEC_EAGLE is not set +# CONFIG_OLIVETTI_M700 is not set # CONFIG_SGI_IP22 is not set # CONFIG_SGI_IP27 is not set CONFIG_SGI_IP32=y +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TANBAC_TB0226 is not set +# CONFIG_TANBAC_TB0229 is not set +# CONFIG_VICTOR_MPC30X is not set +# CONFIG_ZAO_CAPCELLA is not set CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set +CONFIG_ARC=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_NONCOHERENT_IO=y +# CONFIG_CPU_LITTLE_ENDIAN is not set CONFIG_BOOT_ELF32=y +CONFIG_L1_CACHE_SHIFT=5 CONFIG_ARC32=y -CONFIG_PC_KEYB=y -CONFIG_PCI=y +# CONFIG_FB is not set CONFIG_ARC_MEMORY=y -CONFIG_L1_CACHE_SHIFT=5 -# CONFIG_ISA is not set -# CONFIG_EISA is not set -# CONFIG_MCA is not set -# CONFIG_SBUS is not set +CONFIG_ARC_PROMLIB=y +CONFIG_BOARD_SCACHE=y # # CPU selection # +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set # CONFIG_CPU_R4300 is not set # CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set CONFIG_CPU_R5000=y +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set # CONFIG_CPU_NEVADA is not set # CONFIG_CPU_R8000 is not set # CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_R5000_CPU_SCACHE=y +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +CONFIG_KALLSYMS=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set # -# General setup +# Bus options (PCI, PCMCIA, EISA, ISA, TC) # -# CONFIG_CPU_LITTLE_ENDIAN is not set -# CONFIG_MIPS_FPU_EMULATOR is not set -CONFIG_NET=y +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y CONFIG_PCI_NAMES=y +CONFIG_MMU=y # CONFIG_HOTPLUG is not set -# CONFIG_PCMCIA is not set -CONFIG_SYSVIPC=y -CONFIG_BSD_PROCESS_ACCT=y -CONFIG_SYSCTL=y -# CONFIG_PROM_CONSOLE is not set -CONFIG_BINFMT_ELF=y -CONFIG_MIPS32_COMPAT=y -CONFIG_BINFMT_ELF32=y -CONFIG_BINFMT_MISC=y # -# Loadable module support +# Executable file formats # -# CONFIG_MODULES is not set -CONFIG_PCI_NAMES=y +CONFIG_KCORE_ELF=y +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y +CONFIG_MIPS32_COMPAT=y +CONFIG_COMPAT=y +CONFIG_MIPS32_O32=y +# CONFIG_MIPS32_N32 is not set +CONFIG_BINFMT_ELF32=y # # Memory Technology Devices (MTD) @@ -71,90 +135,35 @@ # CONFIG_PARPORT is not set # +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# # Block devices # # CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_RAM is not set # CONFIG_BLK_DEV_INITRD is not set # -# Multi-device support (RAID and LVM) -# -# CONFIG_MD is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set -# CONFIG_BLK_DEV_LVM is not set - -# -# Networking options -# -CONFIG_PACKET=y -CONFIG_PACKET_MMAP=y -# CONFIG_NETLINK is not set -# CONFIG_NETFILTER is not set -# CONFIG_FILTER is not set -CONFIG_UNIX=y -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -# CONFIG_IP_PNP_DHCP is not set -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_INET_ECN is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_IPV6 is not set -# CONFIG_KHTTPD is not set -# CONFIG_ATM is not set - -# -# -# -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_LLC is not set -# CONFIG_NET_DIVERT is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Telephony Support -# -# CONFIG_PHONE is not set -# CONFIG_PHONE_IXJ is not set - -# -# ATA/IDE/MFM/RLL support +# ATA/ATAPI/MFM/RLL support # # CONFIG_IDE is not set -# CONFIG_BLK_DEV_IDE_MODES is not set -# CONFIG_BLK_DEV_HD is not set # -# SCSI support +# SCSI device support # CONFIG_SCSI=y @@ -162,19 +171,17 @@ # SCSI support type (disk, tape, CD-ROM) # CONFIG_BLK_DEV_SD=y -CONFIG_SD_EXTRA_DEVS=40 CONFIG_CHR_DEV_ST=y CONFIG_CHR_DEV_OSST=y CONFIG_BLK_DEV_SR=y CONFIG_BLK_DEV_SR_VENDOR=y -CONFIG_SR_EXTRA_DEVS=2 CONFIG_CHR_DEV_SG=y # # Some SCSI devices (e.g. CD jukebox) support multiple LUNs # -CONFIG_SCSI_DEBUG_QUEUES=y CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_REPORT_LUNS is not set CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y @@ -182,63 +189,122 @@ # SCSI low-level drivers # # CONFIG_BLK_DEV_3W_XXXX_RAID is not set -# CONFIG_SCSI_7000FASST is not set # CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AHA152X is not set -# CONFIG_SCSI_AHA1542 is not set -# CONFIG_SCSI_AHA1740 is not set +# CONFIG_SCSI_AACRAID is not set CONFIG_SCSI_AIC7XXX=y CONFIG_AIC7XXX_CMDS_PER_DEVICE=8 CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC7XXX_PROBE_EISA_VL is not set # CONFIG_AIC7XXX_BUILD_FIRMWARE is not set +CONFIG_AIC7XXX_DEBUG_ENABLE=y +CONFIG_AIC7XXX_DEBUG_MASK=0 +CONFIG_AIC7XXX_REG_PRETTY_PRINT=y +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_DPT_I2O is not set # CONFIG_SCSI_ADVANSYS is not set -# CONFIG_SCSI_IN2000 is not set -# CONFIG_SCSI_AM53C974 is not set # CONFIG_SCSI_MEGARAID is not set # CONFIG_SCSI_BUSLOGIC is not set # CONFIG_SCSI_CPQFCTS is not set # CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_DTC3280 is not set # CONFIG_SCSI_EATA is not set -# CONFIG_SCSI_EATA_DMA is not set # CONFIG_SCSI_EATA_PIO is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_GDTH is not set -# CONFIG_SCSI_GENERIC_NCR5380 is not set # CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_NCR53C7xx is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set # CONFIG_SCSI_NCR53C8XX is not set # CONFIG_SCSI_SYM53C8XX is not set -# CONFIG_SCSI_PAS16 is not set # CONFIG_SCSI_PCI2000 is not set # CONFIG_SCSI_PCI2220I is not set -# CONFIG_SCSI_PSI240I is not set -# CONFIG_SCSI_QLOGIC_FAS is not set # CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set -# CONFIG_SCSI_SIM710 is not set -# CONFIG_SCSI_SYM53C416 is not set +# CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_T128 is not set -# CONFIG_SCSI_U14_34F is not set +# CONFIG_SCSI_NSP32 is not set # CONFIG_SCSI_DEBUG is not set # +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# # I2O device support # # CONFIG_I2O is not set -# CONFIG_I2O_PCI is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set # -# Network device support +# Networking support # +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_NETLINK_DEV=y +# CONFIG_NETFILTER is not set +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +# CONFIG_IP_PNP_DHCP is not set +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set CONFIG_NETDEVICES=y # @@ -249,58 +315,42 @@ # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set -# CONFIG_NET_SB1000 is not set +# CONFIG_ETHERTAP is not set # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +CONFIG_SGI_O2MACE_ETH=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set # CONFIG_NET_VENDOR_3COM is not set -# CONFIG_LANCE is not set -# CONFIG_NET_VENDOR_SMC is not set -# CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_AT1700 is not set -# CONFIG_DEPCA is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set # CONFIG_HP100 is not set -# CONFIG_NET_ISA is not set -CONFIG_NET_PCI=y -# CONFIG_PCNET32 is not set -# CONFIG_ADAPTEC_STARFIRE is not set -# CONFIG_APRICOT is not set -# CONFIG_CS89x0 is not set -CONFIG_TULIP=y -# CONFIG_DE4X5 is not set -# CONFIG_DGRS is not set -# CONFIG_DM9102 is not set -CONFIG_EEPRO100=y -# CONFIG_EEPRO100_PM is not set -# CONFIG_LNE390 is not set -# CONFIG_FEALNX is not set -# CONFIG_NATSEMI is not set -# CONFIG_NE2K_PCI is not set -# CONFIG_NE3210 is not set -# CONFIG_ES3210 is not set -# CONFIG_8139TOO is not set -# CONFIG_8139TOO_PIO is not set -# CONFIG_8139TOO_TUNE_TWISTER is not set -# CONFIG_8139TOO_8129 is not set -# CONFIG_SIS900 is not set -# CONFIG_EPIC100 is not set -# CONFIG_SUNDANCE is not set -# CONFIG_TLAN is not set -# CONFIG_VIA_RHINE is not set -# CONFIG_WINBOND_840 is not set -# CONFIG_HAPPYMEAL is not set -# CONFIG_LAN_SAA9730 is not set -# CONFIG_NET_POCKET is not set +# CONFIG_NET_PCI is not set # # Ethernet (1000 Mbit) # # CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set # CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set # CONFIG_PPP is not set @@ -312,9 +362,8 @@ # CONFIG_NET_RADIO is not set # -# Token Ring devices +# Token Ring devices (depends on LLC=y) # -# CONFIG_TR is not set # CONFIG_NET_FC is not set # CONFIG_RCPCI is not set # CONFIG_SHAPER is not set @@ -337,21 +386,65 @@ # # ISDN subsystem # -# CONFIG_ISDN is not set +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set # -# Old CD-ROM drivers (not SCSI, not IDE) +# Input device support # -# CONFIG_CD_NO_IDESCSI is not set +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set # # Character devices # # CONFIG_VT is not set -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y -# CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y CONFIG_UNIX98_PTY_COUNT=256 @@ -361,31 +454,32 @@ # CONFIG_I2C is not set # -# Mice +# I2C Hardware Sensors Mainboard support # -# CONFIG_BUSMOUSE is not set -CONFIG_MOUSE=y -CONFIG_PSMOUSE=y -# CONFIG_82C710_MOUSE is not set -# CONFIG_PC110_PAD is not set # -# Joysticks +# I2C Hardware Sensors Chip support # -# CONFIG_JOYSTICK is not set +# CONFIG_I2C_SENSOR is not set # -# Input core support is needed for joysticks +# Mice # +# CONFIG_BUSMOUSE is not set # CONFIG_QIC02_TAPE is not set # +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# # Watchdog Cards # # CONFIG_WATCHDOG is not set -# CONFIG_INTEL_RNG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set @@ -396,6 +490,8 @@ # CONFIG_FTAPE is not set # CONFIG_AGP is not set # CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HANGCHECK_TIMER is not set # # Multimedia devices @@ -403,73 +499,84 @@ # CONFIG_VIDEO_DEV is not set # +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# # File systems # +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_REISERFS_CHECK is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +CONFIG_TMPFS=y +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# # CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set -# CONFIG_FAT_FS is not set -# CONFIG_MSDOS_FS is not set -# CONFIG_UMSDOS_FS is not set -# CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set # CONFIG_CRAMFS is not set -CONFIG_TMPFS=y -# CONFIG_RAMFS is not set -# CONFIG_ISO9660_FS is not set -# CONFIG_JOLIET is not set -# CONFIG_MINIX_FS is not set # CONFIG_VXFS_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_DEBUG is not set -# CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set -# CONFIG_SYSV_FS_WRITE is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set # # Network File Systems # -# CONFIG_CODA_FS is not set CONFIG_NFS_FS=y CONFIG_NFS_V3=y -CONFIG_ROOT_NFS=y +# CONFIG_NFS_V4 is not set # CONFIG_NFSD is not set -# CONFIG_NFSD_V3 is not set -CONFIG_SUNRPC=y +CONFIG_ROOT_NFS=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set # CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set # CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set # # Partition Types @@ -481,12 +588,16 @@ # CONFIG_ATARI_PARTITION is not set # CONFIG_MAC_PARTITION is not set # CONFIG_MSDOS_PARTITION is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_NEC98_PARTITION is not set CONFIG_SGI_PARTITION=y # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set -# CONFIG_SMB_NLS is not set -# CONFIG_NLS is not set -CONFIG_KCORE_ELF=y +# CONFIG_EFI_PARTITION is not set + +# +# Graphics support +# # # Sound @@ -497,16 +608,30 @@ # USB support # # CONFIG_USB is not set +# CONFIG_USB_GADGET is not set # -# Input core support +# Bluetooth support # -# CONFIG_INPUT is not set +# CONFIG_BT is not set # # Kernel hacking # CONFIG_CROSSCOMPILE=y -# CONFIG_REMOTE_DEBUG is not set -CONFIG_MAGIC_SYSRQ=y -CONFIG_MIPS_UNCACHED=y +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set diff -Nru a/arch/mips64/defconfig-malta b/arch/mips64/defconfig-malta --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips64/defconfig-malta Tue Jul 1 18:44:40 2003 @@ -0,0 +1,558 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS32 is not set +CONFIG_MIPS64=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_EMBEDDED is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_ACER_PICA_61 is not set +# CONFIG_CASIO_E55 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_IBM_WORKPAD is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MAGNUM_4000 is not set +CONFIG_MIPS_MALTA=y +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_NEC_EAGLE is not set +# CONFIG_OLIVETTI_M700 is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP27 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TANBAC_TB0226 is not set +# CONFIG_TANBAC_TB0229 is not set +# CONFIG_VICTOR_MPC30X is not set +# CONFIG_ZAO_CAPCELLA is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_I8259=y +CONFIG_NONCOHERENT_IO=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_MIPS_BOARDS_GEN=y +CONFIG_SWAP_IO_SPACE=y +CONFIG_BOOT_ELF32=y +CONFIG_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set +CONFIG_HAVE_STD_PC_SERIAL_PORT=y + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +CONFIG_CPU_R4X00=y +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +CONFIG_KALLSYMS=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +# CONFIG_PCI is not set +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_KCORE_ELF=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_MIPS32_COMPAT=y +CONFIG_COMPAT=y +CONFIG_MIPS32_O32=y +# CONFIG_MIPS32_N32 is not set +CONFIG_BINFMT_ELF32=y + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# +# Block devices +# +CONFIG_BLK_DEV_FD=y +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_INITRD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_SCSI=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_REPORT_LUNS is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI low-level drivers +# +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# I2O device support +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +# CONFIG_PACKET is not set +CONFIG_NETLINK_DEV=y +# CONFIG_NETFILTER is not set +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set + +# +# Ethernet (1000 Mbit) +# + +# +# Ethernet (10000 Mbit) +# +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices (depends on LLC=y) +# +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# I2C Hardware Sensors Mainboard support +# + +# +# I2C Hardware Sensors Chip support +# +# CONFIG_I2C_SENSOR is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +CONFIG_RTC=y +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HANGCHECK_TIMER is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=y +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +CONFIG_DEVPTS_FS_SECURITY=y +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +CONFIG_EFS_FS=y +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V4 is not set +CONFIG_NFSD=y +CONFIG_NFSD_V3=y +# CONFIG_NFSD_V4 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_ROOT_NFS=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=y +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Graphics support +# + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB_GADGET is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set diff -Nru a/arch/mips64/defconfig-sb1250-swarm b/arch/mips64/defconfig-sb1250-swarm --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips64/defconfig-sb1250-swarm Tue Jul 1 18:44:40 2003 @@ -0,0 +1,611 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS32 is not set +CONFIG_MIPS64=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=15 +# CONFIG_EMBEDDED is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Machine selection +# +# CONFIG_ACER_PICA_61 is not set +# CONFIG_CASIO_E55 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_IBM_WORKPAD is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MIPS_MALTA is not set +# CONFIG_MIPS_SEAD is not set +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_NEC_EAGLE is not set +# CONFIG_OLIVETTI_M700 is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP27 is not set +# CONFIG_SGI_IP32 is not set +CONFIG_SIBYTE_SB1xxx_SOC=y +CONFIG_SIBYTE_SB1250=y +# CONFIG_SIMULATION is not set +CONFIG_SIBYTE_CFE=y +# CONFIG_SIBYTE_CFE_CONSOLE is not set +# CONFIG_SIBYTE_BUS_WATCHER is not set +# CONFIG_SIBYTE_SB1250_PROF is not set +# CONFIG_SIBYTE_TBPROF is not set +CONFIG_SIBYTE_SWARM=y +CONFIG_SIBYTE_BOARD=y +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TANBAC_TB0226 is not set +# CONFIG_TANBAC_TB0229 is not set +# CONFIG_VICTOR_MPC30X is not set +# CONFIG_ZAO_CAPCELLA is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +CONFIG_DUMMY_KEYB=y +CONFIG_SWAP_IO_SPACE=y +CONFIG_BOOT_ELF32=y +# CONFIG_FB is not set + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +CONFIG_CPU_SB1=y +CONFIG_CPU_HAS_PREFETCH=y +CONFIG_VTAG_ICACHE=y +CONFIG_CPU_SB1_PASS_1=y +# CONFIG_CPU_SB1_PASS_2 is not set +# CONFIG_CPU_SB1_PASS_2_2 is not set +CONFIG_SB1_PASS_1_WORKAROUNDS=y +CONFIG_SB1_CACHE_ERROR=y +CONFIG_SB1_CERR_IGNORE_RECOVERABLE=y +# CONFIG_SB1_CERR_SPIN is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_SMP=y +CONFIG_NR_CPUS=2 +# CONFIG_PREEMPT is not set +CONFIG_KALLSYMS=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_PCI=y +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_KCORE_ELF=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_MIPS32_COMPAT=y +CONFIG_COMPAT=y +CONFIG_MIPS32_O32=y +# CONFIG_MIPS32_N32 is not set +CONFIG_BINFMT_ELF32=y + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=9220 +# CONFIG_BLK_DEV_INITRD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +CONFIG_PACKET_MMAP=y +CONFIG_NETLINK_DEV=y +# CONFIG_NETFILTER is not set +CONFIG_UNIX=y +CONFIG_NET_KEY=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +# CONFIG_INET_ESP is not set +# CONFIG_INET_IPCOMP is not set +# CONFIG_IPV6 is not set +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_ETHERTAP is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +CONFIG_NET_SB1250_MAC=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices (depends on LLC=y) +# +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +# CONFIG_VT is not set +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_COMPUTONE is not set +# CONFIG_ROCKETPORT is not set +# CONFIG_CYCLADES is not set +# CONFIG_DIGIEPCA is not set +# CONFIG_DIGI is not set +# CONFIG_MOXA_INTELLIO is not set +# CONFIG_MOXA_SMARTIO is not set +# CONFIG_ISI is not set +# CONFIG_SYNCLINK is not set +# CONFIG_SYNCLINKMP is not set +# CONFIG_N_HDLC is not set +# CONFIG_RISCOM8 is not set +# CONFIG_SPECIALIX is not set +# CONFIG_SX is not set +# CONFIG_RIO is not set +# CONFIG_STALDRV is not set +CONFIG_SIBYTE_SB1250_DUART=y +CONFIG_SIBYTE_SB1250_DUART_CONSOLE=y +CONFIG_SERIAL_CONSOLE=y + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_UNIX98_PTYS is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# I2C Hardware Sensors Mainboard support +# + +# +# I2C Hardware Sensors Chip support +# +# CONFIG_I2C_SENSOR is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HANGCHECK_TIMER is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V4 is not set +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +# CONFIG_EXPORTFS is not set +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_GSS is not set +# CONFIG_SMB_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Graphics support +# + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set +# CONFIG_USB_GADGET is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_BLOWFISH=y +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_SERPENT=y +CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_TEST is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y diff -Nru a/arch/mips64/defconfig-sead b/arch/mips64/defconfig-sead --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips64/defconfig-sead Tue Jul 1 18:44:40 2003 @@ -0,0 +1,391 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_MIPS=y +# CONFIG_MIPS32 is not set +CONFIG_MIPS64=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# General setup +# +CONFIG_SWAP=y +# CONFIG_SYSVIPC is not set +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_EMBEDDED is not set +CONFIG_FUTEX=y +CONFIG_EPOLL=y + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# Machine selection +# +# CONFIG_ACER_PICA_61 is not set +# CONFIG_CASIO_E55 is not set +# CONFIG_MIPS_COBALT is not set +# CONFIG_DECSTATION is not set +# CONFIG_MIPS_EV64120 is not set +# CONFIG_MIPS_EV96100 is not set +# CONFIG_MIPS_IVR is not set +# CONFIG_LASAT is not set +# CONFIG_HP_LASERJET is not set +# CONFIG_IBM_WORKPAD is not set +# CONFIG_MIPS_ITE8172 is not set +# CONFIG_MIPS_ATLAS is not set +# CONFIG_MIPS_MAGNUM_4000 is not set +# CONFIG_MIPS_MALTA is not set +CONFIG_MIPS_SEAD=y +# CONFIG_MOMENCO_OCELOT is not set +# CONFIG_MOMENCO_OCELOT_G is not set +# CONFIG_MOMENCO_OCELOT_C is not set +# CONFIG_DDB5074 is not set +# CONFIG_DDB5476 is not set +# CONFIG_DDB5477 is not set +# CONFIG_NEC_OSPREY is not set +# CONFIG_NEC_EAGLE is not set +# CONFIG_OLIVETTI_M700 is not set +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP27 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SIBYTE_SB1xxx_SOC is not set +# CONFIG_SNI_RM200_PCI is not set +# CONFIG_TANBAC_TB0226 is not set +# CONFIG_TANBAC_TB0229 is not set +# CONFIG_VICTOR_MPC30X is not set +# CONFIG_ZAO_CAPCELLA is not set +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_NONCOHERENT_IO=y +CONFIG_CPU_LITTLE_ENDIAN=y +CONFIG_MIPS_BOARDS_GEN=y +CONFIG_L1_CACHE_SHIFT=5 +# CONFIG_FB is not set + +# +# CPU selection +# +# CONFIG_CPU_MIPS32 is not set +# CONFIG_CPU_MIPS64 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_VR41XX is not set +# CONFIG_CPU_R4300 is not set +CONFIG_CPU_R4X00=y +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_LLDSCD=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_PREEMPT is not set +CONFIG_KALLSYMS=y +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set + +# +# Bus options (PCI, PCMCIA, EISA, ISA, TC) +# +CONFIG_MMU=y +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_KCORE_ELF=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_MIPS32_COMPAT=y +CONFIG_COMPAT=y +CONFIG_MIPS32_O32=y +# CONFIG_MIPS32_N32 is not set +CONFIG_BINFMT_ELF32=y + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=18432 +CONFIG_BLK_DEV_INITRD=y + +# +# MIPS initrd options +# +# CONFIG_EMBEDDED_RAMDISK is not set + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Fusion MPT device support +# + +# +# I2O device support +# + +# +# Networking support +# +# CONFIG_NET is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# ISDN subsystem +# + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +# CONFIG_VT is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_UNIX98_PTYS is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# I2C Hardware Sensors Mainboard support +# + +# +# I2C Hardware Sensors Chip support +# +# CONFIG_I2C_SENSOR is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HANGCHECK_TIMER is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_TMPFS is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Graphics support +# + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB_GADGET is not set + +# +# Kernel hacking +# +CONFIG_CROSSCOMPILE=y +# CONFIG_DEBUG_KERNEL is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set diff -Nru a/arch/mips64/kernel/Makefile b/arch/mips64/kernel/Makefile --- a/arch/mips64/kernel/Makefile Tue Jul 1 18:44:34 2003 +++ b/arch/mips64/kernel/Makefile Tue Jul 1 18:44:34 2003 @@ -2,18 +2,29 @@ # Makefile for the Linux/MIPS kernel. # -extra-y := head.o init_task.o +extra-y := head.o init_task.o -obj-y := branch.o entry.o proc.o process.o ptrace.o r4k_cache.o r4k_fpu.o \ - r4k_genex.o r4k_switch.o r4k_tlb.o r4k_tlb_debug.o r4k_tlb_glue.o \ - scall_64.o semaphore.o setup.o signal.o softfp.o syscall.o \ - traps.o unaligned.o +obj-y := branch.o cpu-probe.o entry.o irq.o proc.o process.o \ + ptrace.o r4k_cache.o r4k_fpu.o r4k_genex.o r4k_switch.o \ + reset.o scall_64.o semaphore.o setup.o signal.o syscall.o \ + time.o traps.o unaligned.o + +obj-$(CONFIG_I8259) += i8259.o +obj-$(CONFIG_IRQ_CPU) += irq_cpu.o obj-$(CONFIG_MODULES) += mips64_ksyms.o -obj-$(CONFIG_MIPS32_COMPAT) += linux32.o scall_o32.o signal32.o ioctl32.o -obj-$(CONFIG_BINFMT_ELF32) += binfmt_elf32.o +obj-$(CONFIG_MIPS32_COMPAT) += linux32.o signal32.o ioctl32.o +obj-$(CONFIG_MIPS32_N32) += binfmt_elfn32.o scall_n32.o +obj-$(CONFIG_MIPS32_O32) += binfmt_elfo32.o scall_o32.o obj-$(CONFIG_SMP) += smp.o -AFLAGS_r4k_genex.o := -P -AFLAGS_r4k_tlb_glue.o := -P +ifndef CONFIG_MAPPED_PCI_IO +obj-y += pci-dma.o +endif + +obj-$(CONFIG_MODULES) += module.o + +CFLAGS_cpu-probe.o = $(shell if $(CC) $(CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi) +AFLAGS_r4k_genex.o = -P + EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips64/kernel/binfmt_elf32.c b/arch/mips64/kernel/binfmt_elf32.c --- a/arch/mips64/kernel/binfmt_elf32.c Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,99 +0,0 @@ -/* - * Support for 32-bit Linux/MIPS ELF binaries. - * - * Copyright (C) 1999, 2001 Ralf Baechle - * Copyright (C) 1999, 2001 Silicon Graphics, Inc. - * - * Heavily inspired by the 32-bit Sparc compat code which is - * Copyright (C) 1995, 1996, 1997, 1998 David S. Miller (davem@redhat.com) - * Copyright (C) 1995, 1996, 1997, 1998 Jakub Jelinek (jj@ultra.linux.cz) - */ - -#define ELF_ARCH EM_MIPS -#define ELF_CLASS ELFCLASS32 -#ifdef __MIPSEB__ -#define ELF_DATA ELFDATA2MSB; -#else /* __MIPSEL__ */ -#define ELF_DATA ELFDATA2LSB; -#endif - -/* ELF register definitions */ -#define ELF_NGREG 45 -#define ELF_NFPREG 33 - -typedef unsigned int elf_greg_t; -typedef elf_greg_t elf_gregset_t[ELF_NGREG]; - -typedef double elf_fpreg_t; -typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; - -#define elf_check_arch(x) \ - ((x)->e_machine == EM_MIPS) - -#define TASK32_SIZE 0x80000000UL -#undef ELF_ET_DYN_BASE -#define ELF_ET_DYN_BASE (TASK32_SIZE / 3 * 2) - -#include -#include -#include -#include - -struct timeval32 -{ - unsigned int tv_sec, tv_usec; -}; - -#define elf_prstatus elf_prstatus32 -struct elf_prstatus32 -{ - struct elf_siginfo pr_info; /* Info associated with signal */ - short pr_cursig; /* Current signal */ - unsigned int pr_sigpend; /* Set of pending signals */ - unsigned int pr_sighold; /* Set of held signals */ - pid_t pr_pid; - pid_t pr_ppid; - pid_t pr_pgrp; - pid_t pr_sid; - struct timeval32 pr_utime; /* User time */ - struct timeval32 pr_stime; /* System time */ - struct timeval32 pr_cutime; /* Cumulative user time */ - struct timeval32 pr_cstime; /* Cumulative system time */ - elf_gregset_t pr_reg; /* GP registers */ - int pr_fpvalid; /* True if math co-processor being used. */ -}; - -#define elf_prpsinfo elf_prpsinfo32 -struct elf_prpsinfo32 -{ - char pr_state; /* numeric process state */ - char pr_sname; /* char for pr_state */ - char pr_zomb; /* zombie */ - char pr_nice; /* nice val */ - unsigned int pr_flag; /* flags */ - u16 pr_uid; - u16 pr_gid; - pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid; - /* Lots missing */ - char pr_fname[16]; /* filename of executable */ - char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */ -}; - -#define elf_addr_t u32 -#define init_elf_binfmt init_elf32_binfmt -#undef CONFIG_BINFMT_ELF -#ifdef CONFIG_BINFMT_ELF32 -#define CONFIG_BINFMT_ELF CONFIG_BINFMT_ELF32 -#endif -#undef CONFIG_BINFMT_ELF_MODULE -#ifdef CONFIG_BINFMT_ELF32_MODULE -#define CONFIG_BINFMT_ELF_MODULE CONFIG_BINFMT_ELF32_MODULE -#endif - -MODULE_DESCRIPTION("Binary format loader for compatibility with 32bit Linux/MIPS binaries"); -MODULE_AUTHOR("Ralf Baechle (ralf@oss.sgi.com)"); - -#undef MODULE_DESCRIPTION -#undef MODULE_AUTHOR - -#include "../../../fs/binfmt_elf.c" diff -Nru a/arch/mips64/kernel/binfmt_elfn32.c b/arch/mips64/kernel/binfmt_elfn32.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips64/kernel/binfmt_elfn32.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,115 @@ +/* + * Support for n32 Linux/MIPS ELF binaries. + * + * Copyright (C) 1999, 2001 Ralf Baechle + * Copyright (C) 1999, 2001 Silicon Graphics, Inc. + * + * Heavily inspired by the 32-bit Sparc compat code which is + * Copyright (C) 1995, 1996, 1997, 1998 David S. Miller (davem@redhat.com) + * Copyright (C) 1995, 1996, 1997, 1998 Jakub Jelinek (jj@ultra.linux.cz) + */ + +#define ELF_ARCH EM_MIPS +#define ELF_CLASS ELFCLASS32 +#ifdef __MIPSEB__ +#define ELF_DATA ELFDATA2MSB; +#else /* __MIPSEL__ */ +#define ELF_DATA ELFDATA2LSB; +#endif + +/* ELF register definitions */ +#define ELF_NGREG 45 +#define ELF_NFPREG 33 + +typedef unsigned long elf_greg_t; +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +typedef double elf_fpreg_t; +typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; + +/* + * This is used to ensure we don't load something for the wrong architecture. + */ +#define elf_check_arch(hdr) \ +({ \ + int __res = 1; \ + struct elfhdr *__h = (hdr); \ + \ + if (__h->e_machine != EM_MIPS) \ + __res = 0; \ + if (__h->e_ident[EI_CLASS] != ELFCLASS32) \ + __res = 0; \ + if (((__h->e_flags & EF_MIPS_ABI2) == 0) || \ + ((__h->e_flags & EF_MIPS_ABI) != 0)) \ + __res = 0; \ + \ + __res; \ +}) + +#define TASK32_SIZE 0x7fff8000UL +#undef ELF_ET_DYN_BASE +#define ELF_ET_DYN_BASE (TASK32_SIZE / 3 * 2) + +#include +#include +#include +#include +#include + +#define elf_prstatus elf_prstatus32 +struct elf_prstatus32 +{ + struct elf_siginfo pr_info; /* Info associated with signal */ + short pr_cursig; /* Current signal */ + unsigned int pr_sigpend; /* Set of pending signals */ + unsigned int pr_sighold; /* Set of held signals */ + pid_t pr_pid; + pid_t pr_ppid; + pid_t pr_pgrp; + pid_t pr_sid; + struct compat_timeval pr_utime; /* User time */ + struct compat_timeval pr_stime; /* System time */ + struct compat_timeval pr_cutime;/* Cumulative user time */ + struct compat_timeval pr_cstime;/* Cumulative system time */ + elf_gregset_t pr_reg; /* GP registers */ + int pr_fpvalid; /* True if math co-processor being used. */ +}; + +#define elf_prpsinfo elf_prpsinfo32 +struct elf_prpsinfo32 +{ + char pr_state; /* numeric process state */ + char pr_sname; /* char for pr_state */ + char pr_zomb; /* zombie */ + char pr_nice; /* nice val */ + unsigned int pr_flag; /* flags */ + __kernel_uid_t pr_uid; + __kernel_gid_t pr_gid; + pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* filename of executable */ + char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */ +}; + +#define elf_addr_t u32 +#define elf_caddr_t u32 +#define init_elf_binfmt init_elfn32_binfmt + +#define ELF_CORE_EFLAGS EF_MIPS_ABI2 + +#undef CONFIG_BINFMT_ELF +#ifdef CONFIG_BINFMT_ELF32 +#define CONFIG_BINFMT_ELF CONFIG_BINFMT_ELF32 +#endif +#undef CONFIG_BINFMT_ELF_MODULE +#ifdef CONFIG_BINFMT_ELF32_MODULE +#define CONFIG_BINFMT_ELF_MODULE CONFIG_BINFMT_ELF32_MODULE +#endif + +MODULE_DESCRIPTION("Binary format loader for compatibility with n32 Linux/MIPS binaries"); +MODULE_AUTHOR("Ralf Baechle (ralf@linux-mips.org)"); + +#undef MODULE_DESCRIPTION +#undef MODULE_AUTHOR + +#include "../../../fs/binfmt_elf.c" diff -Nru a/arch/mips64/kernel/binfmt_elfo32.c b/arch/mips64/kernel/binfmt_elfo32.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips64/kernel/binfmt_elfo32.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,136 @@ +/* + * Support for o32 Linux/MIPS ELF binaries. + * + * Copyright (C) 1999, 2001 Ralf Baechle + * Copyright (C) 1999, 2001 Silicon Graphics, Inc. + * + * Heavily inspired by the 32-bit Sparc compat code which is + * Copyright (C) 1995, 1996, 1997, 1998 David S. Miller (davem@redhat.com) + * Copyright (C) 1995, 1996, 1997, 1998 Jakub Jelinek (jj@ultra.linux.cz) + */ + +#define ELF_ARCH EM_MIPS +#define ELF_CLASS ELFCLASS32 +#ifdef __MIPSEB__ +#define ELF_DATA ELFDATA2MSB; +#else /* __MIPSEL__ */ +#define ELF_DATA ELFDATA2LSB; +#endif + +/* ELF register definitions */ +#define ELF_NGREG 45 +#define ELF_NFPREG 33 + +typedef unsigned int elf_greg_t; +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +typedef double elf_fpreg_t; +typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; + +/* + * This is used to ensure we don't load something for the wrong architecture. + */ +#define elf_check_arch(hdr) \ +({ \ + int __res = 1; \ + struct elfhdr *__h = (hdr); \ + \ + if (__h->e_machine != EM_MIPS) \ + __res = 0; \ + if (__h->e_ident[EI_CLASS] != ELFCLASS32) \ + __res = 0; \ + if ((__h->e_flags & EF_MIPS_ABI2) != 0) \ + __res = 0; \ + if (((__h->e_flags & EF_MIPS_ABI) != 0) && \ + ((__h->e_flags & EF_MIPS_ABI) != EF_MIPS_ABI_O32)) \ + __res = 0; \ + \ + __res; \ +}) + +#define TASK32_SIZE 0x7fff8000UL +#undef ELF_ET_DYN_BASE +#define ELF_ET_DYN_BASE (TASK32_SIZE / 3 * 2) + +#include +#include +#include +#include +#include + +#define elf_prstatus elf_prstatus32 +struct elf_prstatus32 +{ + struct elf_siginfo pr_info; /* Info associated with signal */ + short pr_cursig; /* Current signal */ + unsigned int pr_sigpend; /* Set of pending signals */ + unsigned int pr_sighold; /* Set of held signals */ + pid_t pr_pid; + pid_t pr_ppid; + pid_t pr_pgrp; + pid_t pr_sid; + struct compat_timeval pr_utime; /* User time */ + struct compat_timeval pr_stime; /* System time */ + struct compat_timeval pr_cutime;/* Cumulative user time */ + struct compat_timeval pr_cstime;/* Cumulative system time */ + elf_gregset_t pr_reg; /* GP registers */ + int pr_fpvalid; /* True if math co-processor being used. */ +}; + +#define elf_prpsinfo elf_prpsinfo32 +struct elf_prpsinfo32 +{ + char pr_state; /* numeric process state */ + char pr_sname; /* char for pr_state */ + char pr_zomb; /* zombie */ + char pr_nice; /* nice val */ + unsigned int pr_flag; /* flags */ + __kernel_uid_t pr_uid; + __kernel_gid_t pr_gid; + pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid; + /* Lots missing */ + char pr_fname[16]; /* filename of executable */ + char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */ +}; + +#define elf_addr_t u32 +#define elf_caddr_t u32 +#define init_elf_binfmt init_elf32_binfmt + + +#undef ELF_CORE_COPY_REGS +#define ELF_CORE_COPY_REGS(_dest,_regs) elf32_core_copy_regs(_dest,_regs); + +void elf32_core_copy_regs(elf_gregset_t _dest, struct pt_regs *_regs) +{ + int i; + + memset(_dest, 0, sizeof(elf_gregset_t)); + + /* XXXKW the 6 is from EF_REG0 in gdb/gdb/mips-linux-tdep.c, include/asm-mips/reg.h */ + for (i=6; i<38; i++) + _dest[i] = (elf_greg_t) _regs->regs[i-6]; + _dest[i++] = (elf_greg_t) _regs->lo; + _dest[i++] = (elf_greg_t) _regs->hi; + _dest[i++] = (elf_greg_t) _regs->cp0_epc; + _dest[i++] = (elf_greg_t) _regs->cp0_badvaddr; + _dest[i++] = (elf_greg_t) _regs->cp0_status; + _dest[i++] = (elf_greg_t) _regs->cp0_cause; +} + +#undef CONFIG_BINFMT_ELF +#ifdef CONFIG_BINFMT_ELF32 +#define CONFIG_BINFMT_ELF CONFIG_BINFMT_ELF32 +#endif +#undef CONFIG_BINFMT_ELF_MODULE +#ifdef CONFIG_BINFMT_ELF32_MODULE +#define CONFIG_BINFMT_ELF_MODULE CONFIG_BINFMT_ELF32_MODULE +#endif + +MODULE_DESCRIPTION("Binary format loader for compatibility with o32 Linux/MIPS binaries"); +MODULE_AUTHOR("Ralf Baechle (ralf@linux-mips.org)"); + +#undef MODULE_DESCRIPTION +#undef MODULE_AUTHOR + +#include "../../../fs/binfmt_elf.c" diff -Nru a/arch/mips64/kernel/branch.c b/arch/mips64/kernel/branch.c --- a/arch/mips64/kernel/branch.c Tue Jul 1 18:44:34 2003 +++ b/arch/mips64/kernel/branch.c Tue Jul 1 18:44:34 2003 @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -163,7 +164,10 @@ * And now the FPA/cp1 branch instructions. */ case cop1_op: - asm ("cfc1\t%0,$31":"=r" (fcr31)); + if (!cpu_has_fpu) + fcr31 = current->thread.fpu.soft.sr; + else + asm volatile("cfc1\t%0,$31" : "=r" (fcr31)); bit = (insn.i_format.rt >> 2); bit += (bit != 0); bit += 23; diff -Nru a/arch/mips64/kernel/cpu-probe.c b/arch/mips64/kernel/cpu-probe.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips64/kernel/cpu-probe.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,746 @@ +/* + * arch/mips64/kernel/cpu-probe.c + * + * Processor capabilities determination functions. + * + * Copyright (C) xxxx the Anonymous + * Copyright (C) 2003 Maciej W. Rozycki + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* + * Not all of the MIPS CPUs have the "wait" instruction available. Moreover, + * the implementation of the "wait" feature differs between CPU families. This + * points to the function that implements CPU specific wait. + * The wait instruction stops the pipeline and reduces the power consumption of + * the CPU very much. + */ +void (*cpu_wait)(void) = NULL; + +static void r3081_wait(void) +{ + unsigned long cfg = read_c0_conf(); + write_c0_conf(cfg | R30XX_CONF_HALT); +} + +static void r39xx_wait(void) +{ + unsigned long cfg = read_c0_conf(); + write_c0_conf(cfg | TX39_CONF_HALT); +} + +static void r4k_wait(void) +{ + __asm__(".set\tmips3\n\t" + "wait\n\t" + ".set\tmips0"); +} + +void au1k_wait(void) +{ +#ifdef CONFIG_PM + /* using the wait instruction makes CP0 counter unusable */ + __asm__(".set\tmips3\n\t" + "wait\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + ".set\tmips0"); +#else + __asm__("nop\n\t" + "nop"); +#endif +} + +static inline void check_wait(void) +{ + struct cpuinfo_mips *c = ¤t_cpu_data; + + printk("Checking for 'wait' instruction... "); + switch (c->cputype) { + case CPU_R3081: + case CPU_R3081E: + cpu_wait = r3081_wait; + printk(" available.\n"); + break; + case CPU_TX3927: + cpu_wait = r39xx_wait; + printk(" available.\n"); + break; + case CPU_R4200: +/* case CPU_R4300: */ + case CPU_R4600: + case CPU_R4640: + case CPU_R4650: + case CPU_R4700: + case CPU_R5000: + case CPU_NEVADA: + case CPU_RM7000: + case CPU_TX49XX: + case CPU_4KC: + case CPU_4KEC: + case CPU_4KSC: + case CPU_5KC: +/* case CPU_20KC:*/ + cpu_wait = r4k_wait; + printk(" available.\n"); + break; + case CPU_AU1000: + case CPU_AU1100: + case CPU_AU1500: + cpu_wait = au1k_wait; + printk(" available.\n"); + break; + default: + printk(" unavailable.\n"); + break; + } +} + +static inline void check_mult_sh(void) +{ + unsigned long flags; + int m1, m2; + long p, s, v; + + printk("Checking for the multiply/shift bug... "); + + local_irq_save(flags); + /* + * The following code leads to a wrong result of dsll32 when + * executed on R4000 rev. 2.2 or 3.0. + * + * See "MIPS R4000PC/SC Errata, Processor Revision 2.2 and + * 3.0" by MIPS Technologies, Inc., errata #16 and #28 for + * details. I got no permission to duplicate them here, + * sigh... --macro + */ + asm volatile( + ".set push\n\t" + ".set noat\n\t" + ".set noreorder\n\t" + ".set nomacro\n\t" + "mult %1, %2\n\t" + "dsll32 %0, %3, %4\n\t" + "mflo $0\n\t" + ".set pop" + : "=r" (v) + : "r" (5), "r" (8), "r" (5), "I" (0) + : "hi", "lo", "accum"); + local_irq_restore(flags); + + if (v == 5L << 32) { + printk("no.\n"); + return; + } + + printk("yes, workaround... "); + local_irq_save(flags); + /* + * We want the multiply and the shift to be isolated from the + * rest of the code to disable gcc optimizations. Hence the + * asm statements that execute nothing, but make gcc not know + * what the values of m1, m2 and s are and what v and p are + * used for. + * + * We have to use single integers for m1 and m2 and a double + * one for p to be sure the mulsidi3 gcc's RTL multiplication + * instruction has the workaround applied. Older versions of + * gcc have correct mulsi3, but other multiplication variants + * lack the workaround. + */ + asm volatile( + "" + : "=r" (m1), "=r" (m2), "=r" (s) + : "0" (5), "1" (8), "2" (5)); + p = m1 * m2; + v = s << 32; + asm volatile( + "" + : "=r" (v) + : "0" (v), "r" (p)); + local_irq_restore(flags); + + if (v == 5L << 32) { + printk("yes.\n"); + return; + } + + printk("no.\n"); + panic("Reliable operation impossible!\n" +#ifndef CONFIG_CPU_R4000 + "Configure for R4000 to enable the workaround." +#else + "Please report to ." +#endif + ); +} + +static volatile int daddi_ov __initdata = 0; + +asmlinkage void __init do_daddi_ov(struct pt_regs *regs) +{ + daddi_ov = 1; + regs->cp0_epc += 4; +} + +static inline void check_daddi(void) +{ + extern asmlinkage void handle_daddi_ov(void); + unsigned long flags; + void *handler; + long v; + + printk("Checking for the daddi bug... "); + + local_irq_save(flags); + handler = set_except_vector(12, handle_daddi_ov); + /* + * The following code fails to trigger an overflow exception + * when executed on R4000 rev. 2.2 or 3.0. + * + * See "MIPS R4000PC/SC Errata, Processor Revision 2.2 and + * 3.0" by MIPS Technologies, Inc., erratum #23 for details. + * I got no permission to duplicate it here, sigh... --macro + */ + asm volatile( + ".set push\n\t" + ".set noat\n\t" + ".set noreorder\n\t" + ".set nomacro\n\t" +#ifdef HAVE_AS_SET_DADDI + ".set daddi\n\t" +#endif + "daddi %0, %1, %2\n\t" + ".set pop" + : "=r" (v) + : "r" (0x7fffffffffffedcd), "I" (0x1234)); + set_except_vector(12, handler); + local_irq_restore(flags); + + if (daddi_ov) { + printk("no.\n"); + return; + } + + printk("yes, workaround... "); + + local_irq_save(flags); + handler = set_except_vector(12, handle_daddi_ov); + asm volatile( + "daddi %0, %1, %2" + : "=r" (v) + : "r" (0x7fffffffffffedcd), "I" (0x1234)); + set_except_vector(12, handler); + local_irq_restore(flags); + + if (daddi_ov) { + printk("yes.\n"); + return; + } + + printk("no.\n"); + panic("Reliable operation impossible!\n" +#if !defined(CONFIG_CPU_R4000) && !defined(CONFIG_CPU_R4400) + "Configure for R4000 or R4400 to enable the workaround." +#else + "Please report to ." +#endif + ); +} + +static inline void check_daddiu(void) +{ + long v, w; + + printk("Checking for the daddiu bug... "); + + /* + * The following code leads to a wrong result of daddiu when + * executed on R4400 rev. 1.0. + * + * See "MIPS R4400PC/SC Errata, Processor Revision 1.0" by + * MIPS Technologies, Inc., erratum #7 for details. + * + * According to "MIPS R4000PC/SC Errata, Processor Revision + * 2.2 and 3.0" by MIPS Technologies, Inc., erratum #41 this + * problem affects R4000 rev. 2.2 and 3.0, too. Testing + * failed to trigger it so far. + * + * I got no permission to duplicate the errata here, sigh... + * --macro + */ + asm volatile( + ".set push\n\t" + ".set noat\n\t" + ".set noreorder\n\t" + ".set nomacro\n\t" +#ifdef HAVE_AS_SET_DADDI + ".set daddi\n\t" +#endif + "daddiu %0, %2, %3\n\t" + "addiu %1, $0, %3\n\t" + "daddu %1, %2\n\t" + ".set pop" + : "=&r" (v), "=&r" (w) + : "r" (0x7fffffffffffedcd), "I" (0x1234)); + + if (v == w) { + printk("no.\n"); + return; + } + + printk("yes, workaround... "); + + asm volatile( + "daddiu %0, %2, %3\n\t" + "addiu %1, $0, %3\n\t" + "daddu %1, %2" + : "=&r" (v), "=&r" (w) + : "r" (0x7fffffffffffedcd), "I" (0x1234)); + + if (v == w) { + printk("yes.\n"); + return; + } + + printk("no.\n"); + panic("Reliable operation impossible!\n" +#if !defined(CONFIG_CPU_R4000) && !defined(CONFIG_CPU_R4400) + "Configure for R4000 or R4400 to enable the workaround." +#else + "Please report to ." +#endif + ); +} + +void __init check_bugs(void) +{ + check_wait(); + check_mult_sh(); + check_daddi(); + check_daddiu(); +} + +/* + * Probe whether cpu has config register by trying to play with + * alternate cache bit and see whether it matters. + * It's used by cpu_probe to distinguish between R3000A and R3081. + */ +static inline int cpu_has_confreg(void) +{ +#ifdef CONFIG_CPU_R3000 + extern unsigned long r3k_cache_size(unsigned long); + unsigned long size1, size2; + unsigned long cfg = read_c0_conf(); + + size1 = r3k_cache_size(ST0_ISC); + write_c0_conf(cfg ^ R30XX_CONF_AC); + size2 = r3k_cache_size(ST0_ISC); + write_c0_conf(cfg); + return size1 != size2; +#else + return 0; +#endif +} + +/* + * Get the FPU Implementation/Revision. + */ +static inline unsigned long cpu_get_fpu_id(void) +{ + unsigned long tmp, fpu_id; + + tmp = read_c0_status(); + __enable_fpu(); + fpu_id = read_32bit_cp1_register(CP1_REVISION); + write_c0_status(tmp); + return fpu_id; +} + +/* + * Check the CPU has an FPU the official way. + */ +static inline int __cpu_has_fpu(void) +{ + return ((cpu_get_fpu_id() & 0xff00) != FPIR_IMP_NONE); +} + +#define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4KTLB \ + | MIPS_CPU_COUNTER | MIPS_CPU_CACHE_CDEX) + +__init void cpu_probe(void) +{ + struct cpuinfo_mips *c = ¤t_cpu_data; + unsigned long config0 = read_c0_config(); + unsigned long config1; + + c->processor_id = PRID_IMP_UNKNOWN; + c->fpu_id = FPIR_IMP_NONE; + c->cputype = CPU_UNKNOWN; + + if (config0 & (1 << 31)) { + /* MIPS32 or MIPS64 compliant CPU. Read Config 1 register. */ + c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX | + MIPS_CPU_4KTLB | MIPS_CPU_COUNTER | MIPS_CPU_DIVEC | + MIPS_CPU_LLSC; + config1 = read_c0_config1(); + if (config1 & (1 << 3)) + c->options |= MIPS_CPU_WATCH; + if (config1 & (1 << 2)) + c->options |= MIPS_CPU_MIPS16; + if (config1 & (1 << 1)) + c->options |= MIPS_CPU_EJTAG; + if (config1 & 1) { + c->options |= MIPS_CPU_FPU; + c->options |= MIPS_CPU_32FPR; + } + c->scache.flags = MIPS_CACHE_NOT_PRESENT; + + c->tlbsize = ((config1 >> 25) & 0x3f) + 1; + } + + c->processor_id = read_c0_prid(); + switch (c->processor_id & 0xff0000) { + case PRID_COMP_LEGACY: + switch (c->processor_id & 0xff00) { + case PRID_IMP_R2000: + c->cputype = CPU_R2000; + c->isa_level = MIPS_CPU_ISA_I; + c->options = MIPS_CPU_TLB | MIPS_CPU_NOFPUEX | + MIPS_CPU_LLSC; + if (__cpu_has_fpu()) + c->options |= MIPS_CPU_FPU; + c->tlbsize = 64; + break; + case PRID_IMP_R3000: + if ((c->processor_id & 0xff) == PRID_REV_R3000A) + if (cpu_has_confreg()) + c->cputype = CPU_R3081E; + else + c->cputype = CPU_R3000A; + else + c->cputype = CPU_R3000; + c->isa_level = MIPS_CPU_ISA_I; + c->options = MIPS_CPU_TLB | MIPS_CPU_NOFPUEX | + MIPS_CPU_LLSC; + if (__cpu_has_fpu()) + c->options |= MIPS_CPU_FPU; + c->tlbsize = 64; + break; + case PRID_IMP_R4000: + if ((c->processor_id & 0xff) >= PRID_REV_R4400) + c->cputype = CPU_R4400SC; + else + c->cputype = CPU_R4000SC; + c->isa_level = MIPS_CPU_ISA_III; + c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_WATCH | MIPS_CPU_VCE | + MIPS_CPU_LLSC; + c->tlbsize = 48; + break; + case PRID_IMP_VR41XX: + switch (c->processor_id & 0xf0) { +#ifndef CONFIG_VR4181 + case PRID_REV_VR4111: + c->cputype = CPU_VR4111; + break; +#else + case PRID_REV_VR4181: + c->cputype = CPU_VR4181; + break; +#endif + case PRID_REV_VR4121: + c->cputype = CPU_VR4121; + break; + case PRID_REV_VR4122: + if ((c->processor_id & 0xf) < 0x3) + c->cputype = CPU_VR4122; + else + c->cputype = CPU_VR4181A; + break; + case PRID_REV_VR4131: + c->cputype = CPU_VR4131; + break; + default: + printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n"); + c->cputype = CPU_VR41XX; + break; + } + c->isa_level = MIPS_CPU_ISA_III; + c->options = R4K_OPTS; + c->tlbsize = 32; + break; + case PRID_IMP_R4300: + c->cputype = CPU_R4300; + c->isa_level = MIPS_CPU_ISA_III; + c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_LLSC; + c->tlbsize = 32; + break; + case PRID_IMP_R4600: + c->cputype = CPU_R4600; + c->isa_level = MIPS_CPU_ISA_III; + c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_LLSC; + c->tlbsize = 48; + break; + #if 0 + case PRID_IMP_R4650: + /* + * This processor doesn't have an MMU, so it's not + * "real easy" to run Linux on it. It is left purely + * for documentation. Commented out because it shares + * it's c0_prid id number with the TX3900. + */ + c->cputype = CPU_R4650; + c->isa_level = MIPS_CPU_ISA_III; + c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_LLSC; + c->tlbsize = 48; + break; + #endif + case PRID_IMP_TX39: + c->isa_level = MIPS_CPU_ISA_I; + c->options = MIPS_CPU_TLB; + + if ((c->processor_id & 0xf0) == + (PRID_REV_TX3927 & 0xf0)) { + c->cputype = CPU_TX3927; + c->tlbsize = 64; + } else { + switch (c->processor_id & 0xff) { + case PRID_REV_TX3912: + c->cputype = CPU_TX3912; + c->tlbsize = 32; + break; + case PRID_REV_TX3922: + c->cputype = CPU_TX3922; + c->tlbsize = 64; + break; + default: + c->cputype = CPU_UNKNOWN; + break; + } + } + break; + case PRID_IMP_R4700: + c->cputype = CPU_R4700; + c->isa_level = MIPS_CPU_ISA_III; + c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_LLSC; + c->tlbsize = 48; + break; + case PRID_IMP_TX49: + c->cputype = CPU_TX49XX; + c->isa_level = MIPS_CPU_ISA_III; + c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_LLSC; + c->tlbsize = 48; + break; + case PRID_IMP_R5000: + c->cputype = CPU_R5000; + c->isa_level = MIPS_CPU_ISA_IV; + c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_LLSC; + c->tlbsize = 48; + break; + case PRID_IMP_R5432: + c->cputype = CPU_R5432; + c->isa_level = MIPS_CPU_ISA_IV; + c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_WATCH | MIPS_CPU_LLSC; + c->tlbsize = 48; + break; + case PRID_IMP_R5500: + c->cputype = CPU_R5500; + c->isa_level = MIPS_CPU_ISA_IV; + c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_WATCH | MIPS_CPU_LLSC; + c->tlbsize = 48; + break; + case PRID_IMP_NEVADA: + c->cputype = CPU_NEVADA; + c->isa_level = MIPS_CPU_ISA_IV; + c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_DIVEC | MIPS_CPU_LLSC; + c->tlbsize = 48; + break; + case PRID_IMP_R6000: + c->cputype = CPU_R6000; + c->isa_level = MIPS_CPU_ISA_II; + c->options = MIPS_CPU_TLB | MIPS_CPU_FPU | + MIPS_CPU_LLSC; + c->tlbsize = 32; + break; + case PRID_IMP_R6000A: + c->cputype = CPU_R6000A; + c->isa_level = MIPS_CPU_ISA_II; + c->options = MIPS_CPU_TLB | MIPS_CPU_FPU | + MIPS_CPU_LLSC; + c->tlbsize = 32; + break; + case PRID_IMP_RM7000: + c->cputype = CPU_RM7000; + c->isa_level = MIPS_CPU_ISA_IV; + c->options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_LLSC; + /* + * Undocumented RM7000: Bit 29 in the info register of + * the RM7000 v2.0 indicates if the TLB has 48 or 64 + * entries. + * + * 29 1 => 64 entry JTLB + * 0 => 48 entry JTLB + */ + c->tlbsize = (read_c0_info() & (1 << 29)) ? 64 : 48; + break; + case PRID_IMP_R8000: + c->cputype = CPU_R8000; + c->isa_level = MIPS_CPU_ISA_IV; + c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX | + MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_LLSC; + c->tlbsize = 384; /* has weird TLB: 3-way x 128 */ + break; + case PRID_IMP_R10000: + c->cputype = CPU_R10000; + c->isa_level = MIPS_CPU_ISA_IV; + c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX | + MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_COUNTER | MIPS_CPU_WATCH | + MIPS_CPU_LLSC; + c->tlbsize = 64; + break; + case PRID_IMP_R12000: + c->cputype = CPU_R12000; + c->isa_level = MIPS_CPU_ISA_IV; + c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX | + MIPS_CPU_FPU | MIPS_CPU_32FPR | + MIPS_CPU_COUNTER | MIPS_CPU_WATCH | + MIPS_CPU_LLSC; + c->tlbsize = 64; + break; + default: + c->cputype = CPU_UNKNOWN; + break; + } + break; + case PRID_COMP_MIPS: + switch (c->processor_id & 0xff00) { + case PRID_IMP_4KC: + c->cputype = CPU_4KC; + c->isa_level = MIPS_CPU_ISA_M32; + break; + case PRID_IMP_4KEC: + c->cputype = CPU_4KEC; + c->isa_level = MIPS_CPU_ISA_M32; + break; + case PRID_IMP_4KSC: + c->cputype = CPU_4KSC; + c->isa_level = MIPS_CPU_ISA_M32; + break; + case PRID_IMP_5KC: + c->cputype = CPU_5KC; + c->isa_level = MIPS_CPU_ISA_M64; + break; + case PRID_IMP_20KC: + c->cputype = CPU_20KC; + c->isa_level = MIPS_CPU_ISA_M64; + break; + default: + c->cputype = CPU_UNKNOWN; + break; + } + break; + case PRID_COMP_ALCHEMY: + switch (c->processor_id & 0xff00) { + case PRID_IMP_AU1_REV1: + case PRID_IMP_AU1_REV2: + switch ((c->processor_id >> 24) & 0xff) { + case 0: + c->cputype = CPU_AU1000; + break; + case 1: + c->cputype = CPU_AU1500; + break; + case 2: + c->cputype = CPU_AU1100; + break; + default: + panic("Unknown Au Core!"); + break; + } + c->isa_level = MIPS_CPU_ISA_M32; + break; + default: + c->cputype = CPU_UNKNOWN; + break; + } + break; + case PRID_COMP_SIBYTE: + switch (c->processor_id & 0xff00) { + case PRID_IMP_SB1: + c->cputype = CPU_SB1; + c->isa_level = MIPS_CPU_ISA_M64; + c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX | + MIPS_CPU_COUNTER | MIPS_CPU_DIVEC | + MIPS_CPU_MCHECK | MIPS_CPU_EJTAG | + MIPS_CPU_WATCH | MIPS_CPU_LLSC; +#ifndef CONFIG_SB1_PASS_1_WORKAROUNDS + /* FPU in pass1 is known to have issues. */ + c->options |= MIPS_CPU_FPU | MIPS_CPU_32FPR; +#endif + break; + default: + c->cputype = CPU_UNKNOWN; + break; + } + break; + + case PRID_COMP_SANDCRAFT: + switch (c->processor_id & 0xff00) { + case PRID_IMP_SR71000: + c->cputype = CPU_SR71000; + c->isa_level = MIPS_CPU_ISA_M64; + c->options = MIPS_CPU_TLB | MIPS_CPU_4KEX | + MIPS_CPU_4KTLB | MIPS_CPU_FPU | + MIPS_CPU_COUNTER | MIPS_CPU_MCHECK; + c->scache.ways = 8; + c->tlbsize = 64; + break; + default: + c->cputype = CPU_UNKNOWN; + break; + } + break; + default: + c->cputype = CPU_UNKNOWN; + c->tlbsize = ((config1 >> 25) & 0x3f) + 1; + } + if (c->options & MIPS_CPU_FPU) + c->fpu_id = cpu_get_fpu_id(); +} + +__init void cpu_report(void) +{ + struct cpuinfo_mips *c = ¤t_cpu_data; + + printk("CPU revision is: %08x\n", c->processor_id); + if (c->options & MIPS_CPU_FPU) + printk("FPU revision is: %08x\n", c->fpu_id); +} diff -Nru a/arch/mips64/kernel/entry.S b/arch/mips64/kernel/entry.S --- a/arch/mips64/kernel/entry.S Tue Jul 1 18:44:32 2003 +++ b/arch/mips64/kernel/entry.S Tue Jul 1 18:44:32 2003 @@ -9,67 +9,88 @@ * Copyright (C) 1999, 2000 Silicon Graphics * Copyright (C) 2001 MIPS Technologies, Inc. */ -#include - #include #include #include #include - -/* This duplicates the definition from */ -#error #define PT_TRACESYS 0x00000002 /* tracing system calls */ +#include #define KU_USER 0x10 .text - .align 4 -FEXPORT(ret_from_fork) - move a0, v0 # prev - jal schedule_tail -#error lw t0, TASK_PTRACE($28) # syscall tracing enabled? -#error andi t0, PT_TRACESYS - bnez t0, tracesys_exit - j ret_from_sys_call - -tracesys_exit: - jal syscall_trace - b ret_from_sys_call - -EXPORT(ret_from_irq) -EXPORT(ret_from_exception) - lw t0, PT_STATUS(sp) # returning to kernel mode? + .align 5 +FEXPORT(ret_from_irq) +FEXPORT(ret_from_exception) + ld t0, PT_STATUS(sp) # returning to kernel mode? andi t0, t0, KU_USER - bnez t0, ret_from_sys_call + beqz t0, restore_all + +FEXPORT(resume_userspace) + mfc0 t0, CP0_STATUS # make sure need_resched and + ori t0, t0, 1 # signals dont change between + xori t0, t0, 1 # sampling and return + SSNOP; SSNOP; SSNOP + + LONG_L a2, TI_FLAGS($28) + andi a2, _TIF_WORK_MASK # current->work (ignoring + # syscall_trace + bnez a2, work_pending j restore_all -reschedule: jal schedule +FEXPORT(ret_from_fork) + jal schedule_tail -FEXPORT(ret_from_sys_call) - mfc0 t0, CP0_STATUS # need_resched and signals atomic test - ori t0, t0, 1 - xori t0, t0, 1 +FEXPORT(syscall_exit) + mfc0 t0, CP0_STATUS # make sure need_resched and + ori t0, t0, 1 # signals dont change between + xori t0, t0, 1 # sampling and return mtc0 t0, CP0_STATUS + SSNOP; SSNOP; SSNOP -#error ld v0, TASK_NEED_RESCHED($28) -#error lw v1, TASK_SIGPENDING($28) - bnez v0, reschedule - bnez v1, signal_return + LONG_L a2, TI_FLAGS($28) # current->work + bnez a2, syscall_exit_work -restore_all: .set noat +restore_all: + .set noat RESTORE_ALL eret .set at -signal_return: .type signal_return, @function +work_pending: + bltz a2, work_notifysig # current->work.need_resched + # test high 8 bits +work_resched: + jal schedule + + mfc0 t0, CP0_STATUS # make sure need_resched and + ori t0, t0, 1 # signals dont change between + xori t0, t0, 1 # sampling and return + mtc0 t0, CP0_STATUS + SSNOP; SSNOP; SSNOP + + LONG_L a2, TI_FLAGS($28) # This also converts into + # a union of four chars + andi a2, _TIF_WORK_MASK # is there any work to be done + # other than syscall tracing? + beqz a2, restore_all + andi t0, a2, _TIF_NEED_RESCHED + bnez t0, work_notifysig + +work_notifysig: # deal with pending signals and + # notify-resume requests + move a0, sp + li a1, 0 + jal do_notify_resume # a2 already loaded + j restore_all - mfc0 t0, CP0_STATUS +FEXPORT(syscall_exit_work) + LONG_L t0, TI_FLAGS($28) # current->work.syscall_trace + bgez t0, work_pending + mfc0 t0, CP0_STATUS # sti ori t0, t0, 1 mtc0 t0, CP0_STATUS - - move a0, zero - move a1, sp - jal do_signal - b restore_all + jal do_syscall_trace + b resume_userspace /* * Common spurious interrupt handler. @@ -81,9 +102,10 @@ * Someone tried to fool us by sending an interrupt but we * couldn't find a cause for it. */ - lui t1,%hi(spurious_count) - lw t0,%lo(spurious_count)(t1) - addiu t0,1 - sw t0,%lo(spurious_count)(t1) + lui t1, %hi(irq_err_count) +1: ll t0, %lo(irq_err_count)(t1) + addiu t0, 1 + sc t0, %lo(irq_err_count)(t1) + beqz t0, 1b j ret_from_irq END(spurious_interrupt) diff -Nru a/arch/mips64/kernel/head.S b/arch/mips64/kernel/head.S --- a/arch/mips64/kernel/head.S Tue Jul 1 18:44:34 2003 +++ b/arch/mips64/kernel/head.S Tue Jul 1 18:44:34 2003 @@ -10,7 +10,6 @@ * Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999 Ralf Baechle * Copyright (C) 1999 Silicon Graphics, Inc. */ -#define __ASSEMBLY__ #include #include #include @@ -27,7 +26,7 @@ #if defined(CONFIG_ARC64) || defined(CONFIG_MAPPED_KERNEL) /* We get launched at a XKPHYS address but the kernel is linked to run at a KSEG0 address, so jump there. */ - la t0, \@f + PTR_LA t0, \@f jr t0 \@: #endif @@ -35,13 +34,13 @@ #ifdef CONFIG_SGI_IP27 /* - * outputs the local nasid into t1. + * outputs the local nasid into res. IP27 stuff. */ - .macro GET_NASID_ASM - dli t1, LOCAL_HUB_ADDR(NI_STATUS_REV_ID) - ld t1, (t1) - and t1, NSRI_NODEID_MASK - dsrl t1, NSRI_NODEID_SHFT + .macro GET_NASID_ASM res + dli \res, LOCAL_HUB_ADDR(NI_STATUS_REV_ID) + ld \res, (\res) + and \res, NSRI_NODEID_MASK + dsrl \res, NSRI_NODEID_SHFT .endm #endif /* CONFIG_SGI_IP27 */ @@ -97,7 +96,7 @@ xori sp, 0xf #ifdef CONFIG_SGI_IP27 - GET_NASID_ASM + GET_NASID_ASM t1 move t2, t1 # text and data are here MAPPED_KERNEL_SETUP_TLB #endif /* IP27 */ @@ -106,39 +105,39 @@ CLI # disable interrupts - mfc0 t0, CP0_STATUS + PTR_LA $28, init_thread_union # init current pointer + daddiu sp, $28, KERNEL_STACK_SIZE-32 + set_saved_sp sp, t0, t1 + /* - * On IP27, I am seeing the TS bit set when the - * kernel is loaded. Maybe because the kernel is - * in ckseg0 and not xkphys? Clear it anyway ... + * The firmware/bootloader passes argc/argp/envp + * to us as arguments. But clear bss first because + * the romvec and other important info is stored there + * by prom_init(). */ - li t1, ~(ST0_TS|ST0_CU1|ST0_CU2|ST0_CU3) - and t0, t1 - or t0, (ST0_CU0|ST0_KX|ST0_SX|ST0_FR) # Bogosity: cu0 indicates kernel - mtc0 t0, CP0_STATUS # thread in copy_thread. - - la $28, init_task_union # init current pointer - daddiu t0, $28, KERNEL_STACK_SIZE-32 - sd t0, kernelsp - dsubu sp, t0, 4*SZREG # init stack pointer - move t0, $28 -#ifdef CONFIG_SMP - mtc0 t0, CP0_WATCHLO - dsrl32 t0, t0, 0 - mtc0 t0, CP0_WATCHHI -#endif - /* Note that all firmware passed argument registers still - have their values. */ - jal prom_init # initialize firmware + PTR_LA t0, __bss_start + sd zero, (t0) + PTR_LA t1, __bss_stop - 8 +1: + daddiu t0, 8 + sd zero, (t0) + bne t0, t1, 1b + + dsubu sp, 4*SZREG # init stack pointer - jal start_kernel -1: b 1b # just in case ... + j init_arch END(kernel_entry) +#ifdef CONFIG_SMP +/* + * SMP slave cpus entry point. Board specific code for bootstrap calls this + * function after setting up the stack and gp registers. + */ +NESTED(smp_bootstrap, 16, sp) #ifdef CONFIG_SGI_IP27 -NESTED(bootstrap, 16, sp) - GET_NASID_ASM - li t0, KLDIR_OFFSET + (KLI_KERN_VARS * KLDIR_ENT_SIZE) + KLDIR_OFF_POINTER + K0BASE + GET_NASID_ASM t1 + li t0, KLDIR_OFFSET + (KLI_KERN_VARS * KLDIR_ENT_SIZE) + \ + KLDIR_OFF_POINTER + K0BASE dsll t1, NASID_SHFT or t0, t0, t1 ld t0, 0(t0) # t0 points to kern_vars struct @@ -146,19 +145,27 @@ lh t2, KV_RW_NASID_OFFSET(t0) MAPPED_KERNEL_SETUP_TLB ARC64_TWIDDLE_PC - CLI - mfc0 t0, CP0_STATUS - li t1, ~(ST0_CU1|ST0_CU2|ST0_CU3) - and t0, t1 - or t0, (ST0_CU0|ST0_KX|ST0_SX|ST0_FR) # Bogosity: cu0 indicates kernel - mtc0 t0, CP0_STATUS # thread in copy_thread. - jal cboot - END(bootstrap) #endif /* CONFIG_SGI_IP27 */ + CLI + + /* + * For the moment set ST0_KU so the CPU will not spit fire when + * executing 64-bit instructions. The full initialization of the + * CPU's status register is done later in per_cpu_trap_init(). + */ + mfc0 t0, CP0_STATUS + or t0, ST0_KX + mtc0 t0, CP0_STATUS + + jal start_secondary + + END(smp_bootstrap) +#endif /* CONFIG_SMP */ + __FINIT - .comm kernelsp, 8, 8 # current stackpointer + declare_saved_sp #undef PAGE_SIZE #define PAGE_SIZE 0x1000 @@ -171,12 +178,12 @@ .endm .data - .align 12 + .align PAGE_SHIFT page swapper_pg_dir, 1 page invalid_pte_table, 0 page invalid_pmd_table, 1 - page kptbl, KPTBL_PAGE_ORDER + page kptbl, _PGD_ORDER .globl ekptbl page kpmdtbl, 0 ekptbl: diff -Nru a/arch/mips64/kernel/i8259.c b/arch/mips64/kernel/i8259.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips64/kernel/i8259.c Tue Jul 1 18:44:39 2003 @@ -0,0 +1,336 @@ +/* + * 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. + * + * Code to handle x86 style IRQs plus some generic interrupt stuff. + * + * Copyright (C) 1992 Linus Torvalds + * Copyright (C) 1994 - 2000 Ralf Baechle + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +void enable_8259A_irq(unsigned int irq); +void disable_8259A_irq(unsigned int irq); + +/* + * This is the 'legacy' 8259A Programmable Interrupt Controller, + * present in the majority of PC/AT boxes. + * plus some generic x86 specific things if generic specifics makes + * any sense at all. + * this file should become arch/i386/kernel/irq.c when the old irq.c + * moves to arch independent land + */ + +static spinlock_t i8259A_lock = SPIN_LOCK_UNLOCKED; + +static void end_8259A_irq (unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)) && + irq_desc[irq].action) + enable_8259A_irq(irq); +} + +#define shutdown_8259A_irq disable_8259A_irq + +void mask_and_ack_8259A(unsigned int); + +static unsigned int startup_8259A_irq(unsigned int irq) +{ + enable_8259A_irq(irq); + + return 0; /* never anything pending */ +} + +static struct hw_interrupt_type i8259A_irq_type = { + "XT-PIC", + startup_8259A_irq, + shutdown_8259A_irq, + enable_8259A_irq, + disable_8259A_irq, + mask_and_ack_8259A, + end_8259A_irq, + NULL +}; + +/* + * 8259A PIC functions to handle ISA devices: + */ + +/* + * This contains the irq mask for both 8259A irq controllers, + */ +static unsigned int cached_irq_mask = 0xffff; + +#define cached_21 (cached_irq_mask) +#define cached_A1 (cached_irq_mask >> 8) + +void disable_8259A_irq(unsigned int irq) +{ + unsigned int mask = 1 << irq; + unsigned long flags; + + spin_lock_irqsave(&i8259A_lock, flags); + cached_irq_mask |= mask; + if (irq & 8) + outb(cached_A1,0xA1); + else + outb(cached_21,0x21); + spin_unlock_irqrestore(&i8259A_lock, flags); +} + +void enable_8259A_irq(unsigned int irq) +{ + unsigned int mask = ~(1 << irq); + unsigned long flags; + + spin_lock_irqsave(&i8259A_lock, flags); + cached_irq_mask &= mask; + if (irq & 8) + outb(cached_A1,0xA1); + else + outb(cached_21,0x21); + spin_unlock_irqrestore(&i8259A_lock, flags); +} + +int i8259A_irq_pending(unsigned int irq) +{ + unsigned int mask = 1 << irq; + unsigned long flags; + int ret; + + spin_lock_irqsave(&i8259A_lock, flags); + if (irq < 8) + ret = inb(0x20) & mask; + else + ret = inb(0xA0) & (mask >> 8); + spin_unlock_irqrestore(&i8259A_lock, flags); + + return ret; +} + +void make_8259A_irq(unsigned int irq) +{ + disable_irq_nosync(irq); + irq_desc[irq].handler = &i8259A_irq_type; + enable_irq(irq); +} + +/* + * This function assumes to be called rarely. Switching between + * 8259A registers is slow. + * This has to be protected by the irq controller spinlock + * before being called. + */ +static inline int i8259A_irq_real(unsigned int irq) +{ + int value; + int irqmask = 1 << irq; + + if (irq < 8) { + outb(0x0B,0x20); /* ISR register */ + value = inb(0x20) & irqmask; + outb(0x0A,0x20); /* back to the IRR register */ + return value; + } + outb(0x0B,0xA0); /* ISR register */ + value = inb(0xA0) & (irqmask >> 8); + outb(0x0A,0xA0); /* back to the IRR register */ + return value; +} + +/* + * Careful! The 8259A is a fragile beast, it pretty + * much _has_ to be done exactly like this (mask it + * first, _then_ send the EOI, and the order of EOI + * to the two 8259s is important! + */ +void mask_and_ack_8259A(unsigned int irq) +{ + unsigned int irqmask = 1 << irq; + unsigned long flags; + + spin_lock_irqsave(&i8259A_lock, flags); + /* + * Lightweight spurious IRQ detection. We do not want to overdo + * spurious IRQ handling - it's usually a sign of hardware problems, so + * we only do the checks we can do without slowing down good hardware + * nnecesserily. + * + * Note that IRQ7 and IRQ15 (the two spurious IRQs usually resulting + * rom the 8259A-1|2 PICs) occur even if the IRQ is masked in the 8259A. + * Thus we can check spurious 8259A IRQs without doing the quite slow + * i8259A_irq_real() call for every IRQ. This does not cover 100% of + * spurious interrupts, but should be enough to warn the user that + * there is something bad going on ... + */ + if (cached_irq_mask & irqmask) + goto spurious_8259A_irq; + cached_irq_mask |= irqmask; + +handle_real_irq: + if (irq & 8) { + inb(0xA1); /* DUMMY - (do we need this?) */ + outb(cached_A1,0xA1); + outb(0x60+(irq&7),0xA0);/* 'Specific EOI' to slave */ + outb(0x62,0x20); /* 'Specific EOI' to master-IRQ2 */ + } else { + inb(0x21); /* DUMMY - (do we need this?) */ + outb(cached_21,0x21); + outb(0x60+irq,0x20); /* 'Specific EOI' to master */ + } + spin_unlock_irqrestore(&i8259A_lock, flags); + return; + +spurious_8259A_irq: + /* + * this is the slow path - should happen rarely. + */ + if (i8259A_irq_real(irq)) + /* + * oops, the IRQ _is_ in service according to the + * 8259A - not spurious, go handle it. + */ + goto handle_real_irq; + + { + static int spurious_irq_mask = 0; + /* + * At this point we can be sure the IRQ is spurious, + * lets ACK and report it. [once per IRQ] + */ + if (!(spurious_irq_mask & irqmask)) { + printk("spurious 8259A interrupt: IRQ%d.\n", irq); + spurious_irq_mask |= irqmask; + } + atomic_inc(&irq_err_count); + /* + * Theoretically we do not have to handle this IRQ, + * but in Linux this does not cause problems and is + * simpler for us. + */ + goto handle_real_irq; + } +} + +static int i8259A_resume(struct sys_device *dev) +{ + init_8259A(0); + return 0; +} + +static struct sysdev_class i8259_sysdev_class = { + set_kset_name("i8259"), + .resume = i8259A_resume, +}; + +static struct sys_device device_i8259A = { + .id = 0, + .cls = &i8259_sysdev_class, +}; + +static int __init i8259A_init_sysfs(void) +{ + int error = sysdev_class_register(&i8259_sysdev_class); + if (!error) + error = sys_device_register(&device_i8259A); + return error; +} + +device_initcall(i8259A_init_sysfs); + +void __init init_8259A(int auto_eoi) +{ + unsigned long flags; + + spin_lock_irqsave(&i8259A_lock, flags); + + outb(0xff, 0x21); /* mask all of 8259A-1 */ + outb(0xff, 0xA1); /* mask all of 8259A-2 */ + + /* + * outb_p - this has to work on a wide range of PC hardware. + */ + outb_p(0x11, 0x20); /* ICW1: select 8259A-1 init */ + outb_p(0x00, 0x21); /* ICW2: 8259A-1 IR0-7 mapped to 0x00-0x07 */ + outb_p(0x04, 0x21); /* 8259A-1 (the master) has a slave on IR2 */ + if (auto_eoi) + outb_p(0x03, 0x21); /* master does Auto EOI */ + else + outb_p(0x01, 0x21); /* master expects normal EOI */ + + outb_p(0x11, 0xA0); /* ICW1: select 8259A-2 init */ + outb_p(0x08, 0xA1); /* ICW2: 8259A-2 IR0-7 mapped to 0x08-0x0f */ + outb_p(0x02, 0xA1); /* 8259A-2 is a slave on master's IR2 */ + outb_p(0x01, 0xA1); /* (slave's support for AEOI in flat mode + is to be investigated) */ + + if (auto_eoi) + /* + * in AEOI mode we just have to mask the interrupt + * when acking. + */ + i8259A_irq_type.ack = disable_8259A_irq; + else + i8259A_irq_type.ack = mask_and_ack_8259A; + + udelay(100); /* wait for 8259A to initialize */ + + outb(cached_21, 0x21); /* restore master IRQ mask */ + outb(cached_A1, 0xA1); /* restore slave IRQ mask */ + + spin_unlock_irqrestore(&i8259A_lock, flags); +} + +asmlinkage void i8259_do_irq(int irq, struct pt_regs regs) +{ + panic("i8259_do_irq: I want to be implemented"); +} + +/* + * IRQ2 is cascade interrupt to second interrupt controller + */ +static struct irqaction irq2 = { + no_action, 0, 0, "cascade", NULL, NULL +}; + +static struct resource pic1_io_resource = { + "pic1", 0x20, 0x3f, IORESOURCE_BUSY +}; + +static struct resource pic2_io_resource = { + "pic2", 0xa0, 0xbf, IORESOURCE_BUSY +}; + +/* + * On systems with i8259-style interrupt controllers we assume for + * driver compatibility reasons interrupts 0 - 15 to be the i8295 + * interrupts even if the hardware uses a different interrupt numbering. + */ +void __init init_i8259_irqs (void) +{ + int i; + + request_resource(&ioport_resource, &pic1_io_resource); + request_resource(&ioport_resource, &pic2_io_resource); + + init_8259A(0); + + for (i = 0; i < 16; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = 1; + irq_desc[i].handler = &i8259A_irq_type; + } + + setup_irq(2, &irq2); +} diff -Nru a/arch/mips64/kernel/init_task.c b/arch/mips64/kernel/init_task.c --- a/arch/mips64/kernel/init_task.c Tue Jul 1 18:44:34 2003 +++ b/arch/mips64/kernel/init_task.c Tue Jul 1 18:44:34 2003 @@ -1,17 +1,19 @@ #include #include #include +#include #include #include static struct fs_struct init_fs = INIT_FS; static struct files_struct init_files = INIT_FILES; -static struct signal_struct init_signals = INIT_SIGNALS; +static struct signal_struct init_signals = INIT_SIGNALS(init_signals); +static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); struct mm_struct init_mm = INIT_MM(init_mm); /* - * Initial task structure. + * Initial thread structure. * * We need to make sure that this is 8192-byte aligned due to the * way process stacks are handled. This is done by making sure @@ -20,6 +22,13 @@ * * The things we do for performance.. */ -union task_union init_task_union +union thread_union init_thread_union __attribute__((__section__(".data.init_task"))) = - { INIT_TASK(init_task_union.task) }; + { INIT_THREAD_INFO(init_task) }; + +/* + * Initial task structure. + * + * All other task structs will be allocated on slabs in fork.c + */ +struct task_struct init_task = INIT_TASK(init_task); diff -Nru a/arch/mips64/kernel/ioctl32.c b/arch/mips64/kernel/ioctl32.c --- a/arch/mips64/kernel/ioctl32.c Tue Jul 1 18:44:35 2003 +++ b/arch/mips64/kernel/ioctl32.c Tue Jul 1 18:44:35 2003 @@ -4,33 +4,95 @@ * Copyright (C) 2000 Silicon Graphics, Inc. * Written by Ulf Carlsson (ulfc@engr.sgi.com) * Copyright (C) 2000 Ralf Baechle + * Copyright (C) 2002 Maciej W. Rozycki * * Mostly stolen from the sparc64 ioctl32 implementation. */ #include #include #include +#include #include -#include #include +#include #include #include +#include +#include +#include +#include #include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include +#include +#include #include +#include +#include +#include #include #include +#include #include #include #include -#include -#include -#include +#include +#include #include -#include -#include + +#include +#undef __KERNEL__ /* This file was born to be ugly ... */ +#include +#define __KERNEL__ +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifdef CONFIG_SIBYTE_TBPROF +#include +#endif long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); @@ -39,7 +101,7 @@ mm_segment_t old_fs = get_fs(); int err; unsigned long val; - + set_fs (KERNEL_DS); err = sys_ioctl(fd, cmd, (unsigned long)&val); set_fs (old_fs); @@ -66,6 +128,166 @@ #define A(__x) ((unsigned long)(__x)) + +#ifdef CONFIG_FB + +struct fb_fix_screeninfo32 { + char id[16]; /* identification string eg "TT Builtin" */ + __u32 smem_start; /* Start of frame buffer mem */ + /* (physical address) */ + __u32 smem_len; /* Length of frame buffer mem */ + __u32 type; /* see FB_TYPE_* */ + __u32 type_aux; /* Interleave for interleaved Planes */ + __u32 visual; /* see FB_VISUAL_* */ + __u16 xpanstep; /* zero if no hardware panning */ + __u16 ypanstep; /* zero if no hardware panning */ + __u16 ywrapstep; /* zero if no hardware ywrap */ + __u32 line_length; /* length of a line in bytes */ + __u32 mmio_start; /* Start of Memory Mapped I/O */ + /* (physical address) */ + __u32 mmio_len; /* Length of Memory Mapped I/O */ + __u32 accel; /* Type of acceleration available */ + __u16 reserved[3]; /* Reserved for future compatibility */ +}; + +static int do_fbioget_fscreeninfo_ioctl(unsigned int fd, unsigned int cmd, + unsigned long arg) +{ + mm_segment_t old_fs = get_fs(); + struct fb_fix_screeninfo fix; + struct fb_fix_screeninfo32 *fix32 = (struct fb_fix_screeninfo32 *)arg; + int err; + + set_fs(KERNEL_DS); + err = sys_ioctl(fd, cmd, (unsigned long)&fix); + set_fs(old_fs); + + if (err == 0) { + err = __copy_to_user((char *)fix32->id, (char *)fix.id, + sizeof(fix.id)); + err |= __put_user((__u32)(unsigned long)fix.smem_start, + &fix32->smem_start); + err |= __put_user(fix.smem_len, &fix32->smem_len); + err |= __put_user(fix.type, &fix32->type); + err |= __put_user(fix.type_aux, &fix32->type_aux); + err |= __put_user(fix.visual, &fix32->visual); + err |= __put_user(fix.xpanstep, &fix32->xpanstep); + err |= __put_user(fix.ypanstep, &fix32->ypanstep); + err |= __put_user(fix.ywrapstep, &fix32->ywrapstep); + err |= __put_user(fix.line_length, &fix32->line_length); + err |= __put_user((__u32)(unsigned long)fix.mmio_start, + &fix32->mmio_start); + err |= __put_user(fix.mmio_len, &fix32->mmio_len); + err |= __put_user(fix.accel, &fix32->accel); + err |= __copy_to_user((char *)fix32->reserved, + (char *)fix.reserved, + sizeof(fix.reserved)); + if (err) + err = -EFAULT; + } + + return err; +} + +struct fb_cmap32 { + __u32 start; /* First entry */ + __u32 len; /* Number of entries */ + __u32 red; /* Red values */ + __u32 green; + __u32 blue; + __u32 transp; /* transparency, can be NULL */ +}; + +static int do_fbiocmap_ioctl(unsigned int fd, unsigned int cmd, + unsigned long arg) +{ + mm_segment_t old_fs = get_fs(); + u32 red = 0, green = 0, blue = 0, transp = 0; + struct fb_cmap cmap; + struct fb_cmap32 *cmap32 = (struct fb_cmap32 *)arg; + int err; + + memset(&cmap, 0, sizeof(cmap)); + + err = __get_user(cmap.start, &cmap32->start); + err |= __get_user(cmap.len, &cmap32->len); + err |= __get_user(red, &cmap32->red); + err |= __get_user(green, &cmap32->green); + err |= __get_user(blue, &cmap32->blue); + err |= __get_user(transp, &cmap32->transp); + if (err) + return -EFAULT; + + err = -ENOMEM; + cmap.red = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL); + if (!cmap.red) + goto out; + cmap.green = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL); + if (!cmap.green) + goto out; + cmap.blue = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL); + if (!cmap.blue) + goto out; + if (transp) { + cmap.transp = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL); + if (!cmap.transp) + goto out; + } + + if (cmd == FBIOPUTCMAP) { + err = __copy_from_user(cmap.red, (char *)A(red), + cmap.len * sizeof(__u16)); + err |= __copy_from_user(cmap.green, (char *)A(green), + cmap.len * sizeof(__u16)); + err |= __copy_from_user(cmap.blue, (char *)A(blue), + cmap.len * sizeof(__u16)); + if (cmap.transp) + err |= __copy_from_user(cmap.transp, (char *)A(transp), + cmap.len * sizeof(__u16)); + if (err) { + err = -EFAULT; + goto out; + } + } + + set_fs(KERNEL_DS); + err = sys_ioctl(fd, cmd, (unsigned long)&cmap); + set_fs(old_fs); + if (err) + goto out; + + if (cmd == FBIOGETCMAP) { + err = __copy_to_user((char *)A(red), cmap.red, + cmap.len * sizeof(__u16)); + err |= __copy_to_user((char *)A(green), cmap.blue, + cmap.len * sizeof(__u16)); + err |= __copy_to_user((char *)A(blue), cmap.blue, + cmap.len * sizeof(__u16)); + if (cmap.transp) + err |= __copy_to_user((char *)A(transp), cmap.transp, + cmap.len * sizeof(__u16)); + if (err) { + err = -EFAULT; + goto out; + } + } + +out: + if (cmap.red) + kfree(cmap.red); + if (cmap.green) + kfree(cmap.green); + if (cmap.blue) + kfree(cmap.blue); + if (cmap.transp) + kfree(cmap.transp); + + return err; +} + +#endif /* CONFIG_FB */ + + static int do_siocgstamp(unsigned int fd, unsigned int cmd, unsigned long arg) { struct compat_timeval *up = (struct compat_timeval *)arg; @@ -190,7 +412,7 @@ old_fs = get_fs(); set_fs (KERNEL_DS); - err = sys_ioctl (fd, SIOCGIFCONF, (unsigned long)&ifc); + err = sys_ioctl (fd, SIOCGIFCONF, (unsigned long)&ifc); set_fs (old_fs); if (err) goto out; @@ -217,28 +439,52 @@ return err; } -static inline int dev_ifsioc(unsigned int fd, unsigned int cmd, - unsigned long arg) +int siocdevprivate_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + struct ifreq *u_ifreq64; + struct ifreq32 *u_ifreq32 = (struct ifreq32 *) arg; + char tmp_buf[IFNAMSIZ]; + void *data64; + u32 data32; + + if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]), + IFNAMSIZ)) + return -EFAULT; + if (__get_user(data32, &u_ifreq32->ifr_ifru.ifru_data)) + return -EFAULT; + data64 = (void *) A(data32); + + u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64)); + + /* Don't check these user accesses, just let that get trapped + * in the ioctl handler instead. + */ + copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0], IFNAMSIZ); + __put_user(data64, &u_ifreq64->ifr_ifru.ifru_data); + + return sys_ioctl(fd, cmd, (unsigned long) u_ifreq64); +} + +static int dev_ifsioc(unsigned int fd, unsigned int cmd, unsigned long arg) { - struct ifreq32 *uifr = (struct ifreq32 *)arg; struct ifreq ifr; mm_segment_t old_fs; int err; switch (cmd) { case SIOCSIFMAP: - err = copy_from_user(&ifr, uifr, sizeof(ifr.ifr_name)); - err |= __get_user(ifr.ifr_map.mem_start, &(uifr->ifr_ifru.ifru_map.mem_start)); - err |= __get_user(ifr.ifr_map.mem_end, &(uifr->ifr_ifru.ifru_map.mem_end)); - err |= __get_user(ifr.ifr_map.base_addr, &(uifr->ifr_ifru.ifru_map.base_addr)); - err |= __get_user(ifr.ifr_map.irq, &(uifr->ifr_ifru.ifru_map.irq)); - err |= __get_user(ifr.ifr_map.dma, &(uifr->ifr_ifru.ifru_map.dma)); - err |= __get_user(ifr.ifr_map.port, &(uifr->ifr_ifru.ifru_map.port)); + err = copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(ifr.ifr_name)); + err |= __get_user(ifr.ifr_map.mem_start, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_start)); + err |= __get_user(ifr.ifr_map.mem_end, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_end)); + err |= __get_user(ifr.ifr_map.base_addr, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.base_addr)); + err |= __get_user(ifr.ifr_map.irq, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.irq)); + err |= __get_user(ifr.ifr_map.dma, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.dma)); + err |= __get_user(ifr.ifr_map.port, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.port)); if (err) return -EFAULT; break; default: - if (copy_from_user(&ifr, uifr, sizeof(struct ifreq32))) + if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32))) return -EFAULT; break; } @@ -259,17 +505,17 @@ case SIOCGIFDSTADDR: case SIOCGIFNETMASK: case SIOCGIFTXQLEN: - if (copy_to_user(uifr, &ifr, sizeof(struct ifreq32))) + if (copy_to_user((struct ifreq32 *)arg, &ifr, sizeof(struct ifreq32))) return -EFAULT; break; case SIOCGIFMAP: - err = copy_to_user(uifr, &ifr, sizeof(ifr.ifr_name)); - err |= __put_user(ifr.ifr_map.mem_start, &(uifr->ifr_ifru.ifru_map.mem_start)); - err |= __put_user(ifr.ifr_map.mem_end, &(uifr->ifr_ifru.ifru_map.mem_end)); - err |= __put_user(ifr.ifr_map.base_addr, &(uifr->ifr_ifru.ifru_map.base_addr)); - err |= __put_user(ifr.ifr_map.irq, &(uifr->ifr_ifru.ifru_map.irq)); - err |= __put_user(ifr.ifr_map.dma, &(uifr->ifr_ifru.ifru_map.dma)); - err |= __put_user(ifr.ifr_map.port, &(uifr->ifr_ifru.ifru_map.port)); + err = copy_to_user((struct ifreq32 *)arg, &ifr, sizeof(ifr.ifr_name)); + err |= __put_user(ifr.ifr_map.mem_start, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_start)); + err |= __put_user(ifr.ifr_map.mem_end, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_end)); + err |= __put_user(ifr.ifr_map.base_addr, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.base_addr)); + err |= __put_user(ifr.ifr_map.irq, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.irq)); + err |= __put_user(ifr.ifr_map.dma, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.dma)); + err |= __put_user(ifr.ifr_map.port, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.port)); if (err) err = -EFAULT; break; @@ -306,7 +552,7 @@ u32 rtdev; int ret; mm_segment_t old_fs = get_fs(); - + ret = copy_from_user (&r.rt_dst, &(ur->rt_dst), 3 * sizeof(struct sockaddr)); ret |= __get_user (r.rt_flags, &(ur->rt_flags)); ret |= __get_user (r.rt_metric, &(ur->rt_metric)); @@ -404,7 +650,7 @@ struct blkpg_partition p; int err; mm_segment_t old_fs = get_fs(); - + err = get_user(a.op, &arg->op); err |= __get_user(a.flags, &arg->flags); err |= __get_user(a.datalen, &arg->datalen); @@ -423,7 +669,7 @@ set_fs (old_fs); default: return -EINVAL; - } + } return err; } @@ -557,235 +803,356 @@ return rw_long(fd, AUTOFS_IOC_SETTIMEOUT, arg); } -struct ioctl32_handler { - unsigned int cmd; - int (*function)(unsigned int, unsigned int, unsigned long); -}; - -struct ioctl32_list { - struct ioctl32_handler handler; - struct ioctl32_list *next; -}; - -#define IOCTL32_DEFAULT(cmd) { { cmd, (void *) sys_ioctl }, 0 } -#define IOCTL32_HANDLER(cmd, handler) { { cmd, (void *) handler }, 0 } - -static struct ioctl32_list ioctl32_handler_table[] = { - IOCTL32_DEFAULT(TCGETA), - IOCTL32_DEFAULT(TCSETA), - IOCTL32_DEFAULT(TCSETAW), - IOCTL32_DEFAULT(TCSETAF), - IOCTL32_DEFAULT(TCSBRK), - IOCTL32_DEFAULT(TCXONC), - IOCTL32_DEFAULT(TCFLSH), - IOCTL32_DEFAULT(TCGETS), - IOCTL32_DEFAULT(TCSETS), - IOCTL32_DEFAULT(TCSETSW), - IOCTL32_DEFAULT(TCSETSF), - IOCTL32_DEFAULT(TIOCLINUX), - - IOCTL32_DEFAULT(TIOCGETD), - IOCTL32_DEFAULT(TIOCSETD), - IOCTL32_DEFAULT(TIOCEXCL), - IOCTL32_DEFAULT(TIOCNXCL), - IOCTL32_DEFAULT(TIOCCONS), - IOCTL32_DEFAULT(TIOCGSOFTCAR), - IOCTL32_DEFAULT(TIOCSSOFTCAR), - IOCTL32_DEFAULT(TIOCSWINSZ), - IOCTL32_DEFAULT(TIOCGWINSZ), - IOCTL32_DEFAULT(TIOCMGET), - IOCTL32_DEFAULT(TIOCMBIC), - IOCTL32_DEFAULT(TIOCMBIS), - IOCTL32_DEFAULT(TIOCMSET), - IOCTL32_DEFAULT(TIOCPKT), - IOCTL32_DEFAULT(TIOCNOTTY), - IOCTL32_DEFAULT(TIOCSTI), - IOCTL32_DEFAULT(TIOCOUTQ), - IOCTL32_DEFAULT(TIOCSPGRP), - IOCTL32_DEFAULT(TIOCGPGRP), - IOCTL32_DEFAULT(TIOCSCTTY), - IOCTL32_DEFAULT(TIOCGPTN), - IOCTL32_DEFAULT(TIOCSPTLCK), - IOCTL32_DEFAULT(TIOCGSERIAL), - IOCTL32_DEFAULT(TIOCSSERIAL), - IOCTL32_DEFAULT(TIOCSERGETLSR), - - IOCTL32_DEFAULT(FIOCLEX), - IOCTL32_DEFAULT(FIONCLEX), - IOCTL32_DEFAULT(FIOASYNC), - IOCTL32_DEFAULT(FIONBIO), - IOCTL32_DEFAULT(FIONREAD), - - IOCTL32_DEFAULT(PIO_FONT), - IOCTL32_DEFAULT(GIO_FONT), - IOCTL32_DEFAULT(KDSIGACCEPT), - IOCTL32_DEFAULT(KDGETKEYCODE), - IOCTL32_DEFAULT(KDSETKEYCODE), - IOCTL32_DEFAULT(KIOCSOUND), - IOCTL32_DEFAULT(KDMKTONE), - IOCTL32_DEFAULT(KDGKBTYPE), - IOCTL32_DEFAULT(KDSETMODE), - IOCTL32_DEFAULT(KDGETMODE), - IOCTL32_DEFAULT(KDSKBMODE), - IOCTL32_DEFAULT(KDGKBMODE), - IOCTL32_DEFAULT(KDSKBMETA), - IOCTL32_DEFAULT(KDGKBMETA), - IOCTL32_DEFAULT(KDGKBENT), - IOCTL32_DEFAULT(KDSKBENT), - IOCTL32_DEFAULT(KDGKBSENT), - IOCTL32_DEFAULT(KDSKBSENT), - IOCTL32_DEFAULT(KDGKBDIACR), - IOCTL32_DEFAULT(KDSKBDIACR), - IOCTL32_DEFAULT(KDGKBLED), - IOCTL32_DEFAULT(KDSKBLED), - IOCTL32_DEFAULT(KDGETLED), - IOCTL32_DEFAULT(KDSETLED), - IOCTL32_DEFAULT(GIO_SCRNMAP), - IOCTL32_DEFAULT(PIO_SCRNMAP), - IOCTL32_DEFAULT(GIO_UNISCRNMAP), - IOCTL32_DEFAULT(PIO_UNISCRNMAP), - IOCTL32_DEFAULT(PIO_FONTRESET), - IOCTL32_DEFAULT(PIO_UNIMAPCLR), - - IOCTL32_DEFAULT(VT_SETMODE), - IOCTL32_DEFAULT(VT_GETMODE), - IOCTL32_DEFAULT(VT_GETSTATE), - IOCTL32_DEFAULT(VT_OPENQRY), - IOCTL32_DEFAULT(VT_ACTIVATE), - IOCTL32_DEFAULT(VT_WAITACTIVE), - IOCTL32_DEFAULT(VT_RELDISP), - IOCTL32_DEFAULT(VT_DISALLOCATE), - IOCTL32_DEFAULT(VT_RESIZE), - IOCTL32_DEFAULT(VT_RESIZEX), - IOCTL32_DEFAULT(VT_LOCKSWITCH), - IOCTL32_DEFAULT(VT_UNLOCKSWITCH), +typedef int (* ioctl32_handler_t)(unsigned int, unsigned int, unsigned long, struct file *); + +#define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL((cmd),sys_ioctl) +#define HANDLE_IOCTL(cmd,handler) { (cmd), (ioctl32_handler_t)(handler), NULL }, +#define IOCTL_TABLE_START \ + struct ioctl_trans ioctl_start[] = { +#define IOCTL_TABLE_END \ + }; struct ioctl_trans ioctl_end[0]; + + +IOCTL_TABLE_START +#include +COMPATIBLE_IOCTL(TCGETA) +COMPATIBLE_IOCTL(TCSETA) +COMPATIBLE_IOCTL(TCSETAW) +COMPATIBLE_IOCTL(TCSETAF) +COMPATIBLE_IOCTL(TCSBRK) +COMPATIBLE_IOCTL(TCXONC) +COMPATIBLE_IOCTL(TCFLSH) +COMPATIBLE_IOCTL(TCGETS) +COMPATIBLE_IOCTL(TCSETS) +COMPATIBLE_IOCTL(TCSETSW) +COMPATIBLE_IOCTL(TCSETSF) +COMPATIBLE_IOCTL(TIOCLINUX) + +COMPATIBLE_IOCTL(TIOCGETD) +COMPATIBLE_IOCTL(TIOCSETD) +COMPATIBLE_IOCTL(TIOCEXCL) +COMPATIBLE_IOCTL(TIOCNXCL) +COMPATIBLE_IOCTL(TIOCCONS) +COMPATIBLE_IOCTL(TIOCGSOFTCAR) +COMPATIBLE_IOCTL(TIOCSSOFTCAR) +COMPATIBLE_IOCTL(TIOCSWINSZ) +COMPATIBLE_IOCTL(TIOCGWINSZ) +COMPATIBLE_IOCTL(TIOCMGET) +COMPATIBLE_IOCTL(TIOCMBIC) +COMPATIBLE_IOCTL(TIOCMBIS) +COMPATIBLE_IOCTL(TIOCMSET) +COMPATIBLE_IOCTL(TIOCPKT) +COMPATIBLE_IOCTL(TIOCNOTTY) +COMPATIBLE_IOCTL(TIOCSTI) +COMPATIBLE_IOCTL(TIOCOUTQ) +COMPATIBLE_IOCTL(TIOCSPGRP) +COMPATIBLE_IOCTL(TIOCGPGRP) +COMPATIBLE_IOCTL(TIOCSCTTY) +COMPATIBLE_IOCTL(TIOCGPTN) +COMPATIBLE_IOCTL(TIOCSPTLCK) +COMPATIBLE_IOCTL(TIOCGSERIAL) +COMPATIBLE_IOCTL(TIOCSSERIAL) +COMPATIBLE_IOCTL(TIOCSERGETLSR) + +COMPATIBLE_IOCTL(FIOCLEX) +COMPATIBLE_IOCTL(FIONCLEX) +COMPATIBLE_IOCTL(FIOASYNC) +COMPATIBLE_IOCTL(FIONBIO) +COMPATIBLE_IOCTL(FIONREAD) + +#ifdef CONFIG_FB +/* Big F */ +COMPATIBLE_IOCTL(FBIOGET_VSCREENINFO) +COMPATIBLE_IOCTL(FBIOPUT_VSCREENINFO) +HANDLE_IOCTL(FBIOGET_FSCREENINFO, do_fbioget_fscreeninfo_ioctl) +HANDLE_IOCTL(FBIOGETCMAP, do_fbiocmap_ioctl) +HANDLE_IOCTL(FBIOPUTCMAP, do_fbiocmap_ioctl) +COMPATIBLE_IOCTL(FBIOPAN_DISPLAY) +#endif /* CONFIG_FB */ + +/* Big K */ +COMPATIBLE_IOCTL(PIO_FONT) +COMPATIBLE_IOCTL(GIO_FONT) +COMPATIBLE_IOCTL(KDSIGACCEPT) +COMPATIBLE_IOCTL(KDGETKEYCODE) +COMPATIBLE_IOCTL(KDSETKEYCODE) +COMPATIBLE_IOCTL(KIOCSOUND) +COMPATIBLE_IOCTL(KDMKTONE) +COMPATIBLE_IOCTL(KDGKBTYPE) +COMPATIBLE_IOCTL(KDSETMODE) +COMPATIBLE_IOCTL(KDGETMODE) +COMPATIBLE_IOCTL(KDSKBMODE) +COMPATIBLE_IOCTL(KDGKBMODE) +COMPATIBLE_IOCTL(KDSKBMETA) +COMPATIBLE_IOCTL(KDGKBMETA) +COMPATIBLE_IOCTL(KDGKBENT) +COMPATIBLE_IOCTL(KDSKBENT) +COMPATIBLE_IOCTL(KDGKBSENT) +COMPATIBLE_IOCTL(KDSKBSENT) +COMPATIBLE_IOCTL(KDGKBDIACR) +COMPATIBLE_IOCTL(KDSKBDIACR) +COMPATIBLE_IOCTL(KDKBDREP) +COMPATIBLE_IOCTL(KDGKBLED) +COMPATIBLE_IOCTL(KDSKBLED) +COMPATIBLE_IOCTL(KDGETLED) +COMPATIBLE_IOCTL(KDSETLED) +COMPATIBLE_IOCTL(GIO_SCRNMAP) +COMPATIBLE_IOCTL(PIO_SCRNMAP) +COMPATIBLE_IOCTL(GIO_UNISCRNMAP) +COMPATIBLE_IOCTL(PIO_UNISCRNMAP) +COMPATIBLE_IOCTL(PIO_FONTRESET) +COMPATIBLE_IOCTL(PIO_UNIMAPCLR) + +/* Big S */ +COMPATIBLE_IOCTL(SCSI_IOCTL_GET_IDLUN) +COMPATIBLE_IOCTL(SCSI_IOCTL_DOORLOCK) +COMPATIBLE_IOCTL(SCSI_IOCTL_DOORUNLOCK) +COMPATIBLE_IOCTL(SCSI_IOCTL_TEST_UNIT_READY) +COMPATIBLE_IOCTL(SCSI_IOCTL_TAGGED_ENABLE) +COMPATIBLE_IOCTL(SCSI_IOCTL_TAGGED_DISABLE) +COMPATIBLE_IOCTL(SCSI_IOCTL_GET_BUS_NUMBER) +COMPATIBLE_IOCTL(SCSI_IOCTL_SEND_COMMAND) + +/* Big V */ +COMPATIBLE_IOCTL(VT_SETMODE) +COMPATIBLE_IOCTL(VT_GETMODE) +COMPATIBLE_IOCTL(VT_GETSTATE) +COMPATIBLE_IOCTL(VT_OPENQRY) +COMPATIBLE_IOCTL(VT_ACTIVATE) +COMPATIBLE_IOCTL(VT_WAITACTIVE) +COMPATIBLE_IOCTL(VT_RELDISP) +COMPATIBLE_IOCTL(VT_DISALLOCATE) +COMPATIBLE_IOCTL(VT_RESIZE) +COMPATIBLE_IOCTL(VT_RESIZEX) +COMPATIBLE_IOCTL(VT_LOCKSWITCH) +COMPATIBLE_IOCTL(VT_UNLOCKSWITCH) #ifdef CONFIG_NET - /* Socket level stuff */ - IOCTL32_DEFAULT(FIOSETOWN), - IOCTL32_DEFAULT(SIOCSPGRP), - IOCTL32_DEFAULT(FIOGETOWN), - IOCTL32_DEFAULT(SIOCGPGRP), - IOCTL32_DEFAULT(SIOCATMARK), - IOCTL32_DEFAULT(SIOCSIFLINK), - IOCTL32_DEFAULT(SIOCSIFENCAP), - IOCTL32_DEFAULT(SIOCGIFENCAP), - IOCTL32_DEFAULT(SIOCSIFBR), - IOCTL32_DEFAULT(SIOCGIFBR), - IOCTL32_DEFAULT(SIOCSARP), - IOCTL32_DEFAULT(SIOCGARP), - IOCTL32_DEFAULT(SIOCDARP), - IOCTL32_DEFAULT(SIOCSRARP), - IOCTL32_DEFAULT(SIOCGRARP), - IOCTL32_DEFAULT(SIOCDRARP), - IOCTL32_DEFAULT(SIOCADDDLCI), - IOCTL32_DEFAULT(SIOCDELDLCI), - - IOCTL32_HANDLER(SIOCGIFNAME, dev_ifname32), - IOCTL32_HANDLER(SIOCGIFCONF, dev_ifconf), - IOCTL32_HANDLER(SIOCGIFFLAGS, dev_ifsioc), - IOCTL32_HANDLER(SIOCSIFFLAGS, dev_ifsioc), - IOCTL32_HANDLER(SIOCGIFMETRIC, dev_ifsioc), - IOCTL32_HANDLER(SIOCSIFMETRIC, dev_ifsioc), - IOCTL32_HANDLER(SIOCGIFMTU, dev_ifsioc), - IOCTL32_HANDLER(SIOCSIFMTU, dev_ifsioc), - IOCTL32_HANDLER(SIOCGIFMEM, dev_ifsioc), - IOCTL32_HANDLER(SIOCSIFMEM, dev_ifsioc), - IOCTL32_HANDLER(SIOCGIFHWADDR, dev_ifsioc), - IOCTL32_HANDLER(SIOCSIFHWADDR, dev_ifsioc), - IOCTL32_HANDLER(SIOCADDMULTI, dev_ifsioc), - IOCTL32_HANDLER(SIOCDELMULTI, dev_ifsioc), - IOCTL32_HANDLER(SIOCGIFINDEX, dev_ifsioc), - IOCTL32_HANDLER(SIOCGIFMAP, dev_ifsioc), - IOCTL32_HANDLER(SIOCSIFMAP, dev_ifsioc), - IOCTL32_HANDLER(SIOCGIFADDR, dev_ifsioc), - IOCTL32_HANDLER(SIOCSIFADDR, dev_ifsioc), - IOCTL32_HANDLER(SIOCGIFBRDADDR, dev_ifsioc), - IOCTL32_HANDLER(SIOCSIFBRDADDR, dev_ifsioc), - IOCTL32_HANDLER(SIOCGIFDSTADDR, dev_ifsioc), - IOCTL32_HANDLER(SIOCSIFDSTADDR, dev_ifsioc), - IOCTL32_HANDLER(SIOCGIFNETMASK, dev_ifsioc), - IOCTL32_HANDLER(SIOCSIFNETMASK, dev_ifsioc), - IOCTL32_HANDLER(SIOCSIFPFLAGS, dev_ifsioc), - IOCTL32_HANDLER(SIOCGIFPFLAGS, dev_ifsioc), - IOCTL32_HANDLER(SIOCGIFTXQLEN, dev_ifsioc), - IOCTL32_HANDLER(SIOCSIFTXQLEN, dev_ifsioc), - IOCTL32_HANDLER(SIOCADDRT, routing_ioctl), - IOCTL32_HANDLER(SIOCDELRT, routing_ioctl), - /* - * Note SIOCRTMSG is no longer, so this is safe and * the user would - * have seen just an -EINVAL anyways. - */ - IOCTL32_HANDLER(SIOCRTMSG, ret_einval), - IOCTL32_HANDLER(SIOCGSTAMP, do_siocgstamp), +/* Socket level stuff */ +COMPATIBLE_IOCTL(FIOSETOWN) +COMPATIBLE_IOCTL(SIOCSPGRP) +COMPATIBLE_IOCTL(FIOGETOWN) +COMPATIBLE_IOCTL(SIOCGPGRP) +COMPATIBLE_IOCTL(SIOCATMARK) +COMPATIBLE_IOCTL(SIOCSIFLINK) +COMPATIBLE_IOCTL(SIOCSIFENCAP) +COMPATIBLE_IOCTL(SIOCGIFENCAP) +COMPATIBLE_IOCTL(SIOCSIFBR) +COMPATIBLE_IOCTL(SIOCGIFBR) +COMPATIBLE_IOCTL(SIOCSARP) +COMPATIBLE_IOCTL(SIOCGARP) +COMPATIBLE_IOCTL(SIOCDARP) +COMPATIBLE_IOCTL(SIOCSRARP) +COMPATIBLE_IOCTL(SIOCGRARP) +COMPATIBLE_IOCTL(SIOCDRARP) +COMPATIBLE_IOCTL(SIOCADDDLCI) +COMPATIBLE_IOCTL(SIOCDELDLCI) +/* SG stuff */ +COMPATIBLE_IOCTL(SG_SET_TIMEOUT) +COMPATIBLE_IOCTL(SG_GET_TIMEOUT) +COMPATIBLE_IOCTL(SG_EMULATED_HOST) +COMPATIBLE_IOCTL(SG_SET_TRANSFORM) +COMPATIBLE_IOCTL(SG_GET_TRANSFORM) +COMPATIBLE_IOCTL(SG_SET_RESERVED_SIZE) +COMPATIBLE_IOCTL(SG_GET_RESERVED_SIZE) +COMPATIBLE_IOCTL(SG_GET_SCSI_ID) +COMPATIBLE_IOCTL(SG_SET_FORCE_LOW_DMA) +COMPATIBLE_IOCTL(SG_GET_LOW_DMA) +COMPATIBLE_IOCTL(SG_SET_FORCE_PACK_ID) +COMPATIBLE_IOCTL(SG_GET_PACK_ID) +COMPATIBLE_IOCTL(SG_GET_NUM_WAITING) +COMPATIBLE_IOCTL(SG_SET_DEBUG) +COMPATIBLE_IOCTL(SG_GET_SG_TABLESIZE) +COMPATIBLE_IOCTL(SG_GET_COMMAND_Q) +COMPATIBLE_IOCTL(SG_SET_COMMAND_Q) +COMPATIBLE_IOCTL(SG_GET_VERSION_NUM) +COMPATIBLE_IOCTL(SG_NEXT_CMD_LEN) +COMPATIBLE_IOCTL(SG_SCSI_RESET) +COMPATIBLE_IOCTL(SG_IO) +COMPATIBLE_IOCTL(SG_GET_REQUEST_TABLE) +COMPATIBLE_IOCTL(SG_SET_KEEP_ORPHAN) +COMPATIBLE_IOCTL(SG_GET_KEEP_ORPHAN) +/* PPP stuff */ +COMPATIBLE_IOCTL(PPPIOCGFLAGS) +COMPATIBLE_IOCTL(PPPIOCSFLAGS) +COMPATIBLE_IOCTL(PPPIOCGASYNCMAP) +COMPATIBLE_IOCTL(PPPIOCSASYNCMAP) +COMPATIBLE_IOCTL(PPPIOCGUNIT) +COMPATIBLE_IOCTL(PPPIOCGRASYNCMAP) +COMPATIBLE_IOCTL(PPPIOCSRASYNCMAP) +COMPATIBLE_IOCTL(PPPIOCGMRU) +COMPATIBLE_IOCTL(PPPIOCSMRU) +COMPATIBLE_IOCTL(PPPIOCSMAXCID) +COMPATIBLE_IOCTL(PPPIOCGXASYNCMAP) +COMPATIBLE_IOCTL(PPPIOCSXASYNCMAP) +COMPATIBLE_IOCTL(PPPIOCXFERUNIT) +COMPATIBLE_IOCTL(PPPIOCGNPMODE) +COMPATIBLE_IOCTL(PPPIOCSNPMODE) +COMPATIBLE_IOCTL(PPPIOCGDEBUG) +COMPATIBLE_IOCTL(PPPIOCSDEBUG) +COMPATIBLE_IOCTL(PPPIOCNEWUNIT) +COMPATIBLE_IOCTL(PPPIOCATTACH) +COMPATIBLE_IOCTL(PPPIOCGCHAN) +/* PPPOX */ +COMPATIBLE_IOCTL(PPPOEIOCSFWD) +COMPATIBLE_IOCTL(PPPOEIOCDFWD) +/* CDROM stuff */ +COMPATIBLE_IOCTL(CDROMPAUSE) +COMPATIBLE_IOCTL(CDROMRESUME) +COMPATIBLE_IOCTL(CDROMPLAYMSF) +COMPATIBLE_IOCTL(CDROMPLAYTRKIND) +COMPATIBLE_IOCTL(CDROMREADTOCHDR) +COMPATIBLE_IOCTL(CDROMREADTOCENTRY) +COMPATIBLE_IOCTL(CDROMSTOP) +COMPATIBLE_IOCTL(CDROMSTART) +COMPATIBLE_IOCTL(CDROMEJECT) +COMPATIBLE_IOCTL(CDROMVOLCTRL) +COMPATIBLE_IOCTL(CDROMSUBCHNL) +COMPATIBLE_IOCTL(CDROMEJECT_SW) +COMPATIBLE_IOCTL(CDROMMULTISESSION) +COMPATIBLE_IOCTL(CDROM_GET_MCN) +COMPATIBLE_IOCTL(CDROMRESET) +COMPATIBLE_IOCTL(CDROMVOLREAD) +COMPATIBLE_IOCTL(CDROMSEEK) +COMPATIBLE_IOCTL(CDROMPLAYBLK) +COMPATIBLE_IOCTL(CDROMCLOSETRAY) +COMPATIBLE_IOCTL(CDROM_SET_OPTIONS) +COMPATIBLE_IOCTL(CDROM_CLEAR_OPTIONS) +COMPATIBLE_IOCTL(CDROM_SELECT_SPEED) +COMPATIBLE_IOCTL(CDROM_SELECT_DISC) +COMPATIBLE_IOCTL(CDROM_MEDIA_CHANGED) +COMPATIBLE_IOCTL(CDROM_DRIVE_STATUS) +COMPATIBLE_IOCTL(CDROM_DISC_STATUS) +COMPATIBLE_IOCTL(CDROM_CHANGER_NSLOTS) +COMPATIBLE_IOCTL(CDROM_LOCKDOOR) +COMPATIBLE_IOCTL(CDROM_DEBUG) +COMPATIBLE_IOCTL(CDROM_GET_CAPABILITY) +/* DVD ioctls */ +COMPATIBLE_IOCTL(DVD_READ_STRUCT) +COMPATIBLE_IOCTL(DVD_WRITE_STRUCT) +COMPATIBLE_IOCTL(DVD_AUTH) +/* Big L */ +COMPATIBLE_IOCTL(LOOP_SET_FD) +COMPATIBLE_IOCTL(LOOP_CLR_FD) + +/* And these ioctls need translation */ +HANDLE_IOCTL(SIOCGIFNAME, dev_ifname32) +HANDLE_IOCTL(SIOCGIFCONF, dev_ifconf) +HANDLE_IOCTL(SIOCGIFFLAGS, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFFLAGS, dev_ifsioc) +HANDLE_IOCTL(SIOCGIFMETRIC, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFMETRIC, dev_ifsioc) +HANDLE_IOCTL(SIOCGIFMTU, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFMTU, dev_ifsioc) +HANDLE_IOCTL(SIOCGIFMEM, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFMEM, dev_ifsioc) +HANDLE_IOCTL(SIOCGIFHWADDR, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFHWADDR, dev_ifsioc) +HANDLE_IOCTL(SIOCADDMULTI, dev_ifsioc) +HANDLE_IOCTL(SIOCDELMULTI, dev_ifsioc) +HANDLE_IOCTL(SIOCGIFINDEX, dev_ifsioc) +HANDLE_IOCTL(SIOCGIFMAP, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFMAP, dev_ifsioc) +HANDLE_IOCTL(SIOCGIFADDR, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFADDR, dev_ifsioc) +HANDLE_IOCTL(SIOCGIFBRDADDR, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFBRDADDR, dev_ifsioc) +HANDLE_IOCTL(SIOCGIFDSTADDR, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFDSTADDR, dev_ifsioc) +HANDLE_IOCTL(SIOCGIFNETMASK, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFNETMASK, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFPFLAGS, dev_ifsioc) +HANDLE_IOCTL(SIOCGIFPFLAGS, dev_ifsioc) +HANDLE_IOCTL(SIOCGPPPSTATS, dev_ifsioc) +HANDLE_IOCTL(SIOCGPPPCSTATS, dev_ifsioc) +HANDLE_IOCTL(SIOCGPPPVER, dev_ifsioc) +HANDLE_IOCTL(SIOCGIFTXQLEN, dev_ifsioc) +HANDLE_IOCTL(SIOCSIFTXQLEN, dev_ifsioc) +HANDLE_IOCTL(SIOCADDRT, routing_ioctl) +HANDLE_IOCTL(SIOCDELRT, routing_ioctl) +/* + * Note SIOCRTMSG is no longer, so this is safe and * the user would + * have seen just an -EINVAL anyways. + */ +HANDLE_IOCTL(SIOCRTMSG, ret_einval) +HANDLE_IOCTL(SIOCGSTAMP, do_siocgstamp) #endif /* CONFIG_NET */ - IOCTL32_HANDLER(EXT2_IOC32_GETFLAGS, do_ext2_ioctl), - IOCTL32_HANDLER(EXT2_IOC32_SETFLAGS, do_ext2_ioctl), - IOCTL32_HANDLER(EXT2_IOC32_GETVERSION, do_ext2_ioctl), - IOCTL32_HANDLER(EXT2_IOC32_SETVERSION, do_ext2_ioctl), - - IOCTL32_HANDLER(HDIO_GETGEO, hdio_getgeo), /* hdreg.h ioctls */ - IOCTL32_HANDLER(HDIO_GET_UNMASKINTR, hdio_ioctl_trans), - IOCTL32_HANDLER(HDIO_GET_MULTCOUNT, hdio_ioctl_trans), - IOCTL32_HANDLER(HDIO_GET_KEEPSETTINGS, hdio_ioctl_trans), - IOCTL32_HANDLER(HDIO_GET_32BIT, hdio_ioctl_trans), - IOCTL32_HANDLER(HDIO_GET_NOWERR, hdio_ioctl_trans), - IOCTL32_HANDLER(HDIO_GET_DMA, hdio_ioctl_trans), - IOCTL32_HANDLER(HDIO_GET_NICE, hdio_ioctl_trans), - IOCTL32_DEFAULT(HDIO_GET_IDENTITY), - IOCTL32_DEFAULT(HDIO_DRIVE_CMD), - IOCTL32_DEFAULT(HDIO_SET_MULTCOUNT), - IOCTL32_DEFAULT(HDIO_SET_UNMASKINTR), - IOCTL32_DEFAULT(HDIO_SET_KEEPSETTINGS), - IOCTL32_DEFAULT(HDIO_SET_32BIT), - IOCTL32_DEFAULT(HDIO_SET_NOWERR), - IOCTL32_DEFAULT(HDIO_SET_DMA), - IOCTL32_DEFAULT(HDIO_SET_PIO_MODE), - IOCTL32_DEFAULT(HDIO_SET_NICE), - - IOCTL32_DEFAULT(BLKROSET), /* fs.h ioctls */ - IOCTL32_DEFAULT(BLKROGET), - IOCTL32_DEFAULT(BLKRRPART), - IOCTL32_HANDLER(BLKGETSIZE, w_long), - - IOCTL32_DEFAULT(BLKFLSBUF), - IOCTL32_DEFAULT(BLKSECTSET), - IOCTL32_HANDLER(BLKSECTGET, w_long), - IOCTL32_DEFAULT(BLKSSZGET), - IOCTL32_HANDLER(BLKPG, blkpg_ioctl_trans), - IOCTL32_DEFAULT(BLKBSZGET), - IOCTL32_DEFAULT(BLKBSZSET), +HANDLE_IOCTL(EXT2_IOC32_GETFLAGS, do_ext2_ioctl) +HANDLE_IOCTL(EXT2_IOC32_SETFLAGS, do_ext2_ioctl) +HANDLE_IOCTL(EXT2_IOC32_GETVERSION, do_ext2_ioctl) +HANDLE_IOCTL(EXT2_IOC32_SETVERSION, do_ext2_ioctl) + +HANDLE_IOCTL(HDIO_GETGEO, hdio_getgeo) /* hdreg.h ioctls */ +HANDLE_IOCTL(HDIO_GET_UNMASKINTR, hdio_ioctl_trans) +HANDLE_IOCTL(HDIO_GET_MULTCOUNT, hdio_ioctl_trans) +// HDIO_OBSOLETE_IDENTITY +//HANDLE_IOCTL(HDIO_GET_KEEPSETTINGS, hdio_ioctl_trans) +HANDLE_IOCTL(HDIO_GET_32BIT, hdio_ioctl_trans) +HANDLE_IOCTL(HDIO_GET_NOWERR, hdio_ioctl_trans) +HANDLE_IOCTL(HDIO_GET_DMA, hdio_ioctl_trans) +HANDLE_IOCTL(HDIO_GET_NICE, hdio_ioctl_trans) +COMPATIBLE_IOCTL(HDIO_GET_IDENTITY) +// HDIO_TRISTATE_HWIF /* not implemented */ +// HDIO_DRIVE_TASK /* To do, need specs */ +COMPATIBLE_IOCTL(HDIO_DRIVE_CMD) +COMPATIBLE_IOCTL(HDIO_SET_MULTCOUNT) +COMPATIBLE_IOCTL(HDIO_SET_UNMASKINTR) +//COMPATIBLE_IOCTL(HDIO_SET_KEEPSETTINGS) +COMPATIBLE_IOCTL(HDIO_SET_32BIT) +COMPATIBLE_IOCTL(HDIO_SET_NOWERR) +COMPATIBLE_IOCTL(HDIO_SET_DMA) +COMPATIBLE_IOCTL(HDIO_SET_PIO_MODE) +COMPATIBLE_IOCTL(HDIO_SET_NICE) + +COMPATIBLE_IOCTL(BLKROSET) /* fs.h ioctls */ +COMPATIBLE_IOCTL(BLKROGET) +COMPATIBLE_IOCTL(BLKRRPART) +HANDLE_IOCTL(BLKGETSIZE, w_long) + +COMPATIBLE_IOCTL(BLKFLSBUF) +COMPATIBLE_IOCTL(BLKSECTSET) +HANDLE_IOCTL(BLKSECTGET, w_long) +COMPATIBLE_IOCTL(BLKSSZGET) +HANDLE_IOCTL(BLKPG, blkpg_ioctl_trans) +COMPATIBLE_IOCTL(BLKBSZGET) +COMPATIBLE_IOCTL(BLKBSZSET) #ifdef CONFIG_MD - /* status */ - IOCTL32_DEFAULT(RAID_VERSION), - IOCTL32_DEFAULT(GET_ARRAY_INFO), - IOCTL32_DEFAULT(GET_DISK_INFO), - IOCTL32_DEFAULT(PRINT_RAID_DEBUG), - IOCTL32_DEFAULT(RAID_AUTORUN), - - /* configuration */ - IOCTL32_DEFAULT(CLEAR_ARRAY), - IOCTL32_DEFAULT(ADD_NEW_DISK), - IOCTL32_DEFAULT(HOT_REMOVE_DISK), - IOCTL32_DEFAULT(SET_ARRAY_INFO), - IOCTL32_DEFAULT(SET_DISK_INFO), - IOCTL32_DEFAULT(WRITE_RAID_INFO), - IOCTL32_DEFAULT(UNPROTECT_ARRAY), - IOCTL32_DEFAULT(PROTECT_ARRAY), - IOCTL32_DEFAULT(HOT_ADD_DISK), - IOCTL32_DEFAULT(SET_DISK_FAULTY), - - /* usage */ - IOCTL32_DEFAULT(RUN_ARRAY), - IOCTL32_DEFAULT(START_ARRAY), - IOCTL32_DEFAULT(STOP_ARRAY), - IOCTL32_DEFAULT(STOP_ARRAY_RO), - IOCTL32_DEFAULT(RESTART_ARRAY_RW), +/* status */ +COMPATIBLE_IOCTL(RAID_VERSION) +COMPATIBLE_IOCTL(GET_ARRAY_INFO) +COMPATIBLE_IOCTL(GET_DISK_INFO) +COMPATIBLE_IOCTL(PRINT_RAID_DEBUG) +COMPATIBLE_IOCTL(RAID_AUTORUN) + +/* configuration */ +COMPATIBLE_IOCTL(CLEAR_ARRAY) +COMPATIBLE_IOCTL(ADD_NEW_DISK) +COMPATIBLE_IOCTL(HOT_REMOVE_DISK) +COMPATIBLE_IOCTL(SET_ARRAY_INFO) +COMPATIBLE_IOCTL(SET_DISK_INFO) +COMPATIBLE_IOCTL(WRITE_RAID_INFO) +COMPATIBLE_IOCTL(UNPROTECT_ARRAY) +COMPATIBLE_IOCTL(PROTECT_ARRAY) +COMPATIBLE_IOCTL(HOT_ADD_DISK) +COMPATIBLE_IOCTL(SET_DISK_FAULTY) + +/* usage */ +COMPATIBLE_IOCTL(RUN_ARRAY) +COMPATIBLE_IOCTL(START_ARRAY) +COMPATIBLE_IOCTL(STOP_ARRAY) +COMPATIBLE_IOCTL(STOP_ARRAY_RO) +COMPATIBLE_IOCTL(RESTART_ARRAY_RW) #endif /* CONFIG_MD */ +#ifdef CONFIG_SIBYTE_TBPROF +COMPATIBLE_IOCTL(SBPROF_ZBSTART), +COMPATIBLE_IOCTL(SBPROF_ZBSTOP), +COMPATIBLE_IOCTL(SBPROF_ZBWAITFULL), +#endif /* CONFIG_SIBYTE_TBPROF */ + #if defined(CONFIG_BLK_DEV_DM) || defined(CONFIG_BLK_DEV_DM_MODULE) IOCTL32_DEFAULT(DM_VERSION), IOCTL32_DEFAULT(DM_REMOVE_ALL), @@ -800,25 +1167,44 @@ IOCTL32_DEFAULT(DM_TARGET_WAIT), #endif /* CONFIG_BLK_DEV_DM */ - IOCTL32_DEFAULT(MTIOCTOP), /* mtio.h ioctls */ - IOCTL32_HANDLER(MTIOCGET32, mt_ioctl_trans), - IOCTL32_HANDLER(MTIOCPOS32, mt_ioctl_trans), - IOCTL32_HANDLER(MTIOCGETCONFIG32, mt_ioctl_trans), - IOCTL32_HANDLER(MTIOCSETCONFIG32, mt_ioctl_trans), - // MTIOCRDFTSEG - // MTIOCWRFTSEG - // MTIOCVOLINFO - // MTIOCGETSIZE - // MTIOCFTFORMAT - // MTIOCFTCMD - - IOCTL32_DEFAULT(AUTOFS_IOC_READY), /* auto_fs.h ioctls */ - IOCTL32_DEFAULT(AUTOFS_IOC_FAIL), - IOCTL32_DEFAULT(AUTOFS_IOC_CATATONIC), - IOCTL32_DEFAULT(AUTOFS_IOC_PROTOVER), - IOCTL32_HANDLER(AUTOFS_IOC_SETTIMEOUT32, ioc_settimeout), - IOCTL32_DEFAULT(AUTOFS_IOC_EXPIRE) -}; +COMPATIBLE_IOCTL(MTIOCTOP) /* mtio.h ioctls */ +HANDLE_IOCTL(MTIOCGET32, mt_ioctl_trans) +HANDLE_IOCTL(MTIOCPOS32, mt_ioctl_trans) +HANDLE_IOCTL(MTIOCGETCONFIG32, mt_ioctl_trans) +HANDLE_IOCTL(MTIOCSETCONFIG32, mt_ioctl_trans) +// MTIOCRDFTSEG +// MTIOCWRFTSEG +// MTIOCVOLINFO +// MTIOCGETSIZE +// MTIOCFTFORMAT +// MTIOCFTCMD + +COMPATIBLE_IOCTL(AUTOFS_IOC_READY) /* auto_fs.h ioctls */ +COMPATIBLE_IOCTL(AUTOFS_IOC_FAIL) +COMPATIBLE_IOCTL(AUTOFS_IOC_CATATONIC) +COMPATIBLE_IOCTL(AUTOFS_IOC_PROTOVER) +HANDLE_IOCTL(AUTOFS_IOC_SETTIMEOUT32, ioc_settimeout) +COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE) +COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE_MULTI) + +/* Little p (/dev/rtc, /dev/envctrl, etc.) */ +COMPATIBLE_IOCTL(_IOR('p', 20, int[7])) /* RTCGET */ +COMPATIBLE_IOCTL(_IOW('p', 21, int[7])) /* RTCSET */ +COMPATIBLE_IOCTL(RTC_AIE_ON) +COMPATIBLE_IOCTL(RTC_AIE_OFF) +COMPATIBLE_IOCTL(RTC_UIE_ON) +COMPATIBLE_IOCTL(RTC_UIE_OFF) +COMPATIBLE_IOCTL(RTC_PIE_ON) +COMPATIBLE_IOCTL(RTC_PIE_OFF) +COMPATIBLE_IOCTL(RTC_WIE_ON) +COMPATIBLE_IOCTL(RTC_WIE_OFF) +COMPATIBLE_IOCTL(RTC_ALM_SET) +COMPATIBLE_IOCTL(RTC_ALM_READ) +COMPATIBLE_IOCTL(RTC_RD_TIME) +COMPATIBLE_IOCTL(RTC_SET_TIME) +COMPATIBLE_IOCTL(RTC_WKALM_SET) +COMPATIBLE_IOCTL(RTC_WKALM_RD) +IOCTL_TABLE_END -#define NR_IOCTL32_HANDLERS (sizeof(ioctl32_handler_table) / \ - sizeof(ioctl32_handler_table[0])) +#define NR_IOCTL_TRANS (sizeof(ioctl_translations) / \ + sizeof(ioctl_translations[0])) diff -Nru a/arch/mips64/kernel/irq.c b/arch/mips64/kernel/irq.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips64/kernel/irq.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,984 @@ +/* + * 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. + * + * Code to handle x86 style IRQs plus some generic interrupt stuff. + * + * Copyright (C) 1992 Linus Torvalds + * Copyright (C) 1994 - 2000 Ralf Baechle + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* + * Controller mappings for all interrupt sources: + */ +irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = { + [0 ... NR_IRQS-1] = { + .handler = &no_irq_type, + .lock = SPIN_LOCK_UNLOCKED + } +}; + +static void register_irq_proc (unsigned int irq); + +/* + * Special irq handlers. + */ + +irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs) +{ return IRQ_NONE; } + +/* + * Generic no controller code + */ + +static void enable_none(unsigned int irq) { } +static unsigned int startup_none(unsigned int irq) { return 0; } +static void disable_none(unsigned int irq) { } +static void ack_none(unsigned int irq) +{ + /* + * 'what should we do if we get a hw irq event on an illegal vector'. + * each architecture has to answer this themselves, it doesn't deserve + * a generic callback i think. + */ + printk("unexpected interrupt %d\n", irq); +} + +/* startup is the same as "enable", shutdown is same as "disable" */ +#define shutdown_none disable_none +#define end_none enable_none + +struct hw_interrupt_type no_irq_type = { + "none", + startup_none, + shutdown_none, + enable_none, + disable_none, + ack_none, + end_none +}; + +atomic_t irq_err_count; + +/* + * Generic, controller-independent functions: + */ + +int show_interrupts(struct seq_file *p, void *v) +{ + int i, j; + struct irqaction * action; + unsigned long flags; + + seq_printf(p, " "); + for (j=0; jtypename); + seq_printf(p, " %s", action->name); + + for (action=action->next; action; action = action->next) + seq_printf(p, ", %s", action->name); + + seq_putc(p, '\n'); +skip: + spin_unlock_irqrestore(&irq_desc[i].lock, flags); + } + seq_putc(p, '\n'); + seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count)); + + return 0; +} + +#ifdef CONFIG_SMP +inline void synchronize_irq(unsigned int irq) +{ + while (irq_desc[irq].status & IRQ_INPROGRESS) + cpu_relax(); +} +#endif + +/* + * This should really return information about whether + * we should do bottom half handling etc. Right now we + * end up _always_ checking the bottom half, which is a + * waste of time and is not what some drivers would + * prefer. + */ +int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action) +{ + int status = 1; /* Force the "do bottom halves" bit */ + int retval = 0; + + if (!(action->flags & SA_INTERRUPT)) + local_irq_enable(); + + do { + status |= action->flags; + retval |= action->handler(irq, action->dev_id, regs); + action = action->next; + } while (action); + if (status & SA_SAMPLE_RANDOM) + add_interrupt_randomness(irq); + local_irq_disable(); + + return retval; +} + +static void __report_bad_irq(int irq, irq_desc_t *desc, irqreturn_t action_ret) +{ + struct irqaction *action; + + if (action_ret != IRQ_HANDLED && action_ret != IRQ_NONE) { + printk(KERN_ERR "irq event %d: bogus return value %x\n", + irq, action_ret); + } else { + printk(KERN_ERR "irq %d: nobody cared!\n", irq); + } + dump_stack(); + printk(KERN_ERR "handlers:\n"); + action = desc->action; + do { + printk(KERN_ERR "[<%p>]", action->handler); + print_symbol(" (%s)", + (unsigned long)action->handler); + printk("\n"); + action = action->next; + } while (action); +} + +static void report_bad_irq(int irq, irq_desc_t *desc, irqreturn_t action_ret) +{ + static int count = 100; + + if (count) { + count--; + __report_bad_irq(irq, desc, action_ret); + } +} + +static int noirqdebug; + +static int __init noirqdebug_setup(char *str) +{ + noirqdebug = 1; + printk("IRQ lockup detection disabled\n"); + return 1; +} + +__setup("noirqdebug", noirqdebug_setup); + +/* + * If 99,900 of the previous 100,000 interrupts have not been handled then + * assume that the IRQ is stuck in some manner. Drop a diagnostic and try to + * turn the IRQ off. + * + * (The other 100-of-100,000 interrupts may have been a correctly-functioning + * device sharing an IRQ with the failing one) + * + * Called under desc->lock + */ +static void note_interrupt(int irq, irq_desc_t *desc, irqreturn_t action_ret) +{ + if (action_ret != IRQ_HANDLED) { + desc->irqs_unhandled++; + if (action_ret != IRQ_NONE) + report_bad_irq(irq, desc, action_ret); + } + + desc->irq_count++; + if (desc->irq_count < 100000) + return; + + desc->irq_count = 0; + if (desc->irqs_unhandled > 99900) { + /* + * The interrupt is stuck + */ + __report_bad_irq(irq, desc, action_ret); + /* + * Now kill the IRQ + */ + printk(KERN_EMERG "Disabling IRQ #%d\n", irq); + desc->status |= IRQ_DISABLED; + desc->handler->disable(irq); + } + desc->irqs_unhandled = 0; +} + +/* + * Generic enable/disable code: this just calls + * down into the PIC-specific version for the actual + * hardware disable after having gotten the irq + * controller lock. + */ + +/** + * disable_irq_nosync - disable an irq without waiting + * @irq: Interrupt to disable + * + * Disable the selected interrupt line. Disables of an interrupt + * stack. Unlike disable_irq(), this function does not ensure existing + * instances of the IRQ handler have completed before returning. + * + * This function may be called from IRQ context. + */ + +void inline disable_irq_nosync(unsigned int irq) +{ + irq_desc_t *desc = irq_desc + irq; + unsigned long flags; + + spin_lock_irqsave(&desc->lock, flags); + if (!desc->depth++) { + desc->status |= IRQ_DISABLED; + desc->handler->disable(irq); + } + spin_unlock_irqrestore(&desc->lock, flags); +} + +/** + * disable_irq - disable an irq and wait for completion + * @irq: Interrupt to disable + * + * Disable the selected interrupt line. Disables of an interrupt + * stack. That is for two disables you need two enables. This + * function waits for any pending IRQ handlers for this interrupt + * to complete before returning. If you use this function while + * holding a resource the IRQ handler may need you will deadlock. + * + * This function may be called - with care - from IRQ context. + */ + +void disable_irq(unsigned int irq) +{ + disable_irq_nosync(irq); + synchronize_irq(irq); +} + +/** + * enable_irq - enable interrupt handling on an irq + * @irq: Interrupt to enable + * + * Re-enables the processing of interrupts on this IRQ line + * providing no disable_irq calls are now in effect. + * + * This function may be called from IRQ context. + */ + +void enable_irq(unsigned int irq) +{ + irq_desc_t *desc = irq_desc + irq; + unsigned long flags; + + spin_lock_irqsave(&desc->lock, flags); + switch (desc->depth) { + case 1: { + unsigned int status = desc->status & ~IRQ_DISABLED; + desc->status = status; + if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) { + desc->status = status | IRQ_REPLAY; + hw_resend_irq(desc->handler,irq); + } + desc->handler->enable(irq); + /* fall-through */ + } + default: + desc->depth--; + break; + case 0: + printk("enable_irq(%u) unbalanced from %p\n", irq, + __builtin_return_address(0)); + } + spin_unlock_irqrestore(&desc->lock, flags); +} + +/* + * do_IRQ handles all normal device IRQ's (the special + * SMP cross-CPU interrupts have their own specific + * handlers). + */ +asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs) +{ + /* + * We ack quickly, we don't want the irq controller + * thinking we're snobs just because some other CPU has + * disabled global interrupts (we have already done the + * INT_ACK cycles, it's too late to try to pretend to the + * controller that we aren't taking the interrupt). + * + * 0 return value means that this irq is already being + * handled by some other CPU. (or is disabled) + */ + int cpu = smp_processor_id(); + irq_desc_t *desc = irq_desc + irq; + struct irqaction * action; + unsigned int status; + + irq_enter(); + kstat_cpu(cpu).irqs[irq]++; + spin_lock(&desc->lock); + desc->handler->ack(irq); + /* + REPLAY is when Linux resends an IRQ that was dropped earlier + WAITING is used by probe to mark irqs that are being tested + */ + status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING); + status |= IRQ_PENDING; /* we _want_ to handle it */ + + /* + * If the IRQ is disabled for whatever reason, we cannot + * use the action we have. + */ + action = NULL; + if (likely(!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))) { + action = desc->action; + status &= ~IRQ_PENDING; /* we commit to handling */ + status |= IRQ_INPROGRESS; /* we are handling it */ + } + desc->status = status; + + /* + * If there is no IRQ handler or it was disabled, exit early. + Since we set PENDING, if another processor is handling + a different instance of this same irq, the other processor + will take care of it. + */ + if (unlikely(!action)) + goto out; + + /* + * Edge triggered interrupts need to remember + * pending events. + * This applies to any hw interrupts that allow a second + * instance of the same irq to arrive while we are in do_IRQ + * or in the handler. But the code here only handles the _second_ + * instance of the irq, not the third or fourth. So it is mostly + * useful for irq hardware that does not mask cleanly in an + * SMP environment. + */ + for (;;) { + irqreturn_t action_ret; + + spin_unlock(&desc->lock); + action_ret = handle_IRQ_event(irq, ®s, action); + spin_lock(&desc->lock); + if (!noirqdebug) + note_interrupt(irq, desc, action_ret); + if (likely(!(desc->status & IRQ_PENDING))) + break; + desc->status &= ~IRQ_PENDING; + } + desc->status &= ~IRQ_INPROGRESS; + +out: + /* + * The ->end() handler has to deal with interrupts which got + * disabled while the handler was running. + */ + desc->handler->end(irq); + spin_unlock(&desc->lock); + + irq_exit(); + + return 1; +} + +/** + * request_irq - allocate an interrupt line + * @irq: Interrupt line to allocate + * @handler: Function to be called when the IRQ occurs + * @irqflags: Interrupt type flags + * @devname: An ascii name for the claiming device + * @dev_id: A cookie passed back to the handler function + * + * This call allocates interrupt resources and enables the + * interrupt line and IRQ handling. From the point this + * call is made your handler function may be invoked. Since + * your handler function must clear any interrupt the board + * raises, you must take care both to initialise your hardware + * and to set up the interrupt handler in the right order. + * + * Dev_id must be globally unique. Normally the address of the + * device data structure is used as the cookie. Since the handler + * receives this value it makes sense to use it. + * + * If your interrupt is shared you must pass a non NULL dev_id + * as this is required when freeing the interrupt. + * + * Flags: + * + * SA_SHIRQ Interrupt is shared + * + * SA_INTERRUPT Disable local interrupts while processing + * + * SA_SAMPLE_RANDOM The interrupt can be used for entropy + * + */ + +int request_irq(unsigned int irq, + irqreturn_t (*handler)(int, void *, struct pt_regs *), + unsigned long irqflags, + const char * devname, + void *dev_id) +{ + int retval; + struct irqaction * action; + +#if 1 + /* + * Sanity-check: shared interrupts should REALLY pass in + * a real dev-ID, otherwise we'll have trouble later trying + * to figure out which interrupt is which (messes up the + * interrupt freeing logic etc). + */ + if (irqflags & SA_SHIRQ) { + if (!dev_id) + printk("Bad boy: %s (at 0x%x) called us without a dev_id!\n", devname, (&irq)[-1]); + } +#endif + + if (irq >= NR_IRQS) + return -EINVAL; + if (!handler) + return -EINVAL; + + action = (struct irqaction *) + kmalloc(sizeof(struct irqaction), GFP_ATOMIC); + if (!action) + return -ENOMEM; + + action->handler = handler; + action->flags = irqflags; + action->mask = 0; + action->name = devname; + action->next = NULL; + action->dev_id = dev_id; + + retval = setup_irq(irq, action); + if (retval) + kfree(action); + return retval; +} + +/** + * free_irq - free an interrupt + * @irq: Interrupt line to free + * @dev_id: Device identity to free + * + * Remove an interrupt handler. The handler is removed and if the + * interrupt line is no longer in use by any driver it is disabled. + * On a shared IRQ the caller must ensure the interrupt is disabled + * on the card it drives before calling this function. The function + * does not return until any executing interrupts for this IRQ + * have completed. + * + * This function must not be called from interrupt context. + */ + +void free_irq(unsigned int irq, void *dev_id) +{ + irq_desc_t *desc; + struct irqaction **p; + unsigned long flags; + + if (irq >= NR_IRQS) + return; + + desc = irq_desc + irq; + spin_lock_irqsave(&desc->lock,flags); + p = &desc->action; + for (;;) { + struct irqaction * action = *p; + if (action) { + struct irqaction **pp = p; + p = &action->next; + if (action->dev_id != dev_id) + continue; + + /* Found it - now remove it from the list of entries */ + *pp = action->next; + if (!desc->action) { + desc->status |= IRQ_DISABLED; + desc->handler->shutdown(irq); + } + spin_unlock_irqrestore(&desc->lock,flags); + + /* Wait to make sure it's not being used on another CPU */ + synchronize_irq(irq); + kfree(action); + return; + } + printk("Trying to free free IRQ%d\n",irq); + spin_unlock_irqrestore(&desc->lock,flags); + return; + } +} + +/* + * IRQ autodetection code.. + * + * This depends on the fact that any interrupt that + * comes in on to an unassigned handler will get stuck + * with "IRQ_WAITING" cleared and the interrupt + * disabled. + */ + +static DECLARE_MUTEX(probe_sem); + +/** + * probe_irq_on - begin an interrupt autodetect + * + * Commence probing for an interrupt. The interrupts are scanned + * and a mask of potential interrupt lines is returned. + * + */ + +unsigned long probe_irq_on(void) +{ + unsigned int i; + irq_desc_t *desc; + unsigned long val; + unsigned long delay; + + down(&probe_sem); + /* + * something may have generated an irq long ago and we want to + * flush such a longstanding irq before considering it as spurious. + */ + for (i = NR_IRQS-1; i > 0; i--) { + desc = irq_desc + i; + + spin_lock_irq(&desc->lock); + if (!irq_desc[i].action) + irq_desc[i].handler->startup(i); + spin_unlock_irq(&desc->lock); + } + + /* Wait for longstanding interrupts to trigger. */ + for (delay = jiffies + HZ/50; time_after(delay, jiffies); ) + /* about 20ms delay */ barrier(); + + /* + * enable any unassigned irqs + * (we must startup again here because if a longstanding irq + * happened in the previous stage, it may have masked itself) + */ + for (i = NR_IRQS-1; i > 0; i--) { + desc = irq_desc + i; + + spin_lock_irq(&desc->lock); + if (!desc->action) { + desc->status |= IRQ_AUTODETECT | IRQ_WAITING; + if (desc->handler->startup(i)) + desc->status |= IRQ_PENDING; + } + spin_unlock_irq(&desc->lock); + } + + /* + * Wait for spurious interrupts to trigger + */ + for (delay = jiffies + HZ/10; time_after(delay, jiffies); ) + /* about 100ms delay */ barrier(); + + /* + * Now filter out any obviously spurious interrupts + */ + val = 0; + for (i = 0; i < NR_IRQS; i++) { + irq_desc_t *desc = irq_desc + i; + unsigned int status; + + spin_lock_irq(&desc->lock); + status = desc->status; + + if (status & IRQ_AUTODETECT) { + /* It triggered already - consider it spurious. */ + if (!(status & IRQ_WAITING)) { + desc->status = status & ~IRQ_AUTODETECT; + desc->handler->shutdown(i); + } else + if (i < 32) + val |= 1 << i; + } + spin_unlock_irq(&desc->lock); + } + + return val; +} + +/* + * Return a mask of triggered interrupts (this + * can handle only legacy ISA interrupts). + */ + +/** + * probe_irq_mask - scan a bitmap of interrupt lines + * @val: mask of interrupts to consider + * + * Scan the ISA bus interrupt lines and return a bitmap of + * active interrupts. The interrupt probe logic state is then + * returned to its previous value. + * + * Note: we need to scan all the irq's even though we will + * only return ISA irq numbers - just so that we reset them + * all to a known state. + */ +unsigned int probe_irq_mask(unsigned long val) +{ + int i; + unsigned int mask; + + mask = 0; + for (i = 0; i < NR_IRQS; i++) { + irq_desc_t *desc = irq_desc + i; + unsigned int status; + + spin_lock_irq(&desc->lock); + status = desc->status; + + if (status & IRQ_AUTODETECT) { + if (i < 16 && !(status & IRQ_WAITING)) + mask |= 1 << i; + + desc->status = status & ~IRQ_AUTODETECT; + desc->handler->shutdown(i); + } + spin_unlock_irq(&desc->lock); + } + up(&probe_sem); + + return mask & val; +} + +/* + * Return the one interrupt that triggered (this can + * handle any interrupt source). + */ + +/** + * probe_irq_off - end an interrupt autodetect + * @val: mask of potential interrupts (unused) + * + * Scans the unused interrupt lines and returns the line which + * appears to have triggered the interrupt. If no interrupt was + * found then zero is returned. If more than one interrupt is + * found then minus the first candidate is returned to indicate + * their is doubt. + * + * The interrupt probe logic state is returned to its previous + * value. + * + * BUGS: When used in a module (which arguably shouldnt happen) + * nothing prevents two IRQ probe callers from overlapping. The + * results of this are non-optimal. + */ + +int probe_irq_off(unsigned long val) +{ + int i, irq_found, nr_irqs; + + nr_irqs = 0; + irq_found = 0; + for (i = 0; i < NR_IRQS; i++) { + irq_desc_t *desc = irq_desc + i; + unsigned int status; + + spin_lock_irq(&desc->lock); + status = desc->status; + + if (status & IRQ_AUTODETECT) { + if (!(status & IRQ_WAITING)) { + if (!nr_irqs) + irq_found = i; + nr_irqs++; + } + desc->status = status & ~IRQ_AUTODETECT; + desc->handler->shutdown(i); + } + spin_unlock_irq(&desc->lock); + } + up(&probe_sem); + + if (nr_irqs > 1) + irq_found = -irq_found; + return irq_found; +} + +/* this was setup_x86_irq but it seems pretty generic */ +int setup_irq(unsigned int irq, struct irqaction * new) +{ + int shared = 0; + unsigned long flags; + struct irqaction *old, **p; + irq_desc_t *desc = irq_desc + irq; + + /* + * Some drivers like serial.c use request_irq() heavily, + * so we have to be careful not to interfere with a + * running system. + */ + if (new->flags & SA_SAMPLE_RANDOM) { + /* + * This function might sleep, we want to call it first, + * outside of the atomic block. + * Yes, this might clear the entropy pool if the wrong + * driver is attempted to be loaded, without actually + * installing a new handler, but is this really a problem, + * only the sysadmin is able to do this. + */ + rand_initialize_irq(irq); + } + + /* + * The following block of code has to be executed atomically + */ + spin_lock_irqsave(&desc->lock,flags); + p = &desc->action; + if ((old = *p) != NULL) { + /* Can't share interrupts unless both agree to */ + if (!(old->flags & new->flags & SA_SHIRQ)) { + spin_unlock_irqrestore(&desc->lock,flags); + return -EBUSY; + } + + /* add new interrupt at end of irq queue */ + do { + p = &old->next; + old = *p; + } while (old); + shared = 1; + } + + *p = new; + + if (!shared) { + desc->depth = 0; + desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS); + desc->handler->startup(irq); + } + spin_unlock_irqrestore(&desc->lock,flags); + + register_irq_proc(irq); + return 0; +} + +void __init init_generic_irq(void) +{ + int i; + + for (i = 0; i < NR_IRQS; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = NULL; + irq_desc[i].depth = 1; + irq_desc[i].handler = &no_irq_type; + } +} + +EXPORT_SYMBOL(disable_irq_nosync); +EXPORT_SYMBOL(disable_irq); +EXPORT_SYMBOL(enable_irq); +EXPORT_SYMBOL(probe_irq_mask); + +static struct proc_dir_entry * root_irq_dir; +static struct proc_dir_entry * irq_dir [NR_IRQS]; + +#define HEX_DIGITS 8 + +static unsigned int parse_hex_value (const char *buffer, + unsigned long count, unsigned long *ret) +{ + unsigned char hexnum [HEX_DIGITS]; + unsigned long value; + int i; + + if (!count) + return -EINVAL; + if (count > HEX_DIGITS) + count = HEX_DIGITS; + if (copy_from_user(hexnum, buffer, count)) + return -EFAULT; + + /* + * Parse the first 8 characters as a hex string, any non-hex char + * is end-of-string. '00e1', 'e1', '00E1', 'E1' are all the same. + */ + value = 0; + + for (i = 0; i < count; i++) { + unsigned int c = hexnum[i]; + + switch (c) { + case '0' ... '9': c -= '0'; break; + case 'a' ... 'f': c -= 'a'-10; break; + case 'A' ... 'F': c -= 'A'-10; break; + default: + goto out; + } + value = (value << 4) | c; + } +out: + *ret = value; + return 0; +} + +#ifdef CONFIG_SMP + +static struct proc_dir_entry * smp_affinity_entry [NR_IRQS]; + +static unsigned long irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL }; +static int irq_affinity_read_proc (char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + if (count < HEX_DIGITS+1) + return -EINVAL; + return sprintf (page, "%08lx\n", irq_affinity[(long)data]); +} + +static int irq_affinity_write_proc (struct file *file, const char *buffer, + unsigned long count, void *data) +{ + int irq = (long) data, full_count = count, err; + unsigned long new_value; + + if (!irq_desc[irq].handler->set_affinity) + return -EIO; + + err = parse_hex_value(buffer, count, &new_value); + + /* + * Do not allow disabling IRQs completely - it's a too easy + * way to make the system unusable accidentally :-) At least + * one online CPU still has to be targeted. + */ + if (!(new_value & cpu_online_map)) + return -EINVAL; + + irq_affinity[irq] = new_value; + irq_desc[irq].handler->set_affinity(irq, new_value); + + return full_count; +} + +#endif + +static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + unsigned long *mask = (unsigned long *) data; + if (count < HEX_DIGITS+1) + return -EINVAL; + return sprintf (page, "%08lx\n", *mask); +} + +static int prof_cpu_mask_write_proc (struct file *file, const char *buffer, + unsigned long count, void *data) +{ + unsigned long *mask = (unsigned long *) data, full_count = count, err; + unsigned long new_value; + + err = parse_hex_value(buffer, count, &new_value); + if (err) + return err; + + *mask = new_value; + return full_count; +} + +#define MAX_NAMELEN 10 + +static void register_irq_proc (unsigned int irq) +{ + char name [MAX_NAMELEN]; + + if (!root_irq_dir || (irq_desc[irq].handler == &no_irq_type) || + irq_dir[irq]) + return; + + memset(name, 0, MAX_NAMELEN); + sprintf(name, "%d", irq); + + /* create /proc/irq/1234 */ + irq_dir[irq] = proc_mkdir(name, root_irq_dir); + +#ifdef CONFIG_SMP + { + struct proc_dir_entry *entry; + + /* create /proc/irq/1234/smp_affinity */ + entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]); + + if (entry) { + entry->nlink = 1; + entry->data = (void *)(long)irq; + entry->read_proc = irq_affinity_read_proc; + entry->write_proc = irq_affinity_write_proc; + } + + smp_affinity_entry[irq] = entry; + } +#endif +} + +unsigned long prof_cpu_mask = -1; + +void init_irq_proc (void) +{ + struct proc_dir_entry *entry; + int i; + + /* create /proc/irq */ + root_irq_dir = proc_mkdir("irq", 0); + + /* create /proc/irq/prof_cpu_mask */ + entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir); + + if (!entry) + return; + + entry->nlink = 1; + entry->data = (void *)&prof_cpu_mask; + entry->read_proc = prof_cpu_mask_read_proc; + entry->write_proc = prof_cpu_mask_write_proc; + + /* + * Create entries for all existing IRQs. + */ + for (i = 0; i < NR_IRQS; i++) + register_irq_proc(i); +} diff -Nru a/arch/mips64/kernel/irq_cpu.c b/arch/mips64/kernel/irq_cpu.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips64/kernel/irq_cpu.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,116 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * Copyright (C) 2001 Ralf Baechle + * + * This file define the irq handler for MIPS CPU interrupts. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +/* + * Almost all MIPS CPUs define 8 interrupt sources. They are typically + * level triggered (i.e., cannot be cleared from CPU; must be cleared from + * device). The first two are software interrupts which we don't really + * use or support. The last one is usually cpu timer interrupt if a counter + * register is present. + * + * Don't even think about using this on SMP. You have been warned. + * + * This file exports one global function: + * mips_cpu_irq_init(u32 irq_base); + */ +#include +#include +#include + +#include +#include + +static int mips_cpu_irq_base; + +static inline void unmask_mips_irq(unsigned int irq) +{ + clear_c0_cause(0x100 << (irq - mips_cpu_irq_base)); + set_c0_status(0x100 << (irq - mips_cpu_irq_base)); +} + +static inline void mask_mips_irq(unsigned int irq) +{ + clear_c0_status(0x100 << (irq - mips_cpu_irq_base)); +} + +static inline void mips_cpu_irq_enable(unsigned int irq) +{ + unsigned long flags; + + local_irq_save(flags); + unmask_mips_irq(irq); + local_irq_restore(flags); +} + +static void mips_cpu_irq_disable(unsigned int irq) +{ + unsigned long flags; + + local_irq_save(flags); + mask_mips_irq(irq); + local_irq_restore(flags); +} + +static unsigned int mips_cpu_irq_startup(unsigned int irq) +{ + mips_cpu_irq_enable(irq); + + return 0; +} + +#define mips_cpu_irq_shutdown mips_cpu_irq_disable + +/* + * While we ack the interrupt interrupts are disabled and thus we don't need + * to deal with concurrency issues. Same for mips_cpu_irq_end. + */ +static void mips_cpu_irq_ack(unsigned int irq) +{ + /* Only necessary for soft interrupts */ + clear_c0_cause(1 << (irq - mips_cpu_irq_base + 8)); + + mask_mips_irq(irq); +} + +static void mips_cpu_irq_end(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + unmask_mips_irq(irq); +} + +static hw_irq_controller mips_cpu_irq_controller = { + "CPU_irq", + mips_cpu_irq_startup, + mips_cpu_irq_shutdown, + mips_cpu_irq_enable, + mips_cpu_irq_disable, + mips_cpu_irq_ack, + mips_cpu_irq_end, + NULL /* no affinity stuff for UP */ +}; + + +void mips_cpu_irq_init(u32 irq_base) +{ + u32 i; + + for (i = irq_base; i < irq_base + 8; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = NULL; + irq_desc[i].depth = 1; + irq_desc[i].handler = &mips_cpu_irq_controller; + } + + mips_cpu_irq_base = irq_base; +} diff -Nru a/arch/mips64/kernel/linux32.c b/arch/mips64/kernel/linux32.c --- a/arch/mips64/kernel/linux32.c Tue Jul 1 18:44:36 2003 +++ b/arch/mips64/kernel/linux32.c Tue Jul 1 18:44:36 2003 @@ -1,10 +1,11 @@ -/* +/* * Conversion between 32-bit and 64-bit native system calls. * * Copyright (C) 2000 Silicon Graphics, Inc. * Written by Ulf Carlsson (ulfc@engr.sgi.com) * sys32_execve from ia64/ia32 code, Feb 2000, Kanoj Sarcar (kanoj@sgi.com) */ +#include #include #include #include @@ -14,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -21,29 +23,52 @@ #include #include #include +#include #include +#include #include #include #include #include +#include +#include +#include #include #include + #include +#include +#include #include +#include #include -#include - +/* Use this to get at 32-bit user passed pointers. */ +/* A() macro should be used for places where you e.g. + have some internal variable u32 and just want to get + rid of a compiler warning. AA() has to be used in + places where you want to convert a function argument + to 32bit pointer or when you e.g. access pt_regs + structure and want to consider 32bit registers only. + */ #define A(__x) ((unsigned long)(__x)) +#define AA(__x) ((unsigned long)((int)__x)) + +#ifdef __MIPSEB__ +#define merge_64(r1,r2) ((((r1) & 0xffffffffUL) << 32) + ((r2) & 0xffffffffUL)) +#endif +#ifdef __MIPSEL__ +#define merge_64(r1,r2) ((((r2) & 0xffffffffUL) << 32) + ((r1) & 0xffffffffUL)) +#endif /* * Revalidate the inode. This is required for proper NFS attribute caching. */ -static int cp_new_stat32(struct kstat *stat, struct stat32 *statbuf) +int cp_compat_stat(struct kstat *stat, struct compat_stat *statbuf) { - struct stat32 tmp; + struct compat_stat tmp; memset(&tmp, 0, sizeof(tmp)); tmp.st_dev = stat->dev; @@ -54,48 +79,45 @@ SET_STAT_GID(tmp, stat->gid); tmp.st_rdev = stat->rdev; tmp.st_size = stat->size; - tmp.st_atime = stat->atime; - tmp.st_mtime = stat->mtime; - tmp.st_ctime = stat->ctime; + tmp.st_atime = stat->atime.tv_sec; + tmp.st_mtime = stat->mtime.tv_sec; + tmp.st_ctime = stat->ctime.tv_sec; +#ifdef STAT_HAVE_NSEC + tmp.st_atime_nsec = stat->atime.tv_nsec; + tmp.st_mtime_nsec = stat->mtime.tv_nsec; + tmp.st_ctime_nsec = stat->ctime.tv_nsec; +#endif tmp.st_blocks = stat->blocks; tmp.st_blksize = stat->blksize; return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; } -asmlinkage int sys32_newstat(char * filename, struct stat32 *statbuf) -{ - struct kstat stat; - int error = vfs_stat(filename, &stat); - - if (!error) - error = cp_new_stat32(&stat, statbuf); - - return error; -} - -asmlinkage int sys32_newlstat(char * filename, struct stat32 *statbuf) -{ - struct kstat stat; - int error = vfs_lstat(filename, &stat); - - if (!error) - error = cp_new_stat32(&stat, statbuf); - - return error; -} - -asmlinkage long sys32_newfstat(unsigned int fd, struct stat32 * statbuf) -{ - struct kstat stat; - int error = vfs_fstat(fd, &stat); +asmlinkage unsigned long +sys32_mmap2(unsigned long addr, size_t len, unsigned long prot, + unsigned long flags, unsigned long fd, unsigned long pgoff) +{ + struct file * file = NULL; + unsigned long error; + + error = -EINVAL; + if (!(flags & MAP_ANONYMOUS)) { + error = -EBADF; + file = fget(fd); + if (!file) + goto out; + } + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!error) - error = cp_new_stat32(&stat, statbuf); + down_write(¤t->mm->mmap_sem); + error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); + up_write(¤t->mm->mmap_sem); + if (file) + fput(file); +out: return error; } -asmlinkage int sys_mmap2(void) {return 0;} asmlinkage long sys_truncate(const char * path, unsigned long length); @@ -117,7 +139,6 @@ return sys_ftruncate(fd, ((long) high << 32) | low); } -#if 0 /* * count32() counts the number of arguments/envelopes */ @@ -127,15 +148,15 @@ if (argv != NULL) { for (;;) { - u32 p; - /* egcs is stupid */ - if (!access_ok(VERIFY_READ, argv, sizeof (u32))) - return -EFAULT; - __get_user(p,argv); + u32 p; int error; + + error = get_user(p,argv); + if (error) + return error; if (!p) break; argv++; - if(++i > max) + if (++i > max) return -E2BIG; } } @@ -148,7 +169,7 @@ * memory to free pages in kernel mem. These are in a format ready * to be put directly into the top of new user memory. */ -int copy_strings32(int argc, u32 * argv, struct linux_binprm *bprm) +int copy_strings32(int argc, u32 * argv, struct linux_binprm *bprm) { while (argc-- > 0) { u32 str; @@ -156,13 +177,13 @@ unsigned long pos; if (get_user(str, argv+argc) || !str || - !(len = strnlen_user((char *)A(str), bprm->p))) + !(len = strnlen_user((char *)A(str), bprm->p))) return -EFAULT; - if (bprm->p < len) - return -E2BIG; + if (bprm->p < len) + return -E2BIG; bprm->p -= len; - /* XXX: add architecture specific overflow check here. */ + /* XXX: add architecture specific overflow check here. */ pos = bprm->p; while (len > 0) { @@ -199,7 +220,7 @@ kunmap(page); if (err) - return -EFAULT; + return -EFAULT; pos += bytes_to_copy; str += bytes_to_copy; @@ -209,73 +230,95 @@ return 0; } - /* - * sys_execve32() executes a new program. + * sys32_execve() executes a new program. */ -int do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs) +static inline int +do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs) { struct linux_binprm bprm; - struct dentry * dentry; + struct file * file; int retval; int i; - bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); - memset(bprm.page, 0, MAX_ARG_PAGES*sizeof(bprm.page[0])); + file = open_exec(filename); - dentry = open_namei(filename, 0, 0); - retval = PTR_ERR(dentry); - if (IS_ERR(dentry)) + retval = PTR_ERR(file); + if (IS_ERR(file)) return retval; - bprm.dentry = dentry; + bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); + memset(bprm.page, 0, MAX_ARG_PAGES * sizeof(bprm.page[0])); + + bprm.file = file; bprm.filename = filename; bprm.sh_bang = 0; bprm.loader = 0; bprm.exec = 0; - if ((bprm.argc = count32(argv, bprm.p / sizeof(u32))) < 0) { - dput(dentry); - return bprm.argc; - } + bprm.security = NULL; + bprm.mm = mm_alloc(); + retval = -ENOMEM; + if (!bprm.mm) + goto out_file; + + retval = init_new_context(current, bprm.mm); + if (retval < 0) + goto out_mm; + + bprm.argc = count32(argv, bprm.p / sizeof(u32)); + if ((retval = bprm.argc) < 0) + goto out_mm; + + bprm.envc = count32(envp, bprm.p / sizeof(u32)); + if ((retval = bprm.envc) < 0) + goto out_mm; - if ((bprm.envc = count32(envp, bprm.p / sizeof(u32))) < 0) { - dput(dentry); - return bprm.envc; - } + if ((retval = security_bprm_alloc(&bprm))) + goto out; retval = prepare_binprm(&bprm); - if (retval < 0) - goto out; - + if (retval < 0) + goto out; + retval = copy_strings_kernel(1, &bprm.filename, &bprm); - if (retval < 0) - goto out; + if (retval < 0) + goto out; bprm.exec = bprm.p; retval = copy_strings32(bprm.envc, envp, &bprm); - if (retval < 0) - goto out; + if (retval < 0) + goto out; retval = copy_strings32(bprm.argc, argv, &bprm); - if (retval < 0) - goto out; + if (retval < 0) + goto out; - retval = search_binary_handler(&bprm,regs); - if (retval >= 0) + retval = search_binary_handler(&bprm, regs); + if (retval >= 0) { /* execve success */ + security_bprm_free(&bprm); return retval; + } out: /* Something went wrong, return the inode and free the argument pages*/ - if (bprm.dentry) - dput(bprm.dentry); - - /* Assumes that free_page() can take a NULL argument. */ - /* I hope this is ok for all architectures */ - for (i = 0 ; i < MAX_ARG_PAGES ; i++) - if (bprm.page[i]) - __free_page(bprm.page[i]); - + for (i = 0 ; i < MAX_ARG_PAGES ; i++) { + struct page * page = bprm.page[i]; + if (page) + __free_page(page); + } + + if (bprm.security) + security_bprm_free(&bprm); + +out_mm: + mmdrop(bprm.mm); + +out_file: + if (bprm.file) { + allow_write_access(bprm.file); + fput(bprm.file); + } return retval; } @@ -299,84 +342,6 @@ out: return error; } -#else -static int -nargs(unsigned int arg, char **ap) -{ - char *ptr; - int n, ret; - - n = 0; - do { - /* egcs is stupid */ - if (!access_ok(VERIFY_READ, arg, sizeof (unsigned int))) - return -EFAULT; - if (IS_ERR(ret = __get_user((long)ptr,(int *)A(arg)))) - return ret; - if (ap) /* no access_ok needed, we allocated */ - if (IS_ERR(ret = __put_user(ptr, ap++))) - return ret; - arg += sizeof(unsigned int); - n++; - } while (ptr); - return(n - 1); -} - -asmlinkage int -sys32_execve(abi64_no_regargs, struct pt_regs regs) -{ - extern asmlinkage int sys_execve(abi64_no_regargs, struct pt_regs regs); - extern asmlinkage long sys_munmap(unsigned long addr, size_t len); - unsigned int argv = (unsigned int)regs.regs[5]; - unsigned int envp = (unsigned int)regs.regs[6]; - char **av, **ae; - int na, ne, r, len; - char * filename; - - na = nargs(argv, NULL); - if (IS_ERR(na)) - return(na); - ne = nargs(envp, NULL); - if (IS_ERR(ne)) - return(ne); - len = (na + ne + 2) * sizeof(*av); - /* - * kmalloc won't work because the `sys_exec' code will attempt - * to do a `get_user' on the arg list and `get_user' will fail - * on a kernel address (simplifies `get_user'). Instead we - * do an mmap to get a user address. Note that since a successful - * `execve' frees all current memory we only have to do an - * `munmap' if the `execve' failes. - */ - down_write(¤t->mm->mmap_sem); - av = (char **) do_mmap_pgoff(0, 0, len, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, 0); - up_write(¤t->mm->mmap_sem); - - if (IS_ERR(av)) - return (long) av; - ae = av + na + 1; - if (IS_ERR(r = __put_user(0, (av + na)))) - goto out; - if (IS_ERR(r = __put_user(0, (ae + ne)))) - goto out; - if (IS_ERR(r = nargs(argv, av))) - goto out; - if (IS_ERR(r = nargs(envp, ae))) - goto out; - filename = getname((char *) (long)regs.regs[4]); - r = PTR_ERR(filename); - if (IS_ERR(filename)) - goto out; - - r = do_execve(filename, av, ae, ®s); - putname(filename); - if (IS_ERR(r)) -out: - sys_munmap((unsigned long)av, len); - return(r); -} -#endif struct dirent32 { unsigned int d_ino; @@ -446,8 +411,8 @@ int ru_nswap; int ru_inblock; int ru_oublock; - int ru_msgsnd; - int ru_msgrcv; + int ru_msgsnd; + int ru_msgrcv; int ru_nsignals; int ru_nvcsw; int ru_nivcsw; @@ -457,8 +422,11 @@ put_rusage (struct rusage32 *ru, struct rusage *r) { int err; - - err = put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec); + + if (verify_area(VERIFY_WRITE, ru, sizeof *ru)) + return -EFAULT; + + err = __put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec); err |= __put_user (r->ru_utime.tv_usec, &ru->ru_utime.tv_usec); err |= __put_user (r->ru_stime.tv_sec, &ru->ru_stime.tv_sec); err |= __put_user (r->ru_stime.tv_usec, &ru->ru_stime.tv_usec); @@ -476,6 +444,7 @@ err |= __put_user (r->ru_nsignals, &ru->ru_nsignals); err |= __put_user (r->ru_nvcsw, &ru->ru_nvcsw); err |= __put_user (r->ru_nivcsw, &ru->ru_nivcsw); + return err; } @@ -490,8 +459,8 @@ int ret; unsigned int status; mm_segment_t old_fs = get_fs(); - - set_fs(KERNEL_DS); + + set_fs(KERNEL_DS); ret = sys_wait4(pid, stat_addr ? &status : NULL, options, &r); set_fs(old_fs); if (put_rusage (ru, &r)) return -EFAULT; @@ -507,139 +476,90 @@ return sys32_wait4(pid, stat_addr, options, NULL); } -#define RLIM_INFINITY32 0x7fffffff -#define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x) - -struct rlimit32 { - int rlim_cur; - int rlim_max; +struct sysinfo32 { + s32 uptime; + u32 loads[3]; + u32 totalram; + u32 freeram; + u32 sharedram; + u32 bufferram; + u32 totalswap; + u32 freeswap; + u16 procs; + u32 totalhigh; + u32 freehigh; + u32 mem_unit; + char _f[8]; }; -extern asmlinkage int sys_old_getrlimit(unsigned int resource, struct rlimit *rlim); +extern asmlinkage int sys_sysinfo(struct sysinfo *info); -asmlinkage int -sys32_getrlimit(unsigned int resource, struct rlimit32 *rlim) +asmlinkage int sys32_sysinfo(struct sysinfo32 *info) { - struct rlimit r; - int ret; + struct sysinfo s; + int ret, err; mm_segment_t old_fs = get_fs (); set_fs (KERNEL_DS); - ret = sys_old_getrlimit(resource, &r); + ret = sys_sysinfo(&s); set_fs (old_fs); - if (!ret) { - ret = put_user (RESOURCE32(r.rlim_cur), &rlim->rlim_cur); - ret |= __put_user (RESOURCE32(r.rlim_max), &rlim->rlim_max); - } - return ret; -} - -extern asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim); - -asmlinkage int -sys32_setrlimit(unsigned int resource, struct rlimit32 *rlim) -{ - struct rlimit r; - int ret; - mm_segment_t old_fs = get_fs (); - - if (resource >= RLIM_NLIMITS) return -EINVAL; - if (get_user (r.rlim_cur, &rlim->rlim_cur) || - __get_user (r.rlim_max, &rlim->rlim_max)) + err = put_user (s.uptime, &info->uptime); + err |= __put_user (s.loads[0], &info->loads[0]); + err |= __put_user (s.loads[1], &info->loads[1]); + err |= __put_user (s.loads[2], &info->loads[2]); + err |= __put_user (s.totalram, &info->totalram); + err |= __put_user (s.freeram, &info->freeram); + err |= __put_user (s.sharedram, &info->sharedram); + err |= __put_user (s.bufferram, &info->bufferram); + err |= __put_user (s.totalswap, &info->totalswap); + err |= __put_user (s.freeswap, &info->freeswap); + err |= __put_user (s.procs, &info->procs); + err |= __put_user (s.totalhigh, &info->totalhigh); + err |= __put_user (s.freehigh, &info->freehigh); + err |= __put_user (s.mem_unit, &info->mem_unit); + if (err) return -EFAULT; - if (r.rlim_cur == RLIM_INFINITY32) - r.rlim_cur = RLIM_INFINITY; - if (r.rlim_max == RLIM_INFINITY32) - r.rlim_max = RLIM_INFINITY; - set_fs (KERNEL_DS); - ret = sys_setrlimit(resource, &r); - set_fs (old_fs); return ret; } -struct statfs32 { - int f_type; - int f_bsize; - int f_frsize; - int f_blocks; - int f_bfree; - int f_files; - int f_ffree; - int f_bavail; - __kernel_fsid_t32 f_fsid; - int f_namelen; - int f_spare[6]; +#define RLIM_INFINITY32 0x7fffffff +#define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x) + +struct rlimit32 { + int rlim_cur; + int rlim_max; }; -static inline int -put_statfs (struct statfs32 *ubuf, struct statfs *kbuf) +#ifdef __MIPSEB__ +asmlinkage long sys32_truncate64(const char * path, unsigned long __dummy, + int length_hi, int length_lo) +#endif +#ifdef __MIPSEL__ +asmlinkage long sys32_truncate64(const char * path, unsigned long __dummy, + int length_lo, int length_hi) +#endif { - int err; - - err = put_user (kbuf->f_type, &ubuf->f_type); - err |= __put_user (kbuf->f_bsize, &ubuf->f_bsize); - err |= __put_user (kbuf->f_blocks, &ubuf->f_blocks); - err |= __put_user (kbuf->f_bfree, &ubuf->f_bfree); - err |= __put_user (kbuf->f_bavail, &ubuf->f_bavail); - err |= __put_user (kbuf->f_files, &ubuf->f_files); - err |= __put_user (kbuf->f_ffree, &ubuf->f_ffree); - err |= __put_user (kbuf->f_namelen, &ubuf->f_namelen); - err |= __put_user (kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]); - err |= __put_user (kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]); - return err; -} + loff_t length; -extern asmlinkage int sys_statfs(const char * path, struct statfs * buf); + length = ((unsigned long) length_hi << 32) | (unsigned int) length_lo; -asmlinkage int -sys32_statfs(const char * path, struct statfs32 *buf) -{ - int ret; - struct statfs s; - mm_segment_t old_fs = get_fs(); - - set_fs (KERNEL_DS); - ret = sys_statfs((const char *)path, &s); - set_fs (old_fs); - if (put_statfs(buf, &s)) - return -EFAULT; - return ret; + return sys_truncate(path, length); } -extern asmlinkage int sys_fstatfs(unsigned int fd, struct statfs * buf); - -asmlinkage int -sys32_fstatfs(unsigned int fd, struct statfs32 *buf) +#ifdef __MIPSEB__ +asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long __dummy, + int length_hi, int length_lo) +#endif +#ifdef __MIPSEL__ +asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned long __dummy, + int length_lo, int length_hi) +#endif { - int ret; - struct statfs s; - mm_segment_t old_fs = get_fs(); - - set_fs (KERNEL_DS); - ret = sys_fstatfs(fd, &s); - set_fs (old_fs); - if (put_statfs(buf, &s)) - return -EFAULT; - return ret; -} - -extern asmlinkage int -sys_getrusage(int who, struct rusage *ru); + loff_t length; -asmlinkage int -sys32_getrusage(int who, struct rusage32 *ru) -{ - struct rusage r; - int ret; - mm_segment_t old_fs = get_fs(); - - set_fs (KERNEL_DS); - ret = sys_getrusage(who, &r); - set_fs (old_fs); - if (put_rusage (ru, &r)) - return -EFAULT; + length = ((unsigned long) length_hi << 32) | (unsigned int) length_lo; - return ret; + return sys_ftruncate(fd, length); } static inline long @@ -658,31 +578,7 @@ __put_user(i->tv_usec, &o->tv_usec))); } -asmlinkage unsigned long -sys32_alarm(unsigned int seconds) -{ - struct itimerval it_new, it_old; - unsigned int oldalarm; - - it_new.it_interval.tv_sec = it_new.it_interval.tv_usec = 0; - it_new.it_value.tv_sec = seconds; - it_new.it_value.tv_usec = 0; - do_setitimer(ITIMER_REAL, &it_new, &it_old); - oldalarm = it_old.it_value.tv_sec; - /* ehhh.. We can't return 0 if we have an alarm pending.. */ - /* And we'd better return too much than too little anyway */ - if (it_old.it_value.tv_usec) - oldalarm++; - - return oldalarm; -} - -/* Translations due to time_t size differences. Which affects all - sorts of things, like timeval and itimerval. */ - - extern struct timezone sys_tz; -extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz); asmlinkage int sys32_gettimeofday(struct compat_timeval *tv, struct timezone *tz) @@ -700,14 +596,28 @@ return 0; } +static inline long get_ts32(struct timespec *o, struct compat_timeval *i) +{ + long usec; + + if (!access_ok(VERIFY_READ, i, sizeof(*i))) + return -EFAULT; + if (__get_user(o->tv_sec, &i->tv_sec)) + return -EFAULT; + if (__get_user(usec, &i->tv_usec)) + return -EFAULT; + o->tv_nsec = usec * 1000; + return 0; +} + asmlinkage int sys32_settimeofday(struct compat_timeval *tv, struct timezone *tz) { - struct timeval ktv; + struct timespec kts; struct timezone ktz; if (tv) { - if (get_tv32(&ktv, tv)) + if (get_ts32(&kts, tv)) return -EFAULT; } if (tz) { @@ -715,16 +625,16 @@ return -EFAULT; } - return do_sys_settimeofday(tv ? &ktv : NULL, tz ? &ktz : NULL); + return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL); } extern asmlinkage long sys_llseek(unsigned int fd, unsigned long offset_high, unsigned long offset_low, loff_t * result, unsigned int origin); -extern asmlinkage int sys32_llseek(unsigned int fd, unsigned int offset_high, - unsigned int offset_low, loff_t * result, - unsigned int origin) +asmlinkage int sys32_llseek(unsigned int fd, unsigned int offset_high, + unsigned int offset_low, loff_t * result, + unsigned int origin) { return sys_llseek(fd, offset_high, offset_low, result, origin); } @@ -805,7 +715,7 @@ /* VERIFY_WRITE actually means a read, as we write to user space */ fn = file->f_op->read; if (type == VERIFY_READ) - fn = (IO_fn_t) file->f_op->write; + fn = (IO_fn_t) file->f_op->write; ivp = iov; while (count > 0) { void * base; @@ -876,11 +786,12 @@ non-seekable files. */ asmlinkage ssize_t sys32_pread(unsigned int fd, char * buf, - size_t count, u32 unused, loff_t pos) + size_t count, u32 unused, u64 a4, u64 a5) { ssize_t ret; struct file * file; ssize_t (*read)(struct file *, char *, size_t, loff_t *); + loff_t pos; ret = -EBADF; file = fget(fd); @@ -888,6 +799,7 @@ goto bad_file; if (!(file->f_mode & FMODE_READ)) goto out; + pos = merge_64(a4, a5); ret = locks_verify_area(FLOCK_VERIFY_READ, file->f_dentry->d_inode, file, pos, count); if (ret) @@ -907,11 +819,12 @@ } asmlinkage ssize_t sys32_pwrite(unsigned int fd, const char * buf, - size_t count, u32 unused, loff_t pos) + size_t count, u32 unused, u64 a4, u64 a5) { ssize_t ret; struct file * file; ssize_t (*write)(struct file *, const char *, size_t, loff_t *); + loff_t pos; ret = -EBADF; file = fget(fd); @@ -919,6 +832,7 @@ goto bad_file; if (!(file->f_mode & FMODE_WRITE)) goto out; + pos = merge_64(a4, a5); ret = locks_verify_area(FLOCK_VERIFY_WRITE, file->f_dentry->d_inode, file, pos, count); if (ret) @@ -945,7 +859,6 @@ static inline int get_fd_set32(unsigned long n, unsigned long *fdset, u32 *ufdset) { -#ifdef __MIPSEB__ if (ufdset) { unsigned long odd; @@ -972,9 +885,6 @@ memset(fdset, 0, ((n + 1) & ~1)*sizeof(u32)); } return 0; -#else - <> -#endif } static inline void @@ -1047,7 +957,7 @@ /* * 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. + * long-words. */ ret = -ENOMEM; size = FDS_BYTES(n); @@ -1105,15 +1015,15 @@ extern asmlinkage int sys_sched_rr_get_interval(pid_t pid, - struct timespec *interval); + struct timespec *interval); -asmlinkage int -sys32_sched_rr_get_interval(__kernel_pid_t32 pid, struct compat_timespec *interval) +asmlinkage int sys32_sched_rr_get_interval(__kernel_pid_t32 pid, + struct compat_timespec *interval) { struct timespec t; int ret; mm_segment_t old_fs = get_fs (); - + set_fs (KERNEL_DS); ret = sys_sched_rr_get_interval(pid, &t); set_fs (old_fs); @@ -1123,113 +1033,6 @@ return ret; } - -struct tms32 { - int tms_utime; - int tms_stime; - int tms_cutime; - int tms_cstime; -}; - -extern asmlinkage long sys_times(struct tms * tbuf); -asmlinkage long sys32_times(struct tms32 *tbuf) -{ - struct tms t; - long ret; - mm_segment_t old_fs = get_fs(); - int err; - - set_fs(KERNEL_DS); - ret = sys_times(tbuf ? &t : NULL); - set_fs(old_fs); - if (tbuf) { - err = put_user (t.tms_utime, &tbuf->tms_utime); - err |= __put_user (t.tms_stime, &tbuf->tms_stime); - err |= __put_user (t.tms_cutime, &tbuf->tms_cutime); - err |= __put_user (t.tms_cstime, &tbuf->tms_cstime); - if (err) - ret = -EFAULT; - } - return ret; -} - -struct flock32 { - short l_type; - short l_whence; - __kernel_off_t32 l_start; - __kernel_off_t32 l_len; - __kernel_pid_t32 l_pid; - short __unused; -}; - -static inline int get_flock(struct flock *kfl, struct flock32 *ufl) -{ - int err; - - err = get_user(kfl->l_type, &ufl->l_type); - err |= __get_user(kfl->l_whence, &ufl->l_whence); - err |= __get_user(kfl->l_start, &ufl->l_start); - err |= __get_user(kfl->l_len, &ufl->l_len); - err |= __get_user(kfl->l_pid, &ufl->l_pid); - return err; -} - -static inline int put_flock(struct flock *kfl, struct flock32 *ufl) -{ - int err; - - err = __put_user(kfl->l_type, &ufl->l_type); - err |= __put_user(kfl->l_whence, &ufl->l_whence); - err |= __put_user(kfl->l_start, &ufl->l_start); - err |= __put_user(kfl->l_len, &ufl->l_len); - err |= __put_user(kfl->l_pid, &ufl->l_pid); - return err; -} - -extern asmlinkage long -sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg); - -asmlinkage long -sys32_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - switch (cmd) { - case F_GETLK: - case F_SETLK: - case F_SETLKW: - { - struct flock f; - mm_segment_t old_fs; - long ret; - - if (get_flock(&f, (struct flock32 *)arg)) - return -EFAULT; - old_fs = get_fs(); set_fs (KERNEL_DS); - ret = sys_fcntl(fd, cmd, (unsigned long)&f); - set_fs (old_fs); - if (put_flock(&f, (struct flock32 *)arg)) - return -EFAULT; - return ret; - } - default: - return sys_fcntl(fd, cmd, (unsigned long)arg); - } -} - -asmlinkage long -sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - switch (cmd) { - case F_GETLK64: - return sys_fcntl(fd, F_GETLK, arg); - case F_SETLK64: - return sys_fcntl(fd, F_SETLK, arg); - case F_SETLKW64: - return sys_fcntl(fd, F_SETLKW, arg); - } - - return sys32_fcntl(fd, cmd, arg); -} - struct msgbuf32 { s32 mtype; char mtext[1]; }; struct ipc_perm32 @@ -1243,6 +1046,19 @@ unsigned short seq; }; +struct ipc64_perm32 { + key_t key; + __kernel_uid_t32 uid; + __kernel_gid_t32 gid; + __kernel_uid_t32 cuid; + __kernel_gid_t32 cgid; + __kernel_mode_t32 mode; + unsigned short seq; + unsigned short __pad1; + unsigned int __unused1; + unsigned int __unused2; +}; + struct semid_ds32 { struct ipc_perm32 sem_perm; /* permissions .. see ipc.h */ compat_time_t sem_otime; /* last semop time */ @@ -1254,6 +1070,15 @@ unsigned short sem_nsems; /* no. of semaphores in array */ }; +struct semid64_ds32 { + struct ipc64_perm32 sem_perm; + compat_time_t sem_otime; + compat_time_t sem_ctime; + unsigned int sem_nsems; + unsigned int __unused1; + unsigned int __unused2; +}; + struct msqid_ds32 { struct ipc_perm32 msg_perm; @@ -1265,24 +1090,57 @@ u32 wwait; u32 rwait; unsigned short msg_cbytes; - unsigned short msg_qnum; + unsigned short msg_qnum; unsigned short msg_qbytes; __kernel_ipc_pid_t32 msg_lspid; __kernel_ipc_pid_t32 msg_lrpid; }; +struct msqid64_ds32 { + struct ipc64_perm32 msg_perm; + compat_time_t msg_stime; + unsigned int __unused1; + compat_time_t msg_rtime; + unsigned int __unused2; + compat_time_t msg_ctime; + unsigned int __unused3; + unsigned int msg_cbytes; + unsigned int msg_qnum; + unsigned int msg_qbytes; + __kernel_pid_t32 msg_lspid; + __kernel_pid_t32 msg_lrpid; + unsigned int __unused4; + unsigned int __unused5; +}; + struct shmid_ds32 { struct ipc_perm32 shm_perm; int shm_segsz; - compat_time_t shm_atime; - compat_time_t shm_dtime; - compat_time_t shm_ctime; - __kernel_ipc_pid_t32 shm_cpid; - __kernel_ipc_pid_t32 shm_lpid; + compat_time_t shm_atime; + compat_time_t shm_dtime; + compat_time_t shm_ctime; + __kernel_ipc_pid_t32 shm_cpid; + __kernel_ipc_pid_t32 shm_lpid; unsigned short shm_nattch; }; -#define IPCOP_MASK(__x) (1UL << (__x)) +struct shmid64_ds32 { + struct ipc64_perm32 shm_perm; + compat_size_t shm_segsz; + compat_time_t shm_atime; + compat_time_t shm_dtime; + compat_time_t shm_ctime; + __kernel_pid_t32 shm_cpid; + __kernel_pid_t32 shm_lpid; + unsigned int shm_nattch; + unsigned int __unused1; + unsigned int __unused2; +}; + +struct ipc_kludge32 { + u32 msgp; + s32 msgtyp; +}; static int do_sys32_semctl(int first, int second, int third, void *uptr) @@ -1291,7 +1149,6 @@ u32 pad; int err, err2; struct semid64_ds s; - struct semid_ds32 *usp; mm_segment_t old_fs; if (!uptr) @@ -1304,7 +1161,6 @@ else fourth.__pad = (void *)A(pad); switch (third & ~IPC_64) { - case IPC_INFO: case IPC_RMID: case IPC_SET: @@ -1321,29 +1177,54 @@ case IPC_STAT: case SEM_STAT: - usp = (struct semid_ds32 *)A(pad); fourth.__pad = &s; old_fs = get_fs (); set_fs (KERNEL_DS); err = sys_semctl (first, second, third, fourth); set_fs (old_fs); - err2 = put_user(s.sem_perm.key, &usp->sem_perm.key); - err2 |= __put_user(s.sem_perm.uid, &usp->sem_perm.uid); - err2 |= __put_user(s.sem_perm.gid, &usp->sem_perm.gid); - err2 |= __put_user(s.sem_perm.cuid, - &usp->sem_perm.cuid); - err2 |= __put_user (s.sem_perm.cgid, - &usp->sem_perm.cgid); - err2 |= __put_user (s.sem_perm.mode, - &usp->sem_perm.mode); - err2 |= __put_user (s.sem_perm.seq, &usp->sem_perm.seq); - err2 |= __put_user (s.sem_otime, &usp->sem_otime); - err2 |= __put_user (s.sem_ctime, &usp->sem_ctime); - err2 |= __put_user (s.sem_nsems, &usp->sem_nsems); + + if (third & IPC_64) { + struct semid64_ds32 *usp64 = (struct semid64_ds32 *) A(pad); + + if (!access_ok(VERIFY_WRITE, usp64, sizeof(*usp64))) { + err = -EFAULT; + break; + } + err2 = __put_user(s.sem_perm.key, &usp64->sem_perm.key); + err2 |= __put_user(s.sem_perm.uid, &usp64->sem_perm.uid); + err2 |= __put_user(s.sem_perm.gid, &usp64->sem_perm.gid); + err2 |= __put_user(s.sem_perm.cuid, &usp64->sem_perm.cuid); + err2 |= __put_user(s.sem_perm.cgid, &usp64->sem_perm.cgid); + err2 |= __put_user(s.sem_perm.mode, &usp64->sem_perm.mode); + err2 |= __put_user(s.sem_perm.seq, &usp64->sem_perm.seq); + err2 |= __put_user(s.sem_otime, &usp64->sem_otime); + err2 |= __put_user(s.sem_ctime, &usp64->sem_ctime); + err2 |= __put_user(s.sem_nsems, &usp64->sem_nsems); + } else { + struct semid_ds32 *usp32 = (struct semid_ds32 *) A(pad); + + if (!access_ok(VERIFY_WRITE, usp32, sizeof(*usp32))) { + err = -EFAULT; + break; + } + err2 = __put_user(s.sem_perm.key, &usp32->sem_perm.key); + err2 |= __put_user(s.sem_perm.uid, &usp32->sem_perm.uid); + err2 |= __put_user(s.sem_perm.gid, &usp32->sem_perm.gid); + err2 |= __put_user(s.sem_perm.cuid, &usp32->sem_perm.cuid); + err2 |= __put_user(s.sem_perm.cgid, &usp32->sem_perm.cgid); + err2 |= __put_user(s.sem_perm.mode, &usp32->sem_perm.mode); + err2 |= __put_user(s.sem_perm.seq, &usp32->sem_perm.seq); + err2 |= __put_user(s.sem_otime, &usp32->sem_otime); + err2 |= __put_user(s.sem_ctime, &usp32->sem_ctime); + err2 |= __put_user(s.sem_nsems, &usp32->sem_nsems); + } if (err2) err = -EFAULT; break; + default: + err = - EINVAL; + break; } return err; @@ -1352,15 +1233,20 @@ static int do_sys32_msgsnd (int first, int second, int third, void *uptr) { - struct msgbuf *p = kmalloc (second + sizeof (struct msgbuf) - + 4, GFP_USER); struct msgbuf32 *up = (struct msgbuf32 *)uptr; + struct msgbuf *p; mm_segment_t old_fs; int err; + if (second < 0) + return -EINVAL; + p = kmalloc (second + sizeof (struct msgbuf) + + 4, GFP_USER); if (!p) return -ENOMEM; err = get_user (p->mtype, &up->mtype); + if (err) + goto out; err |= __copy_from_user (p->mtext, &up->mtext, second); if (err) goto out; @@ -1370,6 +1256,7 @@ set_fs (old_fs); out: kfree (p); + return err; } @@ -1383,18 +1270,21 @@ int err; if (!version) { - struct ipc_kludge *uipck = (struct ipc_kludge *)uptr; - struct ipc_kludge ipck; + struct ipc_kludge32 *uipck = (struct ipc_kludge32 *)uptr; + struct ipc_kludge32 ipck; err = -EINVAL; if (!uptr) goto out; err = -EFAULT; - if (copy_from_user (&ipck, uipck, sizeof (struct ipc_kludge))) + if (copy_from_user (&ipck, uipck, sizeof (struct ipc_kludge32))) goto out; - uptr = (void *)A(ipck.msgp); + uptr = (void *)AA(ipck.msgp); msgtyp = ipck.msgtyp; } + + if (second < 0) + return -EINVAL; err = -ENOMEM; p = kmalloc (second + sizeof (struct msgbuf) + 4, GFP_USER); if (!p) @@ -1419,13 +1309,12 @@ do_sys32_msgctl (int first, int second, void *uptr) { int err = -EINVAL, err2; - struct msqid_ds m; - struct msqid64_ds m64; - struct msqid_ds32 *up = (struct msqid_ds32 *)uptr; + struct msqid64_ds m; + struct msqid_ds32 *up32 = (struct msqid_ds32 *)uptr; + struct msqid64_ds32 *up64 = (struct msqid64_ds32 *)uptr; mm_segment_t old_fs; - switch (second) { - + switch (second & ~IPC_64) { case IPC_INFO: case IPC_RMID: case MSG_INFO: @@ -1433,15 +1322,30 @@ break; case IPC_SET: - err = get_user (m.msg_perm.uid, &up->msg_perm.uid); - err |= __get_user (m.msg_perm.gid, &up->msg_perm.gid); - err |= __get_user (m.msg_perm.mode, &up->msg_perm.mode); - err |= __get_user (m.msg_qbytes, &up->msg_qbytes); + if (second & IPC_64) { + if (!access_ok(VERIFY_READ, up64, sizeof(*up64))) { + err = -EFAULT; + break; + } + err = __get_user(m.msg_perm.uid, &up64->msg_perm.uid); + err |= __get_user(m.msg_perm.gid, &up64->msg_perm.gid); + err |= __get_user(m.msg_perm.mode, &up64->msg_perm.mode); + err |= __get_user(m.msg_qbytes, &up64->msg_qbytes); + } else { + if (!access_ok(VERIFY_READ, up32, sizeof(*up32))) { + err = -EFAULT; + break; + } + err = __get_user(m.msg_perm.uid, &up32->msg_perm.uid); + err |= __get_user(m.msg_perm.gid, &up32->msg_perm.gid); + err |= __get_user(m.msg_perm.mode, &up32->msg_perm.mode); + err |= __get_user(m.msg_qbytes, &up32->msg_qbytes); + } if (err) break; old_fs = get_fs (); set_fs (KERNEL_DS); - err = sys_msgctl (first, second, &m); + err = sys_msgctl (first, second, (struct msqid_ds *)&m); set_fs (old_fs); break; @@ -1449,27 +1353,54 @@ case MSG_STAT: old_fs = get_fs (); set_fs (KERNEL_DS); - err = sys_msgctl (first, second, (void *) &m64); + err = sys_msgctl (first, second, (struct msqid_ds *)&m); set_fs (old_fs); - err2 = put_user (m64.msg_perm.key, &up->msg_perm.key); - err2 |= __put_user(m64.msg_perm.uid, &up->msg_perm.uid); - err2 |= __put_user(m64.msg_perm.gid, &up->msg_perm.gid); - err2 |= __put_user(m64.msg_perm.cuid, &up->msg_perm.cuid); - err2 |= __put_user(m64.msg_perm.cgid, &up->msg_perm.cgid); - err2 |= __put_user(m64.msg_perm.mode, &up->msg_perm.mode); - err2 |= __put_user(m64.msg_perm.seq, &up->msg_perm.seq); - err2 |= __put_user(m64.msg_stime, &up->msg_stime); - err2 |= __put_user(m64.msg_rtime, &up->msg_rtime); - err2 |= __put_user(m64.msg_ctime, &up->msg_ctime); - err2 |= __put_user(m64.msg_cbytes, &up->msg_cbytes); - err2 |= __put_user(m64.msg_qnum, &up->msg_qnum); - err2 |= __put_user(m64.msg_qbytes, &up->msg_qbytes); - err2 |= __put_user(m64.msg_lspid, &up->msg_lspid); - err2 |= __put_user(m64.msg_lrpid, &up->msg_lrpid); - if (err2) - err = -EFAULT; + if (second & IPC_64) { + if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) { + err = -EFAULT; + break; + } + err2 = __put_user(m.msg_perm.key, &up64->msg_perm.key); + err2 |= __put_user(m.msg_perm.uid, &up64->msg_perm.uid); + err2 |= __put_user(m.msg_perm.gid, &up64->msg_perm.gid); + err2 |= __put_user(m.msg_perm.cuid, &up64->msg_perm.cuid); + err2 |= __put_user(m.msg_perm.cgid, &up64->msg_perm.cgid); + err2 |= __put_user(m.msg_perm.mode, &up64->msg_perm.mode); + err2 |= __put_user(m.msg_perm.seq, &up64->msg_perm.seq); + err2 |= __put_user(m.msg_stime, &up64->msg_stime); + err2 |= __put_user(m.msg_rtime, &up64->msg_rtime); + err2 |= __put_user(m.msg_ctime, &up64->msg_ctime); + err2 |= __put_user(m.msg_cbytes, &up64->msg_cbytes); + err2 |= __put_user(m.msg_qnum, &up64->msg_qnum); + err2 |= __put_user(m.msg_qbytes, &up64->msg_qbytes); + err2 |= __put_user(m.msg_lspid, &up64->msg_lspid); + err2 |= __put_user(m.msg_lrpid, &up64->msg_lrpid); + if (err2) + err = -EFAULT; + } else { + if (!access_ok(VERIFY_WRITE, up32, sizeof(*up32))) { + err = -EFAULT; + break; + } + err2 = __put_user(m.msg_perm.key, &up32->msg_perm.key); + err2 |= __put_user(m.msg_perm.uid, &up32->msg_perm.uid); + err2 |= __put_user(m.msg_perm.gid, &up32->msg_perm.gid); + err2 |= __put_user(m.msg_perm.cuid, &up32->msg_perm.cuid); + err2 |= __put_user(m.msg_perm.cgid, &up32->msg_perm.cgid); + err2 |= __put_user(m.msg_perm.mode, &up32->msg_perm.mode); + err2 |= __put_user(m.msg_perm.seq, &up32->msg_perm.seq); + err2 |= __put_user(m.msg_stime, &up32->msg_stime); + err2 |= __put_user(m.msg_rtime, &up32->msg_rtime); + err2 |= __put_user(m.msg_ctime, &up32->msg_ctime); + err2 |= __put_user(m.msg_cbytes, &up32->msg_cbytes); + err2 |= __put_user(m.msg_qnum, &up32->msg_qnum); + err2 |= __put_user(m.msg_qbytes, &up32->msg_qbytes); + err2 |= __put_user(m.msg_lspid, &up32->msg_lspid); + err2 |= __put_user(m.msg_lrpid, &up32->msg_lrpid); + if (err2) + err = -EFAULT; + } break; - } return err; @@ -1499,7 +1430,8 @@ int err = -EFAULT, err2; struct shmid_ds s; struct shmid64_ds s64; - struct shmid_ds32 *up = (struct shmid_ds32 *)uptr; + struct shmid_ds32 *up32 = (struct shmid_ds32 *)uptr; + struct shmid64_ds32 *up64 = (struct shmid64_ds32 *)uptr; mm_segment_t old_fs; struct shm_info32 { int used_ids; @@ -1508,18 +1440,24 @@ } *uip = (struct shm_info32 *)uptr; struct shm_info si; - switch (second) { - + switch (second & ~IPC_64) { case IPC_INFO: + second = IPC_INFO; /* So that we don't have to translate it */ case IPC_RMID: case SHM_LOCK: case SHM_UNLOCK: err = sys_shmctl (first, second, (struct shmid_ds *)uptr); break; case IPC_SET: - err = get_user (s.shm_perm.uid, &up->shm_perm.uid); - err |= __get_user (s.shm_perm.gid, &up->shm_perm.gid); - err |= __get_user (s.shm_perm.mode, &up->shm_perm.mode); + if (second & IPC_64) { + err = get_user(s.shm_perm.uid, &up64->shm_perm.uid); + err |= get_user(s.shm_perm.gid, &up64->shm_perm.gid); + err |= get_user(s.shm_perm.mode, &up64->shm_perm.mode); + } else { + err = get_user(s.shm_perm.uid, &up32->shm_perm.uid); + err |= get_user(s.shm_perm.gid, &up32->shm_perm.gid); + err |= get_user(s.shm_perm.mode, &up32->shm_perm.mode); + } if (err) break; old_fs = get_fs (); @@ -1536,23 +1474,45 @@ set_fs (old_fs); if (err < 0) break; - err2 = put_user (s64.shm_perm.key, &up->shm_perm.key); - err2 |= __put_user (s64.shm_perm.uid, &up->shm_perm.uid); - err2 |= __put_user (s64.shm_perm.gid, &up->shm_perm.gid); - err2 |= __put_user (s64.shm_perm.cuid, - &up->shm_perm.cuid); - err2 |= __put_user (s64.shm_perm.cgid, - &up->shm_perm.cgid); - err2 |= __put_user (s64.shm_perm.mode, - &up->shm_perm.mode); - err2 |= __put_user (s64.shm_perm.seq, &up->shm_perm.seq); - err2 |= __put_user (s64.shm_atime, &up->shm_atime); - err2 |= __put_user (s64.shm_dtime, &up->shm_dtime); - err2 |= __put_user (s64.shm_ctime, &up->shm_ctime); - err2 |= __put_user (s64.shm_segsz, &up->shm_segsz); - err2 |= __put_user (s64.shm_nattch, &up->shm_nattch); - err2 |= __put_user (s64.shm_cpid, &up->shm_cpid); - err2 |= __put_user (s64.shm_lpid, &up->shm_lpid); + if (second & IPC_64) { + if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) { + err = -EFAULT; + break; + } + err2 = __put_user(s64.shm_perm.key, &up64->shm_perm.key); + err2 |= __put_user(s64.shm_perm.uid, &up64->shm_perm.uid); + err2 |= __put_user(s64.shm_perm.gid, &up64->shm_perm.gid); + err2 |= __put_user(s64.shm_perm.cuid, &up64->shm_perm.cuid); + err2 |= __put_user(s64.shm_perm.cgid, &up64->shm_perm.cgid); + err2 |= __put_user(s64.shm_perm.mode, &up64->shm_perm.mode); + err2 |= __put_user(s64.shm_perm.seq, &up64->shm_perm.seq); + err2 |= __put_user(s64.shm_atime, &up64->shm_atime); + err2 |= __put_user(s64.shm_dtime, &up64->shm_dtime); + err2 |= __put_user(s64.shm_ctime, &up64->shm_ctime); + err2 |= __put_user(s64.shm_segsz, &up64->shm_segsz); + err2 |= __put_user(s64.shm_nattch, &up64->shm_nattch); + err2 |= __put_user(s64.shm_cpid, &up64->shm_cpid); + err2 |= __put_user(s64.shm_lpid, &up64->shm_lpid); + } else { + if (!access_ok(VERIFY_WRITE, up32, sizeof(*up32))) { + err = -EFAULT; + break; + } + err2 = __put_user(s64.shm_perm.key, &up32->shm_perm.key); + err2 |= __put_user(s64.shm_perm.uid, &up32->shm_perm.uid); + err2 |= __put_user(s64.shm_perm.gid, &up32->shm_perm.gid); + err2 |= __put_user(s64.shm_perm.cuid, &up32->shm_perm.cuid); + err2 |= __put_user(s64.shm_perm.cgid, &up32->shm_perm.cgid); + err2 |= __put_user(s64.shm_perm.mode, &up32->shm_perm.mode); + err2 |= __put_user(s64.shm_perm.seq, &up32->shm_perm.seq); + err2 |= __put_user(s64.shm_atime, &up32->shm_atime); + err2 |= __put_user(s64.shm_dtime, &up32->shm_dtime); + err2 |= __put_user(s64.shm_ctime, &up32->shm_ctime); + err2 |= __put_user(s64.shm_segsz, &up32->shm_segsz); + err2 |= __put_user(s64.shm_nattch, &up32->shm_nattch); + err2 |= __put_user(s64.shm_cpid, &up32->shm_cpid); + err2 |= __put_user(s64.shm_lpid, &up32->shm_lpid); + } if (err2) err = -EFAULT; break; @@ -1576,7 +1536,11 @@ err = -EFAULT; break; + default: + err = -ENOSYS; + break; } + return err; } @@ -1592,7 +1556,7 @@ case SEMOP: /* struct sembuf is the same on 32 and 64bit :)) */ - err = sys_semop (first, (struct sembuf *)A(ptr), + err = sys_semop (first, (struct sembuf *)AA(ptr), second); break; case SEMGET: @@ -1600,36 +1564,36 @@ break; case SEMCTL: err = do_sys32_semctl (first, second, third, - (void *)A(ptr)); + (void *)AA(ptr)); break; case MSGSND: err = do_sys32_msgsnd (first, second, third, - (void *)A(ptr)); + (void *)AA(ptr)); break; case MSGRCV: err = do_sys32_msgrcv (first, second, fifth, third, - version, (void *)A(ptr)); + version, (void *)AA(ptr)); break; case MSGGET: err = sys_msgget ((key_t) first, second); break; case MSGCTL: - err = do_sys32_msgctl (first, second, (void *)A(ptr)); + err = do_sys32_msgctl (first, second, (void *)AA(ptr)); break; case SHMAT: err = do_sys32_shmat (first, second, third, - version, (void *)A(ptr)); + version, (void *)AA(ptr)); break; - case SHMDT: + case SHMDT: err = sys_shmdt ((char *)A(ptr)); break; case SHMGET: err = sys_shmget (first, second, third); break; case SHMCTL: - err = do_sys32_shmctl (first, second, (void *)A(ptr)); + err = do_sys32_shmctl (first, second, (void *)AA(ptr)); break; default: err = -EINVAL; @@ -1650,81 +1614,103 @@ unsigned int __unused[4]; }; -asmlinkage long sys32_sysctl(struct sysctl_args32 *uargs32) -{ - struct __sysctl_args kargs; - struct sysctl_args32 kargs32; - mm_segment_t old_fs; - int name[CTL_MAXNAME]; - size_t oldlen[1]; - int err, ret; - - ret = -EFAULT; - - memset(&kargs, 0, sizeof (kargs)); - - err = get_user(kargs32.name, &uargs32->name); - err |= __get_user(kargs32.nlen, &uargs32->nlen); - err |= __get_user(kargs32.oldval, &uargs32->oldval); - err |= __get_user(kargs32.oldlenp, &uargs32->oldlenp); - err |= __get_user(kargs32.newval, &uargs32->newval); - err |= __get_user(kargs32.newlen, &uargs32->newlen); - if (err) - goto out; +#ifdef CONFIG_SYSCTL - if (kargs32.nlen == 0 || kargs32.nlen >= CTL_MAXNAME) { - ret = -ENOTDIR; - goto out; - } +asmlinkage long sys32_sysctl(struct sysctl_args32 *args) +{ + struct sysctl_args32 tmp; + int error; + size_t oldlen, *oldlenp = NULL; + unsigned long addr = (((long)&args->__unused[0]) + 7) & ~7; - kargs.name = name; - kargs.nlen = kargs32.nlen; - if (copy_from_user(kargs.name, (int *)A(kargs32.name), - kargs32.nlen * sizeof(name) / sizeof(name[0]))) - goto out; + if (copy_from_user(&tmp, args, sizeof(tmp))) + return -EFAULT; - if (kargs32.oldval) { - if (!kargs32.oldlenp || get_user(oldlen[0], - (int *)A(kargs32.oldlenp))) + if (tmp.oldval && tmp.oldlenp) { + /* Duh, this is ugly and might not work if sysctl_args + is in read-only memory, but do_sysctl does indirectly + a lot of uaccess in both directions and we'd have to + basically copy the whole sysctl.c here, and + glibc's __sysctl uses rw memory for the structure + anyway. */ + if (get_user(oldlen, (u32 *)A(tmp.oldlenp)) || + put_user(oldlen, (size_t *)addr)) return -EFAULT; - kargs.oldlenp = oldlen; - kargs.oldval = kmalloc(oldlen[0], GFP_KERNEL); - if (!kargs.oldval) { - ret = -ENOMEM; - goto out; - } + oldlenp = (size_t *)addr; } - if (kargs32.newval && kargs32.newlen) { - kargs.newval = kmalloc(kargs32.newlen, GFP_KERNEL); - if (!kargs.newval) { - ret = -ENOMEM; - goto out; + lock_kernel(); + error = do_sysctl((int *)A(tmp.name), tmp.nlen, (void *)A(tmp.oldval), + oldlenp, (void *)A(tmp.newval), tmp.newlen); + unlock_kernel(); + if (oldlenp) { + if (!error) { + if (get_user(oldlen, (size_t *)addr) || + put_user(oldlen, (u32 *)A(tmp.oldlenp))) + error = -EFAULT; } - if (copy_from_user(kargs.newval, (int *)A(kargs32.newval), - kargs32.newlen)) - goto out; + copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused)); } + return error; +} - old_fs = get_fs(); set_fs (KERNEL_DS); - ret = sys_sysctl(&kargs); - set_fs (old_fs); +#else /* CONFIG_SYSCTL */ - if (ret) - goto out; +asmlinkage long sys32_sysctl(struct sysctl_args32 *args) +{ + return -ENOSYS; +} + +#endif /* CONFIG_SYSCTL */ + +extern asmlinkage int sys_sched_setaffinity(pid_t pid, unsigned int len, + unsigned long *user_mask_ptr); - if (kargs.oldval) { - if (put_user(oldlen[0], (int *)A(kargs32.oldlenp)) || - copy_to_user((int *)A(kargs32.oldval), kargs.oldval, - oldlen[0])) +asmlinkage int sys32_sched_setaffinity(__kernel_pid_t32 pid, unsigned int len, + u32 *user_mask_ptr) +{ + unsigned long kernel_mask; + mm_segment_t old_fs; + int ret; + + if (get_user(kernel_mask, user_mask_ptr)) + return -EFAULT; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_sched_setaffinity(pid, + /* XXX Nice api... */ + sizeof(kernel_mask), + &kernel_mask); + set_fs(old_fs); + + return ret; +} + +extern asmlinkage int sys_sched_getaffinity(pid_t pid, unsigned int len, + unsigned long *user_mask_ptr); + +asmlinkage int sys32_sched_getaffinity(__kernel_pid_t32 pid, unsigned int len, + u32 *user_mask_ptr) +{ + unsigned long kernel_mask; + mm_segment_t old_fs; + int ret; + + old_fs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_sched_getaffinity(pid, + /* XXX Nice api... */ + sizeof(kernel_mask), + &kernel_mask); + set_fs(old_fs); + + if (ret == 0) { + if (put_user(kernel_mask, user_mask_ptr)) ret = -EFAULT; } -out: - if (kargs.oldval) - kfree(kargs.oldval); - if (kargs.newval) - kfree(kargs.newval); - return ret; + + return ret; } asmlinkage long sys32_newuname(struct new_utsname * name) @@ -1780,7 +1766,7 @@ memset(&txc, 0, sizeof(struct timex)); - if(get_user(txc.modes, &utp->modes) || + 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) || @@ -1804,7 +1790,7 @@ ret = do_adjtimex(&txc); - if(put_user(txc.modes, &utp->modes) || + 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) || @@ -1829,3 +1815,31 @@ return ret; } +extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count); + +asmlinkage int sys32_sendfile(int out_fd, int in_fd, __kernel_off_t32 *offset, s32 count) +{ + mm_segment_t old_fs = get_fs(); + int ret; + off_t of; + + if (offset && get_user(of, offset)) + return -EFAULT; + + set_fs(KERNEL_DS); + ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count); + set_fs(old_fs); + + if (offset && put_user(of, offset)) + return -EFAULT; + + return ret; +} + +asmlinkage ssize_t sys_readahead(int fd, loff_t offset, size_t count); + +asmlinkage ssize_t sys32_readahead(int fd, u32 pad0, u64 a2, u64 a3, + size_t count) +{ + return sys_readahead(fd, merge_64(a2, a3), count); +} diff -Nru a/arch/mips64/kernel/mips64_ksyms.c b/arch/mips64/kernel/mips64_ksyms.c --- a/arch/mips64/kernel/mips64_ksyms.c Tue Jul 1 18:44:34 2003 +++ b/arch/mips64/kernel/mips64_ksyms.c Tue Jul 1 18:44:34 2003 @@ -13,9 +13,9 @@ #include #include #include -#include #include #include +#include #include #include @@ -38,7 +38,10 @@ extern long __strnlen_user_asm(const char *s); EXPORT_SYMBOL(mips_machtype); + +#ifdef CONFIG_EISA EXPORT_SYMBOL(EISA_bus); +#endif /* * String functions @@ -53,12 +56,9 @@ EXPORT_SYMBOL_NOVERS(strncat); EXPORT_SYMBOL_NOVERS(strnlen); EXPORT_SYMBOL_NOVERS(strrchr); -EXPORT_SYMBOL_NOVERS(strsep); EXPORT_SYMBOL_NOVERS(strpbrk); EXPORT_SYMBOL(_clear_page); -EXPORT_SYMBOL(enable_irq); -EXPORT_SYMBOL(disable_irq); EXPORT_SYMBOL(kernel_thread); /* @@ -74,43 +74,16 @@ EXPORT_SYMBOL_NOVERS(__strnlen_user_asm); -/* - * Functions to control caches. - */ -EXPORT_SYMBOL(_flush_page_to_ram); -EXPORT_SYMBOL(_flush_cache_l1); -#ifndef CONFIG_COHERENT_IO -EXPORT_SYMBOL(_dma_cache_wback_inv); -EXPORT_SYMBOL(_dma_cache_inv); -#endif - EXPORT_SYMBOL(invalid_pte_table); /* - * Base address of ports for Intel style I/O. - */ -#if defined (CONFIG_PCI) || defined (CONFIG_ISA) -EXPORT_SYMBOL(mips_io_port_base); -#endif - -/* * Kernel hacking ... */ #include #include -int register_fpe(void (*handler)(struct pt_regs *regs, unsigned int fcr31)); -int unregister_fpe(void (*handler)(struct pt_regs *regs, unsigned int fcr31)); - -#ifdef CONFIG_MIPS_FPE_MODULE -EXPORT_SYMBOL(__compute_return_epc); -EXPORT_SYMBOL(register_fpe); -EXPORT_SYMBOL(unregister_fpe); -#endif - #ifdef CONFIG_VT EXPORT_SYMBOL(screen_info); #endif EXPORT_SYMBOL(get_wchan); -EXPORT_SYMBOL(_flush_tlb_page); diff -Nru a/arch/mips64/kernel/module.c b/arch/mips64/kernel/module.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips64/kernel/module.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,349 @@ +/* Kernel module help for MIPS. + Copyright (C) 2001 Rusty Russell. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#include +#include +#include +#include +#include +#include +#include + +struct mips_hi16 { + struct mips_hi16 *next; + Elf32_Addr *addr; + Elf32_Addr value; +}; + +static struct mips_hi16 *mips_hi16_list; + +#if 0 +#define DEBUGP printk +#else +#define DEBUGP(fmt , ...) +#endif + +static struct vm_struct * modvmlist = NULL; + +void module_unmap(void * addr) +{ + struct vm_struct **p, *tmp; + int i; + + if (!addr) + return; + if ((PAGE_SIZE-1) & (unsigned long) addr) { + printk("Trying to unmap module with bad address (%p)\n", addr); + return; + } + + for (p = &modvmlist ; (tmp = *p) ; p = &tmp->next) { + if (tmp->addr == addr) { + *p = tmp->next; + goto found; + } + } + printk("Trying to unmap nonexistent module vm area (%p)\n", addr); + return; + +found: + unmap_vm_area(tmp); + + for (i = 0; i < tmp->nr_pages; i++) { + if (unlikely(!tmp->pages[i])) + BUG(); + __free_page(tmp->pages[i]); + } + + kfree(tmp->pages); + kfree(tmp); +} + +#define MODULES_LEN (512*1024*1024) /* Random silly large number */ +#define MODULES_END (512*1024*1024) /* Random silly large number */ +#define MODULES_VADDR (512*1024*1024) /* Random silly large number */ + +void *module_map(unsigned long size) +{ + struct vm_struct **p, *tmp, *area; + struct page **pages; + void * addr; + unsigned int nr_pages, array_size, i; + + size = PAGE_ALIGN(size); + if (!size || size > MODULES_LEN) + return NULL; + + addr = (void *) MODULES_VADDR; + for (p = &modvmlist; (tmp = *p) ; p = &tmp->next) { + if (size + (unsigned long) addr < (unsigned long) tmp->addr) + break; + addr = (void *) (tmp->size + (unsigned long) tmp->addr); + } + if ((unsigned long) addr + size >= MODULES_END) + return NULL; + + area = (struct vm_struct *) kmalloc(sizeof(*area), GFP_KERNEL); + if (!area) + return NULL; + area->size = size + PAGE_SIZE; + area->addr = addr; + area->next = *p; + area->pages = NULL; + area->nr_pages = 0; + area->phys_addr = 0; + *p = area; + + nr_pages = size >> PAGE_SHIFT; + array_size = (nr_pages * sizeof(struct page *)); + + area->nr_pages = nr_pages; + area->pages = pages = kmalloc(array_size, GFP_KERNEL); + if (!area->pages) + goto fail; + + memset(area->pages, 0, array_size); + + for (i = 0; i < area->nr_pages; i++) { + area->pages[i] = alloc_page(GFP_KERNEL); + if (unlikely(!area->pages[i])) + goto fail; + } + + if (map_vm_area(area, PAGE_KERNEL, &pages)) { + unmap_vm_area(area); + goto fail; + } + + return area->addr; + +fail: + if (area->pages) { + for (i = 0; i < area->nr_pages; i++) { + if (area->pages[i]) + __free_page(area->pages[i]); + } + kfree(area->pages); + } + kfree(area); + + return NULL; +} + +void *module_alloc(unsigned long size) +{ + if (size == 0) + return NULL; + return vmalloc(size); +} + + +/* Free memory returned from module_alloc */ +void module_free(struct module *mod, void *module_region) +{ + vfree(module_region); + /* FIXME: If module_region == mod->init_region, trim exception + table entries. */ +} + +/* We don't need anything special. */ +long module_core_size(const Elf32_Ehdr *hdr, + const Elf32_Shdr *sechdrs, + const char *secstrings, + struct module *module) +{ + return module->core_size; +} + +long module_init_size(const Elf32_Ehdr *hdr, + const Elf32_Shdr *sechdrs, + const char *secstrings, + struct module *module) +{ + return module->init_size; +} + +int module_frob_arch_sections(Elf_Ehdr *hdr, + Elf_Shdr *sechdrs, + char *secstrings, + struct module *mod) +{ + return 0; +} + +int apply_relocate(Elf32_Shdr *sechdrs, + const char *strtab, + unsigned int symindex, + unsigned int relsec, + struct module *me) +{ + unsigned int i; + Elf32_Rel *rel = (void *)sechdrs[relsec].sh_offset; + Elf32_Sym *sym; + uint32_t *location; + Elf32_Addr v; + + DEBUGP("Applying relocate section %u to %u\n", relsec, + sechdrs[relsec].sh_info); + for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { + /* This is where to make the change */ + location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_offset + + rel[i].r_offset; + /* This is the symbol it is referring to */ + sym = (Elf32_Sym *)sechdrs[symindex].sh_offset + + ELF32_R_SYM(rel[i].r_info); + if (!sym->st_value) { + printk(KERN_WARNING "%s: Unknown symbol %s\n", + me->name, strtab + sym->st_name); + return -ENOENT; + } + + v = sym->st_value; + + switch (ELF32_R_TYPE(rel[i].r_info)) { + case R_MIPS_NONE: + break; + + case R_MIPS_32: + *location += v; + break; + + case R_MIPS_26: + if (v % 4) + printk(KERN_ERR + "module %s: dangerous relocation\n", + me->name); + return -ENOEXEC; + if ((v & 0xf0000000) != + (((unsigned long)location + 4) & 0xf0000000)) + printk(KERN_ERR + "module %s: relocation overflow\n", + me->name); + return -ENOEXEC; + *location = (*location & ~0x03ffffff) | + ((*location + (v >> 2)) & 0x03ffffff); + break; + + case R_MIPS_HI16: { + struct mips_hi16 *n; + + /* + * We cannot relocate this one now because we don't + * know the value of the carry we need to add. Save + * the information, and let LO16 do the actual + * relocation. + */ + n = (struct mips_hi16 *) kmalloc(sizeof *n, GFP_KERNEL); + n->addr = location; + n->value = v; + n->next = mips_hi16_list; + mips_hi16_list = n; + break; + } + + case R_MIPS_LO16: { + unsigned long insnlo = *location; + Elf32_Addr val, vallo; + + /* Sign extend the addend we extract from the lo insn. */ + vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000; + + if (mips_hi16_list != NULL) { + struct mips_hi16 *l; + + l = mips_hi16_list; + while (l != NULL) { + struct mips_hi16 *next; + unsigned long insn; + + /* + * The value for the HI16 had best be + * the same. + */ + printk(KERN_ERR "module %s: dangerous " + "relocation\n", me->name); + return -ENOEXEC; + + /* + * Do the HI16 relocation. Note that + * we actually don't need to know + * anything about the LO16 itself, + * except where to find the low 16 bits + * of the addend needed by the LO16. + */ + insn = *l->addr; + val = ((insn & 0xffff) << 16) + vallo; + val += v; + + /* + * Account for the sign extension that + * will happen in the low bits. + */ + val = ((val >> 16) + ((val & 0x8000) != + 0)) & 0xffff; + + insn = (insn & ~0xffff) | val; + *l->addr = insn; + + next = l->next; + kfree(l); + l = next; + } + + mips_hi16_list = NULL; + } + + /* + * Ok, we're done with the HI16 relocs. Now deal with + * the LO16. + */ + val = v + vallo; + insnlo = (insnlo & ~0xffff) | (val & 0xffff); + *location = insnlo; + break; + } + + default: + printk(KERN_ERR "module %s: Unknown relocation: %u\n", + me->name, ELF32_R_TYPE(rel[i].r_info)); + return -ENOEXEC; + } + } + return 0; +} + +int apply_relocate_add(Elf32_Shdr *sechdrs, + const char *strtab, + unsigned int symindex, + unsigned int relsec, + struct module *me) +{ + printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n", + me->name); + return -ENOEXEC; +} + +int module_finalize(const Elf_Ehdr *hdr, + const Elf_Shdr *sechdrs, + struct module *me) +{ + return 0; +} + +void module_arch_cleanup(struct module *mod) +{ +} diff -Nru a/arch/mips64/kernel/offset.c b/arch/mips64/kernel/offset.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips64/kernel/offset.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,207 @@ +/* + * offset.c: Calculate pt_regs and task_struct offsets. + * + * Copyright (C) 1996 David S. Miller + * Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Ralf Baechle + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + * + * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. + */ +#include +#include +#include +#include + +#include +#include + +#define text(t) __asm__("\n@@@" t) +#define _offset(type, member) (&(((type *)NULL)->member)) + +#define offset(string, ptr, member) \ + __asm__("\n@@@" string "%0" : : "i" (_offset(ptr, member))) +#define constant(string, member) \ + __asm__("\n@@@" string "%x0" : : "i" (member)) +#define size(string, size) \ + __asm__("\n@@@" string "%0" : : "i" (sizeof(size))) +#define linefeed text("") + +void output_ptreg_defines(void) +{ + text("/* MIPS pt_regs offsets. */"); + offset("#define PT_R0 ", struct pt_regs, regs[0]); + offset("#define PT_R1 ", struct pt_regs, regs[1]); + offset("#define PT_R2 ", struct pt_regs, regs[2]); + offset("#define PT_R3 ", struct pt_regs, regs[3]); + offset("#define PT_R4 ", struct pt_regs, regs[4]); + offset("#define PT_R5 ", struct pt_regs, regs[5]); + offset("#define PT_R6 ", struct pt_regs, regs[6]); + offset("#define PT_R7 ", struct pt_regs, regs[7]); + offset("#define PT_R8 ", struct pt_regs, regs[8]); + offset("#define PT_R9 ", struct pt_regs, regs[9]); + offset("#define PT_R10 ", struct pt_regs, regs[10]); + offset("#define PT_R11 ", struct pt_regs, regs[11]); + offset("#define PT_R12 ", struct pt_regs, regs[12]); + offset("#define PT_R13 ", struct pt_regs, regs[13]); + offset("#define PT_R14 ", struct pt_regs, regs[14]); + offset("#define PT_R15 ", struct pt_regs, regs[15]); + offset("#define PT_R16 ", struct pt_regs, regs[16]); + offset("#define PT_R17 ", struct pt_regs, regs[17]); + offset("#define PT_R18 ", struct pt_regs, regs[18]); + offset("#define PT_R19 ", struct pt_regs, regs[19]); + offset("#define PT_R20 ", struct pt_regs, regs[20]); + offset("#define PT_R21 ", struct pt_regs, regs[21]); + offset("#define PT_R22 ", struct pt_regs, regs[22]); + offset("#define PT_R23 ", struct pt_regs, regs[23]); + offset("#define PT_R24 ", struct pt_regs, regs[24]); + offset("#define PT_R25 ", struct pt_regs, regs[25]); + offset("#define PT_R26 ", struct pt_regs, regs[26]); + offset("#define PT_R27 ", struct pt_regs, regs[27]); + offset("#define PT_R28 ", struct pt_regs, regs[28]); + offset("#define PT_R29 ", struct pt_regs, regs[29]); + offset("#define PT_R30 ", struct pt_regs, regs[30]); + offset("#define PT_R31 ", struct pt_regs, regs[31]); + offset("#define PT_LO ", struct pt_regs, lo); + offset("#define PT_HI ", struct pt_regs, hi); + offset("#define PT_EPC ", struct pt_regs, cp0_epc); + offset("#define PT_BVADDR ", struct pt_regs, cp0_badvaddr); + offset("#define PT_STATUS ", struct pt_regs, cp0_status); + offset("#define PT_CAUSE ", struct pt_regs, cp0_cause); + size("#define PT_SIZE ", struct pt_regs); + linefeed; +} + +void output_task_defines(void) +{ + text("/* MIPS task_struct offsets. */"); + offset("#define TASK_STATE ", struct task_struct, state); + offset("#define TASK_THREAD_INFO ", struct task_struct, thread_info); + offset("#define TASK_FLAGS ", struct task_struct, flags); + offset("#define TASK_MM ", struct task_struct, mm); + offset("#define TASK_PID ", struct task_struct, pid); + size( "#define TASK_STRUCT_SIZE ", struct task_struct); + linefeed; +} + +void output_thread_info_defines(void) +{ + text("/* MIPS thread_info offsets. */"); + offset("#define TI_TASK ", struct thread_info, task); + offset("#define TI_EXEC_DOMAIN ", struct thread_info, exec_domain); + offset("#define TI_FLAGS ", struct thread_info, flags); + offset("#define TI_CPU ", struct thread_info, cpu); + offset("#define TI_PRE_COUNT ", struct thread_info, preempt_count); + offset("#define TI_ADDR_LIMIT ", struct thread_info, addr_limit); + offset("#define TI_RESTART_BLOCK ", struct thread_info, restart_block); + linefeed; +} + +void output_thread_defines(void) +{ + text("/* MIPS specific thread_struct offsets. */"); + offset("#define THREAD_REG16 ", struct task_struct, thread.reg16); + offset("#define THREAD_REG17 ", struct task_struct, thread.reg17); + offset("#define THREAD_REG18 ", struct task_struct, thread.reg18); + offset("#define THREAD_REG19 ", struct task_struct, thread.reg19); + offset("#define THREAD_REG20 ", struct task_struct, thread.reg20); + offset("#define THREAD_REG21 ", struct task_struct, thread.reg21); + offset("#define THREAD_REG22 ", struct task_struct, thread.reg22); + offset("#define THREAD_REG23 ", struct task_struct, thread.reg23); + offset("#define THREAD_REG29 ", struct task_struct, thread.reg29); + offset("#define THREAD_REG30 ", struct task_struct, thread.reg30); + offset("#define THREAD_REG31 ", struct task_struct, thread.reg31); + offset("#define THREAD_STATUS ", struct task_struct, \ + thread.cp0_status); + offset("#define THREAD_FPU ", struct task_struct, thread.fpu); + offset("#define THREAD_BVADDR ", struct task_struct, \ + thread.cp0_badvaddr); + offset("#define THREAD_BUADDR ", struct task_struct, \ + thread.cp0_baduaddr); + offset("#define THREAD_ECODE ", struct task_struct, \ + thread.error_code); + offset("#define THREAD_TRAPNO ", struct task_struct, thread.trap_no); + offset("#define THREAD_MFLAGS ", struct task_struct, thread.mflags); + offset("#define THREAD_TRAMP ", struct task_struct, \ + thread.irix_trampoline); + offset("#define THREAD_OLDCTX ", struct task_struct, \ + thread.irix_oldctx); + linefeed; +} + +void output_mm_defines(void) +{ + text("/* Linux mm_struct offsets. */"); + offset("#define MM_USERS ", struct mm_struct, mm_users); + offset("#define MM_PGD ", struct mm_struct, pgd); + offset("#define MM_CONTEXT ", struct mm_struct, context); + linefeed; + constant("#define _PAGE_SIZE ", PAGE_SIZE); + constant("#define _PGD_ORDER ", PGD_ORDER); + constant("#define _PGDIR_SHIFT ", PGDIR_SHIFT); + linefeed; +} + +void output_sc_defines(void) +{ + text("/* Linux sigcontext offsets. */"); + offset("#define SC_REGS ", struct sigcontext, sc_regs); + offset("#define SC_FPREGS ", struct sigcontext, sc_fpregs); + offset("#define SC_MDHI ", struct sigcontext, sc_mdhi); + offset("#define SC_MDLO ", struct sigcontext, sc_mdlo); + offset("#define SC_PC ", struct sigcontext, sc_pc); + offset("#define SC_STATUS ", struct sigcontext, sc_status); + offset("#define SC_FPC_CSR ", struct sigcontext, sc_fpc_csr); + offset("#define SC_FPC_EIR ", struct sigcontext, sc_fpc_eir); + offset("#define SC_CAUSE ", struct sigcontext, sc_cause); + offset("#define SC_BADVADDR ", struct sigcontext, sc_badvaddr); + linefeed; +} + +void output_signal_defined(void) +{ + text("/* Linux signal numbers. */"); + constant("#define _SIGHUP ", SIGHUP); + constant("#define _SIGINT ", SIGINT); + constant("#define _SIGQUIT ", SIGQUIT); + constant("#define _SIGILL ", SIGILL); + constant("#define _SIGTRAP ", SIGTRAP); + constant("#define _SIGIOT ", SIGIOT); + constant("#define _SIGABRT ", SIGABRT); + constant("#define _SIGEMT ", SIGEMT); + constant("#define _SIGFPE ", SIGFPE); + constant("#define _SIGKILL ", SIGKILL); + constant("#define _SIGBUS ", SIGBUS); + constant("#define _SIGSEGV ", SIGSEGV); + constant("#define _SIGSYS ", SIGSYS); + constant("#define _SIGPIPE ", SIGPIPE); + constant("#define _SIGALRM ", SIGALRM); + constant("#define _SIGTERM ", SIGTERM); + constant("#define _SIGUSR1 ", SIGUSR1); + constant("#define _SIGUSR2 ", SIGUSR2); + constant("#define _SIGCHLD ", SIGCHLD); + constant("#define _SIGPWR ", SIGPWR); + constant("#define _SIGWINCH ", SIGWINCH); + constant("#define _SIGURG ", SIGURG); + constant("#define _SIGIO ", SIGIO); + constant("#define _SIGSTOP ", SIGSTOP); + constant("#define _SIGTSTP ", SIGTSTP); + constant("#define _SIGCONT ", SIGCONT); + constant("#define _SIGTTIN ", SIGTTIN); + constant("#define _SIGTTOU ", SIGTTOU); + constant("#define _SIGVTALRM ", SIGVTALRM); + constant("#define _SIGPROF ", SIGPROF); + constant("#define _SIGXCPU ", SIGXCPU); + constant("#define _SIGXFSZ ", SIGXFSZ); + linefeed; +} + +void output_irq_cpustat_t_defines(void) +{ + text("/* Linux irq_cpustat_t offsets. */"); + offset("#define IC_SOFTIRQ_PENDING ", irq_cpustat_t, __softirq_pending); + offset("#define IC_SYSCALL_COUNT ", irq_cpustat_t, __syscall_count); + offset("#define IC_KSOFTIRQD_TASK ", irq_cpustat_t, __ksoftirqd_task); + size("#define IC_IRQ_CPUSTAT_T ", irq_cpustat_t); + linefeed; +} diff -Nru a/arch/mips64/kernel/pci-dma.c b/arch/mips64/kernel/pci-dma.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips64/kernel/pci-dma.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,62 @@ +/* + * 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) 2000 Ani Joshi + * Copyright (C) 2000, 2001 Ralf Baechle + * swiped from i386, and cloned for MIPS by Geert, polished by Ralf. + */ +#include +#include +#include +#include +#include +#include + +#include + +#ifndef UNCAC_BASE /* Hack ... */ +#define UNCAC_BASE 0x9000000000000000UL +#endif + +void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, + dma_addr_t * dma_handle) +{ + void *ret; + int gfp = GFP_ATOMIC; + struct pci_bus *bus = NULL; + +#ifdef CONFIG_ISA + if (hwdev == NULL || hwdev->dma_mask != 0xffffffff) + gfp |= GFP_DMA; +#endif + ret = (void *) __get_free_pages(gfp, get_order(size)); + + if (ret != NULL) { + memset(ret, 0, size); + if (hwdev) + bus = hwdev->bus; + *dma_handle = bus_to_baddr(bus, __pa(ret)); +#ifdef CONFIG_NONCOHERENT_IO + dma_cache_wback_inv((unsigned long) ret, size); + ret = UNCAC_ADDR(ret); +#endif + } + + return ret; +} + +void pci_free_consistent(struct pci_dev *hwdev, size_t size, + void *vaddr, dma_addr_t dma_handle) +{ + unsigned long addr = (unsigned long) vaddr; + +#ifdef CONFIG_NONCOHERENT_IO + addr = CAC_ADDR(addr); +#endif + free_pages(addr, get_order(size)); +} + +EXPORT_SYMBOL(pci_alloc_consistent); +EXPORT_SYMBOL(pci_free_consistent); diff -Nru a/arch/mips64/kernel/proc.c b/arch/mips64/kernel/proc.c --- a/arch/mips64/kernel/proc.c Tue Jul 1 18:44:38 2003 +++ b/arch/mips64/kernel/proc.c Tue Jul 1 18:44:38 2003 @@ -1,76 +1,143 @@ /* - * 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. + * linux/arch/mips/kernel/proc.c * - * Copyright (C) 1995, 1996, 1999, 2001 Ralf Baechle - * Copyright (C) 2001 MIPS Technologies, Inc. + * Copyright (C) 1995, 1996, 2001 Ralf Baechle + * Copyright (C) 2001 MIPS Technologies, Inc. */ +#include #include #include #include -#include +#include #include +#include #include #include #include -extern unsigned long unaligned_instructions; unsigned int vced_count, vcei_count; -/* - * BUFFER is PAGE_SIZE bytes long. - * - * Currently /proc/cpuinfo is being abused to print data about the - * number of date/instruction cacheflushes. - */ -int get_cpuinfo(char *buffer) +static const char *cpu_name[] = { + [CPU_UNKNOWN] "unknown", + [CPU_R2000] "R2000", + [CPU_R3000] "R3000", + [CPU_R3000A] "R3000A", + [CPU_R3041] "R3041", + [CPU_R3051] "R3051", + [CPU_R3052] "R3052", + [CPU_R3081] "R3081", + [CPU_R3081E] "R3081E", + [CPU_R4000PC] "R4000PC", + [CPU_R4000SC] "R4000SC", + [CPU_R4000MC] "R4000MC", + [CPU_R4200] "R4200", + [CPU_R4400PC] "R4400PC", + [CPU_R4400SC] "R4400SC", + [CPU_R4400MC] "R4400MC", + [CPU_R4600] "R4600", + [CPU_R6000] "R6000", + [CPU_R6000A] "R6000A", + [CPU_R8000] "R8000", + [CPU_R10000] "R10000", + [CPU_R4300] "R4300", + [CPU_R4650] "R4650", + [CPU_R4700] "R4700", + [CPU_R5000] "R5000", + [CPU_R5000A] "R5000A", + [CPU_R4640] "R4640", + [CPU_NEVADA] "Nevada", + [CPU_RM7000] "RM7000", + [CPU_R5432] "R5432", + [CPU_4KC] "MIPS 4Kc", + [CPU_5KC] "MIPS 5Kc", + [CPU_R4310] "R4310", + [CPU_SB1] "SiByte SB1", + [CPU_TX3912] "TX3912", + [CPU_TX3922] "TX3922", + [CPU_TX3927] "TX3927", + [CPU_AU1000] "Au1000", + [CPU_AU1500] "Au1500", + [CPU_4KEC] "MIPS 4KEc", + [CPU_4KSC] "MIPS 4KSc", + [CPU_VR41XX] "NEC Vr41xx", + [CPU_R5500] "R5500", + [CPU_TX49XX] "TX49xx", + [CPU_20KC] "MIPS 20Kc", + [CPU_VR4111] "NEC VR4111", + [CPU_VR4121] "NEC VR4121", + [CPU_VR4122] "NEC VR4122", + [CPU_VR4131] "NEC VR4131", + [CPU_VR4181] "NEC VR4181", + [CPU_VR4181A] "NEC VR4181A", + [CPU_SR71000] "Sandcraft SR71000" +}; + + +static int show_cpuinfo(struct seq_file *m, void *v) { + unsigned int version = current_cpu_data.processor_id; + unsigned int fp_vers = current_cpu_data.fpu_id; + unsigned long n = (unsigned long) v - 1; char fmt [64]; - size_t len; - len = sprintf(buffer, "cpu\t\t\t: MIPS\n"); -#if 0 - len += sprintf(buffer + len, "cpu model\t\t: %s V%d.%d\n", - cpu_name[mips_cputype <= CPU_LAST ? - mips_cputype : - CPU_UNKNOWN], - (version >> 4) & 0x0f, - version & 0x0f); - len += sprintf(buffer + len, "system type\t\t: %s %s\n", - mach_group_names[mips_machgroup], - mach_group_to_name[mips_machgroup][mips_machtype]); +#ifdef CONFIG_SMP + if (!CPUMASK_TSTB(cpu_online_map, n)) + return 0; #endif - len += sprintf(buffer + len, "BogoMIPS\t\t: %lu.%02lu\n", - (loops_per_jiffy + 2500) / (500000/HZ), - ((loops_per_jiffy + 2500) / (5000/HZ)) % 100); - len += sprintf(buffer + len, "Number of cpus\t\t: %d\n", smp_num_cpus); -#if defined (__MIPSEB__) - len += sprintf(buffer + len, "byteorder\t\t: big endian\n"); -#endif -#if defined (__MIPSEL__) - len += sprintf(buffer + len, "byteorder\t\t: little endian\n"); -#endif - len += sprintf(buffer + len, "unaligned accesses\t: %lu\n", - unaligned_instructions); - len += sprintf(buffer + len, "wait instruction\t: %s\n", - wait_available ? "yes" : "no"); - len += sprintf(buffer + len, "microsecond timers\t: %s\n", - cyclecounter_available ? "yes" : "no"); - len += sprintf(buffer + len, "extra interrupt vector\t: %s\n", - dedicated_iv_available ? "yes" : "no"); - len += sprintf(buffer + len, "hardware watchpoint\t: %s\n", - watch_available ? "yes" : "no"); + + /* + * For the first processor also print the system type + */ + if (n == 0) + seq_printf(m, "system type\t\t: %s\n", get_system_type()); + + seq_printf(m, "processor\t\t: %ld\n", n); + sprintf(fmt, "cpu model\t\t: %%s V%%d.%%d%s\n", + cpu_has_fpu ? " FPU V%d.%d" : ""); + seq_printf(m, fmt, cpu_name[current_cpu_data.cputype <= CPU_LAST ? + current_cpu_data.cputype : CPU_UNKNOWN], + (version >> 4) & 0x0f, version & 0x0f, + (fp_vers >> 4) & 0x0f, fp_vers & 0x0f); + seq_printf(m, "BogoMIPS\t\t: %lu.%02lu\n", + loops_per_jiffy / (500000/HZ), + (loops_per_jiffy / (5000/HZ)) % 100); + seq_printf(m, "wait instruction\t: %s\n", cpu_wait ? "yes" : "no"); + seq_printf(m, "microsecond timers\t: %s\n", + cpu_has_counter ? "yes" : "no"); + seq_printf(m, "tlb_entries\t\t: %d\n", current_cpu_data.tlbsize); + seq_printf(m, "extra interrupt vector\t: %s\n", + cpu_has_divec ? "yes" : "no"); + seq_printf(m, "hardware watchpoint\t: %s\n", + cpu_has_watch ? "yes" : "no"); sprintf(fmt, "VCE%%c exceptions\t\t: %s\n", - vce_available ? "%d" : "not available"); - len += sprintf(buffer + len, fmt, 'D', vced_count); - len += sprintf(buffer + len, fmt, 'I', vcei_count); + cpu_has_vce ? "%d" : "not available"); + seq_printf(m, fmt, 'D', vced_count); + seq_printf(m, fmt, 'I', vcei_count); - return len; + return 0; } -void init_irq_proc(void) +static void *c_start(struct seq_file *m, loff_t *pos) { - /* Nothing, for now. */ + unsigned long i = *pos; + + return i < NR_CPUS ? (void *) (i + 1) : NULL; } + +static void *c_next(struct seq_file *m, void *v, loff_t *pos) +{ + ++*pos; + return c_start(m, pos); +} + +static void c_stop(struct seq_file *m, void *v) +{ +} + +struct seq_operations cpuinfo_op = { + .start = c_start, + .next = c_next, + .stop = c_stop, + .show = show_cpuinfo, +}; diff -Nru a/arch/mips64/kernel/process.c b/arch/mips64/kernel/process.c --- a/arch/mips64/kernel/process.c Tue Jul 1 18:44:33 2003 +++ b/arch/mips64/kernel/process.c Tue Jul 1 18:44:33 2003 @@ -15,9 +15,12 @@ #include #include #include +#include #include #include #include +#include +#include #include #include @@ -28,78 +31,88 @@ #include #include #include +#include +#include +#include -asmlinkage int cpu_idle(void) +/* + * We use this if we don't have any better idle routine.. + * (This to kill: kernel/platform.c. + */ +void default_idle (void) +{ +} + +/* + * The idle thread. There's no useful work to be done, so just try to conserve + * power and have a low exit latency (ie sit in a loop waiting for somebody to + * say that they'd like to reschedule) + */ +ATTRIB_NORET void cpu_idle(void) { /* endless idle loop with no priority at all */ - init_idle(); - current->nice = 20; while (1) { while (!need_resched()) - if (wait_available) - __asm__("wait"); + if (cpu_wait) + (*cpu_wait)(); schedule(); - check_pgt_cache(); } } -struct task_struct *last_task_used_math = NULL; - asmlinkage void ret_from_fork(void); +void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp) +{ + unsigned long status; + + /* New thread loses kernel privileges. */ + status = regs->cp0_status & ~(ST0_CU0|ST0_FR|ST0_KSU); + status |= KSU_USER; + status |= (current->thread.mflags & MF_32BIT_REGS) ? 0 : ST0_FR; + regs->cp0_status = status; + current->used_math = 0; + loose_fpu(); + regs->cp0_epc = pc; + regs->regs[29] = sp; + current_thread_info()->addr_limit = USER_DS; +} + void exit_thread(void) { - /* Forget lazy fpu state */ - if (IS_FPU_OWNER()) { - set_cp0_status(ST0_CU1, ST0_CU1); - __asm__ __volatile__("cfc1\t$0,$31"); - CLEAR_FPU_OWNER(); - } } void flush_thread(void) { - /* Forget lazy fpu state */ - if (IS_FPU_OWNER()) { - set_cp0_status(ST0_CU1, ST0_CU1); - __asm__ __volatile__("cfc1\t$0,$31"); - CLEAR_FPU_OWNER(); - } } int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, - unsigned long unused, - struct task_struct * p, struct pt_regs * regs) + unsigned long unused, struct task_struct *p, + struct pt_regs *regs) { - struct pt_regs * childregs; + struct thread_info *ti = p->thread_info; + struct pt_regs *childregs; long childksp; - childksp = (unsigned long)p + KERNEL_STACK_SIZE - 32; + childksp = (unsigned long)ti + KERNEL_STACK_SIZE - 32; - if (IS_FPU_OWNER()) { + if (is_fpu_owner()) { save_fp(p); } + /* set up new TSS. */ childregs = (struct pt_regs *) childksp - 1; *childregs = *regs; childregs->regs[7] = 0; /* Clear error flag */ - if (current->personality == PER_LINUX) { - childregs->regs[2] = 0; /* Child gets zero as return value */ - regs->regs[2] = p->pid; - } else { - /* Under IRIX things are a little different. */ - childregs->regs[2] = 0; - childregs->regs[3] = 1; - regs->regs[2] = p->pid; - regs->regs[3] = 0; - } + childregs->regs[2] = 0; /* Child gets zero as return value */ + regs->regs[2] = p->pid; + if (childregs->cp0_status & ST0_CU0) { - childregs->regs[28] = (unsigned long) p; + childregs->regs[28] = (unsigned long) ti; childregs->regs[29] = childksp; - p->thread.current_ds = KERNEL_DS; + ti->addr_limit = KERNEL_DS; } else { childregs->regs[29] = usp; - p->thread.current_ds = USER_DS; + ti->addr_limit = USER_DS; } p->thread.reg29 = (unsigned long) childregs; p->thread.reg31 = (unsigned long) ret_from_fork; @@ -108,9 +121,9 @@ * New tasks lose permission to use the fpu. This accelerates context * switching for most programs since they don't use the fpu. */ - p->thread.cp0_status = read_32bit_cp0_register(CP0_STATUS) & - ~(ST0_CU3|ST0_CU2|ST0_CU1|ST0_KSU); - childregs->cp0_status &= ~(ST0_CU3|ST0_CU2|ST0_CU1); + p->thread.cp0_status = read_c0_status() & ~(ST0_CU2|ST0_CU1|ST0_KSU); + childregs->cp0_status &= ~(ST0_CU2|ST0_CU1); + p->set_child_tid = p->clear_child_tid = NULL; return 0; } @@ -118,32 +131,8 @@ /* Fill in the fpu structure for a core dump.. */ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r) { - /* We actually store the FPU info in the task->thread - * area. - */ - if(regs->cp0_status & ST0_CU1) { - memcpy(r, ¤t->thread.fpu, sizeof(current->thread.fpu)); - return 1; - } - return 0; /* Task didn't use the fpu at all. */ -} - -/* Fill in the user structure for a core dump.. */ -void dump_thread(struct pt_regs *regs, struct user *dump) -{ - dump->magic = CMAGIC; - dump->start_code = current->mm->start_code; - dump->start_data = current->mm->start_data; - dump->start_stack = regs->regs[29] & ~(PAGE_SIZE - 1); - dump->u_tsize = (current->mm->end_code - dump->start_code) - >> PAGE_SHIFT; - dump->u_dsize = (current->mm->brk + (PAGE_SIZE - 1) - dump->start_data) - >> PAGE_SHIFT; - dump->u_ssize = (current->mm->start_stack - dump->start_stack + - PAGE_SIZE - 1) >> PAGE_SHIFT; - memcpy(&dump->regs[0], regs, sizeof(struct pt_regs)); - memcpy(&dump->regs[EF_SIZE/4], ¤t->thread.fpu, - sizeof(current->thread.fpu)); + memcpy(r, ¤t->thread.fpu, sizeof(current->thread.fpu)); + return 1; } /* @@ -154,29 +143,106 @@ int retval; __asm__ __volatile__( - "move\t$6, $sp\n\t" - "move\t$4, %5\n\t" - "li\t$2, %1\n\t" - "syscall\n\t" - "beq\t$6, $sp, 1f\n\t" - "move\t$4, %3\n\t" - "jalr\t%4\n\t" - "move\t$4, $2\n\t" - "li\t$2, %2\n\t" - "syscall\n" - "1:\tmove\t%0, $2" - :"=r" (retval) - :"i" (__NR_clone), "i" (__NR_exit), "r" (arg), "r" (fn), - "r" (flags | CLONE_VM | CLONE_UNTRACED) - - /* The called subroutine might have destroyed any of the - * at, result, argument or temporary registers ... */ - :"$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", - "$9","$10","$11","$12","$13","$14","$15","$24","$25"); + " move $6, $sp \n" + " move $4, %5 \n" + " li $2, %1 \n" + " syscall \n" + " beq $6, $sp, 1f \n" + " move $4, %3 \n" + " jalr %4 \n" + " move $4, $2 \n" + " li $2, %2 \n" + " syscall \n" + "1: move %0, $2" + : "=r" (retval) + : "i" (__NR_clone), "i" (__NR_exit), "r" (arg), "r" (fn), + "r" (flags | CLONE_VM | CLONE_UNTRACED) + /* + * The called subroutine might have destroyed any of the + * at, result, argument or temporary registers ... + */ + : "$2", "$3", "$4", "$5", "$6", "$7", "$8", + "$9","$10","$11","$12","$13","$14","$15","$24","$25","$31"); return retval; } +struct mips_frame_info { + int frame_offset; + int pc_offset; +}; +static struct mips_frame_info schedule_frame; +static struct mips_frame_info schedule_timeout_frame; +static struct mips_frame_info sleep_on_frame; +static struct mips_frame_info sleep_on_timeout_frame; +static struct mips_frame_info wait_for_completion_frame; +static int mips_frame_info_initialized; +static int __init get_frame_info(struct mips_frame_info *info, void *func) +{ + int i; + union mips_instruction *ip = (union mips_instruction *)func; + info->pc_offset = -1; + info->frame_offset = -1; + for (i = 0; i < 128; i++, ip++) { + /* if jal, jalr, jr, stop. */ + if (ip->j_format.opcode == jal_op || + (ip->r_format.opcode == spec_op && + (ip->r_format.func == jalr_op || + ip->r_format.func == jr_op))) + break; + if (ip->i_format.opcode == sd_op && + ip->i_format.rs == 29) { + /* sd $ra, offset($sp) */ + if (ip->i_format.rt == 31) { + if (info->pc_offset != -1) + break; + info->pc_offset = + ip->i_format.simmediate / sizeof(long); + } + /* sd $s8, offset($sp) */ + if (ip->i_format.rt == 30) { + if (info->frame_offset != -1) + break; + info->frame_offset = + ip->i_format.simmediate / sizeof(long); + } + } + } + if (info->pc_offset == -1 || info->frame_offset == -1) { + printk("Can't analyze prologue code at %p\n", func); + info->pc_offset = -1; + info->frame_offset = -1; + return -1; + } + + return 0; +} +void __init frame_info_init(void) +{ + mips_frame_info_initialized = + !get_frame_info(&schedule_frame, schedule) && + !get_frame_info(&schedule_timeout_frame, schedule_timeout) && + !get_frame_info(&sleep_on_frame, sleep_on) && + !get_frame_info(&sleep_on_timeout_frame, sleep_on_timeout) && + !get_frame_info(&wait_for_completion_frame, wait_for_completion); +} + +/* + * Return saved PC of a blocked thread. + */ +unsigned long thread_saved_pc(struct thread_struct *t) +{ + extern void ret_from_fork(void); + + /* New born processes are a special case */ + if (t->reg31 == (unsigned long) ret_from_fork) + return t->reg31; + + if (schedule_frame.pc_offset < 0) + return 0; + return ((unsigned long *)t->reg29)[schedule_frame.pc_offset]; +} + /* * These bracket the sleeping functions.. */ @@ -193,6 +259,8 @@ if (!p || p == current || p->state == TASK_RUNNING) return 0; + if (!mips_frame_info_initialized) + return 0; pc = thread_saved_pc(&p->thread); if (pc < first_sched || pc >= last_sched) goto out; @@ -205,30 +273,33 @@ goto schedule_timeout_caller; if (pc >= (unsigned long)interruptible_sleep_on) goto schedule_caller; + if (pc >= (unsigned long)wait_for_completion) + goto schedule_caller; goto schedule_timeout_caller; schedule_caller: - frame = ((unsigned long *)p->thread.reg30)[10]; - pc = ((unsigned long *)frame)[7]; + frame = ((unsigned long *)p->thread.reg30)[schedule_frame.frame_offset]; + if (pc >= (unsigned long) sleep_on) + pc = ((unsigned long *)frame)[sleep_on_frame.pc_offset]; + else + pc = ((unsigned long *)frame)[wait_for_completion_frame.pc_offset]; goto out; schedule_timeout_caller: /* Must be schedule_timeout ... */ - pc = ((unsigned long *)p->thread.reg30)[11]; - frame = ((unsigned long *)p->thread.reg30)[10]; + frame = ((unsigned long *)p->thread.reg30)[schedule_frame.frame_offset]; /* The schedule_timeout frame ... */ - pc = ((unsigned long *)frame)[9]; - frame = ((unsigned long *)frame)[8]; + pc = ((unsigned long *)frame)[schedule_timeout_frame.pc_offset]; if (pc >= first_sched && pc < last_sched) { - /* schedule_timeout called by interruptible_sleep_on_timeout */ - pc = ((unsigned long *)frame)[7]; - frame = ((unsigned long *)frame)[6]; + /* schedule_timeout called by [interruptible_]sleep_on_timeout */ + frame = ((unsigned long *)frame)[schedule_timeout_frame.frame_offset]; + pc = ((unsigned long *)frame)[sleep_on_timeout_frame.pc_offset]; } out: - if (current->thread.mflags & MF_32BIT) /* Kludge for 32-bit ps */ + if (current->thread.mflags & MF_32BIT_REGS) /* Kludge for 32-bit ps */ pc &= 0xffffffff; return pc; diff -Nru a/arch/mips64/kernel/ptrace.c b/arch/mips64/kernel/ptrace.c --- a/arch/mips64/kernel/ptrace.c Tue Jul 1 18:44:37 2003 +++ b/arch/mips64/kernel/ptrace.c Tue Jul 1 18:44:37 2003 @@ -21,12 +21,16 @@ #include #include #include +#include +#include +#include #include #include #include #include #include +#include /* * Called by kernel/ptrace.c when detaching.. @@ -53,6 +57,8 @@ /* are we already being traced? */ if (current->ptrace & PT_PTRACED) goto out; + if ((ret = security_ptrace(current->parent, current))) + goto out; /* set the ptrace bit in the process flags. */ current->ptrace |= PT_PTRACED; ret = 0; @@ -75,18 +81,14 @@ ret = ptrace_attach(child); goto out_tsk; } - ret = -ESRCH; - if (!(child->ptrace & PT_PTRACED)) - goto out_tsk; - if (child->state != TASK_STOPPED) { - if (request != PTRACE_KILL) - goto out_tsk; - } - if (child->p_pptr != current) + + ret = ptrace_check_attach(child, request == PTRACE_KILL); + if (ret < 0) goto out_tsk; + switch (request) { /* when I and D space are separate, these will need to be fixed. */ - case PTRACE_PEEKTEXT: /* read word at location addr. */ + case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_PEEKDATA: { unsigned int tmp; int copied; @@ -104,7 +106,7 @@ struct pt_regs *regs; unsigned int tmp; - regs = (struct pt_regs *) ((unsigned long) child + + regs = (struct pt_regs *) ((unsigned long) child->thread_info + KERNEL_STACK_SIZE - 32 - sizeof(struct pt_regs)); ret = 0; @@ -114,28 +116,19 @@ break; case FPR_BASE ... FPR_BASE + 31: if (child->used_math) { - unsigned long *fregs = - (void *) child->thread.fpu.hard.fp_regs; - -#ifndef CONFIG_SMP - if (last_task_used_math == child) { - set_cp0_status(ST0_CU1, ST0_CU1); - save_fp(child); - set_cp0_status(ST0_CU1, 0); - last_task_used_math = NULL; - } -#endif + unsigned long long *fregs; + fregs = (unsigned long long *)get_fpu_regs(child); /* * The odd registers are actually the high * order bits of the values stored in the even - * registers. + * registers - unless we're using r2k_switch.S. */ if (addr & 1) tmp = (unsigned long) (fregs[((addr & ~1) - 32)] >> 32); else tmp = (unsigned long) (fregs[(addr - 32)] & 0xffffffff); } else { - tmp = -EIO; + tmp = -1; /* FP not yet used */ } break; case PC: @@ -154,14 +147,17 @@ tmp = regs->lo; break; case FPC_CSR: - tmp = child->thread.fpu.hard.control; + if (cpu_has_fpu) + tmp = child->thread.fpu.hard.control; + else + tmp = child->thread.fpu.soft.sr; break; case FPC_EIR: { /* implementation / version register */ unsigned int flags; - local_save_flags(flags); - set_cp0_status(ST0_CU1, ST0_CU1); + flags = read_c0_status(); + __enable_fpu(); __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp)); - local_irq_restore(flags); + write_c0_status(flags); break; } default: @@ -184,7 +180,7 @@ case PTRACE_POKEUSR: { struct pt_regs *regs; ret = 0; - regs = (struct pt_regs *) ((unsigned long) child + + regs = (struct pt_regs *) ((unsigned long) child->thread_info + KERNEL_STACK_SIZE - 32 - sizeof(struct pt_regs)); switch (addr) { @@ -192,19 +188,9 @@ regs->regs[addr] = data; break; case FPR_BASE ... FPR_BASE + 31: { - unsigned long *fregs = - (void *) child->thread.fpu.hard.fp_regs; - if (child->used_math) { -#ifndef CONFIG_SMP - if (last_task_used_math == child) { - set_cp0_status(ST0_CU1, ST0_CU1); - save_fp(child); - set_cp0_status(ST0_CU1, 0); - last_task_used_math = NULL; - regs->cp0_status &= ~ST0_CU1; - } -#endif - } else { + unsigned long long *fregs; + fregs = (unsigned long long *)get_fpu_regs(child); + if (!child->used_math) { /* FP not yet used */ memset(&child->thread.fpu.hard, ~0, sizeof(child->thread.fpu.hard)); @@ -217,10 +203,12 @@ */ if (addr & 1) { fregs[(addr & ~1) - FPR_BASE] &= 0xffffffff; - fregs[(addr & ~1) - FPR_BASE] |= ((unsigned long) data) << 32; + fregs[(addr & ~1) - FPR_BASE] |= ((unsigned long long) data) << 32; } else { fregs[addr - FPR_BASE] &= ~0xffffffffLL; - fregs[addr - FPR_BASE] |= data; + /* Must cast, lest sign extension fill upper + bits! */ + fregs[addr - FPR_BASE] |= (unsigned int)data; } break; } @@ -234,24 +222,29 @@ regs->lo = data; break; case FPC_CSR: - child->thread.fpu.hard.control = data; + if (cpu_has_fpu) + child->thread.fpu.hard.control = data; + else + child->thread.fpu.soft.sr = data; break; default: /* The rest are not allowed. */ ret = -EIO; break; } - goto out; + break; } case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ case PTRACE_CONT: { /* restart after signal. */ ret = -EIO; if ((unsigned int) data > _NSIG) break; - if (request == PTRACE_SYSCALL) - child->ptrace |= PT_TRACESYS; - else - child->ptrace &= ~PT_TRACESYS; + if (request == PTRACE_SYSCALL) { + set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); + } + else { + clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); + } child->exit_code = data; wake_up_process(child); ret = 0; @@ -259,8 +252,8 @@ } /* - * make the child exit. Best I can do is send it a sigkill. - * perhaps it should be put in the status that it wants to + * make the child exit. Best I can do is send it a sigkill. + * perhaps it should be put in the status that it wants to * exit. */ case PTRACE_KILL: { @@ -281,7 +274,7 @@ } out_tsk: - free_task_struct(child); + put_task_struct(child); out: unlock_kernel(); return ret; @@ -303,6 +296,8 @@ /* are we already being traced? */ if (current->ptrace & PT_PTRACED) goto out; + if ((ret = security_ptrace(current->parent, current))) + goto out; /* set the ptrace bit in the process flags. */ current->ptrace |= PT_PTRACED; ret = 0; @@ -319,25 +314,20 @@ ret = -EPERM; if (pid == 1) /* you may not mess with init */ - goto out; + goto out_tsk; if (request == PTRACE_ATTACH) { ret = ptrace_attach(child); goto out_tsk; } - ret = -ESRCH; - if (!(child->ptrace & PT_PTRACED)) - goto out_tsk; - if (child->state != TASK_STOPPED) { - if (request != PTRACE_KILL) - goto out_tsk; - } - if (child->p_pptr != current) + + ret = ptrace_check_attach(child, request == PTRACE_KILL); + if (ret < 0) goto out_tsk; switch (request) { /* when I and D space are separate, these will need to be fixed. */ - case PTRACE_PEEKTEXT: /* read word at location addr. */ + case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_PEEKDATA: { unsigned long tmp; int copied; @@ -355,7 +345,7 @@ struct pt_regs *regs; unsigned long tmp; - regs = (struct pt_regs *) ((unsigned long) child + + regs = (struct pt_regs *) ((unsigned long) child->thread_info + KERNEL_STACK_SIZE - 32 - sizeof(struct pt_regs)); ret = 0; @@ -365,26 +355,8 @@ break; case FPR_BASE ... FPR_BASE + 31: if (child->used_math) { - unsigned long long *fregs - = (unsigned long long *) - &child->thread.fpu.hard.fp_regs[0]; -#ifndef CONFIG_SMP - if (last_task_used_math == child) { - set_cp0_status(ST0_CU1, ST0_CU1); - save_fp(child); - set_cp0_status(ST0_CU1, 0); - last_task_used_math = NULL; - } -#endif - /* - * The odd registers are actually the high - * order bits of the values stored in the even - * registers. - */ - if (addr & 1) - tmp = (unsigned long) (fregs[((addr & ~1) - 32)] >> 32); - else - tmp = (unsigned long) (fregs[(addr - 32)] & 0xffffffff); + unsigned long *fregs = get_fpu_regs(child); + tmp = fregs[addr - FPR_BASE]; } else { tmp = -EIO; } @@ -405,14 +377,17 @@ tmp = regs->lo; break; case FPC_CSR: - tmp = child->thread.fpu.hard.control; + if (cpu_has_fpu) + tmp = child->thread.fpu.hard.control; + else + tmp = child->thread.fpu.soft.sr; break; case FPC_EIR: { /* implementation / version register */ unsigned int flags; - local_save_flags(flags); - set_cp0_status(ST0_CU1, ST0_CU1); + flags = read_c0_status(); + __enable_fpu(); __asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp)); - local_irq_restore(flags); + write_c0_status(flags); break; } default: @@ -435,7 +410,7 @@ case PTRACE_POKEUSR: { struct pt_regs *regs; ret = 0; - regs = (struct pt_regs *) ((unsigned long) child + + regs = (struct pt_regs *) ((unsigned long) child->thread_info + KERNEL_STACK_SIZE - 32 - sizeof(struct pt_regs)); switch (addr) { @@ -443,36 +418,14 @@ regs->regs[addr] = data; break; case FPR_BASE ... FPR_BASE + 31: { - unsigned long *fregs = - (void *) child->thread.fpu.hard.fp_regs; - if (child->used_math) { -#ifndef CONFIG_SMP - if (last_task_used_math == child) { - set_cp0_status(ST0_CU1, ST0_CU1); - save_fp(child); - set_cp0_status(ST0_CU1, 0); - last_task_used_math = NULL; - regs->cp0_status &= ~ST0_CU1; - } -#endif - } else { + unsigned long *fregs = get_fpu_regs(child); + if (!child->used_math) { /* FP not yet used */ memset(&child->thread.fpu.hard, ~0, sizeof(child->thread.fpu.hard)); child->thread.fpu.hard.control = 0; } - /* - * The odd registers are actually the high order bits - * of the values stored in the even registers - unless - * we're using r2k_switch.S. - */ - if (addr & 1) { - fregs[(addr & ~1) - FPR_BASE] &= 0xffffffff; - fregs[(addr & ~1) - FPR_BASE] |= ((unsigned long) data) << 32; - } else { - fregs[addr - FPR_BASE] &= ~0xffffffffLL; - fregs[addr - FPR_BASE] |= data; - } + fregs[addr - FPR_BASE] = data; break; } case PC: @@ -485,24 +438,29 @@ regs->lo = data; break; case FPC_CSR: - child->thread.fpu.hard.control = data; + if (cpu_has_fpu) + child->thread.fpu.hard.control = data; + else + child->thread.fpu.soft.sr = data; break; default: /* The rest are not allowed. */ ret = -EIO; break; } - goto out; + break; } case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ case PTRACE_CONT: { /* restart after signal. */ ret = -EIO; if ((unsigned long) data > _NSIG) break; - if (request == PTRACE_SYSCALL) - child->ptrace |= PT_TRACESYS; - else - child->ptrace &= ~PT_TRACESYS; + if (request == PTRACE_SYSCALL) { + set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); + } + else { + clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); + } child->exit_code = data; wake_up_process(child); ret = 0; @@ -510,8 +468,8 @@ } /* - * make the child exit. Best I can do is send it a sigkill. - * perhaps it should be put in the status that it wants to + * make the child exit. Best I can do is send it a sigkill. + * perhaps it should be put in the status that it wants to * exit. */ case PTRACE_KILL: { @@ -532,25 +490,47 @@ } out_tsk: - free_task_struct(child); + put_task_struct(child); out: unlock_kernel(); return ret; } -asmlinkage void syscall_trace(void) +struct task_work_bf { +#ifdef __MIPSEB__ + signed need_resched :8; + unsigned syscall_trace; /* count of syscall interceptors */ + unsigned sigpending; + unsigned notify_resume; /* request for notification on + userspace execution resumption */ +#endif +#ifdef __MIPSEL__ + unsigned notify_resume : 8; /* request for notification on + userspace execution + resumption */ + unsigned sigpending : 8; + unsigned syscall_trace : 8; /* count of syscall + interceptors */ + signed need_resched : 8; +#endif +}; + +asmlinkage void do_syscall_trace(void) { - if ((current->ptrace & (PT_PTRACED|PT_TRACESYS)) - != (PT_PTRACED|PT_TRACESYS)) + if (!test_thread_flag(TIF_SYSCALL_TRACE)) + return; + if (!(current->ptrace & PT_PTRACED)) return; /* The 0x80 provides a way for the tracing parent to distinguish between a syscall stop and SIGTRAP delivery */ current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) ? 0x80 : 0); + preempt_disable(); current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); schedule(); + preempt_enable(); /* * this isn't the same as continuing with a signal, but it will do * for normal use. strace only continues with a signal if the diff -Nru a/arch/mips64/kernel/r4k_fpu.S b/arch/mips64/kernel/r4k_fpu.S --- a/arch/mips64/kernel/r4k_fpu.S Tue Jul 1 18:44:31 2003 +++ b/arch/mips64/kernel/r4k_fpu.S Tue Jul 1 18:44:31 2003 @@ -31,7 +31,7 @@ .set noreorder /* Save floating point context */ -LEAF(save_fp_context) +LEAF(_save_fp_context) mfc0 t1, CP0_STATUS sll t2, t1,5 @@ -79,7 +79,7 @@ jr ra li v0, 0 # success - END(save_fp_context) + END(_save_fp_context) /* * Restore FPU state: @@ -90,7 +90,7 @@ * frame on the current content of c0_status, not on the content of the * stack frame which might have been changed by the user. */ -LEAF(restore_fp_context) +LEAF(_restore_fp_context) mfc0 t1, CP0_STATUS sll t0, t1,5 bgez t0, 1f @@ -139,7 +139,7 @@ ctc1 t0, fcr31 jr ra li v0, 0 # success - END(restore_fp_context) + END(_restore_fp_context) .type fault@function .ent fault diff -Nru a/arch/mips64/kernel/r4k_genex.S b/arch/mips64/kernel/r4k_genex.S --- a/arch/mips64/kernel/r4k_genex.S Tue Jul 1 18:44:36 2003 +++ b/arch/mips64/kernel/r4k_genex.S Tue Jul 1 18:44:36 2003 @@ -5,116 +5,61 @@ * * Copyright (C) 1994 - 1999 by Ralf Baechle * Copyright (C) 1999 Silicon Graphics + * Copyright (C) 2002 Maciej W. Rozycki * * Low level exception handling */ -#define __ASSEMBLY__ #include #include #include #include #include #include -#include - - .macro __build_clear_none - .endm - - .macro __build_clear_sti - STI - .endm - - .macro __build_clear_cli - CLI - .endm - - .macro __build_clear_fpe - cfc1 a1, fcr31 - li a2, ~(0x3f << 13) - and a2, a1 - ctc1 a2, fcr31 - STI - .endm - - .macro __build_clear_ade - dmfc0 t0, CP0_BADVADDR - sd t0, PT_BVADDR(sp) - KMODE - .endm - - .macro __BUILD_silent exception - .endm - - /* Gas tries to parse the PRINT argument as a string containing - string escapes and emits bogus warnings if it believes to - recognize an unknown escape code. So make the arguments - start with an n and gas will believe \n is ok ... */ - .macro __BUILD_verbose nexception - ld a1, PT_EPC(sp) - PRINT("Got \nexception at %016lx\012") - .endm - - .macro __BUILD_count exception - .set reorder - ld t0,exception_count_\exception - daddiu t0, 1 - sd t0,exception_count_\exception - .set noreorder - .comm exception_count\exception, 8, 8 - .endm - - .macro BUILD_HANDLER exception handler clear verbose - .align 5 - NESTED(handle_\exception, PT_SIZE, sp) - .set noat - SAVE_ALL -#if DEBUG_MIPS64 -jal dodebug2 -ld $4, PT_R4(sp) -ld $5, PT_R5(sp) -ld $6, PT_R6(sp) -ld $7, PT_R7(sp) -ld $2, PT_R2(sp) -#endif - __BUILD_clear_\clear - .set at - __BUILD_\verbose \exception - move a0, sp - jal do_\handler - j ret_from_sys_call - nop - END(handle_\exception) - .endm +#include +#include BUILD_HANDLER adel ade ade silent /* #4 */ BUILD_HANDLER ades ade ade silent /* #5 */ - BUILD_HANDLER ibe ibe cli silent /* #6 */ - BUILD_HANDLER dbe dbe cli silent /* #7 */ + BUILD_HANDLER ibe be cli silent /* #6 */ + BUILD_HANDLER dbe be cli silent /* #7 */ BUILD_HANDLER bp bp sti silent /* #9 */ BUILD_HANDLER ri ri sti silent /* #10 */ BUILD_HANDLER cpu cpu sti silent /* #11 */ BUILD_HANDLER ov ov sti silent /* #12 */ BUILD_HANDLER tr tr sti silent /* #13 */ BUILD_HANDLER fpe fpe fpe silent /* #15 */ + BUILD_HANDLER mdmx mdmx sti silent /* #22 */ BUILD_HANDLER watch watch sti verbose /* #23 */ + BUILD_HANDLER mcheck mcheck cli verbose /* #24 */ BUILD_HANDLER reserved reserved sti verbose /* others */ + __INIT +/* A temporary overflow handler used by check_daddi(). */ + + BUILD_HANDLER daddi_ov daddi_ov none silent /* #12 */ + + /* General exception handler for CPUs with virtual coherency exception. * - * Be careful when changing this, it has to be at most 128 bytes to fit - * into space reserved for the exception handler. + * Be careful when changing this, it has to be at most 256 (as a special + * exception) bytes to fit into space reserved for the exception handler. */ - NESTED(except_vec3_r4000, 0, sp) + .set push .set noat +NESTED(except_vec3_r4000, 0, sp) mfc0 k1, CP0_CAUSE - andi k1, k1, 0x7c li k0, 31<<2 + andi k1, k1, 0x7c + .set push + .set noreorder + .set nomacro beq k1, k0, handle_vced li k0, 14<<2 beq k1, k0, handle_vcei dsll k1, k1, 1 + .set pop ld k0, exception_handlers(k1) jr k0 @@ -125,51 +70,110 @@ * store will be re-executed. */ handle_vced: - mfc0 k0, CP0_BADVADDR + dmfc0 k0, CP0_BADVADDR li k1, -4 # Is this ... and k0, k1 # ... really needed? mtc0 zero, CP0_TAGLO cache Index_Store_Tag_D,(k0) cache Hit_Writeback_Inv_SD,(k0) - lui k0, %hi(vced_count) - lw k1, %lo(vced_count)(k0) + dla k0, vced_count + lw k1, (k0) addiu k1, 1 - sw k1, %lo(vced_count)(k0) + sw k1, (k0) eret handle_vcei: - mfc0 k0, CP0_BADVADDR + dmfc0 k0, CP0_BADVADDR cache Hit_Writeback_Inv_SD,(k0) # also cleans pi - lui k0, %hi(vcei_count) - lw k1, %lo(vcei_count)(k0) + dla k0, vcei_count + lw k1, (k0) addiu k1, 1 - sw k1, %lo(vcei_count)(k0) + sw k1, (k0) eret +END(except_vec3_r4000) + .set pop - END(except_vec3_r4000) - .set at - /* General exception vector for all other CPUs. */ - NESTED(except_vec3_generic, 0, sp) +/* General exception vector for all other CPUs. + * + * Be careful when changing this, it has to be at most 128 bytes + * to fit into space reserved for the exception handler. + */ + .set push .set noat +NESTED(except_vec3_generic, 0, sp) +#if R5432_CP0_INTERRUPT_WAR + mfc0 k0, CP0_INDEX +#endif mfc0 k1, CP0_CAUSE andi k1, k1, 0x7c dsll k1, k1, 1 ld k0, exception_handlers(k1) jr k0 - nop - END(except_vec3_generic) - .set at +END(except_vec3_generic) + .set pop + /* - * Special interrupt vector for embedded MIPS. This is a dedicated interrupt - * vector which reduces interrupt processing overhead. The jump instruction - * will be inserted here at initialization time. This handler may only be 8 - * bytes in size! + * Special interrupt vector for MIPS64 ISA & embedded MIPS processors. + * This is a dedicated interrupt exception vector which reduces the + * interrupt processing overhead. The jump instruction will be replaced + * at the initialization time. + * + * Be careful when changing this, it has to be at most 128 bytes + * to fit into space reserved for the exception handler. */ NESTED(except_vec4, 0, sp) 1: j 1b /* Dummy, will be replaced */ +END(except_vec4) + + /* + * EJTAG debug exception handler. + * The EJTAG debug exception entry point is 0xbfc00480, which + * normally is in the boot PROM, so the boot PROM must do a + * unconditional jump to this vector. + */ +NESTED(except_vec_ejtag_debug, 0, sp) + j ejtag_debug_handler nop - END(except_vec4) + END(except_vec_ejtag_debug) __FINIT + + /* + * EJTAG debug exception handler. + */ + NESTED(ejtag_debug_handler, PT_SIZE, sp) + .set noat + .set noreorder + mtc0 k0, CP0_DESAVE + mfc0 k0, CP0_DEBUG + + sll k0, k0, 30 # Check for SDBBP. + bgez k0, ejtag_return + + la k0, ejtag_debug_buffer + sw k1, 0(k0) + SAVE_ALL + jal ejtag_exception_handler + move a0, sp + RESTORE_ALL + la k0, ejtag_debug_buffer + lw k1, 0(k0) + +ejtag_return: + mfc0 k0, CP0_DESAVE + .set mips32 + deret + .set mips0 + nop + .set at + END(ejtag_debug_handler) + + /* + * This buffer is reserved for the use of the EJTAG debug + * handler. + */ + .data + EXPORT(ejtag_debug_buffer) + .fill 8 diff -Nru a/arch/mips64/kernel/r4k_switch.S b/arch/mips64/kernel/r4k_switch.S --- a/arch/mips64/kernel/r4k_switch.S Tue Jul 1 18:44:31 2003 +++ b/arch/mips64/kernel/r4k_switch.S Tue Jul 1 18:44:31 2003 @@ -8,11 +8,8 @@ * Copyright (C) 1994, 1995, 1996, by Andreas Busse * Copyright (C) 1999 Silicon Graphics, Inc. */ -#include #include -#include #include -#include #include #include #include @@ -21,15 +18,32 @@ #include #include #include +#include #include .set mips3 +/* + * Offset to the current process status flags, the first 32 bytes of the + * stack are not used. + */ +#define ST_OFF (KERNEL_STACK_SIZE - 32 - PT_SIZE + PT_STATUS) + +/* + * FPU context is saved iff the process has used it's FPU in the current + * time slice as indicated by TIF_USEDFPU. In any case, the CU1 bit for user + * space STATUS register should be 0, so that a process *always* starts its + * userland with FPU disabled after each context switch. + * + * FPU will be enabled as soon as the process accesses FPU again, through + * do_cpu() trap. + */ + /* - * task_struct *resume(task_struct *prev, task_struct *next) + * task_struct *resume(task_struct *prev, task_struct *next, + * struct thread_info *next_ti)) */ - .set noreorder .align 5 LEAF(resume) mfc0 t1, CP0_STATUS @@ -38,86 +52,85 @@ sd ra, THREAD_REG31(a0) /* + * check if we need to save FPU registers + */ + ld t3, TASK_THREAD_INFO(a0) + ld t0, TI_FLAGS(t3) + li t1, TIF_USEDFPU + and t2, t0, t1 + beqz t2, 1f + nor t1, zero, t1 + + and t0, t0, t1 + sd t0, TI_FLAGS(t3) + + /* + * clear saved user stack CU1 bit + */ + ld t0, ST_OFF(t3) + li t1, ~ST0_CU1 + and t0, t0, t1 + sd t0, ST_OFF(t3) + + + sll t2, t0, 5 + bgez t2, 2f + sdc1 $f0, (THREAD_FPU + 0x00)(a0) + fpu_save_16odd a0 +2: + fpu_save_16even a0 t1 # clobbers t1 +1: + + /* * The order of restoring the registers takes care of the race * updating $28, $29 and kernelsp without disabling ints. */ - move $28, a1 - cpu_restore_nonscratch $28 -#ifndef CONFIG_SMP - daddiu t0, $28, KERNEL_STACK_SIZE-32 - sd t0, kernelsp -#else - mtc0 a1, CP0_WATCHLO - dsrl32 a1, a1, 0 - mtc0 a1, CP0_WATCHHI -#endif + move $28, a2 + cpu_restore_nonscratch a1 + + daddiu t1, $28, KERNEL_STACK_SIZE-32 + set_saved_sp t1, t0, t2 + mfc0 t1, CP0_STATUS /* Do we really need this? */ li a3, 0xff00 and t1, a3 - ld a2, THREAD_STATUS($28) + ld a2, THREAD_STATUS(a1) nor a3, $0, a3 and a2, a3 or a2, t1 mtc0 a2, CP0_STATUS + move v0, a0 jr ra - move v0, a0 END(resume) /* - * Do lazy fpu context switch. Saves FPU context to the process in a0 - * and loads the new context of the current process. + * Save a thread's fp context. */ - -#define ST_OFF (KERNEL_STACK_SIZE - 32 - PT_SIZE + PT_STATUS) - -LEAF(lazy_fpu_switch) - mfc0 t0, CP0_STATUS # enable cp1 - li t3, 0x20000000 - or t0, t3 - mtc0 t0, CP0_STATUS - - beqz a0, 2f # Save floating point state - nor t3, zero, t3 - - ld t1, ST_OFF(a0) # last thread loses fpu - and t1, t3 - sd t1, ST_OFF(a0) - sll t2, t1, 5 - bgez t2, 1f - sdc1 $f0, (THREAD_FPU + 0x00)(a0) +LEAF(_save_fp) + mfc0 t0, CP0_STATUS + sll t1, t0, 5 + bgez t1, 1f # 16 register mode? fpu_save_16odd a0 1: fpu_save_16even a0 t1 # clobbers t1 -2: - - beqz a1, 3f - - sll t0, t0, 5 # load new fp state - bgez t0, 1f - ldc1 $f0, (THREAD_FPU + 0x00)($28) - fpu_restore_16odd $28 -1: - .set reorder - fpu_restore_16even $28, t0 # clobbers t0 -3: + sdc1 $f0, (THREAD_FPU + 0x00)(a0) jr ra - END(lazy_fpu_switch) + END(_save_fp) /* - * Save a thread's fp context. + * Restore a thread's fp context. */ - .set noreorder -LEAF(save_fp) +LEAF(_restore_fp) mfc0 t0, CP0_STATUS sll t1, t0, 5 bgez t1, 1f # 16 register mode? - nop - fpu_save_16odd a0 -1: - fpu_save_16even a0 t1 # clobbers t1 + + fpu_restore_16odd a0 +1: fpu_restore_16even a0, t0 # clobbers t0 + ldc1 $f0, (THREAD_FPU + 0x00)(a0) + jr ra - sdc1 $f0, (THREAD_FPU + 0x00)(a0) - END(save_fp) + END(_restore_fp) /* * Load the FPU with signalling NANS. This bit pattern we're using has @@ -129,18 +142,19 @@ #define FPU_DEFAULT 0x00000000 -LEAF(init_fpu) +LEAF(_init_fpu) mfc0 t0, CP0_STATUS - li t1, 0x20000000 + li t1, ST0_CU1 or t0, t1 mtc0 t0, CP0_STATUS + FPU_ENABLE_HAZARD sll t0, t0, 5 li t1, FPU_DEFAULT ctc1 t1, fcr31 + li t0, -1 # SNaN bgez t0, 1f # 16 / 32 register mode? - li t0, -1 dmtc1 t0, $f1 dmtc1 t0, $f3 @@ -174,6 +188,6 @@ dmtc1 t0, $f24 dmtc1 t0, $f26 dmtc1 t0, $f28 + dmtc1 t0, $f30 jr ra - dmtc1 t0, $f30 - END(init_fpu) + END(_init_fpu) diff -Nru a/arch/mips64/kernel/r4k_tlb.S b/arch/mips64/kernel/r4k_tlb.S --- a/arch/mips64/kernel/r4k_tlb.S Tue Jul 1 18:44:39 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,126 +0,0 @@ -/* - * 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) 2000 Silicon Graphics, Inc. - * Written by Ulf Carlsson (ulfc@engr.sgi.com) - */ -#include -#include -#include -#include -#include -#include -#include - - .data - .comm pgd_current, NR_CPUS * 8, 8 - - /* - * After this macro runs we have a pointer to the pte of the address - * that caused the fault in in PTR. - */ - - .macro LOAD_PTE2, ptr, tmp -#ifdef CONFIG_SMP - dmfc0 \tmp, CP0_CONTEXT - dla \ptr, pgd_current - dsrl \tmp, 23 - daddu \ptr, \tmp -#else - dla \ptr, pgd_current -#endif - dmfc0 \tmp, CP0_BADVADDR - ld \ptr, (\ptr) - bltz \tmp, kaddr - dsrl \tmp, (PGDIR_SHIFT-3) # get pgd offset in bytes - andi \tmp, ((PTRS_PER_PGD - 1)<<3) - daddu \ptr, \tmp # add in pgd offset - dmfc0 \tmp, CP0_BADVADDR - ld \ptr, (\ptr) # get pmd pointer - dsrl \tmp, (PMD_SHIFT-3) # get pmd offset in bytes - andi \tmp, ((PTRS_PER_PMD - 1)<<3) - daddu \ptr, \tmp # add in pmd offset - dmfc0 \tmp, CP0_XCONTEXT - ld \ptr, (\ptr) # get pte pointer - andi \tmp, 0xff0 # get pte offset - daddu \ptr, \tmp - .endm - - /* - * This places the even/odd pte pair in the page table at the pte - * entry pointed to by PTE into ENTRYLO0 and ENTRYLO1. - */ - .macro PTE_RELOAD, pte0, pte1 - dsrl \pte0, 6 # convert to entrylo0 - dmtc0 \pte0, CP0_ENTRYLO0 # load it - dsrl \pte1, 6 # convert to entrylo1 - dmtc0 \pte1, CP0_ENTRYLO1 # load it - .endm - - .text - .set noreorder - .set mips3 - - .align 5 -FEXPORT(except_vec0) - .set noat -1: b 1b - nop - - /* TLB refill handler for the R10000. - * Attention: We may only use 32 instructions. - */ - - .align 5 -FEXPORT(except_vec1_r10k) - .set noat - LOAD_PTE2 k1 k0 - ld k0, 0(k1) # get even pte - ld k1, 8(k1) # get odd pte - PTE_RELOAD k0 k1 - nop - tlbwr - eret -kaddr: - dla k0, handle_vmalloc_address # MAPPED kernel needs this - jr k0 - nop - - .align 5 -FEXPORT(handle_vmalloc_address) - .set noat - /* - * First, determine that the address is in/above vmalloc range. - */ - dmfc0 k0, CP0_BADVADDR - dli k1, VMALLOC_START - - /* - * Now find offset into kptbl. - */ - dsubu k0, k0, k1 - dla k1, kptbl - dsrl k0, (PAGE_SHIFT+1) # get vpn2 - dsll k0, 4 # byte offset of pte - daddu k1, k1, k0 - - /* - * Determine that fault address is within vmalloc range. - */ - dla k0, ekptbl - sltu k0, k1, k0 - beqz k0, not_vmalloc - - /* - * Load cp0 registers. - */ - ld k0, 0(k1) # get even pte - ld k1, 8(k1) # get odd pte - -not_vmalloc: - PTE_RELOAD k0 k1 - nop - tlbwr - eret diff -Nru a/arch/mips64/kernel/r4k_tlb_debug.c b/arch/mips64/kernel/r4k_tlb_debug.c --- a/arch/mips64/kernel/r4k_tlb_debug.c Tue Jul 1 18:44:38 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,71 +0,0 @@ -/* - * 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) 1999 Ralf Baechle - * Copyright (C) 1999 Silicon Graphics, Inc. - * - * TLB debugging routines. These perform horribly slow but can easily be - * modified for debugging purposes. - */ -#include -#include -#include -#include -#include -#include -#include -#include - -asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write, - unsigned long address); - -asmlinkage void tlb_refill_debug(struct pt_regs regs) -{ - show_regs(®s); - panic(__FUNCTION__ " called. This Does Not Happen (TM)."); -} - -asmlinkage void xtlb_refill_debug(struct pt_regs *regs) -{ - unsigned long addr; - pgd_t *pgd; - pmd_t *pmd; - pte_t *pte; - - addr = regs->cp0_badvaddr & ~((PAGE_SIZE << 1) - 1); - pgd = pgd_offset(current->active_mm, addr); - pmd = pmd_offset(pgd, addr); - pte = pte_offset(pmd, addr); - - set_entrylo0(pte_val(pte[0]) >> 6); - set_entrylo1(pte_val(pte[1]) >> 6); - __asm__ __volatile__("nop;nop;nop"); - - tlb_write_random(); -} - -asmlinkage void xtlb_mod_debug(struct pt_regs *regs) -{ - unsigned long addr; - - addr = regs->cp0_badvaddr; - do_page_fault(regs, 1, addr); -} - -asmlinkage void xtlb_tlbl_debug(struct pt_regs *regs) -{ - unsigned long addr; - - addr = regs->cp0_badvaddr; - do_page_fault(regs, 0, addr); -} - -asmlinkage void xtlb_tlbs_debug(struct pt_regs *regs) -{ - unsigned long addr; - - addr = regs->cp0_badvaddr; - do_page_fault(regs, 1, addr); -} diff -Nru a/arch/mips64/kernel/r4k_tlb_glue.S b/arch/mips64/kernel/r4k_tlb_glue.S --- a/arch/mips64/kernel/r4k_tlb_glue.S Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,46 +0,0 @@ -/* - * 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) 1999 Ralf Baechle - * Copyright (C) 1999 Silicon Graphics, Inc. - */ -#define __ASSEMBLY__ -#include -#include -#include -#include - - .macro __BUILD_cli - CLI - .endm - - .macro __BUILD_sti - STI - .endm - - .macro tlb_handler name interruptible writebit - NESTED(__\name, PT_SIZE, sp) - SAVE_ALL -#if DEBUG_MIPS64 -jal dodebug2 -ld $4, PT_R4(sp) -ld $5, PT_R5(sp) -ld $6, PT_R6(sp) -ld $7, PT_R7(sp) -ld $2, PT_R2(sp) -#endif - dmfc0 a2, CP0_BADVADDR - __BUILD_\interruptible - li a1, \writebit - sd a2, PT_BVADDR(sp) - move a0, sp - jal do_page_fault - j ret_from_sys_call - END(__\name) - .endm - - tlb_handler xtlb_mod sti 1 - tlb_handler xtlb_tlbl sti 0 - tlb_handler xtlb_tlbs sti 1 diff -Nru a/arch/mips64/kernel/reset.c b/arch/mips64/kernel/reset.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips64/kernel/reset.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,36 @@ +/* + * 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) 2001 by Ralf Baechle + * Copyright (C) 2001 MIPS Technologies, Inc. + */ +#include +#include +#include +#include + +/* + * Urgs ... Too many MIPS machines to handle this in a generic way. + * So handle all using function pointers to machine specific + * functions. + */ +void (*_machine_restart)(char *command); +void (*_machine_halt)(void); +void (*_machine_power_off)(void); + +void machine_restart(char *command) +{ + _machine_restart(command); +} + +void machine_halt(void) +{ + _machine_halt(); +} + +void machine_power_off(void) +{ + _machine_power_off(); +} diff -Nru a/arch/mips64/kernel/scall_64.S b/arch/mips64/kernel/scall_64.S --- a/arch/mips64/kernel/scall_64.S Tue Jul 1 18:44:32 2003 +++ b/arch/mips64/kernel/scall_64.S Tue Jul 1 18:44:32 2003 @@ -3,106 +3,125 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1995, 96, 97, 98, 99, 2000, 01 by Ralf Baechle + * Copyright (C) 1995, 96, 97, 98, 99, 2000, 01, 02 by Ralf Baechle * Copyright (C) 1999, 2000 Silicon Graphics, Inc. * Copyright (C) 2001 MIPS Technologies, Inc. */ #include #include #include -#include #include #include #include +#include #include +#include -/* This duplicates the definition from */ -#define PT_TRACESYS 0x00000002 /* tracing system calls */ - -/* This duplicates the definition from */ -#define SIGILL 4 /* Illegal instruction (ANSI). */ - -#ifndef CONFIG_MIPS32_COMPAT +#ifndef CONFIG_BINFMT_ELF32 +/* Neither O32 nor N32, so define handle_sys here */ #define handle_sys64 handle_sys #endif .align 5 NESTED(handle_sys64, PT_SIZE, sp) -/* When 32-bit compatibility is configured scall_o32.S already did this. */ -#ifndef CONFIG_MIPS32_COMPAT - .set noat - SAVE_SOME - STI - .set at +#if !defined(CONFIG_MIPS32_O32) && !defined(CONFIG_MIPS32_N32) + /* + * When 32-bit compatibility is configured scall_o32.S + * already did this. + */ + .set noat + SAVE_SOME + STI + .set at #endif - ld t1, PT_EPC(sp) # skip syscall on return - - subu t0, v0, __NR_Linux # check syscall number - sltiu t0, t0, __NR_Linux_syscalls + 1 - daddiu t1, 4 # skip to next instruction - beqz t0, illegal_syscall - sd t1, PT_EPC(sp) - - dsll t0, v0, 3 # offset into table - ld t2, (sys_call_table - (__NR_Linux * 8))(t0) # syscall routine + ld t1, PT_EPC(sp) # skip syscall on return - sd a3, PT_R26(sp) # save a3 for syscall restarting - - ld t0, TASK_PTRACE($28) # syscall tracing enabled? - andi t0, PT_TRACESYS - bnez t0, trace_a_syscall - - jalr t2 # Do The Real Thing (TM) - - li t0, -EMAXERRNO - 1 # error? - sltu t0, t0, v0 - sd t0, PT_R7(sp) # set error flag - beqz t0, 1f - - negu v0 # error - sd v0, PT_R0(sp) # set flag for syscall restarting -1: sd v0, PT_R2(sp) # result - -ret_from_sys_call: - mfc0 t0, CP0_STATUS - xori t0, t0, 1 - ori t0, t0, 1 - mtc0 t0, CP0_STATUS - -#error ld t2, TASK_NEED_RESCHED($28) - bnez t2, reschedule -#error lw v0, TASK_SIGPENDING($28) - bnez v0, signal_return - -restore_all: - RESTORE_SOME - RESTORE_SP - eret - -/* Put this behind restore_all for the sake of the branch prediction. */ -signal_return: - .type signal_return, @function - - mfc0 t0, CP0_STATUS - ori t0, t0, 1 - mtc0 t0, CP0_STATUS - - move a0, zero - move a1, sp - jal do_signal - b restore_all - -reschedule: - SAVE_STATIC - jal schedule - b ret_from_sys_call + subu t0, v0, __NR_Linux # check syscall number + sltiu t0, t0, __NR_Linux_syscalls + 1 + daddiu t1, 4 # skip to next instruction + beqz t0, illegal_syscall + sd t1, PT_EPC(sp) + + dsll t0, v0, 3 # offset into table + ld t2, (sys_call_table - (__NR_Linux * 8))(t0) + # syscall routine + + sd a3, PT_R26(sp) # save a3 for syscall restarting + + LONG_L t0, TI_FLAGS($28) + bltz t0, syscall_trace_entry # syscall tracing enabled? + + jalr t2 # Do The Real Thing (TM) + + li t0, -EMAXERRNO - 1 # error? + sltu t0, t0, v0 + sd t0, PT_R7(sp) # set error flag + beqz t0, 1f + + negu v0 # error + sd v0, PT_R0(sp) # set flag for syscall + # restarting +1: sd v0, PT_R2(sp) # result + +syscall_exit: + mfc0 t0, CP0_STATUS # make sure need_resched and + ori t0, t0, 1 # signals dont change between + xori t0, t0, 1 # sampling and return + mtc0 t0, CP0_STATUS + SSNOP; SSNOP; SSNOP + + LONG_L a2, TI_FLAGS($28) # current->work + bnez a2, syscall_exit_work + +FEXPORT(restore_all) + RESTORE_SOME + RESTORE_SP + eret + +EXPORT(work_pending) + andi t0, a2, _TIF_NEED_RESCHED + bltz t0, work_notifysig +work_resched: + jal schedule + + mfc0 t0, CP0_STATUS # make sure need_resched and + ori t0, t0, 1 # signals dont change between + xori t0, t0, 1 # sampling and return + mtc0 t0, CP0_STATUS + SSNOP; SSNOP; SSNOP + + LONG_L a2, TI_FLAGS($28) + andi a2, _TIF_WORK_MASK # is there any work to be done + # other than syscall tracing + beqz a2, restore_all + andi t0, a2, _TIF_NEED_RESCHED + bnez t0, work_resched + +work_notifysig: # deal with pending signals and + # notify-resume requests + SAVE_STATIC + move a0, sp + li a1, 0 + jal do_notify_resume # a2 already loaded + RESTORE_STATIC + j restore_all + +syscall_exit_work: + LONG_L t0, TI_FLAGS($28) # current->work.syscall_trace + bgez t0, work_pending + + mfc0 t0, CP0_STATUS # sti + ori t0, t0, 1 + mtc0 t0, CP0_STATUS + jal do_syscall_trace + j resume_userspace /* ------------------------------------------------------------------------ */ -trace_a_syscall: +syscall_trace_entry: SAVE_STATIC sd t2,PT_R1(sp) - jal syscall_trace + jal do_syscall_trace ld t2,PT_R1(sp) ld a0, PT_R4(sp) # Restore argument registers @@ -120,8 +139,7 @@ sd v0, PT_R0(sp) # set flag for syscall restarting 1: sd v0, PT_R2(sp) # result - jal syscall_trace - j ret_from_sys_call + j syscall_exit illegal_syscall: /* This also isn't a 64-bit syscall, throw an error. */ @@ -129,223 +147,224 @@ sd v0, PT_R2(sp) li t0, 1 # set error flag sd t0, PT_R7(sp) - j ret_from_sys_call + j syscall_exit END(handle_sys64) + .align 3 sys_call_table: - PTR sys_syscall /* 5000 */ - PTR sys_exit - PTR sys_fork - PTR sys_read + PTR sys_read /* 5000 */ PTR sys_write - PTR sys_open /* 5005 */ + PTR sys_open PTR sys_close - PTR sys_waitpid - PTR sys_creat - PTR sys_link - PTR sys_unlink /* 5010 */ - PTR sys_execve - PTR sys_chdir - PTR sys_time - PTR sys_mknod - PTR sys_chmod /* 5015 */ - PTR sys_lchown - PTR sys_ni_syscall - PTR sys_stat + PTR sys_newstat + PTR sys_newfstat /* 5005 */ + PTR sys_newlstat + PTR sys_poll PTR sys_lseek - PTR sys_getpid /* 5020 */ - PTR sys_mount - PTR sys_oldumount - PTR sys_setuid - PTR sys_getuid - PTR sys_stime /* 5025 */ - PTR sys_ni_syscall /* ptrace */ - PTR sys_alarm - PTR sys_fstat + PTR sys_mmap + PTR sys_mprotect /* 5010 */ + PTR sys_munmap + PTR sys_brk + PTR sys_rt_sigaction + PTR sys_rt_sigprocmask + PTR sys_ioctl /* 5015 */ + PTR sys_pread64 + PTR sys_pwrite64 + PTR sys_readv + PTR sys_writev + PTR sys_access /* 5020 */ + PTR sys_pipe + PTR sys_select + PTR sys_sched_yield + PTR sys_mremap + PTR sys_msync /* 5025 */ + PTR sys_mincore + PTR sys_madvise + PTR sys_shmget + PTR sys_shmat + PTR sys_shmctl /* 5030 */ + PTR sys_dup + PTR sys_dup2 PTR sys_pause - PTR sys_utime /* 5030 */ - PTR sys_ni_syscall - PTR sys_ni_syscall - PTR sys_access - PTR sys_nice - PTR sys_ni_syscall /* 5035 */ - PTR sys_sync - PTR sys_kill - PTR sys_rename + PTR sys_nanosleep + PTR sys_getitimer /* 5035 */ + PTR sys_setitimer + PTR sys_alarm + PTR sys_getpid + PTR sys_sendfile + PTR sys_socket /* 5040 */ + PTR sys_connect + PTR sys_accept + PTR sys_sendto + PTR sys_recvfrom + PTR sys_sendmsg /* 5045 */ + PTR sys_recvmsg + PTR sys_shutdown + PTR sys_bind + PTR sys_listen + PTR sys_getsockname /* 5050 */ + PTR sys_getpeername + PTR sys_socketpair + PTR sys_setsockopt + PTR sys_getsockopt + PTR sys_clone /* 5055 */ + PTR sys_fork + PTR sys_execve + PTR sys_exit + PTR sys_wait4 + PTR sys_kill /* 5060 */ + PTR sys_newuname + PTR sys_semget + PTR sys_semop + PTR sys_semctl + PTR sys_shmdt /* 5065 */ + PTR sys_msgget + PTR sys_msgsnd + PTR sys_msgrcv + PTR sys_msgctl + PTR sys_fcntl /* 5070 */ + PTR sys_flock + PTR sys_fsync + PTR sys_fdatasync + PTR sys_truncate + PTR sys_ftruncate /* 5075 */ + PTR sys_getdents + PTR sys_getcwd + PTR sys_chdir + PTR sys_fchdir + PTR sys_rename /* 5080 */ PTR sys_mkdir - PTR sys_rmdir /* 5040 */ - PTR sys_dup - PTR sys_pipe + PTR sys_rmdir + PTR sys_creat + PTR sys_link + PTR sys_unlink /* 5085 */ + PTR sys_symlink + PTR sys_readlink + PTR sys_chmod + PTR sys_fchmod + PTR sys_chown /* 5090 */ + PTR sys_fchown + PTR sys_lchown + PTR sys_umask + PTR sys_gettimeofday + PTR sys_getrlimit /* 5095 */ + PTR sys_getrusage + PTR sys_sysinfo PTR sys_times - PTR sys_ni_syscall - PTR sys_brk /* 5045 */ - PTR sys_setgid + PTR sys_ptrace + PTR sys_getuid /* 5100 */ + PTR sys_syslog PTR sys_getgid - PTR sys_ni_syscall /* was signal 2 */ - PTR sys_geteuid - PTR sys_getegid /* 5050 */ - PTR sys_acct - PTR sys_umount - PTR sys_ni_syscall - PTR sys_ioctl - PTR sys_fcntl /* 5055 */ - PTR sys_ni_syscall + PTR sys_setuid + PTR sys_setgid + PTR sys_geteuid /* 5105 */ + PTR sys_getegid PTR sys_setpgid - PTR sys_ni_syscall - PTR sys_ni_syscall - PTR sys_umask /* 5060 */ - PTR sys_chroot - PTR sys_ustat - PTR sys_dup2 PTR sys_getppid - PTR sys_getpgrp /* 5065 */ - PTR sys_setsid - PTR sys_sigaction - PTR sys_sgetmask - PTR sys_ssetmask - PTR sys_setreuid /* 5070 */ + PTR sys_getpgrp + PTR sys_setsid /* 5110 */ + PTR sys_setreuid PTR sys_setregid - PTR sys_sigsuspend - PTR sys_sigpending - PTR sys_sethostname - PTR sys_setrlimit /* 5075 */ - PTR sys_getrlimit - PTR sys_getrusage - PTR sys_gettimeofday - PTR sys_settimeofday - PTR sys_getgroups /* 5080 */ + PTR sys_getgroups PTR sys_setgroups - PTR sys_ni_syscall /* old_select */ - PTR sys_symlink - PTR sys_lstat - PTR sys_readlink /* 5085 */ - PTR sys_uselib - PTR sys_swapon - PTR sys_reboot - PTR sys_ni_syscall /* old_readdir */ - PTR sys_mmap /* 5090 */ - PTR sys_munmap - PTR sys_truncate - PTR sys_ftruncate - PTR sys_fchmod - PTR sys_fchown /* 5095 */ - PTR sys_getpriority - PTR sys_setpriority - PTR sys_ni_syscall - PTR sys_statfs - PTR sys_fstatfs /* 5100 */ - PTR sys_ni_syscall /* sys_ioperm */ - PTR sys_socketcall - PTR sys_syslog - PTR sys_setitimer - PTR sys_getitimer /* 5105 */ - PTR sys_newstat - PTR sys_newlstat - PTR sys_newfstat - PTR sys_ni_syscall - PTR sys_ni_syscall /* sys_ioperm *//* 5110 */ - PTR sys_vhangup - PTR sys_ni_syscall /* was sys_idle */ - PTR sys_ni_syscall /* sys_vm86 */ - PTR sys_wait4 - PTR sys_swapoff /* 5115 */ - PTR sys_sysinfo - PTR sys_ipc - PTR sys_fsync - PTR sys_sigreturn - PTR sys_clone /* 5120 */ - PTR sys_setdomainname - PTR sys_newuname - PTR sys_ni_syscall /* sys_modify_ldt */ - PTR sys_adjtimex - PTR sys_mprotect /* 5125 */ - PTR sys_sigprocmask - PTR sys_create_module - PTR sys_init_module - PTR sys_delete_module - PTR sys_get_kernel_syms /* 5130 */ - PTR sys_quotactl + PTR sys_setresuid /* 5115 */ + PTR sys_getresuid + PTR sys_setresgid + PTR sys_getresgid PTR sys_getpgid - PTR sys_fchdir - PTR sys_bdflush - PTR sys_sysfs /* 5135 */ - PTR sys_personality - PTR sys_ni_syscall /* for afs_syscall */ - PTR sys_setfsuid + PTR sys_setfsuid /* 5120 */ PTR sys_setfsgid - PTR sys_llseek /* 5140 */ - PTR sys_getdents - PTR sys_select - PTR sys_flock - PTR sys_msync - PTR sys_readv /* 5145 */ - PTR sys_writev - PTR sys_cacheflush - PTR sys_cachectl - PTR sys_sysmips - PTR sys_ni_syscall /* 5150 */ PTR sys_getsid - PTR sys_fdatasync - PTR sys_sysctl - PTR sys_mlock - PTR sys_munlock /* 5155 */ - PTR sys_mlockall - PTR sys_munlockall + PTR sys_capget + PTR sys_capset + PTR sys_rt_sigpending /* 5125 */ + PTR sys_rt_sigtimedwait + PTR sys_rt_sigqueueinfo + PTR sys_rt_sigsuspend + PTR sys_sigaltstack + PTR sys_utime /* 5130 */ + PTR sys_mknod + PTR sys_personality + PTR sys_ustat + PTR sys_statfs + PTR sys_fstatfs /* 5135 */ + PTR sys_sysfs + PTR sys_getpriority + PTR sys_setpriority PTR sys_sched_setparam - PTR sys_sched_getparam - PTR sys_sched_setscheduler /* 5160 */ + PTR sys_sched_getparam /* 5140 */ + PTR sys_sched_setscheduler PTR sys_sched_getscheduler - PTR sys_sched_yield PTR sys_sched_get_priority_max PTR sys_sched_get_priority_min - PTR sys_sched_rr_get_interval /* 5165 */ - PTR sys_nanosleep - PTR sys_mremap - PTR sys_accept - PTR sys_bind - PTR sys_connect /* 5170 */ - PTR sys_getpeername - PTR sys_getsockname - PTR sys_getsockopt - PTR sys_listen - PTR sys_recv /* 5175 */ - PTR sys_recvfrom - PTR sys_recvmsg - PTR sys_send - PTR sys_sendmsg - PTR sys_sendto /* 5180 */ - PTR sys_setsockopt - PTR sys_shutdown - PTR sys_socket - PTR sys_socketpair - PTR sys_setresuid /* 5185 */ - PTR sys_getresuid - PTR sys_query_module - PTR sys_poll - PTR sys_nfsservctl - PTR sys_setresgid /* 5190 */ - PTR sys_getresgid + PTR sys_sched_rr_get_interval /* 5145 */ + PTR sys_mlock + PTR sys_munlock + PTR sys_mlockall + PTR sys_munlockall + PTR sys_vhangup /* 5150 */ + PTR sys_pivot_root + PTR sys_sysctl PTR sys_prctl - PTR sys_rt_sigreturn - PTR sys_rt_sigaction - PTR sys_rt_sigprocmask /* 5195 */ - PTR sys_rt_sigpending - PTR sys_rt_sigtimedwait - PTR sys_rt_sigqueueinfo - PTR sys_rt_sigsuspend - PTR sys_pread64 /* 5200 */ - PTR sys_pwrite64 - PTR sys_chown - PTR sys_getcwd - PTR sys_capget - PTR sys_capset /* 5205 */ - PTR sys_sigaltstack - PTR sys_sendfile - PTR sys_ni_syscall - PTR sys_ni_syscall - PTR sys_pivot_root /* 5210 */ - PTR sys_mincore - PTR sys_madvise - PTR sys_getdents64 + PTR sys_adjtimex + PTR sys_setrlimit /* 5155 */ + PTR sys_chroot + PTR sys_sync + PTR sys_acct + PTR sys_settimeofday + PTR sys_mount /* 5160 */ + PTR sys_umount + PTR sys_swapon + PTR sys_swapoff + PTR sys_reboot + PTR sys_sethostname /* 5165 */ + PTR sys_setdomainname + PTR sys_ni_syscall /* was create_module */ + PTR sys_init_module + PTR sys_delete_module + PTR sys_ni_syscall /* 5170, was get_kernel_syms */ + PTR sys_ni_syscall /* was query_module */ + PTR sys_quotactl + PTR sys_nfsservctl + PTR sys_ni_syscall /* res. for getpmsg */ + PTR sys_ni_syscall /* 5175 for putpmsg */ + PTR sys_ni_syscall /* res. for afs_syscall */ + PTR sys_ni_syscall /* res. for security */ PTR sys_gettid + PTR sys_readahead + PTR sys_setxattr /* 5180 */ + PTR sys_lsetxattr + PTR sys_fsetxattr + PTR sys_getxattr + PTR sys_lgetxattr + PTR sys_fgetxattr /* 5185 */ + PTR sys_listxattr + PTR sys_llistxattr + PTR sys_flistxattr + PTR sys_removexattr + PTR sys_lremovexattr /* 5190 */ + PTR sys_fremovexattr PTR sys_tkill + PTR sys_time + PTR sys_futex + PTR sys_sched_setaffinity /* 5195 */ + PTR sys_sched_getaffinity + PTR sys_cacheflush + PTR sys_cachectl + PTR sys_sysmips + PTR sys_io_setup /* 5200 */ + PTR sys_io_destroy + PTR sys_io_getevents + PTR sys_io_submit + PTR sys_io_cancel + PTR sys_exit_group /* 5205 */ + PTR sys_lookup_dcookie + PTR sys_epoll_create + PTR sys_epoll_ctl + PTR sys_epoll_wait + PTR sys_remap_file_pages /* 5210 */ + PTR sys_rt_sigreturn + PTR sys_set_tid_address + PTR sys_restart_syscall + PTR sys_semtimedop + PTR sys_fadvise64 /* 5215 */ diff -Nru a/arch/mips64/kernel/scall_n32.S b/arch/mips64/kernel/scall_n32.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips64/kernel/scall_n32.S Tue Jul 1 18:44:40 2003 @@ -0,0 +1,334 @@ +/* + * 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) 1995, 96, 97, 98, 99, 2000, 01 by Ralf Baechle + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + * Copyright (C) 2001 MIPS Technologies, Inc. + */ +#include +#include +#include +#include +#include +#include +#include + +/* This duplicates the definition from */ +#define PT_TRACESYS 0x00000002 /* tracing system calls */ + +/* This duplicates the definition from */ +#define SIGILL 4 /* Illegal instruction (ANSI). */ + +#ifndef CONFIG_MIPS32_O32 +/* No O32, so define handle_sys here */ +#define handle_sysn32 handle_sys +#endif + + .align 5 +NESTED(handle_sysn32, PT_SIZE, sp) +#ifndef CONFIG_MIPS32_O32 + .set noat + SAVE_SOME + STI + .set at +#endif + ld t1, PT_EPC(sp) # skip syscall on return + + subu t0, v0, __NR_N32_Linux # check syscall number + sltiu t0, t0, __NR_N32_Linux_syscalls + 1 + daddiu t1, 4 # skip to next instruction + beqz t0, not_n32_scall + sd t1, PT_EPC(sp) + + dsll t0, v0, 3 # offset into table + ld t2, (sysn32_call_table - (__NR_N32_Linux * 8))(t0) + + sd a3, PT_R26(sp) # save a3 for syscall restarting + + LONG_L t0, TI_FLAGS($28) # syscall tracing enabled? + bltz t0, n32_syscall_trace_entry + + jalr t2 # Do The Real Thing (TM) + + li t0, -EMAXERRNO - 1 # error? + sltu t0, t0, v0 + sd t0, PT_R7(sp) # set error flag + beqz t0, 1f + + negu v0 # error + sd v0, PT_R0(sp) # set flag for syscall restarting +1: sd v0, PT_R2(sp) # result + +FEXPORT(n32_syscall_exit) + mfc0 t0, CP0_STATUS # make sure need_resched and + xori t0, t0, 1 # signals dont change between + ori t0, t0, 1 # sampling and return + mtc0 t0, CP0_STATUS + SSNOP; SSNOP; SSNOP + + LONG_L a2, TI_FLAGS($28) # current->work + bnez a2, n32_syscall_exit_work + +restore_all: + RESTORE_SOME + RESTORE_SP + eret + +n32_syscall_exit_work: + SAVE_STATIC + j syscall_exit_work + +/* ------------------------------------------------------------------------ */ + +n32_syscall_trace_entry: + SAVE_STATIC + sd t2,PT_R1(sp) + jal do_syscall_trace + ld t2,PT_R1(sp) + + ld a0, PT_R4(sp) # Restore argument registers + ld a1, PT_R5(sp) + ld a2, PT_R6(sp) + ld a3, PT_R7(sp) + jalr t2 + + li t0, -EMAXERRNO - 1 # error? + sltu t0, t0, v0 + sd t0, PT_R7(sp) # set error flag + beqz t0, 1f + + negu v0 # error + sd v0, PT_R0(sp) # set flag for syscall restarting +1: sd v0, PT_R2(sp) # result + + j n32_syscall_exit + +not_n32_scall: + /* This is not an n32 compatibility syscall, pass it on to + the n64 syscall handlers. */ + j handle_sys64 + + END(handle_sysn32) + +EXPORT(sysn32_call_table) + PTR sys_read /* 6000 */ + PTR sys_write + PTR sys_open + PTR sys_close + PTR sys_newstat + PTR sys_newfstat /* 6005 */ + PTR sys_newlstat + PTR sys_poll + PTR sys_lseek + PTR sys_mmap + PTR sys_mprotect /* 6010 */ + PTR sys_munmap + PTR sys_brk + PTR sys32_rt_sigaction + PTR sys32_rt_sigprocmask + PTR compat_sys_ioctl /* 6015 */ + PTR sys_pread64 + PTR sys_pwrite64 + PTR sys32_readv + PTR sys32_writev + PTR sys_access /* 6020 */ + PTR sys_pipe + PTR sys32_select + PTR sys_sched_yield + PTR sys_mremap + PTR sys_msync /* 6025 */ + PTR sys_mincore + PTR sys_madvise + PTR sys_shmget + PTR sys_shmat + PTR sys_shmctl /* 6030 */ + PTR sys_dup + PTR sys_dup2 + PTR sys_pause + PTR compat_sys_nanosleep + PTR compat_sys_getitimer /* 6035 */ + PTR compat_sys_setitimer + PTR sys_alarm + PTR sys_getpid + PTR sys32_sendfile + PTR sys_socket /* 6040 */ + PTR sys_connect + PTR sys_accept + PTR sys_sendto + PTR sys_recvfrom + PTR compat_sys_sendmsg /* 6045 */ + PTR compat_sys_recvmsg + PTR sys_shutdown + PTR sys_bind + PTR sys_listen + PTR sys_getsockname /* 6050 */ + PTR sys_getpeername + PTR sys_socketpair + PTR compat_sys_setsockopt + PTR sys_getsockopt + PTR sys_clone /* 6055 */ + PTR sys_fork + PTR sys32_execve + PTR sys_exit + PTR sys32_wait4 + PTR sys_kill /* 6060 */ + PTR sys32_newuname + PTR sys_semget + PTR sys_semop + PTR sys_semctl + PTR sys_shmdt /* 6065 */ + PTR sys_msgget + PTR sys_msgsnd + PTR sys_msgrcv + PTR sys_msgctl + PTR compat_sys_fcntl /* 6070 */ + PTR sys_flock + PTR sys_fsync + PTR sys_fdatasync + PTR sys_truncate + PTR sys_ftruncate /* 6075 */ + PTR sys32_getdents + PTR sys_getcwd + PTR sys_chdir + PTR sys_fchdir + PTR sys_rename /* 6080 */ + PTR sys_mkdir + PTR sys_rmdir + PTR sys_creat + PTR sys_link + PTR sys_unlink /* 6085 */ + PTR sys_symlink + PTR sys_readlink + PTR sys_chmod + PTR sys_fchmod + PTR sys_chown /* 6090 */ + PTR sys_fchown + PTR sys_lchown + PTR sys_umask + PTR sys32_gettimeofday + PTR compat_sys_getrlimit /* 6095 */ + PTR compat_sys_getrusage + PTR sys32_sysinfo + PTR compat_sys_times + PTR sys_ptrace + PTR sys_getuid /* 6100 */ + PTR sys_syslog + PTR sys_getgid + PTR sys_setuid + PTR sys_setgid + PTR sys_geteuid /* 6105 */ + PTR sys_getegid + PTR sys_setpgid + PTR sys_getppid + PTR sys_getpgrp + PTR sys_setsid /* 6110 */ + PTR sys_setreuid + PTR sys_setregid + PTR sys_getgroups + PTR sys_setgroups + PTR sys_setresuid /* 6115 */ + PTR sys_getresuid + PTR sys_setresgid + PTR sys_getresgid + PTR sys_getpgid + PTR sys_setfsuid /* 6120 */ + PTR sys_setfsgid + PTR sys_getsid + PTR sys_capget + PTR sys_capset + PTR sys32_rt_sigpending /* 6125 */ + PTR sys32_rt_sigtimedwait + PTR sys32_rt_sigqueueinfo + PTR sys32_rt_sigsuspend + PTR sys32_sigaltstack + PTR compat_sys_utime /* 6130 */ + PTR sys_mknod + PTR sys32_personality + PTR sys_ustat + PTR compat_sys_statfs + PTR compat_sys_fstatfs /* 6135 */ + PTR sys_sysfs + PTR sys_getpriority + PTR sys_setpriority + PTR sys_sched_setparam + PTR sys_sched_getparam /* 6140 */ + PTR sys_sched_setscheduler + PTR sys_sched_getscheduler + PTR sys_sched_get_priority_max + PTR sys_sched_get_priority_min + PTR sys32_sched_rr_get_interval /* 6145 */ + PTR sys_mlock + PTR sys_munlock + PTR sys_mlockall + PTR sys_munlockall + PTR sys_vhangup /* 6150 */ + PTR sys_pivot_root + PTR sys32_sysctl + PTR sys_prctl + PTR sys32_adjtimex + PTR compat_sys_setrlimit /* 6155 */ + PTR sys_chroot + PTR sys_sync + PTR sys_acct + PTR sys32_settimeofday + PTR sys_mount /* 6160 */ + PTR sys_umount + PTR sys_swapon + PTR sys_swapoff + PTR sys_reboot + PTR sys_sethostname /* 6165 */ + PTR sys_setdomainname + PTR sys_ni_syscall /* was create_module */ + PTR sys_init_module + PTR sys_delete_module + PTR sys_ni_syscall /* 6170, was get_kernel_syms */ + PTR sys_ni_syscall /* was query_module */ + PTR sys_quotactl + PTR sys_nfsservctl + PTR sys_ni_syscall /* res. for getpmsg */ + PTR sys_ni_syscall /* 6175 for putpmsg */ + PTR sys_ni_syscall /* res. for afs_syscall */ + PTR sys_ni_syscall /* res. for security */ + PTR sys_gettid + PTR sys32_readahead + PTR sys_setxattr /* 6180 */ + PTR sys_lsetxattr + PTR sys_fsetxattr + PTR sys_getxattr + PTR sys_lgetxattr + PTR sys_fgetxattr /* 6185 */ + PTR sys_listxattr + PTR sys_llistxattr + PTR sys_flistxattr + PTR sys_removexattr + PTR sys_lremovexattr /* 6190 */ + PTR sys_fremovexattr + PTR sys_tkill + PTR sys_time + PTR compat_sys_futex + PTR sys32_sched_setaffinity /* 6195 */ + PTR sys32_sched_getaffinity + PTR sys_cacheflush + PTR sys_cachectl + PTR sys_sysmips + PTR sys_io_setup /* 6200 */ + PTR sys_io_destroy + PTR sys_io_getevents + PTR sys_io_submit + PTR sys_io_cancel + PTR sys_exit_group /* 6205 */ + PTR sys_lookup_dcookie + PTR sys_epoll_create + PTR sys_epoll_ctl + PTR sys_epoll_wait + PTR sys_remap_file_pages /* 6210 */ + PTR sys_ni_syscall + PTR sys_fcntl + PTR sys_set_tid_address + PTR sys_restart_syscall + PTR sys_semtimedop /* 6215 */ + PTR sys_fadvise64 + PTR sys_statfs64 + PTR sys_fstatfs64 diff -Nru a/arch/mips64/kernel/scall_o32.S b/arch/mips64/kernel/scall_o32.S --- a/arch/mips64/kernel/scall_o32.S Tue Jul 1 18:44:36 2003 +++ b/arch/mips64/kernel/scall_o32.S Tue Jul 1 18:44:36 2003 @@ -14,22 +14,12 @@ */ #include #include -#include #include #include #include #include #include -/* This duplicates the definition from */ -#error #define PT_TRACESYS 0x00000002 /* tracing system calls */ - -/* This duplicates the definition from */ -#define SIGILL 4 /* Illegal instruction (ANSI). */ - -/* Highest syscall used of any syscall flavour */ -#define MAX_SYSCALL_NO __NR_Linux32 + __NR_Linux32_syscalls - .align 5 NESTED(handle_sys, PT_SIZE, sp) .set noat @@ -38,24 +28,35 @@ .set at ld t1, PT_EPC(sp) # skip syscall on return - subu t0, v0, __NR_Linux32 # check syscall number - sltiu t0, t0, __NR_Linux32_syscalls + 1 + subu t0, v0, __NR_O32_Linux # check syscall number + sltiu t0, t0, __NR_O32_Linux_syscalls + 1 daddiu t1, 4 # skip to next instruction beqz t0, not_o32_scall sd t1, PT_EPC(sp) +#if 0 + SAVE_ALL + move a1, v0 + PRINT("Scall %ld\n") + RESTORE_ALL +#endif + + sll a0, a0, 0 + sll a1, a1, 0 + sll a2, a2, 0 + sll a3, a3, 0 /* XXX Put both in one cacheline, should save a bit. */ dsll t0, v0, 3 # offset into table - ld t2, (sys_call_table - (__NR_Linux32 * 8))(t0) # syscall routine - lbu t3, (sys_narg_table - __NR_Linux32)(v0) # number of arguments + ld t2, (sys_call_table - (__NR_O32_Linux * 8))(t0) + lbu t3, (sys_narg_table - __NR_O32_Linux)(v0) subu t0, t3, 5 # 5 or more arguments? sd a3, PT_R26(sp) # save a3 for syscall restarting bgez t0, stackargs stack_done: -#error ld t0, TASK_PTRACE($28) # syscall tracing enabled? -#error andi t0, PT_TRACESYS + LONG_L t0, TI_FLAGS($28) + # syscall tracing enabled? bnez t0, trace_a_syscall jalr t2 # Do The Real Thing (TM) @@ -69,35 +70,23 @@ sd v0, PT_R0(sp) # flag for syscall restarting 1: sd v0, PT_R2(sp) # result -FEXPORT(o32_ret_from_sys_call) - mfc0 t0, CP0_STATUS # need_resched and signals atomic test - ori t0, t0, 1 - xori t0, t0, 1 +FEXPORT(o32_syscall_exit) + mfc0 t0, CP0_STATUS # make need_resched and + ori t0, t0, 1 # signals dont change between + xori t0, t0, 1 # sampling and return mtc0 t0, CP0_STATUS + SSNOP; SSNOP; SSNOP -#error ld t2, TASK_NEED_RESCHED($28) - bnez t2, o32_reschedule -#error lw v0, TASK_SIGPENDING($28) - bnez v0, signal_return + LONG_L a2, TI_FLAGS($28) + bnez a2, o32_syscall_exit_work restore_all: RESTORE_SOME RESTORE_SP - .set mips3 eret - .set mips0 - -signal_return: mfc0 t0, CP0_STATUS # need_resched and signals atomic test - ori t0, t0, 1 - mtc0 t0, CP0_STATUS - move a0, zero - move a1, sp - SAVE_STATIC -#error jal do_signal -o32_reschedule: +o32_syscall_exit_work: SAVE_STATIC - jal schedule - b o32_ret_from_sys_call + j syscall_exit_work /* ------------------------------------------------------------------------ */ @@ -109,7 +98,7 @@ sd a7, PT_R11(sp) sd t2,PT_R1(sp) - jal syscall_trace + jal do_syscall_trace ld t2,PT_R1(sp) ld a0, PT_R4(sp) # Restore argument registers @@ -130,8 +119,7 @@ sd v0, PT_R0(sp) # set flag for syscall restarting 1: sd v0, PT_R2(sp) # result -#error jal syscall_trace - j o32_ret_from_sys_call + j syscall_exit /* ------------------------------------------------------------------------ */ @@ -150,16 +138,20 @@ bltz t0, bad_stack # -> sp is bad ld t0, PT_R29(sp) # get old user stack pointer - la t1, 3f # copy 1 to 2 arguments + PTR_LA t1, 3f # copy 1 to 2 arguments sll t3, t3, 2 subu t1, t3 jr t1 /* Ok, copy the args from the luser stack to the kernel stack */ + .set push + .set noreorder + .set nomacro 1: lw a5, 20(t0) # argument #6 from usp 2: lw a4, 16(t0) # argument #5 from usp +3: .set pop -3: j stack_done # go back + j stack_done # go back .section __ex_table,"a" PTR 1b, bad_stack @@ -170,70 +162,148 @@ * The stackpointer for a call with more than 4 arguments is bad. */ bad_stack: - negu v0 # error - sd v0, PT_R0(sp) - sd v0, PT_R2(sp) - li t0, 1 # set error flag - sd t0, PT_R7(sp) - j ret_from_sys_call + negu v0 # error + sd v0, PT_R0(sp) + sd v0, PT_R2(sp) + li t0, 1 # set error flag + sd t0, PT_R7(sp) + j o32_syscall_exit not_o32_scall: - /* This is not an 32-bit compatibility syscall, pass it on to - the 64-bit syscall handlers. */ - j handle_sys64 + /* + * This is not an o32 compatibility syscall, pass it on + * to the 64-bit syscall handlers. + */ +#ifdef CONFIG_MIPS32_N32 + j handle_sysn32 +#else + j handle_sys64 +#endif illegal_syscall: - /* This also isn't a 64-bit syscall, throw an error. */ - li v0, ENOSYS # error - sd v0, PT_R2(sp) - li t0, 1 # set error flag - sd t0, PT_R7(sp) - j ret_from_sys_call - END(handle_sys) - - LEAF(mips_atomic_set) - ld v1, THREAD_CURDS($28) - daddiu a0, a1, 4 - or a0, a0, a1 - li v0, -EFAULT - and a0, a0, v1 - bltz a0, 9f - - /* Ok, this is the ll/sc case. World is sane :-) */ -1: ll v0, (a1) - move a0, a2 -2: sc a0, (a1) - beqz a0, 1b + /* This also isn't a 64-bit syscall, throw an error. */ + li v0, ENOSYS # error + sd v0, PT_R2(sp) + li t0, 1 # set error flag + sd t0, PT_R7(sp) + j o32_syscall_exit + END(handle_sys) + +LEAF(mips_atomic_set) + andi v0, a1, 3 # must be word aligned + bnez v0, bad_alignment + + ld v1, TI_ADDR_LIMIT($28) # in legal address range? + daddiu a0, a1, 4 + or a0, a0, a1 + and a0, a0, v1 + bnez a0, bad_address + + /* Ok, this is the ll/sc case. World is sane :-) */ +1: ll v0, (a1) + move a0, a2 +2: sc a0, (a1) + beqz a0, 1b + + .section __ex_table,"a" + PTR 1b, bad_stack + PTR 2b, bad_stack + .previous + +1: sd v0, PT_R2(sp) # result + + /* Success, so skip usual error handling garbage. */ + LONG_L t0, TI_FLAGS($28) # syscall tracing enabled? + bltz t0, 1f + b o32_syscall_exit + +1: SAVE_STATIC + jal do_syscall_trace + li a3, 0 # success + j syscall_exit + +bad_address: + li v0, -EFAULT + jr ra + +bad_alignment: + li v0, -EINVAL + jr ra + END(mips_atomic_set) + +LEAF(sys32_sysmips) + beq a0, MIPS_ATOMIC_SET, mips_atomic_set + j sys_sysmips + END(sys32_sysmips) + +LEAF(sys32_syscall) + ld t0, PT_R29(sp) # user sp + + sltu v0, a0, __NR_O32_Linux + __NR_O32_Linux_syscalls + 1 + beqz v0, enosys + + dsll v0, a0, 3 + dla v1, sys32_syscall + ld t2, (sys_call_table - (__NR_O32_Linux * 8))(v0) + lbu t3, (sys_narg_table - __NR_O32_Linux)(a0) + + li v0, -EINVAL + beq t2, v1, out # do not recurse + + beqz t2, enosys # null function pointer? + + andi v0, t0, 0x3 # unaligned stack pointer? + bnez v0, sigsegv + + daddiu v0, t0, 16 # v0 = usp + 16 + daddu t1, v0, 12 # 3 32-bit arguments + ld v1, TI_ADDR_LIMIT($28) + or v0, v0, t1 + and v1, v1, v0 + bnez v1, efault + + move a0, a1 # shift argument registers + move a1, a2 + move a2, a3 + +1: lw a3, 16(t0) +2: lw t3, 20(t0) +3: lw t1, 24(t0) .section __ex_table,"a" - PTR 1b, bad_stack - PTR 2b, bad_stack + PTR 1b, efault + PTR 2b, efault + PTR 3b, efault .previous -1: sd v0, PT_R2(sp) # result + sw t3, 16(sp) # put into new stackframe + sw t1, 20(sp) + + bnez t1, 1f # zero arguments? + daddu a0, sp, 32 # then pass sp in a0 +1: + + sw t3, 16(sp) + sw v1, 20(sp) + jr t2 + /* Unreached */ + +enosys: li v0, -ENOSYS + b out + +sigsegv: + li a0, _SIGSEGV + move a1, $28 + jal force_sig + /* Fall through */ - /* Success, so skip usual error handling garbage. */ -#error ld t0, TASK_PTRACE($28) # syscall tracing enabled? -#error andi t0, PT_TRACESYS - bnez t0, 1f - b o32_ret_from_sys_call - -1: SAVE_STATIC -#error jal syscall_trace - li a3, 0 # success - j ret_from_sys_call - -9: li v0, -EFAULT - jr ra - END(mips_atomic_set) - - LEAF(sys_sysmips) - beq a0, MIPS_ATOMIC_SET, mips_atomic_set - j _sys_sysmips - END(sys_sysmips) +efault: li v0, -EFAULT + +out: jr ra + END(sys32_syscall) .macro syscalltable - sys sys_syscall 0 /* 4000 */ + sys sys32_syscall 0 /* 4000 */ sys sys_exit 1 sys sys_fork 0 sys sys_read 3 @@ -251,7 +321,7 @@ sys sys_chmod 2 /* 4015 */ sys sys_lchown 3 sys sys_ni_syscall 0 - sys sys_stat 2 + sys sys_ni_syscall 0 /* was sys_stat */ sys sys_lseek 3 sys sys_getpid 0 /* 4020 */ sys sys_mount 5 @@ -260,8 +330,8 @@ sys sys_getuid 0 sys sys_stime 1 /* 4025 */ sys sys32_ptrace 4 - sys sys32_alarm 1 - sys sys_fstat 2 + sys sys_alarm 1 + sys sys_ni_syscall 0 /* was sys_fstat */ sys sys_pause 0 sys compat_sys_utime 2 /* 4030 */ sys sys_ni_syscall 0 @@ -276,7 +346,7 @@ sys sys_rmdir 1 /* 4040 */ sys sys_dup 1 sys sys_pipe 0 - sys sys32_times 1 + sys compat_sys_times 1 sys sys_ni_syscall 0 sys sys_brk 1 /* 4045 */ sys sys_setgid 1 @@ -288,7 +358,7 @@ sys sys_umount 2 sys sys_ni_syscall 0 sys compat_sys_ioctl 3 - sys sys32_fcntl 3 /* 4055 */ + sys compat_sys_fcntl 3 /* 4055 */ sys sys_ni_syscall 2 sys sys_setpgid 2 sys sys_ni_syscall, 0 @@ -306,18 +376,18 @@ sys sys_setreuid 2 /* 4070 */ sys sys_setregid 2 sys sys32_sigsuspend 0 - sys sys32_sigpending 1 + sys compat_sys_sigpending 1 sys sys_sethostname 2 - sys sys32_setrlimit 2 /* 4075 */ - sys sys32_getrlimit 2 - sys sys32_getrusage 2 + sys compat_sys_setrlimit 2 /* 4075 */ + sys compat_sys_getrlimit 2 + sys compat_sys_getrusage 2 sys sys32_gettimeofday 2 sys sys32_settimeofday 2 sys sys_getgroups 2 /* 4080 */ sys sys_setgroups 2 - sys sys_ni_syscall 0 /* old_select */ + sys sys_ni_syscall 0 /* old_select */ sys sys_symlink 2 - sys sys_lstat 2 + sys sys_ni_syscall 0 /* was sys_lstat */ sys sys_readlink 3 /* 4085 */ sys sys_uselib 1 sys sys_swapon 2 @@ -332,24 +402,24 @@ sys sys_getpriority 2 sys sys_setpriority 3 sys sys_ni_syscall 0 - sys sys32_statfs 2 - sys sys32_fstatfs 2 /* 4100 */ - sys sys_ni_syscall 0 /* sys_ioperm */ - sys sys_socketcall 2 - sys sys_syslog 3 + sys compat_sys_statfs 2 + sys compat_sys_fstatfs 2 /* 4100 */ + sys sys_ni_syscall 0 /* sys_ioperm */ + sys sys_socketcall 2 + sys sys_syslog 3 sys compat_sys_setitimer 3 - sys compat_sys_getitimer 2 /* 4105 */ - sys sys32_newstat 2 - sys sys32_newlstat 2 - sys sys32_newfstat 2 - sys sys_ni_syscall 0 /* was sys_uname */ - sys sys_ni_syscall 0 /* sys_ioperm *//* 4110 */ - sys sys_vhangup 0 - sys sys_ni_syscall 0 /* was sys_idle */ - sys sys_ni_syscall 0 /* sys_vm86 */ - sys sys32_wait4 4 - sys sys_swapoff 1 /* 4115 */ - sys sys_sysinfo 1 + sys compat_sys_getitimer 2 /* 4105 */ + sys compat_sys_newstat 2 + sys compat_sys_newlstat 2 + sys compat_sys_newfstat 2 + sys sys_ni_syscall 0 /* was sys_uname */ + sys sys_ni_syscall 0 /* sys_ioperm *//* 4110 */ + sys sys_vhangup 0 + sys sys_ni_syscall 0 /* was sys_idle */ + sys sys_ni_syscall 0 /* sys_vm86 */ + sys sys32_wait4 4 + sys sys_swapoff 1 /* 4115 */ + sys sys32_sysinfo 1 sys sys32_ipc 6 sys sys_fsync 1 sys sys32_sigreturn 0 @@ -359,11 +429,11 @@ sys sys_ni_syscall 0 /* sys_modify_ldt */ sys sys32_adjtimex 1 sys sys_mprotect 3 /* 4125 */ - sys sys32_sigprocmask 3 - sys sys_create_module 2 + sys compat_sys_sigprocmask 3 + sys sys_ni_syscall 0 /* was creat_module */ sys sys_init_module 5 sys sys_delete_module 1 - sys sys_get_kernel_syms 1 /* 4130 */ + sys sys_ni_syscall 0 /* 4130, get_kernel_syms */ sys sys_quotactl 0 sys sys_getpgid 1 sys sys_fchdir 1 @@ -378,11 +448,11 @@ sys sys32_select 5 sys sys_flock 2 sys sys_msync 3 - sys compat_sys_readv 3 /* 4145 */ - sys compat_sys_writev 3 + sys sys32_readv 3 /* 4145 */ + sys sys32_writev 3 sys sys_cacheflush 3 sys sys_cachectl 3 - sys sys_sysmips 4 + sys sys32_sysmips 4 sys sys_ni_syscall 0 /* 4150 */ sys sys_getsid 1 sys sys_fdatasync 0 @@ -420,7 +490,7 @@ sys sys_socketpair 4 sys sys_setresuid 3 /* 4185 */ sys sys_getresuid 3 - sys sys_query_module 5 + sys sys_ni_syscall 0 /* was query_module */ sys sys_poll 3 sys sys_nfsservctl 3 sys sys_setresgid 3 /* 4190 */ @@ -440,12 +510,12 @@ sys sys_capget 2 sys sys_capset 2 /* 4205 */ sys sys32_sigaltstack 0 - sys sys_sendfile 3 + sys sys32_sendfile 4 sys sys_ni_syscall 0 sys sys_ni_syscall 0 - sys sys_mmap2 6 /* 4210 */ - sys sys_truncate64 2 - sys sys_ftruncate64 2 + sys sys32_mmap2 6 /* 4210 */ + sys sys32_truncate64 4 + sys sys32_ftruncate64 4 sys sys_newstat 2 sys sys_newlstat 2 sys sys_newfstat 2 /* 4215 */ @@ -453,15 +523,50 @@ sys sys_mincore 3 sys sys_madvise 3 sys sys_getdents64 3 - sys sys32_fcntl64 3 /* 4220 */ - sys sys32_gettid 0 - sys sys32_tkill 2 + sys compat_sys_fcntl64 3 /* 4220 */ + sys sys_ni_syscall 0 + sys sys_gettid 0 + sys sys32_readahead 5 + sys sys_setxattr 5 + sys sys_lsetxattr 5 /* 4225 */ + sys sys_fsetxattr 5 + sys sys_getxattr 4 + sys sys_lgetxattr 4 + sys sys_fgetxattr 4 + sys sys_listxattr 3 /* 4230 */ + sys sys_llistxattr 3 + sys sys_flistxattr 3 + sys sys_removexattr 2 + sys sys_lremovexattr 2 + sys sys_fremovexattr 2 /* 4235 */ + sys sys_tkill 2 + sys sys_sendfile64 5 + sys compat_sys_futex 5 + sys sys32_sched_setaffinity 3 + sys sys32_sched_getaffinity 3 /* 4240 */ + sys sys_io_setup 2 + sys sys_io_destroy 1 + sys sys_io_getevents 5 + sys sys_io_submit 3 + sys sys_io_cancel 3 /* 4245 */ + sys sys_exit_group 1 + sys sys_lookup_dcookie 3 + sys sys_epoll_create 1 + sys sys_epoll_ctl 4 + sys sys_epoll_wait 3 /* 4250 */ + sys sys_remap_file_pages 5 + sys sys_set_tid_address 1 + sys sys_restart_syscall 0 + sys sys_fadvise64 6 + sys sys_statfs64 3 /* 4255 */ + sys sys_fstatfs64 2 .endm .macro sys function, nargs PTR \function .endm + .align 3 sys_call_table: syscalltable diff -Nru a/arch/mips64/kernel/setup.c b/arch/mips64/kernel/setup.c --- a/arch/mips64/kernel/setup.c Tue Jul 1 18:44:31 2003 +++ b/arch/mips64/kernel/setup.c Tue Jul 1 18:44:31 2003 @@ -4,16 +4,20 @@ * for more details. * * Copyright (C) 1995 Linus Torvalds - * Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999 Ralf Baechle + * Copyright (C) 1995 Waldorf Electronics + * Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Ralf Baechle * Copyright (C) 1996 Stoned Elipot * Copyright (C) 1999 Silicon Graphics, Inc. + * Copyright (C) 2002 Maciej W. Rozycki */ #include #include #include +#include #include #include #include +#include #include #include #include @@ -23,42 +27,35 @@ #include #include #include +#include #ifdef CONFIG_BLK_DEV_RAM #include #endif +#include +#include +#include -#include +#include #include -#include #include +#include #include #include +#include #include -#ifndef CONFIG_SMP -struct cpuinfo_mips cpu_data[1]; -#endif +struct cpuinfo_mips cpu_data[NR_CPUS]; #ifdef CONFIG_VT struct screen_info screen_info; #endif /* - * Not all of the MIPS CPUs have the "wait" instruction available. This - * is set to true if it is available. The wait instruction stops the - * pipeline and reduces the power consumption of the CPU very much. - */ -char wait_available; - -/* - * Do we have a cyclecounter available? - */ -char cyclecounter_available; - -/* * Set if box has EISA slots. */ +#ifdef CONFIG_EISA int EISA_bus = 0; +#endif #ifdef CONFIG_BLK_DEV_FD extern struct fd_ops no_fd_ops; @@ -70,6 +67,8 @@ struct ide_ops *ide_ops; #endif +extern void * __rd_start, * __rd_end; + extern struct rtc_ops no_rtc_ops; struct rtc_ops *rtc_ops; @@ -81,7 +80,6 @@ * * These are initialized so they are in the .data section */ -unsigned long mips_cputype = CPU_UNKNOWN; unsigned long mips_machtype = MACH_UNKNOWN; unsigned long mips_machgroup = MACH_GROUP_UNKNOWN; @@ -89,70 +87,396 @@ unsigned char aux_device_present; -extern void load_mmu(void); - static char command_line[CL_SIZE] = { 0, }; char saved_command_line[CL_SIZE]; extern char arcs_cmdline[CL_SIZE]; -extern void ip22_setup(void); -extern void ip27_setup(void); +/* + * mips_io_port_base is the begin of the address space to which x86 style + * I/O ports are mapped. + */ +const unsigned long mips_io_port_base = -1; +EXPORT_SYMBOL(mips_io_port_base); + +/* + * isa_slot_offset is the address where E(ISA) busaddress 0 is mapped + * for the processor. + */ +unsigned long isa_slot_offset; +EXPORT_SYMBOL(isa_slot_offset); + +extern void SetUpBootInfo(void); +extern void load_mmu(void); +extern ATTRIB_NORET asmlinkage void start_kernel(void); +extern void prom_init(int, char **, char **, int *); + +static struct resource code_resource = { "Kernel code" }; +static struct resource data_resource = { "Kernel data" }; -static inline void cpu_probe(void) +asmlinkage void __init init_arch(int argc, char **argv, char **envp, + int *prom_vec) { - unsigned int prid = read_32bit_cp0_register(CP0_PRID); + /* Determine which MIPS variant we are running on. */ + cpu_probe(); - switch(prid & 0xff00) { - case PRID_IMP_R4000: - if((prid & 0xff) == PRID_REV_R4400) - mips_cputype = CPU_R4400SC; - else - mips_cputype = CPU_R4000SC; - break; - case PRID_IMP_R4600: - mips_cputype = CPU_R4600; - break; - case PRID_IMP_R4700: - mips_cputype = CPU_R4700; - break; - case PRID_IMP_R5000: - mips_cputype = CPU_R5000; - break; - case PRID_IMP_NEVADA: - mips_cputype = CPU_NEVADA; - break; - case PRID_IMP_R8000: - mips_cputype = CPU_R8000; - break; - case PRID_IMP_R10000: - case PRID_IMP_R12000: - mips_cputype = CPU_R10000; - break; - default: - mips_cputype = CPU_UNKNOWN; + prom_init(argc, argv, envp, prom_vec); + + cpu_report(); + + /* + * Determine the mmu/cache attached to this machine, then flush the + * tlb and caches. On the r4xx0 variants this also sets CP0_WIRED to + * zero. + */ + load_mmu(); + + /* + * On IP27, I am seeing the TS bit set when the kernel is loaded. + * Maybe because the kernel is in ckseg0 and not xkphys? Clear it + * anyway ... + */ + clear_c0_status(ST0_BEV|ST0_TS|ST0_CU1|ST0_CU2|ST0_CU3); + set_c0_status(ST0_CU0|ST0_KX|ST0_SX|ST0_FR); + + start_kernel(); +} + +void __init add_memory_region(phys_t start, phys_t size, + long type) +{ + int x = boot_mem_map.nr_map; + + if (x == BOOT_MEM_MAP_MAX) { + printk("Ooops! Too many entries in the memory map!\n"); + return; } + + boot_mem_map.map[x].addr = start; + boot_mem_map.map[x].size = size; + boot_mem_map.map[x].type = type; + boot_mem_map.nr_map++; } -void __init setup_arch(char **cmdline_p) +static void __init print_memory_map(void) { - cpu_probe(); - load_mmu(); + int i; + + for (i = 0; i < boot_mem_map.nr_map; i++) { + printk(" memory: %016Lx @ %016Lx ", + (unsigned long long) boot_mem_map.map[i].size, + (unsigned long long) boot_mem_map.map[i].addr); + switch (boot_mem_map.map[i].type) { + case BOOT_MEM_RAM: + printk("(usable)\n"); + break; + case BOOT_MEM_ROM_DATA: + printk("(ROM data)\n"); + break; + case BOOT_MEM_RESERVED: + printk("(reserved)\n"); + break; + default: + printk("type %lu\n", boot_mem_map.map[i].type); + break; + } + } +} + +static inline void parse_cmdline_early(void) +{ + char c = ' ', *to = command_line, *from = saved_command_line; + unsigned long start_at, mem_size; + int len = 0; + int usermem = 0; + + printk("Determined physical RAM map:\n"); + print_memory_map(); + + for (;;) { + /* + * "mem=XXX[kKmM]" defines a memory region from + * 0 to , overriding the determined size. + * "mem=XXX[KkmM]@YYY[KkmM]" defines a memory region from + * to +, overriding the determined size. + */ + if (c == ' ' && !memcmp(from, "mem=", 4)) { + if (to != command_line) + to--; + /* + * If a user specifies memory size, we + * blow away any automatically generated + * size. + */ + if (usermem == 0) { + boot_mem_map.nr_map = 0; + usermem = 1; + } + mem_size = memparse(from + 4, &from); + if (*from == '@') + start_at = memparse(from + 1, &from); + else + start_at = 0; + add_memory_region(start_at, mem_size, BOOT_MEM_RAM); + } + c = *(from++); + if (!c) + break; + if (CL_SIZE <= ++len) + break; + *(to++) = c; + } + *to = '\0'; + if (usermem) { + printk("User-defined physical RAM map:\n"); + print_memory_map(); + } +} + + +#define PFN_UP(x) (((x) + PAGE_SIZE - 1) >> PAGE_SHIFT) +#define PFN_DOWN(x) ((x) >> PAGE_SHIFT) +#define PFN_PHYS(x) ((x) << PAGE_SHIFT) + +static inline void bootmem_init(void) +{ +#ifdef CONFIG_BLK_DEV_INITRD + unsigned long tmp; + unsigned long *initrd_header; +#endif + unsigned long bootmap_size; + unsigned long start_pfn, max_pfn; + int i; + +#ifdef CONFIG_BLK_DEV_INITRD + tmp = (((unsigned long)&_end + PAGE_SIZE-1) & PAGE_MASK) - 8; + if (tmp < (unsigned long)&_end) + tmp += PAGE_SIZE; + initrd_header = (unsigned long *)tmp; + if (initrd_header[0] == 0x494E5244) { + initrd_start = (unsigned long)&initrd_header[2]; + initrd_end = initrd_start + initrd_header[1]; + } + start_pfn = PFN_UP(CPHYSADDR((&_end)+(initrd_end - initrd_start) + PAGE_SIZE)); +#else + /* + * Partially used pages are not usable - thus + * we are rounding upwards. + */ + start_pfn = PFN_UP(CPHYSADDR(&_end)); +#endif /* CONFIG_BLK_DEV_INITRD */ + +#ifndef CONFIG_SGI_IP27 + /* Find the highest page frame number we have available. */ + max_pfn = 0; + for (i = 0; i < boot_mem_map.nr_map; i++) { + unsigned long start, end; + + if (boot_mem_map.map[i].type != BOOT_MEM_RAM) + continue; + + start = PFN_UP(boot_mem_map.map[i].addr); + end = PFN_DOWN(boot_mem_map.map[i].addr + + boot_mem_map.map[i].size); + + if (start >= end) + continue; + if (end > max_pfn) + max_pfn = end; + } + + /* Initialize the boot-time allocator. */ + bootmap_size = init_bootmem(start_pfn, max_pfn); + + /* + * Register fully available low RAM pages with the bootmem allocator. + */ + for (i = 0; i < boot_mem_map.nr_map; i++) { + unsigned long curr_pfn, last_pfn, size; + + /* + * Reserve usable memory. + */ + if (boot_mem_map.map[i].type != BOOT_MEM_RAM) + continue; + + /* + * We are rounding up the start address of usable memory: + */ + curr_pfn = PFN_UP(boot_mem_map.map[i].addr); + if (curr_pfn >= max_pfn) + continue; + if (curr_pfn < start_pfn) + curr_pfn = start_pfn; + + /* + * ... and at the end of the usable range downwards: + */ + last_pfn = PFN_DOWN(boot_mem_map.map[i].addr + + boot_mem_map.map[i].size); + + if (last_pfn > max_pfn) + last_pfn = max_pfn; + + /* + * ... finally, did all the rounding and playing + * around just make the area go away? + */ + if (last_pfn <= curr_pfn) + continue; + + size = last_pfn - curr_pfn; + free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size)); + } + + /* Reserve the bootmap memory. */ + reserve_bootmem(PFN_PHYS(start_pfn), bootmap_size); +#endif + +#ifdef CONFIG_BLK_DEV_INITRD + /* Board specific code should have set up initrd_start and initrd_end */ + ROOT_DEV = Root_RAM0; + if (&__rd_start != &__rd_end) { + initrd_start = (unsigned long)&__rd_start; + initrd_end = (unsigned long)&__rd_end; + } + initrd_below_start_ok = 1; + if (initrd_start) { + unsigned long initrd_size = ((unsigned char *)initrd_end) - ((unsigned char *)initrd_start); + printk("Initial ramdisk at: 0x%p (%lu bytes)\n", + (void *)initrd_start, + initrd_size); +/* FIXME: is this right? */ +#ifndef CONFIG_SGI_IP27 + if (CPHYSADDR(initrd_end) > PFN_PHYS(max_pfn)) { + printk("initrd extends beyond end of memory " + "(0x%p > 0x%p)\ndisabling initrd\n", + (void *)CPHYSADDR(initrd_end), + (void *)PFN_PHYS(max_pfn)); + initrd_start = 0; + } +#endif /* !CONFIG_SGI_IP27 */ + } +#endif +} + +static inline void resource_init(void) +{ + int i; + + code_resource.start = virt_to_bus(&_text); + code_resource.end = virt_to_bus(&_etext) - 1; + data_resource.start = virt_to_bus(&_etext); + data_resource.end = virt_to_bus(&_edata) - 1; + + /* + * Request address space for all standard RAM. + */ + for (i = 0; i < boot_mem_map.nr_map; i++) { + struct resource *res; + + res = alloc_bootmem(sizeof(struct resource)); + switch (boot_mem_map.map[i].type) { + case BOOT_MEM_RAM: + case BOOT_MEM_ROM_DATA: + res->name = "System RAM"; + break; + case BOOT_MEM_RESERVED: + default: + res->name = "reserved"; + } + + res->start = boot_mem_map.map[i].addr; + res->end = boot_mem_map.map[i].addr + + boot_mem_map.map[i].size - 1; + + res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; + request_resource(&iomem_resource, res); + + /* + * We don't know which RAM region contains kernel data, + * so we try it repeatedly and let the resource manager + * test it. + */ + request_resource(res, &code_resource); + request_resource(res, &data_resource); + } +} + +#undef PFN_UP +#undef PFN_DOWN +#undef PFN_PHYS + + +void __init setup_arch(char **cmdline_p) +{ + extern void decstation_setup(void); + extern void ip22_setup(void); + extern void ip27_setup(void); + extern void ip32_setup(void); + extern void swarm_setup(void); + extern void malta_setup(void); + extern void momenco_ocelot_setup(void); + extern void momenco_ocelot_g_setup(void); + extern void momenco_ocelot_c_setup(void); + extern void swarm_setup(void); + void frame_info_init(void); + + frame_info_init(); +#ifdef CONFIG_DECSTATION + decstation_setup(); +#endif #ifdef CONFIG_SGI_IP22 ip22_setup(); #endif #ifdef CONFIG_SGI_IP27 ip27_setup(); #endif - -#ifdef CONFIG_ARC_MEMORY - bootmem_init (); +#ifdef CONFIG_SGI_IP32 + ip32_setup(); +#endif +#ifdef CONFIG_SIBYTE_BOARD + swarm_setup(); +#endif +#ifdef CONFIG_MIPS_MALTA + malta_setup(); +#endif +#ifdef CONFIG_MOMENCO_OCELOT + case MACH_GROUP_MOMENCO: + momenco_ocelot_setup(); + break; +#endif +#ifdef CONFIG_MOMENCO_OCELOT_G + case MACH_GROUP_MOMENCO: + momenco_ocelot_g_setup(); + break; #endif +#ifdef CONFIG_MOMENCO_OCELOT_C + case MACH_GROUP_MOMENCO: + momenco_ocelot_c_setup(); + break; +#endif + strlcpy(command_line, arcs_cmdline, sizeof(command_line)); strlcpy(saved_command_line, command_line, sizeof(saved_command_line)); *cmdline_p = command_line; + parse_cmdline_early(); + + bootmem_init(); + paging_init(); + + resource_init(); } + +int __init fpu_disable(char *s) +{ + cpu_data[0].options &= ~MIPS_CPU_FPU; + + return 1; +} + +__setup("nofpu", fpu_disable); diff -Nru a/arch/mips64/kernel/signal.c b/arch/mips64/kernel/signal.c --- a/arch/mips64/kernel/signal.c Tue Jul 1 18:44:33 2003 +++ b/arch/mips64/kernel/signal.c Tue Jul 1 18:44:33 2003 @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -21,118 +22,25 @@ #include #include -#include +#include #include #include #include #include +#include #define DEBUG_SIG 0 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) extern asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs); -extern asmlinkage int save_fp_context(struct sigcontext *sc); -extern asmlinkage int restore_fp_context(struct sigcontext *sc); -extern asmlinkage void syscall_trace(void); - -int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from) -{ - if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t))) - return -EFAULT; - if (from->si_code < 0) - return __copy_to_user(to, from, sizeof(siginfo_t)); - else { - int err; - - /* If you change siginfo_t structure, please be sure - this code is fixed accordingly. - It should never copy any pad contained in the structure - to avoid security leaks, but must copy the generic - 3 ints plus the relevant union member. */ - err = __put_user(from->si_signo, &to->si_signo); - err |= __put_user(from->si_errno, &to->si_errno); - err |= __put_user((short)from->si_code, &to->si_code); - switch (from->si_code >> 16) { - case __SI_FAULT >> 16: - err |= __put_user((long)from->si_addr, &to->si_addr); - break; - case __SI_CHLD >> 16: - err |= __put_user(from->si_utime, &to->si_utime); - err |= __put_user(from->si_stime, &to->si_stime); - err |= __put_user(from->si_status, &to->si_status); - default: - err |= __put_user(from->si_pid, &to->si_pid); - err |= __put_user(from->si_uid, &to->si_uid); - break; - /* case __SI_RT: This is not generated by the kernel as of now. */ - } - return err; - } -} - -static inline int store_fp_context(struct sigcontext *sc) -{ - unsigned int fcr0; - int err = 0; - - err |= __copy_to_user(&sc->sc_fpregs[0], - ¤t->thread.fpu.hard.fp_regs[0], NUM_FPU_REGS * - sizeof(unsigned long)); - err |= __copy_to_user(&sc->sc_fpc_csr, ¤t->thread.fpu.hard.control, - sizeof(unsigned int)); - __asm__ __volatile__("cfc1 %0, $0\n\t" : "=r" (fcr0)); - err |= __copy_to_user(&sc->sc_fpc_eir, &fcr0, sizeof(unsigned int)); - - return err; -} - -static inline int refill_fp_context(struct sigcontext *sc) -{ - int err = 0; - - if (verify_area(VERIFY_READ, sc, sizeof(*sc))) - return -EFAULT; - err |= __copy_from_user(¤t->thread.fpu.hard.fp_regs[0], - &sc->sc_fpregs[0], NUM_FPU_REGS * sizeof(unsigned long)); - err |= __copy_from_user(¤t->thread.fpu.hard.control, &sc->sc_fpc_csr, - sizeof(unsigned int)); - return err; -} +extern asmlinkage void do_syscall_trace(void); /* * Atomically swap in the new signal mask, and wait for a signal. */ -asmlinkage inline int -sys_sigsuspend(abi64_no_regargs, struct pt_regs regs) -{ - sigset_t *uset, saveset, newset; - - save_static(®s); - uset = (sigset_t *) regs.regs[4]; - if (copy_from_user(&newset, uset, sizeof(sigset_t))) - return -EFAULT; - sigdelsetmask(&newset, ~_BLOCKABLE); - - spin_lock_irq(¤t->sigmask_lock); - saveset = current->blocked; - current->blocked = newset; - recalc_sigpending(); - spin_unlock_irq(¤t->sigmask_lock); - - regs.regs[2] = EINTR; - regs.regs[7] = 1; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (do_signal(&saveset, ®s)) - return -EINTR; - } -} - -asmlinkage int -sys_rt_sigsuspend(abi64_no_regargs, struct pt_regs regs) +asmlinkage int sys_rt_sigsuspend(abi64_no_regargs, struct pt_regs regs) { sigset_t *unewset, saveset, newset; size_t sigsetsize; @@ -149,11 +57,11 @@ return -EFAULT; sigdelsetmask(&newset, ~_BLOCKABLE); - spin_lock_irq(¤t->sigmask_lock); + spin_lock_irq(¤t->sighand->siglock); saveset = current->blocked; current->blocked = newset; recalc_sigpending(); - spin_unlock_irq(¤t->sigmask_lock); + spin_unlock_irq(¤t->sighand->siglock); regs.regs[2] = EINTR; regs.regs[7] = 1; @@ -165,47 +73,7 @@ } } -asmlinkage int -sys_sigaction(int sig, const struct sigaction *act, struct sigaction *oact) -{ - struct k_sigaction new_ka, old_ka; - int ret; - int err = 0; - - if (act) { - old_sigset_t mask; - - if (!access_ok(VERIFY_READ, act, sizeof(*act))) - return -EFAULT; - err |= __get_user(new_ka.sa.sa_handler, &act->sa_handler); - err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags); - err |= __get_user(mask, &act->sa_mask.sig[0]); - err |= __get_user(new_ka.sa.sa_restorer, &act->sa_restorer); - if (err) - return -EFAULT; - - siginitset(&new_ka.sa.sa_mask, mask); - } - - ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); - - if (!ret && oact) { - if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact))) - return -EFAULT; - err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags); - err |= __put_user(old_ka.sa.sa_handler, &oact->sa_handler); - err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig); - err |= __put_user(0, &oact->sa_mask.sig[1]); - err |= __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer); - if (err) - return -EFAULT; - } - - return ret; -} - -asmlinkage int -sys_sigaltstack(abi64_no_regargs, struct pt_regs regs) +asmlinkage int sys_sigaltstack(abi64_no_regargs, struct pt_regs regs) { const stack_t *uss = (const stack_t *) regs.regs[4]; stack_t *uoss = (stack_t *) regs.regs[5]; @@ -214,10 +82,8 @@ return do_sigaltstack(uss, uoss, usp); } -asmlinkage int -restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc) +asmlinkage int restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc) { - int owned_fp; int err = 0; err |= __get_user(regs->cp0_epc, &sc->sc_pc); @@ -240,26 +106,20 @@ restore_gp_reg(31); #undef restore_gp_reg - err |= __get_user(owned_fp, &sc->sc_ownedfp); - if (owned_fp) { - if (IS_FPU_OWNER()) { - CLEAR_FPU_OWNER(); - regs->cp0_status &= ~ST0_CU1; - } - current->used_math = 1; - err |= refill_fp_context(sc); + err |= __get_user(current->used_math, &sc->sc_used_math); + + if (current->used_math) { + /* restore fpu context if we have used it before */ + own_fpu(); + err |= restore_fp_context(sc); + } else { + /* signal handler may have used FPU. Give it up. */ + loose_fpu(); } return err; } -struct sigframe { - u32 sf_ass[4]; /* argument save space for o32 */ - u32 sf_code[2]; /* signal trampoline */ - struct sigcontext sf_sc; - sigset_t sf_mask; -}; - struct rt_sigframe { u32 rs_ass[4]; /* argument save space for o32 */ u32 rs_code[2]; /* signal trampoline */ @@ -267,42 +127,6 @@ struct ucontext rs_uc; }; -asmlinkage void sys_sigreturn(abi64_no_regargs, struct pt_regs regs) -{ - struct sigframe *frame; - sigset_t blocked; - - frame = (struct sigframe *) regs.regs[29]; - if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) - goto badframe; - if (__copy_from_user(&blocked, &frame->sf_mask, sizeof(blocked))) - goto badframe; - - sigdelsetmask(&blocked, ~_BLOCKABLE); - spin_lock_irq(¤t->sigmask_lock); - current->blocked = blocked; - recalc_sigpending(); - spin_unlock_irq(¤t->sigmask_lock); - - if (restore_sigcontext(®s, &frame->sf_sc)) - goto badframe; - - /* - * Don't let your children do this ... - */ - if (current->ptrace & PT_TRACESYS) - syscall_trace(); - __asm__ __volatile__( - "move\t$29, %0\n\t" - "j\tret_from_sys_call" - :/* no outputs */ - :"r" (®s)); - /* Unreached */ - -badframe: - force_sig(SIGSEGV, current); -} - asmlinkage void sys_rt_sigreturn(abi64_no_regargs, struct pt_regs regs) { struct rt_sigframe *frame; @@ -316,10 +140,10 @@ goto badframe; sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sigmask_lock); + spin_lock_irq(¤t->sighand->siglock); current->blocked = set; recalc_sigpending(); - spin_unlock_irq(¤t->sigmask_lock); + spin_unlock_irq(¤t->sighand->siglock); if (restore_sigcontext(®s, &frame->rs_uc.uc_mcontext)) goto badframe; @@ -335,7 +159,7 @@ */ __asm__ __volatile__( "move\t$29, %0\n\t" - "j\tret_from_sys_call" + "j\tsyscall_exit" :/* no outputs */ :"r" (®s)); /* Unreached */ @@ -344,12 +168,12 @@ force_sig(SIGSEGV, current); } -static inline int setup_sigcontext(struct pt_regs *regs, - struct sigcontext *sc) +static inline int setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc) { int err = 0; err |= __put_user(regs->cp0_epc, &sc->sc_pc); + err |= __put_user(regs->cp0_status, &sc->sc_status); #define save_gp_reg(i) do { \ err |= __put_user(regs->regs[i], &sc->sc_regs[i]); \ @@ -370,20 +194,22 @@ err |= __put_user(regs->cp0_cause, &sc->sc_cause); err |= __put_user(regs->cp0_badvaddr, &sc->sc_badvaddr); - if (current->used_math) { /* fp is active. */ - if (IS_FPU_OWNER()) { - lazy_fpu_switch(current, 0); - CLEAR_FPU_OWNER(); - regs->cp0_status &= ~ST0_CU1; - } - err |= __put_user(1, &sc->sc_ownedfp); - err |= store_fp_context(sc); - current->used_math = 0; - } else { - err |= __put_user(0, &sc->sc_ownedfp); + err |= __put_user(current->used_math, &sc->sc_used_math); + + if (!current->used_math) + goto out; + + /* + * Save FPU state to signal context. Signal handler will "inherit" + * current FPU state. + */ + if (!is_fpu_owner()) { + own_fpu(); + restore_fp(current); } - err |= __put_user(regs->cp0_status, &sc->sc_status); + err |= save_fp_context(sc); +out: return err; } @@ -391,13 +217,20 @@ * Determine which stack to use.. */ static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, - size_t frame_size) + size_t frame_size) { unsigned long sp; /* Default to using normal stack */ sp = regs->regs[29]; + /* + * FPU emulator may have it's own trampoline active just + * above the user stack, 16-bytes before the next lowest + * 16 byte boundary. Try to avoid trashing it. + */ + sp -= 32; + /* This is the X/Open sanctioned signal stack switching. */ if ((ka->sa.sa_flags & SA_ONSTACK) && ! on_sig_stack(sp)) sp = current->sas_ss_sp + current->sas_ss_size; @@ -405,96 +238,25 @@ return (void *)((sp - frame_size) & ALMASK); } -static void inline setup_frame(struct k_sigaction * ka, struct pt_regs *regs, - int signr, sigset_t *set) +static void inline setup_rt_frame(struct k_sigaction * ka, + struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info) { - struct sigframe *frame; + struct rt_sigframe *frame; int err = 0; frame = get_sigframe(ka, regs, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) goto give_sigsegv; - /* Set up to return from userspace. If provided, use a stub already - in userspace. */ - if (ka->sa.sa_flags & SA_RESTORER) - regs->regs[31] = (unsigned long) ka->sa.sa_restorer; - else { - /* - * Set up the return code ... - * - * li v0, __NR_sigreturn - * syscall - */ - err |= __put_user(0x24020000 + __NR_sigreturn, - frame->sf_code + 0); - err |= __put_user(0x0000000c , - frame->sf_code + 1); - flush_cache_sigtramp((unsigned long) frame->sf_code); - } - - err |= setup_sigcontext(regs, &frame->sf_sc); - err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set)); - if (err) - goto give_sigsegv; - /* - * Arguments to signal handler: - * - * a0 = signal number - * a1 = 0 (should be cause) - * a2 = pointer to struct sigcontext + * Set up the return code ... * - * $25 and c0_epc point to the signal handler, $29 points to the - * struct sigframe. + * li v0, __NR_rt_sigreturn + * syscall */ - regs->regs[ 4] = signr; - regs->regs[ 5] = 0; - regs->regs[ 6] = (unsigned long) &frame->sf_sc; - regs->regs[29] = (unsigned long) frame; - regs->regs[31] = (unsigned long) frame->sf_code; - regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; - -#if DEBUG_SIG - printk("SIG deliver (%s:%d): sp=0x%p pc=0x%p ra=0x%p\n", - current->comm, current->pid, frame, regs->cp0_epc, frame->code); -#endif - return; - -give_sigsegv: - if (signr == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - force_sig(SIGSEGV, current); -} - -static void inline setup_rt_frame(struct k_sigaction * ka, - struct pt_regs *regs, int signr, - sigset_t *set, siginfo_t *info) -{ - struct rt_sigframe *frame; - int err = 0; - - frame = get_sigframe(ka, regs, sizeof(*frame)); - if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) - goto give_sigsegv; - - /* Set up to return from userspace. If provided, use a stub already - in userspace. */ - if (ka->sa.sa_flags & SA_RESTORER) - regs->regs[31] = (unsigned long) ka->sa.sa_restorer; - else { - /* - * Set up the return code ... - * - * li v0, __NR_rt_sigreturn - * syscall - */ - err |= __put_user(0x24020000 + __NR_rt_sigreturn, - frame->rs_code + 0); - err |= __put_user(0x0000000c , - frame->rs_code + 1); - flush_cache_sigtramp((unsigned long) frame->rs_code); - } + err |= __put_user(0x24020000 + __NR_rt_sigreturn, frame->rs_code + 0); + err |= __put_user(0x0000000c , frame->rs_code + 1); + flush_cache_sigtramp((unsigned long) frame->rs_code); /* Create siginfo. */ err |= copy_siginfo_to_user(&frame->rs_info, info); @@ -532,8 +294,9 @@ regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; #if DEBUG_SIG - printk("SIG deliver (%s:%d): sp=0x%p pc=0x%p ra=0x%p\n", - current->comm, current->pid, frame, regs->cp0_epc, frame->code); + printk("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%p\n", + current->comm, current->pid, + frame, regs->cp0_epc, regs->regs[31]); #endif return; @@ -544,29 +307,10 @@ } static inline void handle_signal(unsigned long sig, siginfo_t *info, - sigset_t *oldset, struct pt_regs *regs) + sigset_t *oldset, struct pt_regs *regs) { - struct k_sigaction *ka = ¤t->sig->action[sig-1]; - - if (ka->sa.sa_flags & SA_SIGINFO) - setup_rt_frame(ka, regs, sig, oldset, info); - else - setup_frame(ka, regs, sig, oldset); - - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; - if (!(ka->sa.sa_flags & SA_NODEFER)) { - spin_lock_irq(¤t->sigmask_lock); - sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); - sigaddset(¤t->blocked,sig); - recalc_sigpending(); - spin_unlock_irq(¤t->sigmask_lock); - } -} + struct k_sigaction *ka = ¤t->sighand->action[sig-1]; -static inline void syscall_restart(struct pt_regs *regs, - struct k_sigaction *ka) -{ switch(regs->regs[0]) { case ERESTARTNOHAND: regs->regs[2] = EINTR; @@ -583,10 +327,23 @@ } regs->regs[0] = 0; /* Don't deal with this again. */ + + setup_rt_frame(ka, regs, sig, oldset, info); + + if (ka->sa.sa_flags & SA_ONESHOT) + ka->sa.sa_handler = SIG_DFL; + if (!(ka->sa.sa_flags & SA_NODEFER)) { + spin_lock_irq(¤t->sighand->siglock); + sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + sigaddset(¤t->blocked,sig); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + } } -extern int do_irix_signal(sigset_t *oldset, struct pt_regs *regs); + extern int do_signal32(sigset_t *oldset, struct pt_regs *regs); +extern int do_irix_signal(sigset_t *oldset, struct pt_regs *regs); asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) { @@ -594,7 +351,7 @@ int signr; #ifdef CONFIG_BINFMT_ELF32 - if (current->thread.mflags & MF_32BIT) { + if (current->thread.mflags & MF_32BIT_REGS) { return do_signal32(oldset, regs); } #endif @@ -604,9 +361,6 @@ signr = get_signal_to_deliver(&info, regs, NULL); if (signr > 0) { - if (regs->regs[0]) - syscall_restart(regs, ka); - /* Whee! Actually deliver the signal. */ handle_signal(signr, &info, oldset, regs); return 1; } @@ -625,4 +379,30 @@ } } return 0; +} + + +/* + * notification of userspace execution resumption + * - triggered by current->work.notify_resume + */ +asmlinkage void do_notify_resume(struct pt_regs *regs, sigset_t *oldset, + __u32 thread_info_flags) +{ + /* deal with pending signal delivery */ + if (thread_info_flags & _TIF_SIGPENDING) { +#ifdef CONFIG_BINFMT_ELF32 + if (likely((current->thread.mflags & MF_32BIT_REGS))) { + do_signal32(oldset, regs); + return; + } +#endif +#ifdef CONFIG_BINFMT_IRIX + if (unlikely(current->personality != PER_LINUX)) { + do_irix_signal(oldset, regs); + return; + } +#endif + do_signal(oldset, regs); + } } diff -Nru a/arch/mips64/kernel/signal32.c b/arch/mips64/kernel/signal32.c --- a/arch/mips64/kernel/signal32.c Tue Jul 1 18:44:35 2003 +++ b/arch/mips64/kernel/signal32.c Tue Jul 1 18:44:35 2003 @@ -26,25 +26,20 @@ #include #include #include +#include #define DEBUG_SIG 0 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) extern asmlinkage int do_signal32(sigset_t *oldset, struct pt_regs *regs); -extern asmlinkage int save_fp_context(struct sigcontext *sc); -extern asmlinkage int restore_fp_context(struct sigcontext *sc); -extern asmlinkage void syscall_trace(void); +extern asmlinkage void do_syscall_trace(void); /* 32-bit compatibility types */ -#define _NSIG32_BPW 32 -#define _NSIG32_WORDS (_NSIG / _NSIG32_BPW) - -typedef struct { - unsigned int sig[_NSIG32_WORDS]; -} sigset32_t; +#define _NSIG_BPW32 32 +#define _NSIG_WORDS32 (_NSIG / _NSIG_BPW32) typedef unsigned int __sighandler32_t; typedef void (*vfptr_t)(void); @@ -52,9 +47,7 @@ struct sigaction32 { unsigned int sa_flags; __sighandler32_t sa_handler; - sigset32_t sa_mask; - unsigned int sa_restorer; - int sa_resv[1]; /* reserved */ + compat_sigset_t sa_mask; }; /* IRIX compatible stack_t */ @@ -64,41 +57,10 @@ int ss_flags; } stack32_t; - -static inline int store_fp_context(struct sigcontext *sc) -{ - unsigned int fcr0; - int err = 0; - - err |= __copy_to_user(&sc->sc_fpregs[0], - ¤t->thread.fpu.hard.fp_regs[0], NUM_FPU_REGS * - sizeof(unsigned long)); - err |= __copy_to_user(&sc->sc_fpc_csr, ¤t->thread.fpu.hard.control, - sizeof(unsigned int)); - __asm__ __volatile__("cfc1 %0, $0\n\t" : "=r" (fcr0)); - err |= __copy_to_user(&sc->sc_fpc_eir, &fcr0, sizeof(unsigned int)); - - return err; -} - -static inline int refill_fp_context(struct sigcontext *sc) -{ - int err = 0; - - if (verify_area(VERIFY_READ, sc, sizeof(*sc))) - return -EFAULT; - err |= __copy_from_user(¤t->thread.fpu.hard.fp_regs[0], - &sc->sc_fpregs[0], NUM_FPU_REGS * sizeof(unsigned long)); - err |= __copy_from_user(¤t->thread.fpu.hard.control, &sc->sc_fpc_csr, - sizeof(unsigned int)); - return err; -} - extern void __put_sigset_unknown_nsig(void); extern void __get_sigset_unknown_nsig(void); -static inline int -put_sigset(const sigset_t *kbuf, sigset32_t *ubuf) +static inline int put_sigset(const sigset_t *kbuf, compat_sigset_t *ubuf) { int err = 0; @@ -119,8 +81,7 @@ return err; } -static inline int -get_sigset(sigset_t *kbuf, const sigset32_t *ubuf) +static inline int get_sigset(sigset_t *kbuf, const compat_sigset_t *ubuf) { int err = 0; unsigned long sig[4]; @@ -147,23 +108,22 @@ /* * Atomically swap in the new signal mask, and wait for a signal. */ -asmlinkage inline int -sys32_sigsuspend(abi64_no_regargs, struct pt_regs regs) +asmlinkage inline int sys32_sigsuspend(abi64_no_regargs, struct pt_regs regs) { - sigset32_t *uset; + compat_sigset_t *uset; sigset_t newset, saveset; save_static(®s); - uset = (sigset32_t *) regs.regs[4]; + uset = (compat_sigset_t *) regs.regs[4]; if (get_sigset(&newset, uset)) return -EFAULT; sigdelsetmask(&newset, ~_BLOCKABLE); - spin_lock_irq(¤t->sigmask_lock); + spin_lock_irq(¤t->sighand->siglock); saveset = current->blocked; current->blocked = newset; recalc_sigpending(); - spin_unlock_irq(¤t->sigmask_lock); + spin_unlock_irq(¤t->sighand->siglock); regs.regs[2] = EINTR; regs.regs[7] = 1; @@ -175,29 +135,28 @@ } } -asmlinkage int -sys32_rt_sigsuspend(abi64_no_regargs, struct pt_regs regs) +asmlinkage int sys32_rt_sigsuspend(abi64_no_regargs, struct pt_regs regs) { - sigset32_t *uset; + compat_sigset_t *uset; sigset_t newset, saveset; size_t sigsetsize; save_static(®s); /* XXX Don't preclude handling different sized sigset_t's. */ sigsetsize = regs.regs[5]; - if (sigsetsize != sizeof(sigset32_t)) + if (sigsetsize != sizeof(compat_sigset_t)) return -EINVAL; - uset = (sigset32_t *) regs.regs[4]; + uset = (compat_sigset_t *) regs.regs[4]; if (get_sigset(&newset, uset)) return -EFAULT; sigdelsetmask(&newset, ~_BLOCKABLE); - spin_lock_irq(¤t->sigmask_lock); + spin_lock_irq(¤t->sighand->siglock); saveset = current->blocked; current->blocked = newset; recalc_sigpending(); - spin_unlock_irq(¤t->sigmask_lock); + spin_unlock_irq(¤t->sighand->siglock); regs.regs[2] = EINTR; regs.regs[7] = 1; @@ -225,8 +184,6 @@ &act->sa_handler); err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags); err |= __get_user(mask, &act->sa_mask.sig[0]); - err |= __get_user((u32)(u64)new_ka.sa.sa_restorer, - &act->sa_restorer); if (err) return -EFAULT; @@ -245,8 +202,6 @@ err |= __put_user(0, &oact->sa_mask.sig[1]); err |= __put_user(0, &oact->sa_mask.sig[2]); err |= __put_user(0, &oact->sa_mask.sig[3]); - err |= __put_user((u32)(u64)old_ka.sa.sa_restorer, - &oact->sa_restorer); if (err) return -EFAULT; } @@ -254,8 +209,7 @@ return ret; } -asmlinkage int -sys32_sigaltstack(abi64_no_regargs, struct pt_regs regs) +asmlinkage int sys32_sigaltstack(abi64_no_regargs, struct pt_regs regs) { const stack32_t *uss = (const stack32_t *) regs.regs[4]; stack32_t *uoss = (stack32_t *) regs.regs[5]; @@ -293,10 +247,9 @@ return ret; } -static asmlinkage int -restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc) +static asmlinkage int restore_sigcontext(struct pt_regs *regs, + struct sigcontext *sc) { - int owned_fp; int err = 0; err |= __get_user(regs->cp0_epc, &sc->sc_pc); @@ -319,14 +272,15 @@ restore_gp_reg(31); #undef restore_gp_reg - err |= __get_user(owned_fp, &sc->sc_ownedfp); - if (owned_fp) { - if (IS_FPU_OWNER()) { - CLEAR_FPU_OWNER(); - regs->cp0_status &= ~ST0_CU1; - } - current->used_math = 1; - err |= refill_fp_context(sc); + err |= __get_user(current->used_math, &sc->sc_used_math); + + if (current->used_math) { + /* restore fpu context if we have used it before */ + own_fpu(); + err |= restore_fp_context(sc); + } else { + /* signal handler may have used FPU. Give it up. */ + loose_fpu(); } return err; @@ -339,15 +293,56 @@ sigset_t sf_mask; }; -struct rt_sigframe { +struct rt_sigframe32 { u32 rs_ass[4]; /* argument save space for o32 */ u32 rs_code[2]; /* signal trampoline */ - struct siginfo rs_info; + struct siginfo32 rs_info; struct ucontext rs_uc; }; -asmlinkage void -sys32_sigreturn(abi64_no_regargs, struct pt_regs regs) +static int copy_siginfo_to_user32(siginfo_t32 *to, siginfo_t *from) +{ + int err; + + if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t32))) + return -EFAULT; + + /* If you change siginfo_t structure, please be sure + this code is fixed accordingly. + It should never copy any pad contained in the structure + to avoid security leaks, but must copy the generic + 3 ints plus the relevant union member. + This routine must convert siginfo from 64bit to 32bit as well + at the same time. */ + err = __put_user(from->si_signo, &to->si_signo); + err |= __put_user(from->si_errno, &to->si_errno); + err |= __put_user((short)from->si_code, &to->si_code); + if (from->si_code < 0) + err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE); + else { + switch (from->si_code >> 16) { + case __SI_CHLD >> 16: + err |= __put_user(from->si_utime, &to->si_utime); + err |= __put_user(from->si_stime, &to->si_stime); + err |= __put_user(from->si_status, &to->si_status); + default: + err |= __put_user(from->si_pid, &to->si_pid); + err |= __put_user(from->si_uid, &to->si_uid); + break; + case __SI_FAULT >> 16: + err |= __put_user((long)from->si_addr, &to->si_addr); + break; + case __SI_POLL >> 16: + err |= __put_user(from->si_band, &to->si_band); + err |= __put_user(from->si_fd, &to->si_fd); + break; + /* case __SI_RT: This is not generated by the kernel as of now. */ + } + } + return err; +} + +asmlinkage void sys32_sigreturn(abi64_no_regargs, struct pt_regs regs) { struct sigframe *frame; sigset_t blocked; @@ -359,10 +354,10 @@ goto badframe; sigdelsetmask(&blocked, ~_BLOCKABLE); - spin_lock_irq(¤t->sigmask_lock); + spin_lock_irq(¤t->sighand->siglock); current->blocked = blocked; recalc_sigpending(); - spin_unlock_irq(¤t->sigmask_lock); + spin_unlock_irq(¤t->sighand->siglock); if (restore_sigcontext(®s, &frame->sf_sc)) goto badframe; @@ -370,11 +365,11 @@ /* * Don't let your children do this ... */ - if (current->ptrace & PT_TRACESYS) - syscall_trace(); + if (current_thread_info()->flags & TIF_SYSCALL_TRACE) + do_syscall_trace(); __asm__ __volatile__( "move\t$29, %0\n\t" - "j\tret_from_sys_call" + "j\tsyscall_exit" :/* no outputs */ :"r" (®s)); /* Unreached */ @@ -383,24 +378,23 @@ force_sig(SIGSEGV, current); } -asmlinkage void -sys32_rt_sigreturn(abi64_no_regargs, struct pt_regs regs) +asmlinkage void sys32_rt_sigreturn(abi64_no_regargs, struct pt_regs regs) { - struct rt_sigframe *frame; + struct rt_sigframe32 *frame; sigset_t set; stack_t st; - frame = (struct rt_sigframe *) regs.regs[29]; + frame = (struct rt_sigframe32 *) regs.regs[29]; if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) goto badframe; if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set))) goto badframe; sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sigmask_lock); + spin_lock_irq(¤t->sighand->siglock); current->blocked = set; recalc_sigpending(); - spin_unlock_irq(¤t->sigmask_lock); + spin_unlock_irq(¤t->sighand->siglock); if (restore_sigcontext(®s, &frame->rs_uc.uc_mcontext)) goto badframe; @@ -416,7 +410,7 @@ */ __asm__ __volatile__( "move\t$29, %0\n\t" - "j\tret_from_sys_call" + "j\tsyscall_exit" :/* no outputs */ :"r" (®s)); /* Unreached */ @@ -425,12 +419,13 @@ force_sig(SIGSEGV, current); } -static inline int -setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc) +static inline int setup_sigcontext(struct pt_regs *regs, + struct sigcontext *sc) { int err = 0; err |= __put_user(regs->cp0_epc, &sc->sc_pc); + err |= __put_user(regs->cp0_status, &sc->sc_status); #define save_gp_reg(i) { \ err |= __put_user(regs->regs[i], &sc->sc_regs[i]); \ @@ -451,34 +446,43 @@ err |= __put_user(regs->cp0_cause, &sc->sc_cause); err |= __put_user(regs->cp0_badvaddr, &sc->sc_badvaddr); - if (current->used_math) { /* fp is active. */ - if (IS_FPU_OWNER()) { - lazy_fpu_switch(current, 0); - CLEAR_FPU_OWNER(); - regs->cp0_status &= ~ST0_CU1; - } - err |= __put_user(1, &sc->sc_ownedfp); - err |= store_fp_context(sc); - current->used_math = 0; - } else { - err |= __put_user(0, &sc->sc_ownedfp); + err |= __put_user(current->used_math, &sc->sc_used_math); + + if (!current->used_math) + goto out; + + /* + * Save FPU state to signal context. Signal handler will "inherit" + * current FPU state. + */ + if (!is_fpu_owner()) { + own_fpu(); + restore_fp(current); } - err |= __put_user(regs->cp0_status, &sc->sc_status); + err |= save_fp_context(sc); +out: return err; } /* * Determine which stack to use.. */ -static inline void * -get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) +static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, + size_t frame_size) { unsigned long sp; /* Default to using normal stack */ sp = regs->regs[29]; + /* + * FPU emulator may have it's own trampoline active just + * above the user stack, 16-bytes before the next lowest + * 16 byte boundary. Try to avoid trashing it. + */ + sp -= 32; + /* This is the X/Open sanctioned signal stack switching. */ if ((ka->sa.sa_flags & SA_ONSTACK) && ! on_sig_stack(sp)) sp = current->sas_ss_sp + current->sas_ss_size; @@ -486,9 +490,8 @@ return (void *)((sp - frame_size) & ALMASK); } -static void inline -setup_frame(struct k_sigaction * ka, struct pt_regs *regs, - int signr, sigset_t *set) +static inline void setup_frame(struct k_sigaction * ka, struct pt_regs *regs, + int signr, sigset_t *set) { struct sigframe *frame; int err = 0; @@ -497,23 +500,15 @@ if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) goto give_sigsegv; - /* Set up to return from userspace. If provided, use a stub already - in userspace. */ - if (ka->sa.sa_flags & SA_RESTORER) - regs->regs[31] = (unsigned long) ka->sa.sa_restorer; - else { - /* - * Set up the return code ... - * - * li v0, __NR_Linux32_sigreturn - * syscall - */ - err |= __put_user(0x24020000 + __NR_Linux32_sigreturn, - frame->sf_code + 0); - err |= __put_user(0x0000000c , - frame->sf_code + 1); - flush_cache_sigtramp((unsigned long) frame->sf_code); - } + /* + * Set up the return code ... + * + * li v0, __NR_O32_sigreturn + * syscall + */ + err |= __put_user(0x24020000 + __NR_O32_sigreturn, frame->sf_code + 0); + err |= __put_user(0x0000000c , frame->sf_code + 1); + flush_cache_sigtramp((unsigned long) frame->sf_code); err |= setup_sigcontext(regs, &frame->sf_sc); err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set)); @@ -538,8 +533,9 @@ regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; #if DEBUG_SIG - printk("SIG deliver (%s:%d): sp=0x%p pc=0x%p ra=0x%p\n", - current->comm, current->pid, frame, regs->cp0_epc, frame->code); + printk("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%p\n", + current->comm, current->pid, + frame, regs->cp0_epc, frame->sf_code); #endif return; @@ -549,11 +545,11 @@ force_sig(SIGSEGV, current); } -static void inline -setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, - int signr, sigset_t *set, siginfo_t *info) +static inline void setup_rt_frame(struct k_sigaction * ka, + struct pt_regs *regs, int signr, + sigset_t *set, siginfo_t *info) { - struct rt_sigframe *frame; + struct rt_sigframe32 *frame; int err = 0; frame = get_sigframe(ka, regs, sizeof(*frame)); @@ -562,24 +558,18 @@ /* Set up to return from userspace. If provided, use a stub already in userspace. */ - if (ka->sa.sa_flags & SA_RESTORER) - regs->regs[31] = (unsigned long) ka->sa.sa_restorer; - else { - /* - * Set up the return code ... - * - * li v0, __NR_Linux32_rt_sigreturn - * syscall - */ - err |= __put_user(0x24020000 + __NR_Linux32_rt_sigreturn, - frame->rs_code + 0); - err |= __put_user(0x0000000c , - frame->rs_code + 1); - flush_cache_sigtramp((unsigned long) frame->rs_code); - } + /* + * Set up the return code ... + * + * li v0, __NR_O32_rt_sigreturn + * syscall + */ + err |= __put_user(0x24020000 + __NR_O32_rt_sigreturn, frame->rs_code + 0); + err |= __put_user(0x0000000c , frame->rs_code + 1); + flush_cache_sigtramp((unsigned long) frame->rs_code); - /* Create siginfo. */ - err |= __copy_to_user(&frame->rs_info, info, sizeof(*info)); + /* Convert (siginfo_t -> siginfo_t32) and copy to user. */ + err |= copy_siginfo_to_user32(&frame->rs_info, info); /* Create the ucontext. */ err |= __put_user(0, &frame->rs_uc.uc_flags); @@ -604,7 +594,7 @@ * a2 = pointer to ucontext * * $25 and c0_epc point to the signal handler, $29 points to - * the struct rt_sigframe. + * the struct rt_sigframe32. */ regs->regs[ 4] = signr; regs->regs[ 5] = (unsigned long) &frame->rs_info; @@ -614,8 +604,9 @@ regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; #if DEBUG_SIG - printk("SIG deliver (%s:%d): sp=0x%p pc=0x%p ra=0x%p\n", - current->comm, current->pid, frame, regs->cp0_epc, frame->code); + printk("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%p\n", + current->comm, current->pid, + frame, regs->cp0_epc, frame->rs_code); #endif return; @@ -625,32 +616,12 @@ force_sig(SIGSEGV, current); } -static inline void -handle_signal(unsigned long sig siginfo_t *info, sigset_t *oldset, - struct pt_regs * regs) +static inline void handle_signal(unsigned long sig, siginfo_t *info, + sigset_t *oldset, struct pt_regs * regs) { - struct k_sigaction *ka = ¤t->sig->action[sig-1]; + struct k_sigaction *ka = ¤t->sighand->action[sig-1]; - if (ka->sa.sa_flags & SA_SIGINFO) - setup_rt_frame(ka, regs, sig, oldset, info); - else - setup_frame(ka, regs, sig, oldset); - - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; - if (!(ka->sa.sa_flags & SA_NODEFER)) { - spin_lock_irq(¤t->sigmask_lock); - sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); - sigaddset(¤t->blocked,sig); - recalc_sigpending(); - spin_unlock_irq(¤t->sigmask_lock); - } -} - -static inline void -syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) -{ - switch(regs->regs[0]) { + switch (regs->regs[0]) { case ERESTARTNOHAND: regs->regs[2] = EINTR; break; @@ -666,6 +637,21 @@ } regs->regs[0] = 0; /* Don't deal with this again. */ + + if (ka->sa.sa_flags & SA_SIGINFO) + setup_rt_frame(ka, regs, sig, oldset, info); + else + setup_frame(ka, regs, sig, oldset); + + if (ka->sa.sa_flags & SA_ONESHOT) + ka->sa.sa_handler = SIG_DFL; + if (!(ka->sa.sa_flags & SA_NODEFER)) { + spin_lock_irq(¤t->sighand->siglock); + sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + sigaddset(¤t->blocked,sig); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + } } asmlinkage int do_signal32(sigset_t *oldset, struct pt_regs *regs) @@ -678,9 +664,6 @@ signr = get_signal_to_deliver(&info, regs, NULL); if (signr > 0) { - if (regs->regs[0]) - syscall_restart(regs, ka); - /* Whee! Actually deliver the signal. */ handle_signal(signr, &info, oldset, regs); return 1; } @@ -701,44 +684,6 @@ return 0; } -extern asmlinkage int sys_sigprocmask(int how, old_sigset_t *set, - old_sigset_t *oset); - -asmlinkage int sys32_sigprocmask(int how, old_sigset_t32 *set, - old_sigset_t32 *oset) -{ - old_sigset_t s; - int ret; - mm_segment_t old_fs = get_fs(); - - if (set && get_user (s, set)) - return -EFAULT; - set_fs (KERNEL_DS); - ret = sys_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL); - set_fs (old_fs); - if (!ret && oset && put_user (s, oset)) - return -EFAULT; - return ret; -} - -asmlinkage long sys_sigpending(old_sigset_t *set); - -asmlinkage int sys32_sigpending(old_sigset_t32 *set) -{ - old_sigset_t pending; - int ret; - mm_segment_t old_fs = get_fs(); - - set_fs (KERNEL_DS); - ret = sys_sigpending(&pending); - set_fs (old_fs); - - if (put_user(pending, set)) - return -EFAULT; - - return ret; -} - asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 *act, struct sigaction32 *oact, unsigned int sigsetsize) @@ -758,8 +703,6 @@ err |= __get_user((u32)(u64)new_sa.sa.sa_handler, &act->sa_handler); err |= __get_user(new_sa.sa.sa_flags, &act->sa_flags); - err |= __get_user((u32)(u64)new_sa.sa.sa_restorer, - &act->sa_restorer); err |= get_sigset(&new_sa.sa.sa_mask, &act->sa_mask); if (err) return -EFAULT; @@ -776,8 +719,6 @@ err |= __put_user((u32)(u64)old_sa.sa.sa_handler, &oact->sa_handler); err |= __put_user(old_sa.sa.sa_flags, &oact->sa_flags); - err |= __put_user((u32)(u64)old_sa.sa.sa_restorer, - &oact->sa_restorer); err |= put_sigset(&old_sa.sa.sa_mask, &oact->sa_mask); if (err) return -EFAULT; @@ -789,8 +730,8 @@ asmlinkage long sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset, size_t sigsetsize); -asmlinkage int sys32_rt_sigprocmask(int how, sigset32_t *set, sigset32_t *oset, - unsigned int sigsetsize) +asmlinkage int sys32_rt_sigprocmask(int how, compat_sigset_t *set, + compat_sigset_t *oset, unsigned int sigsetsize) { sigset_t old_set, new_set; int ret; @@ -798,7 +739,7 @@ if (set && get_sigset(&new_set, set)) return -EFAULT; - + set_fs (KERNEL_DS); ret = sys_rt_sigprocmask(how, set ? &new_set : NULL, oset ? &old_set : NULL, sigsetsize); @@ -812,7 +753,8 @@ asmlinkage long sys_rt_sigpending(sigset_t *set, size_t sigsetsize); -asmlinkage int sys32_rt_sigpending(sigset32_t *uset, unsigned int sigsetsize) +asmlinkage int sys32_rt_sigpending(compat_sigset_t *uset, + unsigned int sigsetsize) { int ret; sigset_t set; @@ -828,5 +770,110 @@ return ret; } -asmlinkage void sys32_rt_sigtimedwait(void) { panic(__FUNCTION__ " called."); } -asmlinkage void sys32_rt_sigqueueinfo(void) { panic(__FUNCTION__ " called."); } +asmlinkage int sys32_rt_sigtimedwait(compat_sigset_t *uthese, + siginfo_t32 *uinfo, struct compat_timespec *uts, + compat_time_t sigsetsize) +{ + int ret, sig; + sigset_t these; + compat_sigset_t these32; + struct timespec ts; + siginfo_t info; + long timeout = 0; + + /* + * As the result of a brainfarting competition a few years ago the + * size of sigset_t for the 32-bit kernel was choosen to be 128 bits + * but nothing so far is actually using that many, 64 are enough. So + * for now we just drop the high bits. + */ + if (copy_from_user (&these32, uthese, sizeof(compat_old_sigset_t))) + return -EFAULT; + + switch (_NSIG_WORDS) { +#ifdef __MIPSEB__ + case 4: these.sig[3] = these32.sig[6] | (((long)these32.sig[7]) << 32); + case 3: these.sig[2] = these32.sig[4] | (((long)these32.sig[5]) << 32); + case 2: these.sig[1] = these32.sig[2] | (((long)these32.sig[3]) << 32); + case 1: these.sig[0] = these32.sig[0] | (((long)these32.sig[1]) << 32); +#endif +#ifdef __MIPSEL__ + case 4: these.sig[3] = these32.sig[7] | (((long)these32.sig[6]) << 32); + case 3: these.sig[2] = these32.sig[5] | (((long)these32.sig[4]) << 32); + case 2: these.sig[1] = these32.sig[3] | (((long)these32.sig[2]) << 32); + case 1: these.sig[0] = these32.sig[1] | (((long)these32.sig[0]) << 32); +#endif + } + + /* + * Invert the set of allowed signals to get those we + * want to block. + */ + sigdelsetmask(&these, sigmask(SIGKILL)|sigmask(SIGSTOP)); + signotset(&these); + + if (uts) { + if (get_user (ts.tv_sec, &uts->tv_sec) || + get_user (ts.tv_nsec, &uts->tv_nsec)) + return -EINVAL; + if (ts.tv_nsec >= 1000000000L || ts.tv_nsec < 0 + || ts.tv_sec < 0) + return -EINVAL; + } + + spin_lock_irq(¤t->sighand->siglock); + sig = dequeue_signal(current, &these, &info); + if (!sig) { + /* None ready -- temporarily unblock those we're interested + in so that we'll be awakened when they arrive. */ + sigset_t oldblocked = current->blocked; + sigandsets(¤t->blocked, ¤t->blocked, &these); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + + timeout = MAX_SCHEDULE_TIMEOUT; + if (uts) + timeout = (timespec_to_jiffies(&ts) + + (ts.tv_sec || ts.tv_nsec)); + + current->state = TASK_INTERRUPTIBLE; + timeout = schedule_timeout(timeout); + + spin_lock_irq(¤t->sighand->siglock); + sig = dequeue_signal(current, &these, &info); + current->blocked = oldblocked; + recalc_sigpending(); + } + spin_unlock_irq(¤t->sighand->siglock); + + if (sig) { + ret = sig; + if (uinfo) { + if (copy_siginfo_to_user32(uinfo, &info)) + ret = -EFAULT; + } + } else { + ret = -EAGAIN; + if (timeout) + ret = -EINTR; + } + + return ret; +} + +extern asmlinkage int sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo); + +asmlinkage int sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 *uinfo) +{ + siginfo_t info; + int ret; + mm_segment_t old_fs = get_fs(); + + if (copy_from_user (&info, uinfo, 3*sizeof(int)) || + copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE)) + return -EFAULT; + set_fs (KERNEL_DS); + ret = sys_rt_sigqueueinfo(pid, sig, &info); + set_fs (old_fs); + return ret; +} diff -Nru a/arch/mips64/kernel/smp.c b/arch/mips64/kernel/smp.c --- a/arch/mips64/kernel/smp.c Tue Jul 1 18:44:36 2003 +++ b/arch/mips64/kernel/smp.c Tue Jul 1 18:44:36 2003 @@ -1,100 +1,156 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Copyright (C) 2000, 2001 Kanoj Sarcar + * Copyright (C) 2000, 2001 Ralf Baechle + * Copyright (C) 2000, 2001 Silicon Graphics, Inc. + * Copyright (C) 2000, 2001 Broadcom Corporation + */ #include +#include +#include #include +#include #include #include +#include #include #include #include -#include -#include #include +#include #include #include #include #include -#include +#include -#ifdef CONFIG_SGI_IP27 +int smp_threads_ready; /* Not used */ -#include -#include -#include -#include -#include +// static atomic_t cpus_booted = ATOMIC_INIT(0); +atomic_t cpus_booted = ATOMIC_INIT(0); -#define DORESCHED 0xab -#define DOCALL 0xbc +cpumask_t phys_cpu_present_map; /* Bitmask of physically CPUs */ +cpumask_t cpu_online_map; /* Bitmask of currently online CPUs */ +int __cpu_number_map[NR_CPUS]; +int __cpu_logical_map[NR_CPUS]; -static void sendintr(int destid, unsigned char status) -{ - int irq; +/* These are defined by the board-specific code. */ -#if (CPUS_PER_NODE == 2) - switch (status) { - case DORESCHED: irq = CPU_RESCHED_A_IRQ; break; - case DOCALL: irq = CPU_CALL_A_IRQ; break; - default: panic("sendintr"); - } - irq += cputoslice(destid); +/* + * Cause the function described by call_data to be executed on the passed + * cpu. When the function has finished, increment the finished field of + * call_data. + */ +void core_send_ipi(int cpu, unsigned int action); - /* - * Convert the compact hub number to the NASID to get the correct - * part of the address space. Then set the interrupt bit associated - * with the CPU we want to send the interrupt to. - */ - REMOTE_HUB_SEND_INTR(COMPACT_TO_NASID_NODEID(cputocnode(destid)), - FAST_IRQ_TO_LEVEL(irq)); -#else - << Bomb! Must redefine this for more than 2 CPUS. >> -#endif -} +/* + * Clear all undefined state in the cpu, set up sp and gp to the passed + * values, and kick the cpu into smp_bootstrap(); + */ +void prom_boot_secondary(int cpu, unsigned long sp, unsigned long gp); -#endif /* CONFIG_SGI_IP27 */ +/* + * After we've done initial boot, this function is called to allow the + * board code to clean up state, if needed + */ +void prom_init_secondary(void); + +void prom_smp_finish(void); -/* The 'big kernel lock' */ -int smp_threads_ready; /* Not used */ -atomic_t smp_commenced = ATOMIC_INIT(0); -struct cpuinfo_mips cpu_data[NR_CPUS]; -int smp_num_cpus = 1; /* Number that came online. */ -int __cpu_number_map[NR_CPUS]; -int __cpu_logical_map[NR_CPUS]; cycles_t cacheflush_time; +unsigned long cache_decay_ticks; -static void smp_tune_scheduling (void) +void smp_tune_scheduling (void) { -} + struct cache_desc *cd = ¤t_cpu_data.scache; + unsigned long cachesize; /* kB */ + unsigned long bandwidth = 350; /* MB/s */ + unsigned long cpu_khz; -void __init smp_boot_cpus(void) -{ - extern void allowboot(void); + /* + * Crude estimate until we actually meassure ... + */ + cpu_khz = loops_per_jiffy * 2 * HZ / 1000; - init_new_context(current, &init_mm); - current->processor = 0; - init_idle(); - smp_tune_scheduling(); - allowboot(); -} + /* + * Rough estimation for SMP scheduling, this is the number of + * cycles it takes for a fully memory-limited process to flush + * the SMP-local cache. + * + * (For a P5 this pretty much means we will choose another idle + * CPU almost always at wakeup time (this is due to the small + * L1 cache), on PIIs it's around 50-100 usecs, depending on + * the cache size) + */ + if (!cpu_khz) { + /* + * This basically disables processor-affinity scheduling on SMP + * without a cycle counter. Currently all SMP capable MIPS + * processors have a cycle counter. + */ + cacheflush_time = 0; + return; + } -void __init smp_commence(void) -{ - wmb(); - atomic_set(&smp_commenced,1); + cachesize = cd->linesz * cd->sets * cd->ways; + cacheflush_time = (cpu_khz>>10) * (cachesize<<10) / bandwidth; + cache_decay_ticks = (long)cacheflush_time/cpu_khz * HZ / 1000; + + printk("per-CPU timeslice cutoff: %ld.%02ld usecs.\n", + (long)cacheflush_time/(cpu_khz/1000), + ((long)cacheflush_time*100/(cpu_khz/1000)) % 100); + printk("task migration cache decay timeout: %ld msecs.\n", + (cache_decay_ticks + 1) * 1000 / HZ); +} + +void __init smp_callin(void) +{ +#if 0 + calibrate_delay(); + smp_store_cpu_info(cpuid); +#endif } -static void stop_this_cpu(void *dummy) +#ifndef CONFIG_SGI_IP27 +/* + * Hook for doing final board-specific setup after the generic smp setup + * is done + */ +asmlinkage void start_secondary(void) { + unsigned int cpu = smp_processor_id(); + + cpu_probe(); + prom_init_secondary(); + per_cpu_trap_init(); + /* - * Remove this CPU + * XXX parity protection should be folded in here when it's converted + * to an option instead of something based on .cputype */ - for (;;); -} - -void smp_send_stop(void) -{ - smp_call_function(stop_this_cpu, NULL, 1, 0); - smp_num_cpus = 1; + pgd_current[cpu] = init_mm.pgd; + cpu_data[cpu].udelay_val = loops_per_jiffy; + prom_smp_finish(); + printk("Slave cpu booted successfully\n"); + CPUMASK_SETB(cpu_online_map, cpu); + atomic_inc(&cpus_booted); + cpu_idle(); } +#endif /* CONFIG_SGI_IP27 */ /* * this function sends a 'reschedule' IPI to another CPU. @@ -103,14 +159,12 @@ */ void smp_send_reschedule(int cpu) { - sendintr(cpu, DORESCHED); + core_send_ipi(cpu, SMP_RESCHEDULE_YOURSELF); } -/* Not really SMP stuff ... */ -int setup_profiling_timer(unsigned int multiplier) -{ - return 0; -} +static spinlock_t call_lock = SPIN_LOCK_UNLOCKED; + +struct call_data_struct *call_data; /* * Run a function on all other CPUs. @@ -122,23 +176,18 @@ * * Does not return until remote CPUs are nearly ready to execute * or are or have executed. + * + * You must not call this function with disabled interrupts or from a + * hardware interrupt handler or from a bottom half handler. */ -static volatile struct call_data_struct { - void (*func) (void *info); - void *info; - atomic_t started; - atomic_t finished; - int wait; -} *call_data; - -int smp_call_function (void (*func) (void *info), void *info, int retry, +int smp_call_function (void (*func) (void *info), void *info, int retry, int wait) { struct call_data_struct data; - int i, cpus = smp_num_cpus-1; - static spinlock_t lock = SPIN_LOCK_UNLOCKED; + int i, cpus = num_online_cpus() - 1; + int cpu = smp_processor_id(); - if (cpus == 0) + if (!cpus) return 0; data.func = func; @@ -148,12 +197,13 @@ if (wait) atomic_set(&data.finished, 0); - spin_lock_bh(&lock); + spin_lock(&call_lock); call_data = &data; + /* Send a message to all other CPUs and wait for them to respond */ - for (i = 0; i < smp_num_cpus; i++) - if (smp_processor_id() != i) - sendintr(i, DOCALL); + for (i = 0; i < NR_CPUS; i++) + if (cpu_online(cpu) && cpu != smp_processor_id()) + core_send_ipi(i, SMP_CALL_FUNCTION); /* Wait for response */ /* FIXME: lock-up detection, backtrace on lock-up */ @@ -163,34 +213,62 @@ if (wait) while (atomic_read(&data.finished) != cpus) barrier(); - spin_unlock_bh(&lock); + spin_unlock(&call_lock); + return 0; } -extern void smp_call_function_interrupt(int irq, void *d, struct pt_regs *r) +void smp_call_function_interrupt(void) { void (*func) (void *info) = call_data->func; void *info = call_data->info; int wait = call_data->wait; + irq_enter(); /* * Notify initiating CPU that I've grabbed the data and am * about to execute the function. */ + mb(); atomic_inc(&call_data->started); /* * At this point the info structure may be out of scope unless wait==1. */ + irq_enter(); (*func)(info); - if (wait) + irq_exit(); + + if (wait) { + mb(); atomic_inc(&call_data->finished); + } +} + +static void stop_this_cpu(void *dummy) +{ + /* + * Remove this CPU: + */ + clear_bit(smp_processor_id(), &cpu_online_map); + local_irq_enable(); /* May need to service _machine_restart IPI */ + for (;;); /* Wait if available. */ +} + +void smp_send_stop(void) +{ + smp_call_function(stop_this_cpu, NULL, 1, 0); +} + +/* Not really SMP stuff ... */ +int setup_profiling_timer(unsigned int multiplier) +{ + return 0; } - static void flush_tlb_all_ipi(void *info) { - _flush_tlb_all(); + local_flush_tlb_all(); } void flush_tlb_all(void) @@ -200,15 +278,15 @@ static void flush_tlb_mm_ipi(void *mm) { - _flush_tlb_mm((struct mm_struct *)mm); + local_flush_tlb_mm((struct mm_struct *)mm); } /* - * The following tlb flush calls are invoked when old translations are + * The following tlb flush calls are invoked when old translations are * being torn down, or pte attributes are changing. For single threaded * address spaces, a new context is obtained on the current cpu, and tlb * context on other cpus are invalidated to force a new context allocation - * at switch_mm time, should the mm ever be used on other cpus. For + * at switch_mm time, should the mm ever be used on other cpus. For * multithreaded address spaces, intercpu interrupts have to be sent. * Another case where intercpu interrupts are required is when the target * mm might be active on another cpu (eg debuggers doing the flushes on @@ -224,17 +302,16 @@ smp_call_function(flush_tlb_mm_ipi, (void *)mm, 1, 1); } else { int i; - for (i = 0; i < smp_num_cpus; i++) + for (i = 0; i < num_online_cpus(); i++) if (smp_processor_id() != i) - CPU_CONTEXT(i, mm) = 0; + cpu_context(i, mm) = 0; } - _flush_tlb_mm(mm); + local_flush_tlb_mm(mm); preempt_enable(); } struct flush_tlb_data { - struct mm_struct *mm; struct vm_area_struct *vma; unsigned long addr1; unsigned long addr2; @@ -244,13 +321,14 @@ { struct flush_tlb_data *fd = (struct flush_tlb_data *)info; - _flush_tlb_range(fd->vma, fd->addr1, fd->addr2); + local_flush_tlb_range(fd->vma, fd->addr1, fd->addr2); } void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) { - preempt_disable(); + struct mm_struct *mm = vma->vm_mm; + preempt_disable(); if ((atomic_read(&mm->mm_users) != 1) || (current->mm != mm)) { struct flush_tlb_data fd; @@ -260,26 +338,41 @@ smp_call_function(flush_tlb_range_ipi, (void *)&fd, 1, 1); } else { int i; - for (i = 0; i < smp_num_cpus; i++) + for (i = 0; i < num_online_cpus(); i++) if (smp_processor_id() != i) - CPU_CONTEXT(i, mm) = 0; + cpu_context(i, mm) = 0; } - _flush_tlb_range(mm, start, end); - + local_flush_tlb_range(vma, start, end); preempt_enable(); } +static void flush_tlb_kernel_range_ipi(void *info) +{ + struct flush_tlb_data *fd = (struct flush_tlb_data *)info; + + local_flush_tlb_kernel_range(fd->addr1, fd->addr2); +} + +void flush_tlb_kernel_range(unsigned long start, unsigned long end) +{ + struct flush_tlb_data fd; + + fd.addr1 = start; + fd.addr2 = end; + smp_call_function(flush_tlb_kernel_range_ipi, (void *)&fd, 1, 1); + local_flush_tlb_kernel_range(start, end); +} + static void flush_tlb_page_ipi(void *info) { struct flush_tlb_data *fd = (struct flush_tlb_data *)info; - _flush_tlb_page(fd->vma, fd->addr1); + local_flush_tlb_page(fd->vma, fd->addr1); } void flush_tlb_page(struct vm_area_struct *vma, unsigned long page) { preempt_disable(); - if ((atomic_read(&vma->vm_mm->mm_users) != 1) || (current->mm != vma->vm_mm)) { struct flush_tlb_data fd; @@ -288,12 +381,28 @@ smp_call_function(flush_tlb_page_ipi, (void *)&fd, 1, 1); } else { int i; - for (i = 0; i < smp_num_cpus; i++) + for (i = 0; i < num_online_cpus(); i++) if (smp_processor_id() != i) - CPU_CONTEXT(i, vma->vm_mm) = 0; + cpu_context(i, vma->vm_mm) = 0; } - _flush_tlb_page(vma, page); - + local_flush_tlb_page(vma, page); preempt_enable(); } +static void flush_tlb_one_ipi(void *info) +{ + unsigned long vaddr = (unsigned long) info; + + local_flush_tlb_one(vaddr); +} + +void flush_tlb_one(unsigned long vaddr) +{ + smp_call_function(flush_tlb_one_ipi, (void *) vaddr, 1, 1); + local_flush_tlb_one(vaddr); +} + +EXPORT_SYMBOL(flush_tlb_page); +EXPORT_SYMBOL(flush_tlb_one); +EXPORT_SYMBOL(cpu_data); +EXPORT_SYMBOL(synchronize_irq); diff -Nru a/arch/mips64/kernel/softfp.S b/arch/mips64/kernel/softfp.S --- a/arch/mips64/kernel/softfp.S Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,666 +0,0 @@ -/* - * 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) 1998, 1999, 2000 by Ralf Baechle - * Copyright (C) 1999, 2000 by Silicon Graphics, Inc. - * - * For now it's just a crude hack good enough to run certain fp programs like - * Mozilla. - * XXX: Handle MIPS II/III/IV/V enhancements, exceptions, ... - */ -#include -#include - -#ifndef __KERNEL__ -#define printk printf -#endif - -#define LOCK_KERNEL -#define UNLOCK_KERNEL - -/* - * This duplicates definitions from . - */ -#define KERN_EMERG "<0>" /* system is unusable */ -#define KERN_ALERT "<1>" /* action must be taken immediately */ -#define KERN_CRIT "<2>" /* critical conditions */ -#define KERN_ERR "<3>" /* error conditions */ -#define KERN_WARNING "<4>" /* warning conditions */ -#define KERN_NOTICE "<5>" /* normal but significant condition */ -#define KERN_INFO "<6>" /* informational */ -#define KERN_DEBUG "<7>" /* debug-level messages */ - -/* - * This duplicates definitions from - */ -#define SIGILL 4 /* Illegal instruction (ANSI). */ - -/* - * Definitions about the instruction format - */ -#define fd_shift 6 -#define fr_shift 21 -#define fs_shift 11 -#define ft_shift 16 - -/* - * NaNs as use by the MIPS architecture - */ -#define S_QNaN 0x7fbfffff -#define D_QNaN 0x7ff7ffffffffffff -#define W_QNaN 0x7fffffff -#define L_QNaN 0x7fffffffffffffff - -/* - * Checking for NaNs - */ -#define S_is_QNaN(reg,res) \ - sll res, reg, S_F_size - S_F_bits -#define D_is_QNaN(reg1,reg2,res) \ - sll res, reg1, (D_F_size - 32) - (D_F_bits - 32); \ - or res, reg2 - -/* - * Checking for Denorms - */ -#define S_is_Denorm(reg,res) \ - li res, 1 << (S_F_bits - 1); \ - and reg, res - -/* - * Some constants that define the properties of single precission numbers. - */ -#define S_M_prec 24 -#define S_E_max 127 -#define S_E_min -126 -#define S_E_bias 127 -#define S_E_bits 8 -#define S_F_bits 23 -#define S_F_size 32 - -/* Set temp0, if exponent of reg is S_E_max + 1. */ -#define S_is_E_max(reg,temp0,temp1) \ - li temp0, (S_E_max + 1 + S_E_bias) << S_F_bits; \ - and temp1, temp0, reg; \ - seq temp0, temp1 /* temp0 != 0 if NaN */ - -/* Clear temp0, if exponent of reg is S_E_min - 1. */ -#define S_is_E_min(reg,temp0) \ - li temp0, (S_E_min - 1 + S_E_bias) << S_F_bits; \ - and temp0, reg /* temp0 == 0 if denorm or zero */ - -/* Set temp0 if reg is a NaN assuming S_is_E_max is true */ -#define S_get_F(reg,temp0) \ - li temp0, (1 << S_F_bits) - 1; \ - and temp0, reg /* temp0 != 0 if NaN */ - -/* Set res if fraction of reg is != 0. */ -#define S_is_Inf(reg,res) \ - li res, (1 << S_F_bits) - 1; \ - and res, reg /* temp0 == 0 if Inf */ - - -/* - * Some constants that define the properties of double precission numbers. - */ -#define D_M_prec 53 -#define D_E_max 1023 -#define D_E_min -1022 -#define D_E_bias 1023 -#define D_E_bits 8 -#define D_F_bits 52 -#define D_F_size 64 - -/* Set temp0, if exponent of reg1/reg2 is D_E_max. */ -#define D_is_E_max(reg1,reg2,temp0,temp1) \ - li temp0, (D_E_max + 1 + D_E_bias) << (D_F_bits - 32); \ - and temp1, temp0, reg1; \ - seq temp0, temp1 /* temp0 != 0 if NaN */ - -/* Clear temp0, if exponent of reg is D_E_min. */ -#define D_is_E_min(reg1,reg2,res) \ - li res, (D_E_min + 1 + D_E_bias) << (D_F_bits - 32); \ - and res, reg1 /* temp0 == 0 if NaN or zero */ - -/* Set res if reg is a NaN assuming S_is_E_max is true */ -#define D_get_F(reg1,reg2,res) \ - li res, (1 << (D_F_bits - 32)) - 1; \ - and res, reg1 /* temp0 != 0 if NaN */ - -/* Set temp0 if reg1/reg2 is a NaN */ -#define D_is_NAN(reg1,reg2,temp0,temp1) \ - li temp0, (1 << (D_F_bits - 32) - 1; \ - and temp0, reg1; \ - or temp0, reg2; \ - sne temp0, zero, temp0 /* temp0 != 0 if NaN */ - -/* Set res if fraction of reg1/reg2 is != 0. */ -#define D_is_Inf(reg1,reg2,res) \ - li res, (1 << (D_F_bits - 32)) - 1; \ - and res, reg1; \ - or res, reg2 /* temp0 == 0 if Inf */ - -/* Complain about yet unhandled instruction. */ -#define BITCH(insn) \ -insn: LOCK_KERNEL; \ - la a1, 8f; \ - TEXT(#insn); \ - la a0, nosim; \ - jal printk; \ - UNLOCK_KERNEL; \ - j done - - .data -nosim: .asciz KERN_DEBUG "Don't know how to simulate %s instruction\n" - .previous - -/* - * When we come here, we've saved some of the integer registers and - * reenabled interrupts. - */ -LEAF(simfp) - .set noreorder - .cpload $25 - .set reorder - - dsubu sp, 16 - .cprestore 20 - sd ra, 0(sp) - - /* For now we assume that we get the opcode to simulate passed in as - an argument. */ - move ta0, a0 - - /* - * First table lookup using insn[5:0] - */ - la ta1, lowtab - andi ta2, ta0, 0x3f - sll ta2, ta2, 3 - daddu ta1, ta2 - ld ta1, (ta1) - jr ta1 - END(simfp) - -/* - * We only decode the lower 3 of the 5 bit in the fmt field. That way we - * can keep the jump table significantly shorter. - */ -#define FMT_switch(insn,opc,temp0,temp1) \ -insn: srl temp0, opc, 18; \ - andi temp0, 0x1c; \ - la temp1, insn##.tab; \ - daddu temp0, temp1; \ - ld temp0, (temp0); \ - jr temp0; \ - \ - .data; \ -insn##.tab: \ - .dword insn##.s, insn##.d, unimp, unimp; \ - .dword insn##.w, insn##.l, unimp, unimp; \ - .previous - - BITCH(add) - BITCH(sub) - BITCH(mul) - BITCH(div) - BITCH(sqrt) - BITCH(abs) - BITCH(mov) - BITCH(neg) - BITCH(round.l) - BITCH(trunc.l) - BITCH(ceil.l) - BITCH(floor.l) - BITCH(round.w) - BITCH(trunc.w) - BITCH(ceil.w) - BITCH(floor.w) - BITCH(cvt.s) - BITCH(cvt.d) - -/* ------------------------------------------------------------------------ */ - -FMT_switch(cvt.w,ta0,ta1,ta2) - -/* Convert a single fp to a fixed point integer. */ -cvt.w.s: - srl ta1, ta0, fs_shift # Get source register - andi ta1, 31 - jal s_get_fpreg - - S_is_E_max(ta1,ta2,ta3) - beqz ta2, 3f - /* Might be a NaN or Inf. */ - S_get_F(ta1,ta2) - beqz ta2, 2f - - /* It's a NaN. IEEE says undefined. */ - /* Is it a QNaN? Then the result is a QNaN as well. */ - S_is_QNaN(ta1,ta2) - bltz ta2, 1f - - /* XXX Ok, it's a SNaN. Signal invalid exception, if enabled. - For now we don't signal and supply a QNaN for result. */ - -1: li ta2, W_QNaN - srl ta1, ta0, fd_shift # Put result register - andi ta1, 31 - jal s_put_fpreg - j done -2: - - S_is_Inf(ta1,ta2) - bnez ta2, 2f - - /* It's +/- Inf. Set register to +/- max. integer. */ - /* XXX Send invalid operation exception instead, if enabled. */ - srl ta1, ta1, 31 # Extract sign bit - li ta2, 0x7fffffff - addu ta2, ta1 - - srl ta1, ta0, fd_shift # Put result register - andi ta1, 31 - jal s_put_fpreg - j done -2: -3: - - /* But then it might be a denorm or zero? */ - S_is_E_min(ta1,ta2) - bnez ta2, 2f - - /* Ok, it's a denorm or zero. */ - S_get_F(ta1,ta2) - beqz ta2, 1f - - /* It's a denorm. */ - /* XXX Should be signaling inexact exception, if enabled. */ - /* Fall through. */ -1: - /* Yes, it is a denorm or zero. Supply a zero as result. */ - move ta2, zero - srl ta1, ta0, fd_shift # Put result register - andi ta1, 31 - jal s_put_fpreg - j done -2: - - /* XXX Ok, it's a normal number. We don't handle that case yet. - If we have fp hardware this case is unreached. Add this for - full fp simulation. */ - - /* Done, return. */ - ld ra, 0(sp) - daddu sp, 16 - jr ra - -/* Convert a double fp to a fixed point integer. */ -cvt.w.d: - srl ta1, ta0, fs_shift # Get source register - andi ta1, 31 - jal d_get_fpreg - - D_is_E_max(ta1,ta2,ta3,t0) - beqz ta3, 3f - - /* Might be a NaN or Inf. */ - D_get_F(ta1,ta2,ta3) - or ta3, ta2 - beqz ta3, 2f - - /* It's a NaN. IEEE says undefined. */ - /* Is it a QNaN? Then the result is a QNaN as well. */ - D_is_QNaN(ta1,ta2,ta3) - bltz ta3, 1f - - /* XXX Ok, it's a SNaN. Signal invalid exception, if enabled. - For now we don't signal and supply a QNaN for result. */ - -1: li ta2, W_QNaN - srl ta1, ta0, fd_shift # Put result register - andi ta1, 31 - jal s_put_fpreg - j done -2: - - D_is_Inf(ta1,ta2,ta3) - bnez ta3, 2f - - /* It's +/- Inf. Set register to +/- max. integer. */ - /* XXX Send invalid operation exception instead, if enabled. */ - srl ta1, ta1, 31 # Extract sign bit - li ta2, 0x7fffffff - addu ta2, ta1 - - srl ta1, ta0, fd_shift # Put result register - andi ta1, 31 - jal s_put_fpreg - j done -2: -3: - - /* But then it might be a denorm or zero? */ - D_is_E_min(ta1,ta2,ta3) - bnez ta3, 2f - - /* Ok, it's a denorm or zero. */ - D_get_F(ta1,ta2,ta3) - or ta3, ta2 - beqz ta3, 1f - - /* It's a denorm. */ - /* XXX Should be signaling inexact exception, if enabled. */ - /* Fall through. */ -1: - /* Yes, it is a denorm or zero. Supply a zero as result. */ - move ta2, zero - srl ta1, ta0, fd_shift # Put result register - andi ta1, 31 - jal s_put_fpreg - j done -2: - - /* XXX Ok, it's a normal number. We don't handle that case yet. - If we have fp hardware this case is only reached if the value - of the source register exceeds the range which is representable - in a single precission register. For now we kludge by returning - +/- maxint and don't signal overflow. */ - - srl ta1, ta1, 31 # Extract sign bit - li ta2, 0x7fffffff - addu ta2, ta1 - - srl ta1, ta0, fd_shift # Put result register - andi ta1, 31 - jal s_put_fpreg - - /* Done, return. */ - ld ra, 0(sp) - daddu sp, 16 - jr ra - -cvt.w.w = unimp # undefined result -cvt.w.l = unimp # undefined result - -/* MIPS III extension, no need to handle for 32bit OS. */ -cvt.l = unimp - -/* ------------------------------------------------------------------------ */ - - BITCH(c.f) - BITCH(c.un) - BITCH(c.eq) - BITCH(c.ueq) - BITCH(c.olt) - BITCH(c.ult) - BITCH(c.ole) - BITCH(c.ule) - BITCH(c.sf) - BITCH(c.ngle) - BITCH(c.seq) - BITCH(c.ngl) - BITCH(c.lt) - BITCH(c.nge) - BITCH(c.le) - BITCH(c.ngt) - -/* Get the single precission register which's number is in ta1. */ -s_get_fpreg: - .set noat - sll ta1, 3 - la AT, 1f - daddu AT, ta1 - jr AT - .set at - -1: mfc1 ta1, $0 - jr ra - mfc1 ta1, $1 - jr ra - mfc1 ta1, $2 - jr ra - mfc1 ta1, $3 - jr ra - mfc1 ta1, $4 - jr ra - mfc1 ta1, $5 - jr ra - mfc1 ta1, $6 - jr ra - mfc1 ta1, $7 - jr ra - mfc1 ta1, $8 - jr ra - mfc1 ta1, $9 - jr ra - mfc1 ta1, $10 - jr ra - mfc1 ta1, $11 - jr ra - mfc1 ta1, $12 - jr ra - mfc1 ta1, $13 - jr ra - mfc1 ta1, $14 - jr ra - mfc1 ta1, $15 - jr ra - mfc1 ta1, $16 - jr ra - mfc1 ta1, $17 - jr ra - mfc1 ta1, $18 - jr ra - mfc1 ta1, $19 - jr ra - mfc1 ta1, $20 - jr ra - mfc1 ta1, $21 - jr ra - mfc1 ta1, $22 - jr ra - mfc1 ta1, $23 - jr ra - mfc1 ta1, $24 - jr ra - mfc1 ta1, $25 - jr ra - mfc1 ta1, $26 - jr ra - mfc1 ta1, $27 - jr ra - mfc1 ta1, $28 - jr ra - mfc1 ta1, $29 - jr ra - mfc1 ta1, $30 - jr ra - mfc1 ta1, $31 - jr ra - -/* - * Put the value in ta2 into the single precission register which's number - * is in ta1. - */ -s_put_fpreg: - .set noat - sll ta1, 3 - la AT, 1f - daddu AT, ta1 - jr AT - .set at - -1: mtc1 ta2, $0 - jr ra - mtc1 ta2, $1 - jr ra - mtc1 ta2, $2 - jr ra - mtc1 ta2, $3 - jr ra - mtc1 ta2, $4 - jr ra - mtc1 ta2, $5 - jr ra - mtc1 ta2, $6 - jr ra - mtc1 ta2, $7 - jr ra - mtc1 ta2, $8 - jr ra - mtc1 ta2, $9 - jr ra - mtc1 ta2, $10 - jr ra - mtc1 ta2, $11 - jr ra - mtc1 ta2, $12 - jr ra - mtc1 ta2, $13 - jr ra - mtc1 ta2, $14 - jr ra - mtc1 ta2, $15 - jr ra - mtc1 ta2, $16 - jr ra - mtc1 ta2, $17 - jr ra - mtc1 ta2, $18 - jr ra - mtc1 ta2, $19 - jr ra - mtc1 ta2, $20 - jr ra - mtc1 ta2, $21 - jr ra - mtc1 ta2, $22 - jr ra - mtc1 ta2, $23 - jr ra - mtc1 ta2, $24 - jr ra - mtc1 ta2, $25 - jr ra - mtc1 ta2, $26 - jr ra - mtc1 ta2, $27 - jr ra - mtc1 ta2, $28 - jr ra - mtc1 ta2, $29 - jr ra - mtc1 ta2, $30 - jr ra - mtc1 ta2, $31 - jr ra - -/* Get the double precission register which's number is in ta1 into ta1/ta2. */ -d_get_fpreg: - .set noat - sll AT, ta1, 1 - sll ta1, 2 - daddu ta1, AT - la AT, 1f - daddu AT, ta1 - jr AT - .set at - -1: mfc1 ta1, $0 - mfc1 ta2, $1 - jr ra - mfc1 ta1, $2 - mfc1 ta2, $3 - jr ra - mfc1 ta1, $4 - mfc1 ta2, $5 - jr ra - mfc1 ta1, $6 - mfc1 ta2, $7 - jr ra - mfc1 ta1, $8 - mfc1 ta2, $9 - jr ra - mfc1 ta1, $10 - mfc1 ta2, $11 - jr ra - mfc1 ta1, $12 - mfc1 ta2, $13 - jr ra - mfc1 ta1, $14 - mfc1 ta2, $15 - jr ra - mfc1 ta1, $16 - mfc1 ta2, $17 - jr ra - mfc1 ta1, $18 - mfc1 ta2, $19 - jr ra - mfc1 ta1, $20 - mfc1 ta2, $21 - jr ra - mfc1 ta1, $22 - mfc1 ta2, $23 - jr ra - mfc1 ta1, $24 - mfc1 ta2, $25 - jr ra - mfc1 ta1, $26 - mfc1 ta2, $27 - jr ra - mfc1 ta1, $28 - mfc1 ta2, $29 - jr ra - mfc1 ta1, $30 - mfc1 ta2, $31 - jr ra - -/* - * Send an invalid operation exception. - */ -invalid: - ld ra, 0(sp) - daddu sp, 16 - jr ra - -/* - * Done, just skip over the current instruction - */ -done: - ld ra, 0(sp) - daddu sp, 16 - jr ra - -unimp: - /* We've run into an yet unknown instruction. This happens either - on new, yet unsupported CPU types or when the faulting instruction - is being executed for cache but has been overwritten in memory. */ - LOCK_KERNEL - move a1, ta0 - PRINT(KERN_DEBUG "FP support: unknown fp op %08lx, ") - PRINT("please mail to ralf@gnu.org.\n") - UNLOCK_KERNEL - - li a0, SIGILL # Die, sucker ... - move a1, $28 - jal force_sig - - ld ra, 0(sp) - daddu sp, 16 - jr ra - -/* - * Jump table for the lowest 6 bits of a cp1 instruction. - */ - .data -lowtab: .dword add, sub, mul, div, sqrt, abs, mov, neg - .dword round.l,trunc.l,ceil.l,floor.l,round.w,trunc.w,ceil.w,floor.w - .dword unimp, unimp, unimp, unimp, unimp, unimp, unimp, unimp - .dword unimp, unimp, unimp, unimp, unimp, unimp, unimp, unimp - .dword cvt.s, cvt.d, unimp, unimp, cvt.w, cvt.l, unimp, unimp - .dword unimp, unimp, unimp, unimp, unimp, unimp, unimp, unimp - .dword c.f, c.un, c.eq, c.ueq, c.olt, c.ult, c.ole, c.ule - .dword c.sf, c.ngle,c.seq, c.ngl, c.lt, c.nge, c.le, c.ngt diff -Nru a/arch/mips64/kernel/syscall.c b/arch/mips64/kernel/syscall.c --- a/arch/mips64/kernel/syscall.c Tue Jul 1 18:44:36 2003 +++ b/arch/mips64/kernel/syscall.c Tue Jul 1 18:44:36 2003 @@ -32,8 +32,6 @@ #include #include -u64 jiffies_64; - extern asmlinkage void syscall_trace(void); asmlinkage int sys_pipe(abi64_no_regargs, struct pt_regs regs) @@ -52,12 +50,71 @@ return res; } +unsigned long shm_align_mask = PAGE_SIZE - 1; /* Sane caches */ + +#define COLOUR_ALIGN(addr,pgoff) \ + ((((addr) + shm_align_mask) & ~shm_align_mask) + \ + (((pgoff) << PAGE_SHIFT) & shm_align_mask)) + +unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, + unsigned long len, unsigned long pgoff, unsigned long flags) +{ + struct vm_area_struct * vmm; + int do_color_align; + + if (flags & MAP_FIXED) { + /* + * We do not accept a shared mapping if it would violate + * cache aliasing constraints. + */ + if ((flags & MAP_SHARED) && (addr & shm_align_mask)) + return -EINVAL; + return addr; + } + + if (len > TASK_SIZE) + return -ENOMEM; + do_color_align = 0; + if (filp || (flags & MAP_SHARED)) + do_color_align = 1; + if (addr) { + if (do_color_align) + addr = COLOUR_ALIGN(addr, pgoff); + else + addr = PAGE_ALIGN(addr); + vmm = find_vma(current->mm, addr); + if (TASK_SIZE - len >= addr && + (!vmm || addr + len <= vmm->vm_start)) + return addr; + } + addr = TASK_UNMAPPED_BASE; + if (do_color_align) + addr = COLOUR_ALIGN(addr, pgoff); + else + addr = PAGE_ALIGN(addr); + + for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) { + /* At this point: (!vmm || addr < vmm->vm_end). */ + if (TASK_SIZE - len < addr) + return -ENOMEM; + if (!vmm || addr + len <= vmm->vm_start) + return addr; + addr = vmm->vm_end; + if (do_color_align) + addr = COLOUR_ALIGN(addr, pgoff); + } +} + asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len, unsigned long prot, unsigned long flags, unsigned long fd, off_t offset) { struct file * file = NULL; - unsigned long error = -EFAULT; + unsigned long error; + + error = -EINVAL; + if (offset & ~PAGE_MASK) + goto out; if (!(flags & MAP_ANONYMOUS)) { error = -EBADF; @@ -72,33 +129,32 @@ up_write(¤t->mm->mmap_sem); if (file) fput(file); -out: +out: return error; } asmlinkage int sys_fork(abi64_no_regargs, struct pt_regs regs) { - struct task_struct *p; - save_static(®s); - p = do_fork(SIGCHLD, regs.regs[29], ®s, 0); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; + return do_fork(SIGCHLD, regs.regs[29], ®s, 0, NULL, NULL); } asmlinkage int sys_clone(abi64_no_regargs, struct pt_regs regs) { unsigned long clone_flags; unsigned long newsp; - struct task_struct *p; + int *parent_tidptr, *child_tidptr; save_static(®s); clone_flags = regs.regs[4]; newsp = regs.regs[5]; if (!newsp) newsp = regs.regs[29]; - p = do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0); - return IS_ERR(p) ? PTR_ERR(p) : p->pid; + parent_tidptr = (int *) regs.regs[6]; + child_tidptr = (int *) regs.regs[7]; + return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, ®s, 0, + parent_tidptr, child_tidptr); } /* @@ -131,12 +187,10 @@ return -ENOSYS; } -asmlinkage int -_sys_sysmips(int cmd, long arg1, int arg2, int arg3) +asmlinkage int sys_sysmips(int cmd, long arg1, int arg2, int arg3) { - int *p; + int tmp, len; char *name; - int tmp, len, errno; switch(cmd) { case SETNAME: { @@ -150,11 +204,12 @@ len = strncpy_from_user(nodename, name, __NEW_UTS_LEN); if (len < 0) return -EFAULT; - nodename[__NEW_UTS_LEN] = '\0'; down_write(&uts_sem); + strncpy(system_utsname.nodename, nodename, len); + nodename[__NEW_UTS_LEN] = '\0'; strlcpy(system_utsname.nodename, nodename, - sizeof(system_utsname.nodename)); + sizeof(system_utsname.nodename)); up_write(&uts_sem); return 0; } @@ -169,7 +224,7 @@ return 0; case FLUSH_CACHE: - _flush_cache_l2(); + __flush_cache_all(); return 0; case MIPS_RDNVRAM: @@ -207,7 +262,7 @@ } case MSGSND: - return sys_msgsnd (first, (struct msgbuf *) ptr, + return sys_msgsnd (first, (struct msgbuf *) ptr, second, third); case MSGRCV: switch (version) { @@ -215,9 +270,9 @@ struct ipc_kludge tmp; if (!ptr) return -EINVAL; - + if (copy_from_user(&tmp, - (struct ipc_kludge *) ptr, + (struct ipc_kludge *) ptr, sizeof (tmp))) return -EFAULT; return sys_msgrcv (first, tmp.msgp, second, @@ -247,7 +302,7 @@ return -EINVAL; return sys_shmat (first, (char *) ptr, second, (ulong *) third); } - case SHMDT: + case SHMDT: return sys_shmdt ((char *)ptr); case SHMGET: return sys_shmget (first, second, third); @@ -255,15 +310,14 @@ return sys_shmctl (first, second, (struct shmid_ds *) ptr); default: - return -EINVAL; + return -ENOSYS; } } /* * No implemented yet ... */ -asmlinkage int -sys_cachectl(char *addr, int nbytes, int op) +asmlinkage int sys_cachectl(char *addr, int nbytes, int op) { return -ENOSYS; } diff -Nru a/arch/mips64/kernel/time.c b/arch/mips64/kernel/time.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips64/kernel/time.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,602 @@ +/* + * Copyright 2001 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * Common time service routines for MIPS machines. See + * Documents/mips/README.txt. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* This is for machines which generate the exact clock. */ +#define USECS_PER_JIFFY (1000000/HZ) +#define USECS_PER_JIFFY_FRAC ((u32)((1000000ULL << 32) / HZ)) + +#define TICK_SIZE (tick_nsec / 1000) + +u64 jiffies_64; + +/* + * forward reference + */ +extern volatile unsigned long wall_jiffies; + +spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED; + +/* + * whether we emulate local_timer_interrupts for SMP machines. + */ +int emulate_local_timer_interrupt; + +/* + * By default we provide the null RTC ops + */ +static unsigned long null_rtc_get_time(void) +{ + return mktime(2000, 1, 1, 0, 0, 0); +} + +static int null_rtc_set_time(unsigned long sec) +{ + return 0; +} + +unsigned long (*rtc_get_time)(void) = null_rtc_get_time; +int (*rtc_set_time)(unsigned long) = null_rtc_set_time; + + +/* + * This version of gettimeofday has microsecond resolution and better than + * microsecond precision on fast machines with cycle counter. + */ +void do_gettimeofday(struct timeval *tv) +{ + unsigned long seq; + unsigned long usec, sec; + + do { + seq = read_seqbegin(&xtime_lock); + usec = do_gettimeoffset(); + { + unsigned long lost = jiffies - wall_jiffies; + if (lost) + usec += lost * (1000000 / HZ); + } + sec = xtime.tv_sec; + usec += (xtime.tv_nsec / 1000); + } while (read_seqretry(&xtime_lock, seq)); + + while (usec >= 1000000) { + usec -= 1000000; + sec++; + } + + tv->tv_sec = sec; + tv->tv_usec = usec; +} + +int do_settimeofday(struct timespec *tv) +{ + if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) + return -EINVAL; + + write_seqlock_irq(&xtime_lock); + /* + * This is revolting. We need to set "xtime" correctly. However, the + * value in this location is the value at the most recent update of + * wall time. Discover what correction gettimeofday() would have + * made, and then undo it! + */ + tv->tv_nsec -= do_gettimeoffset() * NSEC_PER_USEC; + tv->tv_nsec -= (jiffies - wall_jiffies) * TICK_NSEC; + + while (tv->tv_nsec < 0) { + tv->tv_nsec += NSEC_PER_SEC; + tv->tv_sec--; + } + + xtime.tv_sec = tv->tv_sec; + xtime.tv_nsec = tv->tv_nsec; + time_adjust = 0; /* stop active adjtime() */ + time_status |= STA_UNSYNC; + time_maxerror = NTP_PHASE_LIMIT; + time_esterror = NTP_PHASE_LIMIT; + write_sequnlock_irq(&xtime_lock); + + return 0; +} + + +/* + * Gettimeoffset routines. These routines returns the time duration + * since last timer interrupt in usecs. + * + * If the exact CPU counter frequency is known, use fixed_rate_gettimeoffset. + * Otherwise use calibrate_gettimeoffset() + * + * If the CPU does not have counter register all, you can either supply + * your own gettimeoffset() routine, or use null_gettimeoffset() routines, + * which gives the same resolution as HZ. + */ + + +/* This is for machines which generate the exact clock. */ +#define USECS_PER_JIFFY (1000000/HZ) + +/* usecs per counter cycle, shifted to left by 32 bits */ +static unsigned int sll32_usecs_per_cycle=0; + +/* how many counter cycles in a jiffy */ +static unsigned long cycles_per_jiffy=0; + +/* Cycle counter value at the previous timer interrupt.. */ +static unsigned int timerhi, timerlo; + +/* expirelo is the count value for next CPU timer interrupt */ +static unsigned int expirelo; + +/* last time when xtime and rtc are sync'ed up */ +static long last_rtc_update; + +/* the function pointer to one of the gettimeoffset funcs*/ +unsigned long (*do_gettimeoffset)(void) = null_gettimeoffset; + +unsigned long null_gettimeoffset(void) +{ + return 0; +} + +unsigned long fixed_rate_gettimeoffset(void) +{ + u32 count; + unsigned long res; + + /* Get last timer tick in absolute kernel time */ + count = read_c0_count(); + + /* .. relative to previous jiffy (32 bits is enough) */ + count -= timerlo; + + __asm__("multu\t%1,%2\n\t" + "mfhi\t%0" + :"=r" (res) + :"r" (count), + "r" (sll32_usecs_per_cycle)); + + /* + * Due to possible jiffies inconsistencies, we need to check + * the result so that we'll get a timer that is monotonic. + */ + if (res >= USECS_PER_JIFFY) + res = USECS_PER_JIFFY-1; + + return res; +} + +/* + * Cached "1/(clocks per usec)*2^32" value. + * It has to be recalculated once each jiffy. + */ +static unsigned long cached_quotient; + +/* Last jiffy when calibrate_divXX_gettimeoffset() was called. */ +static unsigned long last_jiffies = 0; + + +/* + * This is copied from dec/time.c:do_ioasic_gettimeoffset() by Mercij. + */ +unsigned long calibrate_div32_gettimeoffset(void) +{ + u32 count; + unsigned long res, tmp; + unsigned long quotient; + + tmp = jiffies; + + quotient = cached_quotient; + + if (last_jiffies != tmp) { + last_jiffies = tmp; + if (last_jiffies != 0) { + unsigned long r0; + do_div64_32(r0, timerhi, timerlo, tmp); + do_div64_32(quotient, USECS_PER_JIFFY, + USECS_PER_JIFFY_FRAC, r0); + cached_quotient = quotient; + } + } + + /* Get last timer tick in absolute kernel time */ + count = read_c0_count(); + + /* .. relative to previous jiffy (32 bits is enough) */ + count -= timerlo; + + __asm__("multu %2,%3" + : "=l" (tmp), "=h" (res) + : "r" (count), "r" (quotient)); + + /* + * Due to possible jiffies inconsistencies, we need to check + * the result so that we'll get a timer that is monotonic. + */ + if (res >= USECS_PER_JIFFY) + res = USECS_PER_JIFFY - 1; + + return res; +} + +unsigned long calibrate_div64_gettimeoffset(void) +{ + u32 count; + unsigned long res, tmp; + unsigned long quotient; + + tmp = jiffies; + + quotient = cached_quotient; + + if (tmp && last_jiffies != tmp) { + last_jiffies = tmp; + __asm__(".set\tnoreorder\n\t" + ".set\tnoat\n\t" + ".set\tmips3\n\t" + "lwu\t%0,%2\n\t" + "dsll32\t$1,%1,0\n\t" + "or\t$1,$1,%0\n\t" + "ddivu\t$0,$1,%3\n\t" + "mflo\t$1\n\t" + "dsll32\t%0,%4,0\n\t" + "nop\n\t" + "ddivu\t$0,%0,$1\n\t" + "mflo\t%0\n\t" + ".set\tmips0\n\t" + ".set\tat\n\t" + ".set\treorder" + :"=&r" (quotient) + :"r" (timerhi), + "m" (timerlo), + "r" (tmp), + "r" (USECS_PER_JIFFY)); + cached_quotient = quotient; + } + + /* Get last timer tick in absolute kernel time */ + count = read_c0_count(); + + /* .. relative to previous jiffy (32 bits is enough) */ + count -= timerlo; + + __asm__("multu\t%1,%2\n\t" + "mfhi\t%0" + :"=r" (res) + :"r" (count), + "r" (quotient)); + + /* + * Due to possible jiffies inconsistencies, we need to check + * the result so that we'll get a timer that is monotonic. + */ + if (res >= USECS_PER_JIFFY) + res = USECS_PER_JIFFY-1; + + return res; +} + + +/* + * local_timer_interrupt() does profiling and process accounting + * on a per-CPU basis. + * + * In UP mode, it is invoked from the (global) timer_interrupt. + * + * In SMP mode, it might invoked by per-CPU timer interrupt, or + * a broadcasted inter-processor interrupt which itself is triggered + * by the global timer interrupt. + */ +void local_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + if (!user_mode(regs)) { + if (prof_buffer && current->pid) { + extern int _stext; + unsigned long pc = regs->cp0_epc; + + pc -= (unsigned long) &_stext; + pc >>= prof_shift; + /* + * Dont ignore out-of-bounds pc values silently, + * put them into the last histogram slot, so if + * present, they will show up as a sharp peak. + */ + if (pc > prof_len-1) + pc = prof_len-1; + atomic_inc((atomic_t *)&prof_buffer[pc]); + } + } + +#ifdef CONFIG_SMP + /* in UP mode, update_process_times() is invoked by do_timer() */ + update_process_times(user_mode(regs)); +#endif +} + +/* + * high-level timer interrupt service routines. This function + * is set as irqaction->handler and is invoked through do_IRQ. + */ +irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + if (cpu_has_counter) { + unsigned int count; + + /* ack timer interrupt, and try to set next interrupt */ + expirelo += cycles_per_jiffy; + write_c0_compare(expirelo); + count = read_c0_count(); + + /* check to see if we have missed any timer interrupts */ + if ((count - expirelo) < 0x7fffffff) { + /* missed_timer_count ++; */ + expirelo = count + cycles_per_jiffy; + write_c0_compare(expirelo); + } + + /* Update timerhi/timerlo for intra-jiffy calibration. */ + timerhi += count < timerlo; /* Wrap around */ + timerlo = count; + } + + /* + * call the generic timer interrupt handling + */ + do_timer(regs); + + /* + * If we have an externally synchronized Linux clock, then update + * CMOS clock accordingly every ~11 minutes. rtc_set_time() has to be + * called as close as possible to 500 ms before the new second starts. + */ + write_seqlock(&xtime_lock); + if ((time_status & STA_UNSYNC) == 0 && + xtime.tv_sec > last_rtc_update + 660 && + (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 && + (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) { + if (rtc_set_time(xtime.tv_sec) == 0) { + last_rtc_update = xtime.tv_sec; + } else { + last_rtc_update = xtime.tv_sec - 600; + /* do it again in 60 s */ + } + } + write_sequnlock(&xtime_lock); + + /* + * If jiffies has overflowed in this timer_interrupt we must + * update the timer[hi]/[lo] to make fast gettimeoffset funcs + * quotient calc still valid. -arca + */ + if (!jiffies) { + timerhi = timerlo = 0; + } + +#if !defined(CONFIG_SMP) + /* + * In UP mode, we call local_timer_interrupt() to do profiling + * and process accouting. + * + * In SMP mode, local_timer_interrupt() is invoked by appropriate + * low-level local timer interrupt handler. + */ + local_timer_interrupt(0, NULL, regs); + +#else /* CONFIG_SMP */ + + if (emulate_local_timer_interrupt) { + /* + * this is the place where we send out inter-process + * interrupts and let each CPU do its own profiling + * and process accouting. + * + * Obviously we need to call local_timer_interrupt() for + * the current CPU too. + */ + panic("Not implemented yet!!!"); + } +#endif /* CONFIG_SMP */ + + return IRQ_HANDLED; +} + +asmlinkage void ll_timer_interrupt(int irq, struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + + irq_enter(); + kstat_cpu(cpu).irqs[irq]++; + + /* we keep interrupt disabled all the time */ + timer_interrupt(irq, NULL, regs); + + irq_exit(); + + if (softirq_pending(cpu)) + do_softirq(); +} + +asmlinkage void ll_local_timer_interrupt(int irq, struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + + irq_enter(); + kstat_cpu(cpu).irqs[irq]++; + + /* we keep interrupt disabled all the time */ + local_timer_interrupt(irq, NULL, regs); + + irq_exit(); + + if (softirq_pending(cpu)) + do_softirq(); +} + +/* + * time_init() - it does the following things. + * + * 1) board_time_init() - + * a) (optional) set up RTC routines, + * b) (optional) calibrate and set the mips_counter_frequency + * (only needed if you intended to use fixed_rate_gettimeoffset + * or use cpu counter as timer interrupt source) + * 2) setup xtime based on rtc_get_time(). + * 3) choose a appropriate gettimeoffset routine. + * 4) calculate a couple of cached variables for later usage + * 5) board_timer_setup() - + * a) (optional) over-write any choices made above by time_init(). + * b) machine specific code should setup the timer irqaction. + * c) enable the timer interrupt + */ + +void (*board_time_init)(void) = NULL; +void (*board_timer_setup)(struct irqaction *irq) = NULL; + +unsigned int mips_counter_frequency = 0; + +static struct irqaction timer_irqaction = { + timer_interrupt, + SA_INTERRUPT, + 0, + "timer", + NULL, + NULL +}; + +void __init time_init(void) +{ + if (board_time_init) + board_time_init(); + + xtime.tv_sec = rtc_get_time(); + xtime.tv_nsec = 0; + + /* choose appropriate gettimeoffset routine */ + if (!cpu_has_counter) { + /* no cpu counter - sorry */ + do_gettimeoffset = null_gettimeoffset; + } else if (mips_counter_frequency != 0) { + /* we have cpu counter and know counter frequency! */ + do_gettimeoffset = fixed_rate_gettimeoffset; + } else if ((current_cpu_data.isa_level == MIPS_CPU_ISA_M32) || + (current_cpu_data.isa_level == MIPS_CPU_ISA_I) || + (current_cpu_data.isa_level == MIPS_CPU_ISA_II) ) { + /* we need to calibrate the counter but we don't have + * 64-bit division. */ + do_gettimeoffset = calibrate_div32_gettimeoffset; + } else { + /* we need to calibrate the counter but we *do* have + * 64-bit division. */ + do_gettimeoffset = calibrate_div64_gettimeoffset; + } + + /* caclulate cache parameters */ + if (mips_counter_frequency) { + cycles_per_jiffy = mips_counter_frequency / HZ; + + /* sll32_usecs_per_cycle = 10^6 * 2^32 / mips_counter_freq */ + /* any better way to do this? */ + sll32_usecs_per_cycle = mips_counter_frequency / 100000; + sll32_usecs_per_cycle = 0xffffffff / sll32_usecs_per_cycle; + sll32_usecs_per_cycle *= 10; + + /* + * For those using cpu counter as timer, this sets up the + * first interrupt + */ + write_c0_compare(cycles_per_jiffy); + write_c0_count(0); + expirelo = cycles_per_jiffy; + } + + /* + * Call board specific timer interrupt setup. + * + * this pointer must be setup in machine setup routine. + * + * Even if the machine choose to use low-level timer interrupt, + * it still needs to setup the timer_irqaction. + * In that case, it might be better to set timer_irqaction.handler + * to be NULL function so that we are sure the high-level code + * is not invoked accidentally. + */ + board_timer_setup(&timer_irqaction); +} + +#define FEBRUARY 2 +#define STARTOFTIME 1970 +#define SECDAY 86400L +#define SECYR (SECDAY * 365) +#define leapyear(year) ((year) % 4 == 0) +#define days_in_year(a) (leapyear(a) ? 366 : 365) +#define days_in_month(a) (month_days[(a) - 1]) + +static int month_days[12] = { + 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 +}; + +void to_tm(unsigned long tim, struct rtc_time * tm) +{ + long hms, day, gday; + int i; + + gday = day = tim / SECDAY; + hms = tim % SECDAY; + + /* Hours, minutes, seconds are easy */ + tm->tm_hour = hms / 3600; + tm->tm_min = (hms % 3600) / 60; + tm->tm_sec = (hms % 3600) % 60; + + /* Number of years in days */ + for (i = STARTOFTIME; day >= days_in_year(i); i++) + day -= days_in_year(i); + tm->tm_year = i; + + /* Number of months in days left */ + if (leapyear(tm->tm_year)) + days_in_month(FEBRUARY) = 29; + for (i = 1; day >= days_in_month(i); i++) + day -= days_in_month(i); + days_in_month(FEBRUARY) = 28; + tm->tm_mon = i-1; /* tm_mon starts from 0 to 11 */ + + /* Days are what is left over (+1) from all that. */ + tm->tm_mday = day + 1; + + /* + * Determine the day of week + */ + tm->tm_wday = (gday + 4) % 7; /* 1970/1/1 was Thursday */ +} + +EXPORT_SYMBOL(rtc_lock); diff -Nru a/arch/mips64/kernel/traps.c b/arch/mips64/kernel/traps.c --- a/arch/mips64/kernel/traps.c Tue Jul 1 18:44:36 2003 +++ b/arch/mips64/kernel/traps.c Tue Jul 1 18:44:36 2003 @@ -3,29 +3,39 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1994 - 1999 by Ralf Baechle + * Copyright (C) 1994 - 1999, 2000, 01 Ralf Baechle * Copyright (C) 1995, 1996 Paul M. Antoine * Copyright (C) 1998 Ulf Carlsson * Copyright (C) 1999 Silicon Graphics, Inc. + * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000, 01 MIPS Technologies, Inc. + * Copyright (C) 2002, 2003 Maciej W. Rozycki */ #include #include #include +#include #include #include #include #include +#include +#include #include -#include +#include +#include +#include #include -#include -#include #include -#include +#include #include +#include +#include #include #include +#include +#include extern asmlinkage void __xtlb_mod(void); extern asmlinkage void __xtlb_tlbl(void); @@ -41,15 +51,16 @@ extern asmlinkage void handle_ov(void); extern asmlinkage void handle_tr(void); extern asmlinkage void handle_fpe(void); +extern asmlinkage void handle_mdmx(void); extern asmlinkage void handle_watch(void); +extern asmlinkage void handle_mcheck(void); extern asmlinkage void handle_reserved(void); -static char *cpu_names[] = CPU_NAMES; +extern int fpu_emulator_cop1Handler(int xcptno, struct pt_regs *xcp, + struct mips_fpu_soft_struct *ctx); -char watch_available = 0; -char dedicated_iv_available = 0; -char vce_available = 0; -char mips4_available = 0; +void (*board_be_init)(void); +int (*board_be_handler)(struct pt_regs *regs, int is_fixup); /* * These constant is for searching for possible module text segments. @@ -61,84 +72,70 @@ * This routine abuses get_user()/put_user() to reference pointers * with at least a bit of error checking ... */ -void show_stack(unsigned long *sp) +void show_stack(struct task_struct *task, unsigned long *sp) { + const int field = 2 * sizeof(unsigned long); + long stackdata; int i; - unsigned long *stack; - - stack = sp; - i = 0; - printk("Stack:"); - while ((unsigned long) stack & (PAGE_SIZE - 1)) { - unsigned long stackdata; + sp = sp ? sp : (unsigned long *) &sp; - if (__get_user(stackdata, stack++)) { - printk(" (Bad stack address)"); + printk("Stack: "); + i = 1; + while ((unsigned long) sp & (PAGE_SIZE - 1)) { + if (i && ((i % (64 / sizeof(unsigned long))) == 0)) + printk("\n "); + if (i > 40) { + printk(" ..."); break; } - printk(" %016lx", stackdata); - - if (++i > 40) { - printk(" ..."); + if (__get_user(stackdata, sp++)) { + printk(" (Bad stack address)"); break; } - if (i % 4 == 0) - printk("\n "); + printk(" %0*lx", field, stackdata); + i++; } + printk("\n"); } -void show_trace(unsigned long *sp) +void show_trace(struct task_struct *task, unsigned long *stack) { - int i; - unsigned long *stack; - unsigned long kernel_start, kernel_end; - unsigned long module_start, module_end; - extern char _stext, _etext; - - stack = sp; - i = 0; - - kernel_start = (unsigned long) &_stext; - kernel_end = (unsigned long) &_etext; - module_start = VMALLOC_START; - module_end = module_start + MODULE_RANGE; - - printk("\nCall Trace:"); + const int field = 2 * sizeof(unsigned long); + unsigned long addr; - while ((unsigned long) stack & (PAGE_SIZE -1)) { - unsigned long addr; + if (!stack) + stack = (unsigned long*)&stack; - if (__get_user(addr, stack++)) { - printk(" (Bad stack address)\n"); - break; + printk("Call Trace:"); +#ifdef CONFIG_KALLSYMS + printk("\n"); +#endif + while (((long) stack & (THREAD_SIZE-1)) != 0) { + addr = *stack++; + if (kernel_text_address(addr)) { + printk(" [<%0*lx>] ", field, addr); + print_symbol("%s\n", addr); } + } + printk("\n"); +} - /* - * If the address is either in the text segment of the - * kernel, or in the region which contains vmalloc'ed - * memory, it *may* be the address of a calling - * routine; if so, print it so that someone tracing - * down the cause of the crash will be able to figure - * out the call path that was taken. - */ +void show_trace_task(struct task_struct *tsk) +{ + show_trace(tsk, (long *)tsk->thread.reg29); +} - if ((addr >= kernel_start && addr < kernel_end) || - (addr >= module_start && addr < module_end)) { +/* + * The architecture-independent dump_stack generator + */ +void dump_stack(void) +{ + unsigned long stack; - /* Since our kernel is still at KSEG0, - * truncate the address so that ksymoops - * understands it. - */ - printk(" [<%08x>]", (unsigned int) addr); - if (++i > 40) { - printk(" ..."); - break; - } - } - } + show_trace(current, &stack); } void show_code(unsigned int *pc) @@ -153,120 +150,369 @@ printk(" (Bad address in epc)\n"); break; } - printk("%c%08x%c",(i?' ':'<'),insn,(i?' ':'>')); + printk("%c%08x%c", (i?' ':'<'), insn, (i?' ':'>')); + } +} + +void show_regs(struct pt_regs *regs) +{ + const int field = 2 * sizeof(unsigned long); + int i; + + printk("Cpu %d\n", smp_processor_id()); + + /* + * Saved main processor registers + */ + for (i = 0; i < 32; i++) { + if ((i % 4) == 0) + printk("$%2d :", i); + if (i == 0) + printk(" %0*lx", field, 0UL); + else if (i == 26 || i == 27) + printk(" %*s", field, ""); + else + printk(" %0*lx", field, regs->regs[i]); + + i++; + if ((i % 4) == 0) + printk("\n"); } + + printk("Hi : %0*lx\n", field, regs->hi); + printk("Lo : %0*lx\n", field, regs->lo); + + /* + * Saved cp0 registers + */ + printk("epc : %0*lx %s\n", field, regs->cp0_epc, print_tainted()); + printk("Status: %0*lx\n", field, regs->cp0_status); + printk("Cause : %0*lx\n", field, regs->cp0_cause); + + if (regs->cp0_status & ST0_KX) + printk("KX "); + if (regs->cp0_status & ST0_SX) + printk("SX "); + if (regs->cp0_status & ST0_UX) + printk("UX "); + switch (regs->cp0_status & ST0_KSU) { + case KSU_USER: + printk("USER "); + break; + case KSU_SUPERVISOR: + printk("SUPERVISOR "); + break; + case KSU_KERNEL: + printk("KERNEL "); + break; + default: + printk("BAD_MODE "); + break; + } + if (regs->cp0_status & ST0_ERL) + printk("ERL "); + if (regs->cp0_status & ST0_EXL) + printk("EXL "); + if (regs->cp0_status & ST0_IE) + printk("IE "); } -spinlock_t die_lock; +void show_registers(struct pt_regs *regs) +{ + const int field = 2 * sizeof(unsigned long); -void die(const char * str, struct pt_regs * regs, unsigned long err) + show_regs(regs); + printk("Process %s (pid: %d, stackpage=%0*lx)\n", + current->comm, current->pid, field, (unsigned long) current); + show_stack(current, (long *) regs->regs[29]); + show_trace(current, (long *) regs->regs[29]); + show_code((unsigned int *) regs->cp0_epc); + printk("\n"); +} + +static spinlock_t die_lock = SPIN_LOCK_UNLOCKED; + +void __die(const char * str, struct pt_regs * regs, const char * file, + const char * func, unsigned long line) { static int die_counter; - if (user_mode(regs)) /* Just return if in user mode. */ - return; console_verbose(); spin_lock_irq(&die_lock); - printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); - show_regs(regs); - printk("Process %s (pid: %d, stackpage=%08lx)\n", - current->comm, current->pid, (unsigned long) current); - show_stack((unsigned long *) regs->regs[29]); - show_trace((unsigned long *) regs->regs[29]); - show_code((unsigned int *) regs->cp0_epc); - printk("\n"); + printk("%s", str); + if (file && func) + printk(" in %s:%s, line %ld", file, func, line); + printk("[#%d]:\n", ++die_counter); + show_registers(regs); spin_unlock_irq(&die_lock); do_exit(SIGSEGV); } -void die_if_kernel(const char * str, struct pt_regs * regs, unsigned long err) +void __die_if_kernel(const char * str, struct pt_regs * regs, + const char * file, const char * func, unsigned long line) { if (!user_mode(regs)) - die(str, regs, err); + __die(str, regs, file, func, line); +} + +extern const struct exception_table_entry __start___dbe_table[]; +extern const struct exception_table_entry __stop___dbe_table[]; + +void __declare_dbe_table(void) +{ + __asm__ __volatile__( + ".section\t__dbe_table,\"a\"\n\t" + ".previous" + ); } -void do_ov(struct pt_regs *regs) +asmlinkage void do_be(struct pt_regs *regs) { - if (compute_return_epc(regs)) + const int field = 2 * sizeof(unsigned long); + const struct exception_table_entry *fixup = NULL; + int data = regs->cp0_cause & 4; + int action = MIPS_BE_FATAL; + + /* XXX For now. Fixme, this searches the wrong table ... */ + if (data && !user_mode(regs)) + fixup = search_exception_tables(regs->cp0_epc); + + if (fixup) + action = MIPS_BE_FIXUP; + + if (board_be_handler) + action = board_be_handler(regs, fixup != 0); + + switch (action) { + case MIPS_BE_DISCARD: return; - force_sig(SIGFPE, current); + case MIPS_BE_FIXUP: + if (fixup) { + regs->cp0_epc = fixup->nextinsn; + return; + } + break; + default: + break; + } + + /* + * Assume it would be too dangerous to continue ... + */ + printk(KERN_ALERT "%s bus error, epc == %0*lx, ra == %0*lx\n", + data ? "Data" : "Instruction", + field, regs->cp0_epc, field, regs->regs[31]); + die_if_kernel("Oops", regs); + force_sig(SIGBUS, current); } -#ifdef CONFIG_MIPS_FPE_MODULE -static void (*fpe_handler)(struct pt_regs *regs, unsigned int fcr31); +static inline int get_insn_opcode(struct pt_regs *regs, unsigned int *opcode) +{ + unsigned int *epc; + + epc = (unsigned int *) regs->cp0_epc + + ((regs->cp0_cause & CAUSEF_BD) != 0); + if (!get_user(*opcode, epc)) + return 0; + + force_sig(SIGSEGV, current); + return 1; +} + +/* + * ll/sc emulation + */ + +#define OPCODE 0xfc000000 +#define BASE 0x03e00000 +#define RT 0x001f0000 +#define OFFSET 0x0000ffff +#define LL 0xc0000000 +#define SC 0xe0000000 /* - * Register_fpe/unregister_fpe are for debugging purposes only. To make - * this hack work a bit better there is no error checking. + * The ll_bit is cleared by r*_switch.S */ -int register_fpe(void (*handler)(struct pt_regs *regs, unsigned int fcr31)) + +unsigned long ll_bit; + +static struct task_struct *ll_task = NULL; + +static inline void simulate_ll(struct pt_regs *regs, unsigned int opcode) { - fpe_handler = handler; - return 0; + unsigned long value, *vaddr; + long offset; + int signal = 0; + + /* + * analyse the ll instruction that just caused a ri exception + * and put the referenced address to addr. + */ + + /* sign extend offset */ + offset = opcode & OFFSET; + offset <<= 16; + offset >>= 16; + + vaddr = (unsigned long *)((long)(regs->regs[(opcode & BASE) >> 21]) + offset); + + if ((unsigned long)vaddr & 3) { + signal = SIGBUS; + goto sig; + } + if (get_user(value, vaddr)) { + signal = SIGSEGV; + goto sig; + } + + if (ll_task == NULL || ll_task == current) { + ll_bit = 1; + } else { + ll_bit = 0; + } + ll_task = current; + + regs->regs[(opcode & RT) >> 16] = value; + + compute_return_epc(regs); + return; + +sig: + force_sig(signal, current); } -int unregister_fpe(void (*handler)(struct pt_regs *regs, unsigned int fcr31)) +static inline void simulate_sc(struct pt_regs *regs, unsigned int opcode) { - fpe_handler = NULL; - return 0; + unsigned long *vaddr, reg; + long offset; + int signal = 0; + + /* + * analyse the sc instruction that just caused a ri exception + * and put the referenced address to addr. + */ + + /* sign extend offset */ + offset = opcode & OFFSET; + offset <<= 16; + offset >>= 16; + + vaddr = (unsigned long *)((long)(regs->regs[(opcode & BASE) >> 21]) + offset); + reg = (opcode & RT) >> 16; + + if ((unsigned long)vaddr & 3) { + signal = SIGBUS; + goto sig; + } + if (ll_bit == 0 || ll_task != current) { + regs->regs[reg] = 0; + compute_return_epc(regs); + return; + } + + if (put_user(regs->regs[reg], vaddr)) { + signal = SIGSEGV; + goto sig; + } + + regs->regs[reg] = 1; + + compute_return_epc(regs); + return; + +sig: + force_sig(signal, current); } -#endif /* - * XXX Delayed fp exceptions when doing a lazy ctx switch XXX + * ll uses the opcode of lwc0 and sc uses the opcode of swc0. That is both + * opcodes are supposed to result in coprocessor unusable exceptions if + * executed on ll/sc-less processors. That's the theory. In practice a + * few processors such as NEC's VR4100 throw reserved instruction exceptions + * instead, so we're doing the emulation thing in both exception handlers. */ -void do_fpe(struct pt_regs *regs, unsigned long fcr31) +static inline int simulate_llsc(struct pt_regs *regs) { - unsigned long pc; - unsigned int insn; - extern void simfp(unsigned int); - -#ifdef CONFIG_MIPS_FPE_MODULE - if (fpe_handler != NULL) { - fpe_handler(regs, fcr31); - return; - } -#endif - if (fcr31 & 0x20000) { - /* Retry instruction with flush to zero ... */ - if (!(fcr31 & (1<<24))) { - printk("Setting flush to zero for %s.\n", - current->comm); - fcr31 &= ~0x20000; - fcr31 |= (1<<24); - __asm__ __volatile__( - "ctc1\t%0,$31" - : /* No outputs */ - : "r" (fcr31)); - return; - } - pc = regs->cp0_epc + ((regs->cp0_cause & CAUSEF_BD) ? 4 : 0); - if (get_user(insn, (unsigned int *)pc)) { - /* XXX Can this happen? */ - force_sig(SIGSEGV, current); - } + unsigned int opcode; - printk(KERN_DEBUG "Unimplemented exception for insn %08x at 0x%08lx in %s.\n", - insn, regs->cp0_epc, current->comm); - simfp(insn); + if (unlikely(get_insn_opcode(regs, &opcode))) + return -EFAULT; + + if ((opcode & OPCODE) == LL) { + simulate_ll(regs, opcode); + return 0; + } + if ((opcode & OPCODE) == SC) { + simulate_sc(regs, opcode); + return 0; } - if (compute_return_epc(regs)) + return -EFAULT; /* Strange things going on ... */ +} + +asmlinkage void do_ov(struct pt_regs *regs) +{ + siginfo_t info; + + info.si_code = FPE_INTOVF; + info.si_signo = SIGFPE; + info.si_errno = 0; + info.si_addr = (void *)regs->cp0_epc; + force_sig_info(SIGFPE, &info, current); +} + +/* + * XXX Delayed fp exceptions when doing a lazy ctx switch XXX + */ +asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) +{ + if (fcr31 & FPU_CSR_UNI_X) { + int sig; + + /* + * Unimplemented operation exception. If we've got the full + * software emulator on-board, let's use it... + * + * Force FPU to dump state into task/thread context. We're + * moving a lot of data here for what is probably a single + * instruction, but the alternative is to pre-decode the FP + * register operands before invoking the emulator, which seems + * a bit extreme for what should be an infrequent event. + */ + save_fp(current); + + /* Run the emulator */ + sig = fpu_emulator_cop1Handler (0, regs, + ¤t->thread.fpu.soft); + + /* + * We can't allow the emulated instruction to leave any of + * the cause bit set in $fcr31. + */ + current->thread.fpu.soft.sr &= ~FPU_CSR_ALL_X; + + /* Restore the hardware register state */ + restore_fp(current); + + /* If something went wrong, signal */ + if (sig) + force_sig(sig, current); + return; - //force_sig(SIGFPE, current); - printk(KERN_DEBUG "Should send SIGFPE to %s\n", current->comm); + } + + force_sig(SIGFPE, current); } -void do_bp(struct pt_regs *regs) +asmlinkage void do_bp(struct pt_regs *regs) { unsigned int opcode, bcode; - unsigned int *epc; siginfo_t info; - epc = (unsigned int *) regs->cp0_epc + - ((regs->cp0_cause & CAUSEF_BD) != 0); - if (get_user(opcode, epc)) - goto sigsegv; + die_if_kernel("Break instruction in kernel code", regs); + + if (get_insn_opcode(regs, &opcode)) + return; /* * There is the ancient bug in the MIPS assemblers that the break @@ -290,160 +536,243 @@ info.si_code = FPE_INTOVF; info.si_signo = SIGFPE; info.si_errno = 0; - info.si_addr = (void *)compute_return_epc(regs); + info.si_addr = (void *)regs->cp0_epc; force_sig_info(SIGFPE, &info, current); break; default: force_sig(SIGTRAP, current); } - - force_sig(SIGTRAP, current); - return; - -sigsegv: - force_sig(SIGSEGV, current); } -void do_tr(struct pt_regs *regs) +asmlinkage void do_tr(struct pt_regs *regs) { - unsigned int opcode, bcode; - unsigned int *epc; + unsigned int opcode, tcode = 0; siginfo_t info; - epc = (unsigned int *) regs->cp0_epc + - ((regs->cp0_cause & CAUSEF_BD) != 0); - if (get_user(opcode, epc)) - goto sigsegv; + die_if_kernel("Trap instruction in kernel code", regs); - bcode = ((opcode >> 6) & ((1 << 20) - 1)); + if (get_insn_opcode(regs, &opcode)) + return; + + /* Immediate versions don't provide a code. */ + if (!(opcode & OPCODE)) + tcode = ((opcode >> 6) & ((1 << 20) - 1)); /* - * (A short test says that IRIX 5.3 sends SIGTRAP for all break - * insns, even for break codes that indicate arithmetic failures. - * Wiered ...) + * (A short test says that IRIX 5.3 sends SIGTRAP for all trap + * insns, even for trap codes that indicate arithmetic failures. + * Weird ...) * But should we continue the brokenness??? --macro */ - switch (bcode) { + switch (tcode) { case 6: case 7: - if (bcode == 7) + if (tcode == 7) info.si_code = FPE_INTDIV; else info.si_code = FPE_INTOVF; info.si_signo = SIGFPE; info.si_errno = 0; - info.si_addr = (void *)compute_return_epc(regs); + info.si_addr = (void *)regs->cp0_epc; force_sig_info(SIGFPE, &info, current); break; default: force_sig(SIGTRAP, current); } - return; - -sigsegv: - force_sig(SIGSEGV, current); } -void do_ri(struct pt_regs *regs) +asmlinkage void do_ri(struct pt_regs *regs) { - printk("Cpu%d[%s:%d] Illegal instruction at %08lx ra=%08lx\n", - smp_processor_id(), current->comm, current->pid, regs->cp0_epc, - regs->regs[31]); - if (compute_return_epc(regs)) - return; + die_if_kernel("Reserved instruction in kernel code", regs); + + if (!cpu_has_llsc) + if (!simulate_llsc(regs)) + return; + force_sig(SIGILL, current); } -void do_cpu(struct pt_regs *regs) +asmlinkage void do_cpu(struct pt_regs *regs) { - u32 cpid; + unsigned int cpid; + + die_if_kernel("do_cpu invoked from kernel context!", regs); cpid = (regs->cp0_cause >> CAUSEB_CE) & 3; - if (cpid != 1) - goto bad_cid; - regs->cp0_status |= ST0_CU1; -#ifndef CONFIG_SMP - if (last_task_used_math == current) + switch (cpid) { + case 0: + if (cpu_has_llsc) + break; + + if (!simulate_llsc(regs)) + return; + break; + + case 1: + own_fpu(); + if (current->used_math) { /* Using the FPU again. */ + restore_fp(current); + } else { /* First time FPU user. */ + init_fpu(); + current->used_math = 1; + } + + if (!cpu_has_fpu) { + int sig = fpu_emulator_cop1Handler(0, regs, + ¤t->thread.fpu.soft); + if (sig) + force_sig(sig, current); + } + return; - if (current->used_math) { /* Using the FPU again. */ - lazy_fpu_switch(last_task_used_math, current); - } else { /* First time FPU user. */ - lazy_fpu_switch(last_task_used_math, 0); - init_fpu(); - current->used_math = 1; - } - last_task_used_math = current; -#else - if (current->used_math) { - lazy_fpu_switch(0, current); - } else { - init_fpu(); - current->used_math = 1; + case 2: + case 3: + break; } - current->flags |= PF_USEDFPU; -#endif - return; -bad_cid: force_sig(SIGILL, current); } -void do_watch(struct pt_regs *regs) +asmlinkage void do_mdmx(struct pt_regs *regs) +{ + force_sig(SIGILL, current); +} + +asmlinkage void do_watch(struct pt_regs *regs) { /* * We use the watch exception where available to detect stack * overflows. */ + dump_tlb_all(); show_regs(regs); panic("Caught WATCH exception - probably caused by stack overflow."); } -void do_reserved(struct pt_regs *regs) +asmlinkage void do_mcheck(struct pt_regs *regs) +{ + show_regs(regs); + dump_tlb_all(); + /* + * Some chips may have other causes of machine check (e.g. SB1 + * graduation timer) + */ + panic("Caught Machine Check exception - %scaused by multiple " + "matching entries in the TLB.", + (regs->cp0_status & ST0_TS) ? "" : "not "); +} + +asmlinkage void do_reserved(struct pt_regs *regs) { /* * Game over - no way to handle this if it ever occurs. Most probably * caused by a new unknown cpu type or after another deadly * hard/software error. */ + show_regs(regs); panic("Caught reserved exception %ld - should not happen.", - (regs->cp0_cause & 0x1f) >> 2); + (regs->cp0_cause & 0x7f) >> 2); } -static inline void watch_init(unsigned long cputype) +/* + * Some MIPS CPUs can enable/disable for cache parity detection, but do + * it different ways. + */ +static inline void parity_protection_init(void) { - switch(cputype) { - case CPU_R10000: - case CPU_R4000MC: - case CPU_R4400MC: - case CPU_R4000SC: - case CPU_R4400SC: - case CPU_R4000PC: - case CPU_R4400PC: - case CPU_R4200: - case CPU_R4300: - set_except_vector(23, handle_watch); - watch_available = 1; + switch (current_cpu_data.cputype) { + case CPU_5KC: + /* Set the PE bit (bit 31) in the c0_ecc register. */ + printk(KERN_INFO "Enable the cache parity protection for " + "MIPS 5KC CPUs.\n"); + write_c0_ecc(read_c0_ecc() | 0x80000000); + break; + default: break; } } +asmlinkage void cache_parity_error(void) +{ + const int field = 2 * sizeof(unsigned long); + unsigned int reg_val; + + /* For the moment, report the problem and hang. */ + printk("Cache error exception:\n"); + printk("cp0_errorepc == %0*lx\n", field, read_c0_errorepc()); + reg_val = read_c0_cacheerr(); + printk("c0_cacheerr == %08x\n", reg_val); + + printk("Decoded c0_cacheerr: %s cache fault in %s reference.\n", + reg_val & (1<<30) ? "secondary" : "primary", + reg_val & (1<<31) ? "data" : "insn"); + printk("Error bits: %s%s%s%s%s%s%s\n", + reg_val & (1<<29) ? "ED " : "", + reg_val & (1<<28) ? "ET " : "", + reg_val & (1<<26) ? "EE " : "", + reg_val & (1<<25) ? "EB " : "", + reg_val & (1<<24) ? "EI " : "", + reg_val & (1<<23) ? "E1 " : "", + reg_val & (1<<22) ? "E0 " : ""); + printk("IDX: 0x%08x\n", reg_val & ((1<<22)-1)); + +#if defined(CONFIG_CPU_MIPS32) || defined (CONFIG_CPU_MIPS64) + if (reg_val & (1<<22)) + printk("DErrAddr0: 0x%08x\n", read_c0_derraddr0()); + + if (reg_val & (1<<23)) + printk("DErrAddr1: 0x%08x\n", read_c0_derraddr1()); +#endif + + panic("Can't handle the cache error!"); +} + /* - * Some MIPS CPUs have a dedicated interrupt vector which reduces the - * interrupt processing overhead. Use it where available. - * FIXME: more CPUs than just the Nevada have this feature. + * SDBBP EJTAG debug exception handler. + * We skip the instruction and return to the next instruction. */ -static inline void setup_dedicated_int(void) +void ejtag_exception_handler(struct pt_regs *regs) { - extern void except_vec4(void); + const int field = 2 * sizeof(unsigned long); + unsigned long depc, old_epc; + unsigned int debug; + + printk("SDBBP EJTAG debug exception - not handled yet, just ignored!\n"); + depc = read_c0_depc(); + debug = read_c0_debug(); + printk("c0_depc = %0*lx, DEBUG = %08x\n", field, depc, debug); + if (debug & 0x80000000) { + /* + * In branch delay slot. + * We cheat a little bit here and use EPC to calculate the + * debug return address (DEPC). EPC is restored after the + * calculation. + */ + old_epc = regs->cp0_epc; + regs->cp0_epc = depc; + __compute_return_epc(regs); + depc = regs->cp0_epc; + regs->cp0_epc = old_epc; + } else + depc += 4; + write_c0_depc(depc); + +#if 0 + printk("\n\n----- Enable EJTAG single stepping ----\n\n"); + write_c0_debug(debug | 0x100); +#endif +} - switch(mips_cputype) { - case CPU_NEVADA: - memcpy((void *)(KSEG0 + 0x200), except_vec4, 8); - set_cp0_cause(CAUSEF_IV, CAUSEF_IV); - dedicated_iv_available = 1; - } +/* + * NMI exception handler. + */ +void nmi_exception_handler(struct pt_regs *regs) +{ + printk("NMI taken!!!!\n"); + die("NMI", regs); + while(1) ; } unsigned long exception_handlers[32]; @@ -453,139 +782,160 @@ * to interrupt handlers in the address range from * KSEG0 <= x < KSEG0 + 256mb on the Nevada. Oh well ... */ -void set_except_vector(int n, void *addr) +void *set_except_vector(int n, void *addr) { unsigned long handler = (unsigned long) addr; + unsigned long old_handler = exception_handlers[n]; + exception_handlers[n] = handler; - if (n == 0 && dedicated_iv_available) { + if (n == 0 && cpu_has_divec) { *(volatile u32 *)(KSEG0+0x200) = 0x08000000 | (0x03ffffff & (handler >> 2)); flush_icache_range(KSEG0+0x200, KSEG0 + 0x204); } + return (void *)old_handler; } -static inline void mips4_setup(void) -{ - switch (mips_cputype) { - case CPU_R5000: - case CPU_R5000A: - case CPU_NEVADA: - case CPU_R8000: - case CPU_R10000: - mips4_available = 1; - set_cp0_status(ST0_XX, ST0_XX); - } -} +asmlinkage int (*save_fp_context)(struct sigcontext *sc); +asmlinkage int (*restore_fp_context)(struct sigcontext *sc); + +extern asmlinkage int _save_fp_context(struct sigcontext *sc); +extern asmlinkage int _restore_fp_context(struct sigcontext *sc); -static inline void go_64(void) +extern asmlinkage int fpu_emulator_save_context(struct sigcontext *sc); +extern asmlinkage int fpu_emulator_restore_context(struct sigcontext *sc); + +void __init per_cpu_trap_init(void) { - unsigned int bits; + unsigned int cpu = smp_processor_id(); + + /* Some firmware leaves the BEV flag set, clear it. */ + clear_c0_status(ST0_CU1|ST0_CU2|ST0_CU3|ST0_BEV); + set_c0_status(ST0_CU0|ST0_FR|ST0_KX|ST0_SX|ST0_UX); + + /* + * Some MIPS CPUs have a dedicated interrupt vector which reduces the + * interrupt processing overhead. Use it where available. + */ + if (cpu_has_divec) + set_c0_cause(CAUSEF_IV); - bits = ST0_KX|ST0_SX|ST0_UX; - set_cp0_status(bits, bits); - printk("Entering 64-bit mode.\n"); + cpu_data[cpu].asid_cache = ASID_FIRST_VERSION; + write_c0_context(((long)(&pgd_current[cpu])) << 23); + write_c0_wired(0); } void __init trap_init(void) { - extern char except_vec0; - extern char except_vec1_r10k; - extern char except_vec2_generic; + extern char except_vec0_generic; extern char except_vec3_generic, except_vec3_r4000; - extern void bus_error_init(void); + extern char except_vec_ejtag_debug; + extern char except_vec4; unsigned long i; - /* Some firmware leaves the BEV flag set, clear it. */ - set_cp0_status(ST0_BEV, 0); + per_cpu_trap_init(); - /* Copy the generic exception handler code to its final destination. */ - memcpy((void *)(KSEG0 + 0x100), &except_vec2_generic, 0x80); + /* Copy the generic exception handlers to their final destination. */ + memcpy((void *) KSEG0 , &except_vec0_generic, 0x80); memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, 0x80); /* * Setup default vectors */ - for(i = 0; i <= 31; i++) + for (i = 0; i <= 31; i++) set_except_vector(i, handle_reserved); /* + * Copy the EJTAG debug exception vector handler code to it's final + * destination. + */ + if (cpu_has_ejtag) + memcpy((void *)(KSEG0 + 0x300), &except_vec_ejtag_debug, 0x80); + + /* * Only some CPUs have the watch exceptions or a dedicated * interrupt vector. */ - watch_init(mips_cputype); - setup_dedicated_int(); - mips4_setup(); - go_64(); /* In memoriam C128 ;-) */ + if (cpu_has_watch) + set_except_vector(23, handle_watch); /* - * Handling the following exceptions depends mostly of the cpu type + * Some MIPS CPUs have a dedicated interrupt vector which reduces the + * interrupt processing overhead. Use it where available. */ - switch(mips_cputype) { - case CPU_R10000: - /* - * The R10000 is in most aspects similar to the R4400. It - * should get some special optimizations. - */ - write_32bit_cp0_register(CP0_FRAMEMASK, 0); - set_cp0_status(ST0_XX, ST0_XX); - goto r4k; - - case CPU_R4000MC: - case CPU_R4400MC: - case CPU_R4000SC: - case CPU_R4400SC: - vce_available = 1; - /* Fall through ... */ - case CPU_R4000PC: - case CPU_R4400PC: - case CPU_R4200: - case CPU_R4300: - case CPU_R4600: - case CPU_R5000: - case CPU_NEVADA: -r4k: - /* Debug TLB refill handler. */ - memcpy((void *)KSEG0, &except_vec0, 0x80); - memcpy((void *)KSEG0 + 0x080, &except_vec1_r10k, 0x80); - - /* Cache error vector */ - memcpy((void *)(KSEG0 + 0x100), (void *) KSEG0, 0x80); - - if (vce_available) { - memcpy((void *)(KSEG0 + 0x180), &except_vec3_r4000, - 0x180); - } else { - memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, - 0x100); - } + if (cpu_has_divec) + memcpy((void *)(KSEG0 + 0x200), &except_vec4, 0x8); + + /* + * Some CPUs can enable/disable for cache parity detection, but does + * it different ways. + */ + parity_protection_init(); + + /* + * The Data Bus Errors / Instruction Bus Errors are signaled + * by external hardware. Therefore these two exceptions + * may have board specific handlers. + */ + if (board_be_init) + board_be_init(); - set_except_vector(1, __xtlb_mod); - set_except_vector(2, __xtlb_tlbl); - set_except_vector(3, __xtlb_tlbs); - set_except_vector(4, handle_adel); - set_except_vector(5, handle_ades); - - /* DBE / IBE exception handler are system specific. */ - bus_error_init(); - - set_except_vector(8, handle_sys); - set_except_vector(9, handle_bp); - set_except_vector(10, handle_ri); - set_except_vector(11, handle_cpu); - set_except_vector(12, handle_ov); - set_except_vector(13, handle_tr); + set_except_vector(1, __xtlb_mod); + set_except_vector(2, __xtlb_tlbl); + set_except_vector(3, __xtlb_tlbs); + set_except_vector(4, handle_adel); + set_except_vector(5, handle_ades); + + set_except_vector(6, handle_ibe); + set_except_vector(7, handle_dbe); + + set_except_vector(8, handle_sys); + set_except_vector(9, handle_bp); + set_except_vector(10, handle_ri); + set_except_vector(11, handle_cpu); + set_except_vector(12, handle_ov); + set_except_vector(13, handle_tr); + set_except_vector(22, handle_mdmx); + + if (cpu_has_fpu && !cpu_has_nofpuex) set_except_vector(15, handle_fpe); - break; - case CPU_R8000: - panic("unsupported CPU type %s.\n", cpu_names[mips_cputype]); - break; + if (cpu_has_mcheck) + set_except_vector(24, handle_mcheck); - case CPU_UNKNOWN: - default: - panic("Unknown CPU type"); + if (cpu_has_vce) + memcpy((void *)(KSEG0 + 0x180), &except_vec3_r4000, 0x100); + else if (cpu_has_4kex) + memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, 0x80); + else + memcpy((void *)(KSEG0 + 0x080), &except_vec3_generic, 0x80); + + if (current_cpu_data.cputype == CPU_R6000 || + current_cpu_data.cputype == CPU_R6000A) { + /* + * The R6000 is the only R-series CPU that features a machine + * check exception (similar to the R4000 cache error) and + * unaligned ldc1/sdc1 exception. The handlers have not been + * written yet. Well, anyway there is no R6000 machine on the + * current list of targets for Linux/MIPS. + * (Duh, crap, there is someone with a tripple R6k machine) + */ + //set_except_vector(14, handle_mc); + //set_except_vector(15, handle_ndc); + } + + if (cpu_has_fpu) { + save_fp_context = _save_fp_context; + restore_fp_context = _restore_fp_context; + } else { + save_fp_context = fpu_emulator_save_context; + restore_fp_context = fpu_emulator_restore_context; } - flush_icache_range(KSEG0, KSEG0 + 0x200); + + flush_icache_range(KSEG0, KSEG0 + 0x400); + + if (current_cpu_data.isa_level == MIPS_CPU_ISA_IV) + set_c0_status(ST0_XX); atomic_inc(&init_mm.mm_count); /* XXX UP? */ current->active_mm = &init_mm; diff -Nru a/arch/mips64/kernel/unaligned.c b/arch/mips64/kernel/unaligned.c --- a/arch/mips64/kernel/unaligned.c Tue Jul 1 18:44:33 2003 +++ b/arch/mips64/kernel/unaligned.c Tue Jul 1 18:44:33 2003 @@ -5,7 +5,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1996, 1998, 1999 by Ralf Baechle + * Copyright (C) 1996, 1998, 1999, 2002 by Ralf Baechle * Copyright (C) 1999 Silicon Graphics, Inc. * * This file contains exception handler for address error exception with the @@ -41,7 +41,7 @@ * * #include * #include - * + * * struct foo { * unsigned char bar[8]; * }; @@ -74,6 +74,7 @@ */ #include #include +#include #include #include #include @@ -88,23 +89,22 @@ #define STR(x) __STR(x) #define __STR(x) #x -/* - * User code may only access USEG; kernel code may access the - * entire address space. - */ -#define check_axs(pc,a,s) \ - if ((long)(~(pc) & ((a) | ((a)+(s)))) < 0) \ - goto sigbus; +#ifdef CONFIG_PROC_FS +unsigned long unaligned_instructions; +#endif -static inline void -emulate_load_store_insn(struct pt_regs *regs, - unsigned long addr, - unsigned long pc) +static inline int emulate_load_store_insn(struct pt_regs *regs, + void *addr, unsigned long pc, + unsigned long **regptr, unsigned long *newvalue) { union mips_instruction insn; - unsigned long value, fixup; + unsigned long value; + const struct exception_table_entry *fixup; + unsigned int res; regs->regs[0] = 0; + *regptr=NULL; + /* * This load never faults. */ @@ -144,186 +144,295 @@ * The remaining opcodes are the ones that are really of interest. */ case lh_op: - check_axs(pc, addr, 2); - __asm__( - ".set\tnoat\n" + if (verify_area(VERIFY_READ, addr, 2)) + goto sigbus; + + __asm__ __volatile__ (".set\tnoat\n" #ifdef __BIG_ENDIAN - "1:\tlb\t%0,0(%1)\n" - "2:\tlbu\t$1,1(%1)\n\t" + "1:\tlb\t%0, 0(%2)\n" + "2:\tlbu\t$1, 1(%2)\n\t" #endif #ifdef __LITTLE_ENDIAN - "1:\tlb\t%0,1(%1)\n" - "2:\tlbu\t$1,0(%1)\n\t" + "1:\tlb\t%0, 1(%2)\n" + "2:\tlbu\t$1, 0(%2)\n\t" #endif - "sll\t%0,0x8\n\t" - "or\t%0,$1\n\t" - ".set\tat\n\t" + "sll\t%0, 0x8\n\t" + "or\t%0, $1\n\t" + "li\t%1, 0\n" + "3:\t.set\tat\n\t" + ".section\t.fixup,\"ax\"\n\t" + "4:\tli\t%1, %3\n\t" + "j\t3b\n\t" + ".previous\n\t" ".section\t__ex_table,\"a\"\n\t" - STR(PTR)"\t1b,%2\n\t" - STR(PTR)"\t2b,%2\n\t" + STR(PTR)"\t1b, 4b\n\t" + STR(PTR)"\t2b, 4b\n\t" ".previous" - :"=&r" (value) - :"r" (addr), "i" (&&fault) - :"$1"); - regs->regs[insn.i_format.rt] = value; - return; + : "=&r" (value), "=r" (res) + : "r" (addr), "i" (-EFAULT)); + if (res) + goto fault; + *newvalue = value; + *regptr = ®s->regs[insn.i_format.rt]; + break; case lw_op: - check_axs(pc, addr, 4); - __asm__( + if (verify_area(VERIFY_READ, addr, 4)) + goto sigbus; + + __asm__ __volatile__ ( #ifdef __BIG_ENDIAN - "1:\tlwl\t%0,(%1)\n" - "2:\tlwr\t%0,3(%1)\n\t" + "1:\tlwl\t%0, (%2)\n" + "2:\tlwr\t%0, 3(%2)\n\t" #endif #ifdef __LITTLE_ENDIAN - "1:\tlwl\t%0,3(%1)\n" - "2:\tlwr\t%0,(%1)\n\t" + "1:\tlwl\t%0, 3(%2)\n" + "2:\tlwr\t%0, (%2)\n\t" #endif + "li\t%1, 0\n" + "3:\t.section\t.fixup,\"ax\"\n\t" + "4:\tli\t%1, %3\n\t" + "j\t3b\n\t" + ".previous\n\t" ".section\t__ex_table,\"a\"\n\t" - STR(PTR)"\t1b,%2\n\t" - STR(PTR)"\t2b,%2\n\t" + STR(PTR)"\t1b, 4b\n\t" + STR(PTR)"\t2b, 4b\n\t" ".previous" - :"=&r" (value) - :"r" (addr), "i" (&&fault)); - regs->regs[insn.i_format.rt] = value; - return; + : "=&r" (value), "=r" (res) + : "r" (addr), "i" (-EFAULT)); + if (res) + goto fault; + *newvalue = value; + *regptr = ®s->regs[insn.i_format.rt]; + break; case lhu_op: - check_axs(pc, addr, 2); - __asm__( + if (verify_area(VERIFY_READ, addr, 2)) + goto sigbus; + + __asm__ __volatile__ ( ".set\tnoat\n" #ifdef __BIG_ENDIAN - "1:\tlbu\t%0,0(%1)\n" - "2:\tlbu\t$1,1(%1)\n\t" + "1:\tlbu\t%0, 0(%2)\n" + "2:\tlbu\t$1, 1(%2)\n\t" #endif #ifdef __LITTLE_ENDIAN - "1:\tlbu\t%0,1(%1)\n" - "2:\tlbu\t$1,0(%1)\n\t" + "1:\tlbu\t%0, 1(%2)\n" + "2:\tlbu\t$1, 0(%2)\n\t" #endif - "sll\t%0,0x8\n\t" - "or\t%0,$1\n\t" - ".set\tat\n\t" + "sll\t%0, 0x8\n\t" + "or\t%0, $1\n\t" + "li\t%1, 0\n" + "3:\t.set\tat\n\t" + ".section\t.fixup,\"ax\"\n\t" + "4:\tli\t%1, %3\n\t" + "j\t3b\n\t" + ".previous\n\t" ".section\t__ex_table,\"a\"\n\t" - STR(PTR)"\t1b,%2\n\t" - STR(PTR)"\t2b,%2\n\t" + STR(PTR)"\t1b, 4b\n\t" + STR(PTR)"\t2b, 4b\n\t" ".previous" - :"=&r" (value) - :"r" (addr), "i" (&&fault) - :"$1"); - regs->regs[insn.i_format.rt] = value; - return; + : "=&r" (value), "=r" (res) + : "r" (addr), "i" (-EFAULT)); + if (res) + goto fault; + *newvalue = value; + *regptr = ®s->regs[insn.i_format.rt]; + break; case lwu_op: - check_axs(pc, addr, 4); - __asm__( +#ifdef CONFIG_MIPS64 + /* + * A 32-bit kernel might be running on a 64-bit processor. But + * if we're on a 32-bit processor and an i-cache incoherency + * or race makes us see a 64-bit instruction here the sdl/sdr + * would blow up, so for now we don't handle unaligned 64-bit + * instructions on 32-bit kernels. + */ + if (verify_area(VERIFY_READ, addr, 4)) + goto sigbus; + + __asm__ __volatile__ ( #ifdef __BIG_ENDIAN - "1:\tlwl\t%0,(%1)\n" - "2:\tlwr\t%0,3(%1)\n\t" + "1:\tlwl\t%0, (%2)\n" + "2:\tlwr\t%0, 3(%2)\n\t" #endif #ifdef __LITTLE_ENDIAN - "1:\tlwl\t%0,3(%1)\n" - "2:\tlwr\t%0,(%1)\n\t" + "1:\tlwl\t%0, 3(%2)\n" + "2:\tlwr\t%0, (%2)\n\t" #endif + "dsll\t%0, %0, 32\n\t" + "dsrl\t%0, %0, 32\n\t" + "li\t%1, 0\n" + "3:\t.section\t.fixup,\"ax\"\n\t" + "4:\tli\t%1, %3\n\t" + "j\t3b\n\t" + ".previous\n\t" ".section\t__ex_table,\"a\"\n\t" - STR(PTR)"\t1b,%2\n\t" - STR(PTR)"\t2b,%2\n\t" + STR(PTR)"\t1b, 4b\n\t" + STR(PTR)"\t2b, 4b\n\t" ".previous" - :"=&r" (value) - :"r" (addr), "i" (&&fault)); - value &= 0xffffffff; - regs->regs[insn.i_format.rt] = value; - return; + : "=&r" (value), "=r" (res) + : "r" (addr), "i" (-EFAULT)); + if (res) + goto fault; + *newvalue = value; + *regptr = ®s->regs[insn.i_format.rt]; + break; +#endif /* CONFIG_MIPS64 */ + + /* Cannot handle 64-bit instructions in 32-bit kernel */ + goto sigill; case ld_op: - check_axs(pc, addr, 8); - __asm__( - ".set\tmips3\n" +#ifdef CONFIG_MIPS64 + /* + * A 32-bit kernel might be running on a 64-bit processor. But + * if we're on a 32-bit processor and an i-cache incoherency + * or race makes us see a 64-bit instruction here the sdl/sdr + * would blow up, so for now we don't handle unaligned 64-bit + * instructions on 32-bit kernels. + */ + if (verify_area(VERIFY_READ, addr, 8)) + goto sigbus; + + __asm__ __volatile__ ( #ifdef __BIG_ENDIAN - "1:\tldl\t%0,(%1)\n" - "2:\tldr\t%0,7(%1)\n\t" + "1:\tldl\t%0, (%2)\n" + "2:\tldr\t%0, 7(%2)\n\t" #endif #ifdef __LITTLE_ENDIAN - "1:\tldl\t%0,7(%1)\n" - "2:\tldr\t%0,(%1)\n\t" + "1:\tldl\t%0, 7(%2)\n" + "2:\tldr\t%0, (%2)\n\t" #endif - ".set\tmips0\n\t" + "li\t%1, 0\n" + "3:\t.section\t.fixup,\"ax\"\n\t" + "4:\tli\t%1, %3\n\t" + "j\t3b\n\t" + ".previous\n\t" ".section\t__ex_table,\"a\"\n\t" - STR(PTR)"\t1b,%2\n\t" - STR(PTR)"\t2b,%2\n\t" + STR(PTR)"\t1b, 4b\n\t" + STR(PTR)"\t2b, 4b\n\t" ".previous" - :"=&r" (value) - :"r" (addr), "i" (&&fault)); - regs->regs[insn.i_format.rt] = value; - return; + : "=&r" (value), "=r" (res) + : "r" (addr), "i" (-EFAULT)); + if (res) + goto fault; + *newvalue = value; + *regptr = ®s->regs[insn.i_format.rt]; + break; +#endif /* CONFIG_MIPS64 */ + + /* Cannot handle 64-bit instructions in 32-bit kernel */ + goto sigill; case sh_op: - check_axs(pc, addr, 2); + if (verify_area(VERIFY_WRITE, addr, 2)) + goto sigbus; + value = regs->regs[insn.i_format.rt]; - __asm__( + __asm__ __volatile__ ( #ifdef __BIG_ENDIAN ".set\tnoat\n" - "1:\tsb\t%0,1(%1)\n\t" - "srl\t$1,%0,0x8\n" - "2:\tsb\t$1,0(%1)\n\t" + "1:\tsb\t%1, 1(%2)\n\t" + "srl\t$1, %1, 0x8\n" + "2:\tsb\t$1, 0(%2)\n\t" ".set\tat\n\t" #endif #ifdef __LITTLE_ENDIAN ".set\tnoat\n" - "1:\tsb\t%0,0(%1)\n\t" - "srl\t$1,%0,0x8\n" - "2:\tsb\t$1,1(%1)\n\t" + "1:\tsb\t%1, 0(%2)\n\t" + "srl\t$1,%1, 0x8\n" + "2:\tsb\t$1, 1(%2)\n\t" ".set\tat\n\t" #endif + "li\t%0, 0\n" + "3:\n\t" + ".section\t.fixup,\"ax\"\n\t" + "4:\tli\t%0, %3\n\t" + "j\t3b\n\t" + ".previous\n\t" ".section\t__ex_table,\"a\"\n\t" - STR(PTR)"\t1b,%2\n\t" - STR(PTR)"\t2b,%2\n\t" + STR(PTR)"\t1b, 4b\n\t" + STR(PTR)"\t2b, 4b\n\t" ".previous" - : /* no outputs */ - :"r" (value), "r" (addr), "i" (&&fault) - :"$1"); - return; + : "=r" (res) + : "r" (value), "r" (addr), "i" (-EFAULT)); + if (res) + goto fault; + break; case sw_op: - check_axs(pc, addr, 4); + if (verify_area(VERIFY_WRITE, addr, 4)) + goto sigbus; + value = regs->regs[insn.i_format.rt]; - __asm__( + __asm__ __volatile__ ( #ifdef __BIG_ENDIAN - "1:\tswl\t%0,(%1)\n" - "2:\tswr\t%0,3(%1)\n\t" + "1:\tswl\t%1,(%2)\n" + "2:\tswr\t%1, 3(%2)\n\t" #endif #ifdef __LITTLE_ENDIAN - "1:\tswl\t%0,3(%1)\n" - "2:\tswr\t%0,(%1)\n\t" + "1:\tswl\t%1, 3(%2)\n" + "2:\tswr\t%1, (%2)\n\t" #endif + "li\t%0, 0\n" + "3:\n\t" + ".section\t.fixup,\"ax\"\n\t" + "4:\tli\t%0, %3\n\t" + "j\t3b\n\t" + ".previous\n\t" ".section\t__ex_table,\"a\"\n\t" - STR(PTR)"\t1b,%2\n\t" - STR(PTR)"\t2b,%2\n\t" + STR(PTR)"\t1b, 4b\n\t" + STR(PTR)"\t2b, 4b\n\t" ".previous" - : /* no outputs */ - :"r" (value), "r" (addr), "i" (&&fault)); - return; + : "=r" (res) + : "r" (value), "r" (addr), "i" (-EFAULT)); + if (res) + goto fault; + break; case sd_op: - check_axs(pc, addr, 8); +#ifdef CONFIG_MIPS64 + /* + * A 32-bit kernel might be running on a 64-bit processor. But + * if we're on a 32-bit processor and an i-cache incoherency + * or race makes us see a 64-bit instruction here the sdl/sdr + * would blow up, so for now we don't handle unaligned 64-bit + * instructions on 32-bit kernels. + */ + if (verify_area(VERIFY_WRITE, addr, 8)) + goto sigbus; + value = regs->regs[insn.i_format.rt]; - __asm__( - ".set\tmips3\n" + __asm__ __volatile__ ( #ifdef __BIG_ENDIAN - "1:\tsdl\t%0,(%1)\n" - "2:\tsdr\t%0,7(%1)\n\t" + "1:\tsdl\t%1,(%2)\n" + "2:\tsdr\t%1, 7(%2)\n\t" #endif #ifdef __LITTLE_ENDIAN - "1:\tsdl\t%0,7(%1)\n" - "2:\tsdr\t%0,(%1)\n\t" + "1:\tsdl\t%1, 7(%2)\n" + "2:\tsdr\t%1, (%2)\n\t" #endif - ".set\tmips0\n\t" + "li\t%0, 0\n" + "3:\n\t" + ".section\t.fixup,\"ax\"\n\t" + "4:\tli\t%0, %3\n\t" + "j\t3b\n\t" + ".previous\n\t" ".section\t__ex_table,\"a\"\n\t" - STR(PTR)"\t1b,%2\n\t" - STR(PTR)"\t2b,%2\n\t" + STR(PTR)"\t1b, 4b\n\t" + STR(PTR)"\t2b, 4b\n\t" ".previous" - : /* no outputs */ - :"r" (value), "r" (addr), "i" (&&fault)); - return; + : "=r" (res) + : "r" (value), "r" (addr), "i" (-EFAULT)); + if (res) + goto fault; + break; +#endif /* CONFIG_MIPS64 */ + + /* Cannot handle 64-bit instructions in 32-bit kernel */ + goto sigill; case lwc1_op: case ldc1_op: @@ -352,63 +461,97 @@ */ goto sigill; } - return; + +#ifdef CONFIG_PROC_FS + unaligned_instructions++; +#endif + + return 0; fault: /* Did we have an exception handler installed? */ - fixup = search_exception_table(regs->cp0_epc); + fixup = search_exception_tables(exception_epc(regs)); if (fixup) { - long new_epc; - new_epc = fixup_exception(dpf_reg, fixup, regs->cp0_epc); + unsigned long new_epc = fixup->nextinsn; printk(KERN_DEBUG "%s: Forwarding exception at [<%lx>] (%lx)\n", current->comm, regs->cp0_epc, new_epc); regs->cp0_epc = new_epc; - return; + return 1; } die_if_kernel ("Unhandled kernel unaligned access", regs); send_sig(SIGSEGV, current, 1); - return; + + return 0; + sigbus: - die_if_kernel ("Unhandled kernel unaligned access", regs); + die_if_kernel("Unhandled kernel unaligned access", regs); send_sig(SIGBUS, current, 1); - return; + + return 0; + sigill: - die_if_kernel ("Unhandled kernel unaligned access or invalid instruction", regs); + die_if_kernel("Unhandled kernel unaligned access or invalid instruction", regs); send_sig(SIGILL, current, 1); - return; -} -#ifdef CONFIG_PROC_FS -unsigned long unaligned_instructions; -#endif + return 0; +} asmlinkage void do_ade(struct pt_regs *regs) { + unsigned long *regptr, newval; + extern int do_dsemulret(struct pt_regs *); + mm_segment_t seg; unsigned long pc; /* + * Address errors may be deliberately induced by the FPU emulator to + * retake control of the CPU after executing the instruction in the + * delay slot of an emulated branch. + */ + /* Terminate if exception was recognized as a delay slot return */ + if (do_dsemulret(regs)) + return; + + /* Otherwise handle as normal */ + + /* * Did we catch a fault trying to load an instruction? - * This also catches attempts to activate MIPS16 code on - * CPUs which don't support it. + * Or are we running in MIPS16 mode? */ - if (regs->cp0_badvaddr == regs->cp0_epc) + if ((regs->cp0_badvaddr == regs->cp0_epc) || (regs->cp0_epc & 0x1)) goto sigbus; - pc = regs->cp0_epc + ((regs->cp0_cause & CAUSEF_BD) ? 4 : 0); - if (compute_return_epc(regs)) - return; + pc = exception_epc(regs); if ((current->thread.mflags & MF_FIXADE) == 0) goto sigbus; - emulate_load_store_insn(regs, regs->cp0_badvaddr, pc); -#ifdef CONFIG_PROC_FS - unaligned_instructions++; -#endif + /* + * Do branch emulation only if we didn't forward the exception. + * This is all so but ugly ... + */ + seg = get_fs(); + if (!user_mode(regs)) + set_fs(KERNEL_DS); + if (!emulate_load_store_insn(regs, (void *)regs->cp0_badvaddr, pc, + ®ptr, &newval)) { + compute_return_epc(regs); + /* + * Now that branch is evaluated, update the dest + * register if necessary + */ + if (regptr) + *regptr = newval; + } + set_fs(seg); return; sigbus: - die_if_kernel ("Kernel unaligned instruction access", regs); + die_if_kernel("Kernel unaligned instruction access", regs); force_sig(SIGBUS, current); + + /* + * XXX On return from the signal handler we should advance the epc + */ } diff -Nru a/arch/mips64/ld.script.elf64 b/arch/mips64/ld.script.elf64 --- a/arch/mips64/ld.script.elf64 Tue Jul 1 18:44:37 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,143 +0,0 @@ -OUTPUT_ARCH(mips) -ENTRY(kernel_entry) -jiffies = jiffies_64; -SECTIONS -{ - /* Read-only sections, merged into text segment: */ - /* . = 0xc000000000000000; */ - - /* This is the value for an Origin kernel, taken from an IRIX kernel. */ - /* . = 0xc00000000001c000; */ - - /* Set the vaddr for the text segment to a value - >= 0xa800 0000 0001 9000 if no symmon is going to configured - >= 0xa800 0000 0030 0000 otherwise */ - - /* . = 0xa800000000300000; */ - /* . = 0xa800000000300000; */ - . = 0xffffffff80300000; - .text : { - *(.text) - *(.rodata) - *(.rodata.*) - *(.rodata1) - /* .gnu.warning sections are handled specially by elf32.em. */ - *(.gnu.warning) - } = 0 - .kstrtab : { *(.kstrtab) } - __vermagic : { *(__vermagic) } - - . = ALIGN(16); /* Exception table */ - __start___ex_table = .; - __ex_table : { *(__ex_table) } - __stop___ex_table = .; - - __start___dbe_table = .; /* Exception table for data bus errors */ - __dbe_table : { *(__dbe_table) } - __stop___dbe_table = .; - - _etext = .; - - . = ALIGN(16384); - .data.init_task : { *(.data.init_task) } - - /* Startup code */ - . = ALIGN(4096); - __init_begin = .; - .text.init : { *(.text.init) } - .data.init : { *(.data.init) } - . = ALIGN(16); - __setup_start = .; - .setup.init : { *(.setup.init) } - __setup_end = .; - __initcall_start = .; - .initcall.init : { - *(.initcall1.init) - *(.initcall2.init) - *(.initcall3.init) - *(.initcall4.init) - *(.initcall5.init) - *(.initcall6.init) - *(.initcall7.init) - } - __initcall_end = .; - . = ALIGN(4096); /* Align double page for init_task_union */ - __init_end = .; - - . = ALIGN(4096); - .data.page_aligned : { *(.data.idt) } - - . = ALIGN(32); - .data.cacheline_aligned : { *(.data.cacheline_aligned) } - - .fini : { *(.fini) } =0 - .reginfo : { *(.reginfo) } - /* Adjust the address for the data segment. We want to adjust up to - the same address within the page on the next page up. It would - be more correct to do this: - . = .; - The current expression does not correctly handle the case of a - text segment ending precisely at the end of a page; it causes the - data segment to skip a page. The above expression does not have - this problem, but it will currently (2/95) cause BFD to allocate - a single segment, combining both text and data, for this case. - This will prevent the text segment from being shared among - multiple executions of the program; I think that is more - important than losing a page of the virtual address space (note - that no actual memory is lost; the page which is skipped can not - be referenced). */ - . = .; - .data : - { - _fdata = . ; - *(.data) - CONSTRUCTORS - } - .data1 : { *(.data1) } - .lit8 : { *(.lit8) } - .lit4 : { *(.lit4) } - .ctors : { *(.ctors) } - .dtors : { *(.dtors) } - .got : { *(.got.plt) *(.got) } - .dynamic : { *(.dynamic) } - /* We want the small data sections together, so single-instruction offsets - can access them all, and initialized data all before uninitialized, so - we can shorten the on-disk segment size. */ - .sdata : { *(.sdata) } - _edata = .; - - .sbss : { *(.sbss) *(.scommon) } - .bss : - { - *(.dynbss) - *(.bss) - *(COMMON) - _end = . ; - } - - /* Sections to be discarded */ - /DISCARD/ : - { - *(.text.exit) - *(.data.exit) - *(.exitcall.exit) - } - - /* These are needed for ELF backends which have not yet been - converted to the new style linker. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - /* DWARF debug sections. - Symbols in the .debug DWARF section are relative to the beginning of the - section so we begin .debug at 0. It's not clear yet what needs to happen - for the others. */ - .debug 0 : { *(.debug) } - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - .debug_sfnames 0 : { *(.debug_sfnames) } - .line 0 : { *(.line) } - /* These must appear regardless of . */ - .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) } - .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) } -} diff -Nru a/arch/mips64/lib/Makefile b/arch/mips64/lib/Makefile --- a/arch/mips64/lib/Makefile Tue Jul 1 18:44:37 2003 +++ b/arch/mips64/lib/Makefile Tue Jul 1 18:44:37 2003 @@ -2,9 +2,17 @@ # Makefile for MIPS-specific library files.. # -EXTRA_AFLAGS := $(CFLAGS) +lib-y += csum_partial.o csum_partial_copy.o memcpy.o \ + memset.o promlib.o rtc-std.o rtc-no.o strlen_user.o \ + strncpy_user.o strnlen_user.o watch.o + +ifeq ($(CONFIG_CPU_R3000)$(CONFIG_CPU_TX39XX),y) + lib-y += r3k_dump_tlb.o +else + lib-y += dump_tlb.o +endif -lib-y += csum_partial.o csum_partial_copy.o dump_tlb.o floppy-std.o \ - floppy-no.o ide-std.o ide-no.o kbd-std.o kbd-no.o rtc-std.o \ - rtc-no.o memset.o memcpy.o strlen_user.o strncpy_user.o \ - strnlen_user.o watch.o +lib-$(CONFIG_BLK_DEV_FD) += floppy-no.o floppy-std.o +lib-$(subst m,y,$(CONFIG_IDE)) += ide-std.o ide-no.o # needed for ide module + +EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips64/lib/csum_partial_copy.c b/arch/mips64/lib/csum_partial_copy.c --- a/arch/mips64/lib/csum_partial_copy.c Tue Jul 1 18:44:37 2003 +++ b/arch/mips64/lib/csum_partial_copy.c Tue Jul 1 18:44:37 2003 @@ -16,8 +16,8 @@ /* * copy while checksumming, otherwise like csum_partial */ -unsigned int csum_partial_copy_nocheck(const char *src, char *dst, - int len, unsigned int sum) +unsigned int csum_partial_copy_nocheck(const char *src, char *dst, + int len, unsigned int sum) { /* * It's 2:30 am and I don't feel like doing it real ... @@ -44,6 +44,6 @@ memset(dst + len - missing, 0, missing); *err_ptr = -EFAULT; } - + return csum_partial(dst, len, sum); } diff -Nru a/arch/mips64/lib/dump_tlb.c b/arch/mips64/lib/dump_tlb.c --- a/arch/mips64/lib/dump_tlb.c Tue Jul 1 18:44:37 2003 +++ b/arch/mips64/lib/dump_tlb.c Tue Jul 1 18:44:37 2003 @@ -11,34 +11,47 @@ #include #include +#include #include #include #include -#define mips_tlb_entries 64 +static inline const char *msk2str(unsigned int mask) +{ + switch (mask) { + case PM_4K: return "4kb"; + case PM_16K: return "16kb"; + case PM_64K: return "64kb"; + case PM_256K: return "256kb"; + case PM_1M: return "1Mb"; + case PM_4M: return "4Mb"; + case PM_16M: return "16Mb"; + case PM_64M: return "64Mb"; + case PM_256M: return "256Mb"; + } +} -void -dump_tlb(int first, int last) +void dump_tlb(int first, int last) { unsigned long s_entryhi, entryhi, entrylo0, entrylo1, asid; unsigned int s_index, pagemask, c0, c1, i; - s_entryhi = get_entryhi(); - s_index = get_index(); + s_entryhi = read_c0_entryhi(); + s_index = read_c0_index(); asid = s_entryhi & 0xff; for (i = first; i <= last; i++) { - write_32bit_cp0_register(CP0_INDEX, i); + write_c0_index(i); __asm__ __volatile__( ".set\tnoreorder\n\t" "nop;nop;nop;nop\n\t" "tlbr\n\t" "nop;nop;nop;nop\n\t" ".set\treorder"); - pagemask = read_32bit_cp0_register(CP0_PAGEMASK); - entryhi = get_entryhi(); - entrylo0 = get_entrylo0(); - entrylo1 = get_entrylo1(); + pagemask = read_c0_pagemask(); + entryhi = read_c0_entryhi(); + entrylo0 = read_c0_entrylo0(); + entrylo1 = read_c0_entrylo1(); /* Unused entries have a virtual address of CKSEG0. */ if ((entryhi & ~0x1ffffUL) != CKSEG0 @@ -46,47 +59,44 @@ /* * Only print entries in use */ - printk("Index: %2d pgmask=%08x ", i, pagemask); + printk("Index: %2d pgmask=%s ", i, msk2str(pagemask)); c0 = (entrylo0 >> 3) & 7; c1 = (entrylo1 >> 3) & 7; - printk("va=%08lx asid=%02lx" - " [pa=%06lx c=%d d=%d v=%d g=%ld]" - " [pa=%06lx c=%d d=%d v=%d g=%ld]\n", + printk("va=%011lx asid=%02lx\n", (entryhi & ~0x1fffUL), - entryhi & 0xff, - entrylo0 & PAGE_MASK, c0, + entryhi & 0xff); + printk("\t[pa=%011lx c=%d d=%d v=%d g=%ld] ", + (entrylo0 << 6) & PAGE_MASK, c0, (entrylo0 & 4) ? 1 : 0, (entrylo0 & 2) ? 1 : 0, - (entrylo0 & 1), - entrylo1 & PAGE_MASK, c1, + (entrylo0 & 1)); + printk("[pa=%011lx c=%d d=%d v=%d g=%ld]\n", + (entrylo1 << 6) & PAGE_MASK, c1, (entrylo1 & 4) ? 1 : 0, (entrylo1 & 2) ? 1 : 0, (entrylo1 & 1)); - } } printk("\n"); - set_entryhi(s_entryhi); - set_index(s_index); + write_c0_entryhi(s_entryhi); + write_c0_index(s_index); } -void -dump_tlb_all(void) +void dump_tlb_all(void) { - dump_tlb(0, mips_tlb_entries - 1); + dump_tlb(0, current_cpu_data.tlbsize - 1); } -void -dump_tlb_wired(void) +void dump_tlb_wired(void) { int wired; - wired = read_32bit_cp0_register(CP0_WIRED); + wired = read_c0_wired(); printk("Wired: %d", wired); - dump_tlb(0, read_32bit_cp0_register(CP0_WIRED)); + dump_tlb(0, read_c0_wired()); } #define BARRIER \ @@ -95,21 +105,20 @@ "nop;nop;nop;nop;nop;nop;nop\n\t" \ ".set\treorder"); -void -dump_tlb_addr(unsigned long addr) +void dump_tlb_addr(unsigned long addr) { unsigned int flags, oldpid; int index; local_irq_save(flags); - oldpid = get_entryhi() & 0xff; + oldpid = read_c0_entryhi() & 0xff; BARRIER; - set_entryhi((addr & PAGE_MASK) | oldpid); + write_c0_entryhi((addr & PAGE_MASK) | oldpid); BARRIER; tlb_probe(); BARRIER; - index = get_index(); - set_entryhi(oldpid); + index = read_c0_index(); + write_c0_entryhi(oldpid); local_irq_restore(flags); if (index < 0) { @@ -121,14 +130,12 @@ dump_tlb(index, index); } -void -dump_tlb_nonwired(void) +void dump_tlb_nonwired(void) { - dump_tlb(read_32bit_cp0_register(CP0_WIRED), mips_tlb_entries - 1); + dump_tlb(read_c0_wired(), current_cpu_data.tlbsize - 1); } -void -dump_list_process(struct task_struct *t, void *address) +void dump_list_process(struct task_struct *t, void *address) { pgd_t *page_dir, *pgd; pmd_t *pmd; @@ -154,7 +161,7 @@ printk("pte == %08lx, ", (unsigned long) pte); page = *pte; - printk("page == %08lx\n", (unsigned long) pte_val(page)); + printk("page == %08lx\n", pte_val(page)); val = pte_val(page); if (val & _PAGE_PRESENT) printk("present "); @@ -194,8 +201,7 @@ { int i; - for(i=0;i<8;i++) - { + for(i = 0; i < 8; i++) { printk("*%08lx == %08lx, ", (unsigned long)p, (unsigned long)*p); p++; diff -Nru a/arch/mips64/lib/floppy-std.c b/arch/mips64/lib/floppy-std.c --- a/arch/mips64/lib/floppy-std.c Tue Jul 1 18:44:35 2003 +++ b/arch/mips64/lib/floppy-std.c Tue Jul 1 18:44:35 2003 @@ -15,11 +15,11 @@ #include #include #include + #include #include #include #include -#include #include #include #include @@ -100,23 +100,9 @@ return 0x3f0; } -/* Pure 2^n version of get_order */ -static int __get_order(unsigned long size) -{ - int order; - - size = (size-1) >> (PAGE_SHIFT-1); - order = -1; - do { - size >>= 1; - order++; - } while (size); - return order; -} - static unsigned long std_fd_dma_mem_alloc(unsigned long size) { - int order = __get_order(size); + int order = get_order(size); unsigned long mem; mem = __get_dma_pages(GFP_KERNEL,order); @@ -125,8 +111,8 @@ } static void std_fd_dma_mem_free(unsigned long addr, unsigned long size) -{ - free_pages(addr, __get_order(size)); +{ + free_pages(addr, get_order(size)); } static unsigned long std_fd_drive_type(unsigned long n) diff -Nru a/arch/mips64/lib/ide-no.c b/arch/mips64/lib/ide-no.c --- a/arch/mips64/lib/ide-no.c Tue Jul 1 18:44:31 2003 +++ b/arch/mips64/lib/ide-no.c Tue Jul 1 18:44:31 2003 @@ -12,7 +12,6 @@ #include #include #include -#include static int no_ide_default_irq(ide_ioreg_t base) { diff -Nru a/arch/mips64/lib/ide-std.c b/arch/mips64/lib/ide-std.c --- a/arch/mips64/lib/ide-std.c Tue Jul 1 18:44:35 2003 +++ b/arch/mips64/lib/ide-std.c Tue Jul 1 18:44:35 2003 @@ -11,7 +11,6 @@ #include #include #include -#include #include static int std_ide_default_irq(ide_ioreg_t base) @@ -30,16 +29,11 @@ static ide_ioreg_t std_ide_default_io_base(int index) { - switch (index) { - case 0: return 0x1f0; - case 1: return 0x170; - case 2: return 0x1e8; - case 3: return 0x168; - case 4: return 0x1e0; - case 5: return 0x160; - default: - return 0; - } + static unsigned long ata_io_base[MAX_HWIFS] = { + 0x1f0, 0x170, 0x1e8, 0x168, 0x1e0, 0x160 + }; + + return ata_io_base[index]; } static void std_ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, diff -Nru a/arch/mips64/lib/kbd-no.c b/arch/mips64/lib/kbd-no.c --- a/arch/mips64/lib/kbd-no.c Tue Jul 1 18:44:37 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,62 +0,0 @@ -/* - * 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. - * - * Stub keyboard and psaux routines to keep Linux from crashing on machines - * without a keyboard. - * - * Copyright (C) 1998 by Ralf Baechle - */ -#include -#include - -static void no_kbd_request_region(void) -{ - /* No I/O ports are being used on the Indy. */ -} - -static int no_kbd_request_irq(void (*handler)(int, void *, struct pt_regs *)) -{ - return -ENODEV; -} - -static int no_aux_request_irq(void (*handler)(int, void *, struct pt_regs *)) -{ - return -ENODEV; -} - -static void no_aux_free_irq(void) -{ -} - -static unsigned char no_kbd_read_input(void) -{ - return 0; -} - -static void no_kbd_write_output(unsigned char val) -{ -} - -static void no_kbd_write_command(unsigned char val) -{ -} - -static unsigned char no_kbd_read_status(void) -{ - return 0; -} - -struct kbd_ops no_kbd_ops = { - no_kbd_request_region, - no_kbd_request_irq, - - no_aux_request_irq, - no_aux_free_irq, - - no_kbd_read_input, - no_kbd_write_output, - no_kbd_write_command, - no_kbd_read_status -}; diff -Nru a/arch/mips64/lib/kbd-std.c b/arch/mips64/lib/kbd-std.c --- a/arch/mips64/lib/kbd-std.c Tue Jul 1 18:44:37 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,80 +0,0 @@ -/* - * 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. - * - * Routines for standard PC style keyboards accessible via I/O ports. - * - * Copyright (C) 1998, 1999 by Ralf Baechle - */ -#include -#include -#include -#include -#include - -#define KEYBOARD_IRQ 1 -#define AUX_IRQ 12 - -static void std_kbd_request_region(void) -{ - request_region(0x60, 16, "keyboard"); -} - -static int std_kbd_request_irq(void (*handler)(int, void *, struct pt_regs *)) -{ - return request_irq(KEYBOARD_IRQ, handler, 0, "keyboard", NULL); -} - -static int std_aux_request_irq(void (*handler)(int, void *, struct pt_regs *)) -{ - return request_irq(AUX_IRQ, handler, 0, "PS/2 Mouse", NULL); -} - -static void std_aux_free_irq(void) -{ - free_irq(AUX_IRQ, NULL); -} - -static unsigned char std_kbd_read_input(void) -{ - return inb(KBD_DATA_REG); -} - -static void std_kbd_write_output(unsigned char val) -{ - int status; - - do { - status = inb(KBD_CNTL_REG); - } while (status & KBD_STAT_IBF); - outb(val, KBD_DATA_REG); -} - -static void std_kbd_write_command(unsigned char val) -{ - int status; - - do { - status = inb(KBD_CNTL_REG); - } while (status & KBD_STAT_IBF); - outb(val, KBD_CNTL_REG); -} - -static unsigned char std_kbd_read_status(void) -{ - return inb(KBD_STATUS_REG); -} - -struct kbd_ops std_kbd_ops = { - std_kbd_request_region, - std_kbd_request_irq, - - std_aux_request_irq, - std_aux_free_irq, - - std_kbd_read_input, - std_kbd_write_output, - std_kbd_write_command, - std_kbd_read_status -}; diff -Nru a/arch/mips64/lib/memcpy.S b/arch/mips64/lib/memcpy.S --- a/arch/mips64/lib/memcpy.S Tue Jul 1 18:44:31 2003 +++ b/arch/mips64/lib/memcpy.S Tue Jul 1 18:44:31 2003 @@ -5,766 +5,502 @@ * * Unified implementation of memcpy, memmove and the __copy_user backend. * - * Copyright (C) 1998, 1999, 2000, 2001 Ralf Baechle - * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + * Copyright (C) 1998, 99, 2000, 01, 2002 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 1999, 2000, 01, 2002 Silicon Graphics, Inc. + * Copyright (C) 2002 Broadcom, Inc. + * memcpy/copy_user author: Mark Vandevoorde * - * For __rmemcpy and memmove an exception is always a kernel bug, therefore - * they're not protected. In order to keep the exception fixup routine - * simple all memory accesses in __copy_user to src rsp. dst are stricly - * incremental. The fixup routine depends on $at not being changed. + * Mnemonic names for arguments to memcpy/__copy_user */ +#include #include #include #include +#define dst a0 +#define src a1 +#define len a2 + /* - * The fixup routine for copy_to_user depends on copying strictly in - * increasing order. Gas expands the ulw/usw macros in the wrong order for - * little endian machines, so we cannot depend on them. + * Spec + * + * memcpy copies len bytes from src to dst and sets v0 to dst. + * It assumes that + * - src and dst don't overlap + * - src is readable + * - dst is writable + * memcpy uses the standard calling convention + * + * __copy_user copies up to len bytes from src to dst and sets a2 (len) to + * the number of uncopied bytes due to an exception caused by a read or write. + * __copy_user assumes that src and dst don't overlap, and that the call is + * implementing one of the following: + * copy_to_user + * - src is readable (no exceptions when reading src) + * copy_from_user + * - dst is writable (no exceptions when writing dst) + * __copy_user uses a non-standard calling convention; see + * include/asm-mips/uaccess.h + * + * When an exception happens on a load, the handler must + # ensure that all of the destination buffer is overwritten to prevent + * leaking information to user mode programs. */ -#ifdef __MIPSEB__ -#define uswL swl -#define uswU swr -#define ulwL lwl -#define ulwU lwr -#define usdL sdl -#define usdU sdr -#define uldL ldl -#define uldU ldr -#endif -#ifdef __MIPSEL__ -#define uswL swr -#define uswU swl -#define ulwL lwr -#define ulwU lwl -#define usdL sdr -#define usdU sdl -#define uldL ldr -#define uldU ldl -#endif -#define EX(insn,reg,addr,handler) \ -9: insn reg, addr; \ - .section __ex_table,"a"; \ - PTR 9b, handler; \ - .previous +/* + * Implementation + */ -#define UEX(insn,reg,addr,handler) \ -9: insn ## L reg, addr; \ -10: insn ## U reg, 3 + addr; \ - .section __ex_table,"a"; \ - PTR 9b, handler; \ - PTR 10b, handler; \ - .previous +/* + * The exception handler for loads requires that: + * 1- AT contain the address of the byte just past the end of the source + * of the copy, + * 2- src_entry <= src < AT, and + * 3- (dst - src) == (dst_entry - src_entry), + * The _entry suffix denotes values when __copy_user was called. + * + * (1) is set up up by uaccess.h and maintained by not writing AT in copy_user + * (2) is met by incrementing src by the number of bytes copied + * (3) is met by not doing loads between a pair of increments of dst and src + * + * The exception handlers for stores adjust len (if necessary) and return. + * These handlers do not need to overwrite any data. + * + * For __rmemcpy and memmove an exception is always a kernel bug, therefore + * they're not protected. + */ -#define UEXD(insn,reg,addr,handler) \ -9: insn ## L reg, addr; \ -10: insn ## U reg, 7 + addr; \ - .section __ex_table,"a"; \ - PTR 9b, handler; \ - PTR 10b, handler; \ +#define EXC(inst_reg,addr,handler) \ +9: inst_reg, addr; \ + .section __ex_table,"a"; \ + PTR 9b, handler; \ .previous -/* ascending order, destination aligned */ -#define MOVE_BIGGERCHUNK(src, dst, offset, t0, t1, t2, t3) \ - EX(ld, t0, (offset + 0x00)(src), l_fixup); \ - EX(ld, t1, (offset + 0x08)(src), l_fixup); \ - EX(ld, t2, (offset + 0x10)(src), l_fixup); \ - EX(ld, t3, (offset + 0x18)(src), l_fixup); \ - EX(sd, t0, (offset + 0x00)(dst), s_fixup); \ - EX(sd, t1, (offset + 0x08)(dst), s_fixup); \ - EX(sd, t2, (offset + 0x10)(dst), s_fixup); \ - EX(sd, t3, (offset + 0x18)(dst), s_fixup); \ - EX(ld, t0, (offset + 0x20)(src), l_fixup); \ - EX(ld, t1, (offset + 0x28)(src), l_fixup); \ - EX(ld, t2, (offset + 0x30)(src), l_fixup); \ - EX(ld, t3, (offset + 0x38)(src), l_fixup); \ - EX(sd, t0, (offset + 0x20)(dst), s_fixup); \ - EX(sd, t1, (offset + 0x28)(dst), s_fixup); \ - EX(sd, t2, (offset + 0x30)(dst), s_fixup); \ - EX(sd, t3, (offset + 0x38)(dst), s_fixup) - -/* ascending order, destination aligned */ -#define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3) \ - EX(lw, t0, (offset + 0x00)(src), l_fixup); \ - EX(lw, t1, (offset + 0x04)(src), l_fixup); \ - EX(lw, t2, (offset + 0x08)(src), l_fixup); \ - EX(lw, t3, (offset + 0x0c)(src), l_fixup); \ - EX(sw, t0, (offset + 0x00)(dst), s_fixup); \ - EX(sw, t1, (offset + 0x04)(dst), s_fixup); \ - EX(sw, t2, (offset + 0x08)(dst), s_fixup); \ - EX(sw, t3, (offset + 0x0c)(dst), s_fixup); \ - EX(lw, t0, (offset + 0x10)(src), l_fixup); \ - EX(lw, t1, (offset + 0x14)(src), l_fixup); \ - EX(lw, t2, (offset + 0x18)(src), l_fixup); \ - EX(lw, t3, (offset + 0x1c)(src), l_fixup); \ - EX(sw, t0, (offset + 0x10)(dst), s_fixup); \ - EX(sw, t1, (offset + 0x14)(dst), s_fixup); \ - EX(sw, t2, (offset + 0x18)(dst), s_fixup); \ - EX(sw, t3, (offset + 0x1c)(dst), s_fixup) - -/* ascending order, destination unaligned */ -#define UMOVE_BIGGERCHUNK(src, dst, offset, t0, t1, t2, t3) \ - EX(ld, t0, (offset + 0x00)(src), l_fixup); \ - EX(ld, t1, (offset + 0x08)(src), l_fixup); \ - EX(ld, t2, (offset + 0x10)(src), l_fixup); \ - EX(ld, t3, (offset + 0x18)(src), l_fixup); \ - UEXD(usd, t0, (offset + 0x00)(dst), s_fixup); \ - UEXD(usd, t1, (offset + 0x08)(dst), s_fixup); \ - UEXD(usd, t2, (offset + 0x10)(dst), s_fixup); \ - UEXD(usd, t3, (offset + 0x18)(dst), s_fixup); \ - EX(ld, t0, (offset + 0x20)(src), l_fixup); \ - EX(ld, t1, (offset + 0x28)(src), l_fixup); \ - EX(ld, t2, (offset + 0x30)(src), l_fixup); \ - EX(ld, t3, (offset + 0x38)(src), l_fixup); \ - UEXD(usd, t0, (offset + 0x20)(dst), s_fixup); \ - UEXD(usd, t1, (offset + 0x28)(dst), s_fixup); \ - UEXD(usd, t2, (offset + 0x30)(dst), s_fixup); \ - UEXD(usd, t3, (offset + 0x38)(dst), s_fixup) - -/* ascending order, destination unaligned */ -#define UMOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3) \ - EX(lw, t0, (offset + 0x00)(src), l_fixup); \ - EX(lw, t1, (offset + 0x04)(src), l_fixup); \ - EX(lw, t2, (offset + 0x08)(src), l_fixup); \ - EX(lw, t3, (offset + 0x0c)(src), l_fixup); \ - UEX(usw, t0, (offset + 0x00)(dst), s_fixup); \ - UEX(usw, t1, (offset + 0x04)(dst), s_fixup); \ - UEX(usw, t2, (offset + 0x08)(dst), s_fixup); \ - UEX(usw, t3, (offset + 0x0c)(dst), s_fixup); \ - EX(lw, t0, (offset + 0x10)(src), l_fixup); \ - EX(lw, t1, (offset + 0x14)(src), l_fixup); \ - EX(lw, t2, (offset + 0x18)(src), l_fixup); \ - EX(lw, t3, (offset + 0x1c)(src), l_fixup); \ - UEX(usw, t0, (offset + 0x10)(dst), s_fixup); \ - UEX(usw, t1, (offset + 0x14)(dst), s_fixup); \ - UEX(usw, t2, (offset + 0x18)(dst), s_fixup); \ - UEX(usw, t3, (offset + 0x1c)(dst), s_fixup) +/* + * Only on the 64-bit kernel we can made use of 64-bit registers. + */ +#ifdef CONFIG_MIPS64 +#define USE_DOUBLE +#endif + +#ifdef USE_DOUBLE + +#define LOAD ld +#define LOADL ldl +#define LOADR ldr +#define STOREL sdl +#define STORER sdr +#define STORE sd +#define ADD daddu +#define SUB dsubu +#define SRL dsrl +#define SRA dsra +#define SLL dsll +#define SLLV dsllv +#define SRLV dsrlv +#define NBYTES 8 +#define LOG_NBYTES 3 + +/* + * As we are sharing code base with the mips32 tree (which use the o32 ABI + * register definitions). We need to redefine the register definitions from + * the n64 ABI register naming to the o32 ABI register naming. + */ +#undef t0 +#undef t1 +#undef t2 +#undef t3 +#define t0 $8 +#define t1 $9 +#define t2 $10 +#define t3 $11 +#define t4 $12 +#define t5 $13 +#define t6 $14 +#define t7 $15 + +#else + +#define LOAD lw +#define LOADL lwl +#define LOADR lwr +#define STOREL swl +#define STORER swr +#define STORE sw +#define ADD addu +#define SUB subu +#define SRL srl +#define SLL sll +#define SRA sra +#define SLLV sllv +#define SRLV srlv +#define NBYTES 4 +#define LOG_NBYTES 2 + +#endif /* USE_DOUBLE */ + +#ifdef CONFIG_CPU_LITTLE_ENDIAN +#define LDFIRST LOADR +#define LDREST LOADL +#define STFIRST STORER +#define STREST STOREL +#define SHIFT_DISCARD SLLV +#else +#define LDFIRST LOADL +#define LDREST LOADR +#define STFIRST STOREL +#define STREST STORER +#define SHIFT_DISCARD SRLV +#endif + +#define FIRST(unit) ((unit)*NBYTES) +#define REST(unit) (FIRST(unit)+NBYTES-1) +#define UNIT(unit) FIRST(unit) + +#define ADDRMASK (NBYTES-1) .text .set noreorder .set noat +/* + * A combined memcpy/__copy_user + * __copy_user sets len to 0 for success; else to an upper bound of + * the number of uncopied bytes. + * memcpy sets v0 to dst. + */ .align 5 LEAF(memcpy) /* a0=dst a1=src a2=len */ - move v0, a0 /* return value */ + move v0, dst /* return value */ __memcpy: FEXPORT(__copy_user) - xor ta0, a0, a1 - andi ta0, ta0, 0x7 - move t3, a0 - beqz ta0, can_align - sltiu t8, a2, 0x8 - - b memcpy_u_src # bad alignment - move ta2, a2 - -can_align: - bnez t8, small_memcpy # < 8 bytes to copy - move ta2, a2 - - beqz a2, out - andi t8, a1, 0x1 - -hword_align: - beqz t8, word_align - andi t8, a1, 0x2 - - EX(lb, ta0, (a1), l_fixup) - dsubu a2, a2, 0x1 - EX(sb, ta0, (a0), s_fixup) - daddu a1, a1, 0x1 - daddu a0, a0, 0x1 - andi t8, a1, 0x2 - -word_align: - beqz t8, dword_align - sltiu t8, a2, 56 - - EX(lh, ta0, (a1), l_fixup) - dsubu a2, a2, 0x2 - EX(sh, ta0, (a0), s_fixup) - sltiu t8, a2, 56 - daddu a0, a0, 0x2 - daddu a1, a1, 0x2 - -dword_align: - bnez t8, do_end_words - move t8, a2 - - andi t8, a1, 0x4 - beqz t8, qword_align - andi t8, a1, 0x8 - - EX(lw, ta0, 0x00(a1), l_fixup) - dsubu a2, a2, 0x4 - EX(sw, ta0, 0x00(a0), s_fixup) - daddu a1, a1, 0x4 - daddu a0, a0, 0x4 - andi t8, a1, 0x8 - -qword_align: - beqz t8, oword_align - andi t8, a1, 0x10 - - EX(lw, ta0, 0x00(a1), l_fixup) - EX(lw, ta1, 0x04(a1), l_fixup) - dsubu a2, a2, 0x8 - EX(sw, ta0, 0x00(a0), s_fixup) - EX(sw, ta1, 0x04(a0), s_fixup) - daddu a1, a1, 0x8 - andi t8, a1, 0x10 - daddu a0, a0, 0x8 - -oword_align: - beqz t8, begin_movement - srl t8, a2, 0x7 - - EX(lw, ta3, 0x00(a1), l_fixup) - EX(lw, t0, 0x04(a1), l_fixup) - EX(lw, ta0, 0x08(a1), l_fixup) - EX(lw, ta1, 0x0c(a1), l_fixup) - EX(sw, ta3, 0x00(a0), s_fixup) - EX(sw, t0, 0x04(a0), s_fixup) - EX(sw, ta0, 0x08(a0), s_fixup) - EX(sw, ta1, 0x0c(a0), s_fixup) - dsubu a2, a2, 0x10 - daddu a1, a1, 0x10 - srl t8, a2, 0x7 - daddu a0, a0, 0x10 - -begin_movement: - beqz t8, 0f - andi ta2, a2, 0x40 - -move_128bytes: - PREF (0, 2*128(a0)) - PREF (1, 2*128(a1)) - MOVE_BIGGERCHUNK(a1, a0, 0x00, ta0, ta1, ta3, t0) - MOVE_BIGGERCHUNK(a1, a0, 0x40, ta0, ta1, ta3, t0) - dsubu t8, t8, 0x01 - daddu a1, a1, 0x80 - bnez t8, move_128bytes - daddu a0, a0, 0x80 - -0: - beqz ta2, 1f - andi ta2, a2, 0x20 - -move_64bytes: - MOVE_BIGGERCHUNK(a1, a0, 0x00, ta0, ta1, ta3, t0) - daddu a1, a1, 0x40 - daddu a0, a0, 0x40 - + /* + * Note: dst & src may be unaligned, len may be 0 + * Temps + */ +#define rem t8 + + /* + * The "issue break"s below are very approximate. + * Issue delays for dcache fills will perturb the schedule, as will + * load queue full replay traps, etc. + * + * If len < NBYTES use byte operations. + */ + PREF( 0, 0(src) ) + PREF( 1, 0(dst) ) + sltu t2, len, NBYTES + and t1, dst, ADDRMASK + PREF( 0, 1*32(src) ) + PREF( 1, 1*32(dst) ) + bnez t2, copy_bytes_checklen + and t0, src, ADDRMASK + PREF( 0, 2*32(src) ) + PREF( 1, 2*32(dst) ) + bnez t1, dst_unaligned + nop + bnez t0, src_unaligned_dst_aligned + /* + * use delay slot for fall-through + * src and dst are aligned; need to compute rem + */ +both_aligned: + SRL t0, len, LOG_NBYTES+3 # +3 for 8 units/iter + beqz t0, cleanup_both_aligned # len < 8*NBYTES + and rem, len, (8*NBYTES-1) # rem = len % (8*NBYTES) + PREF( 0, 3*32(src) ) + PREF( 1, 3*32(dst) ) + .align 4 1: - beqz ta2, do_end_words - andi t8, a2, 0x1c - -move_32bytes: - MOVE_BIGCHUNK(a1, a0, 0x00, ta0, ta1, ta3, t0) - andi t8, a2, 0x1c - daddu a1, a1, 0x20 - daddu a0, a0, 0x20 - -do_end_words: - beqz t8, maybe_end_cruft - srl t8, t8, 0x2 - -end_words: - EX(lw, ta0, (a1), l_fixup) - dsubu t8, t8, 0x1 - EX(sw, ta0, (a0), s_fixup) - daddu a1, a1, 0x4 - bnez t8, end_words - daddu a0, a0, 0x4 - -maybe_end_cruft: - andi ta2, a2, 0x3 - -small_memcpy: - beqz ta2, out - move a2, ta2 - -end_bytes: - EX(lb, ta0, (a1), l_fixup) - dsubu a2, a2, 0x1 - EX(sb, ta0, (a0), s_fixup) - daddu a1, a1, 0x1 - bnez a2, end_bytes - daddu a0, a0, 0x1 - -out: jr ra - move a2, zero - -/* ------------------------------------------------------------------------- */ +EXC( LOAD t0, UNIT(0)(src), l_exc) +EXC( LOAD t1, UNIT(1)(src), l_exc_copy) +EXC( LOAD t2, UNIT(2)(src), l_exc_copy) +EXC( LOAD t3, UNIT(3)(src), l_exc_copy) + SUB len, len, 8*NBYTES +EXC( LOAD t4, UNIT(4)(src), l_exc_copy) +EXC( LOAD t7, UNIT(5)(src), l_exc_copy) +EXC( STORE t0, UNIT(0)(dst), s_exc_p8u) +EXC( STORE t1, UNIT(1)(dst), s_exc_p7u) +EXC( LOAD t0, UNIT(6)(src), l_exc_copy) +EXC( LOAD t1, UNIT(7)(src), l_exc_copy) + ADD src, src, 8*NBYTES + ADD dst, dst, 8*NBYTES +EXC( STORE t2, UNIT(-6)(dst), s_exc_p6u) +EXC( STORE t3, UNIT(-5)(dst), s_exc_p5u) +EXC( STORE t4, UNIT(-4)(dst), s_exc_p4u) +EXC( STORE t7, UNIT(-3)(dst), s_exc_p3u) +EXC( STORE t0, UNIT(-2)(dst), s_exc_p2u) +EXC( STORE t1, UNIT(-1)(dst), s_exc_p1u) + PREF( 0, 8*32(src) ) + PREF( 1, 8*32(dst) ) + bne len, rem, 1b + nop -/* Bad, bad. At least try to align the source */ + /* + * len == rem == the number of bytes left to copy < 8*NBYTES + */ +cleanup_both_aligned: + beqz len, done + sltu t0, len, 4*NBYTES + bnez t0, less_than_4units + and rem, len, (NBYTES-1) # rem = len % NBYTES + /* + * len >= 4*NBYTES + */ +EXC( LOAD t0, UNIT(0)(src), l_exc) +EXC( LOAD t1, UNIT(1)(src), l_exc_copy) +EXC( LOAD t2, UNIT(2)(src), l_exc_copy) +EXC( LOAD t3, UNIT(3)(src), l_exc_copy) + SUB len, len, 4*NBYTES + ADD src, src, 4*NBYTES +EXC( STORE t0, UNIT(0)(dst), s_exc_p4u) +EXC( STORE t1, UNIT(1)(dst), s_exc_p3u) +EXC( STORE t2, UNIT(2)(dst), s_exc_p2u) +EXC( STORE t3, UNIT(3)(dst), s_exc_p1u) + beqz len, done + ADD dst, dst, 4*NBYTES +less_than_4units: + /* + * rem = len % NBYTES + */ + beq rem, len, copy_bytes + nop +1: +EXC( LOAD t0, 0(src), l_exc) + ADD src, src, NBYTES + SUB len, len, NBYTES +EXC( STORE t0, 0(dst), s_exc_p1u) + bne rem, len, 1b + ADD dst, dst, NBYTES + + /* + * src and dst are aligned, need to copy rem bytes (rem < NBYTES) + * A loop would do only a byte at a time with possible branch + * mispredicts. Can't do an explicit LOAD dst,mask,or,STORE + * because can't assume read-access to dst. Instead, use + * STREST dst, which doesn't require read access to dst. + * + * This code should perform better than a simple loop on modern, + * wide-issue mips processors because the code has fewer branches and + * more instruction-level parallelism. + */ +#define bits t2 + beqz len, done + ADD t1, dst, len # t1 is just past last byte of dst + li bits, 8*NBYTES + SLL rem, len, 3 # rem = number of bits to keep +EXC( LOAD t0, 0(src), l_exc) + SUB bits, bits, rem # bits = number of bits to discard + SHIFT_DISCARD t0, t0, bits +EXC( STREST t0, -1(t1), s_exc) + jr ra + move len, zero +dst_unaligned: + /* + * dst is unaligned + * t0 = src & ADDRMASK + * t1 = dst & ADDRMASK; T1 > 0 + * len >= NBYTES + * + * Copy enough bytes to align dst + * Set match = (src and dst have same alignment) + */ +#define match rem +EXC( LDFIRST t3, FIRST(0)(src), l_exc) + ADD t2, zero, NBYTES +EXC( LDREST t3, REST(0)(src), l_exc_copy) + SUB t2, t2, t1 # t2 = number of bytes copied + xor match, t0, t1 +EXC( STFIRST t3, FIRST(0)(dst), s_exc) + beq len, t2, done + SUB len, len, t2 + ADD dst, dst, t2 + beqz match, both_aligned + ADD src, src, t2 + +src_unaligned_dst_aligned: + SRL t0, len, LOG_NBYTES+2 # +2 for 4 units/iter + PREF( 0, 3*32(src) ) + beqz t0, cleanup_src_unaligned + and rem, len, (4*NBYTES-1) # rem = len % 4*NBYTES + PREF( 1, 3*32(dst) ) +1: +/* + * Avoid consecutive LD*'s to the same register since some mips + * implementations can't issue them in the same cycle. + * It's OK to load FIRST(N+1) before REST(N) because the two addresses + * are to the same unit (unless src is aligned, but it's not). + */ +EXC( LDFIRST t0, FIRST(0)(src), l_exc) +EXC( LDFIRST t1, FIRST(1)(src), l_exc_copy) + SUB len, len, 4*NBYTES +EXC( LDREST t0, REST(0)(src), l_exc_copy) +EXC( LDREST t1, REST(1)(src), l_exc_copy) +EXC( LDFIRST t2, FIRST(2)(src), l_exc_copy) +EXC( LDFIRST t3, FIRST(3)(src), l_exc_copy) +EXC( LDREST t2, REST(2)(src), l_exc_copy) +EXC( LDREST t3, REST(3)(src), l_exc_copy) + PREF( 0, 9*32(src) ) # 0 is PREF_LOAD (not streamed) + ADD src, src, 4*NBYTES +#ifdef CONFIG_CPU_SB1 + nop # improves slotting +#endif +EXC( STORE t0, UNIT(0)(dst), s_exc_p4u) +EXC( STORE t1, UNIT(1)(dst), s_exc_p3u) +EXC( STORE t2, UNIT(2)(dst), s_exc_p2u) +EXC( STORE t3, UNIT(3)(dst), s_exc_p1u) + PREF( 1, 9*32(dst) ) # 1 is PREF_STORE (not streamed) + bne len, rem, 1b + ADD dst, dst, 4*NBYTES + +cleanup_src_unaligned: + beqz len, done + and rem, len, NBYTES-1 # rem = len % NBYTES + beq rem, len, copy_bytes + nop +1: +EXC( LDFIRST t0, FIRST(0)(src), l_exc) +EXC( LDREST t0, REST(0)(src), l_exc_copy) + ADD src, src, NBYTES + SUB len, len, NBYTES +EXC( STORE t0, 0(dst), s_exc_p1u) + bne len, rem, 1b + ADD dst, dst, NBYTES -memcpy_u_src: - bnez t8, small_memcpy # < 8 bytes? - move ta2, a2 - - daddiu ta0, a1, 7 # ta0: how much to align - ori ta0, 7 - xori ta0, 7 - dsubu ta0, a1 - - UEXD(uld, ta1, 0(a1), l_fixup) # dword alignment - UEXD(usd, ta1, 0(a0), s_fixup) - - daddu a1, ta0 # src - daddu a0, ta0 # dst - dsubu a2, ta0 # len - - sltiu t8, a2, 56 - bnez t8, u_do_end_words - andi t8, a2, 0x3c - - andi t8, a1, 8 # now qword aligned? - -u_qword_align: - beqz t8, u_oword_align - andi t8, a1, 0x10 - - EX(ld, ta0, 0x00(a1), l_fixup) - dsubu a2, a2, 0x8 - UEXD(usd, ta0, 0x00(a0), s_fixup) - daddu a1, a1, 0x8 - andi t8, a1, 0x10 - daddu a0, a0, 0x8 - -u_oword_align: - beqz t8, u_begin_movement - srl t8, a2, 0x7 - - EX(lw, ta3, 0x08(a1), l_fixup) - EX(lw, t0, 0x0c(a1), l_fixup) - EX(lw, ta0, 0x00(a1), l_fixup) - EX(lw, ta1, 0x04(a1), l_fixup) - UEX(usw, ta3, 0x08(a0), s_fixup) - UEX(usw, t0, 0x0c(a0), s_fixup) - UEX(usw, ta0, 0x00(a0), s_fixup) - UEX(usw, ta1, 0x04(a0), s_fixup) - dsubu a2, a2, 0x10 - daddu a1, a1, 0x10 - srl t8, a2, 0x7 - daddu a0, a0, 0x10 - -u_begin_movement: - beqz t8, 0f - andi ta2, a2, 0x40 - -u_move_128bytes: - UMOVE_BIGGERCHUNK(a1, a0, 0x00, ta0, ta1, ta3, t0) - UMOVE_BIGGERCHUNK(a1, a0, 0x40, ta0, ta1, ta3, t0) - dsubu t8, t8, 0x01 - daddu a1, a1, 0x80 - bnez t8, u_move_128bytes - daddu a0, a0, 0x80 - -0: - beqz ta2, 1f - andi ta2, a2, 0x20 - -u_move_64bytes: - UMOVE_BIGGERCHUNK(a1, a0, 0x00, ta0, ta1, ta3, t0) - daddu a1, a1, 0x40 - daddu a0, a0, 0x40 +copy_bytes_checklen: + beqz len, done + nop +copy_bytes: + /* 0 < len < NBYTES */ +#define COPY_BYTE(N) \ +EXC( lb t0, N(src), l_exc); \ + SUB len, len, 1; \ + beqz len, done; \ +EXC( sb t0, N(dst), s_exc_p1) + + COPY_BYTE(0) + COPY_BYTE(1) +#ifdef USE_DOUBLE + COPY_BYTE(2) + COPY_BYTE(3) + COPY_BYTE(4) + COPY_BYTE(5) +#endif +EXC( lb t0, NBYTES-2(src), l_exc) + SUB len, len, 1 + jr ra +EXC( sb t0, NBYTES-2(dst), s_exc_p1) +done: + jr ra + nop + END(memcpy) +l_exc_copy: + /* + * Copy bytes from src until faulting load address (or until a + * lb faults) + * + * When reached by a faulting LDFIRST/LDREST, THREAD_BUADDR($28) + * may be more than a byte beyond the last address. + * Hence, the lb below may get an exception. + * + * Assumes src < THREAD_BUADDR($28) + */ + LOAD t0, TI_TASK($28) + LOAD t0, THREAD_BUADDR(t0) 1: - beqz ta2, u_do_end_words - andi t8, a2, 0x1c +EXC( lb t1, 0(src), l_exc) + ADD src, src, 1 + sb t1, 0(dst) # can't fault -- we're copy_from_user + bne src, t0, 1b + ADD dst, dst, 1 +l_exc: + LOAD t0, THREAD_BUADDR($28) # t0 is just past last good address + LOAD t0, THREAD_BUADDR(t0) + nop + SUB len, AT, t0 # len number of uncopied bytes + /* + * Here's where we rely on src and dst being incremented in tandem, + * See (3) above. + * dst += (fault addr - src) to put dst at first byte to clear + */ + ADD dst, t0 # compute start address in a1 + SUB dst, src + /* + * Clear len bytes starting at dst. Can't call __bzero because it + * might modify len. An inefficient loop for these rare times... + */ + beqz len, done + SUB src, len, 1 +1: sb zero, 0(dst) + ADD dst, dst, 1 + bnez src, 1b + SUB src, src, 1 + jr ra + nop -u_move_32bytes: - UMOVE_BIGCHUNK(a1, a0, 0x00, ta0, ta1, ta3, t0) - andi t8, a2, 0x1c - daddu a1, a1, 0x20 - daddu a0, a0, 0x20 - -u_do_end_words: - beqz t8, u_maybe_end_cruft - srl t8, t8, 0x2 - -u_end_words: - EX(lw, ta0, 0x00(a1), l_fixup) - dsubu t8, t8, 0x1 - UEX(usw, ta0, 0x00(a0), s_fixup) - daddu a1, a1, 0x4 - bnez t8, u_end_words - daddu a0, a0, 0x4 - -u_maybe_end_cruft: - andi ta2, a2, 0x3 - -u_cannot_optimize: - beqz ta2, out - move a2, ta2 - -u_end_bytes: - EX(lb, ta0, (a1), l_fixup) - dsubu a2, a2, 0x1 - EX(sb, ta0, (a0), s_fixup) - daddu a1, a1, 0x1 - bnez a2, u_end_bytes - daddu a0, a0, 0x1 - jr ra - move a2, zero - END(memcpy) +#define SEXC(n) \ +s_exc_p ## n ## u: \ + jr ra; \ + ADD len, len, n*NBYTES + +SEXC(8) +SEXC(7) +SEXC(6) +SEXC(5) +SEXC(4) +SEXC(3) +SEXC(2) +SEXC(1) -/* descending order, destination aligned */ -#define RMOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3) \ - lw t0, (offset + 0x10)(src); \ - lw t1, (offset + 0x14)(src); \ - lw t2, (offset + 0x18)(src); \ - lw t3, (offset + 0x1c)(src); \ - sw t0, (offset + 0x10)(dst); \ - sw t1, (offset + 0x14)(dst); \ - sw t2, (offset + 0x18)(dst); \ - sw t3, (offset + 0x1c)(dst); \ - lw t0, (offset + 0x00)(src); \ - lw t1, (offset + 0x04)(src); \ - lw t2, (offset + 0x08)(src); \ - lw t3, (offset + 0x0c)(src); \ - sw t0, (offset + 0x00)(dst); \ - sw t1, (offset + 0x04)(dst); \ - sw t2, (offset + 0x08)(dst); \ - sw t3, (offset + 0x0c)(dst) - -/* descending order, destination ununaligned */ -#define RUMOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3) \ - lw t0, (offset + 0x10)(src); \ - lw t1, (offset + 0x14)(src); \ - lw t2, (offset + 0x18)(src); \ - lw t3, (offset + 0x1c)(src); \ - usw t0, (offset + 0x10)(dst); \ - usw t1, (offset + 0x14)(dst); \ - usw t2, (offset + 0x18)(dst); \ - usw t3, (offset + 0x1c)(dst); \ - lw t0, (offset + 0x00)(src); \ - lw t1, (offset + 0x04)(src); \ - lw t2, (offset + 0x08)(src); \ - lw t3, (offset + 0x0c)(src); \ - usw t0, (offset + 0x00)(dst); \ - usw t1, (offset + 0x04)(dst); \ - usw t2, (offset + 0x08)(dst); \ - usw t3, (offset + 0x0c)(dst) +s_exc_p1: + jr ra + ADD len, len, 1 +s_exc: + jr ra + nop .align 5 LEAF(memmove) - daddu t0, a0, a2 + ADD t0, a0, a2 + ADD t1, a1, a2 sltu t0, a1, t0 # dst + len <= src -> memcpy - daddu t1, a1, a2 sltu t1, a0, t1 # dst >= src + len -> memcpy and t0, t1 beqz t0, __memcpy - move v0, a0 /* return value */ beqz a2, r_out END(memmove) + /* fall through to __rmemcpy */ LEAF(__rmemcpy) /* a0=dst a1=src a2=len */ - sltu t0, a1, a0 + sltu t0, a1, a0 beqz t0, r_end_bytes_up # src >= dst nop - daddu a0, a2 # dst = dst + len - daddu a1, a2 # src = src + len - -#if 0 /* Horror fix */ - xor ta0, a0, a1 - andi ta0, ta0, 0x3 - move t3, a0 - beqz ta0, r_can_align - sltiu t8, a2, 0x8 - - b r_memcpy_u_src # bad alignment - move ta2, a2 - -r_can_align: - bnez t8, r_small_memcpy # < 8 bytes to copy - move ta2, a2 - - beqz a2, r_out - andi t8, a1, 0x1 - -r_hword_align: - beqz t8, r_word_align - andi t8, a1, 0x2 - - lb ta0, -1(a1) - dsubu a2, a2, 0x1 - sb ta0, -1(a0) - dsubu a1, a1, 0x1 - dsubu a0, a0, 0x1 - andi t8, a1, 0x2 - -r_word_align: - beqz t8, r_dword_align - sltiu t8, a2, 56 - - lh ta0, -2(a1) - dsubu a2, a2, 0x2 - sh ta0, -2(a0) - sltiu t8, a2, 56 - dsubu a0, a0, 0x2 - dsubu a1, a1, 0x2 - -r_dword_align: - bnez t8, r_do_end_words - move t8, a2 - - andi t8, a1, 0x4 - beqz t8, r_qword_align - andi t8, a1, 0x8 - - lw ta0, -4(a1) - dsubu a2, a2, 0x4 - sw ta0, -4(a0) - dsubu a1, a1, 0x4 - dsubu a0, a0, 0x4 - andi t8, a1, 0x8 - -r_qword_align: - beqz t8, r_oword_align - andi t8, a1, 0x10 - - dsubu a1, a1, 0x8 - lw ta0, 0x04(a1) - lw ta1, 0x00(a1) - dsubu a0, a0, 0x8 - sw ta0, 0x04(a0) - sw ta1, 0x00(a0) - dsubu a2, a2, 0x8 - - andi t8, a1, 0x10 - -r_oword_align: - beqz t8, r_begin_movement - srl t8, a2, 0x7 - - dsubu a1, a1, 0x10 - lw ta3, 0x08(a1) # assumes subblock ordering - lw t0, 0x0c(a1) - lw ta0, 0x00(a1) - lw ta1, 0x04(a1) - dsubu a0, a0, 0x10 - sw ta3, 0x08(a0) - sw t0, 0x0c(a0) - sw ta0, 0x00(a0) - sw ta1, 0x04(a0) - dsubu a2, a2, 0x10 - srl t8, a2, 0x7 - -r_begin_movement: - beqz t8, 0f - andi ta2, a2, 0x40 - -r_move_128bytes: - RMOVE_BIGCHUNK(a1, a0, -0x80, ta0, ta1, ta3, t0) - RMOVE_BIGCHUNK(a1, a0, -0x60, ta0, ta1, ta3, t0) - RMOVE_BIGCHUNK(a1, a0, -0x40, ta0, ta1, ta3, t0) - RMOVE_BIGCHUNK(a1, a0, -0x20, ta0, ta1, ta3, t0) - dsubu t8, t8, 0x01 - dsubu a1, a1, 0x80 - bnez t8, r_move_128bytes - dsubu a0, a0, 0x80 - -0: - beqz ta2, 1f - andi ta2, a2, 0x20 - -r_move_64bytes: - dsubu a1, a1, 0x40 - dsubu a0, a0, 0x40 - RMOVE_BIGCHUNK(a1, a0, 0x20, ta0, ta1, ta3, t0) - RMOVE_BIGCHUNK(a1, a0, 0x00, ta0, ta1, ta3, t0) - -1: - beqz ta2, r_do_end_words - andi t8, a2, 0x1c - -r_move_32bytes: - dsubu a1, a1, 0x20 - dsubu a0, a0, 0x20 - RMOVE_BIGCHUNK(a1, a0, 0x00, ta0, ta1, ta3, t0) - andi t8, a2, 0x1c - -r_do_end_words: - beqz t8, r_maybe_end_cruft - srl t8, t8, 0x2 - -r_end_words: - lw ta0, -4(a1) - dsubu t8, t8, 0x1 - sw ta0, -4(a0) - dsubu a1, a1, 0x4 - bnez t8, r_end_words - dsubu a0, a0, 0x4 - -r_maybe_end_cruft: - andi ta2, a2, 0x3 - -r_small_memcpy: - beqz ta2, r_out - move a2, ta2 -#endif /* Horror fix */ + ADD a0, a2 # dst = dst + len + ADD a1, a2 # src = src + len r_end_bytes: - lb ta0, -1(a1) - dsubu a2, a2, 0x1 - sb ta0, -1(a0) - dsubu a1, a1, 0x1 + lb t0, -1(a1) + SUB a2, a2, 0x1 + sb t0, -1(a0) + SUB a1, a1, 0x1 bnez a2, r_end_bytes - dsubu a0, a0, 0x1 + SUB a0, a0, 0x1 r_out: - jr ra - move a2, zero + jr ra + move a2, zero r_end_bytes_up: lb t0, (a1) - dsubu a2, a2, 0x1 + SUB a2, a2, 0x1 sb t0, (a0) - daddu a1, a1, 0x1 + ADD a1, a1, 0x1 bnez a2, r_end_bytes_up - daddu a0, a0, 0x1 + ADD a0, a0, 0x1 jr ra move a2, zero - -#if 0 /* Horror fix */ -/* ------------------------------------------------------------------------- */ - -/* Bad, bad. At least try to align the source */ - -r_memcpy_u_src: - bnez t8, r_small_memcpy # < 8 bytes? - move ta2, a2 - - andi ta0, a1, 7 # ta0: how much to align - - ulw ta1, -8(a1) # dword alignment - ulw ta2, -4(a1) - usw ta1, -8(a0) - usw ta2, -4(a0) - - dsubu a1, ta0 # src - dsubu a0, ta0 # dst - dsubu a2, ta0 # len - - sltiu t8, a2, 56 - bnez t8, ru_do_end_words - andi t8, a2, 0x3c - - andi t8, a1, 8 # now qword aligned? - -ru_qword_align: - beqz t8, ru_oword_align - andi t8, a1, 0x10 - - dsubu a1, a1, 0x8 - lw ta0, 0x00(a1) - lw ta1, 0x04(a1) - dsubu a0, a0, 0x8 - usw ta0, 0x00(a0) - usw ta1, 0x04(a0) - dsubu a2, a2, 0x8 - - andi t8, a1, 0x10 - -ru_oword_align: - beqz t8, ru_begin_movement - srl t8, a2, 0x7 - - dsubu a1, a1, 0x10 - lw ta3, 0x08(a1) # assumes subblock ordering - lw t0, 0x0c(a1) - lw ta0, 0x00(a1) - lw ta1, 0x04(a1) - dsubu a0, a0, 0x10 - usw ta3, 0x08(a0) - usw t0, 0x0c(a0) - usw ta0, 0x00(a0) - usw ta1, 0x04(a0) - dsubu a2, a2, 0x10 - - srl t8, a2, 0x7 - -ru_begin_movement: - beqz t8, 0f - andi ta2, a2, 0x40 - -ru_move_128bytes: - RUMOVE_BIGCHUNK(a1, a0, -0x80, ta0, ta1, ta3, t0) - RUMOVE_BIGCHUNK(a1, a0, -0x60, ta0, ta1, ta3, t0) - RUMOVE_BIGCHUNK(a1, a0, -0x40, ta0, ta1, ta3, t0) - RUMOVE_BIGCHUNK(a1, a0, -0x20, ta0, ta1, ta3, t0) - dsubu t8, t8, 0x01 - dsubu a1, a1, 0x80 - bnez t8, ru_move_128bytes - dsubu a0, a0, 0x80 - -0: - beqz ta2, 1f - andi ta2, a2, 0x20 - -ru_move_64bytes: - dsubu a1, a1, 0x40 - dsubu a0, a0, 0x40 - RUMOVE_BIGCHUNK(a1, a0, 0x20, ta0, ta1, ta3, t0) - RUMOVE_BIGCHUNK(a1, a0, 0x00, ta0, ta1, ta3, t0) - -1: - beqz ta2, ru_do_end_words - andi t8, a2, 0x1c - -ru_move_32bytes: - dsubu a1, a1, 0x20 - dsubu a0, a0, 0x20 - RUMOVE_BIGCHUNK(a1, a0, 0x00, ta0, ta1, ta3, t0) - andi t8, a2, 0x1c - -ru_do_end_words: - beqz t8, ru_maybe_end_cruft - srl t8, t8, 0x2 - -ru_end_words: - lw ta0, -4(a1) - usw ta0, -4(a0) - dsubu t8, t8, 0x1 - dsubu a1, a1, 0x4 - bnez t8, ru_end_words - dsubu a0, a0, 0x4 - -ru_maybe_end_cruft: - andi ta2, a2, 0x3 - -ru_cannot_optimize: - beqz ta2, r_out - move a2, ta2 - -ru_end_bytes: - lb ta0, -1(a1) - dsubu a2, a2, 0x1 - sb ta0, -1(a0) - dsubu a1, a1, 0x1 - bnez a2, ru_end_bytes - dsubu a0, a0, 0x1 - - jr ra - move a2, zero -#endif /* Horror fix */ END(__rmemcpy) - -l_fixup: # clear the rest of the buffer - ld ta0, THREAD_BUADDR($28) - nop - dsubu a2, AT, ta0 # a2 bytes to go - daddu a0, ta0 # compute start address in a1 - dsubu a0, a1 - j __bzero - move a1, zero - -s_fixup: - jr ra - nop diff -Nru a/arch/mips64/lib/memset.S b/arch/mips64/lib/memset.S --- a/arch/mips64/lib/memset.S Tue Jul 1 18:44:36 2003 +++ b/arch/mips64/lib/memset.S Tue Jul 1 18:44:36 2003 @@ -52,7 +52,6 @@ 1: FEXPORT(__bzero) - .type __bzero, @function sltiu t0, a2, 8 /* very small region? */ bnez t0, small_memset andi t0, a0, 7 /* aligned? */ @@ -82,7 +81,7 @@ .set noreorder memset_partial: - la t1, 2f /* where to start */ + PTR_LA t1, 2f /* where to start */ .set noat dsrl AT, t0, 1 dsubu t1, AT @@ -90,8 +89,12 @@ jr t1 daddu a0, t0 /* dest ptr */ + .set push + .set noreorder + .set nomacro F_FILL64(a0, -64, a1, partial_fixup) /* ... but first do dwds ... */ -2: andi a2, 7 /* 0 <= n <= 7 to go */ +2: .set pop + andi a2, 7 /* 0 <= n <= 7 to go */ beqz a2, 1f daddu a0, a2 /* What's left */ @@ -121,14 +124,16 @@ nop fwd_fixup: - ld t0, THREAD_BUADDR($28) + ld t2, TI_TASK($28) + ld t0, THREAD_BUADDR(t2) andi a2, 0x3f daddu a2, t1 jr ra dsubu a2, t0 partial_fixup: - ld t0, THREAD_BUADDR($28) + ld t2, TI_TASK($28) + ld t0, THREAD_BUADDR(t2) andi a2, 7 daddu a2, t1 jr ra diff -Nru a/arch/mips64/lib/promlib.c b/arch/mips64/lib/promlib.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips64/lib/promlib.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,24 @@ +#include +#include + +extern void prom_putchar(char); + +void prom_printf(char *fmt, ...) +{ + va_list args; + char ppbuf[1024]; + char *bptr; + + va_start(args, fmt); + vsprintf(ppbuf, fmt, args); + + bptr = ppbuf; + + while (*bptr != 0) { + if (*bptr == '\n') + prom_putchar('\r'); + + prom_putchar(*bptr++); + } + va_end(args); +} diff -Nru a/arch/mips64/lib/strlen_user.S b/arch/mips64/lib/strlen_user.S --- a/arch/mips64/lib/strlen_user.S Tue Jul 1 18:44:34 2003 +++ b/arch/mips64/lib/strlen_user.S Tue Jul 1 18:44:34 2003 @@ -23,9 +23,9 @@ * Return 0 for error */ LEAF(__strlen_user_asm) - ld v0, THREAD_CURDS($28) # pointer ok? + ld v0, TI_ADDR_LIMIT($28) # pointer ok? and v0, a0 - bltz v0, fault + bnez v0, fault FEXPORT(__strlen_user_nocheck_asm) move v0, a0 @@ -35,10 +35,6 @@ dsubu v0, a0 jr ra END(__strlen_user_asm) - - .section __ex_table,"a" - PTR 1b, fault - .previous fault: move v0, zero jr ra diff -Nru a/arch/mips64/lib/strncpy_user.S b/arch/mips64/lib/strncpy_user.S --- a/arch/mips64/lib/strncpy_user.S Tue Jul 1 18:44:33 2003 +++ b/arch/mips64/lib/strncpy_user.S Tue Jul 1 18:44:33 2003 @@ -28,9 +28,9 @@ */ LEAF(__strncpy_from_user_asm) - ld v0, THREAD_CURDS($28) # pointer ok? + ld v0, TI_ADDR_LIMIT($28) # pointer ok? and v0, a1 - bltz v0, fault + bnez v0, fault FEXPORT(__strncpy_from_user_nocheck_asm) move v0, zero diff -Nru a/arch/mips64/lib/strnlen_user.S b/arch/mips64/lib/strnlen_user.S --- a/arch/mips64/lib/strnlen_user.S Tue Jul 1 18:44:34 2003 +++ b/arch/mips64/lib/strnlen_user.S Tue Jul 1 18:44:34 2003 @@ -23,11 +23,11 @@ * Return 0 for error, len on string but at max a1 otherwise */ LEAF(__strnlen_user_asm) - ld v0, THREAD_CURDS($28) # pointer ok? - and v0, ta0 - bltz v0, fault + ld v0, TI_ADDR_LIMIT($28) # pointer ok? + and v0, a0 + bnez v0, fault -EXPORT(__strnlen_user_nocheck_asm) +FEXPORT(__strnlen_user_nocheck_asm) move v0, a0 daddu a1, a0 # stop pointer 1: beq v0, a1, 1f # limit reached? @@ -37,10 +37,6 @@ 1: dsubu v0, a0 jr ra END(__strnlen_user_asm) - - .section __ex_table,"a" - PTR 1b, fault - .previous fault: move v0, zero jr ra diff -Nru a/arch/mips64/math-emu/Makefile b/arch/mips64/math-emu/Makefile --- a/arch/mips64/math-emu/Makefile Tue Jul 1 18:44:32 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,11 +0,0 @@ -# -# Makefile for the Linux/MIPS kernel FPU emulation. -# - -obj-y := cp1emu.o ieee754m.o ieee754d.o ieee754dp.o ieee754sp.o ieee754.o \ - ieee754xcpt.o dp_frexp.o dp_modf.o dp_div.o dp_mul.o dp_sub.o \ - dp_add.o dp_fsp.o dp_cmp.o dp_logb.o dp_scalb.o dp_simple.o \ - dp_tint.o dp_fint.o dp_tlong.o dp_flong.o sp_frexp.o sp_modf.o \ - sp_div.o sp_mul.o sp_sub.o sp_add.o sp_fdp.o sp_cmp.o sp_logb.o \ - sp_scalb.o sp_simple.o sp_tint.o sp_fint.o sp_tlong.o sp_flong.o \ - dp_sqrt.o sp_sqrt.o kernel_linkage.o diff -Nru a/arch/mips64/math-emu/cp1emu.c b/arch/mips64/math-emu/cp1emu.c --- a/arch/mips64/math-emu/cp1emu.c Tue Jul 1 18:44:36 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,1811 +0,0 @@ -/* - * MIPS floating point support - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * cp1emu.c: a MIPS coprocessor 1 (fpu) instruction emulator - * - * A complete emulator for MIPS coprocessor 1 instructions. This is - * required for #float(switch) or #float(trap), where it catches all - * COP1 instructions via the "CoProcessor Unusable" exception. - * - * More surprisingly it is also required for #float(ieee), to help out - * the hardware fpu at the boundaries of the IEEE-754 representation - * (denormalised values, infinities, underflow, etc). It is made - * quite nasty because emulation of some non-COP1 instructions is - * required, e.g. in branch delay slots. - * - * Notes: - * 1) the IEEE754 library (-le) performs the actual arithmetic; - * 2) if you know that you won't have an fpu, then you'll get much - * better performance by compiling with -msoft-float! - * - * Nov 7, 2000 - * Massive changes to integrate with Linux kernel. - * - * Replace use of kernel data area with use of user stack - * for execution of instructions in branch delay slots. - * - * Replace use of static kernel variables with thread_struct elements. - * - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - */ -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "ieee754.h" - -/* Strap kernel emulator for full MIPS IV emulation */ - -#ifdef __mips -#undef __mips -#endif -#define __mips 4 - -typedef void *vaddr_t; - -/* Function which emulates the instruction in a branch delay slot. */ - -static int mips_dsemul(struct pt_regs *, mips_instruction, vaddr_t); - -/* Function which emulates a floating point instruction. */ - -static int fpu_emu(struct pt_regs *, struct mips_fpu_soft_struct *, - mips_instruction); - -#if __mips >= 4 && __mips != 32 -static int fpux_emu(struct pt_regs *, - struct mips_fpu_soft_struct *, mips_instruction); -#endif - -/* Further private data for which no space exists in mips_fpu_soft_struct */ - -struct mips_fpu_emulator_private fpuemuprivate; - -/* Control registers */ - -#define FPCREG_RID 0 /* $0 = revision id */ -#define FPCREG_CSR 31 /* $31 = csr */ - -/* Convert Mips rounding mode (0..3) to IEEE library modes. */ -static const unsigned char ieee_rm[4] = { - IEEE754_RN, IEEE754_RZ, IEEE754_RU, IEEE754_RD -}; - -#if __mips >= 4 -/* convert condition code register number to csr bit */ -static const unsigned int fpucondbit[8] = { - FPU_CSR_COND0, - FPU_CSR_COND1, - FPU_CSR_COND2, - FPU_CSR_COND3, - FPU_CSR_COND4, - FPU_CSR_COND5, - FPU_CSR_COND6, - FPU_CSR_COND7 -}; -#endif - - - -/* - * Redundant with logic already in kernel/branch.c, - * embedded in compute_return_epc. At some point, - * a single subroutine should be used across both - * modules. - */ -static int isBranchInstr(mips_instruction * i) -{ - switch (MIPSInst_OPCODE(*i)) { - case spec_op: - switch (MIPSInst_FUNC(*i)) { - case jalr_op: - case jr_op: - return 1; - } - break; - - case bcond_op: - switch (MIPSInst_RT(*i)) { - case bltz_op: - case bgez_op: - case bltzl_op: - case bgezl_op: - case bltzal_op: - case bgezal_op: - case bltzall_op: - case bgezall_op: - return 1; - } - break; - - case j_op: - case jal_op: - case jalx_op: - case beq_op: - case bne_op: - case blez_op: - case bgtz_op: - case beql_op: - case bnel_op: - case blezl_op: - case bgtzl_op: - return 1; - - case cop0_op: - case cop1_op: - case cop2_op: - case cop1x_op: - if (MIPSInst_RS(*i) == bc_op) - return 1; - break; - } - - return 0; -} - -#define REG_TO_VA (vaddr_t) -#define VA_TO_REG (unsigned long) - -static unsigned long -mips_get_word(struct pt_regs *xcp, void *va, int *perr) -{ - unsigned long temp; - - if (!user_mode(xcp)) { - *perr = 0; - return (*(unsigned long *) va); - } else { - /* Use kernel get_user() macro */ - *perr = (int) get_user(temp, (unsigned long *) va); - return temp; - } -} - -static unsigned long long -mips_get_dword(struct pt_regs *xcp, void *va, int *perr) -{ - unsigned long long temp; - - if (!user_mode(xcp)) { - *perr = 0; - return (*(unsigned long long *) va); - } else { - /* Use kernel get_user() macro */ - *perr = (int) get_user(temp, (unsigned long long *) va); - return temp; - } -} - -static int mips_put_word(struct pt_regs *xcp, void *va, unsigned long val) -{ - if (!user_mode(xcp)) { - *(unsigned long *) va = val; - return 0; - } else { - /* Use kernel get_user() macro */ - return (int) put_user(val, (unsigned long *) va); - } -} - -static int mips_put_dword(struct pt_regs *xcp, void *va, long long val) -{ - if (!user_mode(xcp)) { - *(unsigned long long *) va = val; - return 0; - } else { - /* Use kernel get_user() macro */ - return (int) put_user(val, (unsigned long long *) va); - } -} - - -/* - * In the Linux kernel, we support selection of FPR format on the - * basis of the Status.FR bit. This does imply that, if a full 32 - * FPRs are desired, there needs to be a flip-flop that can be written - * to one at that bit position. In any case, normal MIPS ABI uses - * only the even FPRs (Status.FR = 0). - */ - -#define CP0_STATUS_FR_SUPPORT - -/* - * Emulate the single floating point instruction pointed at by EPC. - * Two instructions if the instruction is in a branch delay slot. - */ - -static int -cop1Emulate(int xcptno, struct pt_regs *xcp, - struct mips_fpu_soft_struct *ctx) -{ - mips_instruction ir; - vaddr_t emulpc; - vaddr_t contpc; - unsigned int cond; - int err = 0; - - - ir = mips_get_word(xcp, REG_TO_VA xcp->cp0_epc, &err); - if (err) { - fpuemuprivate.stats.errors++; - return SIGBUS; - } - - /* XXX NEC Vr54xx bug workaround */ - if ((xcp->cp0_cause & CAUSEF_BD) && !isBranchInstr(&ir)) - xcp->cp0_cause &= ~CAUSEF_BD; - - if (xcp->cp0_cause & CAUSEF_BD) { - /* - * The instruction to be emulated is in a branch delay slot - * which means that we have to emulate the branch instruction - * BEFORE we do the cop1 instruction. - * - * This branch could be a COP1 branch, but in that case we - * would have had a trap for that instruction, and would not - * come through this route. - * - * Linux MIPS branch emulator operates on context, updating the - * cp0_epc. - */ - emulpc = REG_TO_VA(xcp->cp0_epc + 4); /* Snapshot emulation target */ - - if (__compute_return_epc(xcp)) { -#ifdef CP1DBG - printk("failed to emulate branch at %p\n", - REG_TO_VA(xcp->cp0_epc)); -#endif - return SIGILL;; - } - ir = mips_get_word(xcp, emulpc, &err); - if (err) { - fpuemuprivate.stats.errors++; - return SIGBUS; - } - contpc = REG_TO_VA xcp->cp0_epc; - } else { - emulpc = REG_TO_VA xcp->cp0_epc; - contpc = REG_TO_VA xcp->cp0_epc + 4; - } - - emul: - fpuemuprivate.stats.emulated++; - switch (MIPSInst_OPCODE(ir)) { -#ifdef CP0_STATUS_FR_SUPPORT - /* R4000+ 64-bit fpu registers */ -#ifndef SINGLE_ONLY_FPU - case ldc1_op: - { - void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)]) - + MIPSInst_SIMM(ir); - int ft = MIPSInst_RT(ir); - if (!(xcp->cp0_status & ST0_FR)) - ft &= ~1; - ctx->regs[ft] = mips_get_dword(xcp, va, &err); - fpuemuprivate.stats.loads++; - if (err) { - fpuemuprivate.stats.errors++; - return SIGBUS; - } - } - break; - - case sdc1_op: - { - void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)]) - + MIPSInst_SIMM(ir); - int ft = MIPSInst_RT(ir); - if (!(xcp->cp0_status & ST0_FR)) - ft &= ~1; - fpuemuprivate.stats.stores++; - if (mips_put_dword(xcp, va, ctx->regs[ft])) { - fpuemuprivate.stats.errors++; - return SIGBUS; - } - } - break; -#endif - - case lwc1_op: - { - void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)]) - + MIPSInst_SIMM(ir); - fpureg_t val; - int ft = MIPSInst_RT(ir); - fpuemuprivate.stats.loads++; - val = mips_get_word(xcp, va, &err); - if (err) { - fpuemuprivate.stats.errors++; - return SIGBUS; - } - if (xcp->cp0_status & ST0_FR) { - /* load whole register */ - ctx->regs[ft] = val; - } else if (ft & 1) { - /* load to m.s. 32 bits */ -#ifdef SINGLE_ONLY_FPU - /* illegal register in single-float mode */ - return SIGILL; -#else - ctx->regs[(ft & ~1)] &= 0xffffffff; - ctx->regs[(ft & ~1)] |= val << 32; -#endif - } else { - /* load to l.s. 32 bits */ - ctx->regs[ft] &= ~0xffffffffLL; - ctx->regs[ft] |= val; - } - } - break; - - case swc1_op: - { - void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)]) - + MIPSInst_SIMM(ir); - unsigned int val; - int ft = MIPSInst_RT(ir); - fpuemuprivate.stats.stores++; - if (xcp->cp0_status & ST0_FR) { - /* store whole register */ - val = ctx->regs[ft]; - } else if (ft & 1) { -#ifdef SINGLE_ONLY_FPU - /* illegal register in single-float mode */ - return SIGILL; -#else - /* store from m.s. 32 bits */ - val = ctx->regs[(ft & ~1)] >> 32; -#endif - } else { - /* store from l.s. 32 bits */ - val = ctx->regs[ft]; - } - if (mips_put_word(xcp, va, val)) { - fpuemuprivate.stats.errors++; - return SIGBUS; - } - } - break; -#else /* old 32-bit fpu registers */ - case lwc1_op: - { - void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)]) - + MIPSInst_SIMM(ir); - ctx->regs[MIPSInst_RT(ir)] = - mips_get_word(xcp, va, &err); - fpuemuprivate.stats.loads++; - if (err) { - fpuemuprivate.stats.errors++; - return SIGBUS; - } - } - break; - - case swc1_op: - { - void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)]) - + MIPSInst_SIMM(ir); - fpuemuprivate.stats.stores++; - if (mips_put_word - (xcp, va, ctx->regs[MIPSInst_RT(ir)])) { - fpuemuprivate.stats.errors++; - return SIGBUS; - } - } - break; - case ldc1_op: - { - void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)]) - + MIPSInst_SIMM(ir); - unsigned int rt = MIPSInst_RT(ir) & ~1; - int errs = 0; - fpuemuprivate.stats.loads++; -#if (defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) || defined(__MIPSEB__) - ctx->regs[rt + 1] = - mips_get_word(xcp, va + 0, &err); - errs += err; - ctx->regs[rt + 0] = - mips_get_word(xcp, va + 4, &err); - errs += err; -#else - ctx->regs[rt + 0] = - mips_get_word(xcp, va + 0, &err); - errs += err; - ctx->regs[rt + 1] = - mips_get_word(xcp, va + 4, &err); - errs += err; -#endif - if (err) - return SIGBUS; - } - break; - - case sdc1_op: - { - void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)]) - + MIPSInst_SIMM(ir); - unsigned int rt = MIPSInst_RT(ir) & ~1; - fpuemuprivate.stats.stores++; -#if (defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) || defined(__MIPSEB__) - if (mips_put_word(xcp, va + 0, ctx->regs[rt + 1])) - return SIGBUS; - if (mips_put_word(xcp, va + 4, ctx->regs[rt + 0])) - return SIGBUS; -#else - if (mips_put_word(xcp, va + 0, ctx->regs[rt + 0])) - return SIGBUS; - if (mips_put_word(xcp, va + 4, ctx->regs[rt + 1])) - return SIGBUS; -#endif - } - break; -#endif - - case cop1_op: - switch (MIPSInst_RS(ir)) { - -#ifdef CP0_STATUS_FR_SUPPORT -#if __mips64 && !defined(SINGLE_ONLY_FPU) - case dmfc_op: - /* copregister fs -> gpr[rt] */ - if (MIPSInst_RT(ir) != 0) { - int fs = MIPSInst_RD(ir); - if (!(xcp->cp0_status & ST0_FR)) - fs &= ~1; - xcp->regs[MIPSInst_RT(ir)] = ctx->regs[fs]; - } - break; - - case dmtc_op: - /* copregister fs <- rt */ - { - fpureg_t value; - int fs = MIPSInst_RD(ir); - if (!(xcp->cp0_status & ST0_FR)) - fs &= ~1; - value = - (MIPSInst_RT(ir) == - 0) ? 0 : xcp->regs[MIPSInst_RT(ir)]; - ctx->regs[fs] = value; - } - break; -#endif - - case mfc_op: - /* copregister rd -> gpr[rt] */ - if (MIPSInst_RT(ir) != 0) { - /* default value from l.s. 32 bits */ - int value = ctx->regs[MIPSInst_RD(ir)]; - if (MIPSInst_RD(ir) & 1) { -#ifdef SINGLE_ONLY_FPU - /* illegal register in single-float mode */ - return SIGILL; -#else - if (!(xcp->cp0_status & ST0_FR)) { - /* move from m.s. 32 bits */ - value = - ctx-> - regs[MIPSInst_RD(ir) & - ~1] >> 32; - } -#endif - } - xcp->regs[MIPSInst_RT(ir)] = value; - } - break; - - case mtc_op: - /* copregister rd <- rt */ - { - fpureg_t value; - if (MIPSInst_RT(ir) == 0) - value = 0; - else - value = - (unsigned int) xcp-> - regs[MIPSInst_RT(ir)]; - if (MIPSInst_RD(ir) & 1) { -#ifdef SINGLE_ONLY_FPU - /* illegal register in single-float mode */ - return SIGILL; -#else - if (!(xcp->cp0_status & ST0_FR)) { - /* move to m.s. 32 bits */ - ctx-> - regs[ - (MIPSInst_RD(ir) & - ~1)] &= - 0xffffffff; - ctx-> - regs[ - (MIPSInst_RD(ir) & - ~1)] |= - value << 32; - break; - } -#endif - } - /* move to l.s. 32 bits */ - ctx->regs[MIPSInst_RD(ir)] &= - ~0xffffffffLL; - ctx->regs[MIPSInst_RD(ir)] |= value; - } - break; -#else - - case mfc_op: - /* copregister rd -> gpr[rt] */ - if (MIPSInst_RT(ir) != 0) { - unsigned value = - ctx->regs[MIPSInst_RD(ir)]; - xcp->regs[MIPSInst_RT(ir)] = value; - } - break; - - case mtc_op: - /* copregister rd <- rt */ - { - unsigned value; - value = - (MIPSInst_RT(ir) == - 0) ? 0 : xcp->regs[MIPSInst_RT(ir)]; - ctx->regs[MIPSInst_RD(ir)] = value; - } - break; -#endif - - case cfc_op: - /* cop control register rd -> gpr[rt] */ - { - unsigned value; - - if (MIPSInst_RD(ir) == FPCREG_CSR) { - value = ctx->sr; -#ifdef CSRTRACE - printk - ("%p gpr[%d]<-csr=%08x\n", - REG_TO_VA(xcp->cp0_epc), - MIPSInst_RT(ir), value); -#endif - } else if (MIPSInst_RD(ir) == FPCREG_RID) - value = 0; - else - value = 0; - if (MIPSInst_RT(ir)) - xcp->regs[MIPSInst_RT(ir)] = value; - } - break; - - case ctc_op: - /* copregister rd <- rt */ - { - unsigned value; - - if (MIPSInst_RT(ir) == 0) - value = 0; - else - value = xcp->regs[MIPSInst_RT(ir)]; - - /* we only have one writable control reg - */ - if (MIPSInst_RD(ir) == FPCREG_CSR) { -#ifdef CSRTRACE - printk - ("%p gpr[%d]->csr=%08x\n", - REG_TO_VA(xcp->cp0_epc), - MIPSInst_RT(ir), value); -#endif - ctx->sr = value; - /* copy new rounding mode to ieee library state! */ - ieee754_csr.rm = - ieee_rm[value & 0x3]; - } - } - break; - - case bc_op: - if (xcp->cp0_cause & CAUSEF_BD) { - return SIGILL; - } - { - int likely = 0; - -#if __mips >= 4 - cond = - ctx-> - sr & fpucondbit[MIPSInst_RT(ir) >> 2]; -#else - cond = ctx->sr & FPU_CSR_COND; -#endif - switch (MIPSInst_RT(ir) & 3) { - case bcfl_op: - likely = 1; - case bcf_op: - cond = !cond; - break; - case bctl_op: - likely = 1; - case bct_op: - break; - default: - /* thats an illegal instruction */ - return SIGILL; - } - - xcp->cp0_cause |= CAUSEF_BD; - if (cond) { - /* branch taken: emulate dslot instruction */ - xcp->cp0_epc += 4; - contpc = - REG_TO_VA xcp->cp0_epc + - (MIPSInst_SIMM(ir) << 2); - - ir = - mips_get_word(xcp, - REG_TO_VA(xcp-> - cp0_epc), - &err); - if (err) { - fpuemuprivate.stats. - errors++; - return SIGBUS; - } - - switch (MIPSInst_OPCODE(ir)) { - case lwc1_op: - case swc1_op: -#if (__mips >= 2 || __mips64) && !defined(SINGLE_ONLY_FPU) - case ldc1_op: - case sdc1_op: -#endif - case cop1_op: -#if __mips >= 4 && __mips != 32 - case cop1x_op: -#endif - /* its one of ours */ - goto emul; -#if __mips >= 4 - case spec_op: - if (MIPSInst_FUNC(ir) == - movc_op) goto emul; - break; -#endif - } - - /* single step the non-cp1 instruction in the dslot */ - return mips_dsemul(xcp, ir, contpc); - } else { - /* branch not taken */ - if (likely) - /* branch likely nullifies dslot if not taken */ - xcp->cp0_epc += 4; - /* else continue & execute dslot as normal insn */ - } - } - break; - - default: - if (!(MIPSInst_RS(ir) & 0x10)) { - return SIGILL; - } - /* a real fpu computation instruction */ - { - int sig; - if ((sig = fpu_emu(xcp, ctx, ir))) - return sig; - } - } - break; - -#if __mips >= 4 && __mips != 32 - case cop1x_op: - { - int sig; - if ((sig = fpux_emu(xcp, ctx, ir))) - return sig; - } - break; -#endif - -#if __mips >= 4 - case spec_op: - if (MIPSInst_FUNC(ir) != movc_op) - return SIGILL; - cond = fpucondbit[MIPSInst_RT(ir) >> 2]; - if (((ctx->sr & cond) != 0) != - ((MIPSInst_RT(ir) & 1) != 0)) return 0; - xcp->regs[MIPSInst_RD(ir)] = xcp->regs[MIPSInst_RS(ir)]; - break; -#endif - - default: - return SIGILL; - } - - /* we did it !! */ - xcp->cp0_epc = VA_TO_REG(contpc); - xcp->cp0_cause &= ~CAUSEF_BD; - return 0; -} - -/* - * Emulate the arbritrary instruction ir at xcp->cp0_epc. Required when - * we have to emulate the instruction in a COP1 branch delay slot. Do - * not change cp0_epc due to the instruction - * - * According to the spec: - * 1) it shouldnt be a branch :-) - * 2) it can be a COP instruction :-( - * 3) if we are tring to run a protected memory space we must take - * special care on memory access instructions :-( - */ - -/* - * "Trampoline" return routine to catch exception following - * execution of delay-slot instruction execution. - */ - -int do_dsemulret(struct pt_regs *xcp) -{ -#ifdef DSEMUL_TRACE - printk("desemulret\n"); -#endif - /* Set EPC to return to post-branch instruction */ - xcp->cp0_epc = current->thread.dsemul_epc; - /* - * Clear the state that got us here. - */ - current->thread.dsemul_aerpc = (unsigned long) 0; - - return 0; -} - - -#define AdELOAD 0x8c000001 /* lw $0,1($0) */ - -static int -mips_dsemul(struct pt_regs *xcp, mips_instruction ir, vaddr_t cpc) -{ - mips_instruction *dsemul_insns; - mips_instruction forcetrap; - extern asmlinkage void handle_dsemulret(void); - - if (ir == 0) { /* a nop is easy */ - xcp->cp0_epc = VA_TO_REG(cpc); - return 0; - } -#ifdef DSEMUL_TRACE - printk("desemul %p %p\n", REG_TO_VA(xcp->cp0_epc), cpc); -#endif - - /* - * The strategy is to push the instruction onto the user stack - * and put a trap after it which we can catch and jump to - * the required address any alternative apart from full - * instruction emulation!!. - */ - dsemul_insns = (mips_instruction *) (xcp->regs[29] & ~3); - dsemul_insns -= 3; /* Two instructions, plus one for luck ;-) */ - /* Verify that the stack pointer is not competely insane */ - if (verify_area - (VERIFY_WRITE, dsemul_insns, sizeof(mips_instruction) * 2)) - return SIGBUS; - - if (mips_put_word(xcp, &dsemul_insns[0], ir)) { - fpuemuprivate.stats.errors++; - return (SIGBUS); - } - - /* - * Algorithmics used a system call instruction, and - * borrowed that vector. MIPS/Linux version is a bit - * more heavyweight in the interests of portability and - * multiprocessor support. We flag the thread for special - * handling in the unaligned access handler and force an - * address error excpetion. - */ - - /* If one is *really* paranoid, one tests for a bad stack pointer */ - if ((xcp->regs[29] & 0x3) == 0x3) - forcetrap = AdELOAD - 1; - else - forcetrap = AdELOAD; - - if (mips_put_word(xcp, &dsemul_insns[1], forcetrap)) { - fpuemuprivate.stats.errors++; - return (SIGBUS); - } - - /* Set thread state to catch and handle the exception */ - current->thread.dsemul_epc = (unsigned long) cpc; - current->thread.dsemul_aerpc = (unsigned long) &dsemul_insns[1]; - xcp->cp0_epc = VA_TO_REG & dsemul_insns[0]; - flush_cache_sigtramp((unsigned long) dsemul_insns); - - return SIGILL; /* force out of emulation loop */ -} - -/* - * Conversion table from MIPS compare ops 48-63 - * cond = ieee754dp_cmp(x,y,IEEE754_UN); - */ -static const unsigned char cmptab[8] = { - 0, /* cmp_0 (sig) cmp_sf */ - IEEE754_CUN, /* cmp_un (sig) cmp_ngle */ - IEEE754_CEQ, /* cmp_eq (sig) cmp_seq */ - IEEE754_CEQ | IEEE754_CUN, /* cmp_ueq (sig) cmp_ngl */ - IEEE754_CLT, /* cmp_olt (sig) cmp_lt */ - IEEE754_CLT | IEEE754_CUN, /* cmp_ult (sig) cmp_nge */ - IEEE754_CLT | IEEE754_CEQ, /* cmp_ole (sig) cmp_le */ - IEEE754_CLT | IEEE754_CEQ | IEEE754_CUN, /* cmp_ule (sig) cmp_ngt */ -}; - -#define SIFROMREG(si,x) ((si) = ctx->regs[x]) -#define SITOREG(si,x) (ctx->regs[x] = (int)(si)) - -#if __mips64 && !defined(SINGLE_ONLY_FPU) -#define DIFROMREG(di,x) ((di) = ctx->regs[x]) -#define DITOREG(di,x) (ctx->regs[x] = (di)) -#endif - -#define SPFROMREG(sp,x) ((sp).bits = ctx->regs[x]) -#define SPTOREG(sp,x) (ctx->regs[x] = (sp).bits) - -#ifdef CP0_STATUS_FR_SUPPORT -#define DPFROMREG(dp,x) ((dp).bits = \ - ctx->regs[(xcp->cp0_status & ST0_FR) ? x : (x & ~1)]) -#define DPTOREG(dp,x) (ctx->regs[(xcp->cp0_status & ST0_FR) ? x : (x & ~1)]\ - = (dp).bits) -#else -/* Beware: MIPS COP1 doubles are always little_word endian in registers */ -#define DPFROMREG(dp,x) \ - ((dp).bits = ((unsigned long long)ctx->regs[(x)+1] << 32) | ctx->regs[x]) -#define DPTOREG(dp,x) \ - (ctx->regs[x] = (dp).bits, ctx->regs[(x)+1] = (dp).bits >> 32) -#endif - -#if __mips >= 4 && __mips != 32 - -/* - * Additional MIPS4 instructions - */ - -static ieee754dp fpemu_dp_recip(ieee754dp d) -{ - return ieee754dp_div(ieee754dp_one(0), d); -} - -static ieee754dp fpemu_dp_rsqrt(ieee754dp d) -{ - return ieee754dp_div(ieee754dp_one(0), ieee754dp_sqrt(d)); -} - -static ieee754sp fpemu_sp_recip(ieee754sp s) -{ - return ieee754sp_div(ieee754sp_one(0), s); -} - -static ieee754sp fpemu_sp_rsqrt(ieee754sp s) -{ - return ieee754sp_div(ieee754sp_one(0), ieee754sp_sqrt(s)); -} - - -static ieee754dp fpemu_dp_madd(ieee754dp r, ieee754dp s, ieee754dp t) -{ - return ieee754dp_add(ieee754dp_mul(s, t), r); -} - -static ieee754dp fpemu_dp_msub(ieee754dp r, ieee754dp s, ieee754dp t) -{ - return ieee754dp_sub(ieee754dp_mul(s, t), r); -} - -static ieee754dp fpemu_dp_nmadd(ieee754dp r, ieee754dp s, ieee754dp t) -{ - return ieee754dp_neg(ieee754dp_add(ieee754dp_mul(s, t), r)); -} - -static ieee754dp fpemu_dp_nmsub(ieee754dp r, ieee754dp s, ieee754dp t) -{ - return ieee754dp_neg(ieee754dp_sub(ieee754dp_mul(s, t), r)); -} - - -static ieee754sp fpemu_sp_madd(ieee754sp r, ieee754sp s, ieee754sp t) -{ - return ieee754sp_add(ieee754sp_mul(s, t), r); -} - -static ieee754sp fpemu_sp_msub(ieee754sp r, ieee754sp s, ieee754sp t) -{ - return ieee754sp_sub(ieee754sp_mul(s, t), r); -} - -static ieee754sp fpemu_sp_nmadd(ieee754sp r, ieee754sp s, ieee754sp t) -{ - return ieee754sp_neg(ieee754sp_add(ieee754sp_mul(s, t), r)); -} - -static ieee754sp fpemu_sp_nmsub(ieee754sp r, ieee754sp s, ieee754sp t) -{ - return ieee754sp_neg(ieee754sp_sub(ieee754sp_mul(s, t), r)); -} - -static int -fpux_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx, - mips_instruction ir) -{ - unsigned rcsr = 0; /* resulting csr */ - - fpuemuprivate.stats.cp1xops++; - - switch (MIPSInst_FMA_FFMT(ir)) { - case s_fmt: /* 0 */ - { - ieee754sp(*handler) (ieee754sp, ieee754sp, - ieee754sp); - ieee754sp fd, fr, fs, ft; - - switch (MIPSInst_FUNC(ir)) { - case lwxc1_op: - { - void *va = - REG_TO_VA(xcp-> - regs[MIPSInst_FR(ir)] - + - xcp-> - regs[MIPSInst_FT - (ir)]); - fpureg_t val; - int err = 0; - val = mips_get_word(xcp, va, &err); - if (err) { - fpuemuprivate.stats. - errors++; - return SIGBUS; - } - if (xcp->cp0_status & ST0_FR) { - /* load whole register */ - ctx-> - regs[MIPSInst_FD(ir)] = - val; - } else if (MIPSInst_FD(ir) & 1) { - /* load to m.s. 32 bits */ -#if defined(SINGLE_ONLY_FPU) - /* illegal register in single-float mode */ - return SIGILL; -#else - ctx-> - regs[ - (MIPSInst_FD(ir) & - ~1)] &= - 0xffffffff; - ctx-> - regs[ - (MIPSInst_FD(ir) & - ~1)] |= - val << 32; -#endif - } else { - /* load to l.s. 32 bits */ - ctx-> - regs[MIPSInst_FD(ir)] - &= ~0xffffffffLL; - ctx-> - regs[MIPSInst_FD(ir)] - |= val; - } - } - break; - - case swxc1_op: - { - void *va = - REG_TO_VA(xcp-> - regs[MIPSInst_FR(ir)] - + - xcp-> - regs[MIPSInst_FT - (ir)]); - unsigned int val; - if (xcp->cp0_status & ST0_FR) { - /* store whole register */ - val = - ctx-> - regs[MIPSInst_FS(ir)]; - } else if (MIPSInst_FS(ir) & 1) { -#if defined(SINGLE_ONLY_FPU) - /* illegal register in single-float mode */ - return SIGILL; -#else - /* store from m.s. 32 bits */ - val = - ctx-> - regs[ - (MIPSInst_FS(ir) & - ~1)] >> 32; -#endif - } else { - /* store from l.s. 32 bits */ - val = - ctx-> - regs[MIPSInst_FS(ir)]; - } - if (mips_put_word(xcp, va, val)) { - fpuemuprivate.stats. - errors++; - return SIGBUS; - } - } - break; - - case madd_s_op: - handler = fpemu_sp_madd; - goto scoptop; - case msub_s_op: - handler = fpemu_sp_msub; - goto scoptop; - case nmadd_s_op: - handler = fpemu_sp_nmadd; - goto scoptop; - case nmsub_s_op: - handler = fpemu_sp_nmsub; - goto scoptop; - - scoptop: - SPFROMREG(fr, MIPSInst_FR(ir)); - SPFROMREG(fs, MIPSInst_FS(ir)); - SPFROMREG(ft, MIPSInst_FT(ir)); - fd = (*handler) (fr, fs, ft); - SPTOREG(fd, MIPSInst_FD(ir)); - - copcsr: - if (ieee754_cxtest(IEEE754_INEXACT)) - rcsr |= - FPU_CSR_INE_X | FPU_CSR_INE_S; - if (ieee754_cxtest(IEEE754_UNDERFLOW)) - rcsr |= - FPU_CSR_UDF_X | FPU_CSR_UDF_S; - if (ieee754_cxtest(IEEE754_OVERFLOW)) - rcsr |= - FPU_CSR_OVF_X | FPU_CSR_OVF_S; - if (ieee754_cxtest - (IEEE754_INVALID_OPERATION)) rcsr |= - FPU_CSR_INV_X | FPU_CSR_INV_S; - - ctx->sr = - (ctx->sr & ~FPU_CSR_ALL_X) | rcsr; - if ((ctx->sr >> 5) & ctx-> - sr & FPU_CSR_ALL_E) { - /*printk ("SIGFPE: fpu csr = %08x\n",ctx->sr); */ - return SIGFPE; - } - - break; - - default: - return SIGILL; - } - } - break; - -#if !defined(SINGLE_ONLY_FPU) - case d_fmt: /* 1 */ - { - ieee754dp(*handler) (ieee754dp, ieee754dp, - ieee754dp); - ieee754dp fd, fr, fs, ft; - - switch (MIPSInst_FUNC(ir)) { - case ldxc1_op: - { - void *va = - REG_TO_VA(xcp-> - regs[MIPSInst_FR(ir)] - + - xcp-> - regs[MIPSInst_FT - (ir)]); - int err = 0; - ctx->regs[MIPSInst_FD(ir)] = - mips_get_dword(xcp, va, &err); - if (err) { - fpuemuprivate.stats. - errors++; - return SIGBUS; - } - } - break; - - case sdxc1_op: - { - void *va = - REG_TO_VA(xcp-> - regs[MIPSInst_FR(ir)] - + - xcp-> - regs[MIPSInst_FT - (ir)]); - if (mips_put_dword - (xcp, va, - ctx->regs[MIPSInst_FS(ir)])) { - fpuemuprivate.stats. - errors++; - return SIGBUS; - } - } - break; - - case madd_d_op: - handler = fpemu_dp_madd; - goto dcoptop; - case msub_d_op: - handler = fpemu_dp_msub; - goto dcoptop; - case nmadd_d_op: - handler = fpemu_dp_nmadd; - goto dcoptop; - case nmsub_d_op: - handler = fpemu_dp_nmsub; - goto dcoptop; - - dcoptop: - DPFROMREG(fr, MIPSInst_FR(ir)); - DPFROMREG(fs, MIPSInst_FS(ir)); - DPFROMREG(ft, MIPSInst_FT(ir)); - fd = (*handler) (fr, fs, ft); - DPTOREG(fd, MIPSInst_FD(ir)); - goto copcsr; - - default: - return SIGILL; - } - } - break; -#endif - - case 0x7: /* 7 */ - { - if (MIPSInst_FUNC(ir) != pfetch_op) { - return SIGILL; - } - /* ignore prefx operation */ - } - break; - - default: - return SIGILL; - } - - return 0; -} -#endif - - - -/* - * Emulate a single COP1 arithmetic instruction. - */ -static int -fpu_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx, - mips_instruction ir) -{ - int rfmt; /* resulting format */ - unsigned rcsr = 0; /* resulting csr */ - unsigned cond; - union { - ieee754dp d; - ieee754sp s; - int w; -#if __mips64 - long long l; -#endif - } rv; /* resulting value */ - - fpuemuprivate.stats.cp1ops++; - switch (rfmt = (MIPSInst_FFMT(ir) & 0xf)) { - - case s_fmt:{ /* 0 */ - ieee754sp(*handler) (); - - switch (MIPSInst_FUNC(ir)) { - /* binary ops */ - case fadd_op: - handler = ieee754sp_add; - goto scopbop; - case fsub_op: - handler = ieee754sp_sub; - goto scopbop; - case fmul_op: - handler = ieee754sp_mul; - goto scopbop; - case fdiv_op: - handler = ieee754sp_div; - goto scopbop; - - /* unary ops */ -#if __mips >= 2 || __mips64 - case fsqrt_op: - handler = ieee754sp_sqrt; - goto scopuop; -#endif -#if __mips >= 4 && __mips != 32 - case frsqrt_op: - handler = fpemu_sp_rsqrt; - goto scopuop; - case frecip_op: - handler = fpemu_sp_recip; - goto scopuop; -#endif -#if __mips >= 4 - case fmovc_op: - cond = fpucondbit[MIPSInst_FT(ir) >> 2]; - if (((ctx->sr & cond) != 0) != - ((MIPSInst_FT(ir) & 1) != 0)) - return 0; - SPFROMREG(rv.s, MIPSInst_FS(ir)); - break; - case fmovz_op: - if (xcp->regs[MIPSInst_FT(ir)] != 0) - return 0; - SPFROMREG(rv.s, MIPSInst_FS(ir)); - break; - case fmovn_op: - if (xcp->regs[MIPSInst_FT(ir)] == 0) - return 0; - SPFROMREG(rv.s, MIPSInst_FS(ir)); - break; -#endif - case fabs_op: - handler = ieee754sp_abs; - goto scopuop; - case fneg_op: - handler = ieee754sp_neg; - goto scopuop; - case fmov_op: - /* an easy one */ - SPFROMREG(rv.s, MIPSInst_FS(ir)); - break; - /* binary op on handler */ -scopbop: - { - ieee754sp fs, ft; - - SPFROMREG(fs, MIPSInst_FS(ir)); - SPFROMREG(ft, MIPSInst_FT(ir)); - - rv.s = (*handler) (fs, ft); - goto copcsr; - } -scopuop: - { - ieee754sp fs; - - SPFROMREG(fs, MIPSInst_FS(ir)); - rv.s = (*handler) (fs); - goto copcsr; - } -copcsr: - if (ieee754_cxtest(IEEE754_INEXACT)) - rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S; - if (ieee754_cxtest(IEEE754_UNDERFLOW)) - rcsr |= FPU_CSR_UDF_X | FPU_CSR_UDF_S; - if (ieee754_cxtest(IEEE754_OVERFLOW)) - rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S; - if (ieee754_cxtest(IEEE754_ZERO_DIVIDE)) - rcsr |= FPU_CSR_DIV_X | FPU_CSR_DIV_S; - if (ieee754_cxtest - (IEEE754_INVALID_OPERATION)) rcsr |= - FPU_CSR_INV_X | FPU_CSR_INV_S; - break; - - /* unary conv ops */ - case fcvts_op: - return SIGILL; /* not defined */ - case fcvtd_op: -#if defined(SINGLE_ONLY_FPU) - return SIGILL; /* not defined */ -#else - { - ieee754sp fs; - - SPFROMREG(fs, MIPSInst_FS(ir)); - rv.d = ieee754dp_fsp(fs); - rfmt = d_fmt; - goto copcsr; - } -#endif - case fcvtw_op: - { - ieee754sp fs; - - SPFROMREG(fs, MIPSInst_FS(ir)); - rv.w = ieee754sp_tint(fs); - rfmt = w_fmt; - goto copcsr; - } - -#if __mips >= 2 || __mips64 - case fround_op: - case ftrunc_op: - case fceil_op: - case ffloor_op: - { - unsigned int oldrm = ieee754_csr.rm; - ieee754sp fs; - - SPFROMREG(fs, MIPSInst_FS(ir)); - ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3]; - rv.w = ieee754sp_tint(fs); - ieee754_csr.rm = oldrm; - rfmt = w_fmt; - goto copcsr; - } -#endif /* __mips >= 2 */ - -#if __mips64 && !defined(SINGLE_ONLY_FPU) - case fcvtl_op: - { - ieee754sp fs; - - SPFROMREG(fs, MIPSInst_FS(ir)); - rv.l = ieee754sp_tlong(fs); - rfmt = l_fmt; - goto copcsr; - } - - case froundl_op: - case ftruncl_op: - case fceill_op: - case ffloorl_op: - { - unsigned int oldrm = ieee754_csr.rm; - ieee754sp fs; - - SPFROMREG(fs, MIPSInst_FS(ir)); - ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3]; - rv.l = ieee754sp_tlong(fs); - ieee754_csr.rm = oldrm; - rfmt = l_fmt; - goto copcsr; - } -#endif /* __mips64 && !fpu(single) */ - - default: - if (MIPSInst_FUNC(ir) >= fcmp_op) { - unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op; - ieee754sp fs, ft; - - SPFROMREG(fs, MIPSInst_FS(ir)); - SPFROMREG(ft, MIPSInst_FT(ir)); - rv.w = ieee754sp_cmp(fs, ft, cmptab[cmpop & 0x7]); - rfmt = -1; - if ((cmpop & 0x8) && ieee754_cxtest(IEEE754_INVALID_OPERATION)) - rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S; - } else { - return SIGILL; - } - break; - } - break; - } - -#if !defined(SINGLE_ONLY_FPU) - case d_fmt: { - ieee754dp(*handler) (); - - switch (MIPSInst_FUNC(ir)) { - /* binary ops */ - case fadd_op: - handler = ieee754dp_add; - goto dcopbop; - case fsub_op: - handler = ieee754dp_sub; - goto dcopbop; - case fmul_op: - handler = ieee754dp_mul; - goto dcopbop; - case fdiv_op: - handler = ieee754dp_div; - goto dcopbop; - - /* unary ops */ -#if __mips >= 2 || __mips64 - case fsqrt_op: - handler = ieee754dp_sqrt; - goto dcopuop; -#endif -#if __mips >= 4 && __mips != 32 - case frsqrt_op: - handler = fpemu_dp_rsqrt; - goto dcopuop; - case frecip_op: - handler = fpemu_dp_recip; - goto dcopuop; -#endif -#if __mips >= 4 - case fmovc_op: - cond = fpucondbit[MIPSInst_FT(ir) >> 2]; - if (((ctx->sr & cond) != 0) != ((MIPSInst_FT(ir) & 1) != 0)) - return 0; - DPFROMREG(rv.d, MIPSInst_FS(ir)); - break; - case fmovz_op: - if (xcp->regs[MIPSInst_FT(ir)] != 0) - return 0; - DPFROMREG(rv.d, MIPSInst_FS(ir)); - break; - case fmovn_op: - if (xcp->regs[MIPSInst_FT(ir)] == 0) - return 0; - DPFROMREG(rv.d, MIPSInst_FS(ir)); - break; -#endif - case fabs_op: - handler = ieee754dp_abs; - goto dcopuop; - case fneg_op: - handler = ieee754dp_neg; - goto dcopuop; - case fmov_op: - /* an easy one */ - DPFROMREG(rv.d, MIPSInst_FS(ir)); - break; - - /* binary op on handler */ -dcopbop: - { - ieee754dp fs, ft; - - DPFROMREG(fs, MIPSInst_FS(ir)); - DPFROMREG(ft, MIPSInst_FT(ir)); - - rv.d = (*handler) (fs, ft); - goto copcsr; - } -dcopuop: - { - ieee754dp fs; - - DPFROMREG(fs, MIPSInst_FS(ir)); - rv.d = (*handler) (fs); - goto copcsr; - } - - /* unary conv ops */ - case fcvts_op: - { - ieee754dp fs; - - DPFROMREG(fs, MIPSInst_FS(ir)); - rv.s = ieee754sp_fdp(fs); - rfmt = s_fmt; - goto copcsr; - } - case fcvtd_op: - return SIGILL; /* not defined */ - case fcvtw_op: - { - ieee754dp fs; - - DPFROMREG(fs, MIPSInst_FS(ir)); - rv.w = ieee754dp_tint(fs); /* wrong */ - rfmt = w_fmt; - goto copcsr; - } - -#if __mips >= 2 || __mips64 - case fround_op: - case ftrunc_op: - case fceil_op: - case ffloor_op: - { - unsigned int oldrm = ieee754_csr.rm; - ieee754dp fs; - - DPFROMREG(fs, MIPSInst_FS(ir)); - ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3]; - rv.w = ieee754dp_tint(fs); - ieee754_csr.rm = oldrm; - rfmt = w_fmt; - goto copcsr; - } -#endif - -#if __mips64 && !defined(SINGLE_ONLY_FPU) - case fcvtl_op: - { - ieee754dp fs; - - DPFROMREG(fs, MIPSInst_FS(ir)); - rv.l = ieee754dp_tlong(fs); - rfmt = l_fmt; - goto copcsr; - } - - case froundl_op: - case ftruncl_op: - case fceill_op: - case ffloorl_op: - { - unsigned int oldrm = ieee754_csr.rm; - ieee754dp fs; - - DPFROMREG(fs, MIPSInst_FS(ir)); - ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3]; - rv.l = ieee754dp_tlong(fs); - ieee754_csr.rm = oldrm; - rfmt = l_fmt; - goto copcsr; - } -#endif /* __mips >= 3 && !fpu(single) */ - - default: - if (MIPSInst_FUNC(ir) >= fcmp_op) { - unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op; - ieee754dp fs, ft; - - DPFROMREG(fs, MIPSInst_FS(ir)); - DPFROMREG(ft, MIPSInst_FT(ir)); - rv.w = ieee754dp_cmp(fs, ft, cmptab[cmpop & 0x7]); - rfmt = -1; - if ((cmpop & 0x8) && ieee754_cxtest (IEEE754_INVALID_OPERATION)) - rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S; - } else { - return SIGILL; - } - break; - } - break; - } -#endif /* !defined(SINGLE_ONLY_FPU) */ - - case w_fmt: { - switch (MIPSInst_FUNC(ir)) { - case fcvts_op: - /* convert word to single precision real */ - rv.s = ieee754sp_fint(ctx-> regs[MIPSInst_FS(ir)]); - rfmt = s_fmt; - goto copcsr; -#if !defined(SINGLE_ONLY_FPU) - case fcvtd_op: - /* convert word to double precision real */ - rv.d = ieee754dp_fint(ctx-> regs[MIPSInst_FS(ir)]); - rfmt = d_fmt; - goto copcsr; -#endif - default: - return SIGILL; - } - break; - } - -#if __mips64 && !defined(SINGLE_ONLY_FPU) - case l_fmt: { - switch (MIPSInst_FUNC(ir)) { - case fcvts_op: - /* convert long to single precision real */ - rv.s = ieee754sp_flong(ctx-> regs[MIPSInst_FS(ir)]); - rfmt = s_fmt; - goto copcsr; - case fcvtd_op: - /* convert long to double precision real */ - rv.d = ieee754dp_flong(ctx-> regs[MIPSInst_FS(ir)]); - rfmt = d_fmt; - goto copcsr; - default: - return SIGILL; - } - break; - } -#endif - - default: - return SIGILL; - } - - /* - * Update the fpu CSR register for this operation. - * If an exception is required, generate a tidy SIGFPE exception, - * without updating the result register. - * Note: cause exception bits do not accumulate, they are rewritten - * for each op; only the flag/sticky bits accumulate. - */ - ctx->sr = (ctx->sr & ~FPU_CSR_ALL_X) | rcsr; - if ((ctx->sr >> 5) & ctx->sr & FPU_CSR_ALL_E) { - /*printk ("SIGFPE: fpu csr = %08x\n",ctx->sr); */ - return SIGFPE; - } - - /* - * Now we can safely write the result back to the register file. - */ - switch (rfmt) { - case -1: { -#if __mips >= 4 - cond = fpucondbit[MIPSInst_FD(ir) >> 2]; -#else - cond = FPU_CSR_COND; -#endif - if (rv.w) - ctx->sr |= cond; - else - ctx->sr &= ~cond; - break; - } -#if !defined(SINGLE_ONLY_FPU) - case d_fmt: - DPTOREG(rv.d, MIPSInst_FD(ir)); - break; -#endif - case s_fmt: - SPTOREG(rv.s, MIPSInst_FD(ir)); - break; - case w_fmt: - SITOREG(rv.w, MIPSInst_FD(ir)); - break; -#if __mips64 && !defined(SINGLE_ONLY_FPU) - case l_fmt: - DITOREG(rv.l, MIPSInst_FD(ir)); - break; -#endif - default: - return SIGILL; - } - - return 0; -} - - -/* - * Emulate the floating point instruction at EPC, and continue - * to run until we hit a non-fp instruction, or a backward - * branch. This cuts down dramatically on the per instruction - * exception overhead. - */ -int fpu_emulator_cop1Handler(int xcptno, struct pt_regs *xcp) -{ - struct mips_fpu_soft_struct *ctx = ¤t->thread.fpu.soft; - unsigned long oldepc, prevepc; - unsigned int insn; - int sig = 0; - int err = 0; - - oldepc = xcp->cp0_epc; - do { - cond_resched(); - - prevepc = xcp->cp0_epc; - insn = mips_get_word(xcp, REG_TO_VA(xcp->cp0_epc), &err); - if (err) { - fpuemuprivate.stats.errors++; - return SIGBUS; - } - if (insn != 0) - sig = cop1Emulate(xcptno, xcp, ctx); - else - xcp->cp0_epc += 4; /* skip nops */ - - if (mips_cpu.options & MIPS_CPU_FPU) - break; - } while (xcp->cp0_epc > prevepc && sig == 0); - - /* SIGILL indicates a non-fpu instruction */ - if (sig == SIGILL && xcp->cp0_epc != oldepc) - /* but if epc has advanced, then ignore it */ - sig = 0; - - return sig; -} - - -#ifdef NOTDEF -/* - * Patch up the hardware fpu state when an f.p. exception occurs. - */ -static int cop1Patcher(int xcptno, struct pt_regs *xcp) -{ - struct mips_fpu_soft_struct *ctx = ¤t->thread.fpu.soft; - unsigned sr; - int sig; - - /* reenable Cp1, else fpe_save() will get nested exception */ - sr = mips_bissr(ST0_CU1); - - /* get fpu registers and status, then clear pending exceptions */ - fpe_save(ctx); - fpe_setsr(ctx->sr &= ~FPU_CSR_ALL_X); - - /* get current rounding mode for IEEE library, and emulate insn */ - ieee754_csr.rm = ieee_rm[ctx->sr & 0x3]; - sig = cop1Emulate(xcptno, xcp, ctx); - - /* don't return with f.p. exceptions pending */ - ctx->sr &= ~FPU_CSR_ALL_X; - fpe_restore(ctx); - - mips_setsr(sr); - return sig; -} - -void _cop1_init(int emulate) -{ - extern int _nofpu; - - if (emulate) { - /* - * Install cop1 emulator to handle "coprocessor unusable" exception - */ - xcption(XCPTCPU, cop1Handler); - fpuemuactive = 1; /* tell dbg.c that we are in charge */ - _nofpu = 0; /* tell setjmp() it "has" an fpu */ - } else { - /* - * Install cop1 emulator for floating point exceptions only, - * i.e. denormalised results, underflow, overflow etc, which - * must be emulated in s/w. - */ -#ifdef 1 - /* r4000 or above use dedicate exception */ - xcption(XCPTFPE, cop1Patcher); -#else - /* r3000 et al use interrupt */ - extern int _sbd_getfpuintr(void); - int intno = _sbd_getfpuintr(); - intrupt(intno, cop1Patcher, 0); - mips_bissr(SR_IM0 << intno); -#endif - -#if (#cpu(r4640) || #cpu(r4650)) && !defined(SINGLE_ONLY_FPU) - /* For R4640/R4650 compiled *without* the -msingle-float flag, - then we share responsibility: the h/w handles the single - precision operations, and the trap emulator handles the - double precision. We set fpuemuactive so that dbg.c first - fetches the s/w state before saving the h/w state. */ - fpuemuactive = 1; - { - int i; - /* initialise the unused d.p high order words to be NaN */ - for (i = 0; i < 32; i++) - current->thread.fpu.soft.regs[i] = - 0x7ff80bad00000000LL; - } -#endif /* (r4640 || r4650) && !fpu(single) */ - } -} -#endif - diff -Nru a/arch/mips64/math-emu/dp_add.c b/arch/mips64/math-emu/dp_add.c --- a/arch/mips64/math-emu/dp_add.c Tue Jul 1 18:44:39 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,186 +0,0 @@ -/* IEEE754 floating point arithmetic - * double precision: common utilities - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - * - */ - - -#include "ieee754dp.h" - -ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y) -{ - COMPXDP; - COMPYDP; - - EXPLODEXDP; - EXPLODEYDP; - - CLEARCX; - - switch (CLPAIR(xc, yc)) { - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): - return ieee754dp_nanxcpt(ieee754dp_bestnan(x, y), "add", x, - y); - - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): - return ieee754dp_nanxcpt(y, "add", x, y); - - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - return ieee754dp_nanxcpt(x, "add", x, y); - - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): - return ieee754dp_bestnan(x, y); - - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): - return y; - - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF): - return x; - - - /* Inifity handling - */ - - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): - if (xs == ys) - return x; - SETCX(IEEE754_INVALID_OPERATION); - return ieee754dp_xcpt(ieee754dp_indef(), "add", x, y); - - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): - return y; - - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): - return x; - - /* Zero handling - */ - - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): - if (xs == ys) - return x; - else - return ieee754dp_zero(ieee754_csr.rm == - IEEE754_RD); - - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): - return x; - - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): - return y; - - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): - DPDNORMX; - - /* FALL THROUGH */ - - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): - DPDNORMY; - break; - - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM): - DPDNORMX; - break; - - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM): - break; - } - assert(xm & DP_HIDDEN_BIT); - assert(ym & DP_HIDDEN_BIT); - - /* provide guard,round and stick bit space */ - xm <<= 3; - ym <<= 3; - - if (xe > ye) { - /* have to shift y fraction right to align - */ - int s = xe - ye; - ym = XDPSRS(ym, s); - ye += s; - } else if (ye > xe) { - /* have to shift x fraction right to align - */ - int s = ye - xe; - xm = XDPSRS(xm, s); - xe += s; - } - assert(xe == ye); - assert(xe <= DP_EMAX); - - if (xs == ys) { - /* generate 28 bit result of adding two 27 bit numbers - * leaving result in xm,xs,xe - */ - xm = xm + ym; - xe = xe; - xs = xs; - - if (xm >> (DP_MBITS + 1 + 3)) { /* carry out */ - xm = XDPSRS1(xm); - xe++; - } - } else { - if (xm >= ym) { - xm = xm - ym; - xe = xe; - xs = xs; - } else { - xm = ym - xm; - xe = xe; - xs = ys; - } - if (xm == 0) - return ieee754dp_zero(ieee754_csr.rm == - IEEE754_RD); - - /* normalize to rounding precision */ - while ((xm >> (DP_MBITS + 3)) == 0) { - xm <<= 1; - xe--; - } - - } - DPNORMRET2(xs, xe, xm, "add", x, y); -} diff -Nru a/arch/mips64/math-emu/dp_cmp.c b/arch/mips64/math-emu/dp_cmp.c --- a/arch/mips64/math-emu/dp_cmp.c Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,58 +0,0 @@ -/* IEEE754 floating point arithmetic - * double precision: common utilities - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754dp.h" - -int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cmp) -{ - CLEARCX; - - if (ieee754dp_isnan(x) || ieee754dp_isnan(y)) { - if (cmp & IEEE754_CUN) - return 1; - if (cmp & (IEEE754_CLT | IEEE754_CGT)) { - if (SETCX(IEEE754_INVALID_OPERATION)) - return ieee754si_xcpt(0, "fcmpf", x); - } - return 0; - } else { - long long int vx = x.bits; - long long int vy = y.bits; - - if (vx < 0) - vx = -vx ^ DP_SIGN_BIT; - if (vy < 0) - vy = -vy ^ DP_SIGN_BIT; - - if (vx < vy) - return (cmp & IEEE754_CLT) != 0; - else if (vx == vy) - return (cmp & IEEE754_CEQ) != 0; - else - return (cmp & IEEE754_CGT) != 0; - } -} diff -Nru a/arch/mips64/math-emu/dp_div.c b/arch/mips64/math-emu/dp_div.c --- a/arch/mips64/math-emu/dp_div.c Tue Jul 1 18:44:31 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,160 +0,0 @@ -/* IEEE754 floating point arithmetic - * double precision: common utilities - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754dp.h" - -ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y) -{ - COMPXDP; - COMPYDP; - - CLEARCX; - - EXPLODEXDP; - EXPLODEYDP; - - switch (CLPAIR(xc, yc)) { - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): - return ieee754dp_nanxcpt(ieee754dp_bestnan(x, y), "div", x, - y); - - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): - return ieee754dp_nanxcpt(y, "div", x, y); - - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - return ieee754dp_nanxcpt(x, "div", x, y); - - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): - return ieee754dp_bestnan(x, y); - - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): - return y; - - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF): - return x; - - - /* Infinity handling - */ - - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): - SETCX(IEEE754_INVALID_OPERATION); - return ieee754dp_xcpt(ieee754dp_indef(), "div", x, y); - - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): - return ieee754dp_zero(xs ^ ys); - - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): - return ieee754dp_inf(xs ^ ys); - - /* Zero handling - */ - - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): - SETCX(IEEE754_INVALID_OPERATION); - return ieee754dp_xcpt(ieee754dp_indef(), "div", x, y); - - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): - SETCX(IEEE754_ZERO_DIVIDE); - return ieee754dp_xcpt(ieee754dp_inf(xs ^ ys), "div", x, y); - - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): - return ieee754dp_zero(xs == ys ? 0 : 1); - - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): - DPDNORMX; - - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): - DPDNORMY; - break; - - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM): - DPDNORMX; - break; - - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM): - break; - } - assert(xm & DP_HIDDEN_BIT); - assert(ym & DP_HIDDEN_BIT); - - /* provide rounding space */ - xm <<= 3; - ym <<= 3; - - { - /* now the dirty work */ - - unsigned long long rm = 0; - int re = xe - ye; - unsigned long long bm; - - for (bm = DP_MBIT(DP_MBITS + 2); bm; bm >>= 1) { - if (xm >= ym) { - xm -= ym; - rm |= bm; - if (xm == 0) - break; - } - xm <<= 1; - } - rm <<= 1; - if (xm) - rm |= 1; /* have remainder, set sticky */ - - assert(rm); - - /* normalise rm to rounding precision ? - */ - while ((rm >> (DP_MBITS + 3)) == 0) { - rm <<= 1; - re--; - } - - DPNORMRET2(xs == ys ? 0 : 1, re, rm, "div", x, y); - } -} diff -Nru a/arch/mips64/math-emu/dp_fint.c b/arch/mips64/math-emu/dp_fint.c --- a/arch/mips64/math-emu/dp_fint.c Tue Jul 1 18:44:36 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,78 +0,0 @@ -/* IEEE754 floating point arithmetic - * double precision: common utilities - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754dp.h" - -ieee754dp ieee754dp_fint(int x) -{ - COMPXDP; - - CLEARCX; - - if (x == 0) - return ieee754dp_zero(0); - if (x == 1 || x == -1) - return ieee754dp_one(x < 0); - if (x == 10 || x == -10) - return ieee754dp_ten(x < 0); - - xs = (x < 0); - if (xs) { - if (x == (1 << 31)) - xm = ((unsigned) 1 << 31); /* max neg can't be safely negated */ - else - xm = -x; - } else { - xm = x; - } - -#if 1 - /* normalize - result can never be inexact or overflow */ - xe = DP_MBITS; - while ((xm >> DP_MBITS) == 0) { - xm <<= 1; - xe--; - } - return builddp(xs, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT); -#else - /* normalize */ - xe = DP_MBITS + 3; - while ((xm >> (DP_MBITS + 3)) == 0) { - xm <<= 1; - xe--; - } - DPNORMRET1(xs, xe, xm, "fint", x); -#endif -} - -ieee754dp ieee754dp_funs(unsigned int u) -{ - if ((int) u < 0) - return ieee754dp_add(ieee754dp_1e31(), - ieee754dp_fint(u & ~(1 << 31))); - return ieee754dp_fint(u); -} diff -Nru a/arch/mips64/math-emu/dp_flong.c b/arch/mips64/math-emu/dp_flong.c --- a/arch/mips64/math-emu/dp_flong.c Tue Jul 1 18:44:37 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,76 +0,0 @@ -/* IEEE754 floating point arithmetic - * double precision: common utilities - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754dp.h" - -ieee754dp ieee754dp_flong(long long x) -{ - COMPXDP; - - CLEARCX; - - if (x == 0) - return ieee754dp_zero(0); - if (x == 1 || x == -1) - return ieee754dp_one(x < 0); - if (x == 10 || x == -10) - return ieee754dp_ten(x < 0); - - xs = (x < 0); - if (xs) { - if (x == (1ULL << 63)) - xm = (1ULL << 63); /* max neg can't be safely negated */ - else - xm = -x; - } else { - xm = x; - } - - /* normalize */ - xe = DP_MBITS + 3; - if (xm >> (DP_MBITS + 1 + 3)) { - /* shunt out overflow bits */ - while (xm >> (DP_MBITS + 1 + 3)) { - XDPSRSX1(); - } - } else { - /* normalize in grs extended double precision */ - while ((xm >> (DP_MBITS + 3)) == 0) { - xm <<= 1; - xe--; - } - } - DPNORMRET1(xs, xe, xm, "dp_flong", x); -} - -ieee754dp ieee754dp_fulong(unsigned long long u) -{ - if ((long long) u < 0) - return ieee754dp_add(ieee754dp_1e63(), - ieee754dp_flong(u & ~(1ULL << 63))); - return ieee754dp_flong(u); -} diff -Nru a/arch/mips64/math-emu/dp_frexp.c b/arch/mips64/math-emu/dp_frexp.c --- a/arch/mips64/math-emu/dp_frexp.c Tue Jul 1 18:44:31 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,53 +0,0 @@ -/* IEEE754 floating point arithmetic - * double precision: common utilities - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754dp.h" - -/* close to ieeep754dp_logb -*/ -ieee754dp ieee754dp_frexp(ieee754dp x, int *eptr) -{ - COMPXDP; - CLEARCX; - EXPLODEXDP; - - switch (xc) { - case IEEE754_CLASS_SNAN: - case IEEE754_CLASS_QNAN: - case IEEE754_CLASS_INF: - case IEEE754_CLASS_ZERO: - *eptr = 0; - return x; - case IEEE754_CLASS_DNORM: - DPDNORMX; - break; - case IEEE754_CLASS_NORM: - break; - } - *eptr = xe + 1; - return builddp(xs, -1 + DP_EBIAS, xm & ~DP_HIDDEN_BIT); -} diff -Nru a/arch/mips64/math-emu/dp_fsp.c b/arch/mips64/math-emu/dp_fsp.c --- a/arch/mips64/math-emu/dp_fsp.c Tue Jul 1 18:44:35 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,70 +0,0 @@ -/* IEEE754 floating point arithmetic - * double precision: common utilities - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754dp.h" - -ieee754dp ieee754dp_fsp(ieee754sp x) -{ - COMPXSP; - - CLEARCX; - - EXPLODEXSP; - - switch (xc) { - case IEEE754_CLASS_QNAN: - case IEEE754_CLASS_SNAN: - return ieee754dp_nanxcpt(builddp(xs, - DP_EMAX + 1 + DP_EBIAS, - ((unsigned long long) xm - << (DP_MBITS - - SP_MBITS))), "fsp", - x); - case IEEE754_CLASS_INF: - return ieee754dp_inf(xs); - case IEEE754_CLASS_ZERO: - return ieee754dp_zero(xs); - case IEEE754_CLASS_DNORM: - /* normalize */ - while ((xm >> SP_MBITS) == 0) { - xm <<= 1; - xe--; - } - break; - case IEEE754_CLASS_NORM: - break; - } - - /* CANT possibly overflow,underflow, or need rounding - */ - - /* drop the hidden bit */ - xm &= ~SP_HIDDEN_BIT; - - return builddp(xs, xe + DP_EBIAS, - (unsigned long long) xm << (DP_MBITS - SP_MBITS)); -} diff -Nru a/arch/mips64/math-emu/dp_logb.c b/arch/mips64/math-emu/dp_logb.c --- a/arch/mips64/math-emu/dp_logb.c Tue Jul 1 18:44:33 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,54 +0,0 @@ -/* IEEE754 floating point arithmetic - * double precision: common utilities - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754dp.h" - -ieee754dp ieee754dp_logb(ieee754dp x) -{ - COMPXDP; - - CLEARCX; - - EXPLODEXDP; - - switch (xc) { - case IEEE754_CLASS_SNAN: - return ieee754dp_nanxcpt(x, "logb", x); - case IEEE754_CLASS_QNAN: - return x; - case IEEE754_CLASS_INF: - return ieee754dp_inf(0); - case IEEE754_CLASS_ZERO: - return ieee754dp_inf(1); - case IEEE754_CLASS_DNORM: - DPDNORMX; - break; - case IEEE754_CLASS_NORM: - break; - } - return ieee754dp_fint(xe); -} diff -Nru a/arch/mips64/math-emu/dp_modf.c b/arch/mips64/math-emu/dp_modf.c --- a/arch/mips64/math-emu/dp_modf.c Tue Jul 1 18:44:31 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,80 +0,0 @@ -/* IEEE754 floating point arithmetic - * double precision: common utilities - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754dp.h" - -/* modf function is always exact for a finite number -*/ -ieee754dp ieee754dp_modf(ieee754dp x, ieee754dp * ip) -{ - COMPXDP; - - CLEARCX; - - EXPLODEXDP; - - switch (xc) { - case IEEE754_CLASS_SNAN: - case IEEE754_CLASS_QNAN: - case IEEE754_CLASS_INF: - case IEEE754_CLASS_ZERO: - *ip = x; - return x; - case IEEE754_CLASS_DNORM: - /* far to small */ - *ip = ieee754dp_zero(xs); - return x; - case IEEE754_CLASS_NORM: - break; - } - if (xe < 0) { - *ip = ieee754dp_zero(xs); - return x; - } - if (xe >= DP_MBITS) { - *ip = x; - return ieee754dp_zero(xs); - } - /* generate ipart mantissa by clearing bottom bits - */ - *ip = builddp(xs, xe + DP_EBIAS, - ((xm >> (DP_MBITS - xe)) << (DP_MBITS - xe)) & - ~DP_HIDDEN_BIT); - - /* generate fpart mantissa by clearing top bits - * and normalizing (must be able to normalize) - */ - xm = (xm << (64 - (DP_MBITS - xe))) >> (64 - (DP_MBITS - xe)); - if (xm == 0) - return ieee754dp_zero(xs); - - while ((xm >> DP_MBITS) == 0) { - xm <<= 1; - xe--; - } - return builddp(xs, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT); -} diff -Nru a/arch/mips64/math-emu/dp_mul.c b/arch/mips64/math-emu/dp_mul.c --- a/arch/mips64/math-emu/dp_mul.c Tue Jul 1 18:44:39 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,180 +0,0 @@ -/* IEEE754 floating point arithmetic - * double precision: common utilities - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754dp.h" - -ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y) -{ - COMPXDP; - COMPYDP; - - CLEARCX; - - EXPLODEXDP; - EXPLODEYDP; - - switch (CLPAIR(xc, yc)) { - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): - return ieee754dp_nanxcpt(ieee754dp_bestnan(x, y), "mul", x, - y); - - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): - return ieee754dp_nanxcpt(y, "mul", x, y); - - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - return ieee754dp_nanxcpt(x, "mul", x, y); - - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): - return ieee754dp_bestnan(x, y); - - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): - return y; - - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF): - return x; - - - /* Infinity handling */ - - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): - SETCX(IEEE754_INVALID_OPERATION); - return ieee754dp_xcpt(ieee754dp_indef(), "mul", x, y); - - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): - return ieee754dp_inf(xs ^ ys); - - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): - return ieee754dp_zero(xs ^ ys); - - - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): - DPDNORMX; - - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): - DPDNORMY; - break; - - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM): - DPDNORMX; - break; - - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM): - break; - } - /* rm = xm * ym, re = xe+ye basicly */ - assert(xm & DP_HIDDEN_BIT); - assert(ym & DP_HIDDEN_BIT); - { - int re = xe + ye; - int rs = xs ^ ys; - unsigned long long rm; - - /* shunt to top of word */ - xm <<= 64 - (DP_MBITS + 1); - ym <<= 64 - (DP_MBITS + 1); - - /* multiply 32bits xm,ym to give high 32bits rm with stickness - */ - - /* 32 * 32 => 64 */ -#define DPXMULT(x,y) ((unsigned long long)(x) * (unsigned long long)y) - - { - unsigned lxm = xm; - unsigned hxm = xm >> 32; - unsigned lym = ym; - unsigned hym = ym >> 32; - unsigned long long lrm; - unsigned long long hrm; - - lrm = DPXMULT(lxm, lym); - hrm = DPXMULT(hxm, hym); - - { - unsigned long long t = DPXMULT(lxm, hym); - { - unsigned long long at = - lrm + (t << 32); - hrm += at < lrm; - lrm = at; - } - hrm = hrm + (t >> 32); - } - - { - unsigned long long t = DPXMULT(hxm, lym); - { - unsigned long long at = - lrm + (t << 32); - hrm += at < lrm; - lrm = at; - } - hrm = hrm + (t >> 32); - } - rm = hrm | (lrm != 0); - } - - /* - * sticky shift down to normal rounding precision - */ - if ((signed long long) rm < 0) { - rm = - (rm >> (64 - (DP_MBITS + 1 + 3))) | - ((rm << (DP_MBITS + 1 + 3)) != 0); - re++; - } else { - rm = - (rm >> (64 - (DP_MBITS + 1 + 3 + 1))) | - ((rm << (DP_MBITS + 1 + 3 + 1)) != 0); - } - assert(rm & (DP_HIDDEN_BIT << 3)); - DPNORMRET2(rs, re, rm, "mul", x, y); - } -} diff -Nru a/arch/mips64/math-emu/dp_scalb.c b/arch/mips64/math-emu/dp_scalb.c --- a/arch/mips64/math-emu/dp_scalb.c Tue Jul 1 18:44:32 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,58 +0,0 @@ -/* IEEE754 floating point arithmetic - * double precision: common utilities - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754dp.h" - -ieee754dp ieee754dp_scalb(ieee754dp x, int n) -{ - COMPXDP; - - CLEARCX; - - EXPLODEXDP; - - switch (xc) { - case IEEE754_CLASS_SNAN: - return ieee754dp_nanxcpt(x, "scalb", x, n); - case IEEE754_CLASS_QNAN: - case IEEE754_CLASS_INF: - case IEEE754_CLASS_ZERO: - return x; - case IEEE754_CLASS_DNORM: - DPDNORMX; - break; - case IEEE754_CLASS_NORM: - break; - } - DPNORMRET2(xs, xe + n, xm << 3, "scalb", x, n); -} - - -ieee754dp ieee754dp_ldexp(ieee754dp x, int n) -{ - return ieee754dp_scalb(x, n); -} diff -Nru a/arch/mips64/math-emu/dp_simple.c b/arch/mips64/math-emu/dp_simple.c --- a/arch/mips64/math-emu/dp_simple.c Tue Jul 1 18:44:37 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,66 +0,0 @@ -/* IEEE754 floating point arithmetic - * double precision: common utilities - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754dp.h" - -int ieee754dp_finite(ieee754dp x) -{ - return DPBEXP(x) != DP_EMAX + 1 + DP_EBIAS; -} - -ieee754dp ieee754dp_copysign(ieee754dp x, ieee754dp y) -{ - CLEARCX; - DPSIGN(x) = DPSIGN(y); - return x; -} - - -ieee754dp ieee754dp_neg(ieee754dp x) -{ - CLEARCX; - - if (ieee754dp_isnan(x)) /* but not infinity */ - return ieee754dp_nanxcpt(x, "neg", x); - - /* quick fix up */ - DPSIGN(x) ^= 1; - return x; -} - - -ieee754dp ieee754dp_abs(ieee754dp x) -{ - CLEARCX; - - if (ieee754dp_isnan(x)) /* but not infinity */ - return ieee754dp_nanxcpt(x, "abs", x); - - /* quick fix up */ - DPSIGN(x) = 0; - return x; -} diff -Nru a/arch/mips64/math-emu/dp_sqrt.c b/arch/mips64/math-emu/dp_sqrt.c --- a/arch/mips64/math-emu/dp_sqrt.c Tue Jul 1 18:44:31 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,167 +0,0 @@ -/* IEEE754 floating point arithmetic - * double precision square root - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754dp.h" - -static const struct ieee754dp_konst knan = { -#if (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) || defined(__MIPSEL__) - 0, 0, DP_EBIAS + DP_EMAX + 1, 0 -#else - 0, DP_EBIAS + DP_EMAX + 1, 0, 0 -#endif -}; - -#define nan ((ieee754dp)knan) - -static const unsigned table[] = { - 0, 1204, 3062, 5746, 9193, 13348, 18162, 23592, - 29598, 36145, 43202, 50740, 58733, 67158, 75992, - 85215, 83599, 71378, 60428, 50647, 41945, 34246, - 27478, 21581, 16499, 12183, 8588, 5674, 3403, - 1742, 661, 130 -}; - -ieee754dp ieee754dp_sqrt(ieee754dp x) -{ - struct ieee754_csr oldcsr; - ieee754dp y, z, t; - unsigned scalx, yh; - COMPXDP; - - EXPLODEXDP; - - /* x == INF or NAN? */ - switch (xc) { - case IEEE754_CLASS_QNAN: - case IEEE754_CLASS_SNAN: - /* sqrt(Nan) = Nan */ - return ieee754dp_nanxcpt(x, "sqrt"); - case IEEE754_CLASS_ZERO: - /* sqrt(0) = 0 */ - return x; - case IEEE754_CLASS_INF: - if (xs) - /* sqrt(-Inf) = Nan */ - return ieee754dp_nanxcpt(nan, "sqrt"); - /* sqrt(+Inf) = Inf */ - return x; - case IEEE754_CLASS_DNORM: - DPDNORMX; - /* fall through */ - case IEEE754_CLASS_NORM: - if (xs) - /* sqrt(-x) = Nan */ - return ieee754dp_nanxcpt(nan, "sqrt"); - break; - } - - /* save old csr; switch off INX enable & flag; set RN rounding */ - oldcsr = ieee754_csr; - ieee754_csr.mx &= ~IEEE754_INEXACT; - ieee754_csr.sx &= ~IEEE754_INEXACT; - ieee754_csr.rm = IEEE754_RN; - - /* adjust exponent to prevent overflow */ - scalx = 0; - if (xe > 512) { /* x > 2**-512? */ - xe -= 512; /* x = x / 2**512 */ - scalx += 256; - } else if (xe < -512) { /* x < 2**-512? */ - xe += 512; /* x = x * 2**512 */ - scalx -= 256; - } - - y = x = builddp(0, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT); - - /* magic initial approximation to almost 8 sig. bits */ - yh = y.bits >> 32; - yh = (yh >> 1) + 0x1ff80000; - yh = yh - table[(yh >> 15) & 31]; - y.bits = ((unsigned long long) yh << 32) | (y.bits & 0xffffffff); - - /* Heron's rule once with correction to improve to ~18 sig. bits */ - /* t=x/y; y=y+t; py[n0]=py[n0]-0x00100006; py[n1]=0; */ - t = ieee754dp_div(x, y); - y = ieee754dp_add(y, t); - y.bits -= 0x0010000600000000LL; - y.bits &= 0xffffffff00000000LL; - - /* triple to almost 56 sig. bits: y ~= sqrt(x) to within 1 ulp */ - /* t=y*y; z=t; pt[n0]+=0x00100000; t+=z; z=(x-z)*y; */ - z = t = ieee754dp_mul(y, y); - t.parts.bexp += 0x001; - t = ieee754dp_add(t, z); - z = ieee754dp_mul(ieee754dp_sub(x, z), y); - - /* t=z/(t+x) ; pt[n0]+=0x00100000; y+=t; */ - t = ieee754dp_div(z, ieee754dp_add(t, x)); - t.parts.bexp += 0x001; - y = ieee754dp_add(y, t); - - /* twiddle last bit to force y correctly rounded */ - - /* set RZ, clear INEX flag */ - ieee754_csr.rm = IEEE754_RZ; - ieee754_csr.sx &= ~IEEE754_INEXACT; - - /* t=x/y; ...chopped quotient, possibly inexact */ - t = ieee754dp_div(x, y); - - if (ieee754_csr.sx & IEEE754_INEXACT || t.bits != y.bits) { - - if (!(ieee754_csr.sx & IEEE754_INEXACT)) - /* t = t-ulp */ - t.bits -= 1; - - /* add inexact to result status */ - oldcsr.cx |= IEEE754_INEXACT; - oldcsr.sx |= IEEE754_INEXACT; - - switch (oldcsr.rm) { - case IEEE754_RP: - y.bits += 1; - /* drop through */ - case IEEE754_RN: - t.bits += 1; - break; - } - - /* y=y+t; ...chopped sum */ - y = ieee754dp_add(y, t); - - /* adjust scalx for correctly rounded sqrt(x) */ - scalx -= 1; - } - - /* py[n0]=py[n0]+scalx; ...scale back y */ - y.parts.bexp += scalx; - - /* restore rounding mode, possibly set inexact */ - ieee754_csr = oldcsr; - - return y; -} diff -Nru a/arch/mips64/math-emu/dp_sub.c b/arch/mips64/math-emu/dp_sub.c --- a/arch/mips64/math-emu/dp_sub.c Tue Jul 1 18:44:35 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,194 +0,0 @@ -/* IEEE754 floating point arithmetic - * double precision: common utilities - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754dp.h" - -ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y) -{ - COMPXDP; - COMPYDP; - - CLEARCX; - - EXPLODEXDP; - EXPLODEYDP; - - switch (CLPAIR(xc, yc)) { - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): - return ieee754dp_nanxcpt(ieee754dp_bestnan(x, y), "sub", x, - y); - - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): - return ieee754dp_nanxcpt(y, "sub", x, y); - - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - return ieee754dp_nanxcpt(x, "sub", x, y); - - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): - return ieee754dp_bestnan(x, y); - - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): - return y; - - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF): - return x; - - - /* Inifity handling - */ - - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): - if (xs != ys) - return x; - SETCX(IEEE754_INVALID_OPERATION); - return ieee754dp_xcpt(ieee754dp_indef(), "sub", x, y); - - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): - return ieee754dp_inf(ys ^ 1); - - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): - return x; - - /* Zero handling - */ - - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): - if (xs != ys) - return x; - else - return ieee754dp_zero(ieee754_csr.rm == - IEEE754_RD); - - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): - return x; - - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): - /* quick fix up */ - DPSIGN(y) ^= 1; - return y; - - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): - DPDNORMX; - /* FAAL THOROUGH */ - - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): - /* normalize ym,ye */ - DPDNORMY; - break; - - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM): - /* normalize xm,xe */ - DPDNORMX; - break; - - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM): - break; - } - /* flip sign of y and handle as add */ - ys ^= 1; - - assert(xm & DP_HIDDEN_BIT); - assert(ym & DP_HIDDEN_BIT); - - - /* provide guard,round and stick bit dpace */ - xm <<= 3; - ym <<= 3; - - if (xe > ye) { - /* have to shift y fraction right to align - */ - int s = xe - ye; - ym = XDPSRS(ym, s); - ye += s; - } else if (ye > xe) { - /* have to shift x fraction right to align - */ - int s = ye - xe; - xm = XDPSRS(xm, s); - xe += s; - } - assert(xe == ye); - assert(xe <= DP_EMAX); - - if (xs == ys) { - /* generate 28 bit result of adding two 27 bit numbers - */ - xm = xm + ym; - xe = xe; - xs = xs; - - if (xm >> (DP_MBITS + 1 + 3)) { /* carry out */ - xm = XDPSRS1(xm); /* shift preserving sticky */ - xe++; - } - } else { - if (xm >= ym) { - xm = xm - ym; - xe = xe; - xs = xs; - } else { - xm = ym - xm; - xe = xe; - xs = ys; - } - if (xm == 0) { - if (ieee754_csr.rm == IEEE754_RD) - return ieee754dp_zero(1); /* round negative inf. => sign = -1 */ - else - return ieee754dp_zero(0); /* other round modes => sign = 1 */ - } - - /* normalize to rounding precision - */ - while ((xm >> (DP_MBITS + 3)) == 0) { - xm <<= 1; - xe--; - } - } - DPNORMRET2(xs, xe, xm, "sub", x, y); -} diff -Nru a/arch/mips64/math-emu/dp_tint.c b/arch/mips64/math-emu/dp_tint.c --- a/arch/mips64/math-emu/dp_tint.c Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,88 +0,0 @@ -/* IEEE754 floating point arithmetic - * double precision: common utilities - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include -#include "ieee754dp.h" - -int ieee754dp_tint(ieee754dp x) -{ - COMPXDP; - - CLEARCX; - - EXPLODEXDP; - - switch (xc) { - case IEEE754_CLASS_SNAN: - case IEEE754_CLASS_QNAN: - SETCX(IEEE754_INVALID_OPERATION); - return ieee754si_xcpt(ieee754si_indef(), "fixdp", x); - case IEEE754_CLASS_INF: - SETCX(IEEE754_OVERFLOW); - return ieee754si_xcpt(ieee754si_indef(), "fixdp", x); - case IEEE754_CLASS_ZERO: - return 0; - case IEEE754_CLASS_DNORM: /* much to small */ - SETCX(IEEE754_UNDERFLOW); - return ieee754si_xcpt(0, "fixdp", x); - case IEEE754_CLASS_NORM: - break; - } - if (xe >= 31) { - SETCX(IEEE754_OVERFLOW); - return ieee754si_xcpt(ieee754si_indef(), "fix", x); - } - if (xe < 0) { - SETCX(IEEE754_UNDERFLOW); - return ieee754si_xcpt(0, "fix", x); - } - /* oh gawd */ - if (xe > DP_MBITS) { - xm <<= xe - DP_MBITS; - } else if (xe < DP_MBITS) { - /* XXX no rounding - */ - xm >>= DP_MBITS - xe; - } - if (xs) - return -xm; - else - return xm; -} - - -unsigned int ieee754dp_tuns(ieee754dp x) -{ - ieee754dp hb = ieee754dp_1e31(); - - /* what if x < 0 ?? */ - if (ieee754dp_lt(x, hb)) - return (unsigned) ieee754dp_tint(x); - - return (unsigned) ieee754dp_tint(ieee754dp_sub(x, hb)) | - ((unsigned) 1 << 31); -} diff -Nru a/arch/mips64/math-emu/dp_tlong.c b/arch/mips64/math-emu/dp_tlong.c --- a/arch/mips64/math-emu/dp_tlong.c Tue Jul 1 18:44:37 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,141 +0,0 @@ -/* IEEE754 floating point arithmetic - * double precision: common utilities - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754dp.h" - -long long ieee754dp_tlong(ieee754dp x) -{ - COMPXDP; - - CLEARCX; - - EXPLODEXDP; - - switch (xc) { - case IEEE754_CLASS_SNAN: - case IEEE754_CLASS_QNAN: - SETCX(IEEE754_INVALID_OPERATION); - return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x); - case IEEE754_CLASS_INF: - SETCX(IEEE754_OVERFLOW); - return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x); - case IEEE754_CLASS_ZERO: - return 0; - case IEEE754_CLASS_DNORM: /* much too small */ - SETCX(IEEE754_UNDERFLOW); - return ieee754di_xcpt(0, "dp_tlong", x); - case IEEE754_CLASS_NORM: - break; - } - if (xe >= 63) { - SETCX(IEEE754_OVERFLOW); - return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x); - } - if (xe < 0) { - if (ieee754_csr.rm == IEEE754_RU) { - if (xs) { /* Negative */ - return 0x0000000000000000LL; - } else { /* Positive */ - return 0x0000000000000001LL; - } - } else if (ieee754_csr.rm == IEEE754_RD) { - if (xs) { /* Negative , return -1 */ - return 0xffffffffffffffffLL; - } else { /* Positive */ - return 0x0000000000000000LL; - } - } else { - SETCX(IEEE754_UNDERFLOW); - return ieee754di_xcpt(0, "dp_tlong", x); - } - } - /* oh gawd */ - if (xe > DP_MBITS) { - xm <<= xe - DP_MBITS; - } else if (xe < DP_MBITS) { - unsigned long long residue; - unsigned long long mask = 0; - int i; - int round; - int sticky; - int odd; - - /* compute mask */ - for (i = 0; i < DP_MBITS - xe; i++) { - mask = mask << 1; - mask = mask | 0x1; - } - residue = (xm & mask) << (64 - (DP_MBITS - xe)); - round = - ((0x8000000000000000LL & residue) != - 0x0000000000000000LL); - sticky = - ((0x7fffffffffffffffLL & residue) != - 0x0000000000000000LL); - - xm >>= DP_MBITS - xe; - - odd = ((xm & 0x1) != 0x0000000000000000LL); - - /* Do the rounding */ - if (!round && sticky) { - if ((ieee754_csr.rm == IEEE754_RU && !xs) - || (ieee754_csr.rm == IEEE754_RD && xs)) { - xm++; - } - } else if (round && !sticky) { - if ((ieee754_csr.rm == IEEE754_RU && !xs) - || (ieee754_csr.rm == IEEE754_RD && xs) - || (ieee754_csr.rm == IEEE754_RN && odd)) { - xm++; - } - } else if (round && sticky) { - if ((ieee754_csr.rm == IEEE754_RU && !xs) - || (ieee754_csr.rm == IEEE754_RD && xs) - || (ieee754_csr.rm == IEEE754_RN)) { - xm++; - } - } - } - if (xs) - return -xm; - else - return xm; -} - - -unsigned long long ieee754dp_tulong(ieee754dp x) -{ - ieee754dp hb = ieee754dp_1e63(); - - /* what if x < 0 ?? */ - if (ieee754dp_lt(x, hb)) - return (unsigned long long) ieee754dp_tlong(x); - - return (unsigned long long) ieee754dp_tlong(ieee754dp_sub(x, hb)) | - (1ULL << 63); -} diff -Nru a/arch/mips64/math-emu/ieee754.c b/arch/mips64/math-emu/ieee754.c --- a/arch/mips64/math-emu/ieee754.c Tue Jul 1 18:44:33 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,138 +0,0 @@ -/* ieee754 floating point arithmetic - * single and double precision - * - * BUGS - * not much dp done - * doesn't generate IEEE754_INEXACT - * - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754int.h" - -#define DP_EBIAS 1023 -#define DP_EMIN (-1022) -#define DP_EMAX 1023 - -#define SP_EBIAS 127 -#define SP_EMIN (-126) -#define SP_EMAX 127 - -/* indexed by class */ -const char *const ieee754_cname[] = { - "Normal", - "Zero", - "Denormal", - "Infinity", - "QNaN", - "SNaN", -}; - -/* the control status register -*/ -struct ieee754_csr ieee754_csr; - -/* special constants -*/ - - -#if (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) || defined(__MIPSEL__) -#define SPSTR(s,b,m) {m,b,s} -#define DPSTR(s,b,mh,ml) {ml,mh,b,s} -#endif - -#ifdef __MIPSEB__ -#define SPSTR(s,b,m) {s,b,m} -#define DPSTR(s,b,mh,ml) {s,b,mh,ml} -#endif - -const struct ieee754dp_konst __ieee754dp_spcvals[] = { - DPSTR(0, DP_EMIN - 1 + DP_EBIAS, 0, 0), /* + zero */ - DPSTR(1, DP_EMIN - 1 + DP_EBIAS, 0, 0), /* - zero */ - DPSTR(0, DP_EBIAS, 0, 0), /* + 1.0 */ - DPSTR(1, DP_EBIAS, 0, 0), /* - 1.0 */ - DPSTR(0, 3 + DP_EBIAS, 0x40000, 0), /* + 10.0 */ - DPSTR(1, 3 + DP_EBIAS, 0x40000, 0), /* - 10.0 */ - DPSTR(0, DP_EMAX + 1 + DP_EBIAS, 0, 0), /* + infinity */ - DPSTR(1, DP_EMAX + 1 + DP_EBIAS, 0, 0), /* - infinity */ - DPSTR(0, DP_EMAX + 1 + DP_EBIAS, 0x40000, 0), /* + indef quiet Nan */ - DPSTR(0, DP_EMAX + DP_EBIAS, 0xFFFFF, 0xFFFFFFFF), /* + max */ - DPSTR(1, DP_EMAX + DP_EBIAS, 0xFFFFF, 0xFFFFFFFF), /* - max */ - DPSTR(0, DP_EMIN + DP_EBIAS, 0, 0), /* + min normal */ - DPSTR(1, DP_EMIN + DP_EBIAS, 0, 0), /* - min normal */ - DPSTR(0, DP_EMIN - 1 + DP_EBIAS, 0, 1), /* + min denormal */ - DPSTR(1, DP_EMIN - 1 + DP_EBIAS, 0, 1), /* - min denormal */ - DPSTR(0, 31 + DP_EBIAS, 0, 0), /* + 1.0e31 */ - DPSTR(0, 63 + DP_EBIAS, 0, 0), /* + 1.0e63 */ -}; - -const struct ieee754sp_konst __ieee754sp_spcvals[] = { - SPSTR(0, SP_EMIN - 1 + SP_EBIAS, 0), /* + zero */ - SPSTR(1, SP_EMIN - 1 + SP_EBIAS, 0), /* - zero */ - SPSTR(0, SP_EBIAS, 0), /* + 1.0 */ - SPSTR(1, SP_EBIAS, 0), /* - 1.0 */ - SPSTR(0, 3 + SP_EBIAS, 0x200000), /* + 10.0 */ - SPSTR(1, 3 + SP_EBIAS, 0x200000), /* - 10.0 */ - SPSTR(0, SP_EMAX + 1 + SP_EBIAS, 0), /* + infinity */ - SPSTR(1, SP_EMAX + 1 + SP_EBIAS, 0), /* - infinity */ - SPSTR(0, SP_EMAX + 1 + SP_EBIAS, 0x200000), /* + indef quiet Nan */ - SPSTR(0, SP_EMAX + SP_EBIAS, 0x7FFFFF), /* + max normal */ - SPSTR(1, SP_EMAX + SP_EBIAS, 0x7FFFFF), /* - max normal */ - SPSTR(0, SP_EMIN + SP_EBIAS, 0), /* + min normal */ - SPSTR(1, SP_EMIN + SP_EBIAS, 0), /* - min normal */ - SPSTR(0, SP_EMIN - 1 + SP_EBIAS, 1), /* + min denormal */ - SPSTR(1, SP_EMIN - 1 + SP_EBIAS, 1), /* - min denormal */ - SPSTR(0, 31 + SP_EBIAS, 0), /* + 1.0e31 */ - SPSTR(0, 63 + SP_EBIAS, 0), /* + 1.0e63 */ -}; - - -int ieee754si_xcpt(int r, const char *op, ...) -{ - struct ieee754xctx ax; - - if (!TSTX()) - return r; - ax.op = op; - ax.rt = IEEE754_RT_SI; - ax.rv.si = r; - va_start(ax.ap, op); - ieee754_xcpt(&ax); - return ax.rv.si; -} - -long long ieee754di_xcpt(long long r, const char *op, ...) -{ - struct ieee754xctx ax; - - if (!TSTX()) - return r; - ax.op = op; - ax.rt = IEEE754_RT_DI; - ax.rv.di = r; - va_start(ax.ap, op); - ieee754_xcpt(&ax); - return ax.rv.di; -} diff -Nru a/arch/mips64/math-emu/ieee754.h b/arch/mips64/math-emu/ieee754.h --- a/arch/mips64/math-emu/ieee754.h Tue Jul 1 18:44:38 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,490 +0,0 @@ -/* single and double precision fp ops - * missing extended precision. -*/ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - -/************************************************************************** - * Nov 7, 2000 - * Modification to allow integration with Linux kernel - * - * Kevin D. Kissell, kevink@mips.com and Carsten Langgard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - *************************************************************************/ - -#ifdef __KERNEL__ -/* Going from Algorithmics to Linux native environment, add this */ -#include - -/* - * Not very pretty, but the Linux kernel's normal va_list definition - * does not allow it to be used as a structure element, as it is here. - */ -#ifndef _STDARG_H -#include -#endif - -#else - -/* Note that __KERNEL__ is taken to mean Linux kernel */ - -#if #system(OpenBSD) -#include -#endif -#include - -#endif /* __KERNEL__ */ - -#if (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) || defined(__MIPSEL__) -struct ieee754dp_konst { - unsigned mantlo:32; - unsigned manthi:20; - unsigned bexp:11; - unsigned sign:1; -}; -struct ieee754sp_konst { - unsigned mant:23; - unsigned bexp:8; - unsigned sign:1; -}; - -typedef union _ieee754dp { - struct ieee754dp_konst oparts; - struct { - unsigned long long mant:52; - unsigned int bexp:11; - unsigned int sign:1; - } parts; - unsigned long long bits; - double d; -} ieee754dp; - -typedef union _ieee754sp { - struct ieee754sp_konst parts; - float f; - unsigned long bits; -} ieee754sp; -#endif - -#if (defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) || defined(__MIPSEB__) -struct ieee754dp_konst { - unsigned sign:1; - unsigned bexp:11; - unsigned manthi:20; - unsigned mantlo:32; -}; -typedef union _ieee754dp { - struct ieee754dp_konst oparts; - struct { - unsigned int sign:1; - unsigned int bexp:11; - unsigned long long mant:52; - } parts; - double d; - unsigned long long bits; -} ieee754dp; - -struct ieee754sp_konst { - unsigned sign:1; - unsigned bexp:8; - unsigned mant:23; -}; - -typedef union _ieee754sp { - struct ieee754sp_konst parts; - float f; - unsigned long bits; -} ieee754sp; -#endif - -/* - * single precision (often aka float) -*/ -int ieee754sp_finite(ieee754sp x); -int ieee754sp_class(ieee754sp x); - -ieee754sp ieee754sp_abs(ieee754sp x); -ieee754sp ieee754sp_neg(ieee754sp x); -ieee754sp ieee754sp_scalb(ieee754sp x, int); -ieee754sp ieee754sp_logb(ieee754sp x); - -/* x with sign of y */ -ieee754sp ieee754sp_copysign(ieee754sp x, ieee754sp y); - -ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y); -ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y); -ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y); -ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y); - -ieee754sp ieee754sp_fint(int x); -ieee754sp ieee754sp_funs(unsigned x); -ieee754sp ieee754sp_flong(long long x); -ieee754sp ieee754sp_fulong(unsigned long long x); -ieee754sp ieee754sp_fdp(ieee754dp x); - -int ieee754sp_tint(ieee754sp x); -unsigned int ieee754sp_tuns(ieee754sp x); -long long ieee754sp_tlong(ieee754sp x); -unsigned long long ieee754sp_tulong(ieee754sp x); - -int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cop); -/* - * basic sp math - */ -ieee754sp ieee754sp_modf(ieee754sp x, ieee754sp * ip); -ieee754sp ieee754sp_frexp(ieee754sp x, int *exp); -ieee754sp ieee754sp_ldexp(ieee754sp x, int exp); - -ieee754sp ieee754sp_ceil(ieee754sp x); -ieee754sp ieee754sp_floor(ieee754sp x); -ieee754sp ieee754sp_trunc(ieee754sp x); - -ieee754sp ieee754sp_sqrt(ieee754sp x); - -/* - * double precision (often aka double) -*/ -int ieee754dp_finite(ieee754dp x); -int ieee754dp_class(ieee754dp x); - -/* x with sign of y */ -ieee754dp ieee754dp_copysign(ieee754dp x, ieee754dp y); - -ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y); -ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y); -ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y); -ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y); - -ieee754dp ieee754dp_abs(ieee754dp x); -ieee754dp ieee754dp_neg(ieee754dp x); -ieee754dp ieee754dp_scalb(ieee754dp x, int); - -/* return exponent as integer in floating point format - */ -ieee754dp ieee754dp_logb(ieee754dp x); - -ieee754dp ieee754dp_fint(int x); -ieee754dp ieee754dp_funs(unsigned x); -ieee754dp ieee754dp_flong(long long x); -ieee754dp ieee754dp_fulong(unsigned long long x); -ieee754dp ieee754dp_fsp(ieee754sp x); - -ieee754dp ieee754dp_ceil(ieee754dp x); -ieee754dp ieee754dp_floor(ieee754dp x); -ieee754dp ieee754dp_trunc(ieee754dp x); - -int ieee754dp_tint(ieee754dp x); -unsigned int ieee754dp_tuns(ieee754dp x); -long long ieee754dp_tlong(ieee754dp x); -unsigned long long ieee754dp_tulong(ieee754dp x); - -int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cop); -/* - * basic sp math - */ -ieee754dp ieee754dp_modf(ieee754dp x, ieee754dp * ip); -ieee754dp ieee754dp_frexp(ieee754dp x, int *exp); -ieee754dp ieee754dp_ldexp(ieee754dp x, int exp); - -ieee754dp ieee754dp_ceil(ieee754dp x); -ieee754dp ieee754dp_floor(ieee754dp x); -ieee754dp ieee754dp_trunc(ieee754dp x); - -ieee754dp ieee754dp_sqrt(ieee754dp x); - - - -/* 5 types of floating point number -*/ -#define IEEE754_CLASS_NORM 0x00 -#define IEEE754_CLASS_ZERO 0x01 -#define IEEE754_CLASS_DNORM 0x02 -#define IEEE754_CLASS_INF 0x03 -#define IEEE754_CLASS_SNAN 0x04 -#define IEEE754_CLASS_QNAN 0x05 -extern const char *const ieee754_cname[]; - -/* exception numbers */ -#define IEEE754_INEXACT 0x01 -#define IEEE754_UNDERFLOW 0x02 -#define IEEE754_OVERFLOW 0x04 -#define IEEE754_ZERO_DIVIDE 0x08 -#define IEEE754_INVALID_OPERATION 0x10 - -/* cmp operators -*/ -#define IEEE754_CLT 0x01 -#define IEEE754_CEQ 0x02 -#define IEEE754_CGT 0x04 -#define IEEE754_CUN 0x08 - -/* rounding mode -*/ -#define IEEE754_RN 0 /* round to nearest */ -#define IEEE754_RZ 1 /* round toward zero */ -#define IEEE754_RD 2 /* round toward -Infinity */ -#define IEEE754_RU 3 /* round toward +Infinity */ - -/* other naming */ -#define IEEE754_RM IEEE754_RD -#define IEEE754_RP IEEE754_RU - -/* "normal" comparisons -*/ -static __inline int ieee754sp_eq(ieee754sp x, ieee754sp y) -{ - return ieee754sp_cmp(x, y, IEEE754_CEQ); -} - -static __inline int ieee754sp_ne(ieee754sp x, ieee754sp y) -{ - return ieee754sp_cmp(x, y, - IEEE754_CLT | IEEE754_CGT | IEEE754_CUN); -} - -static __inline int ieee754sp_lt(ieee754sp x, ieee754sp y) -{ - return ieee754sp_cmp(x, y, IEEE754_CLT); -} - -static __inline int ieee754sp_le(ieee754sp x, ieee754sp y) -{ - return ieee754sp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ); -} - -static __inline int ieee754sp_gt(ieee754sp x, ieee754sp y) -{ - return ieee754sp_cmp(x, y, IEEE754_CGT); -} - - -static __inline int ieee754sp_ge(ieee754sp x, ieee754sp y) -{ - return ieee754sp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ); -} - -static __inline int ieee754dp_eq(ieee754dp x, ieee754dp y) -{ - return ieee754dp_cmp(x, y, IEEE754_CEQ); -} - -static __inline int ieee754dp_ne(ieee754dp x, ieee754dp y) -{ - return ieee754dp_cmp(x, y, - IEEE754_CLT | IEEE754_CGT | IEEE754_CUN); -} - -static __inline int ieee754dp_lt(ieee754dp x, ieee754dp y) -{ - return ieee754dp_cmp(x, y, IEEE754_CLT); -} - -static __inline int ieee754dp_le(ieee754dp x, ieee754dp y) -{ - return ieee754dp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ); -} - -static __inline int ieee754dp_gt(ieee754dp x, ieee754dp y) -{ - return ieee754dp_cmp(x, y, IEEE754_CGT); -} - -static __inline int ieee754dp_ge(ieee754dp x, ieee754dp y) -{ - return ieee754dp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ); -} - - -/* like strtod -*/ -ieee754dp ieee754dp_fstr(const char *s, char **endp); -char *ieee754dp_tstr(ieee754dp x, int prec, int fmt, int af); - - -/* the control status register -*/ -struct ieee754_csr { - unsigned pad:13; - unsigned noq:1; /* set 1 for no quiet NaN's */ - unsigned nod:1; /* set 1 for no denormalised numbers */ - unsigned cx:5; /* exceptions this operation */ - unsigned mx:5; /* exception enable mask */ - unsigned sx:5; /* exceptions total */ - unsigned rm:2; /* current rounding mode */ -}; -extern struct ieee754_csr ieee754_csr; - -static __inline unsigned ieee754_getrm(void) -{ - return (ieee754_csr.rm); -} -static __inline unsigned ieee754_setrm(unsigned rm) -{ - return (ieee754_csr.rm = rm); -} - -/* - * get current exceptions - */ -static __inline unsigned ieee754_getcx(void) -{ - return (ieee754_csr.cx); -} - -/* test for current exception condition - */ -static __inline int ieee754_cxtest(unsigned n) -{ - return (ieee754_csr.cx & n); -} - -/* - * get sticky exceptions - */ -static __inline unsigned ieee754_getsx(void) -{ - return (ieee754_csr.sx); -} - -/* clear sticky conditions -*/ -static __inline unsigned ieee754_clrsx(void) -{ - return (ieee754_csr.sx = 0); -} - -/* test for sticky exception condition - */ -static __inline int ieee754_sxtest(unsigned n) -{ - return (ieee754_csr.sx & n); -} - -/* debugging */ -ieee754sp ieee754sp_dump(char *s, ieee754sp x); -ieee754dp ieee754dp_dump(char *s, ieee754dp x); - -#define IEEE754_SPCVAL_PZERO 0 -#define IEEE754_SPCVAL_NZERO 1 -#define IEEE754_SPCVAL_PONE 2 -#define IEEE754_SPCVAL_NONE 3 -#define IEEE754_SPCVAL_PTEN 4 -#define IEEE754_SPCVAL_NTEN 5 -#define IEEE754_SPCVAL_PINFINITY 6 -#define IEEE754_SPCVAL_NINFINITY 7 -#define IEEE754_SPCVAL_INDEF 8 -#define IEEE754_SPCVAL_PMAX 9 /* +max norm */ -#define IEEE754_SPCVAL_NMAX 10 /* -max norm */ -#define IEEE754_SPCVAL_PMIN 11 /* +min norm */ -#define IEEE754_SPCVAL_NMIN 12 /* +min norm */ -#define IEEE754_SPCVAL_PMIND 13 /* +min denorm */ -#define IEEE754_SPCVAL_NMIND 14 /* +min denorm */ -#define IEEE754_SPCVAL_P1E31 15 /* + 1.0e31 */ -#define IEEE754_SPCVAL_P1E63 16 /* + 1.0e63 */ - -extern const struct ieee754dp_konst __ieee754dp_spcvals[]; -extern const struct ieee754sp_konst __ieee754sp_spcvals[]; -#define ieee754dp_spcvals ((const ieee754dp *)__ieee754dp_spcvals) -#define ieee754sp_spcvals ((const ieee754sp *)__ieee754sp_spcvals) - -/* return infinity with given sign -*/ -#define ieee754dp_inf(sn) \ - (ieee754dp_spcvals[IEEE754_SPCVAL_PINFINITY+(sn)]) -#define ieee754dp_zero(sn) \ - (ieee754dp_spcvals[IEEE754_SPCVAL_PZERO+(sn)]) -#define ieee754dp_one(sn) \ - (ieee754dp_spcvals[IEEE754_SPCVAL_PONE+(sn)]) -#define ieee754dp_ten(sn) \ - (ieee754dp_spcvals[IEEE754_SPCVAL_PTEN+(sn)]) -#define ieee754dp_indef() \ - (ieee754dp_spcvals[IEEE754_SPCVAL_INDEF]) -#define ieee754dp_max(sn) \ - (ieee754dp_spcvals[IEEE754_SPCVAL_PMAX+(sn)]) -#define ieee754dp_min(sn) \ - (ieee754dp_spcvals[IEEE754_SPCVAL_PMIN+(sn)]) -#define ieee754dp_mind(sn) \ - (ieee754dp_spcvals[IEEE754_SPCVAL_PMIND+(sn)]) -#define ieee754dp_1e31() \ - (ieee754dp_spcvals[IEEE754_SPCVAL_P1E31]) -#define ieee754dp_1e63() \ - (ieee754dp_spcvals[IEEE754_SPCVAL_P1E63]) - -#define ieee754sp_inf(sn) \ - (ieee754sp_spcvals[IEEE754_SPCVAL_PINFINITY+(sn)]) -#define ieee754sp_zero(sn) \ - (ieee754sp_spcvals[IEEE754_SPCVAL_PZERO+(sn)]) -#define ieee754sp_one(sn) \ - (ieee754sp_spcvals[IEEE754_SPCVAL_PONE+(sn)]) -#define ieee754sp_ten(sn) \ - (ieee754sp_spcvals[IEEE754_SPCVAL_PTEN+(sn)]) -#define ieee754sp_indef() \ - (ieee754sp_spcvals[IEEE754_SPCVAL_INDEF]) -#define ieee754sp_max(sn) \ - (ieee754sp_spcvals[IEEE754_SPCVAL_PMAX+(sn)]) -#define ieee754sp_min(sn) \ - (ieee754sp_spcvals[IEEE754_SPCVAL_PMIN+(sn)]) -#define ieee754sp_mind(sn) \ - (ieee754sp_spcvals[IEEE754_SPCVAL_PMIND+(sn)]) -#define ieee754sp_1e31() \ - (ieee754sp_spcvals[IEEE754_SPCVAL_P1E31]) -#define ieee754sp_1e63() \ - (ieee754sp_spcvals[IEEE754_SPCVAL_P1E63]) - -/* indefinite integer value -*/ -#define ieee754si_indef() INT_MIN -#ifdef LONG_LONG_MIN -#define ieee754di_indef() LONG_LONG_MIN -#else -#define ieee754di_indef() (-9223372036854775807LL-1) -#endif - -/* IEEE exception context, passed to handler */ -struct ieee754xctx { - const char *op; /* operation name */ - int rt; /* result type */ - union { - ieee754sp sp; /* single precision */ - ieee754dp dp; /* double precision */ -#ifdef IEEE854_XP - ieee754xp xp; /* extended precision */ -#endif - int si; /* standard signed integer (32bits) */ - long long di; /* extended signed integer (64bits) */ - } rv; /* default result format implied by op */ - va_list ap; -}; - -/* result types for xctx.rt */ -#define IEEE754_RT_SP 0 -#define IEEE754_RT_DP 1 -#define IEEE754_RT_XP 2 -#define IEEE754_RT_SI 3 -#define IEEE754_RT_DI 4 - -extern void ieee754_xcpt(struct ieee754xctx *xcp); - -/* compat */ -#define ieee754dp_fix(x) ieee754dp_tint(x) -#define ieee754sp_fix(x) ieee754sp_tint(x) diff -Nru a/arch/mips64/math-emu/ieee754d.c b/arch/mips64/math-emu/ieee754d.c --- a/arch/mips64/math-emu/ieee754d.c Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,142 +0,0 @@ -/* some debug functions -*/ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - -/************************************************************************** - * Nov 7, 2000 - * Modified to build and operate in Linux kernel environment. - * - * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - *************************************************************************/ - -#include "ieee754.h" - -#define DP_EBIAS 1023 -#define DP_EMIN (-1022) -#define DP_EMAX 1023 -#define DP_FBITS 52 - -#define SP_EBIAS 127 -#define SP_EMIN (-126) -#define SP_EMAX 127 -#define SP_FBITS 23 - -#define DP_MBIT(x) ((unsigned long long)1 << (x)) -#define DP_HIDDEN_BIT DP_MBIT(DP_FBITS) -#define DP_SIGN_BIT DP_MBIT(63) - - -#define SP_MBIT(x) ((unsigned long)1 << (x)) -#define SP_HIDDEN_BIT SP_MBIT(SP_FBITS) -#define SP_SIGN_BIT SP_MBIT(31) - - -#define SPSIGN(sp) (sp.parts.sign) -#define SPBEXP(sp) (sp.parts.bexp) -#define SPMANT(sp) (sp.parts.mant) - -#define DPSIGN(dp) (dp.parts.sign) -#define DPBEXP(dp) (dp.parts.bexp) -#define DPMANT(dp) (dp.parts.mant) - -ieee754dp ieee754dp_dump(char *m, ieee754dp x) -{ - int i; - - printk("%s", m); - printk("<%08x,%08x>\n", (unsigned) (x.bits >> 32), - (unsigned) x.bits); - printk("\t="); - switch (ieee754dp_class(x)) { - case IEEE754_CLASS_QNAN: - case IEEE754_CLASS_SNAN: - printk("Nan %c", DPSIGN(x) ? '-' : '+'); - for (i = DP_FBITS - 1; i >= 0; i--) - printk("%c", DPMANT(x) & DP_MBIT(i) ? '1' : '0'); - break; - case IEEE754_CLASS_INF: - printk("%cInfinity", DPSIGN(x) ? '-' : '+'); - break; - case IEEE754_CLASS_ZERO: - printk("%cZero", DPSIGN(x) ? '-' : '+'); - break; - case IEEE754_CLASS_DNORM: - printk("%c0.", DPSIGN(x) ? '-' : '+'); - for (i = DP_FBITS - 1; i >= 0; i--) - printk("%c", DPMANT(x) & DP_MBIT(i) ? '1' : '0'); - printk("e%d", DPBEXP(x) - DP_EBIAS); - break; - case IEEE754_CLASS_NORM: - printk("%c1.", DPSIGN(x) ? '-' : '+'); - for (i = DP_FBITS - 1; i >= 0; i--) - printk("%c", DPMANT(x) & DP_MBIT(i) ? '1' : '0'); - printk("e%d", DPBEXP(x) - DP_EBIAS); - break; - default: - printk("Illegal/Unknown IEEE754 value class"); - } - printk("\n"); - return x; -} - -ieee754sp ieee754sp_dump(char *m, ieee754sp x) -{ - int i; - - printk("%s=", m); - printk("<%08x>\n", (unsigned) x.bits); - printk("\t="); - switch (ieee754sp_class(x)) { - case IEEE754_CLASS_QNAN: - case IEEE754_CLASS_SNAN: - printk("Nan %c", SPSIGN(x) ? '-' : '+'); - for (i = SP_FBITS - 1; i >= 0; i--) - printk("%c", SPMANT(x) & SP_MBIT(i) ? '1' : '0'); - break; - case IEEE754_CLASS_INF: - printk("%cInfinity", SPSIGN(x) ? '-' : '+'); - break; - case IEEE754_CLASS_ZERO: - printk("%cZero", SPSIGN(x) ? '-' : '+'); - break; - case IEEE754_CLASS_DNORM: - printk("%c0.", SPSIGN(x) ? '-' : '+'); - for (i = SP_FBITS - 1; i >= 0; i--) - printk("%c", SPMANT(x) & SP_MBIT(i) ? '1' : '0'); - printk("e%d", SPBEXP(x) - SP_EBIAS); - break; - case IEEE754_CLASS_NORM: - printk("%c1.", SPSIGN(x) ? '-' : '+'); - for (i = SP_FBITS - 1; i >= 0; i--) - printk("%c", SPMANT(x) & SP_MBIT(i) ? '1' : '0'); - printk("e%d", SPBEXP(x) - SP_EBIAS); - break; - default: - printk("Illegal/Unknown IEEE754 value class"); - } - printk("\n"); - return x; -} - diff -Nru a/arch/mips64/math-emu/ieee754dp.c b/arch/mips64/math-emu/ieee754dp.c --- a/arch/mips64/math-emu/ieee754dp.c Tue Jul 1 18:44:37 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,197 +0,0 @@ -/* IEEE754 floating point arithmetic - * double precision: common utilities - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754dp.h" - -int ieee754dp_class(ieee754dp x) -{ - COMPXDP; - EXPLODEXDP; - return xc; -} - -int ieee754dp_isnan(ieee754dp x) -{ - return ieee754dp_class(x) >= IEEE754_CLASS_SNAN; -} - -int ieee754dp_issnan(ieee754dp x) -{ - assert(ieee754dp_isnan(x)); - if (ieee754_csr.noq) - return 1; - return !(DPMANT(x) & DP_MBIT(DP_MBITS - 1)); -} - - -ieee754dp ieee754dp_xcpt(ieee754dp r, const char *op, ...) -{ - struct ieee754xctx ax; - if (!TSTX()) - return r; - - ax.op = op; - ax.rt = IEEE754_RT_DP; - ax.rv.dp = r; - va_start(ax.ap, op); - ieee754_xcpt(&ax); - return ax.rv.dp; -} - -ieee754dp ieee754dp_nanxcpt(ieee754dp r, const char *op, ...) -{ - struct ieee754xctx ax; - - assert(ieee754dp_isnan(r)); - - if (!ieee754dp_issnan(r)) /* QNAN does not cause invalid op !! */ - return r; - - if (!SETCX(IEEE754_INVALID_OPERATION)) { - /* not enabled convert to a quiet NaN */ - if (ieee754_csr.noq) - return r; - DPMANT(r) |= DP_MBIT(DP_MBITS - 1); - return r; - } - - ax.op = op; - ax.rt = 0; - ax.rv.dp = r; - va_start(ax.ap, op); - ieee754_xcpt(&ax); - return ax.rv.dp; -} - -ieee754dp ieee754dp_bestnan(ieee754dp x, ieee754dp y) -{ - assert(ieee754dp_isnan(x)); - assert(ieee754dp_isnan(y)); - - if (DPMANT(x) > DPMANT(y)) - return x; - else - return y; -} - - -/* generate a normal/denormal number with over,under handling - * sn is sign - * xe is an unbiased exponent - * xm is 3bit extended precision value. - */ -ieee754dp ieee754dp_format(int sn, int xe, unsigned long long xm) -{ - assert(xm); /* we don't gen exact zeros (probably should) */ - - assert((xm >> (DP_MBITS + 1 + 3)) == 0); /* no execess */ - assert(xm & (DP_HIDDEN_BIT << 3)); - - if (xe < DP_EMIN) { - /* strip lower bits */ - int es = DP_EMIN - xe; - - if (ieee754_csr.nod) { - SETCX(IEEE754_UNDERFLOW); - return ieee754dp_zero(sn); - } - - /* sticky right shift es bits - */ - xm = XDPSRS(xm, es); - xe += es; - - assert((xm & (DP_HIDDEN_BIT << 3)) == 0); - assert(xe == DP_EMIN); - } - if (xm & (DP_MBIT(3) - 1)) { - SETCX(IEEE754_INEXACT); - /* inexact must round of 3 bits - */ - switch (ieee754_csr.rm) { - case IEEE754_RZ: - break; - case IEEE754_RN: - xm += 0x3 + ((xm >> 3) & 1); - /* xm += (xm&0x8)?0x4:0x3 */ - break; - case IEEE754_RU: /* toward +Infinity */ - if (!sn) /* ?? */ - xm += 0x8; - break; - case IEEE754_RD: /* toward -Infinity */ - if (sn) /* ?? */ - xm += 0x8; - break; - } - /* adjust exponent for rounding add overflowing - */ - if (xm >> (DP_MBITS + 3 + 1)) { /* add causes mantissa overflow */ - xm >>= 1; - xe++; - } - } - /* strip grs bits */ - xm >>= 3; - - assert((xm >> (DP_MBITS + 1)) == 0); /* no execess */ - assert(xe >= DP_EMIN); - - if (xe > DP_EMAX) { - SETCX(IEEE754_OVERFLOW); - /* -O can be table indexed by (rm,sn) */ - switch (ieee754_csr.rm) { - case IEEE754_RN: - return ieee754dp_inf(sn); - case IEEE754_RZ: - return ieee754dp_max(sn); - case IEEE754_RU: /* toward +Infinity */ - if (sn == 0) - return ieee754dp_inf(0); - else - return ieee754dp_max(1); - case IEEE754_RD: /* toward -Infinity */ - if (sn == 0) - return ieee754dp_max(0); - else - return ieee754dp_inf(1); - } - } - /* gen norm/denorm/zero */ - - if ((xm & DP_HIDDEN_BIT) == 0) { - /* we underflow (tiny/zero) */ - assert(xe == DP_EMIN); - SETCX(IEEE754_UNDERFLOW); - return builddp(sn, DP_EMIN - 1 + DP_EBIAS, xm); - } else { - assert((xm >> (DP_MBITS + 1)) == 0); /* no execess */ - assert(xm & DP_HIDDEN_BIT); - - return builddp(sn, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT); - } -} diff -Nru a/arch/mips64/math-emu/ieee754dp.h b/arch/mips64/math-emu/ieee754dp.h --- a/arch/mips64/math-emu/ieee754dp.h Tue Jul 1 18:44:39 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,83 +0,0 @@ -/* - * IEEE754 floating point - * double precision internal header file - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754int.h" - -#define assert(expr) ((void)0) - -/* 3bit extended double precision sticky right shift */ -#define XDPSRS(v,rs) \ - ((rs > (DP_MBITS+3))?1:((v) >> (rs)) | ((v) << (64-(rs)) != 0)) - -#define XDPSRSX1() \ - (xe++, (xm = (xm >> 1) | (xm & 1))) - -#define XDPSRS1(v) \ - (((v) >> 1) | ((v) & 1)) - -/* convert denormal to normalized with extended exponent */ -#define DPDNORMx(m,e) \ - while( (m >> DP_MBITS) == 0) { m <<= 1; e--; } -#define DPDNORMX DPDNORMx(xm,xe) -#define DPDNORMY DPDNORMx(ym,ye) - -static __inline ieee754dp builddp(int s, int bx, unsigned long long m) -{ - ieee754dp r; - - assert((s) == 0 || (s) == 1); - assert((bx) >= DP_EMIN - 1 + DP_EBIAS - && (bx) <= DP_EMAX + 1 + DP_EBIAS); - assert(((m) >> DP_MBITS) == 0); - - r.parts.sign = s; - r.parts.bexp = bx; - r.parts.mant = m; - return r; -} - -extern int ieee754dp_isnan(ieee754dp); -extern int ieee754dp_issnan(ieee754dp); -extern int ieee754si_xcpt(int, const char *, ...); -extern long long ieee754di_xcpt(long long, const char *, ...); -extern ieee754dp ieee754dp_xcpt(ieee754dp, const char *, ...); -extern ieee754dp ieee754dp_nanxcpt(ieee754dp, const char *, ...); -extern ieee754dp ieee754dp_bestnan(ieee754dp, ieee754dp); -extern ieee754dp ieee754dp_format(int, int, unsigned long long); - - -#define DPNORMRET2(s,e,m,name,a0,a1) \ -{ \ - ieee754dp V = ieee754dp_format(s,e,m); \ - if(TSTX()) \ - return ieee754dp_xcpt(V,name,a0,a1); \ - else \ - return V; \ -} - -#define DPNORMRET1(s,e,m,name,a0) DPNORMRET2(s,e,m,name,a0,a0) diff -Nru a/arch/mips64/math-emu/ieee754int.h b/arch/mips64/math-emu/ieee754int.h --- a/arch/mips64/math-emu/ieee754int.h Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,135 +0,0 @@ -/* - * IEEE754 floating point - * common internal header file - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754.h" - -#define DP_EBIAS 1023 -#define DP_EMIN (-1022) -#define DP_EMAX 1023 -#define DP_MBITS 52 - -#define SP_EBIAS 127 -#define SP_EMIN (-126) -#define SP_EMAX 127 -#define SP_MBITS 23 - -#define DP_MBIT(x) ((unsigned long long)1 << (x)) -#define DP_HIDDEN_BIT DP_MBIT(DP_MBITS) -#define DP_SIGN_BIT DP_MBIT(63) - -#define SP_MBIT(x) ((unsigned long)1 << (x)) -#define SP_HIDDEN_BIT SP_MBIT(SP_MBITS) -#define SP_SIGN_BIT SP_MBIT(31) - - -#define SPSIGN(sp) (sp.parts.sign) -#define SPBEXP(sp) (sp.parts.bexp) -#define SPMANT(sp) (sp.parts.mant) - -#define DPSIGN(dp) (dp.parts.sign) -#define DPBEXP(dp) (dp.parts.bexp) -#define DPMANT(dp) (dp.parts.mant) - -#define CLPAIR(x,y) ((x)*6+(y)) - -#define CLEARCX \ - (ieee754_csr.cx = 0) - -#define SETCX(x) \ - (ieee754_csr.cx |= (x),ieee754_csr.sx |= (x),ieee754_csr.mx & (x)) - -#define TSTX() \ - (ieee754_csr.cx & ieee754_csr.mx) - - -#define COMPXSP \ - unsigned xm; int xe; int xs; int xc - -#define COMPYSP \ - unsigned ym; int ye; int ys; int yc - -#define EXPLODESP(v,vc,vs,ve,vm) \ -{\ - vs = SPSIGN(v);\ - ve = SPBEXP(v);\ - vm = SPMANT(v);\ - if(ve == SP_EMAX+1+SP_EBIAS){\ - if(vm == 0)\ - vc = IEEE754_CLASS_INF;\ - else if(vm & SP_MBIT(SP_MBITS-1)) \ - vc = IEEE754_CLASS_QNAN;\ - else \ - vc = IEEE754_CLASS_SNAN;\ - } else if(ve == SP_EMIN-1+SP_EBIAS) {\ - if(vm) {\ - ve = SP_EMIN;\ - vc = IEEE754_CLASS_DNORM;\ - } else\ - vc = IEEE754_CLASS_ZERO;\ - } else {\ - ve -= SP_EBIAS;\ - vm |= SP_HIDDEN_BIT;\ - vc = IEEE754_CLASS_NORM;\ - }\ -} -#define EXPLODEXSP EXPLODESP(x,xc,xs,xe,xm) -#define EXPLODEYSP EXPLODESP(y,yc,ys,ye,ym) - - -#define COMPXDP \ -unsigned long long xm; int xe; int xs; int xc - -#define COMPYDP \ -unsigned long long ym; int ye; int ys; int yc - -#define EXPLODEDP(v,vc,vs,ve,vm) \ -{\ - vm = DPMANT(v);\ - vs = DPSIGN(v);\ - ve = DPBEXP(v);\ - if(ve == DP_EMAX+1+DP_EBIAS){\ - if(vm == 0)\ - vc = IEEE754_CLASS_INF;\ - else if(vm & DP_MBIT(DP_MBITS-1)) \ - vc = IEEE754_CLASS_QNAN;\ - else \ - vc = IEEE754_CLASS_SNAN;\ - } else if(ve == DP_EMIN-1+DP_EBIAS) {\ - if(vm) {\ - ve = DP_EMIN;\ - vc = IEEE754_CLASS_DNORM;\ - } else\ - vc = IEEE754_CLASS_ZERO;\ - } else {\ - ve -= DP_EBIAS;\ - vm |= DP_HIDDEN_BIT;\ - vc = IEEE754_CLASS_NORM;\ - }\ -} -#define EXPLODEXDP EXPLODEDP(x,xc,xs,xe,xm) -#define EXPLODEYDP EXPLODEDP(y,yc,ys,ye,ym) diff -Nru a/arch/mips64/math-emu/ieee754m.c b/arch/mips64/math-emu/ieee754m.c --- a/arch/mips64/math-emu/ieee754m.c Tue Jul 1 18:44:36 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,56 +0,0 @@ -/* - * floor, trunc, ceil - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754.h" - -ieee754dp ieee754dp_floor(ieee754dp x) -{ - ieee754dp i; - - if (ieee754dp_lt(ieee754dp_modf(x, &i), ieee754dp_zero(0))) - return ieee754dp_sub(i, ieee754dp_one(0)); - else - return i; -} - -ieee754dp ieee754dp_ceil(ieee754dp x) -{ - ieee754dp i; - - if (ieee754dp_gt(ieee754dp_modf(x, &i), ieee754dp_zero(0))) - return ieee754dp_add(i, ieee754dp_one(0)); - else - return i; -} - -ieee754dp ieee754dp_trunc(ieee754dp x) -{ - ieee754dp i; - - (void) ieee754dp_modf(x, &i); - return i; -} diff -Nru a/arch/mips64/math-emu/ieee754sp.c b/arch/mips64/math-emu/ieee754sp.c --- a/arch/mips64/math-emu/ieee754sp.c Tue Jul 1 18:44:35 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,197 +0,0 @@ -/* IEEE754 floating point arithmetic - * single precision - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754sp.h" - -int ieee754sp_class(ieee754sp x) -{ - COMPXSP; - EXPLODEXSP; - return xc; -} - -int ieee754sp_isnan(ieee754sp x) -{ - return ieee754sp_class(x) >= IEEE754_CLASS_SNAN; -} - -int ieee754sp_issnan(ieee754sp x) -{ - assert(ieee754sp_isnan(x)); - if (ieee754_csr.noq) - return 1; - return !(SPMANT(x) & SP_MBIT(SP_MBITS - 1)); -} - - -ieee754sp ieee754sp_xcpt(ieee754sp r, const char *op, ...) -{ - struct ieee754xctx ax; - - if (!TSTX()) - return r; - - ax.op = op; - ax.rt = IEEE754_RT_SP; - ax.rv.sp = r; - va_start(ax.ap, op); - ieee754_xcpt(&ax); - return ax.rv.sp; -} - -ieee754sp ieee754sp_nanxcpt(ieee754sp r, const char *op, ...) -{ - struct ieee754xctx ax; - - assert(ieee754sp_isnan(r)); - - if (!ieee754sp_issnan(r)) /* QNAN does not cause invalid op !! */ - return r; - - if (!SETCX(IEEE754_INVALID_OPERATION)) { - /* not enabled convert to a quiet NaN */ - if (ieee754_csr.noq) - return r; - SPMANT(r) |= SP_MBIT(SP_MBITS - 1); - return r; - } - - ax.op = op; - ax.rt = 0; - ax.rv.sp = r; - va_start(ax.ap, op); - ieee754_xcpt(&ax); - return ax.rv.sp; -} - -ieee754sp ieee754sp_bestnan(ieee754sp x, ieee754sp y) -{ - assert(ieee754sp_isnan(x)); - assert(ieee754sp_isnan(y)); - - if (SPMANT(x) > SPMANT(y)) - return x; - else - return y; -} - - -/* generate a normal/denormal number with over,under handling - * sn is sign - * xe is an unbiased exponent - * xm is 3bit extended precision value. - */ -ieee754sp ieee754sp_format(int sn, int xe, unsigned xm) -{ - assert(xm); /* we don't gen exact zeros (probably should) */ - - assert((xm >> (SP_MBITS + 1 + 3)) == 0); /* no execess */ - assert(xm & (SP_HIDDEN_BIT << 3)); - - if (xe < SP_EMIN) { - /* strip lower bits */ - int es = SP_EMIN - xe; - - if (ieee754_csr.nod) { - SETCX(IEEE754_UNDERFLOW); - return ieee754sp_zero(sn); - } - - /* sticky right shift es bits - */ - SPXSRSXn(es); - - assert((xm & (SP_HIDDEN_BIT << 3)) == 0); - assert(xe == SP_EMIN); - } - if (xm & (SP_MBIT(3) - 1)) { - SETCX(IEEE754_INEXACT); - /* inexact must round of 3 bits - */ - switch (ieee754_csr.rm) { - case IEEE754_RZ: - break; - case IEEE754_RN: - xm += 0x3 + ((xm >> 3) & 1); - /* xm += (xm&0x8)?0x4:0x3 */ - break; - case IEEE754_RU: /* toward +Infinity */ - if (!sn) /* ?? */ - xm += 0x8; - break; - case IEEE754_RD: /* toward -Infinity */ - if (sn) /* ?? */ - xm += 0x8; - break; - } - /* adjust exponent for rounding add overflowing - */ - if (xm >> (SP_MBITS + 1 + 3)) { /* add causes mantissa overflow */ - xm >>= 1; - xe++; - } - } - /* strip grs bits */ - xm >>= 3; - - assert((xm >> (SP_MBITS + 1)) == 0); /* no execess */ - assert(xe >= SP_EMIN); - - if (xe > SP_EMAX) { - SETCX(IEEE754_OVERFLOW); - /* -O can be table indexed by (rm,sn) */ - switch (ieee754_csr.rm) { - case IEEE754_RN: - return ieee754sp_inf(sn); - case IEEE754_RZ: - return ieee754sp_max(sn); - case IEEE754_RU: /* toward +Infinity */ - if (sn == 0) - return ieee754sp_inf(0); - else - return ieee754sp_max(1); - case IEEE754_RD: /* toward -Infinity */ - if (sn == 0) - return ieee754sp_max(0); - else - return ieee754sp_inf(1); - } - } - /* gen norm/denorm/zero */ - - if ((xm & SP_HIDDEN_BIT) == 0) { - /* we underflow (tiny/zero) */ - assert(xe == SP_EMIN); - SETCX(IEEE754_UNDERFLOW); - return buildsp(sn, SP_EMIN - 1 + SP_EBIAS, xm); - } else { - assert((xm >> (SP_MBITS + 1)) == 0); /* no execess */ - assert(xm & SP_HIDDEN_BIT); - - return buildsp(sn, xe + SP_EBIAS, xm & ~SP_HIDDEN_BIT); - } -} diff -Nru a/arch/mips64/math-emu/ieee754sp.h b/arch/mips64/math-emu/ieee754sp.h --- a/arch/mips64/math-emu/ieee754sp.h Tue Jul 1 18:44:37 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,89 +0,0 @@ -/* - * IEEE754 floating point - * double precision internal header file - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754int.h" - -#define assert(expr) ((void)0) - -/* 3bit extended single precision sticky right shift */ -#define SPXSRSXn(rs) \ - (xe += rs, \ - xm = (rs > (SP_MBITS+3))?1:((xm) >> (rs)) | ((xm) << (32-(rs)) != 0)) - -#define SPXSRSX1() \ - (xe++, (xm = (xm >> 1) | (xm & 1))) - -#define SPXSRSYn(rs) \ - (ye+=rs, \ - ym = (rs > (SP_MBITS+3))?1:((ym) >> (rs)) | ((ym) << (32-(rs)) != 0)) - -#define SPXSRSY1() \ - (ye++, (ym = (ym >> 1) | (ym & 1))) - -/* convert denormal to normalized with extended exponent */ -#define SPDNORMx(m,e) \ - while( (m >> SP_MBITS) == 0) { m <<= 1; e--; } -#define SPDNORMX SPDNORMx(xm,xe) -#define SPDNORMY SPDNORMx(ym,ye) - -static __inline ieee754sp buildsp(int s, int bx, unsigned m) -{ - ieee754sp r; - - assert((s) == 0 || (s) == 1); - assert((bx) >= SP_EMIN - 1 + SP_EBIAS - && (bx) <= SP_EMAX + 1 + SP_EBIAS); - assert(((m) >> SP_MBITS) == 0); - - r.parts.sign = s; - r.parts.bexp = bx; - r.parts.mant = m; - - return r; -} - -extern int ieee754sp_isnan(ieee754sp); -extern int ieee754sp_issnan(ieee754sp); -extern int ieee754si_xcpt(int, const char *, ...); -extern long long ieee754di_xcpt(long long, const char *, ...); -extern ieee754sp ieee754sp_xcpt(ieee754sp, const char *, ...); -extern ieee754sp ieee754sp_nanxcpt(ieee754sp, const char *, ...); -extern ieee754sp ieee754sp_bestnan(ieee754sp, ieee754sp); -extern ieee754sp ieee754sp_format(int, int, unsigned); - - -#define SPNORMRET2(s,e,m,name,a0,a1) \ -{ \ - ieee754sp V = ieee754sp_format(s,e,m); \ - if(TSTX()) \ - return ieee754sp_xcpt(V,name,a0,a1); \ - else \ - return V; \ -} - -#define SPNORMRET1(s,e,m,name,a0) SPNORMRET2(s,e,m,name,a0,a0) diff -Nru a/arch/mips64/math-emu/ieee754xcpt.c b/arch/mips64/math-emu/ieee754xcpt.c --- a/arch/mips64/math-emu/ieee754xcpt.c Tue Jul 1 18:44:36 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,48 +0,0 @@ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - -/************************************************************************** - * Nov 7, 2000 - * Added preprocessor hacks to map to Linux kernel diagnostics. - * - * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - *************************************************************************/ - -#include "ieee754.h" - -/* - * Very naff exception handler (you can plug in your own and - * override this). - */ - -static const char *const rtnames[] = { - "sp", "dp", "xp", "si", "di" -}; - -void ieee754_xcpt(struct ieee754xctx *xcp) -{ - printk("floating point exception in \"%s\", type=%s\n", - xcp->op, rtnames[xcp->rt]); -} - diff -Nru a/arch/mips64/math-emu/kernel_linkage.c b/arch/mips64/math-emu/kernel_linkage.c --- a/arch/mips64/math-emu/kernel_linkage.c Tue Jul 1 18:44:37 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,95 +0,0 @@ -/************************************************************************** - * - * arch/mips/math_emu/kernel_linkage.c - * - * Kevin D. Kissell, kevink@mips and Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - *************************************************************************/ -/* - * Routines corresponding to Linux kernel FP context - * manipulation primitives for the Algorithmics MIPS - * FPU Emulator - */ - -#include -#include -#include -#include - -#include - -extern struct mips_fpu_emulator_private fpuemuprivate; - -#define SIGNALLING_NAN 0x7ff800007ff80000LL - -void fpu_emulator_init_fpu(void) -{ - static int first = 1; - int i; - - if (first) { - first = 0; - printk("Algorithmics/MIPS FPU Emulator v1.4\n"); - } - - current->thread.fpu.soft.sr = 0; - for (i = 0; i < 32; i++) { - current->thread.fpu.soft.regs[i] = SIGNALLING_NAN; - } -} - - -/* - * Emulator context save/restore to/from a signal context - * presumed to be on the user stack, and therefore accessed - * with appropriate macros from uaccess.h - */ - -int fpu_emulator_save_context(struct sigcontext *sc) -{ - int i; - int err = 0; - - for (i = 0; i < 32; i++) { - err |= - __put_user(current->thread.fpu.soft.regs[i], - &sc->sc_fpregs[i]); - } - err |= __put_user(current->thread.fpu.soft.sr, &sc->sc_fpc_csr); - err |= __put_user(fpuemuprivate.eir, &sc->sc_fpc_eir); - - return err; -} - -int fpu_emulator_restore_context(struct sigcontext *sc) -{ - int i; - int err = 0; - - for (i = 0; i < 32; i++) { - err |= - __get_user(current->thread.fpu.soft.regs[i], - &sc->sc_fpregs[i]); - } - err |= __get_user(current->thread.fpu.soft.sr, &sc->sc_fpc_csr); - err |= __get_user(fpuemuprivate.eir, &sc->sc_fpc_eir); - - return err; -} - diff -Nru a/arch/mips64/math-emu/sp_add.c b/arch/mips64/math-emu/sp_add.c --- a/arch/mips64/math-emu/sp_add.c Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,180 +0,0 @@ -/* IEEE754 floating point arithmetic - * single precision - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754sp.h" - -ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y) -{ - COMPXSP; - COMPYSP; - - EXPLODEXSP; - EXPLODEYSP; - - CLEARCX; - - switch (CLPAIR(xc, yc)) { - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): - return ieee754sp_nanxcpt(ieee754sp_bestnan(x, y), "add", x, - y); - - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): - return ieee754sp_nanxcpt(y, "add", x, y); - - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - return ieee754sp_nanxcpt(x, "add", x, y); - - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): - return ieee754sp_bestnan(x, y); - - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): - return y; - - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF): - return x; - - - /* Inifity handling - */ - - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): - if (xs == ys) - return x; - SETCX(IEEE754_INVALID_OPERATION); - return ieee754sp_xcpt(ieee754sp_indef(), "add", x, y); - - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): - return y; - - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): - return x; - - /* Zero handling - */ - - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): - if (xs == ys) - return x; - else - return ieee754sp_zero(ieee754_csr.rm == - IEEE754_RD); - - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): - return x; - - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): - return y; - - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): - SPDNORMX; - - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): - SPDNORMY; - break; - - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM): - SPDNORMX; - break; - - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM): - break; - } - assert(xm & SP_HIDDEN_BIT); - assert(ym & SP_HIDDEN_BIT); - - /* provide guard,round and stick bit space */ - xm <<= 3; - ym <<= 3; - - if (xe > ye) { - /* have to shift y fraction right to align - */ - int s = xe - ye; - SPXSRSYn(s); - } else if (ye > xe) { - /* have to shift x fraction right to align - */ - int s = ye - xe; - SPXSRSXn(s); - } - assert(xe == ye); - assert(xe <= SP_EMAX); - - if (xs == ys) { - /* generate 28 bit result of adding two 27 bit numbers - * leaving result in xm,xs,xe - */ - xm = xm + ym; - xe = xe; - xs = xs; - - if (xm >> (SP_MBITS + 1 + 3)) { /* carry out */ - SPXSRSX1(); - } - } else { - if (xm >= ym) { - xm = xm - ym; - xe = xe; - xs = xs; - } else { - xm = ym - xm; - xe = xe; - xs = ys; - } - if (xm == 0) - return ieee754sp_zero(ieee754_csr.rm == - IEEE754_RD); - - /* normalize in extended single precision */ - while ((xm >> (SP_MBITS + 3)) == 0) { - xm <<= 1; - xe--; - } - - } - SPNORMRET2(xs, xe, xm, "add", x, y); -} diff -Nru a/arch/mips64/math-emu/sp_cmp.c b/arch/mips64/math-emu/sp_cmp.c --- a/arch/mips64/math-emu/sp_cmp.c Tue Jul 1 18:44:35 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,58 +0,0 @@ -/* IEEE754 floating point arithmetic - * single precision - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754sp.h" - -int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cmp) -{ - CLEARCX; - - if (ieee754sp_isnan(x) || ieee754sp_isnan(y)) { - if (cmp & IEEE754_CUN) - return 1; - if (cmp & (IEEE754_CLT | IEEE754_CGT)) { - if (SETCX(IEEE754_INVALID_OPERATION)) - return ieee754si_xcpt(0, "fcmpf", x); - } - return 0; - } else { - int vx = x.bits; - int vy = y.bits; - - if (vx < 0) - vx = -vx ^ SP_SIGN_BIT; - if (vy < 0) - vy = -vy ^ SP_SIGN_BIT; - - if (vx < vy) - return (cmp & IEEE754_CLT) != 0; - else if (vx == vy) - return (cmp & IEEE754_CEQ) != 0; - else - return (cmp & IEEE754_CGT) != 0; - } -} diff -Nru a/arch/mips64/math-emu/sp_div.c b/arch/mips64/math-emu/sp_div.c --- a/arch/mips64/math-emu/sp_div.c Tue Jul 1 18:44:39 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,160 +0,0 @@ -/* IEEE754 floating point arithmetic - * single precision - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754sp.h" - -ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y) -{ - COMPXSP; - COMPYSP; - - CLEARCX; - - EXPLODEXSP; - EXPLODEYSP; - - switch (CLPAIR(xc, yc)) { - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): - return ieee754sp_nanxcpt(ieee754sp_bestnan(x, y), "div", x, - y); - - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): - return ieee754sp_nanxcpt(y, "div", x, y); - - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - return ieee754sp_nanxcpt(x, "div", x, y); - - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): - return ieee754sp_bestnan(x, y); - - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): - return y; - - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF): - return x; - - - /* Infinity handling - */ - - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): - SETCX(IEEE754_INVALID_OPERATION); - return ieee754sp_xcpt(ieee754sp_indef(), "div", x, y); - - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): - return ieee754sp_zero(xs ^ ys); - - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): - return ieee754sp_inf(xs ^ ys); - - /* Zero handling - */ - - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): - SETCX(IEEE754_INVALID_OPERATION); - return ieee754sp_xcpt(ieee754sp_indef(), "div", x, y); - - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): - SETCX(IEEE754_ZERO_DIVIDE); - return ieee754sp_xcpt(ieee754sp_inf(xs ^ ys), "div", x, y); - - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): - return ieee754sp_zero(xs == ys ? 0 : 1); - - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): - SPDNORMX; - - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): - SPDNORMY; - break; - - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM): - SPDNORMX; - break; - - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM): - break; - } - assert(xm & SP_HIDDEN_BIT); - assert(ym & SP_HIDDEN_BIT); - - /* provide rounding space */ - xm <<= 3; - ym <<= 3; - - { - /* now the dirty work */ - - unsigned rm = 0; - int re = xe - ye; - unsigned bm; - - for (bm = SP_MBIT(SP_MBITS + 2); bm; bm >>= 1) { - if (xm >= ym) { - xm -= ym; - rm |= bm; - if (xm == 0) - break; - } - xm <<= 1; - } - rm <<= 1; - if (xm) - rm |= 1; /* have remainder, set sticky */ - - assert(rm); - - /* normalise rm to rounding precision ? - */ - while ((rm >> (SP_MBITS + 3)) == 0) { - rm <<= 1; - re--; - } - - SPNORMRET2(xs == ys ? 0 : 1, re, rm, "div", x, y); - } -} diff -Nru a/arch/mips64/math-emu/sp_fdp.c b/arch/mips64/math-emu/sp_fdp.c --- a/arch/mips64/math-emu/sp_fdp.c Tue Jul 1 18:44:38 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,69 +0,0 @@ -/* IEEE754 floating point arithmetic - * single precision - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754sp.h" - -ieee754sp ieee754sp_fdp(ieee754dp x) -{ - COMPXDP; - - CLEARCX; - - EXPLODEXDP; - - switch (xc) { - case IEEE754_CLASS_QNAN: - case IEEE754_CLASS_SNAN: - return ieee754sp_nanxcpt(buildsp(xs, - SP_EMAX + 1 + SP_EBIAS, - (unsigned long) - (xm >> - (DP_MBITS - SP_MBITS))), - "fdp", x); - case IEEE754_CLASS_INF: - return ieee754sp_inf(xs); - case IEEE754_CLASS_ZERO: - return ieee754sp_zero(xs); - case IEEE754_CLASS_DNORM: - /* can't possibly be sp representable */ - SETCX(IEEE754_UNDERFLOW); - return ieee754sp_xcpt(ieee754sp_zero(xs), "fdp", x); - case IEEE754_CLASS_NORM: - break; - } - - { - unsigned long rm; - - /* convert from DP_MBITS to SP_MBITS+3 with sticky right shift - */ - rm = (xm >> (DP_MBITS - (SP_MBITS + 3))) | - ((xm << (64 - (DP_MBITS - (SP_MBITS + 3)))) != 0); - - SPNORMRET1(xs, xe, rm, "fdp", x); - } -} diff -Nru a/arch/mips64/math-emu/sp_fint.c b/arch/mips64/math-emu/sp_fint.c --- a/arch/mips64/math-emu/sp_fint.c Tue Jul 1 18:44:31 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,78 +0,0 @@ -/* IEEE754 floating point arithmetic - * single precision - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754sp.h" - -ieee754sp ieee754sp_fint(int x) -{ - COMPXSP; - - CLEARCX; - - if (x == 0) - return ieee754sp_zero(0); - if (x == 1 || x == -1) - return ieee754sp_one(x < 0); - if (x == 10 || x == -10) - return ieee754sp_ten(x < 0); - - xs = (x < 0); - if (xs) { - if (x == (1 << 31)) - xm = ((unsigned) 1 << 31); /* max neg can't be safely negated */ - else - xm = -x; - } else { - xm = x; - } - xe = SP_MBITS + 3; - - if (xm >> (SP_MBITS + 1 + 3)) { - /* shunt out overflow bits - */ - while (xm >> (SP_MBITS + 1 + 3)) { - SPXSRSX1(); - } - } else { - /* normalize in grs extended single precision - */ - while ((xm >> (SP_MBITS + 3)) == 0) { - xm <<= 1; - xe--; - } - } - SPNORMRET1(xs, xe, xm, "fint", x); -} - - -ieee754sp ieee754sp_funs(unsigned int u) -{ - if ((int) u < 0) - return ieee754sp_add(ieee754sp_1e31(), - ieee754sp_fint(u & ~(1 << 31))); - return ieee754sp_fint(u); -} diff -Nru a/arch/mips64/math-emu/sp_flong.c b/arch/mips64/math-emu/sp_flong.c --- a/arch/mips64/math-emu/sp_flong.c Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,77 +0,0 @@ -/* IEEE754 floating point arithmetic - * single precision - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754sp.h" - -ieee754sp ieee754sp_flong(long long x) -{ - COMPXDP; /* <--- need 64-bit mantissa temp */ - - CLEARCX; - - if (x == 0) - return ieee754sp_zero(0); - if (x == 1 || x == -1) - return ieee754sp_one(x < 0); - if (x == 10 || x == -10) - return ieee754sp_ten(x < 0); - - xs = (x < 0); - if (xs) { - if (x == (1ULL << 63)) - xm = (1ULL << 63); /* max neg can't be safely negated */ - else - xm = -x; - } else { - xm = x; - } - xe = SP_MBITS + 3; - - if (xm >> (SP_MBITS + 1 + 3)) { - /* shunt out overflow bits - */ - while (xm >> (SP_MBITS + 1 + 3)) { - SPXSRSX1(); - } - } else { - /* normalize in grs extended single precision */ - while ((xm >> (SP_MBITS + 3)) == 0) { - xm <<= 1; - xe--; - } - } - SPNORMRET1(xs, xe, xm, "sp_flong", x); -} - - -ieee754sp ieee754sp_fulong(unsigned long long u) -{ - if ((long long) u < 0) - return ieee754sp_add(ieee754sp_1e63(), - ieee754sp_flong(u & ~(1ULL << 63))); - return ieee754sp_flong(u); -} diff -Nru a/arch/mips64/math-emu/sp_frexp.c b/arch/mips64/math-emu/sp_frexp.c --- a/arch/mips64/math-emu/sp_frexp.c Tue Jul 1 18:44:39 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,53 +0,0 @@ -/* IEEE754 floating point arithmetic - * single precision - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754sp.h" - -/* close to ieeep754sp_logb -*/ -ieee754sp ieee754sp_frexp(ieee754sp x, int *eptr) -{ - COMPXSP; - CLEARCX; - EXPLODEXSP; - - switch (xc) { - case IEEE754_CLASS_SNAN: - case IEEE754_CLASS_QNAN: - case IEEE754_CLASS_INF: - case IEEE754_CLASS_ZERO: - *eptr = 0; - return x; - case IEEE754_CLASS_DNORM: - SPDNORMX; - break; - case IEEE754_CLASS_NORM: - break; - } - *eptr = xe + 1; - return buildsp(xs, -1 + SP_EBIAS, xm & ~SP_HIDDEN_BIT); -} diff -Nru a/arch/mips64/math-emu/sp_logb.c b/arch/mips64/math-emu/sp_logb.c --- a/arch/mips64/math-emu/sp_logb.c Tue Jul 1 18:44:36 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,54 +0,0 @@ -/* IEEE754 floating point arithmetic - * single precision - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754sp.h" - -ieee754sp ieee754sp_logb(ieee754sp x) -{ - COMPXSP; - - CLEARCX; - - EXPLODEXSP; - - switch (xc) { - case IEEE754_CLASS_SNAN: - return ieee754sp_nanxcpt(x, "logb", x); - case IEEE754_CLASS_QNAN: - return x; - case IEEE754_CLASS_INF: - return ieee754sp_inf(0); - case IEEE754_CLASS_ZERO: - return ieee754sp_inf(1); - case IEEE754_CLASS_DNORM: - SPDNORMX; - break; - case IEEE754_CLASS_NORM: - break; - } - return ieee754sp_fint(xe); -} diff -Nru a/arch/mips64/math-emu/sp_modf.c b/arch/mips64/math-emu/sp_modf.c --- a/arch/mips64/math-emu/sp_modf.c Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,80 +0,0 @@ -/* IEEE754 floating point arithmetic - * single precision - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754sp.h" - -/* modf function is always exact for a finite number -*/ -ieee754sp ieee754sp_modf(ieee754sp x, ieee754sp * ip) -{ - COMPXSP; - - CLEARCX; - - EXPLODEXSP; - - switch (xc) { - case IEEE754_CLASS_SNAN: - case IEEE754_CLASS_QNAN: - case IEEE754_CLASS_INF: - case IEEE754_CLASS_ZERO: - *ip = x; - return x; - case IEEE754_CLASS_DNORM: - /* far to small */ - *ip = ieee754sp_zero(xs); - return x; - case IEEE754_CLASS_NORM: - break; - } - if (xe < 0) { - *ip = ieee754sp_zero(xs); - return x; - } - if (xe >= SP_MBITS) { - *ip = x; - return ieee754sp_zero(xs); - } - /* generate ipart mantissa by clearing bottom bits - */ - *ip = buildsp(xs, xe + SP_EBIAS, - ((xm >> (SP_MBITS - xe)) << (SP_MBITS - xe)) & - ~SP_HIDDEN_BIT); - - /* generate fpart mantissa by clearing top bits - * and normalizing (must be able to normalize) - */ - xm = (xm << (32 - (SP_MBITS - xe))) >> (32 - (SP_MBITS - xe)); - if (xm == 0) - return ieee754sp_zero(xs); - - while ((xm >> SP_MBITS) == 0) { - xm <<= 1; - xe--; - } - return buildsp(xs, xe + SP_EBIAS, xm & ~SP_HIDDEN_BIT); -} diff -Nru a/arch/mips64/math-emu/sp_mul.c b/arch/mips64/math-emu/sp_mul.c --- a/arch/mips64/math-emu/sp_mul.c Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,174 +0,0 @@ -/* IEEE754 floating point arithmetic - * single precision - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754sp.h" - -ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y) -{ - COMPXSP; - COMPYSP; - - CLEARCX; - - EXPLODEXSP; - EXPLODEYSP; - - switch (CLPAIR(xc, yc)) { - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): - return ieee754sp_nanxcpt(ieee754sp_bestnan(x, y), "mul", x, - y); - - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): - return ieee754sp_nanxcpt(y, "mul", x, y); - - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - return ieee754sp_nanxcpt(x, "mul", x, y); - - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): - return ieee754sp_bestnan(x, y); - - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): - return y; - - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF): - return x; - - - /* Infinity handling */ - - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): - SETCX(IEEE754_INVALID_OPERATION); - return ieee754sp_xcpt(ieee754sp_indef(), "mul", x, y); - - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): - return ieee754sp_inf(xs ^ ys); - - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): - return ieee754sp_zero(xs ^ ys); - - - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): - SPDNORMX; - - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): - SPDNORMY; - break; - - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM): - SPDNORMX; - break; - - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM): - break; - } - /* rm = xm * ym, re = xe+ye basicly */ - assert(xm & SP_HIDDEN_BIT); - assert(ym & SP_HIDDEN_BIT); - - { - int re = xe + ye; - int rs = xs ^ ys; - unsigned rm; - - /* shunt to top of word */ - xm <<= 32 - (SP_MBITS + 1); - ym <<= 32 - (SP_MBITS + 1); - - /* multiply 32bits xm,ym to give high 32bits rm with stickness - */ - { - unsigned short lxm = xm & 0xffff; - unsigned short hxm = xm >> 16; - unsigned short lym = ym & 0xffff; - unsigned short hym = ym >> 16; - unsigned lrm; - unsigned hrm; - - lrm = lxm * lym; /* 16 * 16 => 32 */ - hrm = hxm * hym; /* 16 * 16 => 32 */ - - { - unsigned t = lxm * hym; /* 16 * 16 => 32 */ - { - unsigned at = lrm + (t << 16); - hrm += at < lrm; - lrm = at; - } - hrm = hrm + (t >> 16); - } - - { - unsigned t = hxm * lym; /* 16 * 16 => 32 */ - { - unsigned at = lrm + (t << 16); - hrm += at < lrm; - lrm = at; - } - hrm = hrm + (t >> 16); - } - rm = hrm | (lrm != 0); - } - - /* - * sticky shift down to normal rounding precision - */ - if ((int) rm < 0) { - rm = (rm >> (32 - (SP_MBITS + 1 + 3))) | - ((rm << (SP_MBITS + 1 + 3)) != 0); - re++; - } else { - rm = (rm >> (32 - (SP_MBITS + 1 + 3 + 1))) | - ((rm << (SP_MBITS + 1 + 3 + 1)) != 0); - } - assert(rm & (SP_HIDDEN_BIT << 3)); - - SPNORMRET2(rs, re, rm, "mul", x, y); - } -} diff -Nru a/arch/mips64/math-emu/sp_scalb.c b/arch/mips64/math-emu/sp_scalb.c --- a/arch/mips64/math-emu/sp_scalb.c Tue Jul 1 18:44:38 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,58 +0,0 @@ -/* IEEE754 floating point arithmetic - * single precision - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754sp.h" - -ieee754sp ieee754sp_scalb(ieee754sp x, int n) -{ - COMPXSP; - - CLEARCX; - - EXPLODEXSP; - - switch (xc) { - case IEEE754_CLASS_SNAN: - return ieee754sp_nanxcpt(x, "scalb", x, n); - case IEEE754_CLASS_QNAN: - case IEEE754_CLASS_INF: - case IEEE754_CLASS_ZERO: - return x; - case IEEE754_CLASS_DNORM: - SPDNORMX; - break; - case IEEE754_CLASS_NORM: - break; - } - SPNORMRET2(xs, xe + n, xm << 3, "scalb", x, n); -} - - -ieee754sp ieee754sp_ldexp(ieee754sp x, int n) -{ - return ieee754sp_scalb(x, n); -} diff -Nru a/arch/mips64/math-emu/sp_simple.c b/arch/mips64/math-emu/sp_simple.c --- a/arch/mips64/math-emu/sp_simple.c Tue Jul 1 18:44:35 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,66 +0,0 @@ -/* IEEE754 floating point arithmetic - * single precision - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754sp.h" - -int ieee754sp_finite(ieee754sp x) -{ - return SPBEXP(x) != SP_EMAX + 1 + SP_EBIAS; -} - -ieee754sp ieee754sp_copysign(ieee754sp x, ieee754sp y) -{ - CLEARCX; - SPSIGN(x) = SPSIGN(y); - return x; -} - - -ieee754sp ieee754sp_neg(ieee754sp x) -{ - CLEARCX; - - if (ieee754sp_isnan(x)) /* but not infinity */ - return ieee754sp_nanxcpt(x, "neg", x); - - /* quick fix up */ - SPSIGN(x) ^= 1; - return x; -} - - -ieee754sp ieee754sp_abs(ieee754sp x) -{ - CLEARCX; - - if (ieee754sp_isnan(x)) /* but not infinity */ - return ieee754sp_nanxcpt(x, "abs", x); - - /* quick fix up */ - SPSIGN(x) = 0; - return x; -} diff -Nru a/arch/mips64/math-emu/sp_sqrt.c b/arch/mips64/math-emu/sp_sqrt.c --- a/arch/mips64/math-emu/sp_sqrt.c Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,115 +0,0 @@ -/* IEEE754 floating point arithmetic - * single precision square root - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754sp.h" - -static const struct ieee754sp_konst knan = { - 0, SP_EBIAS + SP_EMAX + 1, 0 -}; - -#define nan ((ieee754sp)knan) - -ieee754sp ieee754sp_sqrt(ieee754sp x) -{ - int sign = (int) 0x80000000; - int ix, s, q, m, t, i; - unsigned int r; - COMPXDP; - - /* take care of Inf and NaN */ - - EXPLODEXDP; - - /* x == INF or NAN? */ - switch (xc) { - case IEEE754_CLASS_QNAN: - case IEEE754_CLASS_SNAN: - /* sqrt(Nan) = Nan */ - return ieee754sp_nanxcpt(x, "sqrt"); - case IEEE754_CLASS_ZERO: - /* sqrt(0) = 0 */ - return x; - case IEEE754_CLASS_INF: - if (xs) - /* sqrt(-Inf) = Nan */ - return ieee754sp_nanxcpt(nan, "sqrt"); - /* sqrt(+Inf) = Inf */ - return x; - case IEEE754_CLASS_DNORM: - case IEEE754_CLASS_NORM: - if (xs) - /* sqrt(-x) = Nan */ - return ieee754sp_nanxcpt(nan, "sqrt"); - break; - } - - ix = x.bits; - - /* normalize x */ - m = (ix >> 23); - if (m == 0) { /* subnormal x */ - for (i = 0; (ix & 0x00800000) == 0; i++) - ix <<= 1; - m -= i - 1; - } - m -= 127; /* unbias exponent */ - ix = (ix & 0x007fffff) | 0x00800000; - if (m & 1) /* odd m, double x to make it even */ - ix += ix; - m >>= 1; /* m = [m/2] */ - - /* generate sqrt(x) bit by bit */ - ix += ix; - q = s = 0; /* q = sqrt(x) */ - r = 0x01000000; /* r = moving bit from right to left */ - - while (r != 0) { - t = s + r; - if (t <= ix) { - s = t + r; - ix -= t; - q += r; - } - ix += ix; - r >>= 1; - } - - if (ix != 0) { - switch (ieee754_csr.rm) { - case IEEE754_RP: - q += 2; - break; - case IEEE754_RN: - q += (q & 1); - break; - } - } - ix = (q >> 1) + 0x3f000000; - ix += (m << 23); - x.bits = ix; - return x; -} diff -Nru a/arch/mips64/math-emu/sp_sub.c b/arch/mips64/math-emu/sp_sub.c --- a/arch/mips64/math-emu/sp_sub.c Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,187 +0,0 @@ -/* IEEE754 floating point arithmetic - * single precision - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754sp.h" - -ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y) -{ - COMPXSP; - COMPYSP; - - CLEARCX; - - EXPLODEXSP; - EXPLODEYSP; - - switch (CLPAIR(xc, yc)) { - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): - return ieee754sp_nanxcpt(ieee754sp_bestnan(x, y), "sub", x, - y); - - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): - return ieee754sp_nanxcpt(y, "sub", x, y); - - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): - case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): - return ieee754sp_nanxcpt(x, "sub", x, y); - - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): - return ieee754sp_bestnan(x, y); - - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): - return y; - - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): - case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF): - return x; - - - /* Inifity handling - */ - - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): - if (xs != ys) - return x; - SETCX(IEEE754_INVALID_OPERATION); - return ieee754sp_xcpt(ieee754sp_indef(), "sub", x, y); - - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): - return ieee754sp_inf(ys ^ 1); - - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): - return x; - - /* Zero handling - */ - - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): - if (xs != ys) - return x; - else - return ieee754sp_zero(ieee754_csr.rm == - IEEE754_RD); - - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): - return x; - - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): - case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): - /* quick fix up */ - DPSIGN(y) ^= 1; - return y; - - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): - SPDNORMX; - - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): - SPDNORMY; - break; - - case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM): - SPDNORMX; - break; - - case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM): - break; - } - /* flip sign of y and handle as add */ - ys ^= 1; - - assert(xm & SP_HIDDEN_BIT); - assert(ym & SP_HIDDEN_BIT); - - - /* provide guard,round and stick bit space */ - xm <<= 3; - ym <<= 3; - - if (xe > ye) { - /* have to shift y fraction right to align - */ - int s = xe - ye; - SPXSRSYn(s); - } else if (ye > xe) { - /* have to shift x fraction right to align - */ - int s = ye - xe; - SPXSRSXn(s); - } - assert(xe == ye); - assert(xe <= SP_EMAX); - - if (xs == ys) { - /* generate 28 bit result of adding two 27 bit numbers - */ - xm = xm + ym; - xe = xe; - xs = xs; - - if (xm >> (SP_MBITS + 1 + 3)) { /* carry out */ - SPXSRSX1(); /* shift preserving sticky */ - } - } else { - if (xm >= ym) { - xm = xm - ym; - xe = xe; - xs = xs; - } else { - xm = ym - xm; - xe = xe; - xs = ys; - } - if (xm == 0) - if (ieee754_csr.rm == IEEE754_RD) - return ieee754sp_zero(1); /* round negative inf. => sign = -1 */ - else - return ieee754sp_zero(0); /* other round modes => sign = 1 */ - - /* normalize to rounding precision - */ - while ((xm >> (SP_MBITS + 3)) == 0) { - xm <<= 1; - xe--; - } - } - SPNORMRET2(xs, xe, xm, "sub", x, y); -} diff -Nru a/arch/mips64/math-emu/sp_tint.c b/arch/mips64/math-emu/sp_tint.c --- a/arch/mips64/math-emu/sp_tint.c Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,88 +0,0 @@ -/* IEEE754 floating point arithmetic - * single precision - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include -#include "ieee754sp.h" - -int ieee754sp_tint(ieee754sp x) -{ - COMPXSP; - - CLEARCX; - - EXPLODEXSP; - - switch (xc) { - case IEEE754_CLASS_SNAN: - case IEEE754_CLASS_QNAN: - SETCX(IEEE754_INVALID_OPERATION); - return ieee754si_xcpt(ieee754si_indef(), "fixsp", x); - case IEEE754_CLASS_INF: - SETCX(IEEE754_OVERFLOW); - return ieee754si_xcpt(ieee754si_indef(), "fixsp", x); - case IEEE754_CLASS_ZERO: - return 0; - case IEEE754_CLASS_DNORM: /* much to small */ - SETCX(IEEE754_UNDERFLOW); - return ieee754si_xcpt(0, "fixsp", x); - case IEEE754_CLASS_NORM: - break; - } - if (xe >= 31) { - SETCX(IEEE754_OVERFLOW); - return ieee754si_xcpt(ieee754si_indef(), "fix", x); - } - if (xe < 0) { - SETCX(IEEE754_UNDERFLOW); - return ieee754si_xcpt(0, "fix", x); - } - /* oh gawd */ - if (xe > SP_MBITS) { - xm <<= xe - SP_MBITS; - } else if (xe < SP_MBITS) { - /* XXX no rounding - */ - xm >>= SP_MBITS - xe; - } - if (xs) - return -xm; - else - return xm; -} - - -unsigned int ieee754sp_tuns(ieee754sp x) -{ - ieee754sp hb = ieee754sp_1e31(); - - /* what if x < 0 ?? */ - if (ieee754sp_lt(x, hb)) - return (unsigned) ieee754sp_tint(x); - - return (unsigned) ieee754sp_tint(ieee754sp_sub(x, hb)) | - ((unsigned) 1 << 31); -} diff -Nru a/arch/mips64/math-emu/sp_tlong.c b/arch/mips64/math-emu/sp_tlong.c --- a/arch/mips64/math-emu/sp_tlong.c Tue Jul 1 18:44:36 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,87 +0,0 @@ -/* IEEE754 floating point arithmetic - * single precision - */ -/* - * MIPS floating point support - * Copyright (C) 1994-2000 Algorithmics Ltd. All rights reserved. - * http://www.algor.co.uk - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - */ - - -#include "ieee754sp.h" - -long long ieee754sp_tlong(ieee754sp x) -{ - COMPXDP; /* <-- need 64-bit mantissa tmp */ - - CLEARCX; - - EXPLODEXSP; - - switch (xc) { - case IEEE754_CLASS_SNAN: - case IEEE754_CLASS_QNAN: - SETCX(IEEE754_INVALID_OPERATION); - return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x); - case IEEE754_CLASS_INF: - SETCX(IEEE754_OVERFLOW); - return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x); - case IEEE754_CLASS_ZERO: - return 0; - case IEEE754_CLASS_DNORM: /* much to small */ - SETCX(IEEE754_UNDERFLOW); - return ieee754di_xcpt(0, "sp_tlong", x); - case IEEE754_CLASS_NORM: - break; - } - if (xe >= 63) { - SETCX(IEEE754_OVERFLOW); - return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x); - } - if (xe < 0) { - SETCX(IEEE754_UNDERFLOW); - return ieee754di_xcpt(0, "sp_tlong", x); - } - /* oh gawd */ - if (xe > SP_MBITS) { - xm <<= xe - SP_MBITS; - } else if (xe < SP_MBITS) { - /* XXX no rounding - */ - xm >>= SP_MBITS - xe; - } - if (xs) - return -xm; - else - return xm; -} - - -unsigned long long ieee754sp_tulong(ieee754sp x) -{ - ieee754sp hb = ieee754sp_1e63(); - - /* what if x < 0 ?? */ - if (ieee754sp_lt(x, hb)) - return (unsigned long long) ieee754sp_tlong(x); - - return (unsigned long long) ieee754sp_tlong(ieee754sp_sub(x, hb)) | - (1ULL << 63); -} diff -Nru a/arch/mips64/mips-boards/atlas/Makefile b/arch/mips64/mips-boards/atlas/Makefile --- a/arch/mips64/mips-boards/atlas/Makefile Tue Jul 1 18:44:37 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,26 +0,0 @@ -# -# Carsten Langgaard, carstenl@mips.com -# Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. -# -# ######################################################################## -# -# This program is free software; you can distribute it and/or modify it -# under the terms of the GNU General Public License (Version 2) as -# published by the Free Software Foundation. -# -# This program is distributed in the hope it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. -# -# ####################################################################### -# -# Makefile for the MIPS Atlas specific kernel interface routines -# under Linux. -# - -obj-y := atlas_int.o atlas_rtc.o atlas_setup.o diff -Nru a/arch/mips64/mips-boards/atlas/atlas_int.c b/arch/mips64/mips-boards/atlas/atlas_int.c --- a/arch/mips64/mips-boards/atlas/atlas_int.c Tue Jul 1 18:44:39 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,255 +0,0 @@ -/* - * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - * - * Routines for generic manipulation of the interrupts found on the MIPS - * Atlas board. - * - */ -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#ifdef CONFIG_REMOTE_DEBUG -#include -#endif - -struct atlas_ictrl_regs *atlas_hw0_icregs - = (struct atlas_ictrl_regs *)ATLAS_ICTRL_REGS_BASE; - -extern asmlinkage void mipsIRQ(void); -extern void do_IRQ(int irq, struct pt_regs *regs); - -unsigned long spurious_count = 0; -irq_desc_t irq_desc[NR_IRQS]; - -#if 0 -#define DEBUG_INT(x...) printk(x) -#else -#define DEBUG_INT(x...) -#endif - -void disable_atlas_irq(unsigned int irq_nr) -{ - atlas_hw0_icregs->intrsten = (1 << irq_nr); -} - -void enable_atlas_irq(unsigned int irq_nr) -{ - atlas_hw0_icregs->intseten = (1 << irq_nr); -} - -static unsigned int startup_atlas_irq(unsigned int irq) -{ - enable_atlas_irq(irq); - return 0; /* never anything pending */ -} - -#define shutdown_atlas_irq disable_atlas_irq - -#define mask_and_ack_atlas_irq disable_atlas_irq - -static void end_atlas_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_atlas_irq(irq); -} - -static struct hw_interrupt_type atlas_irq_type = { - "Atlas", - startup_atlas_irq, - shutdown_atlas_irq, - enable_atlas_irq, - disable_atlas_irq, - mask_and_ack_atlas_irq, - end_atlas_irq, - NULL -}; - -int show_interrupts(struct seq_file *p, void *v) -{ - int i; - int num = 0; - struct irqaction *action; - unsigned long flags; - - for (i = 0; i < ATLASINT_END; i++, num++) { - spin_lock_irqsave(&irq_desc[i].lock, flags); - action = irq_desc[i].action; - if (!action) - goto unlock; - seq_printf(p, "%2d: %8d %c %s", - num, kstat_cpu(0).irqs[num], - (action->flags & SA_INTERRUPT) ? '+' : ' ', - action->name); - for (action=action->next; action; action = action->next) { - seq_printf(p, ",%s %s", - (action->flags & SA_INTERRUPT) ? " +" : "", - action->name); - } - seq_puts(p, " [hw0]\n"); -unlock: - spin_unlock_irqrestore(&irq_desc[i].lock, flags); - } - return 0; -} - -int request_irq(unsigned int irq, - void (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, - const char * devname, - void *dev_id) -{ - struct irqaction *action; - - DEBUG_INT("request_irq: irq=%d, devname = %s\n", irq, devname); - - if (irq >= ATLASINT_END) - return -EINVAL; - if (!handler) - return -EINVAL; - - action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL); - if(!action) - return -ENOMEM; - - action->handler = handler; - action->flags = irqflags; - action->mask = 0; - action->name = devname; - action->dev_id = dev_id; - action->next = 0; - irq_desc[irq].action = action; - enable_atlas_irq(irq); - - return 0; -} - -void free_irq(unsigned int irq, void *dev_id) -{ - struct irqaction *action; - - if (irq >= ATLASINT_END) { - printk("Trying to free IRQ%d\n",irq); - return; - } - - action = irq_desc[irq].action; - irq_desc[irq].action = NULL; - disable_atlas_irq(irq); - kfree(action); -} - -static inline int ls1bit32(unsigned int x) -{ - int b = 31, s; - - s = 16; if (x << 16 == 0) s = 0; b -= s; x <<= s; - s = 8; if (x << 8 == 0) s = 0; b -= s; x <<= s; - s = 4; if (x << 4 == 0) s = 0; b -= s; x <<= s; - s = 2; if (x << 2 == 0) s = 0; b -= s; x <<= s; - s = 1; if (x << 1 == 0) s = 0; b -= s; - - return b; -} - -void atlas_hw0_irqdispatch(struct pt_regs *regs) -{ - struct irqaction *action; - unsigned long int_status; - int irq, cpu = smp_processor_id(); - - int_status = atlas_hw0_icregs->intstatus; - - /* if int_status == 0, then the interrupt has already been cleared */ - if (int_status == 0) - return; - - irq = ls1bit32(int_status); - action = irq_desc[irq].action; - - DEBUG_INT("atlas_hw0_irqdispatch: irq=%d\n", irq); - - /* if action == NULL, then we don't have a handler for the irq */ - if ( action == NULL ) { - printk("No handler for hw0 irq: %i\n", irq); - spurious_count++; - return; - } - - irq_enter(cpu, irq); - kstat_cpu(0).irqs[irq]++; - action->handler(irq, action->dev_id, regs); - irq_exit(cpu, irq); - - return; -} - -unsigned long probe_irq_on (void) -{ - return 0; -} - - -int probe_irq_off (unsigned long irqs) -{ - return 0; -} - -#ifdef CONFIG_REMOTE_DEBUG -extern void breakpoint(void); -extern int remote_debug; -#endif - -void __init init_IRQ(void) -{ - int i; - - /* - * Mask out all interrupt by writing "1" to all bit position in - * the interrupt reset reg. - */ - atlas_hw0_icregs->intrsten = 0xffffffff; - - /* Now safe to set the exception vector. */ - set_except_vector(0, mipsIRQ); - - for (i = 0; i <= ATLASINT_END; i++) { - irq_desc[i].status = IRQ_DISABLED; - irq_desc[i].action = 0; - irq_desc[i].depth = 1; - irq_desc[i].handler = &atlas_irq_type; - spin_lock_init(&irq_desc[i].lock); - } - -#ifdef CONFIG_REMOTE_DEBUG - if (remote_debug) { - set_debug_traps(); - breakpoint(); - } -#endif -} diff -Nru a/arch/mips64/mips-boards/atlas/atlas_rtc.c b/arch/mips64/mips-boards/atlas/atlas_rtc.c --- a/arch/mips64/mips-boards/atlas/atlas_rtc.c Tue Jul 1 18:44:31 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,58 +0,0 @@ -/* - * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - * - * RTC routines for Atlas style attached Dallas chip. - * - */ -#include -#include - - -static unsigned char atlas_rtc_read_data(unsigned long addr) -{ - volatile unsigned int *rtc_adr_reg = (void *)ATLAS_RTC_ADR_REG; - volatile unsigned int *rtc_dat_reg = (void *)ATLAS_RTC_DAT_REG; - - *rtc_adr_reg = addr; - - return *rtc_dat_reg; -} - -static void atlas_rtc_write_data(unsigned char data, unsigned long addr) -{ - volatile unsigned int *rtc_adr_reg = (void *)ATLAS_RTC_ADR_REG; - volatile unsigned int *rtc_dat_reg = (void *)ATLAS_RTC_DAT_REG; - - *rtc_adr_reg = addr; - *rtc_dat_reg = data; -} - -static int atlas_rtc_bcd_mode(void) -{ - return 0; -} - -struct rtc_ops atlas_rtc_ops = { - &atlas_rtc_read_data, - &atlas_rtc_write_data, - &atlas_rtc_bcd_mode -}; - diff -Nru a/arch/mips64/mips-boards/atlas/atlas_setup.c b/arch/mips64/mips-boards/atlas/atlas_setup.c --- a/arch/mips64/mips-boards/atlas/atlas_setup.c Tue Jul 1 18:44:32 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,123 +0,0 @@ -/* - * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - * - * Atlas specific setup, including init of the feature struct. - * - */ -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_PROM_CONSOLE) -extern void console_setup(char *, int *); -char serial_console[20]; -#endif - -#ifdef CONFIG_REMOTE_DEBUG -extern void rs_kgdb_hook(int); -extern void saa9730_kgdb_hook(void); -extern void breakpoint(void); -int remote_debug = 0; -#endif - -extern struct rtc_ops atlas_rtc_ops; - -extern void mips_reboot_setup(void); - -void __init atlas_setup(void) -{ -#ifdef CONFIG_REMOTE_DEBUG - int rs_putDebugChar(char); - char rs_getDebugChar(void); - int saa9730_putDebugChar(char); - char saa9730_getDebugChar(void); - extern int (*putDebugChar)(char); - extern char (*getDebugChar)(void); -#endif - char *argptr; - - current_cpu_data.asid_cache = ASID_FIRST_VERSION; - TLBMISS_HANDLER_SETUP(); - - ioport_resource.end = 0x7fffffff; - -#ifdef CONFIG_SERIAL_CONSOLE - argptr = prom_getcmdline(); - if ((argptr = strstr(argptr, "console=ttyS0")) == NULL) { - int i = 0; - char *s = prom_getenv("modetty0"); - while(s[i] >= '0' && s[i] <= '9') - i++; - strcpy(serial_console, "ttyS0,"); - strncpy(serial_console + 6, s, i); - prom_printf("Config serial console: %s\n", serial_console); - console_setup(serial_console, NULL); - } -#endif - -#ifdef CONFIG_REMOTE_DEBUG - argptr = prom_getcmdline(); - if ((argptr = strstr(argptr, "kgdb=ttyS")) != NULL) { - int line; - argptr += strlen("kgdb=ttyS"); - if (*argptr != '0' && *argptr != '1') - printk("KGDB: Uknown serial line /dev/ttyS%c, " - "falling back to /dev/ttyS1\n", *argptr); - line = *argptr == '0' ? 0 : 1; - printk("KGDB: Using serial line /dev/ttyS%d for session\n", - line ? 1 : 0); - - if(line == 0) { - rs_kgdb_hook(line); - putDebugChar = rs_putDebugChar; - getDebugChar = rs_getDebugChar; - } else { - saa9730_kgdb_hook(); - putDebugChar = saa9730_putDebugChar; - getDebugChar = saa9730_getDebugChar; - } - - prom_printf("KGDB: Using serial line /dev/ttyS%d for session, " - "please connect your debugger\n", line ? 1 : 0); - - remote_debug = 1; - /* Breakpoints and stuff are in atlas_irq_setup() */ - } -#endif - argptr = prom_getcmdline(); - - if ((argptr = strstr(argptr, "nofpu")) != NULL) - mips_cpu.options &= ~MIPS_CPU_FPU; - - rtc_ops = &atlas_rtc_ops; -} diff -Nru a/arch/mips64/mips-boards/generic/Makefile b/arch/mips64/mips-boards/generic/Makefile --- a/arch/mips64/mips-boards/generic/Makefile Tue Jul 1 18:44:33 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,29 +0,0 @@ -# -# Carsten Langgaard, carstenl@mips.com -# Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. -# -# ######################################################################## -# -# This program is free software; you can distribute it and/or modify it -# under the terms of the GNU General Public License (Version 2) as -# published by the Free Software Foundation. -# -# This program is distributed in the hope it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. -# -# ####################################################################### -# -# Makefile for the MIPS boards generic routines under Linux. -# - -obj-y := mipsIRQ.o pci.o reset.o display.o init.o \ - memory.o printf.o cmdline.o time.o -obj-$(CONFIG_REMOTE_DEBUG) += gdb_hook.o - -EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips64/mips-boards/generic/cmdline.c b/arch/mips64/mips-boards/generic/cmdline.c --- a/arch/mips64/mips-boards/generic/cmdline.c Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,71 +0,0 @@ -/* - * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - * - * Kernel command line creation using the prom monitor (YAMON) argc/argv. - * - */ -#include -#include -#include - -#include - -/*#define DEBUG_CMDLINE*/ - -extern int prom_argc; -extern int *_prom_argv; - -/* - * A 32-bit PROM pass arguments and environment as 32-bit pointer. - * This macro take care of sign extension. - */ -#define prom_argv(index) ((char *)(((int *)(int)_prom_argv)[(index)])) - -char arcs_cmdline[CL_SIZE]; - -char * __init prom_getcmdline(void) -{ - return &(arcs_cmdline[0]); -} - - -void __init prom_init_cmdline(void) -{ - char *cp; - int actr; - - actr = 1; /* Always ignore argv[0] */ - - cp = &(arcs_cmdline[0]); - while(actr < prom_argc) { - strcpy(cp, prom_argv(actr)); - cp += strlen(prom_argv(actr)); - *cp++ = ' '; - actr++; - } - if (cp != &(arcs_cmdline[0])) /* get rid of trailing space */ - --cp; - *cp = '\0'; - -#ifdef DEBUG_CMDLINE - prom_printf("prom_init_cmdline: %s\n", &(arcs_cmdline[0])); -#endif -} diff -Nru a/arch/mips64/mips-boards/generic/display.c b/arch/mips64/mips-boards/generic/display.c --- a/arch/mips64/mips-boards/generic/display.c Tue Jul 1 18:44:39 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,47 +0,0 @@ -/* - * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - * - * Display routines for display messages in MIPS boards ascii display. - * - */ - -#include - - -void mips_display_message(const char *str) -{ - volatile unsigned int *display = (void *)ASCII_DISPLAY_POS_BASE; - int i; - - for (i = 0; i <= 14; i=i+2) { - if (*str) - display[i] = *str++; - else - display[i] = ' '; - } -} - -void mips_display_word(unsigned int num) -{ - volatile unsigned int *display = (void *)ASCII_DISPLAY_WORD_BASE; - - *display = num; -} diff -Nru a/arch/mips64/mips-boards/generic/gdb_hook.c b/arch/mips64/mips-boards/generic/gdb_hook.c --- a/arch/mips64/mips-boards/generic/gdb_hook.c Tue Jul 1 18:44:37 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,202 +0,0 @@ -/* - * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - * - * This is the interface to the remote debugger stub. - * - */ - -#include -#include - -#include -#include - -static struct serial_state rs_table[RS_TABLE_SIZE] = { - SERIAL_PORT_DFNS /* Defined in serial.h */ -}; - -static struct async_struct kdb_port_info = {0}; - - -static __inline__ unsigned int serial_in(struct async_struct *info, int offset) -{ - return inb(info->port + offset); -} - -static __inline__ void serial_out(struct async_struct *info, int offset, - int value) -{ - outb(value, info->port+offset); -} - -void rs_kgdb_hook(int tty_no) { - int t; - struct serial_state *ser = &rs_table[tty_no]; - - kdb_port_info.state = ser; - kdb_port_info.magic = SERIAL_MAGIC; - kdb_port_info.port = ser->port; - kdb_port_info.flags = ser->flags; - - /* - * Clear all interrupts - */ - serial_in(&kdb_port_info, UART_LSR); - serial_in(&kdb_port_info, UART_RX); - serial_in(&kdb_port_info, UART_IIR); - serial_in(&kdb_port_info, UART_MSR); - - /* - * Now, initialize the UART - */ - serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8); /* reset DLAB */ - if (kdb_port_info.flags & ASYNC_FOURPORT) { - kdb_port_info.MCR = UART_MCR_DTR | UART_MCR_RTS; - t = UART_MCR_DTR | UART_MCR_OUT1; - } else { - kdb_port_info.MCR - = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2; - t = UART_MCR_DTR | UART_MCR_RTS; - } - - kdb_port_info.MCR = t; /* no interrupts, please */ - serial_out(&kdb_port_info, UART_MCR, kdb_port_info.MCR); - - /* - * and set the speed of the serial port - * (currently hardwired to 9600 8N1 - */ - - /* baud rate is fixed to 9600 (is this sufficient?)*/ - t = kdb_port_info.state->baud_base / 9600; - /* set DLAB */ - serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8 | UART_LCR_DLAB); - serial_out(&kdb_port_info, UART_DLL, t & 0xff);/* LS of divisor */ - serial_out(&kdb_port_info, UART_DLM, t >> 8); /* MS of divisor */ - /* reset DLAB */ - serial_out(&kdb_port_info, UART_LCR, UART_LCR_WLEN8); -} - -int rs_putDebugChar(char c) -{ - - if (!kdb_port_info.state) { /* need to init device first */ - return 0; - } - - while ((serial_in(&kdb_port_info, UART_LSR) & UART_LSR_THRE) == 0) - ; - - serial_out(&kdb_port_info, UART_TX, c); - - return 1; -} - -char rs_getDebugChar(void) -{ - if (!kdb_port_info.state) { /* need to init device first */ - return 0; - } - - while (!(serial_in(&kdb_port_info, UART_LSR) & 1)) - ; - - return(serial_in(&kdb_port_info, UART_RX)); -} - - -#ifdef CONFIG_MIPS_ATLAS - -#include -#include - -#define INB(a) inb((unsigned long)a) -#define OUTB(x,a) outb(x,(unsigned long)a) - -/* - * This is the interface to the remote debugger stub - * if the Philips part is used for the debug port, - * called from the platform setup code. - * - * PCI init will not have been done yet, we make a - * universal assumption about the way the bootloader (YAMON) - * have located and set up the chip. - */ -static t_uart_saa9730_regmap *kgdb_uart = (void *)(ATLAS_SAA9730_REG + SAA9730_UART_REGS_ADDR); - -static int saa9730_kgdb_active = 0; - -void saa9730_kgdb_hook(void) -{ - volatile unsigned char t; - - /* - * Clear all interrupts - */ - t = INB(&kgdb_uart->Lsr); - t += INB(&kgdb_uart->Msr); - t += INB(&kgdb_uart->Thr_Rbr); - t += INB(&kgdb_uart->Iir_Fcr); - - /* - * Now, initialize the UART - */ - /* 8 data bits, one stop bit, no parity */ - OUTB(SAA9730_LCR_DATA8, &kgdb_uart->Lcr); - - /* baud rate is fixed to 9600 (is this sufficient?)*/ - OUTB(0, &kgdb_uart->BaudDivMsb); /* HACK - Assumes standard crystal */ - OUTB(23, &kgdb_uart->BaudDivLsb); /* HACK - known for MIPS Atlas */ - - /* Set RTS/DTR active */ - OUTB(SAA9730_MCR_DTR | SAA9730_MCR_RTS, &kgdb_uart->Mcr); - saa9730_kgdb_active = 1; -} - -int saa9730_putDebugChar(char c) -{ - - if (!saa9730_kgdb_active) { /* need to init device first */ - return 0; - } - - while (!(INB(&kgdb_uart->Lsr) & SAA9730_LSR_THRE)) - ; - OUTB(c, &kgdb_uart->Thr_Rbr); - - return 1; -} - -char saa9730_getDebugChar(void) -{ - char c; - - if (!saa9730_kgdb_active) { /* need to init device first */ - return 0; - } - while (!(INB(&kgdb_uart->Lsr) & SAA9730_LSR_DR)) - ; - - c = INB(&kgdb_uart->Thr_Rbr); - return(c); -} - -#endif diff -Nru a/arch/mips64/mips-boards/generic/init.c b/arch/mips64/mips-boards/generic/init.c --- a/arch/mips64/mips-boards/generic/init.c Tue Jul 1 18:44:36 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,152 +0,0 @@ -/* - * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - * - * PROM library initialisation code. - */ -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/* Environment variable */ -typedef struct -{ - char *name; - char *val; -}t_env_var; - -int prom_argc; -int *_prom_argv, *_prom_envp; - -/* - * A 32-bit PROM pass arguments and environment as 32-bit pointer. - * This macro take care of sign extension. - */ -#define prom_envp(index) ((char *)(((int *)(int)_prom_envp)[(index)])) - -int init_debug = 0; - -char *prom_getenv(char *envname) -{ - /* - * Return a pointer to the given environment variable. - * We're using 64-bit pointers, but all pointers in the PROM - * structures are only 32-bit, so we need some workarounds. - */ - int i, index=0; - - i = strlen(envname); - - while(prom_envp(index)) { - if(strncmp(envname, prom_envp(index), i) == 0) { - return(prom_envp(index+1)); - } - index += 2; - } - - return(NULL); -} - -static inline unsigned char str2hexnum(unsigned char c) -{ - if(c >= '0' && c <= '9') - return c - '0'; - if(c >= 'a' && c <= 'f') - return c - 'a' + 10; - return 0; /* foo */ -} - -static inline void str2eaddr(unsigned char *ea, unsigned char *str) -{ - int i; - - for(i = 0; i < 6; i++) { - unsigned char num; - - if((*str == '.') || (*str == ':')) - str++; - num = str2hexnum(*str++) << 4; - num |= (str2hexnum(*str++)); - ea[i] = num; - } -} - -int get_ethernet_addr(char *ethernet_addr) -{ - char *ethaddr_str; - - ethaddr_str = prom_getenv("ethaddr"); - if (!ethaddr_str) { - printk("ethaddr not set in boot prom\n"); - return -1; - } - str2eaddr(ethernet_addr, ethaddr_str); - - if (init_debug > 1) - { - int i; - printk("get_ethernet_addr: "); - for (i=0; i<5; i++) - printk("%02x:", (unsigned char)*(ethernet_addr+i)); - printk("%02x\n", *(ethernet_addr+i)); - } - - return 0; -} - -int __init prom_init(int argc, char **argv, char **envp) -{ - prom_argc = argc; - _prom_argv = (int *)argv; - _prom_envp = (int *)envp; - - mips_display_message("LINUX"); - - /* - * Setup the North bridge to do Master byte-lane swapping when - * running in bigendian. - */ -#if defined(__MIPSEL__) - GT_WRITE(GT_PCI0_CMD_OFS, GT_PCI0_CMD_MBYTESWAP_BIT | - GT_PCI0_CMD_SBYTESWAP_BIT); -#else - GT_WRITE(GT_PCI0_CMD_OFS, 0); -#endif - -#if defined(CONFIG_MIPS_MALTA) - mips_io_port_base = MALTA_PORT_BASE; -#else - mips_io_port_base = KSEG1; -#endif - - setup_prom_printf(0); - prom_printf("\nLINUX started...\n"); - prom_init_cmdline(); - prom_meminit(); - - return 0; -} diff -Nru a/arch/mips64/mips-boards/generic/memory.c b/arch/mips64/mips-boards/generic/memory.c --- a/arch/mips64/mips-boards/generic/memory.c Tue Jul 1 18:44:35 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,263 +0,0 @@ -/* - * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - * - * PROM library functions for acquiring/using memory descriptors given to - * us from the YAMON. - * - */ -#include -#include -#include -#include - -#include -#include - -#include - -/*#define DEBUG*/ - -enum yamon_memtypes { - yamon_dontuse, - yamon_prom, - yamon_free, -}; -struct prom_pmemblock mdesc[PROM_MAX_PMEMBLOCKS]; - -#define MEMTYPE_DONTUSE 0 -#define MEMTYPE_PROM 1 -#define MEMTYPE_FREE 2 - -#ifdef DEBUG -static char *mtypes[3] = { - "Dont use memory", - "YAMON PROM memory", - "Free memmory", -}; -#endif - -/* References to section boundaries */ -extern char _end; - -#define PFN_ALIGN(x) (((unsigned long)(x) + (PAGE_SIZE - 1)) & PAGE_MASK) - -struct prom_pmemblock * __init prom_getmdesc(void) -{ - char *memsize_str; - unsigned int memsize; - - memsize_str = prom_getenv("memsize"); - if (!memsize_str) { - prom_printf("memsize not set in boot prom, set to default (32Mb)\n"); - memsize = 0x02000000; - } else { -#ifdef DEBUG - prom_printf("prom_memsize = %s\n", memsize_str); -#endif - memsize = simple_strtol(memsize_str, NULL, 0); - } - - memset(mdesc, 0, sizeof(mdesc)); - - mdesc[0].type = yamon_dontuse; - mdesc[0].base = 0x00000000; - mdesc[0].size = 0x00001000; - - mdesc[1].type = yamon_prom; - mdesc[1].base = 0x00001000; - mdesc[1].size = 0x000ef000; - -#if (CONFIG_MIPS_MALTA) - /* - * The area 0x000f0000-0x000fffff is allocated for BIOS memory by the - * south bridge and PCI access always forwarded to the ISA Bus and - * BIOSCS# is always generated. - * This mean that this area can't be used as DMA memory for PCI - * devices. - */ - mdesc[2].type = yamon_dontuse; - mdesc[2].base = 0x000f0000; - mdesc[2].size = 0x00010000; -#else - mdesc[2].type = yamon_prom; - mdesc[2].base = 0x000f0000; - mdesc[2].size = 0x00010000; -#endif - - mdesc[3].type = yamon_dontuse; - mdesc[3].base = 0x00100000; - mdesc[3].size = CPHYSADDR(PFN_ALIGN(&_end)) - mdesc[3].base; - - mdesc[4].type = yamon_free; - mdesc[4].base = CPHYSADDR(PFN_ALIGN(&_end)); - mdesc[4].size = memsize - mdesc[4].base; - - return &mdesc[0]; -} - -int __init page_is_ram(unsigned long pagenr) -{ - if ((pagenr << PAGE_SHIFT) < mdesc[4].base + mdesc[4].size) - return 1; - - return 0; -} - -static struct prom_pmemblock pblocks[PROM_MAX_PMEMBLOCKS]; - -static int __init prom_memtype_classify (unsigned int type) -{ - switch (type) { - case yamon_free: - return MEMTYPE_FREE; - case yamon_prom: - return MEMTYPE_PROM; - default: - return MEMTYPE_DONTUSE; - } -} - -static inline unsigned long find_max_low_pfn(void) -{ - struct prom_pmemblock *p, *highest; - unsigned long pfn; - - p = pblocks; - highest = 0; - while (p->size != 0) { - if (!highest || p->base > highest->base) - highest = p; - p++; - } - - pfn = (highest->base + highest->size) >> PAGE_SHIFT; -#ifdef DEBUG - prom_printf("find_max_low_pfn: 0x%lx pfns.\n", pfn); -#endif - return pfn; -} - -static inline struct prom_pmemblock *find_largest_memblock(void) -{ - struct prom_pmemblock *p, *largest; - - p = pblocks; - largest = 0; - while (p->size != 0) { - if (!largest || p->size > largest->size) - largest = p; - p++; - } - - return largest; -} - -void __init prom_meminit(void) -{ - struct prom_pmemblock *largest, *p; - unsigned long bootmap_size; - int totram; - int i = 0; - -#ifdef DEBUG - prom_printf("YAMON MEMORY DESCRIPTOR dump:\n"); - p = prom_getmdesc(); - while (p->size) { - prom_printf("[%d,%p]: base<%08lx> size<%08lx> type<%s>\n", - i, p, p->base, p->size, mtypes[p->type]); - p++; - i++; - } -#endif - totram = 0; - i = 0; - p = prom_getmdesc(); - - while (p->size) { - pblocks[i].type = prom_memtype_classify (p->type); - pblocks[i].base = p->base; - pblocks[i].size = p->size; - switch (pblocks[i].type) { - case MEMTYPE_FREE: - totram += pblocks[i].size; -#ifdef DEBUG - prom_printf("free_chunk[%d]: base=%08lx size=%d\n", - i, pblocks[i].base, pblocks[i].size); -#endif - i++; - break; - case MEMTYPE_PROM: -#ifdef DEBUG - prom_printf("prom_chunk[%d]: base=%08lx size=%d\n", - i, pblocks[i].base, pblocks[i].size); -#endif - i++; - break; - default: - break; - } - p++; - } - pblocks[i].base = 0xdeadbeef; - pblocks[i].size = 0; /* indicates last elem. of array */ - - max_low_pfn = find_max_low_pfn(); - largest = find_largest_memblock(); - bootmap_size = init_bootmem(largest->base >> PAGE_SHIFT, max_low_pfn); - - for (i = 0; pblocks[i].size; i++) - if (pblocks[i].type == MEMTYPE_FREE) - free_bootmem(pblocks[i].base, pblocks[i].size); - - /* This test is simpleminded. It will fail if the bootmem bitmap - falls into multiple adjacent PROM memory areas. */ - if (bootmap_size > largest->size) { - prom_printf("CRITIAL: overwriting PROM data.\n"); - BUG(); - } - - /* Reserve the memory bootmap itself */ - reserve_bootmem(largest->base, bootmap_size); - printk("PROMLIB: Total free ram %d bytes (%dK,%dMB)\n", - totram, (totram/1024), (totram/1024/1024)); -} - -void prom_free_prom_memory (void) -{ - struct prom_pmemblock *p; - unsigned long freed = 0; - unsigned long addr; - - for (p = pblocks; p->size != 0; p++) { - if (p->type != MEMTYPE_PROM) - continue; - - addr = p->base; - while (addr < p->base + p->size) { - ClearPageReserved(virt_to_page(__va(addr))); - set_page_count(virt_to_page(__va(addr)), 1); - free_page(__va(addr)); - addr += PAGE_SIZE; - freed += PAGE_SIZE; - } - } - printk("Freeing prom memory: %ldkb freed\n", freed >> 10); -} diff -Nru a/arch/mips64/mips-boards/generic/mipsIRQ.S b/arch/mips64/mips-boards/generic/mipsIRQ.S --- a/arch/mips64/mips-boards/generic/mipsIRQ.S Tue Jul 1 18:44:35 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,122 +0,0 @@ -/* - * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - * - * Interrupt exception dispatch code. - * - */ -#include - -#include -#include -#include -#include - -/* A lot of complication here is taken away because: - * - * 1) We handle one interrupt and return, sitting in a loop and moving across - * all the pending IRQ bits in the cause register is _NOT_ the answer, the - * common case is one pending IRQ so optimize in that direction. - * - * 2) We need not check against bits in the status register IRQ mask, that - * would make this routine slow as hell. - * - * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in - * between like BSD spl() brain-damage. - * - * Furthermore, the IRQs on the MIPS board look basically (barring software - * IRQs which we don't use at all and all external interrupt sources are - * combined together on hardware interrupt 0 (MIPS IRQ 2)) like: - * - * MIPS IRQ Source - * -------- ------ - * 0 Software (ignored) - * 1 Software (ignored) - * 2 Combined hardware interrupt (hw0) - * 3 Hardware (ignored) - * 4 Hardware (ignored) - * 5 Hardware (ignored) - * 6 Hardware (ignored) - * 7 R4k timer (what we use) - * - * We handle the IRQ according to _our_ priority which is: - * - * Highest ---- R4k Timer - * Lowest ---- Combined hardware interrupt - * - * then we just return, if multiple IRQs are pending then we will just take - * another exception, big deal. - */ - - .text - .set noreorder - .set noat - .align 5 - NESTED(mipsIRQ, PT_SIZE, sp) - SAVE_ALL - CLI - .set at - - mfc0 s0, CP0_CAUSE # get irq mask - - /* First we check for r4k counter/timer IRQ. */ - andi a0, s0, CAUSEF_IP7 - beq a0, zero, 1f - andi a0, s0, CAUSEF_IP2 # delay slot, check hw0 interrupt - - /* Wheee, a timer interrupt. */ - move a0, sp - jal mips_timer_interrupt - nop - - j ret_from_irq - nop - -1: - beq a0, zero, 1f - nop - - /* Wheee, combined hardware level zero interrupt. */ -#if defined(CONFIG_MIPS_ATLAS) - jal atlas_hw0_irqdispatch -#elif defined(CONFIG_MIPS_MALTA) - jal malta_hw0_irqdispatch -#else -#error "MIPS board not supported\n" -#endif - move a0, sp # delay slot - - j ret_from_irq - nop # delay slot - -1: - /* - * Here by mistake? This is possible, what can happen is that by the - * time we take the exception the IRQ pin goes low, so just leave if - * this is the case. - */ - move a1,s0 - PRINT("Got interrupt: c0_cause = %08x\n") - mfc0 a1, CP0_EPC - PRINT("c0_epc = %08x\n") - - j ret_from_irq - nop - END(mipsIRQ) diff -Nru a/arch/mips64/mips-boards/generic/pci.c b/arch/mips64/mips-boards/generic/pci.c --- a/arch/mips64/mips-boards/generic/pci.c Tue Jul 1 18:44:32 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,326 +0,0 @@ -/* - * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - * - * MIPS boards specific PCI support. - * - */ -#include - -#ifdef CONFIG_PCI - -#include -#include -#include -#include - -#include -#include -#ifdef CONFIG_MIPS_MALTA -#include -#endif - -#define PCI_ACCESS_READ 0 -#define PCI_ACCESS_WRITE 1 - -static int -mips_pcibios_config_access(unsigned char access_type, struct pci_dev *dev, - unsigned char where, u32 *data) -{ - unsigned char bus = dev->bus->number; - unsigned char dev_fn = dev->devfn; - u32 intr; - - if ((bus == 0) && (dev_fn >= PCI_DEVFN(31,0))) - return -1; /* Because of a bug in the galileo (for slot 31). */ - - /* Clear cause register bits */ - GT_WRITE(GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT | - GT_INTRCAUSE_TARABORT0_BIT)); - - /* Setup address */ - GT_WRITE(GT_PCI0_CFGADDR_OFS, - (bus << GT_PCI0_CFGADDR_BUSNUM_SHF) | - (dev_fn << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | - ((where / 4) << GT_PCI0_CFGADDR_REGNUM_SHF) | - GT_PCI0_CFGADDR_CONFIGEN_BIT); - - if (access_type == PCI_ACCESS_WRITE) { - if (bus == 0 && dev_fn == 0) { - /* - * Galileo is acting differently than other devices. - */ - GT_WRITE(GT_PCI0_CFGDATA_OFS, *data); - } else { - GT_PCI_WRITE(GT_PCI0_CFGDATA_OFS, *data); - } - } else { - if (bus == 0 && dev_fn == 0) { - /* - * Galileo is acting differently than other devices. - */ - GT_READ(GT_PCI0_CFGDATA_OFS, *data); - } else { - GT_PCI_READ(GT_PCI0_CFGDATA_OFS, *data); - } - } - - /* Check for master or target abort */ - GT_READ(GT_INTRCAUSE_OFS, intr); - - if (intr & (GT_INTRCAUSE_MASABORT0_BIT | GT_INTRCAUSE_TARABORT0_BIT)) - { - /* Error occurred */ - - /* Clear bits */ - GT_WRITE( GT_INTRCAUSE_OFS, ~(GT_INTRCAUSE_MASABORT0_BIT | - GT_INTRCAUSE_TARABORT0_BIT) ); - - return -1; - } - - return 0; -} - - -/* - * We can't address 8 and 16 bit words directly. Instead we have to - * read/write a 32bit word and mask/modify the data we actually want. - */ -static int -mips_pcibios_read_config_byte (struct pci_dev *dev, int where, u8 *val) -{ - u32 data = 0; - - if (mips_pcibios_config_access(PCI_ACCESS_READ, dev, where, &data)) - return -1; - - *val = (data >> ((where & 3) << 3)) & 0xff; - - return PCIBIOS_SUCCESSFUL; -} - - -static int -mips_pcibios_read_config_word (struct pci_dev *dev, int where, u16 *val) -{ - u32 data = 0; - - if (where & 1) - return PCIBIOS_BAD_REGISTER_NUMBER; - - if (mips_pcibios_config_access(PCI_ACCESS_READ, dev, where, &data)) - return -1; - - *val = (data >> ((where & 3) << 3)) & 0xffff; - - return PCIBIOS_SUCCESSFUL; -} - -static int -mips_pcibios_read_config_dword (struct pci_dev *dev, int where, u32 *val) -{ - u32 data = 0; - - if (where & 3) - return PCIBIOS_BAD_REGISTER_NUMBER; - - if (mips_pcibios_config_access(PCI_ACCESS_READ, dev, where, &data)) - return -1; - - *val = data; - - return PCIBIOS_SUCCESSFUL; -} - - -static int -mips_pcibios_write_config_byte (struct pci_dev *dev, int where, u8 val) -{ - u32 data = 0; - - if (mips_pcibios_config_access(PCI_ACCESS_READ, dev, where, &data)) - return -1; - - data = (data & ~(0xff << ((where & 3) << 3))) | - (val << ((where & 3) << 3)); - - if (mips_pcibios_config_access(PCI_ACCESS_WRITE, dev, where, &data)) - return -1; - - return PCIBIOS_SUCCESSFUL; -} - -static int -mips_pcibios_write_config_word (struct pci_dev *dev, int where, u16 val) -{ - u32 data = 0; - - if (where & 1) - return PCIBIOS_BAD_REGISTER_NUMBER; - - if (mips_pcibios_config_access(PCI_ACCESS_READ, dev, where, &data)) - return -1; - - data = (data & ~(0xffff << ((where & 3) << 3))) | - (val << ((where & 3) << 3)); - - if (mips_pcibios_config_access(PCI_ACCESS_WRITE, dev, where, &data)) - return -1; - - - return PCIBIOS_SUCCESSFUL; -} - -static int -mips_pcibios_write_config_dword(struct pci_dev *dev, int where, u32 val) -{ - if (where & 3) - return PCIBIOS_BAD_REGISTER_NUMBER; - - if (mips_pcibios_config_access(PCI_ACCESS_WRITE, dev, where, &val)) - return -1; - - return PCIBIOS_SUCCESSFUL; -} - -struct pci_ops mips_pci_ops = { - mips_pcibios_read_config_byte, - mips_pcibios_read_config_word, - mips_pcibios_read_config_dword, - mips_pcibios_write_config_byte, - mips_pcibios_write_config_word, - mips_pcibios_write_config_dword -}; - -void __init pcibios_init(void) -{ -#ifdef CONFIG_MIPS_MALTA - struct pci_dev *pdev = NULL; - unsigned char reg_val; -#endif - - printk("PCI: Probing PCI hardware on host bus 0.\n"); - pci_scan_bus(0, &mips_pci_ops, NULL); - - /* - * Due to a bug in the Galileo system controller, we need to setup - * the PCI BAR for the Galileo internal registers. - * This should be done in the bios/bootprom and will be fixed in - * a later revision of YAMON (the MIPS boards boot prom). - */ - GT_WRITE(GT_PCI0_CFGADDR_OFS, - (0 << GT_PCI0_CFGADDR_BUSNUM_SHF) | /* Local bus */ - (0 << GT_PCI0_CFGADDR_DEVNUM_SHF) | /* GT64120 device */ - (0 << GT_PCI0_CFGADDR_FUNCTNUM_SHF) | /* Function 0 */ - ((0x20/4) << GT_PCI0_CFGADDR_REGNUM_SHF) | /* BAR 4 */ - GT_PCI0_CFGADDR_CONFIGEN_BIT ); - - /* Perform the write */ - GT_WRITE( GT_PCI0_CFGDATA_OFS, CPHYSADDR(MIPS_GT_BASE)); - -#ifdef CONFIG_MIPS_MALTA - while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL) { - if ((pdev->vendor == PCI_VENDOR_ID_INTEL) - && (pdev->device == PCI_DEVICE_ID_INTEL_82371AB) - && (PCI_SLOT(pdev->devfn) == 0x0a)) { - /* - * IDE Decode enable. - */ - pci_read_config_byte(pdev, 0x41, ®_val); - pci_write_config_byte(pdev, 0x41, reg_val | 0x80); - pci_read_config_byte(pdev, 0x43, ®_val); - pci_write_config_byte(pdev, 0x43, reg_val | 0x80); - } - - if ((pdev->vendor == PCI_VENDOR_ID_INTEL) - && (pdev->device == PCI_DEVICE_ID_INTEL_82371AB_0) - && (PCI_SLOT(pdev->devfn) == 0x0a)) { - /* - * Set top of main memory accessible by ISA or DMA - * devices to 16 Mb. - */ - pci_read_config_byte(pdev, 0x69, ®_val); - pci_write_config_byte(pdev, 0x69, reg_val | 0xf0); - } - } - - /* - * Activate Floppy Controller in the SMSC FDC37M817 Super I/O - * Controller. - * This should be done in the bios/bootprom and will be fixed in - * a later revision of YAMON (the MIPS boards boot prom). - */ - /* Entering config state. */ - SMSC_WRITE(SMSC_CONFIG_ENTER, SMSC_CONFIG_REG); - - /* Activate floppy controller. */ - SMSC_WRITE(SMSC_CONFIG_DEVNUM, SMSC_CONFIG_REG); - SMSC_WRITE(SMSC_CONFIG_DEVNUM_FLOPPY, SMSC_DATA_REG); - SMSC_WRITE(SMSC_CONFIG_ACTIVATE, SMSC_CONFIG_REG); - SMSC_WRITE(SMSC_CONFIG_ACTIVATE_ENABLE, SMSC_DATA_REG); - - /* Exit config state. */ - SMSC_WRITE(SMSC_CONFIG_EXIT, SMSC_CONFIG_REG); -#endif -} - -int __init -pcibios_enable_device(struct pci_dev *dev) -{ - /* Not needed, since we enable all devices at startup. */ - return 0; -} - -void __init -pcibios_align_resource(void *data, struct resource *res, - unsigned long size, unsigned long align) -{ -} - -char * __init -pcibios_setup(char *str) -{ - /* Nothing to do for now. */ - - return str; -} - -struct pci_fixup pcibios_fixups[] = { - { 0 } -}; - -#warning pcibios_update_resource() is now a generic implementation - please check - -unsigned __init int pcibios_assign_all_busses(void) -{ - return 1; -} - -/* - * Called after each bus is probed, but before its children - * are examined. - */ -void __init pcibios_fixup_bus(struct pci_bus *b) -{ - pci_read_bridge_bases(b); -} - -#endif /* CONFIG_PCI */ diff -Nru a/arch/mips64/mips-boards/generic/printf.c b/arch/mips64/mips-boards/generic/printf.c --- a/arch/mips64/mips-boards/generic/printf.c Tue Jul 1 18:44:37 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,140 +0,0 @@ -/* - * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - * - * Putting things on the screen/serial line using YAMONs facilities. - * - */ -#include -#include -#include -#include -#include -#include -#include -#include - - -#ifdef CONFIG_MIPS_ATLAS -/* - * Atlas registers are memory mapped on 64-bit aligned boundaries and - * only word access are allowed. - * When reading the UART 8 bit registers only the LSB are valid. - */ -unsigned int atlas_serial_in(struct async_struct *info, int offset) -{ - return (*(volatile unsigned int *)(info->port + mips_io_port_base + offset*8) & 0xff); -} - -void atlas_serial_out(struct async_struct *info, int offset, int value) -{ - *(volatile unsigned int *)(info->port + mips_io_port_base + offset*8) = value; -} - -#define serial_in atlas_serial_in -#define serial_out atlas_serial_out - -#else - -static unsigned int serial_in(struct async_struct *info, int offset) -{ - return inb(info->port + offset); -} - -static void serial_out(struct async_struct *info, int offset, - int value) -{ - outb(value, info->port + offset); -} -#endif - -static struct serial_state rs_table[] = { - SERIAL_PORT_DFNS /* Defined in serial.h */ -}; - -/* - * Hooks to fake "prom" console I/O before devices - * are fully initialized. - */ -static struct async_struct prom_port_info = {0}; - -void __init setup_prom_printf(int tty_no) { - struct serial_state *ser = &rs_table[tty_no]; - - prom_port_info.state = ser; - prom_port_info.magic = SERIAL_MAGIC; - prom_port_info.port = ser->port; - prom_port_info.flags = ser->flags; - - /* No setup of UART - assume YAMON left in sane state */ -} - -int putPromChar(char c) -{ - if (!prom_port_info.state) { /* need to init device first */ - return 0; - } - - while ((serial_in(&prom_port_info, UART_LSR) & UART_LSR_THRE) == 0) - ; - - serial_out(&prom_port_info, UART_TX, c); - - return 1; -} - -char getPromChar(void) -{ - if (!prom_port_info.state) { /* need to init device first */ - return 0; - } - - while (!(serial_in(&prom_port_info, UART_LSR) & 1)) - ; - - return(serial_in(&prom_port_info, UART_RX)); -} - -static char buf[1024]; - -void __init prom_printf(char *fmt, ...) -{ - va_list args; - int l; - char *p, *buf_end; - long flags; - - int putPromChar(char); - - /* Low level, brute force, not SMP safe... */ - save_and_cli(flags); - va_start(args, fmt); - l = vsprintf(buf, fmt, args); /* hopefully i < sizeof(buf) */ - va_end(args); - - buf_end = buf + l; - - for (p = buf; p < buf_end; p++) { - /* Crude cr/nl handling is better than none */ - if(*p == '\n')putPromChar('\r'); - putPromChar(*p); - } - restore_flags(flags); -} diff -Nru a/arch/mips64/mips-boards/generic/reset.c b/arch/mips64/mips-boards/generic/reset.c --- a/arch/mips64/mips-boards/generic/reset.c Tue Jul 1 18:44:39 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,61 +0,0 @@ -/* - * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - * - * Reset the MIPS boards. - * - */ -#include - -#include -#if defined(CONFIG_MIPS_ATLAS) -#include -#endif - -void machine_restart(char *command) __attribute__((noreturn)); -void machine_halt(void) __attribute__((noreturn)); -#if defined(CONFIG_MIPS_ATLAS) -void machine_power_off(void) __attribute__((noreturn)); -#endif - -void machine_restart(char *command) -{ - volatile unsigned int *softres_reg = (void *)SOFTRES_REG; - - *softres_reg = GORESET; -} - -void machine_halt(void) -{ - volatile unsigned int *softres_reg = (void *)SOFTRES_REG; - - *softres_reg = GORESET; -} - -void machine_power_off(void) -{ -#if defined(CONFIG_MIPS_ATLAS) - volatile unsigned int *psustby_reg = (void *)ATLAS_PSUSTBY_REG; - - *psustby_reg = ATLAS_GOSTBY; -#else - machine_halt(); -#endif -} diff -Nru a/arch/mips64/mips-boards/generic/time.c b/arch/mips64/mips-boards/generic/time.c --- a/arch/mips64/mips-boards/generic/time.c Tue Jul 1 18:44:33 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,409 +0,0 @@ -/* - * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - * - * Setting up the clock on the MIPS boards. - * - */ - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include - -extern volatile unsigned long wall_jiffies; -static long last_rtc_update = 0; -unsigned long missed_heart_beats = 0; - -static unsigned long r4k_offset; /* Amount to increment compare reg each time */ -static unsigned long r4k_cur; /* What counter should be at next timer irq */ - -#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5) - -#if defined(CONFIG_MIPS_ATLAS) -static char display_string[] = " LINUX ON ATLAS "; -#endif -#if defined(CONFIG_MIPS_MALTA) -static char display_string[] = " LINUX ON MALTA "; -#endif -static unsigned int display_count = 0; -#define MAX_DISPLAY_COUNT (sizeof(display_string) - 8) - -static unsigned int timer_tick_count=0; - - -static inline void ack_r4ktimer(unsigned long newval) -{ - write_32bit_cp0_register(CP0_COMPARE, newval); -} - - -/* - * In order to set the CMOS clock precisely, set_rtc_mmss has to be - * called 500 ms after the second nowtime has started, because when - * nowtime is written into the registers of the CMOS clock, it will - * jump to the next second precisely 500 ms later. Check the Motorola - * MC146818A or Dallas DS12887 data sheet for details. - * - * BUG: This routine does not handle hour overflow properly; it just - * sets the minutes. Usually you won't notice until after reboot! - */ -static int set_rtc_mmss(unsigned long nowtime) -{ - int retval = 0; - int real_seconds, real_minutes, cmos_minutes; - unsigned char save_control, save_freq_select; - - save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ - CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); - - save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */ - CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); - - cmos_minutes = CMOS_READ(RTC_MINUTES); - - /* - * since we're only adjusting minutes and seconds, - * don't interfere with hour overflow. This avoids - * messing with unknown time zones but requires your - * RTC not to be off by more than 15 minutes - */ - real_seconds = nowtime % 60; - real_minutes = nowtime / 60; - if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) - real_minutes += 30; /* correct for half hour time zone */ - real_minutes %= 60; - - if (abs(real_minutes - cmos_minutes) < 30) { - CMOS_WRITE(real_seconds,RTC_SECONDS); - CMOS_WRITE(real_minutes,RTC_MINUTES); - } else { - printk(KERN_WARNING - "set_rtc_mmss: can't update from %d to %d\n", - cmos_minutes, real_minutes); - retval = -1; - } - - /* The following flags have to be released exactly in this order, - * otherwise the DS12887 (popular MC146818A clone with integrated - * battery and quartz) will not reset the oscillator and will not - * update precisely 500 ms later. You won't find this mentioned in - * the Dallas Semiconductor data sheets, but who believes data - * sheets anyway ... -- Markus Kuhn - */ - CMOS_WRITE(save_control, RTC_CONTROL); - CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); - - return retval; -} - -/* - * There are a lot of conceptually broken versions of the MIPS timer interrupt - * handler floating around. This one is rather different, but the algorithm - * is provably more robust. - */ -void mips_timer_interrupt(struct pt_regs *regs) -{ - unsigned long flags; - unsigned long seq; - int irq = 7; - - if (r4k_offset == 0) - goto null; - - do { - kstat_cpu(0).irqs[irq]++; - do_timer(regs); - - /* Historical comment/code: - * RTC time of day s updated approx. every 11 - * minutes. Because of how the numbers work out - * we need to make absolutely sure we do this update - * within 500ms before the * next second starts, - * thus the following code. - */ - do { - seq = read_seqbegin_irqsave(&xtime_lock, flags); - - 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)) - if (set_rtc_mmss(xtime.tv_sec) == 0) - last_rtc_update = xtime.tv_sec; - else - /* do it again in 60 s */ - last_rtc_update = xtime.tv_sec - 600; - } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); - - - if ((timer_tick_count++ % HZ) == 0) { - mips_display_message(&display_string[display_count++]); - if (display_count == MAX_DISPLAY_COUNT) - display_count = 0; - } - - r4k_cur += r4k_offset; - ack_r4ktimer(r4k_cur); - - } while (((unsigned int)read_32bit_cp0_register(CP0_COUNT) - - (unsigned int)r4k_cur) < 0x7fffffff); - - return; - -null: - ack_r4ktimer(0); -} - -/* - * Figure out the r4k offset, the amount to increment the compare - * register for each time tick. - * Use the RTC to calculate offset. - */ -static unsigned long __init cal_r4koff(void) -{ - unsigned long count; - unsigned int flags; - - local_irq_save(flags); - - /* Start counter exactly on falling edge of update flag */ - while (CMOS_READ(RTC_REG_A) & RTC_UIP); - while (!(CMOS_READ(RTC_REG_A) & RTC_UIP)); - - /* Start r4k counter. */ - write_32bit_cp0_register(CP0_COUNT, 0); - - /* Read counter exactly on falling edge of update flag */ - while (CMOS_READ(RTC_REG_A) & RTC_UIP); - while (!(CMOS_READ(RTC_REG_A) & RTC_UIP)); - - count = read_32bit_cp0_register(CP0_COUNT); - - /* restore interrupts */ - local_irq_restore(flags); - - return (count / HZ); -} - -static unsigned long __init get_mips_time(void) -{ - unsigned int year, mon, day, hour, min, sec; - unsigned char save_control; - - save_control = CMOS_READ(RTC_CONTROL); - - /* Freeze it. */ - CMOS_WRITE(save_control | RTC_SET, RTC_CONTROL); - - /* Read regs. */ - sec = CMOS_READ(RTC_SECONDS); - min = CMOS_READ(RTC_MINUTES); - hour = CMOS_READ(RTC_HOURS); - - if (!(save_control & RTC_24H)) - { - if ((hour & 0xf) == 0xc) - hour &= 0x80; - if (hour & 0x80) - hour = (hour & 0xf) + 12; - } - day = CMOS_READ(RTC_DAY_OF_MONTH); - mon = CMOS_READ(RTC_MONTH); - year = CMOS_READ(RTC_YEAR); - - /* Unfreeze clock. */ - CMOS_WRITE(save_control, RTC_CONTROL); - - if ((year += 1900) < 1970) - year += 100; - - return mktime(year, mon, day, hour, min, sec); -} - -void __init time_init(void) -{ - unsigned int est_freq, flags; - - /* Set Data mode - binary. */ - CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL); - - printk("calculating r4koff... "); - r4k_offset = cal_r4koff(); - printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset); - - est_freq = 2*r4k_offset*HZ; - est_freq += 5000; /* round */ - est_freq -= est_freq%10000; - printk("CPU frequency %d.%02d MHz\n", est_freq/1000000, - (est_freq%1000000)*100/1000000); - r4k_cur = (read_32bit_cp0_register(CP0_COUNT) + r4k_offset); - - write_32bit_cp0_register(CP0_COMPARE, r4k_cur); - set_cp0_status(ST0_IM, ALLINTS); - - /* Read time from the RTC chipset. */ - write_seqlock_irqsave (&xtime_lock, flags); - xtime.tv_sec = get_mips_time(); - xtime.tv_usec = 0; - write_sequnlock_irqrestore(&xtime_lock, flags); -} - -/* This is for machines which generate the exact clock. */ -#define USECS_PER_JIFFY (1000000/HZ) -#define USECS_PER_JIFFY_FRAC (0x100000000*1000000/HZ&0xffffffff) - -/* Cycle counter value at the previous timer interrupt.. */ - -static unsigned int timerhi = 0, timerlo = 0; - -/* - * FIXME: Does playing with the RP bit in c0_status interfere with this code? - */ -static unsigned long do_fast_gettimeoffset(void) -{ - u32 count; - unsigned long res, tmp; - - /* Last jiffy when do_fast_gettimeoffset() was called. */ - static unsigned long last_jiffies=0; - unsigned long quotient; - - /* - * Cached "1/(clocks per usec)*2^32" value. - * It has to be recalculated once each jiffy. - */ - static unsigned long cached_quotient=0; - - tmp = jiffies; - - quotient = cached_quotient; - - if (tmp && last_jiffies != tmp) { - last_jiffies = tmp; - __asm__(".set\tnoreorder\n\t" - ".set\tnoat\n\t" - ".set\tmips3\n\t" - "lwu\t%0,%2\n\t" - "dsll32\t$1,%1,0\n\t" - "or\t$1,$1,%0\n\t" - "ddivu\t$0,$1,%3\n\t" - "mflo\t$1\n\t" - "dsll32\t%0,%4,0\n\t" - "nop\n\t" - "ddivu\t$0,%0,$1\n\t" - "mflo\t%0\n\t" - ".set\tmips0\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=&r" (quotient) - :"r" (timerhi), - "m" (timerlo), - "r" (tmp), - "r" (USECS_PER_JIFFY) - :"$1"); - cached_quotient = quotient; - } - - /* Get last timer tick in absolute kernel time */ - count = read_32bit_cp0_register(CP0_COUNT); - - /* .. relative to previous jiffy (32 bits is enough) */ - count -= timerlo; - - __asm__("multu\t%1,%2\n\t" - "mfhi\t%0" - :"=r" (res) - :"r" (count), - "r" (quotient)); - - /* - * Due to possible jiffies inconsistencies, we need to check - * the result so that we'll get a timer that is monotonic. - */ - if (res >= USECS_PER_JIFFY) - res = USECS_PER_JIFFY-1; - - return res; -} - -void do_gettimeofday(struct timeval *tv) -{ - unsigned long flags; - unsigned long seq; - - do { - seq = read_seqbegin_irqsave(&xtime_lock, flags); - - *tv = xtime; - tv->tv_usec += do_fast_gettimeoffset(); - - /* - * xtime is atomically updated in timer_bh. - * jiffies - wall_jiffies - * is nonzero if the timer bottom half hasnt executed yet. - */ - if (jiffies - wall_jiffies) - tv->tv_usec += USECS_PER_JIFFY; - - } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); - - - if (tv->tv_usec >= 1000000) { - tv->tv_usec -= 1000000; - tv->tv_sec++; - } -} - -void do_settimeofday(struct timeval *tv) -{ - write_seqlock_irq (&xtime_lock); - - /* This is revolting. We need to set the xtime.tv_usec correctly. - * However, the value in this location is is value at the last tick. - * Discover what correction gettimeofday would have done, and then - * undo it! - */ - tv->tv_usec -= do_fast_gettimeoffset(); - - if (tv->tv_usec < 0) { - tv->tv_usec += 1000000; - tv->tv_sec--; - } - - xtime = *tv; - time_adjust = 0; /* stop active adjtime() */ - time_status |= STA_UNSYNC; - time_maxerror = NTP_PHASE_LIMIT; - time_esterror = NTP_PHASE_LIMIT; - - write_sequnlock_irq (&xtime_lock); -} diff -Nru a/arch/mips64/mips-boards/malta/Makefile b/arch/mips64/mips-boards/malta/Makefile --- a/arch/mips64/mips-boards/malta/Makefile Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,26 +0,0 @@ -# -# Carsten Langgaard, carstenl@mips.com -# Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. -# -# ######################################################################## -# -# This program is free software; you can distribute it and/or modify it -# under the terms of the GNU General Public License (Version 2) as -# published by the Free Software Foundation. -# -# This program is distributed in the hope it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. -# -# ####################################################################### -# -# Makefile for the MIPS Malta specific kernel interface routines -# under Linux. -# - -obj-y := malta_int.o malta_rtc.o malta_setup.o diff -Nru a/arch/mips64/mips-boards/malta/malta_int.c b/arch/mips64/mips-boards/malta/malta_int.c --- a/arch/mips64/mips-boards/malta/malta_int.c Tue Jul 1 18:44:36 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,391 +0,0 @@ -/* - * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - * - * Routines for generic manipulation of the interrupts found on the MIPS - * Malta board. - * The interrupt controller is located in the South Bridge a PIIX4 device - * with two internal 82C95 interrupt controllers. - * - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -extern asmlinkage void mipsIRQ(void); - -unsigned int local_bh_count[NR_CPUS]; -unsigned int local_irq_count[NR_CPUS]; -unsigned long spurious_count = 0; - -static struct irqaction *hw0_irq_action[MALTAINT_END] = { - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL -}; - -static struct irqaction r4ktimer_action = { - NULL, 0, 0, "R4000 timer/counter", NULL, NULL, -}; - -static struct irqaction *irq_action[8] = { - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, &r4ktimer_action -}; - -#if 0 -#define DEBUG_INT(x...) printk(x) -#else -#define DEBUG_INT(x...) -#endif - -/* - * This contains the interrupt mask for both 82C59 interrupt controllers. - */ -static unsigned int cached_int_mask = 0xffff; - - -void disable_irq(unsigned int irq_nr) -{ - unsigned long flags; - - if(irq_nr >= MALTAINT_END) { - printk("whee, invalid irq_nr %d\n", irq_nr); - panic("IRQ, you lose..."); - } - - save_and_cli(flags); - cached_int_mask |= (1 << irq_nr); - if (irq_nr & 8) { - outb((cached_int_mask >> 8) & 0xff, PIIX4_ICTLR2_OCW1); - } else { - outb(cached_int_mask & 0xff, PIIX4_ICTLR1_OCW1); - } - restore_flags(flags); -} - - -void enable_irq(unsigned int irq_nr) -{ - unsigned long flags; - - if(irq_nr >= MALTAINT_END) { - printk("whee, invalid irq_nr %d\n", irq_nr); - panic("IRQ, you lose..."); - } - - save_and_cli(flags); - cached_int_mask &= ~(1 << irq_nr); - if (irq_nr & 8) { - outb((cached_int_mask >> 8) & 0xff, PIIX4_ICTLR2_OCW1); - - /* Enable irq 2 (cascade interrupt). */ - cached_int_mask &= ~(1 << 2); - outb(cached_int_mask & 0xff, PIIX4_ICTLR1_OCW1); - } else { - outb(cached_int_mask & 0xff, PIIX4_ICTLR1_OCW1); - } - restore_flags(flags); -} - - -int show_interrupts(struct seq_file *p, void *v) -{ - int i; - int num = 0; - struct irqaction *action; - unsigned long flags; - - for (i = 0; i < 8; i++, num++) { - local_irq_save(flags); - action = irq_action[i]; - if (!action) - goto skip_1; - seq_printf(p, "%2d: %8d %c %s", - num, kstat_cpu(0).irqs[num], - (action->flags & SA_INTERRUPT) ? '+' : ' ', - action->name); - for (action=action->next; action; action = action->next) { - seq_printf(p, ",%s %s", - (action->flags & SA_INTERRUPT) ? " +" : "", - action->name); - } - seq_puts(p, " [on-chip]\n"); -skip_1: - local_irq_restore(flags); - } - for (i = 0; i < MALTAINT_END; i++, num++) { - local_irq_save(flags); - action = hw0_irq_action[i]; - if (!action) - goto skip_2; - seq_printf(p, "%2d: %8d %c %s", - num, kstat_cpu(0).irqs[num], - (action->flags & SA_INTERRUPT) ? '+' : ' ', - action->name); - for (action=action->next; action; action = action->next) { - seq_printf(p, ",%s %s", - (action->flags & SA_INTERRUPT) ? " +" : "", - action->name); - } - seq_puts(p, " [hw0]\n"); -skip_2: - local_irq_restore(flags); - } - return 0; -} - -int request_irq(unsigned int irq, - void (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, - const char * devname, - void *dev_id) -{ - struct irqaction *action; - int retval; - - DEBUG_INT("request_irq: irq=%d, devname = %s\n", irq, devname); - - if (irq >= MALTAINT_END) - return -EINVAL; - if (!handler) - return -EINVAL; - - action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL); - if(!action) - return -ENOMEM; - - action->handler = handler; - action->flags = irqflags; - action->mask = 0; - action->name = devname; - action->dev_id = dev_id; - action->next = 0; - - retval = setup_irq(irq, action); - if (retval) - kfree(action); - - return retval; -} - - -void free_irq(unsigned int irq, void *dev_id) -{ - struct irqaction *action, **p; - - if (irq >= MALTAINT_END) { - printk("Trying to free IRQ%d\n",irq); - return; - } - - for (p = &hw0_irq_action[irq]; (action = *p) != NULL; - p = &action->next) - { - if (action->dev_id != dev_id) - continue; - - /* Found it - now free it */ - *p = action->next; - kfree(action); - if (!hw0_irq_action[irq]) - disable_irq(irq); - return; - } - printk("Trying to free IRQ%d\n",irq); -} - -void __init init_IRQ(void) -{ - irq_setup(); -} - -static int setup_irq(unsigned int irq, struct irqaction * new) -{ - int shared = 0; - struct irqaction *old, **p; - - p = &hw0_irq_action[irq]; - if ((old = *p) != NULL) { - /* Can't share interrupts unless both agree to */ - if (!(old->flags & new->flags & SA_SHIRQ)) - return -EBUSY; - - /* Can't share interrupts unless both are same type */ - if ((old->flags ^ new->flags) & SA_INTERRUPT) - return -EBUSY; - - /* add new interrupt at end of irq queue */ - do { - p = &old->next; - old = *p; - } while (old); - shared = 1; - } - - if (new->flags & SA_SAMPLE_RANDOM) - rand_initialize_irq(irq); - - *p = new; - if (!shared) - enable_irq(irq); - - return 0; -} - -static inline int get_int(int *irq) -{ - /* - * Determine highest priority pending interrupt by performing - * a PCI Interrupt Acknowledge cycle. - */ - GT_READ(GT_PCI0_IACK_OFS, *irq); - *irq &= 0xFF; - - /* - * IRQ7 is used to detect spurious interrupts. - * The interrupt acknowledge cycle returns IRQ7, if no - * interrupts is requested. - * We can differentiate between this situation and a - * "Normal" IRQ7 by reading the ISR. - */ - if (*irq == 7) - { - outb(PIIX4_OCW3_SEL | PIIX4_OCW3_ISR, PIIX4_ICTLR1_OCW3); - if (!(inb(PIIX4_ICTLR1_OCW3) & (1 << 7))) - return -1; /* Spurious interrupt. */ - } - - return 0; -} - -static inline void ack_int(int irq) -{ - if (irq & 8) { - /* Specific EOI to cascade */ - outb(PIIX4_OCW2_SEL | PIIX4_OCW2_NSEOI | PIIX4_OCW2_ILS_2, - PIIX4_ICTLR1_OCW2); - - /* Non specific EOI to cascade */ - outb(PIIX4_OCW2_SEL | PIIX4_OCW2_NSEOI, PIIX4_ICTLR2_OCW2); - } else { - /* Non specific EOI to cascade */ - outb(PIIX4_OCW2_SEL | PIIX4_OCW2_NSEOI, PIIX4_ICTLR1_OCW2); - } -} - -void malta_hw0_irqdispatch(struct pt_regs *regs) -{ - struct irqaction *action; - int irq=0, cpu = smp_processor_id(); - - DEBUG_INT("malta_hw0_irqdispatch\n"); - - if (get_int(&irq)) - return; /* interrupt has already been cleared */ - - disable_irq(irq); - ack_int(irq); - - DEBUG_INT("malta_hw0_irqdispatch: irq=%d\n", irq); - action = hw0_irq_action[irq]; - - /* - * if action == NULL, then we don't have a handler - * for the irq - */ - if ( action == NULL ) - return; - - irq_enter(cpu, irq); - kstat_cpu(0).irqs[irq + 8]++; - do { - action->handler(irq, action->dev_id, regs); - action = action->next; - } while (action); - - enable_irq(irq); - irq_exit(cpu, irq); -} - - -unsigned long probe_irq_on (void) -{ - unsigned int i, irqs = 0; - unsigned long delay; - - /* first, enable any unassigned irqs */ - for (i = MALTAINT_END-1; i > 0; i--) { - if (!hw0_irq_action[i]) { - enable_irq(i); - irqs |= (1 << i); - } - } - - /* wait for spurious interrupts to mask themselves out again */ - for (delay = jiffies + HZ/10; time_before(jiffies, delay); ) - /* about 100ms delay */; - - /* now filter out any obviously spurious interrupts */ - return irqs & ~cached_int_mask; -} - - -int probe_irq_off (unsigned long irqs) -{ - unsigned int i; - - irqs &= cached_int_mask; - if (!irqs) - return 0; - i = ffz(~irqs); - if (irqs != (irqs & (1 << i))) - i = -i; - - return i; -} - - -void __init maltaint_init(void) -{ - /* - * Mask out all interrupt by writing "1" to all bit position in - * the IMR register. - */ - outb(cached_int_mask & 0xff, PIIX4_ICTLR1_OCW1); - outb((cached_int_mask >> 8) & 0xff, PIIX4_ICTLR2_OCW1); - - /* Now safe to set the exception vector. */ - set_except_vector(0, mipsIRQ); -} diff -Nru a/arch/mips64/mips-boards/malta/malta_rtc.c b/arch/mips64/mips-boards/malta/malta_rtc.c --- a/arch/mips64/mips-boards/malta/malta_rtc.c Tue Jul 1 18:44:39 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,50 +0,0 @@ -/* - * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - * - * RTC routines for Malta style attached PIIX4 device, which contains a - * Motorola MC146818A-compatible Real Time Clock. - * - */ -#include -#include - -static unsigned char malta_rtc_read_data(unsigned long addr) -{ - outb(addr, MALTA_RTC_ADR_REG); - return inb(MALTA_RTC_DAT_REG); -} - -static void malta_rtc_write_data(unsigned char data, unsigned long addr) -{ - outb(addr, MALTA_RTC_ADR_REG); - outb(data, MALTA_RTC_DAT_REG); -} - -static int malta_rtc_bcd_mode(void) -{ - return 0; -} - -struct rtc_ops malta_rtc_ops = { - &malta_rtc_read_data, - &malta_rtc_write_data, - &malta_rtc_bcd_mode -}; diff -Nru a/arch/mips64/mips-boards/malta/malta_setup.c b/arch/mips64/mips-boards/malta/malta_setup.c --- a/arch/mips64/mips-boards/malta/malta_setup.c Tue Jul 1 18:44:35 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,170 +0,0 @@ -/* - * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. - * - * ######################################################################## - * - * This program is free software; you can distribute it and/or modify it - * under the terms of the GNU General Public License (Version 2) as - * published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - * - * Malta specific setup, including init of the feature struct. - * - */ -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_BLK_DEV_IDE -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_BLK_DEV_FD -#include -#endif -#include -#include - -#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_PROM_CONSOLE) -extern void console_setup(char *, int *); -char serial_console[20]; -#endif - -#ifdef CONFIG_REMOTE_DEBUG -extern void set_debug_traps(void); -extern void rs_kgdb_hook(int); -extern void breakpoint(void); -static int remote_debug = 0; -#endif - -#ifdef CONFIG_BLK_DEV_IDE -extern struct ide_ops std_ide_ops; -#endif -#ifdef CONFIG_BLK_DEV_FD -extern struct fd_ops std_fd_ops; -#endif -extern struct rtc_ops malta_rtc_ops; - -extern void mips_reboot_setup(void); - -struct resource standard_io_resources[] = { - { "dma1", 0x00, 0x1f, IORESOURCE_BUSY }, - { "pic1", 0x20, 0x3f, IORESOURCE_BUSY }, - { "timer", 0x40, 0x5f, IORESOURCE_BUSY }, - { "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY }, - { "pic2", 0xa0, 0xbf, IORESOURCE_BUSY }, - { "dma2", 0xc0, 0xdf, IORESOURCE_BUSY }, -}; - -#define STANDARD_IO_RESOURCES (sizeof(standard_io_resources)/sizeof(struct resource)) - -static void __init malta_irq_setup(void) -{ - maltaint_init(); - -#ifdef CONFIG_REMOTE_DEBUG - if (remote_debug) { - set_debug_traps(); - breakpoint(); - } -#endif -} - - -void __init malta_setup(void) -{ -#ifdef CONFIG_REMOTE_DEBUG - int rs_putDebugChar(char); - char rs_getDebugChar(void); - extern int (*putDebugChar)(char); - extern char (*getDebugChar)(void); -#endif - char *argptr; - int i; - - current_cpu_data.asid_cache = ASID_FIRST_VERSION; - TLBMISS_HANDLER_SETUP(); - - irq_setup = malta_irq_setup; - - /* Request I/O space for devices used on the Malta board. */ - for (i = 0; i < STANDARD_IO_RESOURCES; i++) - request_resource(&ioport_resource, standard_io_resources+i); - - /* - * Enable DMA channel 4 (cascade channel) in the PIIX4 south bridge. - */ - enable_dma(4); - -#ifdef CONFIG_SERIAL_CONSOLE - argptr = prom_getcmdline(); - if ((argptr = strstr(argptr, "console=ttyS0")) == NULL) - { - int i=0; - char *s = prom_getenv("modetty0"); - while(s[i] >= '0' && s[i] <= '9') - i++; - strcpy(serial_console, "ttyS0,"); - strncpy(serial_console + 6, s, i); - prom_printf("Config serial console: %s\n", serial_console); - console_setup(serial_console, NULL); - } -#endif - -#ifdef CONFIG_REMOTE_DEBUG - argptr = prom_getcmdline(); - if ((argptr = strstr(argptr, "kgdb=ttyS")) != NULL) { - int line; - argptr += strlen("kgdb=ttyS"); - if (*argptr != '0' && *argptr != '1') - printk("KGDB: Uknown serial line /dev/ttyS%c, " - "falling back to /dev/ttyS1\n", *argptr); - line = *argptr == '0' ? 0 : 1; - printk("KGDB: Using serial line /dev/ttyS%d for session\n", - line ? 1 : 0); - - rs_kgdb_hook(line); - putDebugChar = rs_putDebugChar; - getDebugChar = rs_getDebugChar; - - prom_printf("KGDB: Using serial line /dev/ttyS%d for session, " - "please connect your debugger\n", line ? 1 : 0); - - remote_debug = 1; - /* Breakpoints and stuff are in malta_irq_setup() */ - } -#endif - - argptr = prom_getcmdline(); - if ((argptr = strstr(argptr, "nofpu")) != NULL) - mips_cpu.options &= ~MIPS_CPU_FPU; - - rtc_ops = &malta_rtc_ops; -#ifdef CONFIG_BLK_DEV_IDE - ide_ops = &std_ide_ops; -#endif -#ifdef CONFIG_BLK_DEV_FD - fd_ops = &std_fd_ops; -#endif -} diff -Nru a/arch/mips64/mm/Makefile b/arch/mips64/mm/Makefile --- a/arch/mips64/mm/Makefile Tue Jul 1 18:44:31 2003 +++ b/arch/mips64/mm/Makefile Tue Jul 1 18:44:31 2003 @@ -2,11 +2,31 @@ # Makefile for the Linux/MIPS-specific parts of the memory manager. # -obj-y := extable.o init.o fault.o loadmmu.o +obj-y := cache.o extable.o init.o fault.o loadmmu.o \ + pgtable.o tlbex-r4k.o -obj-$(CONFIG_CPU_R4300) += r4xx0.o -obj-$(CONFIG_CPU_R4X00) += r4xx0.o -obj-$(CONFIG_CPU_R5000) += r4xx0.o -obj-$(CONFIG_CPU_NEVADA) += r4xx0.o -obj-$(CONFIG_CPU_R10000) += andes.o -obj-$(CONFIG_SGI_IP22) += umap.o +obj-$(CONFIG_CPU_R4300) += c-r4k.o pg-r4k.o tlb-r4k.o tlb-glue-r4k.o +obj-$(CONFIG_CPU_R4X00) += c-r4k.o pg-r4k.o tlb-r4k.o tlb-glue-r4k.o +obj-$(CONFIG_CPU_R5000) += c-r4k.o pg-r4k.o tlb-r4k.o sc-r5k.o \ + tlb-glue-r4k.o +obj-$(CONFIG_CPU_NEVADA) += c-r4k.o pg-r4k.o tlb-r4k.o sc-r5k.o \ + tlb-glue-r4k.o +obj-$(CONFIG_CPU_R5432) += c-r4k.o pg-r4k.o tlb-r4k.o tlb-glue-r4k.o +obj-$(CONFIG_CPU_RM7000) += c-r4k.o pg-r4k.o tlb-r4k.o tlb-glue-r4k.o +obj-$(CONFIG_CPU_R10000) += c-r4k.o pg-r4k.o tlb-andes.o tlb-glue-r4k.o +obj-$(CONFIG_CPU_SB1) += c-sb1.o pg-sb1.o tlb-sb1.o tlb-glue-sb1.o \ + cex-sb1.o cerr-sb1.o +obj-$(CONFIG_CPU_MIPS64) += c-r4k.o pg-r4k.o tlb-r4k.o tlb-glue-r4k.o + +# +# Debug TLB exception handler, currently unused +# +#obj-y += tlb-dbg-r4k.o + +obj-$(CONFIG_CPU_RM7000) += sc-rm7k.o +obj-$(CONFIG_R5000_CPU_SCACHE) += sc-r5k.o +obj-$(CONFIG_SGI_IP22) += sc-ip22.o + +AFLAGS_tlb-glue-r4k.o := -P + +EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips64/mm/andes.c b/arch/mips64/mm/andes.c --- a/arch/mips64/mm/andes.c Tue Jul 1 18:44:31 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,391 +0,0 @@ -/* - * 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) 1997, 1998, 1999 Ralf Baechle (ralf@gnu.org) - * Copyright (C) 1999 Silicon Graphics, Inc. - * Copyright (C) 2000 Kanoj Sarcar (kanoj@sgi.com) - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static int scache_lsz64; - -/* - * This version has been tuned on an Origin. For other machines the arguments - * of the pref instructin may have to be tuned differently. - */ -static void andes_clear_page(void * page) -{ - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%2\n" - "1:\tpref 7,512(%0)\n\t" - "sd\t$0,(%0)\n\t" - "sd\t$0,8(%0)\n\t" - "sd\t$0,16(%0)\n\t" - "sd\t$0,24(%0)\n\t" - "daddiu\t%0,64\n\t" - "sd\t$0,-32(%0)\n\t" - "sd\t$0,-24(%0)\n\t" - "sd\t$0,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sd\t$0,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (page) - :"0" (page), "I" (PAGE_SIZE) - :"$1", "memory"); -} - -/* R10000 has no Create_Dirty type cacheops. */ -static void andes_copy_page(void * to, void * from) -{ - unsigned long dummy1, dummy2, reg1, reg2, reg3, reg4; - - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%8\n" - "1:\tpref\t0,2*128(%1)\n\t" - "pref\t1,2*128(%0)\n\t" - "ld\t%2,(%1)\n\t" - "ld\t%3,8(%1)\n\t" - "ld\t%4,16(%1)\n\t" - "ld\t%5,24(%1)\n\t" - "sd\t%2,(%0)\n\t" - "sd\t%3,8(%0)\n\t" - "sd\t%4,16(%0)\n\t" - "sd\t%5,24(%0)\n\t" - "daddiu\t%0,64\n\t" - "daddiu\t%1,64\n\t" - "ld\t%2,-32(%1)\n\t" - "ld\t%3,-24(%1)\n\t" - "ld\t%4,-16(%1)\n\t" - "ld\t%5,-8(%1)\n\t" - "sd\t%2,-32(%0)\n\t" - "sd\t%3,-24(%0)\n\t" - "sd\t%4,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - " sd\t%5,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2), - "=&r" (reg3), "=&r" (reg4) - :"0" (to), "1" (from), "I" (PAGE_SIZE)); -} - -/* Cache operations. These are only used with the virtual memory system, - not for non-coherent I/O so it's ok to ignore the secondary caches. */ -static void -andes_flush_cache_l1(void) -{ - blast_dcache32(); blast_icache64(); -} - -/* - * This is only used during initialization time. vmalloc() also calls - * this, but that will be changed pretty soon. - */ -static void -andes_flush_cache_l2(void) -{ - switch (sc_lsize()) { - case 64: - blast_scache64(); - break; - case 128: - blast_scache128(); - break; - default: - printk("Unknown L2 line size\n"); - while(1); - } -} - -void -andes_flush_icache_page(unsigned long page) -{ - if (scache_lsz64) - blast_scache64_page(page); - else - blast_scache128_page(page); -} - -static void -andes_flush_cache_sigtramp(unsigned long addr) -{ - protected_writeback_dcache_line(addr & ~(dc_lsize - 1)); - protected_flush_icache_line(addr & ~(ic_lsize - 1)); -} - -#define NTLB_ENTRIES 64 -#define NTLB_ENTRIES_HALF 32 - -static inline void -andes_flush_tlb_all(void) -{ - unsigned long flags; - unsigned long old_ctx; - unsigned long entry; - -#ifdef DEBUG_TLB - printk("[tlball]"); -#endif - - local_irq_save(flags); - /* Save old context and create impossible VPN2 value */ - old_ctx = get_entryhi() & 0xff; - set_entryhi(CKSEG0); - set_entrylo0(0); - set_entrylo1(0); - - entry = get_wired(); - - /* Blast 'em all away. */ - while(entry < NTLB_ENTRIES) { - set_index(entry); - tlb_write_indexed(); - entry++; - } - set_entryhi(old_ctx); - local_irq_restore(flags); -} - -static void andes_flush_tlb_mm(struct mm_struct *mm) -{ - if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { - unsigned long flags; - -#ifdef DEBUG_TLB - printk("[tlbmm<%d>]", mm->context); -#endif - local_irq_save(flags); - get_new_cpu_mmu_context(mm, smp_processor_id()); - if(mm == current->mm) - set_entryhi(CPU_CONTEXT(smp_processor_id(), mm) & 0xff); - local_irq_restore(flags); - } -} - -static void -andes_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, - unsigned long end) -{ - struct mm_struct *mm = vma->vm_mm; - - if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { - unsigned long flags; - int size; - -#ifdef DEBUG_TLB - printk("[tlbrange<%02x,%08lx,%08lx>]", (mm->context & 0xff), - start, end); -#endif - local_irq_save(flags); - size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; - size = (size + 1) >> 1; - if(size <= NTLB_ENTRIES_HALF) { - int oldpid = (get_entryhi() & 0xff); - int newpid = (CPU_CONTEXT(smp_processor_id(), mm) & 0xff); - - start &= (PAGE_MASK << 1); - end += ((PAGE_SIZE << 1) - 1); - end &= (PAGE_MASK << 1); - while(start < end) { - int idx; - - set_entryhi(start | newpid); - start += (PAGE_SIZE << 1); - tlb_probe(); - idx = get_index(); - set_entrylo0(0); - set_entrylo1(0); - set_entryhi(KSEG0); - if(idx < 0) - continue; - tlb_write_indexed(); - } - set_entryhi(oldpid); - } else { - get_new_cpu_mmu_context(mm, smp_processor_id()); - if(mm == current->mm) - set_entryhi(CPU_CONTEXT(smp_processor_id(), mm) & - 0xff); - } - local_irq_restore(flags); - } -} - -static void -andes_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) -{ - if (CPU_CONTEXT(smp_processor_id(), vma->vm_mm) != 0) { - unsigned long flags; - int oldpid, newpid, idx; - -#ifdef DEBUG_TLB - printk("[tlbpage<%d,%08lx>]", vma->vm_mm->context, page); -#endif - newpid = (CPU_CONTEXT(smp_processor_id(), vma->vm_mm) & 0xff); - page &= (PAGE_MASK << 1); - local_irq_save(flags); - oldpid = (get_entryhi() & 0xff); - set_entryhi(page | newpid); - tlb_probe(); - idx = get_index(); - set_entrylo0(0); - set_entrylo1(0); - set_entryhi(KSEG0); - if(idx < 0) - goto finish; - tlb_write_indexed(); - - finish: - set_entryhi(oldpid); - local_irq_restore(flags); - } -} - -/* XXX Simplify this. On the R10000 writing a TLB entry for an virtual - address that already exists will overwrite the old entry and not result - in TLB malfunction or TLB shutdown. */ -static void andes_update_mmu_cache(struct vm_area_struct * vma, - unsigned long address, pte_t pte) -{ - unsigned long flags; - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - int idx, pid; - - /* - * Handle debugger faulting in for debugee. - */ - if (current->active_mm != vma->vm_mm) - return; - - local_irq_save(flags); - pid = get_entryhi() & 0xff; - - if((pid != (CPU_CONTEXT(smp_processor_id(), vma->vm_mm) & 0xff)) || - (CPU_CONTEXT(smp_processor_id(), vma->vm_mm) == 0)) { - printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%d " - "tlbpid=%d\n", (int) (CPU_CONTEXT(smp_processor_id(), - vma->vm_mm) & 0xff), pid); - } - - address &= (PAGE_MASK << 1); - set_entryhi(address | (pid)); - pgdp = pgd_offset(vma->vm_mm, address); - tlb_probe(); - pmdp = pmd_offset(pgdp, address); - idx = get_index(); - ptep = pte_offset(pmdp, address); - set_entrylo0(pte_val(*ptep++) >> 6); - set_entrylo1(pte_val(*ptep) >> 6); - set_entryhi(address | (pid)); - if(idx < 0) { - tlb_write_random(); - } else { - tlb_write_indexed(); - } - set_entryhi(pid); - local_irq_restore(flags); -} - -static void andes_show_regs(struct pt_regs *regs) -{ - printk("Cpu %d\n", smp_processor_id()); - /* Saved main processor registers. */ - printk("$0 : %016lx %016lx %016lx %016lx\n", - 0UL, regs->regs[1], regs->regs[2], regs->regs[3]); - printk("$4 : %016lx %016lx %016lx %016lx\n", - regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]); - printk("$8 : %016lx %016lx %016lx %016lx\n", - regs->regs[8], regs->regs[9], regs->regs[10], regs->regs[11]); - printk("$12 : %016lx %016lx %016lx %016lx\n", - regs->regs[12], regs->regs[13], regs->regs[14], regs->regs[15]); - printk("$16 : %016lx %016lx %016lx %016lx\n", - regs->regs[16], regs->regs[17], regs->regs[18], regs->regs[19]); - printk("$20 : %016lx %016lx %016lx %016lx\n", - regs->regs[20], regs->regs[21], regs->regs[22], regs->regs[23]); - printk("$24 : %016lx %016lx\n", - regs->regs[24], regs->regs[25]); - printk("$28 : %016lx %016lx %016lx %016lx\n", - regs->regs[28], regs->regs[29], regs->regs[30], regs->regs[31]); - printk("Hi : %016lx\n", regs->hi); - printk("Lo : %016lx\n", regs->lo); - - /* Saved cp0 registers. */ - printk("epc : %016lx %s\nbadvaddr: %016lx\n", - regs->cp0_epc, print_tainted(), regs->cp0_badvaddr); - printk("Status : %08x\nCause : %08x\n", - (unsigned int) regs->cp0_status, (unsigned int) regs->cp0_cause); -} - -void __init ld_mmu_andes(void) -{ - printk("CPU revision is: %08x\n", read_32bit_cp0_register(CP0_PRID)); - - printk("Primary instruction cache %dkb, linesize %d bytes\n", - icache_size >> 10, ic_lsize); - printk("Primary data cache %dkb, linesize %d bytes\n", - dcache_size >> 10, dc_lsize); - printk("Secondary cache sized at %ldK, linesize %ld\n", - scache_size() >> 10, sc_lsize()); - - _clear_page = andes_clear_page; - _copy_page = andes_copy_page; - - _flush_cache_l1 = andes_flush_cache_l1; - _flush_cache_l2 = andes_flush_cache_l2; - _flush_cache_sigtramp = andes_flush_cache_sigtramp; - - _flush_tlb_all = andes_flush_tlb_all; - _flush_tlb_mm = andes_flush_tlb_mm; - _flush_tlb_range = andes_flush_tlb_range; - _flush_tlb_page = andes_flush_tlb_page; - - switch (sc_lsize()) { - case 64: - scache_lsz64 = 1; - break; - case 128: - scache_lsz64 = 0; - break; - default: - printk("Unknown L2 line size\n"); - while(1); - } - - update_mmu_cache = andes_update_mmu_cache; - - _show_regs = andes_show_regs; - - flush_cache_l1(); - - /* - * You should never change this register: - * - On R4600 1.7 the tlbp never hits for pages smaller than - * the value in the c0_pagemask register. - * - The entire mm handling assumes the c0_pagemask register to - * be set for 4kb pages. - */ - write_32bit_cp0_register(CP0_PAGEMASK, PM_4K); - - /* From this point on the ARC firmware is dead. */ - _flush_tlb_all(); - - /* Did I tell you that ARC SUCKS? */ -} diff -Nru a/arch/mips64/mm/c-r4k.c b/arch/mips64/mm/c-r4k.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips64/mm/c-r4k.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,1161 @@ +/* + * 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) 1996 David S. Miller (dm@engr.sgi.com) + * Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Primary cache parameters. */ +static unsigned long icache_size, dcache_size, scache_size; +unsigned long icache_way_size, dcache_way_size, scache_way_size; +static unsigned long scache_size; + +#include +#include + +extern void andes_clear_page(void * page); +extern void r4k_clear_page32_d16(void * page); +extern void r4k_clear_page32_d32(void * page); +extern void r4k_clear_page_d16(void * page); +extern void r4k_clear_page_d32(void * page); +extern void r4k_clear_page_r4600_v1(void * page); +extern void r4k_clear_page_r4600_v2(void * page); +extern void r4k_clear_page_s16(void * page); +extern void r4k_clear_page_s32(void * page); +extern void r4k_clear_page_s64(void * page); +extern void r4k_clear_page_s128(void * page); +extern void andes_copy_page(void * to, void * from); +extern void r4k_copy_page_d16(void * to, void * from); +extern void r4k_copy_page_d32(void * to, void * from); +extern void r4k_copy_page_r4600_v1(void * to, void * from); +extern void r4k_copy_page_r4600_v2(void * to, void * from); +extern void r4k_copy_page_s16(void * to, void * from); +extern void r4k_copy_page_s32(void * to, void * from); +extern void r4k_copy_page_s64(void * to, void * from); +extern void r4k_copy_page_s128(void * to, void * from); + +/* + * Dummy cache handling routines for machines without boardcaches + */ +static void no_sc_noop(void) {} + +static struct bcache_ops no_sc_ops = { + .bc_enable = (void *)no_sc_noop, + .bc_disable = (void *)no_sc_noop, + .bc_wback_inv = (void *)no_sc_noop, + .bc_inv = (void *)no_sc_noop +}; + +struct bcache_ops *bcops = &no_sc_ops; + +#define R4600_HIT_CACHEOP_WAR_IMPL \ +do { \ + if (R4600_V2_HIT_CACHEOP_WAR && \ + (read_c0_prid() & 0xfff0) == 0x2020) { /* R4600 V2.0 */\ + *(volatile unsigned long *)KSEG1; \ + } \ + if (R4600_V1_HIT_CACHEOP_WAR) \ + __asm__ __volatile__("nop;nop;nop;nop"); \ +} while (0) + +static void r4k_blast_dcache_page(unsigned long addr) +{ + static void *l = &&init; + unsigned long dc_lsize; + + goto *l; + +dc_16: + blast_dcache16_page(addr); + return; + +dc_32: + R4600_HIT_CACHEOP_WAR_IMPL; + blast_dcache32_page(addr); + return; + +init: + dc_lsize = current_cpu_data.dcache.linesz; + + if (dc_lsize == 16) + l = &&dc_16; + else if (dc_lsize == 32) + l = &&dc_32; + goto *l; +} + +static void r4k_blast_dcache_page_indexed(unsigned long addr) +{ + static void *l = &&init; + unsigned long dc_lsize; + + goto *l; + +dc_16: + blast_dcache16_page_indexed(addr); + return; + +dc_32: + blast_dcache32_page_indexed(addr); + return; + +init: + dc_lsize = current_cpu_data.dcache.linesz; + + if (dc_lsize == 16) + l = &&dc_16; + else if (dc_lsize == 32) + l = &&dc_32; + goto *l; +} + +static void r4k_blast_dcache(void) +{ + static void *l = &&init; + unsigned long dc_lsize; + + goto *l; + +dc_16: + blast_dcache16(); + return; + +dc_32: + blast_dcache32(); + return; + +init: + dc_lsize = current_cpu_data.dcache.linesz; + + if (dc_lsize == 16) + l = &&dc_16; + else if (dc_lsize == 32) + l = &&dc_32; + goto *l; +} + +static void r4k_blast_icache_page(unsigned long addr) +{ + unsigned long ic_lsize = current_cpu_data.icache.linesz; + static void *l = &&init; + + goto *l; + +ic_16: + blast_icache16_page(addr); + return; + +ic_32: + blast_icache32_page(addr); + return; + +ic_64: + blast_icache64_page(addr); + return; + +init: + if (ic_lsize == 16) + l = &&ic_16; + else if (ic_lsize == 32) + l = &&ic_32; + else if (ic_lsize == 64) + l = &&ic_64; + goto *l; +} + +static void r4k_blast_icache_page_indexed(unsigned long addr) +{ + unsigned long ic_lsize = current_cpu_data.icache.linesz; + static void *l = &&init; + + goto *l; + +ic_16: + blast_icache16_page_indexed(addr); + return; + +ic_32: + blast_icache32_page_indexed(addr); + return; + +ic_64: + blast_icache64_page_indexed(addr); + return; + +init: + if (ic_lsize == 16) + l = &&ic_16; + else if (ic_lsize == 32) + l = &&ic_32; + else if (ic_lsize == 64) + l = &&ic_64; + goto *l; +} + +static void r4k_blast_icache(void) +{ + unsigned long ic_lsize = current_cpu_data.icache.linesz; + static void *l = &&init; + + goto *l; + +ic_16: + blast_icache16(); + return; + +ic_32: + blast_icache32(); + return; + +ic_64: + blast_icache64(); + return; + +init: + if (ic_lsize == 16) + l = &&ic_16; + else if (ic_lsize == 32) + l = &&ic_32; + else if (ic_lsize == 64) + l = &&ic_64; + goto *l; +} + +static void r4k_blast_scache_page(unsigned long addr) +{ + unsigned long sc_lsize = current_cpu_data.scache.linesz; + static void *l = &&init; + + goto *l; + +sc_16: + blast_scache16_page(addr); + return; + +sc_32: + blast_scache32_page(addr); + return; + +sc_64: + blast_scache64_page(addr); + return; + +sc_128: + blast_scache128_page(addr); + return; + +init: + if (sc_lsize == 16) + l = &&sc_16; + else if (sc_lsize == 32) + l = &&sc_32; + else if (sc_lsize == 64) + l = &&sc_64; + else if (sc_lsize == 128) + l = &&sc_128; + goto *l; +} + +static void r4k_blast_scache(void) +{ + unsigned long sc_lsize = current_cpu_data.scache.linesz; + static void *l = &&init; + + goto *l; + +sc_16: + blast_scache16(); + return; + +sc_32: + blast_scache32(); + return; + +sc_64: + blast_scache64(); + return; + +sc_128: + blast_scache128(); + return; + +init: + if (sc_lsize == 16) + l = &&sc_16; + else if (sc_lsize == 32) + l = &&sc_32; + else if (sc_lsize == 64) + l = &&sc_64; + else if (sc_lsize == 128) + l = &&sc_128; + goto *l; +} + +static void r4k_flush_cache_all(void) +{ + if (!cpu_has_dc_aliases) + return; + + r4k_blast_dcache(); + r4k_blast_icache(); +} + +static void r4k___flush_cache_all(void) +{ + r4k_blast_dcache(); + r4k_blast_icache(); + + switch (current_cpu_data.cputype) { + case CPU_R4000SC: + case CPU_R4000MC: + case CPU_R4400SC: + case CPU_R4400MC: + case CPU_R10000: + case CPU_R12000: + r4k_blast_scache(); + } +} + +static void r4k_flush_cache_range(struct vm_area_struct *vma, + unsigned long start, unsigned long end) +{ + if (cpu_context(smp_processor_id(), vma->vm_mm) != 0) { + r4k_blast_dcache(); + if (vma->vm_flags & VM_EXEC) + r4k_blast_icache(); + } +} + +static void r4k_flush_cache_mm(struct mm_struct *mm) +{ + if (!cpu_has_dc_aliases) + return; + + if (!cpu_context(smp_processor_id(), mm)) + return; + + r4k_blast_dcache(); + r4k_blast_icache(); + + /* + * Kludge alert. For obscure reasons R4000SC and R4400SC go nuts if we + * only flush the primary caches but R10000 and R12000 behave sane ... + */ + if (current_cpu_data.cputype == CPU_R4000SC || + current_cpu_data.cputype == CPU_R4000MC || + current_cpu_data.cputype == CPU_R4400SC || + current_cpu_data.cputype == CPU_R4400MC) + r4k_blast_scache(); +} + +static void r4k_flush_cache_page(struct vm_area_struct *vma, + unsigned long page) +{ + int exec = vma->vm_flags & VM_EXEC; + struct mm_struct *mm = vma->vm_mm; + pgd_t *pgdp; + pmd_t *pmdp; + pte_t *ptep; + + /* + * If ownes no valid ASID yet, cannot possibly have gotten + * this page into the cache. + */ + if (cpu_context(smp_processor_id(), mm) == 0) + return; + + page &= PAGE_MASK; + pgdp = pgd_offset(mm, page); + pmdp = pmd_offset(pgdp, page); + ptep = pte_offset(pmdp, page); + + /* + * If the page isn't marked valid, the page cannot possibly be + * in the cache. + */ + if (!(pte_val(*ptep) & _PAGE_PRESENT)) + return; + + /* + * Doing flushes for another ASID than the current one is + * too difficult since stupid R4k caches do a TLB translation + * for every cache flush operation. So we do indexed flushes + * in that case, which doesn't overly flush the cache too much. + */ + if ((mm == current->active_mm) && (pte_val(*ptep) & _PAGE_VALID)) { + if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) + r4k_blast_dcache_page(page); + if (exec) + r4k_blast_icache_page(page); + + return; + } + + /* + * Do indexed flush, too much work to get the (possible) TLB refills + * to work correctly. + */ + page = (KSEG0 + (page & (dcache_size - 1))); + if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) + r4k_blast_dcache_page_indexed(page); + if (exec) { + if (cpu_has_vtag_icache) { + int cpu = smp_processor_id(); + + if (cpu_context(cpu, vma->vm_mm) != 0) + drop_mmu_context(vma->vm_mm, cpu); + } else + r4k_blast_icache_page_indexed(page); + } +} + +static void r4k_flush_data_cache_page(unsigned long addr) +{ + r4k_blast_dcache_page(addr); +} + +static void r4k_flush_icache_range(unsigned long start, unsigned long end) +{ + unsigned long dc_lsize = current_cpu_data.dcache.linesz; + unsigned long addr, aend; + + if (!cpu_has_ic_fills_f_dc) { + if (end - start > dcache_size) + r4k_blast_dcache(); + else { + addr = start & ~(dc_lsize - 1); + aend = (end - 1) & ~(dc_lsize - 1); + + while (1) { + /* Hit_Writeback_Inv_D */ + protected_writeback_dcache_line(addr); + if (addr == aend) + break; + addr += dc_lsize; + } + } + } + + if (end - start > icache_size) + r4k_blast_icache(); + else { + addr = start & ~(dc_lsize - 1); + aend = (end - 1) & ~(dc_lsize - 1); + while (1) { + /* Hit_Invalidate_I */ + protected_flush_icache_line(addr); + if (addr == aend) + break; + addr += dc_lsize; + } + } +} + +/* + * Ok, this seriously sucks. We use them to flush a user page but don't + * know the virtual address, so we have to blast away the whole icache + * which is significantly more expensive than the real thing. Otoh we at + * least know the kernel address of the page so we can flush it + * selectivly. + */ +static void r4k_flush_icache_page(struct vm_area_struct *vma, + struct page *page) +{ + /* + * If there's no context yet, or the page isn't executable, no icache + * flush is needed. + */ + if (!(vma->vm_flags & VM_EXEC)) + return; + + /* + * Tricky ... Because we don't know the virtual address we've got the + * choice of either invalidating the entire primary and secondary + * caches or invalidating the secondary caches also. With the subset + * enforcment on R4000SC, R4400SC, R10000 and R12000 invalidating the + * secondary cache will result in any entries in the primary caches + * also getting invalidated which hopefully is a bit more economical. + */ + if (cpu_has_subset_pcaches) { + unsigned long addr = (unsigned long) page_address(page); + r4k_blast_scache_page(addr); + + return; + } + + if (!cpu_has_ic_fills_f_dc) { + unsigned long addr = (unsigned long) page_address(page); + r4k_blast_dcache_page(addr); + } + + /* + * We're not sure of the virtual address(es) involved here, so + * we have to flush the entire I-cache. + */ + if (cpu_has_vtag_icache) { + int cpu = smp_processor_id(); + + if (cpu_context(cpu, vma->vm_mm) != 0) + drop_mmu_context(vma->vm_mm, cpu); + } else + r4k_blast_icache(); +} + +#ifdef CONFIG_NONCOHERENT_IO + +static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size) +{ + unsigned long end, a; + + if (cpu_has_subset_pcaches) { + unsigned long sc_lsize = current_cpu_data.scache.linesz; + + if (size >= scache_size) { + r4k_blast_scache(); + return; + } + + a = addr & ~(sc_lsize - 1); + end = (addr + size - 1) & ~(sc_lsize - 1); + while (1) { + flush_scache_line(a); /* Hit_Writeback_Inv_SD */ + if (a == end) + break; + a += sc_lsize; + } + return; + } + + /* + * Either no secondary cache or the available caches don't have the + * subset property so we have to flush the primary caches + * explicitly + */ + if (size >= dcache_size) { + r4k_blast_dcache(); + } else { + unsigned long dc_lsize = current_cpu_data.dcache.linesz; + + R4600_HIT_CACHEOP_WAR_IMPL; + a = addr & ~(dc_lsize - 1); + end = (addr + size - 1) & ~(dc_lsize - 1); + while (1) { + flush_dcache_line(a); /* Hit_Writeback_Inv_D */ + if (a == end) + break; + a += dc_lsize; + } + } + + bc_wback_inv(addr, size); +} + +static void r4k_dma_cache_inv(unsigned long addr, unsigned long size) +{ + unsigned long end, a; + + if (cpu_has_subset_pcaches) { + unsigned long sc_lsize = current_cpu_data.scache.linesz; + + if (size >= scache_size) { + r4k_blast_scache(); + return; + } + + a = addr & ~(sc_lsize - 1); + end = (addr + size - 1) & ~(sc_lsize - 1); + while (1) { + flush_scache_line(a); /* Hit_Writeback_Inv_SD */ + if (a == end) + break; + a += sc_lsize; + } + return; + } + + if (size >= dcache_size) { + r4k_blast_dcache(); + } else { + unsigned long dc_lsize = current_cpu_data.dcache.linesz; + + R4600_HIT_CACHEOP_WAR_IMPL; + a = addr & ~(dc_lsize - 1); + end = (addr + size - 1) & ~(dc_lsize - 1); + while (1) { + flush_dcache_line(a); /* Hit_Writeback_Inv_D */ + if (a == end) + break; + a += dc_lsize; + } + } + + bc_inv(addr, size); +} +#endif /* CONFIG_NONCOHERENT_IO */ + +/* + * While we're protected against bad userland addresses we don't care + * very much about what happens in that case. Usually a segmentation + * fault will dump the process later on anyway ... + */ +static void r4k_flush_cache_sigtramp(unsigned long addr) +{ + unsigned long ic_lsize = current_cpu_data.icache.linesz; + unsigned long dc_lsize = current_cpu_data.dcache.linesz; + + R4600_HIT_CACHEOP_WAR_IMPL; + protected_writeback_dcache_line(addr & ~(dc_lsize - 1)); + protected_flush_icache_line(addr & ~(ic_lsize - 1)); +} + +static void r4k_flush_icache_all(void) +{ + if (cpu_has_vtag_icache) + r4k_blast_icache(); +} + +static inline void rm7k_erratum31(void) +{ + const unsigned long ic_lsize = 32; + unsigned long addr; + + /* RM7000 erratum #31. The icache is screwed at startup. */ + write_c0_taglo(0); + write_c0_taghi(0); + + for (addr = KSEG0; addr <= KSEG0 + 4096; addr += ic_lsize) { + __asm__ __volatile__ ( + ".set noreorder\n\t" + ".set mips3\n\t" + "cache\t%1, 0(%0)\n\t" + "cache\t%1, 0x1000(%0)\n\t" + "cache\t%1, 0x2000(%0)\n\t" + "cache\t%1, 0x3000(%0)\n\t" + "cache\t%2, 0(%0)\n\t" + "cache\t%2, 0x1000(%0)\n\t" + "cache\t%2, 0x2000(%0)\n\t" + "cache\t%2, 0x3000(%0)\n\t" + "cache\t%1, 0(%0)\n\t" + "cache\t%1, 0x1000(%0)\n\t" + "cache\t%1, 0x2000(%0)\n\t" + "cache\t%1, 0x3000(%0)\n\t" + ".set\tmips0\n\t" + ".set\treorder\n\t" + : + : "r" (addr), "i" (Index_Store_Tag_I), "i" (Fill)); + } +} + +static char *way_string[] = { NULL, "direct mapped", "2-way", "3-way", "4-way", + "5-way", "6-way", "7-way", "8-way" +}; + +static void __init probe_pcache(void) +{ + struct cpuinfo_mips *c = ¤t_cpu_data; + unsigned int config = read_c0_config(); + unsigned int prid = read_c0_prid(); + unsigned long config1; + unsigned int lsize; + + switch (current_cpu_data.cputype) { + case CPU_R4600: /* QED style two way caches? */ + case CPU_R4700: + case CPU_R5000: + case CPU_NEVADA: + icache_size = 1 << (12 + ((config & CONF_IC) >> 9)); + c->icache.linesz = 16 << ((config & CONF_IB) >> 5); + c->icache.ways = 2; + c->icache.waybit = ffs(icache_size/2) - 1; + + dcache_size = 1 << (12 + ((config & CONF_DC) >> 6)); + c->dcache.linesz = 16 << ((config & CONF_DB) >> 4); + c->dcache.ways = 2; + c->dcache.waybit= ffs(dcache_size/2) - 1; + break; + + case CPU_R5432: + case CPU_R5500: + icache_size = 1 << (12 + ((config & CONF_IC) >> 9)); + c->icache.linesz = 16 << ((config & CONF_IB) >> 5); + c->icache.ways = 2; + c->icache.waybit= 0; + + dcache_size = 1 << (12 + ((config & CONF_DC) >> 6)); + c->dcache.linesz = 16 << ((config & CONF_DB) >> 4); + c->dcache.ways = 2; + c->dcache.waybit = 0; + break; + + case CPU_TX49XX: + icache_size = 1 << (12 + ((config & CONF_IC) >> 9)); + c->icache.linesz = 16 << ((config & CONF_IB) >> 5); + c->icache.ways = 4; + c->icache.waybit= 0; + + dcache_size = 1 << (12 + ((config & CONF_DC) >> 6)); + c->dcache.linesz = 16 << ((config & CONF_DB) >> 4); + c->dcache.ways = 4; + c->dcache.waybit = 0; + break; + + case CPU_R4000PC: + case CPU_R4000SC: + case CPU_R4000MC: + case CPU_R4400PC: + case CPU_R4400SC: + case CPU_R4400MC: + icache_size = 1 << (12 + ((config & CONF_IC) >> 9)); + c->icache.linesz = 16 << ((config & CONF_IB) >> 5); + c->icache.ways = 1; + c->icache.waybit = 0; /* doesn't matter */ + + dcache_size = 1 << (12 + ((config & CONF_DC) >> 6)); + c->dcache.linesz = 16 << ((config & CONF_DB) >> 4); + c->dcache.ways = 1; + c->dcache.waybit = 0; /* does not matter */ + break; + + case CPU_R10000: + case CPU_R12000: + icache_size = 1 << (12 + ((config & R10K_CONF_IC) >> 29)); + c->icache.linesz = 64; + c->icache.ways = 2; + c->icache.waybit = 0; + + dcache_size = 1 << (12 + ((config & R10K_CONF_DC) >> 26)); + c->dcache.linesz = 32; + c->dcache.ways = 2; + c->dcache.waybit = 0; + break; + + case CPU_VR4131: + icache_size = 1 << (10 + ((config & CONF_IC) >> 9)); + c->icache.linesz = 16 << ((config & CONF_IB) >> 5); + c->icache.ways = 2; + c->icache.waybit = ffs(icache_size/2) - 1; + + dcache_size = 1 << (10 + ((config & CONF_DC) >> 6)); + c->dcache.linesz = 16 << ((config & CONF_DB) >> 4); + c->dcache.ways = 2; + c->dcache.waybit = ffs(dcache_size/2) - 1; + break; + + case CPU_VR41XX: + case CPU_VR4111: + case CPU_VR4121: + case CPU_VR4122: + case CPU_VR4181: + case CPU_VR4181A: + icache_size = 1 << (10 + ((config & CONF_IC) >> 9)); + c->icache.linesz = 16 << ((config & CONF_IB) >> 5); + c->icache.ways = 1; + c->icache.waybit = 0; /* doesn't matter */ + + dcache_size = 1 << (10 + ((config & CONF_DC) >> 6)); + c->dcache.linesz = 16 << ((config & CONF_DB) >> 4); + c->dcache.ways = 1; + c->dcache.waybit = 0; /* does not matter */ + break; + + case CPU_RM7000: + rm7k_erratum31(); + + icache_size = 1 << (12 + ((config & CONF_IC) >> 9)); + c->icache.linesz = 16 << ((config & CONF_IB) >> 5); + c->icache.ways = 4; + c->icache.waybit = ffs(icache_size / c->icache.ways) - 1; + + dcache_size = 1 << (12 + ((config & CONF_DC) >> 6)); + c->dcache.linesz = 16 << ((config & CONF_DB) >> 4); + c->dcache.ways = 4; + c->dcache.waybit = ffs(dcache_size / c->dcache.ways) - 1; + break; + + default: + if (!(config & MIPS_CONF_M)) + panic("Don't know how to probe P-caches on this cpu."); + + /* + * So we seem to be a MIPS32 or MIPS64 CPU + * So let's probe the I-cache ... + */ + config1 = read_c0_config1(); + + if ((lsize = ((config1 >> 19) & 7))) + c->icache.linesz = 2 << lsize; + else + c->icache.linesz = lsize; + c->icache.sets = 64 << ((config1 >> 22) & 7); + c->icache.ways = 1 + ((config1 >> 16) & 7); + + icache_size = c->icache.sets * + c->icache.ways * + c->icache.linesz; + c->icache.waybit = ffs(icache_size/c->icache.ways) - 1; + + /* + * Now probe the MIPS32 / MIPS64 data cache. + */ + c->dcache.flags = 0; + + if ((lsize = ((config1 >> 10) & 7))) + c->dcache.linesz = 2 << lsize; + else + c->dcache.linesz= lsize; + c->dcache.sets = 64 << ((config1 >> 13) & 7); + c->dcache.ways = 1 + ((config1 >> 7) & 7); + + dcache_size = c->dcache.sets * + c->dcache.ways * + c->dcache.linesz; + c->dcache.waybit = ffs(dcache_size/c->dcache.ways) - 1; + break; + } + + /* + * Processor configuration sanity check for the R4000SC erratum + * #5. With page sizes larger than 32kB there is no possibility + * to get a VCE exception anymore so we don't care about this + * misconfiguration. The case is rather theoretical anyway; + * presumably no vendor is shipping his hardware in the "bad" + * configuration. + */ + if ((prid & 0xff00) == PRID_IMP_R4000 && (prid & 0xff) < 0x40 && + !(config & CONF_SC) && c->icache.linesz != 16 && + PAGE_SIZE <= 0x8000) + panic("Improper R4000SC processor configuration detected"); + + /* compute a couple of other cache variables */ + icache_way_size = icache_size / c->icache.ways; + dcache_way_size = dcache_size / c->dcache.ways; + + c->icache.sets = icache_size / (c->icache.linesz * c->icache.ways); + c->dcache.sets = dcache_size / (c->dcache.linesz * c->dcache.ways); + + /* + * R10000 and R12000 P-caches are odd in a positive way. They're 32kB + * 2-way virtually indexed so normally would suffer from aliases. So + * normally they'd suffer from aliases but magic in the hardware deals + * with that for us so we don't need to take care ourselves. + */ + if (current_cpu_data.cputype != CPU_R10000 && + current_cpu_data.cputype != CPU_R12000) + if (dcache_way_size > PAGE_SIZE) + c->dcache.flags |= MIPS_CACHE_ALIASES; + + if (config & 0x8) /* VI bit */ + c->icache.flags |= MIPS_CACHE_VTAG; + + switch (c->cputype) { + case CPU_20KC: + /* + * Some older 20Kc chips doesn't have the 'VI' bit in + * the config register. + */ + c->icache.flags |= MIPS_CACHE_VTAG; + break; + + case CPU_AU1500: + c->icache.flags |= MIPS_CACHE_IC_F_DC; + break; + } + + printk("Primary instruction cache %ldkB, %s, %s, linesize %d bytes.\n", + icache_size >> 10, + cpu_has_vtag_icache ? "virtually tagged" : "physically tagged", + way_string[c->icache.ways], c->icache.linesz); + + printk("Primary data cache %ldkB %s, linesize %d bytes.\n", + dcache_size >> 10, way_string[c->dcache.ways], c->dcache.linesz); +} + +/* + * If you even _breathe_ on this function, look at the gcc output and make sure + * it does not pop things on and off the stack for the cache sizing loop that + * executes in KSEG1 space or else you will crash and burn badly. You have + * been warned. + */ +static int __init probe_scache(void) +{ + extern unsigned long stext; + unsigned long flags, addr, begin, end, pow2; + unsigned int config = read_c0_config(); + struct cpuinfo_mips *c = ¤t_cpu_data; + int tmp; + + if (config & CONF_SC) + return 0; + + begin = (unsigned long) &stext; + begin &= ~((4 * 1024 * 1024) - 1); + end = begin + (4 * 1024 * 1024); + + /* + * This is such a bitch, you'd think they would make it easy to do + * this. Away you daemons of stupidity! + */ + local_irq_save(flags); + + /* Fill each size-multiple cache line with a valid tag. */ + pow2 = (64 * 1024); + for (addr = begin; addr < end; addr = (begin + pow2)) { + unsigned long *p = (unsigned long *) addr; + __asm__ __volatile__("nop" : : "r" (*p)); /* whee... */ + pow2 <<= 1; + } + + /* Load first line with zero (therefore invalid) tag. */ + write_c0_taglo(0); + write_c0_taghi(0); + __asm__ __volatile__("nop; nop; nop; nop;"); /* avoid the hazard */ + cache_op(Index_Store_Tag_I, begin); + cache_op(Index_Store_Tag_D, begin); + cache_op(Index_Store_Tag_SD, begin); + + /* Now search for the wrap around point. */ + pow2 = (128 * 1024); + tmp = 0; + for (addr = begin + (128 * 1024); addr < end; addr = begin + pow2) { + cache_op(Index_Load_Tag_SD, addr); + __asm__ __volatile__("nop; nop; nop; nop;"); /* hazard... */ + if (!read_c0_taglo()) + break; + pow2 <<= 1; + } + local_irq_restore(flags); + addr -= begin; + + c = ¤t_cpu_data; + scache_size = addr; + c->scache.linesz = 16 << ((config & R4K_CONF_SB) >> 22); + c->scache.ways = 1; + c->dcache.waybit = 0; /* does not matter */ + + return 1; +} + +static void __init setup_noscache_funcs(void) +{ + unsigned int prid; + + switch (current_cpu_data.dcache.linesz) { + case 16: + if (cpu_has_64bits) + _clear_page = r4k_clear_page_d16; + else + _clear_page = r4k_clear_page32_d16; + _copy_page = r4k_copy_page_d16; + + break; + case 32: + prid = read_c0_prid() & 0xfff0; + if (prid == 0x2010) { /* R4600 V1.7 */ + _clear_page = r4k_clear_page_r4600_v1; + _copy_page = r4k_copy_page_r4600_v1; + } else if (prid == 0x2020) { /* R4600 V2.0 */ + _clear_page = r4k_clear_page_r4600_v2; + _copy_page = r4k_copy_page_r4600_v2; + } else { + if (cpu_has_64bits) + _clear_page = r4k_clear_page_d32; + else + _clear_page = r4k_clear_page32_d32; + _copy_page = r4k_copy_page_d32; + } + break; + } +} + +static void __init setup_scache_funcs(void) +{ + if (current_cpu_data.dcache.linesz > current_cpu_data.scache.linesz) + panic("Invalid primary cache configuration detected"); + + if (current_cpu_data.cputype == CPU_R10000 || + current_cpu_data.cputype == CPU_R12000) { + _clear_page = andes_clear_page; + _copy_page = andes_copy_page; + return; + } + + switch (current_cpu_data.scache.linesz) { + case 16: + _clear_page = r4k_clear_page_s16; + _copy_page = r4k_copy_page_s16; + break; + case 32: + _clear_page = r4k_clear_page_s32; + _copy_page = r4k_copy_page_s32; + break; + case 64: + _clear_page = r4k_clear_page_s64; + _copy_page = r4k_copy_page_s64; + break; + case 128: + _clear_page = r4k_clear_page_s128; + _copy_page = r4k_copy_page_s128; + break; + } +} + +typedef int (*probe_func_t)(unsigned long); +extern int r5k_sc_init(void); +extern int rm7k_sc_init(void); + +static void __init setup_scache(void) +{ + struct cpuinfo_mips *c = ¤t_cpu_data; + unsigned int config = read_c0_config(); + probe_func_t probe_scache_kseg1; + int sc_present = 0; + + /* + * Do the probing thing on R4000SC and R4400SC processors. Other + * processors don't have a S-cache that would be relevant to the + * Linux memory managment. + */ + switch (current_cpu_data.cputype) { + case CPU_R4000PC: + case CPU_R4000SC: + case CPU_R4000MC: + case CPU_R4400PC: + case CPU_R4400SC: + case CPU_R4400MC: + probe_scache_kseg1 = (probe_func_t) (KSEG1ADDR(&probe_scache)); + sc_present = probe_scache_kseg1(config); + break; + + case CPU_R10000: + case CPU_R12000: + scache_size = 0x80000 << ((config & R10K_CONF_SS) >> 16); + c->scache.linesz = 64 << ((config >> 13) & 1); + c->scache.ways = 2; + c->scache.waybit= 0; + sc_present = 1; + break; + + case CPU_R5000: + case CPU_NEVADA: + setup_noscache_funcs(); +#ifdef CONFIG_R5000_CPU_SCACHE + r5k_sc_init(); +#endif + return; + + case CPU_RM7000: + setup_noscache_funcs(); +#ifdef CONFIG_RM7000_CPU_SCACHE + rm7k_sc_init(); +#endif + return; + + default: + sc_present = 0; + } + + if (!sc_present) { + setup_noscache_funcs(); + return; + } + + if ((current_cpu_data.isa_level == MIPS_CPU_ISA_M32 || + current_cpu_data.isa_level == MIPS_CPU_ISA_M64) && + !(current_cpu_data.scache.flags & MIPS_CACHE_NOT_PRESENT)) + panic("Dunno how to handle MIPS32 / MIPS64 second level cache"); + + printk("Unified secondary cache %ldkB %s, linesize %d bytes.\n", + scache_size >> 10, way_string[c->scache.ways], c->scache.linesz); + + current_cpu_data.options |= MIPS_CPU_SUBSET_CACHES; + setup_scache_funcs(); +} + +static inline void coherency_setup(void) +{ + change_c0_config(CONF_CM_CMASK, CONF_CM_DEFAULT); + + /* + * c0_status.cu=0 specifies that updates by the sc instruction use + * the coherency mode specified by the TLB; 1 means cachable + * coherent update on write will be used. Not all processors have + * this bit and; some wire it to zero, others like Toshiba had the + * silly idea of putting something else there ... + */ + switch (current_cpu_data.cputype) { + case CPU_R4000PC: + case CPU_R4000SC: + case CPU_R4000MC: + case CPU_R4400PC: + case CPU_R4400SC: + case CPU_R4400MC: + clear_c0_config(CONF_CU); + break; + } + +} + +void __init ld_mmu_r4xx0(void) +{ + extern char except_vec2_generic; + + /* Default cache error handler for R4000 and R5000 family */ + memcpy((void *)(KSEG0 + 0x100), &except_vec2_generic, 0x80); + memcpy((void *)(KSEG1 + 0x100), &except_vec2_generic, 0x80); + + probe_pcache(); + setup_scache(); + coherency_setup(); + + if (current_cpu_data.dcache.sets * + current_cpu_data.dcache.ways > PAGE_SIZE) + current_cpu_data.dcache.flags |= MIPS_CACHE_ALIASES; + + /* + * Some MIPS32 and MIPS64 processors have physically indexed caches. + * This code supports virtually indexed processors and will be + * unnecessarily unefficient on physically indexed processors. + */ + shm_align_mask = max_t(unsigned long, + current_cpu_data.dcache.sets * current_cpu_data.dcache.linesz - 1, + PAGE_SIZE - 1); + + flush_cache_all = r4k_flush_cache_all; + __flush_cache_all = r4k___flush_cache_all; + flush_cache_mm = r4k_flush_cache_mm; + flush_cache_page = r4k_flush_cache_page; + flush_icache_page = r4k_flush_icache_page; + flush_cache_range = r4k_flush_cache_range; + + flush_cache_sigtramp = r4k_flush_cache_sigtramp; + flush_icache_all = r4k_flush_icache_all; + flush_data_cache_page = r4k_flush_data_cache_page; + flush_icache_range = r4k_flush_icache_range; + +#ifdef CONFIG_NONCOHERENT_IO + _dma_cache_wback_inv = r4k_dma_cache_wback_inv; + _dma_cache_wback = r4k_dma_cache_wback_inv; + _dma_cache_inv = r4k_dma_cache_inv; +#endif + + __flush_cache_all(); +} diff -Nru a/arch/mips64/mm/c-sb1.c b/arch/mips64/mm/c-sb1.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips64/mm/c-sb1.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,594 @@ +/* + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * Copyright (C) 1997, 2001 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 2000, 2001 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#include +#include +#include +#include +#include +#include +#include + +extern void sb1_clear_page(void * page); +extern void sb1_copy_page(void * to, void * from); + +/* These are probed at ld_mmu time */ +static unsigned long icache_size; +static unsigned long dcache_size; + +static unsigned long icache_line_size; +static unsigned long dcache_line_size; + +static unsigned int icache_index_mask; +static unsigned int dcache_index_mask; + +static unsigned long icache_assoc; +static unsigned long dcache_assoc; + +static unsigned int icache_sets; +static unsigned int dcache_sets; + +static unsigned int icache_range_cutoff; +static unsigned int dcache_range_cutoff; + +/* + * The dcache is fully coherent to the system, with one + * big caveat: the instruction stream. In other words, + * if we miss in the icache, and have dirty data in the + * L1 dcache, then we'll go out to memory (or the L2) and + * get the not-as-recent data. + * + * So the only time we have to flush the dcache is when + * we're flushing the icache. Since the L2 is fully + * coherent to everything, including I/O, we never have + * to flush it + */ + +/* + * Writeback and invalidate the entire dcache + */ +static inline void __sb1_writeback_inv_dcache_all(void) +{ + __asm__ __volatile__ ( + ".set push \n" + ".set noreorder \n" + ".set noat \n" + ".set mips4 \n" + " move $1, $0 \n" /* Start at index 0 */ + "1: cache %2, 0($1) \n" /* Invalidate this index */ + " cache %2, (1<<13)($1)\n" /* Invalidate this index */ + " cache %2, (2<<13)($1)\n" /* Invalidate this index */ + " cache %2, (3<<13)($1)\n" /* Invalidate this index */ + " daddiu %1, %1, -1 \n" /* Decrement loop count */ + " bnez %1, 1b \n" /* loop test */ + " daddu $1, $1, %0 \n" /* Next address */ + ".set pop \n" + : + : "r" (dcache_line_size), "r" (dcache_sets), + "i" (Index_Writeback_Inv_D)); +} + +/* + * Writeback and invalidate a range of the dcache. The addresses are + * virtual, and since we're using index ops and bit 12 is part of both + * the virtual frame and physical index, we have to clear both sets + * (bit 12 set and cleared). + */ +static inline void __sb1_writeback_inv_dcache_range(unsigned long start, + unsigned long end) +{ + __asm__ __volatile__ ( + " .set push \n" + " .set noreorder \n" + " .set noat \n" + " .set mips4 \n" + " and $1, %0, %3 \n" /* mask non-index bits */ + "1: cache %4, (0<<13)($1) \n" /* Index-WB-inval this address */ + " cache %4, (1<<13)($1) \n" /* Index-WB-inval this address */ + " cache %4, (2<<13)($1) \n" /* Index-WB-inval this address */ + " cache %4, (3<<13)($1) \n" /* Index-WB-inval this address */ + " xori $1, $1, 1<<12 \n" + " cache %4, (0<<13)($1) \n" /* Index-WB-inval this address */ + " cache %4, (1<<13)($1) \n" /* Index-WB-inval this address */ + " cache %4, (2<<13)($1) \n" /* Index-WB-inval this address */ + " cache %4, (3<<13)($1) \n" /* Index-WB-inval this address */ + " daddu %0, %0, %2 \n" /* next line */ + " bne %0, %1, 1b \n" /* loop test */ + " and $1, %0, %3 \n" /* mask non-index bits */ + " sync \n" + " .set pop \n" + : + : "r" (start & ~(dcache_line_size - 1)), + "r" ((end + dcache_line_size - 1) & ~(dcache_line_size - 1)), + "r" (dcache_line_size), + "r" (dcache_index_mask), + "i" (Index_Writeback_Inv_D)); +} + +/* + * Writeback and invalidate a range of the dcache. With physical + * addresseses, we don't have to worry about possible bit 12 aliasing. + * XXXKW is it worth turning on KX and using hit ops with xkphys? + */ +static inline void __sb1_writeback_inv_dcache_phys_range(unsigned long start, + unsigned long end) +{ + __asm__ __volatile__ ( + " .set push \n" + " .set noreorder \n" + " .set noat \n" + " .set mips4 \n" + " and $1, %0, %3 \n" /* mask non-index bits */ + "1: cache %4, (0<<13)($1) \n" /* Index-WB-inval this address */ + " cache %4, (1<<13)($1) \n" /* Index-WB-inval this address */ + " cache %4, (2<<13)($1) \n" /* Index-WB-inval this address */ + " cache %4, (3<<13)($1) \n" /* Index-WB-inval this address */ + " daddu %0, %0, %2 \n" /* next line */ + " bne %0, %1, 1b \n" /* loop test */ + " and $1, %0, %3 \n" /* mask non-index bits */ + " sync \n" + " .set pop \n" + : + : "r" (start & ~(dcache_line_size - 1)), + "r" ((end + dcache_line_size - 1) & ~(dcache_line_size - 1)), + "r" (dcache_line_size), + "r" (dcache_index_mask), + "i" (Index_Writeback_Inv_D)); +} + + +/* + * Invalidate the entire icache + */ +static inline void __sb1_flush_icache_all(void) +{ + __asm__ __volatile__ ( + ".set push \n" + ".set noreorder \n" + ".set noat \n" + ".set mips4 \n" + " move $1, $0 \n" /* Start at index 0 */ + "1: cache %2, 0($1) \n" /* Invalidate this index */ + " cache %2, (1<<13)($1)\n" /* Invalidate this index */ + " cache %2, (2<<13)($1)\n" /* Invalidate this index */ + " cache %2, (3<<13)($1)\n" /* Invalidate this index */ + " daddiu %1, %1, -1 \n" /* Decrement loop count */ + " bnez %1, 1b \n" /* loop test */ + " daddu $1, $1, %0 \n" /* Next address */ + " bnezl $0, 2f \n" /* Force mispredict */ + " nop \n" + "2: sync \n" + ".set pop \n" + : + : "r" (icache_line_size), "r" (icache_sets), + "i" (Index_Invalidate_I)); +} + +/* + * Flush the icache for a given physical page. Need to writeback the + * dcache first, then invalidate the icache. If the page isn't + * executable, nothing is required. + */ +static void local_sb1_flush_cache_page(struct vm_area_struct *vma, + unsigned long addr) +{ + int cpu = smp_processor_id(); + +#ifndef CONFIG_SMP + if (!(vma->vm_flags & VM_EXEC)) + return; +#endif + + __sb1_writeback_inv_dcache_range(addr, addr + PAGE_SIZE); + + /* + * Bumping the ASID is probably cheaper than the flush ... + */ + if (cpu_context(cpu, vma->vm_mm) != 0) + drop_mmu_context(vma->vm_mm, cpu); +} + +#ifdef CONFIG_SMP +struct flush_cache_page_args { + struct vm_area_struct *vma; + unsigned long addr; +}; + +static void sb1_flush_cache_page_ipi(void *info) +{ + struct flush_cache_page_args *args = info; + + local_sb1_flush_cache_page(args->vma, args->addr); +} + +/* Dirty dcache could be on another CPU, so do the IPIs */ +static void sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long addr) +{ + struct flush_cache_page_args args; + + if (!(vma->vm_flags & VM_EXEC)) + return; + + args.vma = vma; + args.addr = addr; + on_each_cpu(sb1_flush_cache_page_ipi, (void *) &args, 1, 1); +} +#else +void sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long addr); +asm("sb1_flush_cache_page = local_sb1_flush_cache_page"); +#endif + +/* + * Invalidate a range of the icache. The addresses are virtual, and + * the cache is virtually indexed and tagged. However, we don't + * necessarily have the right ASID context, so use index ops instead + * of hit ops. + */ +static inline void __sb1_flush_icache_range(unsigned long start, + unsigned long end) +{ + __asm__ __volatile__ ( + ".set push \n" + ".set noreorder \n" + ".set noat \n" + ".set mips4 \n" + " and $1, %0, %3 \n" /* mask non-index bits */ + "1: cache %4, (0<<13)($1) \n" /* Index-inval this address */ + " cache %4, (1<<13)($1) \n" /* Index-inval this address */ + " cache %4, (2<<13)($1) \n" /* Index-inval this address */ + " cache %4, (3<<13)($1) \n" /* Index-inval this address */ + " daddu %0, %0, %2 \n" /* next line */ + " bne %0, %1, 1b \n" /* loop test */ + " and $1, %0, %3 \n" /* mask non-index bits */ + " bnezl $0, 2f \n" /* Force mispredict */ + " nop \n" + "2: sync \n" + ".set pop \n" + : + : "r" (start & ~(icache_line_size - 1)), + "r" ((end + icache_line_size - 1) & ~(icache_line_size - 1)), + "r" (icache_line_size), + "r" (icache_index_mask), + "i" (Index_Invalidate_I)); +} + + +/* + * Invalidate all caches on this CPU + */ +static void local_sb1___flush_cache_all(void) +{ + __sb1_writeback_inv_dcache_all(); + __sb1_flush_icache_all(); +} + +#ifdef CONFIG_SMP +extern void sb1___flush_cache_all_ipi(void *ignored); +asm("sb1___flush_cache_all_ipi = local_sb1___flush_cache_all"); + +static void sb1___flush_cache_all(void) +{ + on_each_cpu(sb1___flush_cache_all_ipi, 0, 1, 1); +} +#else +extern void sb1___flush_cache_all(void); +asm("sb1___flush_cache_all = local_sb1___flush_cache_all"); +#endif + +/* + * When flushing a range in the icache, we have to first writeback + * the dcache for the same range, so new ifetches will see any + * data that was dirty in the dcache. + * + * The start/end arguments are Kseg addresses (possibly mapped Kseg). + */ + +static void local_sb1_flush_icache_range(unsigned long start, + unsigned long end) +{ + /* Just wb-inv the whole dcache if the range is big enough */ + if ((end - start) > dcache_range_cutoff) + __sb1_writeback_inv_dcache_all(); + else + __sb1_writeback_inv_dcache_range(start, end); + + /* Just flush the whole icache if the range is big enough */ + if ((end - start) > icache_range_cutoff) + __sb1_flush_icache_all(); + else + __sb1_flush_icache_range(start, end); +} + +#ifdef CONFIG_SMP +struct flush_icache_range_args { + unsigned long start; + unsigned long end; +}; + +static void sb1_flush_icache_range_ipi(void *info) +{ + struct flush_icache_range_args *args = info; + + local_sb1_flush_icache_range(args->start, args->end); +} + +void sb1_flush_icache_range(unsigned long start, unsigned long end) +{ + struct flush_icache_range_args args; + + args.start = start; + args.end = end; + on_each_cpu(sb1_flush_icache_range_ipi, &args, 1, 1); +} +#else +void sb1_flush_icache_range(unsigned long start, unsigned long end); +asm("sb1_flush_icache_range = local_sb1_flush_icache_range"); +#endif + +/* + * Flush the icache for a given physical page. Need to writeback the + * dcache first, then invalidate the icache. If the page isn't + * executable, nothing is required. + */ +static void local_sb1_flush_icache_page(struct vm_area_struct *vma, + struct page *page) +{ + unsigned long start; + int cpu = smp_processor_id(); + +#ifndef CONFIG_SMP + if (!(vma->vm_flags & VM_EXEC)) + return; +#endif + + /* Need to writeback any dirty data for that page, we have the PA */ + start = (unsigned long)(page-mem_map) << PAGE_SHIFT; + __sb1_writeback_inv_dcache_phys_range(start, start + PAGE_SIZE); + /* + * If there's a context, bump the ASID (cheaper than a flush, + * since we don't know VAs!) + */ + if (cpu_context(cpu, vma->vm_mm) != 0) { + drop_mmu_context(vma->vm_mm, cpu); + } +} + +#ifdef CONFIG_SMP +struct flush_icache_page_args { + struct vm_area_struct *vma; + struct page *page; +}; + +static void sb1_flush_icache_page_ipi(void *info) +{ + struct flush_icache_page_args *args = info; + local_sb1_flush_icache_page(args->vma, args->page); +} + +/* Dirty dcache could be on another CPU, so do the IPIs */ +static void sb1_flush_icache_page(struct vm_area_struct *vma, + struct page *page) +{ + struct flush_icache_page_args args; + + if (!(vma->vm_flags & VM_EXEC)) + return; + args.vma = vma; + args.page = page; + on_each_cpu(sb1_flush_icache_page_ipi, (void *) &args, 1, 1); +} +#else +void sb1_flush_icache_page(struct vm_area_struct *vma, struct page *page); +asm("sb1_flush_icache_page = local_sb1_flush_icache_page"); +#endif + +/* + * A signal trampoline must fit into a single cacheline. + */ +static void local_sb1_flush_cache_sigtramp(unsigned long addr) +{ + __asm__ __volatile__ ( + " .set push \n" + " .set noreorder \n" + " .set noat \n" + " .set mips4 \n" + " cache %2, (0<<13)(%0) \n" /* Index-inval this address */ + " cache %2, (1<<13)(%0) \n" /* Index-inval this address */ + " cache %2, (2<<13)(%0) \n" /* Index-inval this address */ + " cache %2, (3<<13)(%0) \n" /* Index-inval this address */ + " xori $1, %0, 1<<12 \n" /* Flip index bit 12 */ + " cache %2, (0<<13)($1) \n" /* Index-inval this address */ + " cache %2, (1<<13)($1) \n" /* Index-inval this address */ + " cache %2, (2<<13)($1) \n" /* Index-inval this address */ + " cache %2, (3<<13)($1) \n" /* Index-inval this address */ + " cache %3, (0<<13)(%1) \n" /* Index-inval this address */ + " cache %3, (1<<13)(%1) \n" /* Index-inval this address */ + " cache %3, (2<<13)(%1) \n" /* Index-inval this address */ + " cache %3, (3<<13)(%1) \n" /* Index-inval this address */ + " bnezl $0, 1f \n" /* Force mispredict */ + " nop \n" + "1: \n" + " .set pop \n" + : + : "r" (addr & dcache_index_mask), "r" (addr & icache_index_mask), + "i" (Index_Writeback_Inv_D), "i" (Index_Invalidate_I)); +} + +#ifdef CONFIG_SMP +static void sb1_flush_cache_sigtramp_ipi(void *info) +{ + unsigned long iaddr = (unsigned long) info; + local_sb1_flush_cache_sigtramp(iaddr); +} + +static void sb1_flush_cache_sigtramp(unsigned long addr) +{ + on_each_cpu(sb1_flush_cache_sigtramp_ipi, (void *) addr, 1, 1); +} +#else +void sb1_flush_cache_sigtramp(unsigned long addr); +asm("sb1_flush_cache_sigtramp = local_sb1_flush_cache_sigtramp"); +#endif + + +/* + * Anything that just flushes dcache state can be ignored, as we're always + * coherent in dcache space. This is just a dummy function that all the + * nop'ed routines point to + */ +static void sb1_nop(void) +{ +} + +/* + * Cache set values (from the mips64 spec) + * 0 - 64 + * 1 - 128 + * 2 - 256 + * 3 - 512 + * 4 - 1024 + * 5 - 2048 + * 6 - 4096 + * 7 - Reserved + */ + +static unsigned int decode_cache_sets(unsigned int config_field) +{ + if (config_field == 7) { + /* JDCXXX - Find a graceful way to abort. */ + return 0; + } + return (1<<(config_field + 6)); +} + +/* + * Cache line size values (from the mips64 spec) + * 0 - No cache present. + * 1 - 4 bytes + * 2 - 8 bytes + * 3 - 16 bytes + * 4 - 32 bytes + * 5 - 64 bytes + * 6 - 128 bytes + * 7 - Reserved + */ + +static unsigned int decode_cache_line_size(unsigned int config_field) +{ + if (config_field == 0) { + return 0; + } else if (config_field == 7) { + /* JDCXXX - Find a graceful way to abort. */ + return 0; + } + return (1<<(config_field + 1)); +} + +/* + * Relevant bits of the config1 register format (from the MIPS32/MIPS64 specs) + * + * 24:22 Icache sets per way + * 21:19 Icache line size + * 18:16 Icache Associativity + * 15:13 Dcache sets per way + * 12:10 Dcache line size + * 9:7 Dcache Associativity + */ + +static __init void probe_cache_sizes(void) +{ + u32 config1; + + config1 = read_c0_config1(); + icache_line_size = decode_cache_line_size((config1 >> 19) & 0x7); + dcache_line_size = decode_cache_line_size((config1 >> 10) & 0x7); + icache_sets = decode_cache_sets((config1 >> 22) & 0x7); + dcache_sets = decode_cache_sets((config1 >> 13) & 0x7); + icache_assoc = ((config1 >> 16) & 0x7) + 1; + dcache_assoc = ((config1 >> 7) & 0x7) + 1; + icache_size = icache_line_size * icache_sets * icache_assoc; + dcache_size = dcache_line_size * dcache_sets * dcache_assoc; + /* Need to remove non-index bits for index ops */ + icache_index_mask = (icache_sets - 1) * icache_line_size; + dcache_index_mask = (dcache_sets - 1) * dcache_line_size; + /* + * These are for choosing range (index ops) versus all. + * icache flushes all ways for each set, so drop icache_assoc. + * dcache flushes all ways and each setting of bit 12 for each + * index, so drop dcache_assoc and halve the dcache_sets. + */ + icache_range_cutoff = icache_sets * icache_line_size; + dcache_range_cutoff = (dcache_sets / 2) * icache_line_size; +} + +/* + * This is called from loadmmu.c. We have to set up all the + * memory management function pointers, as well as initialize + * the caches and tlbs + */ +void ld_mmu_sb1(void) +{ + extern char except_vec2_sb1; + unsigned long temp; + + /* Special cache error handler for SB1 */ + memcpy((void *)(KSEG0 + 0x100), &except_vec2_sb1, 0x80); + memcpy((void *)(KSEG1 + 0x100), &except_vec2_sb1, 0x80); + + probe_cache_sizes(); + + _clear_page = sb1_clear_page; + _copy_page = sb1_copy_page; + + /* + * None of these are needed for the SB1 - the Dcache is + * physically indexed and tagged, so no virtual aliasing can + * occur + */ + flush_cache_range = (void *) sb1_nop; + flush_cache_page = sb1_flush_cache_page; + flush_cache_mm = (void (*)(struct mm_struct *))sb1_nop; + flush_cache_all = sb1_nop; + + /* These routines are for Icache coherence with the Dcache */ + flush_icache_range = sb1_flush_icache_range; + flush_icache_page = sb1_flush_icache_page; + flush_icache_all = __sb1_flush_icache_all; /* local only */ + + flush_cache_sigtramp = sb1_flush_cache_sigtramp; + flush_data_cache_page = (void *) sb1_nop; + + /* Full flush */ + __flush_cache_all = sb1___flush_cache_all; + + change_c0_config(CONF_CM_CMASK, CONF_CM_DEFAULT); + /* + * This is the only way to force the update of K0 to complete + * before subsequent instruction fetch. + */ + __asm__ __volatile__ ( + " .set push \n" + " .set mips4 \n" + " dla %0, 1f \n" + " dmtc0 %0, $14 \n" + " eret \n" + "1: .set pop \n" + : "=r" (temp)); + flush_cache_all(); +} diff -Nru a/arch/mips64/mm/cache.c b/arch/mips64/mm/cache.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips64/mm/cache.c Tue Jul 1 18:44:39 2003 @@ -0,0 +1,60 @@ +/* + * 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 - 2003 by Ralf Baechle + */ +#include +#include +#include + +#include + +asmlinkage int sys_cacheflush(void *addr, int bytes, int cache) +{ + /* This should flush more selectivly ... */ + __flush_cache_all(); + + return 0; +} + +void flush_dcache_page(struct page *page) +{ + unsigned long addr; + + if (page->mapping && + list_empty(&page->mapping->i_mmap) && + list_empty(&page->mapping->i_mmap_shared)) { + SetPageDcacheDirty(page); + + return; + } + + /* + * We could delay the flush for the !page->mapping case too. But that + * case is for exec env/arg pages and those are %99 certainly going to + * get faulted into the tlb (and thus flushed) anyways. + */ + addr = (unsigned long) page_address(page); + flush_data_cache_page(addr); +} + +void __update_cache(struct vm_area_struct *vma, unsigned long address, + pte_t pte) +{ + struct page *page; + unsigned long pfn, addr; + + pfn = pte_pfn(pte); + if (pfn_valid(pfn) && (page = pfn_to_page(pfn), page->mapping) && + Page_dcache_dirty(page)) { + if (pages_do_alias((unsigned long)page_address(page), + address & PAGE_MASK)) { + addr = (unsigned long) page_address(page); + flush_data_cache_page(addr); + } + + ClearPageDcacheDirty(page); + } +} diff -Nru a/arch/mips64/mm/cerr-sb1.c b/arch/mips64/mm/cerr-sb1.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips64/mm/cerr-sb1.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,542 @@ +/* + * Copyright (C) 2001 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +#ifndef CONFIG_SIBYTE_BUS_WATCHER +#include +#include +#include +#include +#endif + +/* SB1 definitions */ + +/* XXX should come from config1 XXX */ +#define SB1_CACHE_INDEX_MASK 0x1fe0 + +#define CP0_ERRCTL_RECOVERABLE (1 << 31) +#define CP0_ERRCTL_DCACHE (1 << 30) +#define CP0_ERRCTL_ICACHE (1 << 29) +#define CP0_ERRCTL_MULTIBUS (1 << 23) +#define CP0_ERRCTL_MC_TLB (1 << 15) +#define CP0_ERRCTL_MC_TIMEOUT (1 << 14) + +#define CP0_CERRI_TAG_PARITY (1 << 29) +#define CP0_CERRI_DATA_PARITY (1 << 28) +#define CP0_CERRI_EXTERNAL (1 << 26) + +#define CP0_CERRI_IDX_VALID(c) (!((c) & CP0_CERRI_EXTERNAL)) +#define CP0_CERRI_DATA (CP0_CERRI_DATA_PARITY) + +#define CP0_CERRD_MULTIPLE (1 << 31) +#define CP0_CERRD_TAG_STATE (1 << 30) +#define CP0_CERRD_TAG_ADDRESS (1 << 29) +#define CP0_CERRD_DATA_SBE (1 << 28) +#define CP0_CERRD_DATA_DBE (1 << 27) +#define CP0_CERRD_EXTERNAL (1 << 26) +#define CP0_CERRD_LOAD (1 << 25) +#define CP0_CERRD_STORE (1 << 24) +#define CP0_CERRD_FILLWB (1 << 23) +#define CP0_CERRD_COHERENCY (1 << 22) +#define CP0_CERRD_DUPTAG (1 << 21) + +#define CP0_CERRD_DPA_VALID(c) (!((c) & CP0_CERRD_EXTERNAL)) +#define CP0_CERRD_IDX_VALID(c) \ + (((c) & (CP0_CERRD_LOAD | CP0_CERRD_STORE)) ? (!((c) & CP0_CERRD_EXTERNAL)) : 0) +#define CP0_CERRD_CAUSES \ + (CP0_CERRD_LOAD | CP0_CERRD_STORE | CP0_CERRD_FILLWB | CP0_CERRD_COHERENCY | CP0_CERRD_DUPTAG) +#define CP0_CERRD_TYPES \ + (CP0_CERRD_TAG_STATE | CP0_CERRD_TAG_ADDRESS | CP0_CERRD_DATA_SBE | CP0_CERRD_DATA_DBE | CP0_CERRD_EXTERNAL) +#define CP0_CERRD_DATA (CP0_CERRD_DATA_SBE | CP0_CERRD_DATA_DBE) + +static uint32_t extract_ic(unsigned short addr, int data); +static uint32_t extract_dc(unsigned short addr, int data); + +static inline void breakout_errctl(unsigned int val) +{ + if (val & CP0_ERRCTL_RECOVERABLE) + prom_printf(" recoverable"); + if (val & CP0_ERRCTL_DCACHE) + prom_printf(" dcache"); + if (val & CP0_ERRCTL_ICACHE) + prom_printf(" icache"); + if (val & CP0_ERRCTL_MULTIBUS) + prom_printf(" multiple-buserr"); + prom_printf("\n"); +} + +static inline void breakout_cerri(unsigned int val) +{ + if (val & CP0_CERRI_TAG_PARITY) + prom_printf(" tag-parity"); + if (val & CP0_CERRI_DATA_PARITY) + prom_printf(" data-parity"); + if (val & CP0_CERRI_EXTERNAL) + prom_printf(" external"); + prom_printf("\n"); +} + +static inline void breakout_cerrd(unsigned int val) +{ + switch (val & CP0_CERRD_CAUSES) { + case CP0_CERRD_LOAD: + prom_printf(" load,"); + break; + case CP0_CERRD_STORE: + prom_printf(" store,"); + break; + case CP0_CERRD_FILLWB: + prom_printf(" fill/wb,"); + break; + case CP0_CERRD_COHERENCY: + prom_printf(" coherency,"); + break; + case CP0_CERRD_DUPTAG: + prom_printf(" duptags,"); + break; + default: + prom_printf(" NO CAUSE,"); + break; + } + if (!(val & CP0_CERRD_TYPES)) + prom_printf(" NO TYPE"); + else { + if (val & CP0_CERRD_MULTIPLE) + prom_printf(" multi-err"); + if (val & CP0_CERRD_TAG_STATE) + prom_printf(" tag-state"); + if (val & CP0_CERRD_TAG_ADDRESS) + prom_printf(" tag-address"); + if (val & CP0_CERRD_DATA_SBE) + prom_printf(" data-SBE"); + if (val & CP0_CERRD_DATA_DBE) + prom_printf(" data-DBE"); + if (val & CP0_CERRD_EXTERNAL) + prom_printf(" external"); + } + prom_printf("\n"); +} + +#ifndef CONFIG_SIBYTE_BUS_WATCHER + +static void check_bus_watcher(void) +{ + uint32_t status, l2_err, memio_err; + + /* Destructive read, clears register and interrupt */ + status = csr_in32(IO_SPACE_BASE | A_SCD_BUS_ERR_STATUS); + /* Bit 31 is always on, but there's no #define for that */ + if (status & ~(1UL << 31)) { + l2_err = csr_in32(IO_SPACE_BASE | A_BUS_L2_ERRORS); + memio_err = csr_in32(IO_SPACE_BASE | A_BUS_MEM_IO_ERRORS); + prom_printf("Bus watcher error counters: %08x %08x\n", l2_err, memio_err); + prom_printf("\nLast recorded signature:\n"); + prom_printf("Request %02x from %d, answered by %d with Dcode %d\n", + (unsigned int)(G_SCD_BERR_TID(status) & 0x3f), + (int)(G_SCD_BERR_TID(status) >> 6), + (int)G_SCD_BERR_RID(status), + (int)G_SCD_BERR_DCODE(status)); + } else { + prom_printf("Bus watcher indicates no error\n"); + } +} +#else +extern void check_bus_watcher(void); +#endif + +asmlinkage void sb1_cache_error(void) +{ + uint64_t cerr_dpa; + uint32_t errctl, cerr_i, cerr_d, dpalo, dpahi, eepc, res; + + prom_printf("Cache error exception on CPU %x:\n", + (read_c0_prid() >> 25) & 0x7); + + __asm__ __volatile__ ( + " .set push\n\t" + " .set mips64\n\t" + " .set noat\n\t" + " mfc0 %0, $26\n\t" + " mfc0 %1, $27\n\t" + " mfc0 %2, $27, 1\n\t" + " dmfc0 $1, $27, 3\n\t" + " dsrl32 %3, $1, 0 \n\t" + " sll %4, $1, 0 \n\t" + " mfc0 %5, $30\n\t" + " .set pop" + : "=r" (errctl), "=r" (cerr_i), "=r" (cerr_d), + "=r" (dpahi), "=r" (dpalo), "=r" (eepc)); + + cerr_dpa = (((uint64_t)dpahi) << 32) | dpalo; + prom_printf(" c0_errorepc == %08x\n", eepc); + prom_printf(" c0_errctl == %08x", errctl); + breakout_errctl(errctl); + if (errctl & CP0_ERRCTL_ICACHE) { + prom_printf(" c0_cerr_i == %08x", cerr_i); + breakout_cerri(cerr_i); + if (CP0_CERRI_IDX_VALID(cerr_i)) { + if ((eepc & SB1_CACHE_INDEX_MASK) != (cerr_i & SB1_CACHE_INDEX_MASK)) + prom_printf(" cerr_i idx doesn't match eepc\n"); + else { + res = extract_ic(cerr_i & SB1_CACHE_INDEX_MASK, + (cerr_i & CP0_CERRI_DATA) != 0); + if (!(res & cerr_i)) + prom_printf("...didn't see indicated icache problem\n"); + } + } + } + if (errctl & CP0_ERRCTL_DCACHE) { + prom_printf(" c0_cerr_d == %08x", cerr_d); + breakout_cerrd(cerr_d); + if (CP0_CERRD_DPA_VALID(cerr_d)) { + prom_printf(" c0_cerr_dpa == %010llx\n", cerr_dpa); + if (!CP0_CERRD_IDX_VALID(cerr_d)) { + res = extract_dc(cerr_dpa & SB1_CACHE_INDEX_MASK, + (cerr_d & CP0_CERRD_DATA) != 0); + if (!(res & cerr_d)) + prom_printf("...didn't see indicated dcache problem\n"); + } else { + if ((cerr_dpa & SB1_CACHE_INDEX_MASK) != (cerr_d & SB1_CACHE_INDEX_MASK)) + prom_printf(" cerr_d idx doesn't match cerr_dpa\n"); + else { + res = extract_dc(cerr_d & SB1_CACHE_INDEX_MASK, + (cerr_d & CP0_CERRD_DATA) != 0); + if (!(res & cerr_d)) + prom_printf("...didn't see indicated problem\n"); + } + } + } + } + + check_bus_watcher(); + + while (1); + /* + * This tends to make things get really ugly; let's just stall instead. + * panic("Can't handle the cache error!"); + */ +} + + +/* Parity lookup table. */ +static const uint8_t parity[256] = { + 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1, + 1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0, + 1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0, + 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1, + 1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0, + 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1, + 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1, + 1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0 +}; + +/* Masks to select bits for Hamming parity, mask_72_64[i] for bit[i] */ +static const uint64_t mask_72_64[8] = { + 0x0738C808099264FFL, + 0x38C808099264FF07L, + 0xC808099264FF0738L, + 0x08099264FF0738C8L, + 0x099264FF0738C808L, + 0x9264FF0738C80809L, + 0x64FF0738C8080992L, + 0xFF0738C808099264L +}; + +/* Calculate the parity on a range of bits */ +static char range_parity(uint64_t dword, int max, int min) +{ + char parity = 0; + int i; + dword >>= min; + for (i=max-min; i>=0; i--) { + if (dword & 0x1) + parity = !parity; + dword >>= 1; + } + return parity; +} + +/* Calculate the 4-bit even byte-parity for an instruction */ +static unsigned char inst_parity(uint32_t word) +{ + int i, j; + char parity = 0; + for (j=0; j<4; j++) { + char byte_parity = 0; + for (i=0; i<8; i++) { + if (word & 0x80000000) + byte_parity = !byte_parity; + word <<= 1; + } + parity <<= 1; + parity |= byte_parity; + } + return parity; +} + +static uint32_t extract_ic(unsigned short addr, int data) +{ + unsigned short way; + int valid; + uint64_t taglo, va, tlo_tmp; + uint32_t taghi, taglolo, taglohi; + uint8_t lru; + int res = 0; + + prom_printf("Icache index 0x%04x ", addr); + for (way = 0; way < 4; way++) { + /* Index-load-tag-I */ + __asm__ __volatile__ ( + " .set push \n\t" + " .set noreorder \n\t" + " .set mips64 \n\t" + " .set noat \n\t" + " cache 4, 0(%3) \n\t" + " mfc0 %0, $29 \n\t" + " dmfc0 $1, $28 \n\t" + " dsrl32 %1, $1, 0 \n\t" + " sll %2, $1, 0 \n\t" + " .set pop" + : "=r" (taghi), "=r" (taglohi), "=r" (taglolo) + : "r" ((way << 13) | addr)); + + taglo = ((unsigned long long)taglohi << 32) | taglolo; + if (way == 0) { + lru = (taghi >> 14) & 0xff; + prom_printf("[Bank %d Set 0x%02x] LRU > %d %d %d %d > MRU\n", + ((addr >> 5) & 0x3), /* bank */ + ((addr >> 7) & 0x3f), /* index */ + (lru & 0x3), + ((lru >> 2) & 0x3), + ((lru >> 4) & 0x3), + ((lru >> 6) & 0x3)); + } + va = (taglo & 0xC0000FFFFFFFE000) | addr; + if ((taglo & (1 << 31)) && (((taglo >> 62) & 0x3) == 3)) + va |= 0x3FFFF00000000000; + valid = ((taghi >> 29) & 1); + if (valid) { + tlo_tmp = taglo & 0xfff3ff; + if (((taglo >> 10) & 1) ^ range_parity(tlo_tmp, 23, 0)) { + prom_printf(" ** bad parity in VTag0/G/ASID\n"); + res |= CP0_CERRI_TAG_PARITY; + } + if (((taglo >> 11) & 1) ^ range_parity(taglo, 63, 24)) { + prom_printf(" ** bad parity in R/VTag1\n"); + res |= CP0_CERRI_TAG_PARITY; + } + } + if (valid ^ ((taghi >> 27) & 1)) { + prom_printf(" ** bad parity for valid bit\n"); + res |= CP0_CERRI_TAG_PARITY; + } + prom_printf(" %d [VA %016llx] [Vld? %d] raw tags: %08X-%016llX\n", + way, va, valid, taghi, taglo); + + if (data) { + uint32_t datahi, insta, instb; + uint8_t predecode; + int offset; + + /* (hit all banks and ways) */ + for (offset = 0; offset < 4; offset++) { + /* Index-load-data-I */ + __asm__ __volatile__ ( + " .set push\n\t" + " .set noreorder\n\t" + " .set mips64\n\t" + " .set noat\n\t" + " cache 6, 0(%3) \n\t" + " mfc0 %0, $29, 1\n\t" + " dmfc0 $1, $28, 1\n\t" + " dsrl32 %1, $1, 0 \n\t" + " sll %2, $1, 0 \n\t" + " .set pop \n" + : "=r" (datahi), "=r" (insta), "=r" (instb) + : "r" ((way << 13) | addr | (offset << 3))); + predecode = (datahi >> 8) & 0xff; + if (((datahi >> 16) & 1) != (uint32_t)range_parity(predecode, 7, 0)) { + prom_printf(" ** bad parity in predecode\n"); + res |= CP0_CERRI_DATA_PARITY; + } + /* XXXKW should/could check predecode bits themselves */ + if (((datahi >> 4) & 0xf) ^ inst_parity(insta)) { + prom_printf(" ** bad parity in instruction a\n"); + res |= CP0_CERRI_DATA_PARITY; + } + if ((datahi & 0xf) ^ inst_parity(instb)) { + prom_printf(" ** bad parity in instruction b\n"); + res |= CP0_CERRI_DATA_PARITY; + } + prom_printf(" %05X-%08X%08X", datahi, insta, instb); + } + prom_printf("\n"); + } + } + return res; +} + +/* Compute the ECC for a data doubleword */ +static uint8_t dc_ecc(uint64_t dword) +{ + uint64_t t; + uint32_t w; + uint8_t p; + int i; + + p = 0; + for (i = 7; i >= 0; i--) + { + p <<= 1; + t = dword & mask_72_64[i]; + w = (uint32_t)(t >> 32); + p ^= (parity[w>>24] ^ parity[(w>>16) & 0xFF] + ^ parity[(w>>8) & 0xFF] ^ parity[w & 0xFF]); + w = (uint32_t)(t & 0xFFFFFFFF); + p ^= (parity[w>>24] ^ parity[(w>>16) & 0xFF] + ^ parity[(w>>8) & 0xFF] ^ parity[w & 0xFF]); + } + return p; +} + +struct dc_state { + unsigned char val; + char *name; +}; + +static struct dc_state dc_states[] = { + { 0x00, "INVALID" }, + { 0x0f, "COH-SHD" }, + { 0x13, "NCO-E-C" }, + { 0x19, "NCO-E-D" }, + { 0x16, "COH-E-C" }, + { 0x1c, "COH-E-D" }, + { 0xff, "*ERROR*" } +}; + +#define DC_TAG_VALID(state) \ + (((state) == 0xf) || ((state) == 0x13) || ((state) == 0x19) || ((state == 0x16)) || ((state) == 0x1c)) + +static char *dc_state_str(unsigned char state) +{ + struct dc_state *dsc = dc_states; + while (dsc->val != 0xff) { + if (dsc->val == state) + break; + dsc++; + } + return dsc->name; +} + +static uint32_t extract_dc(unsigned short addr, int data) +{ + int valid, way; + unsigned char state; + uint64_t taglo, pa; + uint32_t taghi, taglolo, taglohi; + uint8_t ecc, lru; + int res = 0; + + prom_printf("Dcache index 0x%04x ", addr); + for (way = 0; way < 4; way++) { + __asm__ __volatile__ ( + " .set push\n\t" + " .set noreorder\n\t" + " .set mips64\n\t" + " .set noat\n\t" + " cache 5, 0(%3)\n\t" /* Index-load-tag-D */ + " mfc0 %0, $29, 2\n\t" + " dmfc0 $1, $28, 2\n\t" + " dsrl32 %1, $1, 0\n\t" + " sll %2, $1, 0\n\t" + " .set pop" + : "=r" (taghi), "=r" (taglohi), "=r" (taglolo) + : "r" ((way << 13) | addr)); + + taglo = ((unsigned long long)taglohi << 32) | taglolo; + pa = (taglo & 0xFFFFFFE000) | addr; + if (way == 0) { + lru = (taghi >> 14) & 0xff; + prom_printf("[Bank %d Set 0x%02x] LRU > %d %d %d %d > MRU\n", + ((addr >> 11) & 0x2) | ((addr >> 5) & 1), /* bank */ + ((addr >> 6) & 0x3f), /* index */ + (lru & 0x3), + ((lru >> 2) & 0x3), + ((lru >> 4) & 0x3), + ((lru >> 6) & 0x3)); + } + state = (taghi >> 25) & 0x1f; + valid = DC_TAG_VALID(state); + prom_printf(" %d [PA %010llx] [state %s (%02x)] raw tags: %08X-%016llX\n", + way, pa, dc_state_str(state), state, taghi, taglo); + if (valid) { + if (((taglo >> 11) & 1) ^ range_parity(taglo, 39, 26)) { + prom_printf(" ** bad parity in PTag1\n"); + res |= CP0_CERRD_TAG_ADDRESS; + } + if (((taglo >> 10) & 1) ^ range_parity(taglo, 25, 13)) { + prom_printf(" ** bad parity in PTag0\n"); + res |= CP0_CERRD_TAG_ADDRESS; + } + } else { + res |= CP0_CERRD_TAG_STATE; + } + + if (data) { + uint64_t datalo; + uint32_t datalohi, datalolo, datahi; + int offset; + + for (offset = 0; offset < 4; offset++) { + /* Index-load-data-D */ + __asm__ __volatile__ ( + " .set push\n\t" + " .set noreorder\n\t" + " .set mips64\n\t" + " .set noat\n\t" + " cache 7, 0(%3)\n\t" /* Index-load-data-D */ + " mfc0 %0, $29, 3\n\t" + " dmfc0 $1, $28, 3\n\t" + " dsrl32 %1, $1, 0 \n\t" + " sll %2, $1, 0 \n\t" + " .set pop" + : "=r" (datahi), "=r" (datalohi), "=r" (datalolo) + : "r" ((way << 13) | addr | (offset << 3))); + datalo = ((unsigned long long)datalohi << 32) | datalolo; + ecc = dc_ecc(datalo); + if (ecc != datahi) { + int bits = 0; + prom_printf(" ** bad ECC (%02x %02x) ->", + datahi, ecc); + ecc ^= datahi; + while (ecc) { + if (ecc & 1) bits++; + ecc >>= 1; + } + res |= (bits == 1) ? CP0_CERRD_DATA_SBE : CP0_CERRD_DATA_DBE; + } + prom_printf(" %02X-%016llX", datahi, datalo); + } + prom_printf("\n"); + } + } + return res; +} diff -Nru a/arch/mips64/mm/cex-sb1.S b/arch/mips64/mm/cex-sb1.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips64/mm/cex-sb1.S Tue Jul 1 18:44:40 2003 @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2001,2002,2003 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#include +#include + +#include +#include +#include +#include +#include + + .text + .set noat + .set mips4 + + __INIT + + /* Cache Error handler for SB1 */ + LEAF(except_vec2_sb1) + mfc0 k1, $26 + # check if error was recoverable + bltz k1, leave_cerr +#ifdef CONFIG_SB1_PASS_1_WORKAROUNDS + # look for signature of spurious CErr + lui k0, 0x4000 + bne k0, k1, 1f + .word 0x401Bd801 # mfc0 k1, $27, 1 + lui k0, 0xffe0 + and k1, k0, k1 + lui k0, 0x0200 + beq k0, k1, leave_cerr +1: +#endif + j handle_vec2_sb1 + +leave_cerr: + # clear/unlock the registers + mtc0 zero, $26 + mtc0 zero, $27 + .word 0x4080d801 # mtc0 zero, $27, 1 + .word 0x4080d803 # mtc0 zero, $27, 3 + eret + END(except_vec2_sb1) + + __FINIT + + LEAF(handle_vec2_sb1) + mfc0 k0,CP0_CONFIG + li k1,~CONF_CM_CMASK + and k0,k0,k1 + ori k0,k0,CONF_CM_UNCACHED + mtc0 k0,CP0_CONFIG + + SSNOP + SSNOP + SSNOP + SSNOP + bnezl $0, 1f +1: + mfc0 k0, CP0_STATUS + sll k0, k0, 3 # check CU0 (kernel?) + bltz k0, 2f + get_saved_sp + move sp, k1 # want Kseg SP (so uncached) +2: + j sb1_cache_error + + END(handle_vec2_sb1) diff -Nru a/arch/mips64/mm/extable.c b/arch/mips64/mm/extable.c --- a/arch/mips64/mm/extable.c Tue Jul 1 18:44:32 2003 +++ b/arch/mips64/mm/extable.c Tue Jul 1 18:44:32 2003 @@ -1,65 +1,30 @@ /* - * 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, 1995, 1996, 1999 by Ralf Baechle - * Copyright (C) 1999 by Silicon Graphics + * linux/arch/i386/mm/extable.c */ + #include #include #include #include -extern const struct exception_table_entry __start___ex_table[]; -extern const struct exception_table_entry __stop___ex_table[]; - -static inline unsigned long -search_one_table(const struct exception_table_entry *first, - const struct exception_table_entry *last, - unsigned long value) +/* Simple binary search */ +const struct exception_table_entry * +search_extable(const struct exception_table_entry *first, + const struct exception_table_entry *last, + unsigned long value) { - while (first <= last) { + while (first <= last) { const struct exception_table_entry *mid; long diff; mid = (last - first) / 2 + first; diff = mid->insn - value; - if (diff == 0) - return mid->nextinsn; - else if (diff < 0) - first = mid+1; - else - last = mid-1; - } - return 0; -} - -extern spinlock_t modlist_lock; - -unsigned long search_exception_table(unsigned long addr) -{ - unsigned long ret = 0; - unsigned long flags; - -#ifndef CONFIG_MODULES - /* There is only the kernel to search. */ - ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr); - return ret; -#else - /* The kernel is the last "module" -- no need to treat it special. */ - struct module *mp; - - spin_lock_irqsave(&modlist_lock, flags); - for (mp = module_list; mp != NULL; mp = mp->next) { - if (mp->ex_table_start == NULL) - continue; - ret = search_one_table(mp->ex_table_start, - mp->ex_table_end - 1, addr); - if (ret) - break; - } - spin_unlock_irqrestore(&modlist_lock, flags); - return ret; -#endif + if (diff == 0) + return mid; + else if (diff < 0) + first = mid+1; + else + last = mid-1; + } + return NULL; } diff -Nru a/arch/mips64/mm/fault.c b/arch/mips64/mm/fault.c --- a/arch/mips64/mm/fault.c Tue Jul 1 18:44:35 2003 +++ b/arch/mips64/mm/fault.c Tue Jul 1 18:44:35 2003 @@ -20,7 +20,10 @@ #include #include #include +#include /* For unblank_screen() */ +#include +#include #include #include #include @@ -30,60 +33,34 @@ #define development_version (LINUX_VERSION_CODE & 0x100) -extern void die(char *, struct pt_regs *, unsigned long write); - /* * Macro for exception fixup code to access integer registers. */ #define dpf_reg(r) (regs->regs[r]) -asmlinkage void -dodebug(abi64_no_regargs, struct pt_regs regs) -{ - printk("Got syscall %ld, cpu %d proc %s:%d epc 0x%lx\n", regs.regs[2], - smp_processor_id(), current->comm, current->pid, regs.cp0_epc); -} - -asmlinkage void -dodebug2(abi64_no_regargs, struct pt_regs regs) -{ - unsigned long retaddr; - - __asm__ __volatile__( - ".set noreorder\n\t" - "add %0,$0,$31\n\t" - ".set reorder" - : "=r" (retaddr)); - printk("Got exception 0x%lx at 0x%lx\n", retaddr, regs.cp0_epc); -} - -extern spinlock_t timerlist_lock; - /* - * Unlock any spinlocks which will prevent us from getting the - * message out (timerlist_lock is acquired through the - * console unblank code) + * Unlock any spinlocks which will prevent us from getting the out */ void bust_spinlocks(int yes) { - spin_lock_init(&timerlist_lock); + int loglevel_save = console_loglevel; + if (yes) { oops_in_progress = 1; - } else { - int loglevel_save = console_loglevel; + return; + } #ifdef CONFIG_VT - unblank_screen(); + unblank_screen(); #endif - oops_in_progress = 0; - /* - * OK, the message is on the console. Now we call printk() - * without oops_in_progress set so that printk will give klogd - * a poke. Hold onto your hats... - */ - console_loglevel = 15; /* NMI oopser may have shut the console up */ - printk(" "); - console_loglevel = loglevel_save; - } + oops_in_progress = 0; + /* + * OK, the message is on the console. Now we call printk() + * without oops_in_progress set so that printk will give klogd + * a poke. Hold onto your hats... + */ + console_loglevel = 15; /* NMI oopser may have shut the console up */ + printk(" "); + console_loglevel = loglevel_save; } /* @@ -91,15 +68,20 @@ * and the problem, and then passes it off to one of the appropriate * routines. */ -asmlinkage void -do_page_fault(struct pt_regs *regs, unsigned long write, unsigned long address) +asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write, + unsigned long address) { struct vm_area_struct * vma; struct task_struct *tsk = current; struct mm_struct *mm = tsk->mm; - unsigned long fixup; + const struct exception_table_entry *fixup; siginfo_t info; +#if 0 + printk("Cpu%d[%s:%d:%08lx:%ld:%08lx]\n", smp_processor_id(), + current->comm, current->pid, address, write, regs->cp0_epc); +#endif + /* * We fault-in kernel-space virtual memory on-demand. The * 'reference' page table is init_mm.pgd. @@ -109,7 +91,7 @@ * only copy the information from the master page table, * nothing more. */ - if (address >= TASK_SIZE) + if (address >= VMALLOC_START) goto vmalloc_fault; info.si_code = SEGV_MAPERR; @@ -117,12 +99,9 @@ * If we're in an interrupt or have no user * context, we must not take the fault.. */ - if (in_interrupt() || mm == &init_mm) + if (in_atomic() || !mm) goto no_context; -#if DEBUG_MIPS64 - printk("Cpu%d[%s:%d:%08lx:%ld:%08lx]\n", smp_processor_id(), current->comm, - current->pid, address, write, regs->cp0_epc); -#endif + down_read(&mm->mmap_sem); vma = find_vma(mm, address); if (!vma) @@ -148,22 +127,25 @@ goto bad_area; } +survive: /* * If for any reason at all we couldn't handle the fault, * make sure we exit gracefully rather than endlessly redo * the fault. */ switch (handle_mm_fault(mm, vma, address, write)) { - case 1: + case VM_FAULT_MINOR: tsk->min_flt++; break; - case 2: + case VM_FAULT_MAJOR: tsk->maj_flt++; break; - case 0: + case VM_FAULT_SIGBUS: goto do_sigbus; - default: + case VM_FAULT_OOM: goto out_of_memory; + default: + BUG(); } up_read(&mm->mmap_sem); @@ -176,7 +158,7 @@ bad_area: up_read(&mm->mmap_sem); -bad_area_nosemaphore: + /* User mode accesses just cause a SIGSEGV */ if (user_mode(regs)) { tsk->thread.cp0_badvaddr = address; tsk->thread.error_code = write; @@ -199,12 +181,11 @@ no_context: /* Are we prepared to handle this kernel fault? */ - fixup = search_exception_table(regs->cp0_epc); + fixup = search_exception_tables(exception_epc(regs)); if (fixup) { - long new_epc; + unsigned long new_epc = fixup->nextinsn; tsk->thread.cp0_baduaddr = address; - new_epc = fixup_exception(dpf_reg, fixup, regs->cp0_epc); if (development_version) printk(KERN_DEBUG "%s: Exception at [<%lx>] (%lx)\n", tsk->comm, regs->cp0_epc, new_epc); @@ -220,12 +201,9 @@ bust_spinlocks(1); printk(KERN_ALERT "Cpu %d Unable to handle kernel paging request at " - "address %08lx, epc == %08x, ra == %08x\n", - smp_processor_id(), address, (unsigned int) regs->cp0_epc, - (unsigned int) regs->regs[31]); - die("Oops", regs, write); - do_exit(SIGKILL); - bust_spinlocks(0); + "address %016lx, epc == %016lx, ra == %016lx\n", + smp_processor_id(), address, regs->cp0_epc, regs->regs[31]); + die("Oops", regs); /* * We ran out of memory, or some other thing happened to us that made @@ -233,6 +211,11 @@ */ out_of_memory: up_read(&mm->mmap_sem); + if (tsk->pid == 1) { + yield(); + down_read(&mm->mmap_sem); + goto survive; + } printk("VM: killing process %s\n", tsk->comm); if (user_mode(regs)) do_exit(SIGKILL); diff -Nru a/arch/mips64/mm/init.c b/arch/mips64/mm/init.c --- a/arch/mips64/mm/init.c Tue Jul 1 18:44:36 2003 +++ b/arch/mips64/mm/init.c Tue Jul 1 18:44:36 2003 @@ -27,13 +27,12 @@ #include #include #include +#include #include #include -#ifdef CONFIG_SGI_IP22 -#include -#endif #include #include +#include DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); @@ -57,20 +56,6 @@ } } -pgd_t *get_pgd_slow(void) -{ - pgd_t *ret, *init; - - ret = (pgd_t *) __get_free_pages(GFP_KERNEL, 1); - if (ret) { - init = pgd_offset(&init_mm, 0); - pgd_init((unsigned long)ret); - memcpy(ret + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD, - (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); - } - return ret; -} - void pmd_init(unsigned long addr, unsigned long pagetable) { unsigned long *p, *end; @@ -91,31 +76,6 @@ } } -int do_check_pgt_cache(int low, int high) -{ - int freed = 0; - - if (pgtable_cache_size > high) { - do { - if (pgd_quicklist) - free_pgd_slow(get_pgd_fast()), freed++; - if (pmd_quicklist) - free_pmd_slow(get_pmd_fast()), freed++; - if (pte_quicklist) - free_pte_slow(get_pte_fast()), freed++; - } while (pgtable_cache_size > low); - } - return freed; -} - - -asmlinkage int sys_cacheflush(void *addr, int bytes, int cache) -{ - /* XXX Just get it working for now... */ - flush_cache_l1(); - return 0; -} - /* * We have up to 8 empty zeroed pages so we can map one of the right colour * when needed. This is necessary only on R4000 / R4400 SC and MC versions @@ -130,16 +90,10 @@ unsigned long order, size; struct page *page; - switch (mips_cputype) { - case CPU_R4000SC: - case CPU_R4000MC: - case CPU_R4400SC: - case CPU_R4400MC: + if (cpu_has_vce) order = 3; - break; - default: + else order = 0; - } empty_zero_page = __get_free_pages(GFP_KERNEL, order); if (!empty_zero_page) @@ -159,185 +113,6 @@ return 1UL << order; } -void __init add_memory_region(unsigned long start, unsigned long size, - long type) -{ - int x = boot_mem_map.nr_map; - - if (x == BOOT_MEM_MAP_MAX) { - printk("Ooops! Too many entries in the memory map!\n"); - return; - } - - boot_mem_map.map[x].addr = start; - boot_mem_map.map[x].size = size; - boot_mem_map.map[x].type = type; - boot_mem_map.nr_map++; -} - -static void __init print_memory_map(void) -{ - int i; - - for (i = 0; i < boot_mem_map.nr_map; i++) { - printk(" memory: %08lx @ %08lx ", - boot_mem_map.map[i].size, boot_mem_map.map[i].addr); - switch (boot_mem_map.map[i].type) { - case BOOT_MEM_RAM: - printk("(usable)\n"); - break; - case BOOT_MEM_ROM_DATA: - printk("(ROM data)\n"); - break; - case BOOT_MEM_RESERVED: - printk("(reserved)\n"); - break; - default: - printk("type %lu\n", boot_mem_map.map[i].type); - break; - } - } -} - -void bootmem_init(void) { -#ifdef CONFIG_BLK_DEV_INITRD - unsigned long tmp; - unsigned long *initrd_header; -#endif - unsigned long bootmap_size; - unsigned long start_pfn, max_pfn; - int i; - extern int _end; - -#define PFN_UP(x) (((x) + PAGE_SIZE - 1) >> PAGE_SHIFT) -#define PFN_DOWN(x) ((x) >> PAGE_SHIFT) -#define PFN_PHYS(x) ((x) << PAGE_SHIFT) - - /* - * Partially used pages are not usable - thus - * we are rounding upwards. - */ - start_pfn = PFN_UP(__pa(&_end)); - - /* Find the highest page frame number we have available. */ - max_pfn = 0; - for (i = 0; i < boot_mem_map.nr_map; i++) { - unsigned long start, end; - - if (boot_mem_map.map[i].type != BOOT_MEM_RAM) - continue; - - start = PFN_UP(boot_mem_map.map[i].addr); - end = PFN_DOWN(boot_mem_map.map[i].addr - + boot_mem_map.map[i].size); - - if (start >= end) - continue; - if (end > max_pfn) - max_pfn = end; - } - - /* Initialize the boot-time allocator. */ - bootmap_size = init_bootmem(start_pfn, max_pfn); - - /* - * Register fully available low RAM pages with the bootmem allocator. - */ - for (i = 0; i < boot_mem_map.nr_map; i++) { - unsigned long curr_pfn, last_pfn, size; - - /* - * Reserve usable memory. - */ - if (boot_mem_map.map[i].type != BOOT_MEM_RAM) - continue; - - /* - * We are rounding up the start address of usable memory: - */ - curr_pfn = PFN_UP(boot_mem_map.map[i].addr); - if (curr_pfn >= max_pfn) - continue; - if (curr_pfn < start_pfn) - curr_pfn = start_pfn; - - /* - * ... and at the end of the usable range downwards: - */ - last_pfn = PFN_DOWN(boot_mem_map.map[i].addr - + boot_mem_map.map[i].size); - - if (last_pfn > max_pfn) - last_pfn = max_pfn; - - /* - * ... finally, did all the rounding and playing - * around just make the area go away? - */ - if (last_pfn <= curr_pfn) - continue; - - size = last_pfn - curr_pfn; - free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size)); - } - - /* Reserve the bootmap memory. */ - reserve_bootmem(PFN_PHYS(start_pfn), bootmap_size); - -#ifdef CONFIG_BLK_DEV_INITRD -#error "Initrd is broken, please fit it." - tmp = (((unsigned long)&_end + PAGE_SIZE-1) & PAGE_MASK) - 8; - if (tmp < (unsigned long)&_end) - tmp += PAGE_SIZE; - initrd_header = (unsigned long *)tmp; - if (initrd_header[0] == 0x494E5244) { - initrd_start = (unsigned long)&initrd_header[2]; - initrd_end = initrd_start + initrd_header[1]; - initrd_below_start_ok = 1; - if (initrd_end > memory_end) { - printk("initrd extends beyond end of memory " - "(0x%08lx > 0x%08lx)\ndisabling initrd\n", - initrd_end,memory_end); - initrd_start = 0; - } else - *memory_start_p = initrd_end; - } -#endif - -#undef PFN_UP -#undef PFN_DOWN -#undef PFN_PHYS - -} - -void show_mem(void) -{ - int i, free = 0, total = 0, reserved = 0; - int shared = 0, cached = 0; - - printk("Mem-info:\n"); - show_free_areas(); - printk("Free swap: %6dkB\n", nr_swap_pages<<(PAGE_SHIFT-10)); - i = max_mapnr; - while (i-- > 0) { - total++; - if (PageReserved(mem_map+i)) - reserved++; - else if (PageSwapCache(mem_map+i)) - cached++; - else if (!page_count(mem_map + i)) - free++; - else - shared += page_count(mem_map + i) - 1; - } - printk("%d pages of RAM\n", total); - printk("%d reserved pages\n", reserved); - printk("%d pages shared\n", shared); - printk("%d pages swap cached\n",cached); - printk("%ld pages in page table cache\n", pgtable_cache_size); - printk("%d free pages\n", free); -} - #ifndef CONFIG_DISCONTIGMEM /* References to section boundaries */ @@ -361,7 +136,7 @@ max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT; low = max_low_pfn; -#if defined(CONFIG_PCI) || defined(CONFIG_ISA) +#ifdef CONFIG_ISA if (low < max_dma) zones_size[ZONE_DMA] = low; else { @@ -373,15 +148,38 @@ #endif free_area_init(zones_size); - - memset((void *)kptbl, 0, PAGE_SIZE << KPTBL_PAGE_ORDER); + + memset((void *)kptbl, 0, PAGE_SIZE << PGD_ORDER); memset((void *)kpmdtbl, 0, PAGE_SIZE); - pgd_set(swapper_pg_dir, kpmdtbl); - for (i = 0; i < (1 << KPTBL_PAGE_ORDER); pmd++,i++,pte+=PTRS_PER_PTE) + set_pgd(swapper_pg_dir, __pgd(kpmdtbl)); + for (i = 0; i < (1 << PGD_ORDER); pmd++,i++,pte+=PTRS_PER_PTE) pmd_val(*pmd) = (unsigned long)pte; } -extern int page_is_ram(unsigned long pagenr); +#define PFN_UP(x) (((x) + PAGE_SIZE - 1) >> PAGE_SHIFT) +#define PFN_DOWN(x) ((x) >> PAGE_SHIFT) + +static inline int page_is_ram(unsigned long pagenr) +{ + int i; + + for (i = 0; i < boot_mem_map.nr_map; i++) { + unsigned long addr, end; + + if (boot_mem_map.map[i].type != BOOT_MEM_RAM) + /* not usable memory */ + continue; + + addr = PFN_UP(boot_mem_map.map[i].addr); + end = PFN_DOWN(boot_mem_map.map[i].addr + + boot_mem_map.map[i].size); + + if (pagenr >= addr && pagenr < end) + return 1; + } + + return 0; +} void __init mem_init(void) { @@ -402,12 +200,12 @@ reservedpages++; } - codesize = (unsigned long) &_etext - (unsigned long) &_stext; - datasize = (unsigned long) &_edata - (unsigned long) &_fdata; + codesize = (unsigned long) &_etext - (unsigned long) &_text; + datasize = (unsigned long) &_edata - (unsigned long) &_etext; initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin; - printk("Memory: %luk/%luk available (%ldk kernel code, %ldk reserved, " - "%ldk data, %ldk init)\n", + printk(KERN_INFO "Memory: %luk/%luk available (%ldk kernel code, " + "%ldk reserved, %ldk data, %ldk init)\n", (unsigned long) nr_free_pages() << (PAGE_SHIFT-10), ram << (PAGE_SHIFT-10), codesize >> 10, @@ -420,26 +218,30 @@ #ifdef CONFIG_BLK_DEV_INITRD void free_initrd_mem(unsigned long start, unsigned long end) { + /* Switch from KSEG0 to XKPHYS addresses */ + start = (unsigned long)phys_to_virt(CPHYSADDR(start)); + end = (unsigned long)phys_to_virt(CPHYSADDR(end)); + if (start < end) + printk(KERN_INFO "Freeing initrd memory: %ldk freed\n", + (end - start) >> 10); + for (; start < end; start += PAGE_SIZE) { ClearPageReserved(virt_to_page(start)); set_page_count(virt_to_page(start), 1); free_page(start); totalram_pages++; } - printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); } #endif -extern char __init_begin, __init_end; -extern void prom_free_prom_memory(void); +extern void prom_free_prom_memory(void) __init; -void -free_initmem(void) +void free_initmem(void) { unsigned long addr, page; prom_free_prom_memory(); - + addr = (unsigned long)(&__init_begin); while (addr < (unsigned long)&__init_end) { page = PAGE_OFFSET | CPHYSADDR(addr); @@ -449,6 +251,6 @@ totalram_pages++; addr += PAGE_SIZE; } - printk("Freeing unused kernel memory: %ldk freed\n", + printk(KERN_INFO "Freeing unused kernel memory: %ldk freed\n", (&__init_end - &__init_begin) >> 10); } diff -Nru a/arch/mips64/mm/loadmmu.c b/arch/mips64/mm/loadmmu.c --- a/arch/mips64/mm/loadmmu.c Tue Jul 1 18:44:35 2003 +++ b/arch/mips64/mm/loadmmu.c Tue Jul 1 18:44:35 2003 @@ -4,101 +4,117 @@ * for more details. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * Copyright (C) 1997, 1999 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 1997, 1999, 2000, 2001, 2002, 2003 Ralf Baechle (ralf@gnu.org) * Copyright (C) 1999 Silicon Graphics, Inc. + * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved. */ #include #include #include #include #include +#include +#include +#include #include #include #include -#include -#include /* memory functions */ void (*_clear_page)(void * page); void (*_copy_page)(void * to, void * from); /* Cache operations. */ -void (*_flush_cache_mm)(struct mm_struct *mm); -void (*_flush_cache_range)(struct vm_area_struct *vma, unsigned long start, - unsigned long end); -void (*_flush_cache_page)(struct vm_area_struct *vma, unsigned long page); -void (*_flush_page_to_ram)(struct page * page); +void (*flush_cache_all)(void); +void (*__flush_cache_all)(void); +void (*flush_cache_mm)(struct mm_struct *mm); +void (*flush_cache_range)(struct vm_area_struct *vma, unsigned long start, + unsigned long end); +void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page); +void (*flush_icache_range)(unsigned long start, unsigned long end); +void (*flush_icache_page)(struct vm_area_struct *vma, struct page *page); /* MIPS specific cache operations */ -void (*_flush_cache_sigtramp)(unsigned long addr); -void (*_flush_cache_l2)(void); -void (*_flush_cache_l1)(void); +void (*flush_cache_sigtramp)(unsigned long addr); +void (*flush_data_cache_page)(unsigned long addr); +void (*flush_icache_all)(void); +#ifdef CONFIG_NONCOHERENT_IO /* DMA cache operations. */ void (*_dma_cache_wback_inv)(unsigned long start, unsigned long size); void (*_dma_cache_wback)(unsigned long start, unsigned long size); void (*_dma_cache_inv)(unsigned long start, unsigned long size); -/* TLB operations. */ -void (*_flush_tlb_all)(void); -void (*_flush_tlb_mm)(struct mm_struct *mm); -void (*_flush_tlb_range)(struct vm_area_struct *vma, unsigned long start, - unsigned long end); -void (*_flush_tlb_page)(struct vm_area_struct *vma, unsigned long page); - -/* Miscellaneous. */ -void (*update_mmu_cache)(struct vm_area_struct * vma, - unsigned long address, pte_t pte); +EXPORT_SYMBOL(_dma_cache_wback_inv); +EXPORT_SYMBOL(_dma_cache_wback); +EXPORT_SYMBOL(_dma_cache_inv); -void (*_show_regs)(struct pt_regs *); +#endif /* CONFIG_NONCOHERENT_IO */ +extern void ld_mmu_r23000(void); extern void ld_mmu_r4xx0(void); +extern void ld_mmu_tx39(void); +extern void ld_mmu_r6000(void); +extern void ld_mmu_tfp(void); extern void ld_mmu_andes(void); +extern void ld_mmu_sb1(void); +extern void sb1_tlb_init(void); +extern void r3k_tlb_init(void); +extern void r4k_tlb_init(void); +extern void sb1_tlb_init(void); void __init load_mmu(void) { - switch(mips_cputype) { -#if defined (CONFIG_CPU_R4300) \ - || defined (CONFIG_CPU_R4X00) \ - || defined (CONFIG_CPU_R5000) \ - || defined (CONFIG_CPU_NEVADA) - case CPU_R4000PC: - case CPU_R4000SC: - case CPU_R4000MC: - case CPU_R4200: - case CPU_R4300: - case CPU_R4400PC: - case CPU_R4400SC: - case CPU_R4400MC: - case CPU_R4600: - case CPU_R4640: - case CPU_R4650: - case CPU_R4700: - case CPU_R5000: - case CPU_R5000A: - case CPU_NEVADA: - printk("Loading R4000 MMU routines.\n"); + if (cpu_has_4ktlb) { +#if defined(CONFIG_CPU_R4X00) || defined(CONFIG_CPU_VR41XX) || \ + defined(CONFIG_CPU_R4300) || defined(CONFIG_CPU_R5000) || \ + defined(CONFIG_CPU_NEVADA) || defined(CONFIG_CPU_R5432) || \ + defined(CONFIG_CPU_R5500) || defined(CONFIG_CPU_MIPS32) || \ + defined(CONFIG_CPU_MIPS64) || defined(CONFIG_CPU_TX49XX) || \ + defined(CONFIG_CPU_RM7000) ld_mmu_r4xx0(); + r4k_tlb_init(); +#endif + } else switch (current_cpu_data.cputype) { +#ifdef CONFIG_CPU_R3000 + case CPU_R2000: + case CPU_R3000: + case CPU_R3000A: + case CPU_R3081E: + ld_mmu_r23000(); + r3k_tlb_init(); break; #endif - -#if defined (CONFIG_CPU_R10000) +#ifdef CONFIG_CPU_TX39XX + case CPU_TX3912: + case CPU_TX3922: + case CPU_TX3927: + ld_mmu_tx39(); + r3k_tlb_init(); + break; +#endif +#ifdef CONFIG_CPU_R10000 case CPU_R10000: - printk("Loading R10000 MMU routines.\n"); - ld_mmu_andes(); + case CPU_R12000: + ld_mmu_r4xx0(); + andes_tlb_init(); + break; +#endif +#ifdef CONFIG_CPU_SB1 + case CPU_SB1: + ld_mmu_sb1(); + sb1_tlb_init(); break; #endif + case CPU_R8000: + panic("R8000 is unsupported"); + break; + default: - /* XXX We need an generic routine in the MIPS port - * XXX to jabber stuff onto the screen on all machines - * XXX before the console is setup. The ARCS prom - * XXX routines look good for this, but only the SGI - * XXX code has a full library for that at this time. - */ - panic("Yeee, unsupported mmu/cache architecture or " - "wrong compiletime kernel configuration."); + panic("Yeee, unsupported mmu/cache architecture."); } } diff -Nru a/arch/mips64/mm/pg-r4k.c b/arch/mips64/mm/pg-r4k.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips64/mm/pg-r4k.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,708 @@ +/* + * 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) 1996 David S. Miller (dm@engr.sgi.com) + * Copyright (C) 1997, 98, 99, 2000, 01, 02, 03 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + * Copyright (C) 2000 Kanoj Sarcar (kanoj@sgi.com) + */ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Zero an entire page. Basically a simple unrolled loop should do the + * job but we want more performance by saving memory bus bandwidth. We + * have five flavours of the routine available for: + * + * - 16byte cachelines and no second level cache + * - 32byte cachelines second level cache + * - a version which handles the buggy R4600 v1.x + * - a version which handles the buggy R4600 v2.0 + * - Finally a last version without fancy cache games for the SC and MC + * versions of R4000 and R4400. + */ + +void r4k_clear_page_d16(void * page) +{ + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "daddiu\t$1,%0,%2\n" + "1:\tcache\t%3,(%0)\n\t" + "sd\t$0,(%0)\n\t" + "sd\t$0,8(%0)\n\t" + "cache\t%3,16(%0)\n\t" + "sd\t$0,16(%0)\n\t" + "sd\t$0,24(%0)\n\t" + "daddiu\t%0,64\n\t" + "cache\t%3,-32(%0)\n\t" + "sd\t$0,-32(%0)\n\t" + "sd\t$0,-24(%0)\n\t" + "cache\t%3,-16(%0)\n\t" + "sd\t$0,-16(%0)\n\t" + "bne\t$1,%0,1b\n\t" + "sd\t$0,-8(%0)\n\t" + ".set\tat\n\t" + ".set\treorder" + : "=r" (page) + : "0" (page), "I" (PAGE_SIZE), "i" (Create_Dirty_Excl_D) + : "memory"); +} + +void r4k_clear_page_d32(void * page) +{ + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "daddiu\t$1,%0,%2\n" + "1:\tcache\t%3,(%0)\n\t" + "sd\t$0,(%0)\n\t" + "sd\t$0,8(%0)\n\t" + "sd\t$0,16(%0)\n\t" + "sd\t$0,24(%0)\n\t" + "daddiu\t%0,64\n\t" + "cache\t%3,-32(%0)\n\t" + "sd\t$0,-32(%0)\n\t" + "sd\t$0,-24(%0)\n\t" + "sd\t$0,-16(%0)\n\t" + "bne\t$1,%0,1b\n\t" + "sd\t$0,-8(%0)\n\t" + ".set\tat\n\t" + ".set\treorder" + : "=r" (page) + : "0" (page), "I" (PAGE_SIZE), "i" (Create_Dirty_Excl_D) + : "memory"); +} + + +/* + * This flavour of r4k_clear_page is for the R4600 V1.x. Cite from the + * IDT R4600 V1.7 errata: + * + * 18. The CACHE instructions Hit_Writeback_Invalidate_D, Hit_Writeback_D, + * Hit_Invalidate_D and Create_Dirty_Excl_D should only be + * executed if there is no other dcache activity. If the dcache is + * accessed for another instruction immeidately preceding when these + * cache instructions are executing, it is possible that the dcache + * tag match outputs used by these cache instructions will be + * incorrect. These cache instructions should be preceded by at least + * four instructions that are not any kind of load or store + * instruction. + * + * This is not allowed: lw + * nop + * nop + * nop + * cache Hit_Writeback_Invalidate_D + * + * This is allowed: lw + * nop + * nop + * nop + * nop + * cache Hit_Writeback_Invalidate_D + */ +void r4k_clear_page_r4600_v1(void * page) +{ + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "daddiu\t$1,%0,%2\n" + "1:\tnop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "cache\t%3,(%0)\n\t" + "sd\t$0,(%0)\n\t" + "sd\t$0,8(%0)\n\t" + "sd\t$0,16(%0)\n\t" + "sd\t$0,24(%0)\n\t" + "daddiu\t%0,64\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "cache\t%3,-32(%0)\n\t" + "sd\t$0,-32(%0)\n\t" + "sd\t$0,-24(%0)\n\t" + "sd\t$0,-16(%0)\n\t" + "bne\t$1,%0,1b\n\t" + "sd\t$0,-8(%0)\n\t" + ".set\tat\n\t" + ".set\treorder" + : "=r" (page) + : "0" (page), "I" (PAGE_SIZE), "i" (Create_Dirty_Excl_D) + : "memory"); +} + +/* + * And this one is for the R4600 V2.0 + */ +void r4k_clear_page_r4600_v2(void * page) +{ + unsigned int flags; + + local_irq_save(flags); + *(volatile unsigned int *)KSEG1; + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "daddiu\t$1,%0,%2\n" + "1:\tcache\t%3,(%0)\n\t" + "sd\t$0,(%0)\n\t" + "sd\t$0,8(%0)\n\t" + "sd\t$0,16(%0)\n\t" + "sd\t$0,24(%0)\n\t" + "daddiu\t%0,64\n\t" + "cache\t%3,-32(%0)\n\t" + "sd\t$0,-32(%0)\n\t" + "sd\t$0,-24(%0)\n\t" + "sd\t$0,-16(%0)\n\t" + "bne\t$1,%0,1b\n\t" + "sd\t$0,-8(%0)\n\t" + ".set\tat\n\t" + ".set\treorder" + : "=r" (page) + : "0" (page), "I" (PAGE_SIZE), "i" (Create_Dirty_Excl_D) + : "memory"); + local_irq_restore(flags); +} + +/* + * The next 4 versions are optimized for all possible scache configurations + * of the SC / MC versions of R4000 and R4400 ... + * + * Todo: For even better performance we should have a routine optimized for + * every legal combination of dcache / scache linesize. When I (Ralf) tried + * this the kernel crashed shortly after mounting the root filesystem. CPU + * bug? Weirdo cache instruction semantics? + */ +void r4k_clear_page_s16(void * page) +{ + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "daddiu\t$1,%0,%2\n" + "1:\tcache\t%3,(%0)\n\t" + "sd\t$0,(%0)\n\t" + "sd\t$0,8(%0)\n\t" + "cache\t%3,16(%0)\n\t" + "sd\t$0,16(%0)\n\t" + "sd\t$0,24(%0)\n\t" + "daddiu\t%0,64\n\t" + "cache\t%3,-32(%0)\n\t" + "sd\t$0,-32(%0)\n\t" + "sd\t$0,-24(%0)\n\t" + "cache\t%3,-16(%0)\n\t" + "sd\t$0,-16(%0)\n\t" + "bne\t$1,%0,1b\n\t" + "sd\t$0,-8(%0)\n\t" + ".set\tat\n\t" + ".set\treorder" + : "=r" (page) + : "0" (page), "I" (PAGE_SIZE), "i" (Create_Dirty_Excl_SD) + : "memory"); +} + +void r4k_clear_page_s32(void * page) +{ + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "daddiu\t$1,%0,%2\n" + "1:\tcache\t%3,(%0)\n\t" + "sd\t$0,(%0)\n\t" + "sd\t$0,8(%0)\n\t" + "sd\t$0,16(%0)\n\t" + "sd\t$0,24(%0)\n\t" + "daddiu\t%0,64\n\t" + "cache\t%3,-32(%0)\n\t" + "sd\t$0,-32(%0)\n\t" + "sd\t$0,-24(%0)\n\t" + "sd\t$0,-16(%0)\n\t" + "bne\t$1,%0,1b\n\t" + "sd\t$0,-8(%0)\n\t" + ".set\tat\n\t" + ".set\treorder" + : "=r" (page) + : "0" (page), "I" (PAGE_SIZE), "i" (Create_Dirty_Excl_SD) + : "memory"); +} + +void r4k_clear_page_s64(void * page) +{ + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "daddiu\t$1,%0,%2\n" + "1:\tcache\t%3,(%0)\n\t" + "sd\t$0,(%0)\n\t" + "sd\t$0,8(%0)\n\t" + "sd\t$0,16(%0)\n\t" + "sd\t$0,24(%0)\n\t" + "daddiu\t%0,64\n\t" + "sd\t$0,-32(%0)\n\t" + "sd\t$0,-24(%0)\n\t" + "sd\t$0,-16(%0)\n\t" + "bne\t$1,%0,1b\n\t" + "sd\t$0,-8(%0)\n\t" + ".set\tat\n\t" + ".set\treorder" + : "=r" (page) + : "0" (page), "I" (PAGE_SIZE), "i" (Create_Dirty_Excl_SD) + : "memory"); +} + +void r4k_clear_page_s128(void * page) +{ + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "daddiu\t$1,%0,%2\n" + "1:\tcache\t%3,(%0)\n\t" + "sd\t$0,(%0)\n\t" + "sd\t$0,8(%0)\n\t" + "sd\t$0,16(%0)\n\t" + "sd\t$0,24(%0)\n\t" + "sd\t$0,32(%0)\n\t" + "sd\t$0,40(%0)\n\t" + "sd\t$0,48(%0)\n\t" + "sd\t$0,56(%0)\n\t" + "daddiu\t%0,128\n\t" + "sd\t$0,-64(%0)\n\t" + "sd\t$0,-56(%0)\n\t" + "sd\t$0,-48(%0)\n\t" + "sd\t$0,-40(%0)\n\t" + "sd\t$0,-32(%0)\n\t" + "sd\t$0,-24(%0)\n\t" + "sd\t$0,-16(%0)\n\t" + "bne\t$1,%0,1b\n\t" + "sd\t$0,-8(%0)\n\t" + ".set\tat\n\t" + ".set\treorder" + : "=r" (page) + : "0" (page), "I" (PAGE_SIZE), "i" (Create_Dirty_Excl_SD) + : "memory"); +} + +/* + * This version has been tuned on an Origin. For other machines the arguments + * of the pref instructin may have to be tuned differently. + */ +void andes_clear_page(void * page) +{ + __asm__ __volatile__( + ".set\tpush\n\t" + ".set\tmips4\n\t" + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "daddiu\t$1,%0,%2\n" + "1:\tpref 7,512(%0)\n\t" + "sd\t$0,(%0)\n\t" + "sd\t$0,8(%0)\n\t" + "sd\t$0,16(%0)\n\t" + "sd\t$0,24(%0)\n\t" + "daddiu\t%0,64\n\t" + "sd\t$0,-32(%0)\n\t" + "sd\t$0,-24(%0)\n\t" + "sd\t$0,-16(%0)\n\t" + "bne\t$1,%0,1b\n\t" + "sd\t$0,-8(%0)\n\t" + ".set\tpop" + : "=r" (page) + : "0" (page), "I" (PAGE_SIZE) + : "memory"); +} + + +/* + * This is still inefficient. We only can do better if we know the + * virtual address where the copy will be accessed. + */ + +void r4k_copy_page_d16(void * to, void * from) +{ + unsigned long dummy1, dummy2, reg1, reg2; + + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "daddiu\t$1,%0,%6\n" + "1:\tcache\t%7,(%0)\n\t" + "ld\t%2,(%1)\n\t" + "ld\t%3,8(%1)\n\t" + "sd\t%2,(%0)\n\t" + "sd\t%3,8(%0)\n\t" + "cache\t%7,16(%0)\n\t" + "ld\t%2,16(%1)\n\t" + "ld\t%3,24(%1)\n\t" + "sd\t%2,16(%0)\n\t" + "sd\t%3,24(%0)\n\t" + "cache\t%7,32(%0)\n\t" + "daddiu\t%0,64\n\t" + "daddiu\t%1,64\n\t" + "ld\t%2,-32(%1)\n\t" + "ld\t%3,-24(%1)\n\t" + "sd\t%2,-32(%0)\n\t" + "sd\t%3,-24(%0)\n\t" + "cache\t%7,-16(%0)\n\t" + "ld\t%2,-16(%1)\n\t" + "ld\t%3,-8(%1)\n\t" + "sd\t%2,-16(%0)\n\t" + "bne\t$1,%0,1b\n\t" + " sd\t%3,-8(%0)\n\t" + ".set\tat\n\t" + ".set\treorder" + :"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2) + :"0" (to), "1" (from), "I" (PAGE_SIZE), + "i" (Create_Dirty_Excl_D)); +} + +void r4k_copy_page_d32(void * to, void * from) +{ + unsigned long dummy1, dummy2, reg1, reg2; + + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "daddiu\t$1,%0,%6\n" + "1:\tcache\t%7,(%0)\n\t" + "ld\t%2,(%1)\n\t" + "ld\t%3,8(%1)\n\t" + "sd\t%2,(%0)\n\t" + "sd\t%3,8(%0)\n\t" + "ld\t%2,16(%1)\n\t" + "ld\t%3,24(%1)\n\t" + "sd\t%2,16(%0)\n\t" + "sd\t%3,24(%0)\n\t" + "cache\t%7,32(%0)\n\t" + "daddiu\t%0,64\n\t" + "daddiu\t%1,64\n\t" + "ld\t%2,-32(%1)\n\t" + "ld\t%3,-24(%1)\n\t" + "sd\t%2,-32(%0)\n\t" + "sd\t%3,-24(%0)\n\t" + "ld\t%2,-16(%1)\n\t" + "ld\t%3,-8(%1)\n\t" + "sd\t%2,-16(%0)\n\t" + "bne\t$1,%0,1b\n\t" + " sd\t%3,-8(%0)\n\t" + ".set\tat\n\t" + ".set\treorder" + :"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2) + :"0" (to), "1" (from), "I" (PAGE_SIZE), + "i" (Create_Dirty_Excl_D)); +} + +/* + * Again a special version for the R4600 V1.x + */ +void r4k_copy_page_r4600_v1(void * to, void * from) +{ + unsigned long dummy1, dummy2, reg1, reg2; + + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "daddiu\t$1,%0,%6\n" + "1:\tnop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "\tcache\t%7,(%0)\n\t" + "ld\t%2,(%1)\n\t" + "ld\t%3,8(%1)\n\t" + "sd\t%2,(%0)\n\t" + "sd\t%3,8(%0)\n\t" + "ld\t%2,16(%1)\n\t" + "ld\t%3,24(%1)\n\t" + "sd\t%2,16(%0)\n\t" + "sd\t%3,24(%0)\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "cache\t%7,32(%0)\n\t" + "daddiu\t%0,64\n\t" + "daddiu\t%1,64\n\t" + "ld\t%2,-32(%1)\n\t" + "ld\t%3,-24(%1)\n\t" + "sd\t%2,-32(%0)\n\t" + "sd\t%3,-24(%0)\n\t" + "ld\t%2,-16(%1)\n\t" + "ld\t%3,-8(%1)\n\t" + "sd\t%2,-16(%0)\n\t" + "bne\t$1,%0,1b\n\t" + " sd\t%3,-8(%0)\n\t" + ".set\tat\n\t" + ".set\treorder" + :"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2) + :"0" (to), "1" (from), "I" (PAGE_SIZE), + "i" (Create_Dirty_Excl_D)); +} + +void r4k_copy_page_r4600_v2(void * to, void * from) +{ + unsigned long dummy1, dummy2, reg1, reg2; + unsigned int flags; + + local_irq_save(flags); + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "daddiu\t$1,%0,%6\n" + "1:\tnop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "\tcache\t%7,(%0)\n\t" + "ld\t%2,(%1)\n\t" + "ld\t%3,8(%1)\n\t" + "sd\t%2,(%0)\n\t" + "sd\t%3,8(%0)\n\t" + "ld\t%2,16(%1)\n\t" + "ld\t%3,24(%1)\n\t" + "sd\t%2,16(%0)\n\t" + "sd\t%3,24(%0)\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "cache\t%7,32(%0)\n\t" + "daddiu\t%0,64\n\t" + "daddiu\t%1,64\n\t" + "ld\t%2,-32(%1)\n\t" + "ld\t%3,-24(%1)\n\t" + "sd\t%2,-32(%0)\n\t" + "sd\t%3,-24(%0)\n\t" + "ld\t%2,-16(%1)\n\t" + "ld\t%3,-8(%1)\n\t" + "sd\t%2,-16(%0)\n\t" + "bne\t$1,%0,1b\n\t" + " sd\t%3,-8(%0)\n\t" + ".set\tat\n\t" + ".set\treorder" + :"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2) + :"0" (to), "1" (from), "I" (PAGE_SIZE), + "i" (Create_Dirty_Excl_D)); + local_irq_restore(flags); +} + +/* + * These are for R4000SC / R4400MC + */ +void r4k_copy_page_s16(void * to, void * from) +{ + unsigned long dummy1, dummy2, reg1, reg2; + + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "daddiu\t$1,%0,%6\n" + "1:\tcache\t%7,(%0)\n\t" + "ld\t%2,(%1)\n\t" + "ld\t%3,8(%1)\n\t" + "sd\t%2,(%0)\n\t" + "sd\t%3,8(%0)\n\t" + "cache\t%7,16(%0)\n\t" + "ld\t%2,16(%1)\n\t" + "ld\t%3,24(%1)\n\t" + "sd\t%2,16(%0)\n\t" + "sd\t%3,24(%0)\n\t" + "cache\t%7,32(%0)\n\t" + "daddiu\t%0,64\n\t" + "daddiu\t%1,64\n\t" + "ld\t%2,-32(%1)\n\t" + "ld\t%3,-24(%1)\n\t" + "sd\t%2,-32(%0)\n\t" + "sd\t%3,-24(%0)\n\t" + "cache\t%7,-16(%0)\n\t" + "ld\t%2,-16(%1)\n\t" + "ld\t%3,-8(%1)\n\t" + "sd\t%2,-16(%0)\n\t" + "bne\t$1,%0,1b\n\t" + " sd\t%3,-8(%0)\n\t" + ".set\tat\n\t" + ".set\treorder" + :"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2) + :"0" (to), "1" (from), "I" (PAGE_SIZE), + "i" (Create_Dirty_Excl_SD)); +} + +void r4k_copy_page_s32(void * to, void * from) +{ + unsigned long dummy1, dummy2, reg1, reg2; + + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "daddiu\t$1,%0,%6\n" + "1:\tcache\t%7,(%0)\n\t" + "ld\t%2,(%1)\n\t" + "ld\t%3,8(%1)\n\t" + "sd\t%2,(%0)\n\t" + "sd\t%3,8(%0)\n\t" + "ld\t%2,16(%1)\n\t" + "ld\t%3,24(%1)\n\t" + "sd\t%2,16(%0)\n\t" + "sd\t%3,24(%0)\n\t" + "cache\t%7,32(%0)\n\t" + "daddiu\t%0,64\n\t" + "daddiu\t%1,64\n\t" + "ld\t%2,-32(%1)\n\t" + "ld\t%3,-24(%1)\n\t" + "sd\t%2,-32(%0)\n\t" + "sd\t%3,-24(%0)\n\t" + "ld\t%2,-16(%1)\n\t" + "ld\t%3,-8(%1)\n\t" + "sd\t%2,-16(%0)\n\t" + "bne\t$1,%0,1b\n\t" + " sd\t%3,-8(%0)\n\t" + ".set\tat\n\t" + ".set\treorder" + :"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2) + :"0" (to), "1" (from), "I" (PAGE_SIZE), + "i" (Create_Dirty_Excl_SD)); +} + +void r4k_copy_page_s64(void * to, void * from) +{ + unsigned long dummy1, dummy2, reg1, reg2; + + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "daddiu\t$1,%0,%6\n" + "1:\tcache\t%7,(%0)\n\t" + "ld\t%2,(%1)\n\t" + "ld\t%3,8(%1)\n\t" + "sd\t%2,(%0)\n\t" + "sd\t%3,8(%0)\n\t" + "ld\t%2,16(%1)\n\t" + "ld\t%3,24(%1)\n\t" + "sd\t%2,16(%0)\n\t" + "sd\t%3,24(%0)\n\t" + "daddiu\t%0,64\n\t" + "daddiu\t%1,64\n\t" + "ld\t%2,-32(%1)\n\t" + "ld\t%3,-24(%1)\n\t" + "sd\t%2,-32(%0)\n\t" + "sd\t%3,-24(%0)\n\t" + "ld\t%2,-16(%1)\n\t" + "ld\t%3,-8(%1)\n\t" + "sd\t%2,-16(%0)\n\t" + "bne\t$1,%0,1b\n\t" + " sd\t%3,-8(%0)\n\t" + ".set\tat\n\t" + ".set\treorder" + :"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2) + :"0" (to), "1" (from), "I" (PAGE_SIZE), + "i" (Create_Dirty_Excl_SD)); +} + +void r4k_copy_page_s128(void * to, void * from) +{ + unsigned long dummy1, dummy2; + unsigned long reg1, reg2, reg3, reg4; + + __asm__ __volatile__( + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "daddiu\t$1,%0,%8\n" + "1:\tcache\t%9,(%0)\n\t" + "ld\t%2,(%1)\n\t" + "ld\t%3,8(%1)\n\t" + "ld\t%4,16(%1)\n\t" + "ld\t%5,24(%1)\n\t" + "sd\t%2,(%0)\n\t" + "sd\t%3,8(%0)\n\t" + "sd\t%4,16(%0)\n\t" + "sd\t%5,24(%0)\n\t" + "ld\t%2,32(%1)\n\t" + "ld\t%3,40(%1)\n\t" + "ld\t%4,48(%1)\n\t" + "ld\t%5,56(%1)\n\t" + "sd\t%2,32(%0)\n\t" + "sd\t%3,40(%0)\n\t" + "sd\t%4,48(%0)\n\t" + "sd\t%5,56(%0)\n\t" + "daddiu\t%0,128\n\t" + "daddiu\t%1,128\n\t" + "ld\t%2,-64(%1)\n\t" + "ld\t%3,-56(%1)\n\t" + "ld\t%4,-48(%1)\n\t" + "ld\t%5,-40(%1)\n\t" + "sd\t%2,-64(%0)\n\t" + "sd\t%3,-56(%0)\n\t" + "sd\t%4,-48(%0)\n\t" + "sd\t%5,-40(%0)\n\t" + "ld\t%2,-32(%1)\n\t" + "ld\t%3,-24(%1)\n\t" + "ld\t%4,-16(%1)\n\t" + "ld\t%5,-8(%1)\n\t" + "sd\t%2,-32(%0)\n\t" + "sd\t%3,-24(%0)\n\t" + "sd\t%4,-16(%0)\n\t" + "bne\t$1,%0,1b\n\t" + " sd\t%5,-8(%0)\n\t" + ".set\tat\n\t" + ".set\treorder" + :"=r" (dummy1), "=r" (dummy2), + "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4) + :"0" (to), "1" (from), + "I" (PAGE_SIZE), + "i" (Create_Dirty_Excl_SD)); +} + +/* + * This version has been tuned on an Origin. For other machines the arguments + * of the pref instructin may have to be tuned differently. + */ +void andes_copy_page(void * to, void * from) +{ + unsigned long dummy1, dummy2, reg1, reg2, reg3, reg4; + + __asm__ __volatile__( + ".set\tpush\n\t" + ".set\tmips4\n\t" + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "daddiu\t$1,%0,%8\n" + "1:\tpref\t0,2*128(%1)\n\t" + "pref\t1,2*128(%0)\n\t" + "ld\t%2,(%1)\n\t" + "ld\t%3,8(%1)\n\t" + "ld\t%4,16(%1)\n\t" + "ld\t%5,24(%1)\n\t" + "sd\t%2,(%0)\n\t" + "sd\t%3,8(%0)\n\t" + "sd\t%4,16(%0)\n\t" + "sd\t%5,24(%0)\n\t" + "daddiu\t%0,64\n\t" + "daddiu\t%1,64\n\t" + "ld\t%2,-32(%1)\n\t" + "ld\t%3,-24(%1)\n\t" + "ld\t%4,-16(%1)\n\t" + "ld\t%5,-8(%1)\n\t" + "sd\t%2,-32(%0)\n\t" + "sd\t%3,-24(%0)\n\t" + "sd\t%4,-16(%0)\n\t" + "bne\t$1,%0,1b\n\t" + " sd\t%5,-8(%0)\n\t" + ".set\tpop\n\t" + :"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2), + "=&r" (reg3), "=&r" (reg4) + :"0" (to), "1" (from), "I" (PAGE_SIZE)); +} diff -Nru a/arch/mips64/mm/pg-sb1.c b/arch/mips64/mm/pg-sb1.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips64/mm/pg-sb1.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,131 @@ +/* + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * Copyright (C) 1997, 2001 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 2000 Sibyte + * + * Written by Justin Carlson (carlson@sibyte.com) + * + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#include +#include + +#ifdef CONFIG_SB1_PASS_1_WORKAROUNDS +#define SB1_PREF_LOAD_STREAMED_HINT "0" +#define SB1_PREF_STORE_STREAMED_HINT "1" +#else +#define SB1_PREF_LOAD_STREAMED_HINT "4" +#define SB1_PREF_STORE_STREAMED_HINT "5" +#endif + +/* These are the functions hooked by the memory management function pointers */ +void sb1_clear_page(void *page) +{ + /* + * JDCXXX - This should be bottlenecked by the write buffer, but these + * things tend to be mildly unpredictable...should check this on the + * performance model + * + * We prefetch 4 lines ahead. We're also "cheating" slightly here... + * since we know we're on an SB1, we force the assembler to take + * 64-bit operands to speed things up + */ + __asm__ __volatile__( + ".set push \n" + ".set noreorder \n" + ".set noat \n" + ".set mips4 \n" + " daddiu $1, %0, %2 \n" /* Calculate the end of the page to clear */ +#ifdef CONFIG_CPU_HAS_PREFETCH + " pref " SB1_PREF_STORE_STREAMED_HINT ", 0(%0) \n" /* Prefetch the first 4 lines */ + " pref " SB1_PREF_STORE_STREAMED_HINT ", 32(%0) \n" + " pref " SB1_PREF_STORE_STREAMED_HINT ", 64(%0) \n" + " pref " SB1_PREF_STORE_STREAMED_HINT ", 96(%0) \n" +#endif + "1: sd $0, 0(%0) \n" /* Throw out a cacheline of 0's */ + " sd $0, 8(%0) \n" + " sd $0, 16(%0) \n" + " sd $0, 24(%0) \n" +#ifdef CONFIG_CPU_HAS_PREFETCH + " pref " SB1_PREF_STORE_STREAMED_HINT ",128(%0) \n" /* Prefetch 4 lines ahead */ +#endif + " bne $1, %0, 1b \n" + " daddiu %0, %0, 32\n" /* Next cacheline (This instruction better be short piped!) */ + ".set pop \n" + : "=r" (page) + : "0" (page), "I" (PAGE_SIZE-32) + : "memory"); + +} + +void sb1_copy_page(void *to, void *from) +{ + /* + * This should be optimized in assembly...can't use ld/sd, though, + * because the top 32 bits could be nuked if we took an interrupt + * during the routine. And this is not a good place to be cli()'ing + * + * The pref's used here are using "streaming" hints, which cause the + * copied data to be kicked out of the cache sooner. A page copy often + * ends up copying a lot more data than is commonly used, so this seems + * to make sense in terms of reducing cache pollution, but I've no real + * performance data to back this up + */ + + __asm__ __volatile__( + ".set push \n" + ".set noreorder \n" + ".set noat \n" + ".set mips4 \n" + " daddiu $1, %0, %4 \n" /* Calculate the end of the page to copy */ +#ifdef CONFIG_CPU_HAS_PREFETCH + " pref " SB1_PREF_LOAD_STREAMED_HINT ", 0(%0) \n" /* Prefetch the first 3 lines */ + " pref " SB1_PREF_STORE_STREAMED_HINT ", 0(%1) \n" + " pref " SB1_PREF_LOAD_STREAMED_HINT ", 32(%0) \n" + " pref " SB1_PREF_STORE_STREAMED_HINT ", 32(%1) \n" + " pref " SB1_PREF_LOAD_STREAMED_HINT ", 64(%0) \n" + " pref " SB1_PREF_STORE_STREAMED_HINT ", 64(%1) \n" +#endif + "1: lw $2, 0(%0) \n" /* Block copy a cacheline */ + " lw $3, 4(%0) \n" + " lw $4, 8(%0) \n" + " lw $5, 12(%0) \n" + " lw $6, 16(%0) \n" + " lw $7, 20(%0) \n" + " lw $8, 24(%0) \n" + " lw $9, 28(%0) \n" +#ifdef CONFIG_CPU_HAS_PREFETCH + " pref " SB1_PREF_LOAD_STREAMED_HINT ", 96(%0) \n" /* Prefetch ahead */ + " pref " SB1_PREF_STORE_STREAMED_HINT ", 96(%1) \n" +#endif + " sw $2, 0(%1) \n" + " sw $3, 4(%1) \n" + " sw $4, 8(%1) \n" + " sw $5, 12(%1) \n" + " sw $6, 16(%1) \n" + " sw $7, 20(%1) \n" + " sw $8, 24(%1) \n" + " sw $9, 28(%1) \n" + " daddiu %1, %1, 32 \n" /* Next cacheline */ + " nop \n" /* Force next add to short pipe */ + " nop \n" /* Force next add to short pipe */ + " bne $1, %0, 1b \n" + " daddiu %0, %0, 32 \n" /* Next cacheline */ + ".set pop \n" + : "=r" (to), "=r" (from) + : "0" (from), "1" (to), "I" (PAGE_SIZE-32) + : "$2","$3","$4","$5","$6","$7","$8","$9","memory"); +} diff -Nru a/arch/mips64/mm/pgtable.c b/arch/mips64/mm/pgtable.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips64/mm/pgtable.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,33 @@ +#include +#include +#include + +void show_mem(void) +{ + int pfn, total = 0, reserved = 0; + int shared = 0, cached = 0; + int highmem = 0; + struct page *page; + + printk("Mem-info:\n"); + show_free_areas(); + printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10)); + pfn = max_mapnr; + while (pfn-- > 0) { + page = pfn_to_page(pfn); + total++; + if (PageHighMem(page)) + highmem++; + if (PageReserved(page)) + reserved++; + else if (PageSwapCache(page)) + cached++; + else if (page_count(page)) + shared += page_count(page) - 1; + } + printk("%d pages of RAM\n", total); + printk("%d pages of HIGHMEM\n",highmem); + printk("%d reserved pages\n",reserved); + printk("%d pages shared\n",shared); + printk("%d pages swap cached\n",cached); +} diff -Nru a/arch/mips64/mm/r4xx0.c b/arch/mips64/mm/r4xx0.c --- a/arch/mips64/mm/r4xx0.c Tue Jul 1 18:44:31 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,2414 +0,0 @@ -/* - * 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. - * - * r4xx0.c: R4000 processor variant specific MMU/Cache routines. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * Copyright (C) 1997, 1998, 1999, 2000, 2001 Ralf Baechle (ralf@gnu.org) - * Copyright (C) 1999, 2000 Silicon Graphics, Inc. - */ -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -/* CP0 hazard avoidance. */ -#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \ - "nop; nop; nop; nop; nop; nop;\n\t" \ - ".set reorder\n\t") - -/* Primary cache parameters. */ -static int icache_size, dcache_size; /* Size in bytes */ -static int ic_lsize, dc_lsize; /* LineSize in bytes */ - -/* Secondary cache (if present) parameters. */ -static unsigned int scache_size, sc_lsize; /* Again, in bytes */ - -#include -#include - -#undef DEBUG_CACHE - -/* - * Dummy cache handling routines for machines without boardcaches - */ -static void no_sc_noop(void) {} - -static struct bcache_ops no_sc_ops = { - (void *)no_sc_noop, (void *)no_sc_noop, - (void *)no_sc_noop, (void *)no_sc_noop -}; - -struct bcache_ops *bcops = &no_sc_ops; - -/* - * On processors with QED R4600 style two set assosicative cache - * this is the bit which selects the way in the cache for the - * indexed cachops. - */ -#define icache_waybit (icache_size >> 1) -#define dcache_waybit (dcache_size >> 1) - -/* - * Zero an entire page. Basically a simple unrolled loop should do the - * job but we want more performance by saving memory bus bandwidth. We - * have five flavours of the routine available for: - * - * - 16byte cachelines and no second level cache - * - 32byte cachelines second level cache - * - a version which handles the buggy R4600 v1.x - * - a version which handles the buggy R4600 v2.0 - * - Finally a last version without fancy cache games for the SC and MC - * versions of R4000 and R4400. - */ - -static void r4k_clear_page_d16(void * page) -{ - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%2\n" - "1:\tcache\t%3,(%0)\n\t" - "sd\t$0,(%0)\n\t" - "sd\t$0,8(%0)\n\t" - "cache\t%3,16(%0)\n\t" - "sd\t$0,16(%0)\n\t" - "sd\t$0,24(%0)\n\t" - "daddiu\t%0,64\n\t" - "cache\t%3,-32(%0)\n\t" - "sd\t$0,-32(%0)\n\t" - "sd\t$0,-24(%0)\n\t" - "cache\t%3,-16(%0)\n\t" - "sd\t$0,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sd\t$0,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (page) - :"0" (page), "I" (PAGE_SIZE), "i" (Create_Dirty_Excl_D) - :"$1", "memory"); -} - -static void r4k_clear_page_d32(void * page) -{ - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%2\n" - "1:\tcache\t%3,(%0)\n\t" - "sd\t$0,(%0)\n\t" - "sd\t$0,8(%0)\n\t" - "sd\t$0,16(%0)\n\t" - "sd\t$0,24(%0)\n\t" - "daddiu\t%0,64\n\t" - "cache\t%3,-32(%0)\n\t" - "sd\t$0,-32(%0)\n\t" - "sd\t$0,-24(%0)\n\t" - "sd\t$0,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sd\t$0,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (page) - :"0" (page), "I" (PAGE_SIZE), "i" (Create_Dirty_Excl_D) - :"$1", "memory"); -} - - -/* - * This flavour of r4k_clear_page is for the R4600 V1.x. Cite from the - * IDT R4600 V1.7 errata: - * - * 18. The CACHE instructions Hit_Writeback_Invalidate_D, Hit_Writeback_D, - * Hit_Invalidate_D and Create_Dirty_Excl_D should only be - * executed if there is no other dcache activity. If the dcache is - * accessed for another instruction immeidately preceding when these - * cache instructions are executing, it is possible that the dcache - * tag match outputs used by these cache instructions will be - * incorrect. These cache instructions should be preceded by at least - * four instructions that are not any kind of load or store - * instruction. - * - * This is not allowed: lw - * nop - * nop - * nop - * cache Hit_Writeback_Invalidate_D - * - * This is allowed: lw - * nop - * nop - * nop - * nop - * cache Hit_Writeback_Invalidate_D - */ -static void r4k_clear_page_r4600_v1(void * page) -{ - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%2\n" - "1:\tnop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "cache\t%3,(%0)\n\t" - "sd\t$0,(%0)\n\t" - "sd\t$0,8(%0)\n\t" - "sd\t$0,16(%0)\n\t" - "sd\t$0,24(%0)\n\t" - "daddiu\t%0,64\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "cache\t%3,-32(%0)\n\t" - "sd\t$0,-32(%0)\n\t" - "sd\t$0,-24(%0)\n\t" - "sd\t$0,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sd\t$0,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (page) - :"0" (page), - "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_D) - :"$1", "memory"); -} - -/* - * And this one is for the R4600 V2.0 - */ -static void r4k_clear_page_r4600_v2(void * page) -{ - unsigned int flags; - - local_irq_save(flags); - *(volatile unsigned int *)KSEG1; - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%2\n" - "1:\tcache\t%3,(%0)\n\t" - "sd\t$0,(%0)\n\t" - "sd\t$0,8(%0)\n\t" - "sd\t$0,16(%0)\n\t" - "sd\t$0,24(%0)\n\t" - "daddiu\t%0,64\n\t" - "cache\t%3,-32(%0)\n\t" - "sd\t$0,-32(%0)\n\t" - "sd\t$0,-24(%0)\n\t" - "sd\t$0,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sd\t$0,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (page) - :"0" (page), "I" (PAGE_SIZE), "i" (Create_Dirty_Excl_D) - :"$1", "memory"); - local_irq_restore(flags); -} - -/* - * The next 4 versions are optimized for all possible scache configurations - * of the SC / MC versions of R4000 and R4400 ... - * - * Todo: For even better performance we should have a routine optimized for - * every legal combination of dcache / scache linesize. When I (Ralf) tried - * this the kernel crashed shortly after mounting the root filesystem. CPU - * bug? Weirdo cache instruction semantics? - */ -static void r4k_clear_page_s16(void * page) -{ - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%2\n" - "1:\tcache\t%3,(%0)\n\t" - "sd\t$0,(%0)\n\t" - "sd\t$0,8(%0)\n\t" - "cache\t%3,16(%0)\n\t" - "sd\t$0,16(%0)\n\t" - "sd\t$0,24(%0)\n\t" - "daddiu\t%0,64\n\t" - "cache\t%3,-32(%0)\n\t" - "sd\t$0,-32(%0)\n\t" - "sd\t$0,-24(%0)\n\t" - "cache\t%3,-16(%0)\n\t" - "sd\t$0,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sd\t$0,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (page) - :"0" (page), "I" (PAGE_SIZE), "i" (Create_Dirty_Excl_SD) - :"$1","memory"); -} - -static void r4k_clear_page_s32(void * page) -{ - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%2\n" - "1:\tcache\t%3,(%0)\n\t" - "sd\t$0,(%0)\n\t" - "sd\t$0,8(%0)\n\t" - "sd\t$0,16(%0)\n\t" - "sd\t$0,24(%0)\n\t" - "daddiu\t%0,64\n\t" - "cache\t%3,-32(%0)\n\t" - "sd\t$0,-32(%0)\n\t" - "sd\t$0,-24(%0)\n\t" - "sd\t$0,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sd\t$0,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (page) - :"0" (page), "I" (PAGE_SIZE), "i" (Create_Dirty_Excl_SD) - :"$1","memory"); -} - -static void r4k_clear_page_s64(void * page) -{ - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%2\n" - "1:\tcache\t%3,(%0)\n\t" - "sd\t$0,(%0)\n\t" - "sd\t$0,8(%0)\n\t" - "sd\t$0,16(%0)\n\t" - "sd\t$0,24(%0)\n\t" - "daddiu\t%0,64\n\t" - "sd\t$0,-32(%0)\n\t" - "sd\t$0,-24(%0)\n\t" - "sd\t$0,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sd\t$0,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (page) - :"0" (page), - "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_SD) - :"$1","memory"); -} - -static void r4k_clear_page_s128(void * page) -{ - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%2\n" - "1:\tcache\t%3,(%0)\n\t" - "sd\t$0,(%0)\n\t" - "sd\t$0,8(%0)\n\t" - "sd\t$0,16(%0)\n\t" - "sd\t$0,24(%0)\n\t" - "sd\t$0,32(%0)\n\t" - "sd\t$0,40(%0)\n\t" - "sd\t$0,48(%0)\n\t" - "sd\t$0,56(%0)\n\t" - "daddiu\t%0,128\n\t" - "sd\t$0,-64(%0)\n\t" - "sd\t$0,-56(%0)\n\t" - "sd\t$0,-48(%0)\n\t" - "sd\t$0,-40(%0)\n\t" - "sd\t$0,-32(%0)\n\t" - "sd\t$0,-24(%0)\n\t" - "sd\t$0,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - "sd\t$0,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (page) - :"0" (page), - "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_SD) - :"$1", "memory"); -} - - -/* - * This is still inefficient. We only can do better if we know the - * virtual address where the copy will be accessed. - */ - -static void r4k_copy_page_d16(void * to, void * from) -{ - unsigned long dummy1, dummy2, reg1, reg2; - - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%6\n" - "1:\tcache\t%7,(%0)\n\t" - "ld\t%2,(%1)\n\t" - "ld\t%3,8(%1)\n\t" - "sd\t%2,(%0)\n\t" - "sd\t%3,8(%0)\n\t" - "cache\t%7,16(%0)\n\t" - "ld\t%2,16(%1)\n\t" - "ld\t%3,24(%1)\n\t" - "sd\t%2,16(%0)\n\t" - "sd\t%3,24(%0)\n\t" - "cache\t%7,32(%0)\n\t" - "daddiu\t%0,64\n\t" - "daddiu\t%1,64\n\t" - "ld\t%2,-32(%1)\n\t" - "ld\t%3,-24(%1)\n\t" - "sd\t%2,-32(%0)\n\t" - "sd\t%3,-24(%0)\n\t" - "cache\t%7,-16(%0)\n\t" - "ld\t%2,-16(%1)\n\t" - "ld\t%3,-8(%1)\n\t" - "sd\t%2,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - " sd\t%3,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2) - :"0" (to), "1" (from), "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_D)); -} - -static void r4k_copy_page_d32(void * to, void * from) -{ - unsigned long dummy1, dummy2, reg1, reg2; - - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%6\n" - "1:\tcache\t%7,(%0)\n\t" - "ld\t%2,(%1)\n\t" - "ld\t%3,8(%1)\n\t" - "sd\t%2,(%0)\n\t" - "sd\t%3,8(%0)\n\t" - "ld\t%2,16(%1)\n\t" - "ld\t%3,24(%1)\n\t" - "sd\t%2,16(%0)\n\t" - "sd\t%3,24(%0)\n\t" - "cache\t%7,32(%0)\n\t" - "daddiu\t%0,64\n\t" - "daddiu\t%1,64\n\t" - "ld\t%2,-32(%1)\n\t" - "ld\t%3,-24(%1)\n\t" - "sd\t%2,-32(%0)\n\t" - "sd\t%3,-24(%0)\n\t" - "ld\t%2,-16(%1)\n\t" - "ld\t%3,-8(%1)\n\t" - "sd\t%2,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - " sd\t%3,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2) - :"0" (to), "1" (from), "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_D)); -} - -/* - * Again a special version for the R4600 V1.x - */ -static void r4k_copy_page_r4600_v1(void * to, void * from) -{ - unsigned long dummy1, dummy2, reg1, reg2; - - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%6\n" - "1:\tnop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "\tcache\t%7,(%0)\n\t" - "ld\t%2,(%1)\n\t" - "ld\t%3,8(%1)\n\t" - "sd\t%2,(%0)\n\t" - "sd\t%3,8(%0)\n\t" - "ld\t%2,16(%1)\n\t" - "ld\t%3,24(%1)\n\t" - "sd\t%2,16(%0)\n\t" - "sd\t%3,24(%0)\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "cache\t%7,32(%0)\n\t" - "daddiu\t%0,64\n\t" - "daddiu\t%1,64\n\t" - "ld\t%2,-32(%1)\n\t" - "ld\t%3,-24(%1)\n\t" - "sd\t%2,-32(%0)\n\t" - "sd\t%3,-24(%0)\n\t" - "ld\t%2,-16(%1)\n\t" - "ld\t%3,-8(%1)\n\t" - "sd\t%2,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - " sd\t%3,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2) - :"0" (to), "1" (from), "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_D)); -} - -static void r4k_copy_page_r4600_v2(void * to, void * from) -{ - unsigned long dummy1, dummy2, reg1, reg2; - unsigned int flags; - - local_irq_save(flags); - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%6\n" - "1:\tnop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "\tcache\t%7,(%0)\n\t" - "ld\t%2,(%1)\n\t" - "ld\t%3,8(%1)\n\t" - "sd\t%2,(%0)\n\t" - "sd\t%3,8(%0)\n\t" - "ld\t%2,16(%1)\n\t" - "ld\t%3,24(%1)\n\t" - "sd\t%2,16(%0)\n\t" - "sd\t%3,24(%0)\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "cache\t%7,32(%0)\n\t" - "daddiu\t%0,64\n\t" - "daddiu\t%1,64\n\t" - "ld\t%2,-32(%1)\n\t" - "ld\t%3,-24(%1)\n\t" - "sd\t%2,-32(%0)\n\t" - "sd\t%3,-24(%0)\n\t" - "ld\t%2,-16(%1)\n\t" - "ld\t%3,-8(%1)\n\t" - "sd\t%2,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - " sd\t%3,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2) - :"0" (to), "1" (from), "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_D)); - local_irq_restore(flags); -} - -/* - * These are for R4000SC / R4400MC - */ -static void r4k_copy_page_s16(void * to, void * from) -{ - unsigned long dummy1, dummy2, reg1, reg2; - - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%6\n" - "1:\tcache\t%7,(%0)\n\t" - "ld\t%2,(%1)\n\t" - "ld\t%3,8(%1)\n\t" - "sd\t%2,(%0)\n\t" - "sd\t%3,8(%0)\n\t" - "cache\t%7,16(%0)\n\t" - "ld\t%2,16(%1)\n\t" - "ld\t%3,24(%1)\n\t" - "sd\t%2,16(%0)\n\t" - "sd\t%3,24(%0)\n\t" - "cache\t%7,32(%0)\n\t" - "daddiu\t%0,64\n\t" - "daddiu\t%1,64\n\t" - "ld\t%2,-32(%1)\n\t" - "ld\t%3,-24(%1)\n\t" - "sd\t%2,-32(%0)\n\t" - "sd\t%3,-24(%0)\n\t" - "cache\t%7,-16(%0)\n\t" - "ld\t%2,-16(%1)\n\t" - "ld\t%3,-8(%1)\n\t" - "sd\t%2,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - " sd\t%3,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2) - :"0" (to), "1" (from), "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_SD)); -} - -static void r4k_copy_page_s32(void * to, void * from) -{ - unsigned long dummy1, dummy2, reg1, reg2; - - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%6\n" - "1:\tcache\t%7,(%0)\n\t" - "ld\t%2,(%1)\n\t" - "ld\t%3,8(%1)\n\t" - "sd\t%2,(%0)\n\t" - "sd\t%3,8(%0)\n\t" - "ld\t%2,16(%1)\n\t" - "ld\t%3,24(%1)\n\t" - "sd\t%2,16(%0)\n\t" - "sd\t%3,24(%0)\n\t" - "cache\t%7,32(%0)\n\t" - "daddiu\t%0,64\n\t" - "daddiu\t%1,64\n\t" - "ld\t%2,-32(%1)\n\t" - "ld\t%3,-24(%1)\n\t" - "sd\t%2,-32(%0)\n\t" - "sd\t%3,-24(%0)\n\t" - "ld\t%2,-16(%1)\n\t" - "ld\t%3,-8(%1)\n\t" - "sd\t%2,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - " sd\t%3,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2) - :"0" (to), "1" (from), "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_SD)); -} - -static void r4k_copy_page_s64(void * to, void * from) -{ - unsigned long dummy1, dummy2, reg1, reg2; - - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%6\n" - "1:\tcache\t%7,(%0)\n\t" - "ld\t%2,(%1)\n\t" - "ld\t%3,8(%1)\n\t" - "sd\t%2,(%0)\n\t" - "sd\t%3,8(%0)\n\t" - "ld\t%2,16(%1)\n\t" - "ld\t%3,24(%1)\n\t" - "sd\t%2,16(%0)\n\t" - "sd\t%3,24(%0)\n\t" - "daddiu\t%0,64\n\t" - "daddiu\t%1,64\n\t" - "ld\t%2,-32(%1)\n\t" - "ld\t%3,-24(%1)\n\t" - "sd\t%2,-32(%0)\n\t" - "sd\t%3,-24(%0)\n\t" - "ld\t%2,-16(%1)\n\t" - "ld\t%3,-8(%1)\n\t" - "sd\t%2,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - " sd\t%3,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (dummy1), "=r" (dummy2), "=&r" (reg1), "=&r" (reg2) - :"0" (to), "1" (from), "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_SD)); -} - -static void r4k_copy_page_s128(void * to, void * from) -{ - unsigned long dummy1, dummy2; - unsigned long reg1, reg2, reg3, reg4; - - __asm__ __volatile__( - ".set\tnoreorder\n\t" - ".set\tnoat\n\t" - "daddiu\t$1,%0,%8\n" - "1:\tcache\t%9,(%0)\n\t" - "ld\t%2,(%1)\n\t" - "ld\t%3,8(%1)\n\t" - "ld\t%4,16(%1)\n\t" - "ld\t%5,24(%1)\n\t" - "sd\t%2,(%0)\n\t" - "sd\t%3,8(%0)\n\t" - "sd\t%4,16(%0)\n\t" - "sd\t%5,24(%0)\n\t" - "ld\t%2,32(%1)\n\t" - "ld\t%3,40(%1)\n\t" - "ld\t%4,48(%1)\n\t" - "ld\t%5,56(%1)\n\t" - "sd\t%2,32(%0)\n\t" - "sd\t%3,40(%0)\n\t" - "sd\t%4,48(%0)\n\t" - "sd\t%5,56(%0)\n\t" - "daddiu\t%0,128\n\t" - "daddiu\t%1,128\n\t" - "ld\t%2,-64(%1)\n\t" - "ld\t%3,-56(%1)\n\t" - "ld\t%4,-48(%1)\n\t" - "ld\t%5,-40(%1)\n\t" - "sd\t%2,-64(%0)\n\t" - "sd\t%3,-56(%0)\n\t" - "sd\t%4,-48(%0)\n\t" - "sd\t%5,-40(%0)\n\t" - "ld\t%2,-32(%1)\n\t" - "ld\t%3,-24(%1)\n\t" - "ld\t%4,-16(%1)\n\t" - "ld\t%5,-8(%1)\n\t" - "sd\t%2,-32(%0)\n\t" - "sd\t%3,-24(%0)\n\t" - "sd\t%4,-16(%0)\n\t" - "bne\t$1,%0,1b\n\t" - " sd\t%5,-8(%0)\n\t" - ".set\tat\n\t" - ".set\treorder" - :"=r" (dummy1), "=r" (dummy2), - "=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4) - :"0" (to), "1" (from), - "I" (PAGE_SIZE), - "i" (Create_Dirty_Excl_SD)); -} - - -/* - * If you think for one second that this stuff coming up is a lot - * of bulky code eating too many kernel cache lines. Think _again_. - * - * Consider: - * 1) Taken branches have a 3 cycle penalty on R4k - * 2) The branch itself is a real dead cycle on even R4600/R5000. - * 3) Only one of the following variants of each type is even used by - * the kernel based upon the cache parameters we detect at boot time. - * - * QED. - */ - -static inline void r4k_flush_cache_all_s16d16i16(void) -{ - unsigned long flags; - - local_irq_save(flags); - blast_dcache16(); blast_icache16(); blast_scache16(); - local_irq_restore(flags); -} - -static inline void r4k_flush_cache_all_s32d16i16(void) -{ - unsigned long flags; - - local_irq_save(flags); - blast_dcache16(); blast_icache16(); blast_scache32(); - local_irq_restore(flags); -} - -static inline void r4k_flush_cache_all_s64d16i16(void) -{ - unsigned long flags; - - local_irq_save(flags); - blast_dcache16(); blast_icache16(); blast_scache64(); - local_irq_restore(flags); -} - -static inline void r4k_flush_cache_all_s128d16i16(void) -{ - unsigned long flags; - - local_irq_save(flags); - blast_dcache16(); blast_icache16(); blast_scache128(); - local_irq_restore(flags); -} - -static inline void r4k_flush_cache_all_s32d32i32(void) -{ - unsigned long flags; - - local_irq_save(flags); - blast_dcache32(); blast_icache32(); blast_scache32(); - local_irq_restore(flags); -} - -static inline void r4k_flush_cache_all_s64d32i32(void) -{ - unsigned long flags; - - local_irq_save(flags); - blast_dcache32(); blast_icache32(); blast_scache64(); - local_irq_restore(flags); -} - -static inline void r4k_flush_cache_all_s128d32i32(void) -{ - unsigned long flags; - - local_irq_save(flags); - blast_dcache32(); blast_icache32(); blast_scache128(); - local_irq_restore(flags); -} - -static inline void r4k_flush_cache_all_d16i16(void) -{ - unsigned long flags; - - local_irq_save(flags); - blast_dcache16(); blast_icache16(); - local_irq_restore(flags); -} - -static inline void r4k_flush_cache_all_d32i32(void) -{ - unsigned long flags; - - local_irq_save(flags); - blast_dcache32(); blast_icache32(); - local_irq_restore(flags); -} - -static void r4k_flush_cache_range_s16d16i16(struct vm_area_struct *vma, - unsigned long start, - unsigned long end) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long flags; - - if (CPU_CONTEXT(smp_processor_id(), mm) == 0) - return; - - start &= PAGE_MASK; -#ifdef DEBUG_CACHE - printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); -#endif - if (vma) { - if (CPU_CONTEXT(smp_processor_id(), mm) != - CPU_CONTEXT(smp_processor_id(), current->mm)) { - r4k_flush_cache_all_s16d16i16(); - } else { - pgd_t *pgd; - pmd_t *pmd; - pte_t *pte; - - local_irq_save(flags); - while(start < end) { - pgd = pgd_offset(mm, start); - pmd = pmd_offset(pgd, start); - pte = pte_offset(pmd, start); - - if(pte_val(*pte) & _PAGE_VALID) - blast_scache16_page(start); - start += PAGE_SIZE; - } - local_irq_restore(flags); - } - } -} - -static void r4k_flush_cache_range_s32d16i16(struct vm_area_struct *vma, - unsigned long start, - unsigned long end) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long flags; - - if (CPU_CONTEXT(smp_processor_id(), mm) == 0) - return; - - start &= PAGE_MASK; -#ifdef DEBUG_CACHE - printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); -#endif - if (vma) { - if (CPU_CONTEXT(smp_processor_id(), mm) != - CPU_CONTEXT(smp_processor_id(), current->mm)) { - r4k_flush_cache_all_s32d16i16(); - } else { - pgd_t *pgd; - pmd_t *pmd; - pte_t *pte; - - local_irq_save(flags); - while(start < end) { - pgd = pgd_offset(mm, start); - pmd = pmd_offset(pgd, start); - pte = pte_offset(pmd, start); - - if(pte_val(*pte) & _PAGE_VALID) - blast_scache32_page(start); - start += PAGE_SIZE; - } - local_irq_restore(flags); - } - } -} - -static void r4k_flush_cache_range_s64d16i16(struct vm_area_struct *vma, - unsigned long start, - unsigned long end) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long flags; - - if (CPU_CONTEXT(smp_processor_id(), mm) == 0) - return; - - start &= PAGE_MASK; -#ifdef DEBUG_CACHE - printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); -#endif - if (vma) { - if (CPU_CONTEXT(smp_processor_id(), mm) != - CPU_CONTEXT(smp_processor_id(), current->mm)) { - r4k_flush_cache_all_s64d16i16(); - } else { - pgd_t *pgd; - pmd_t *pmd; - pte_t *pte; - - local_irq_save(flags); - while(start < end) { - pgd = pgd_offset(mm, start); - pmd = pmd_offset(pgd, start); - pte = pte_offset(pmd, start); - - if(pte_val(*pte) & _PAGE_VALID) - blast_scache64_page(start); - start += PAGE_SIZE; - } - local_irq_restore(flags); - } - } -} - -static void r4k_flush_cache_range_s128d16i16(struct vm_area_struct *vma, - unsigned long start, - unsigned long end) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long flags; - - if (CPU_CONTEXT(smp_processor_id(), mm) == 0) - return; - - start &= PAGE_MASK; -#ifdef DEBUG_CACHE - printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); -#endif - if (vma) { - if (CPU_CONTEXT(smp_processor_id(), mm) != - CPU_CONTEXT(smp_processor_id(), current->mm)) { - r4k_flush_cache_all_s128d16i16(); - } else { - pgd_t *pgd; - pmd_t *pmd; - pte_t *pte; - - local_irq_save(flags); - while(start < end) { - pgd = pgd_offset(mm, start); - pmd = pmd_offset(pgd, start); - pte = pte_offset(pmd, start); - - if(pte_val(*pte) & _PAGE_VALID) - blast_scache128_page(start); - start += PAGE_SIZE; - } - local_irq_restore(flags); - } - } -} - -static void r4k_flush_cache_range_s32d32i32(struct vm_area_struct *vma, - unsigned long start, - unsigned long end) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long flags; - - if (CPU_CONTEXT(smp_processor_id(), mm) == 0) - return; - - start &= PAGE_MASK; -#ifdef DEBUG_CACHE - printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); -#endif - if (vma) { - if (CPU_CONTEXT(smp_processor_id(), mm) != - CPU_CONTEXT(smp_processor_id(), current->mm)) { - r4k_flush_cache_all_s32d32i32(); - } else { - pgd_t *pgd; - pmd_t *pmd; - pte_t *pte; - - local_irq_save(flags); - while(start < end) { - pgd = pgd_offset(mm, start); - pmd = pmd_offset(pgd, start); - pte = pte_offset(pmd, start); - - if(pte_val(*pte) & _PAGE_VALID) - blast_scache32_page(start); - start += PAGE_SIZE; - } - local_irq_restore(flags); - } - } -} - -static void r4k_flush_cache_range_s64d32i32(struct vm_area_struct *vma, - unsigned long start, - unsigned long end) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long flags; - - if (CPU_CONTEXT(smp_processor_id(), mm) == 0) - return; - - start &= PAGE_MASK; -#ifdef DEBUG_CACHE - printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); -#endif - if (vma) { - if (CPU_CONTEXT(smp_processor_id(), mm) != - CPU_CONTEXT(smp_processor_id(), current->mm)) { - r4k_flush_cache_all_s64d32i32(); - } else { - pgd_t *pgd; - pmd_t *pmd; - pte_t *pte; - - local_irq_save(flags); - while(start < end) { - pgd = pgd_offset(mm, start); - pmd = pmd_offset(pgd, start); - pte = pte_offset(pmd, start); - - if(pte_val(*pte) & _PAGE_VALID) - blast_scache64_page(start); - start += PAGE_SIZE; - } - local_irq_restore(flags); - } - } -} - -static void r4k_flush_cache_range_s128d32i32(struct vm_area_struct *vma, - unsigned long start, - unsigned long end) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long flags; - - if (CPU_CONTEXT(smp_processor_id(), mm) != 0) - return; - - start &= PAGE_MASK; -#ifdef DEBUG_CACHE - printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); -#endif - if (vma) { - if (CPU_CONTEXT(smp_processor_id(), mm) != - CPU_CONTEXT(smp_processor_id(), current->mm)) { - r4k_flush_cache_all_s128d32i32(); - } else { - pgd_t *pgd; - pmd_t *pmd; - pte_t *pte; - - local_irq_save(flags); - while(start < end) { - pgd = pgd_offset(mm, start); - pmd = pmd_offset(pgd, start); - pte = pte_offset(pmd, start); - - if(pte_val(*pte) & _PAGE_VALID) - blast_scache128_page(start); - start += PAGE_SIZE; - } - local_irq_restore(flags); - } - } -} - -static void r4k_flush_cache_range_d16i16(struct vm_area_struct *vma, - unsigned long start, - unsigned long end) -{ - struct mm_struct *mm = vma->vm_mm; - - if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { - unsigned long flags; - -#ifdef DEBUG_CACHE - printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); -#endif - local_irq_save(flags); - blast_dcache16(); blast_icache16(); - local_irq_restore(flags); - } -} - -static void r4k_flush_cache_range_d32i32(struct vm_area_struct *vma, - unsigned long start, - unsigned long end) -{ - struct mm_struct *mm = vma->vm_mm; - - if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { - unsigned long flags; - -#ifdef DEBUG_CACHE - printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); -#endif - local_irq_save(flags); - blast_dcache32(); blast_icache32(); - local_irq_restore(flags); - } -} - -/* - * On architectures like the Sparc, we could get rid of lines in - * the cache created only by a certain context, but on the MIPS - * (and actually certain Sparc's) we cannot. - */ -static void r4k_flush_cache_mm_s16d16i16(struct mm_struct *mm) -{ - if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { -#ifdef DEBUG_CACHE - printk("cmm[%d]", (int)mm->context); -#endif - r4k_flush_cache_all_s16d16i16(); - } -} - -static void r4k_flush_cache_mm_s32d16i16(struct mm_struct *mm) -{ - if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { -#ifdef DEBUG_CACHE - printk("cmm[%d]", (int)mm->context); -#endif - r4k_flush_cache_all_s32d16i16(); - } -} - -static void r4k_flush_cache_mm_s64d16i16(struct mm_struct *mm) -{ - if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { -#ifdef DEBUG_CACHE - printk("cmm[%d]", (int)mm->context); -#endif - r4k_flush_cache_all_s64d16i16(); - } -} - -static void r4k_flush_cache_mm_s128d16i16(struct mm_struct *mm) -{ - if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { -#ifdef DEBUG_CACHE - printk("cmm[%d]", (int)mm->context); -#endif - r4k_flush_cache_all_s128d16i16(); - } -} - -static void r4k_flush_cache_mm_s32d32i32(struct mm_struct *mm) -{ - if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { -#ifdef DEBUG_CACHE - printk("cmm[%d]", (int)mm->context); -#endif - r4k_flush_cache_all_s32d32i32(); - } -} - -static void r4k_flush_cache_mm_s64d32i32(struct mm_struct *mm) -{ - if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { -#ifdef DEBUG_CACHE - printk("cmm[%d]", (int)mm->context); -#endif - r4k_flush_cache_all_s64d32i32(); - } -} - -static void r4k_flush_cache_mm_s128d32i32(struct mm_struct *mm) -{ - if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { -#ifdef DEBUG_CACHE - printk("cmm[%d]", (int)mm->context); -#endif - r4k_flush_cache_all_s128d32i32(); - } -} - -static void r4k_flush_cache_mm_d16i16(struct mm_struct *mm) -{ - if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { -#ifdef DEBUG_CACHE - printk("cmm[%d]", (int)mm->context); -#endif - r4k_flush_cache_all_d16i16(); - } -} - -static void r4k_flush_cache_mm_d32i32(struct mm_struct *mm) -{ - if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { -#ifdef DEBUG_CACHE - printk("cmm[%d]", (int)mm->context); -#endif - r4k_flush_cache_all_d32i32(); - } -} - -static void r4k_flush_cache_page_s16d16i16(struct vm_area_struct *vma, - unsigned long page) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long flags; - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - - /* - * If ownes no valid ASID yet, cannot possibly have gotten - * this page into the cache. - */ - if (CPU_CONTEXT(smp_processor_id(), mm) == 0) - return; - -#ifdef DEBUG_CACHE - printk("cpage[%d,%08lx]", (int)mm->context, page); -#endif - local_irq_save(flags); - page &= PAGE_MASK; - pgdp = pgd_offset(mm, page); - pmdp = pmd_offset(pgdp, page); - ptep = pte_offset(pmdp, page); - - /* - * If the page isn't marked valid, the page cannot possibly be - * in the cache. - */ - if(!(pte_val(*ptep) & _PAGE_VALID)) - goto out; - - /* Doing flushes for another ASID than the current one is - * too difficult since stupid R4k caches do a TLB translation - * for every cache flush operation. So we do indexed flushes - * in that case, which doesn't overly flush the cache too much. - */ - if (CPU_CONTEXT(smp_processor_id(), mm) != - CPU_CONTEXT(smp_processor_id(), current->mm)) { - /* Do indexed flush, too much work to get the (possible) - * tlb refills to work correctly. - */ - page = (KSEG0 + (page & (scache_size - 1))); - blast_dcache16_page_indexed(page); - blast_scache16_page_indexed(page); - } else - blast_scache16_page(page); -out: - local_irq_restore(flags); -} - -static void r4k_flush_cache_page_s32d16i16(struct vm_area_struct *vma, - unsigned long page) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long flags; - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - - /* - * If ownes no valid ASID yet, cannot possibly have gotten - * this page into the cache. - */ - if (CPU_CONTEXT(smp_processor_id(), mm) == 0) - return; - -#ifdef DEBUG_CACHE - printk("cpage[%d,%08lx]", (int)mm->context, page); -#endif - local_irq_save(flags); - page &= PAGE_MASK; - pgdp = pgd_offset(mm, page); - pmdp = pmd_offset(pgdp, page); - ptep = pte_offset(pmdp, page); - - /* If the page isn't marked valid, the page cannot possibly be - * in the cache. - */ - if(!(pte_val(*ptep) & _PAGE_VALID)) - goto out; - - /* Doing flushes for another ASID than the current one is - * too difficult since stupid R4k caches do a TLB translation - * for every cache flush operation. So we do indexed flushes - * in that case, which doesn't overly flush the cache too much. - */ - if (CPU_CONTEXT(smp_processor_id(), mm) != - CPU_CONTEXT(smp_processor_id(), current->mm)) { - /* Do indexed flush, too much work to get the (possible) - * tlb refills to work correctly. - */ - page = (KSEG0 + (page & (scache_size - 1))); - blast_dcache16_page_indexed(page); - blast_scache32_page_indexed(page); - } else - blast_scache32_page(page); -out: - local_irq_restore(flags); -} - -static void r4k_flush_cache_page_s64d16i16(struct vm_area_struct *vma, - unsigned long page) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long flags; - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - - /* - * If ownes no valid ASID yet, cannot possibly have gotten - * this page into the cache. - */ - if (CPU_CONTEXT(smp_processor_id(), mm) == 0) - return; - -#ifdef DEBUG_CACHE - printk("cpage[%d,%08lx]", (int)mm->context, page); -#endif - local_irq_save(flags); - page &= PAGE_MASK; - pgdp = pgd_offset(mm, page); - pmdp = pmd_offset(pgdp, page); - ptep = pte_offset(pmdp, page); - - /* If the page isn't marked valid, the page cannot possibly be - * in the cache. - */ - if(!(pte_val(*ptep) & _PAGE_VALID)) - goto out; - - /* - * Doing flushes for another ASID than the current one is - * too difficult since stupid R4k caches do a TLB translation - * for every cache flush operation. So we do indexed flushes - * in that case, which doesn't overly flush the cache too much. - */ - if (CPU_CONTEXT(smp_processor_id(), mm) != - CPU_CONTEXT(smp_processor_id(), current->mm)) { - /* Do indexed flush, too much work to get the (possible) - * tlb refills to work correctly. - */ - page = (KSEG0 + (page & (scache_size - 1))); - blast_dcache16_page_indexed(page); - blast_scache64_page_indexed(page); - } else - blast_scache64_page(page); -out: - local_irq_restore(flags); -} - -static void r4k_flush_cache_page_s128d16i16(struct vm_area_struct *vma, - unsigned long page) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long flags; - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - - /* - * If ownes no valid ASID yet, cannot possibly have gotten - * this page into the cache. - */ - if (CPU_CONTEXT(smp_processor_id(), mm) == 0) - return; - -#ifdef DEBUG_CACHE - printk("cpage[%d,%08lx]", (int)mm->context, page); -#endif - local_irq_save(flags); - page &= PAGE_MASK; - pgdp = pgd_offset(mm, page); - pmdp = pmd_offset(pgdp, page); - ptep = pte_offset(pmdp, page); - - /* - * If the page isn't marked valid, the page cannot possibly be - * in the cache. - */ - if(!(pte_val(*ptep) & _PAGE_VALID)) - goto out; - - /* Doing flushes for another ASID than the current one is - * too difficult since stupid R4k caches do a TLB translation - * for every cache flush operation. So we do indexed flushes - * in that case, which doesn't overly flush the cache too much. - */ - if (CPU_CONTEXT(smp_processor_id(), mm) != - CPU_CONTEXT(smp_processor_id(), current->mm)) { - /* - * Do indexed flush, too much work to get the (possible) - * tlb refills to work correctly. - */ - page = (KSEG0 + (page & (scache_size - 1))); - blast_dcache16_page_indexed(page); - blast_scache128_page_indexed(page); - } else - blast_scache128_page(page); -out: - local_irq_restore(flags); -} - -static void r4k_flush_cache_page_s32d32i32(struct vm_area_struct *vma, - unsigned long page) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long flags; - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - - /* - * If ownes no valid ASID yet, cannot possibly have gotten - * this page into the cache. - */ - if (CPU_CONTEXT(smp_processor_id(), mm) == 0) - return; - -#ifdef DEBUG_CACHE - printk("cpage[%d,%08lx]", (int)mm->context, page); -#endif - local_irq_save(flags); - page &= PAGE_MASK; - pgdp = pgd_offset(mm, page); - pmdp = pmd_offset(pgdp, page); - ptep = pte_offset(pmdp, page); - - /* - * If the page isn't marked valid, the page cannot possibly be - * in the cache. - */ - if(!(pte_val(*ptep) & _PAGE_VALID)) - goto out; - - /* - * Doing flushes for another ASID than the current one is - * too difficult since stupid R4k caches do a TLB translation - * for every cache flush operation. So we do indexed flushes - * in that case, which doesn't overly flush the cache too much. - */ - if (CPU_CONTEXT(smp_processor_id(), mm) != - CPU_CONTEXT(smp_processor_id(), current->mm)) { - /* - * Do indexed flush, too much work to get the (possible) - * tlb refills to work correctly. - */ - page = (KSEG0 + (page & (scache_size - 1))); - blast_dcache32_page_indexed(page); - blast_scache32_page_indexed(page); - } else - blast_scache32_page(page); -out: - local_irq_restore(flags); -} - -static void r4k_flush_cache_page_s64d32i32(struct vm_area_struct *vma, - unsigned long page) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long flags; - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - - /* - * If ownes no valid ASID yet, cannot possibly have gotten - * this page into the cache. - */ - if (CPU_CONTEXT(smp_processor_id(), mm) == 0) - return; - -#ifdef DEBUG_CACHE - printk("cpage[%d,%08lx]", (int)mm->context, page); -#endif - local_irq_save(flags); - page &= PAGE_MASK; - pgdp = pgd_offset(mm, page); - pmdp = pmd_offset(pgdp, page); - ptep = pte_offset(pmdp, page); - - /* - * If the page isn't marked valid, the page cannot possibly be - * in the cache. - */ - if(!(pte_val(*ptep) & _PAGE_VALID)) - goto out; - - /* - * Doing flushes for another ASID than the current one is - * too difficult since stupid R4k caches do a TLB translation - * for every cache flush operation. So we do indexed flushes - * in that case, which doesn't overly flush the cache too much. - */ - if (CPU_CONTEXT(smp_processor_id(), mm) != - CPU_CONTEXT(smp_processor_id(), current->mm)) { - /* - * Do indexed flush, too much work to get the (possible) - * tlb refills to work correctly. - */ - page = (KSEG0 + (page & (scache_size - 1))); - blast_dcache32_page_indexed(page); - blast_scache64_page_indexed(page); - } else - blast_scache64_page(page); -out: - local_irq_restore(flags); -} - -static void r4k_flush_cache_page_s128d32i32(struct vm_area_struct *vma, - unsigned long page) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long flags; - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - - /* - * If ownes no valid ASID yet, cannot possibly have gotten - * this page into the cache. - */ - if (CPU_CONTEXT(smp_processor_id(), mm) == 0) - return; - -#ifdef DEBUG_CACHE - printk("cpage[%d,%08lx]", (int)mm->context, page); -#endif - local_irq_save(flags); - page &= PAGE_MASK; - pgdp = pgd_offset(mm, page); - pmdp = pmd_offset(pgdp, page); - ptep = pte_offset(pmdp, page); - - /* If the page isn't marked valid, the page cannot possibly be - * in the cache. - */ - if(!(pte_val(*ptep) & _PAGE_VALID)) - goto out; - - /* - * Doing flushes for another ASID than the current one is - * too difficult since stupid R4k caches do a TLB translation - * for every cache flush operation. So we do indexed flushes - * in that case, which doesn't overly flush the cache too much. - */ - if (CPU_CONTEXT(smp_processor_id(), mm) != - CPU_CONTEXT(smp_processor_id(), current->mm)) { - /* Do indexed flush, too much work to get the (possible) - * tlb refills to work correctly. - */ - page = (KSEG0 + (page & (scache_size - 1))); - blast_dcache32_page_indexed(page); - blast_scache128_page_indexed(page); - } else - blast_scache128_page(page); -out: - local_irq_restore(flags); -} - -static void r4k_flush_cache_page_d16i16(struct vm_area_struct *vma, - unsigned long page) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long flags; - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - - /* - * If ownes no valid ASID yet, cannot possibly have gotten - * this page into the cache. - */ - if (CPU_CONTEXT(smp_processor_id(), mm) == 0) - return; - -#ifdef DEBUG_CACHE - printk("cpage[%d,%08lx]", (int)mm->context, page); -#endif - local_irq_save(flags); - page &= PAGE_MASK; - pgdp = pgd_offset(mm, page); - pmdp = pmd_offset(pgdp, page); - ptep = pte_offset(pmdp, page); - - /* If the page isn't marked valid, the page cannot possibly be - * in the cache. - */ - if(!(pte_val(*ptep) & _PAGE_VALID)) - goto out; - - /* - * Doing flushes for another ASID than the current one is - * too difficult since stupid R4k caches do a TLB translation - * for every cache flush operation. So we do indexed flushes - * in that case, which doesn't overly flush the cache too much. - */ - if(mm == current->mm) { - blast_dcache16_page(page); - } else { - /* Do indexed flush, too much work to get the (possible) - * tlb refills to work correctly. - */ - page = (KSEG0 + (page & (dcache_size - 1))); - blast_dcache16_page_indexed(page); - } -out: - local_irq_restore(flags); -} - -static void r4k_flush_cache_page_d32i32(struct vm_area_struct *vma, - unsigned long page) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long flags; - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - - /* - * If ownes no valid ASID yet, cannot possibly have gotten - * this page into the cache. - */ - if (CPU_CONTEXT(smp_processor_id(), mm) == 0) - return; - -#ifdef DEBUG_CACHE - printk("cpage[%d,%08lx]", (int)mm->context, page); -#endif - local_irq_save(flags); - page &= PAGE_MASK; - pgdp = pgd_offset(mm, page); - pmdp = pmd_offset(pgdp, page); - ptep = pte_offset(pmdp, page); - - /* - * If the page isn't marked valid, the page cannot possibly be - * in the cache. - */ - if(!(pte_val(*ptep) & _PAGE_PRESENT)) - goto out; - - /* - * Doing flushes for another ASID than the current one is - * too difficult since stupid R4k caches do a TLB translation - * for every cache flush operation. So we do indexed flushes - * in that case, which doesn't overly flush the cache too much. - */ - if((mm == current->mm) && (pte_val(*ptep) & _PAGE_VALID)) { - blast_dcache32_page(page); - } else { - /* - * Do indexed flush, too much work to get the (possible) - * tlb refills to work correctly. - */ - page = (KSEG0 + (page & (dcache_size - 1))); - blast_dcache32_page_indexed(page); - } -out: - local_irq_restore(flags); -} - -static void r4k_flush_cache_page_d32i32_r4600(struct vm_area_struct *vma, - unsigned long page) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned long flags; - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - - /* - * If ownes no valid ASID yet, cannot possibly have gotten - * this page into the cache. - */ - if (CPU_CONTEXT(smp_processor_id(), mm) == 0) - return; - -#ifdef DEBUG_CACHE - printk("cpage[%d,%08lx]", (int)mm->context, page); -#endif - local_irq_save(flags); - page &= PAGE_MASK; - pgdp = pgd_offset(mm, page); - pmdp = pmd_offset(pgdp, page); - ptep = pte_offset(pmdp, page); - - /* - * If the page isn't marked valid, the page cannot possibly be - * in the cache. - */ - if(!(pte_val(*ptep) & _PAGE_PRESENT)) - goto out; - - /* - * Doing flushes for another ASID than the current one is - * too difficult since stupid R4k caches do a TLB translation - * for every cache flush operation. So we do indexed flushes - * in that case, which doesn't overly flush the cache too much. - */ - if((mm == current->mm) && (pte_val(*ptep) & _PAGE_VALID)) { - blast_dcache32_page(page); - } else { - /* Do indexed flush, too much work to get the (possible) - * tlb refills to work correctly. - */ - page = (KSEG0 + (page & (dcache_size - 1))); - blast_dcache32_page_indexed(page); - blast_dcache32_page_indexed(page ^ dcache_waybit); - } -out: - local_irq_restore(flags); -} - -static void r4k_flush_page_to_ram_s16(struct page *page) -{ - blast_scache16_page((unsigned long)page_address(page)); -} - -static void r4k_flush_page_to_ram_s32(struct page *page) -{ - blast_scache32_page((unsigned long)page_address(page)); -} - -static void r4k_flush_page_to_ram_s64(struct page *page) -{ - blast_scache64_page((unsigned long)page_address(page)); -} - -static void r4k_flush_page_to_ram_s128(struct page *page) -{ - blast_scache128_page((unsigned long)page_address(page)); -} - -static void r4k_flush_page_to_ram_d16(struct page *page) -{ - unsigned long flags; - - local_irq_save(flags); - blast_dcache16_page((unsigned long)page_address(page)); - local_irq_restore(flags); -} - -static void r4k_flush_page_to_ram_d32(struct page *page) -{ - unsigned long flags; - - local_irq_save(flags); - blast_dcache32_page((unsigned long)page_address(page)); - local_irq_restore(flags); -} - -/* - * Writeback and invalidate the primary cache dcache before DMA. - * - * R4600 v2.0 bug: "The CACHE instructions Hit_Writeback_Inv_D, - * Hit_Writeback_D, Hit_Invalidate_D and Create_Dirty_Exclusive_D will only - * operate correctly if the internal data cache refill buffer is empty. These - * CACHE instructions should be separated from any potential data cache miss - * by a load instruction to an uncached address to empty the response buffer." - * (Revision 2.0 device errata from IDT available on http://www.idt.com/ - * in .pdf format.) - */ -static void r4k_dma_cache_wback_inv_pc(unsigned long addr, unsigned long size) -{ - unsigned long end, a; - unsigned int flags; - - if (size >= (unsigned long)dcache_size) { - flush_cache_l1(); - } else { - /* Workaround for R4600 bug. See comment above. */ - local_irq_save(flags); - *(volatile unsigned long *)KSEG1; - - a = addr & ~((unsigned long)dc_lsize - 1); - end = (addr + size) & ~((unsigned long)dc_lsize - 1); - while (1) { - flush_dcache_line(a); /* Hit_Writeback_Inv_D */ - if (a == end) break; - a += dc_lsize; - } - local_irq_restore(flags); - } - bc_wback_inv(addr, size); -} - -static void r4k_dma_cache_wback_inv_sc(unsigned long addr, unsigned long size) -{ - unsigned long end, a; - - if (size >= (unsigned long)scache_size) { - flush_cache_l1(); - return; - } - - a = addr & ~((unsigned long)sc_lsize - 1); - end = (addr + size) & ~((unsigned long)sc_lsize - 1); - while (1) { - flush_scache_line(a); /* Hit_Writeback_Inv_SD */ - if (a == end) break; - a += sc_lsize; - } -} - -static void r4k_dma_cache_inv_pc(unsigned long addr, unsigned long size) -{ - unsigned long end, a; - unsigned int flags; - - if (size >= (unsigned long)dcache_size) { - flush_cache_l1(); - } else { - /* Workaround for R4600 bug. See comment above. */ - local_irq_save(flags); - *(volatile unsigned long *)KSEG1; - - a = addr & ~((unsigned long)dc_lsize - 1); - end = (addr + size) & ~((unsigned long)dc_lsize - 1); - while (1) { - flush_dcache_line(a); /* Hit_Writeback_Inv_D */ - if (a == end) break; - a += dc_lsize; - } - local_irq_restore(flags); - } - - bc_inv(addr, size); -} - -static void r4k_dma_cache_inv_sc(unsigned long addr, unsigned long size) -{ - unsigned long end, a; - - if (size >= (unsigned long)scache_size) { - flush_cache_l1(); - return; - } - - a = addr & ~((unsigned long)sc_lsize - 1); - end = (addr + size) & ~((unsigned long)sc_lsize - 1); - while (1) { - flush_scache_line(a); /* Hit_Writeback_Inv_SD */ - if (a == end) break; - a += sc_lsize; - } -} - -static void r4k_dma_cache_wback(unsigned long addr, unsigned long size) -{ - panic("r4k_dma_cache called - should not happen.\n"); -} - -/* - * While we're protected against bad userland addresses we don't care - * very much about what happens in that case. Usually a segmentation - * fault will dump the process later on anyway ... - */ -static void r4k_flush_cache_sigtramp(unsigned long addr) -{ - __asm__ __volatile__("nop;nop;nop;nop"); /* R4600 V1.7 */ - - protected_writeback_dcache_line(addr & ~(dc_lsize - 1)); - protected_flush_icache_line(addr & ~(ic_lsize - 1)); -} - -static void r4600v20k_flush_cache_sigtramp(unsigned long addr) -{ - unsigned int flags; - - local_irq_save(flags); - - /* Clear internal cache refill buffer */ - *(volatile unsigned int *)KSEG1; - - protected_writeback_dcache_line(addr & ~(dc_lsize - 1)); - protected_flush_icache_line(addr & ~(ic_lsize - 1)); - - local_irq_restore(flags); -} - -#undef DEBUG_TLB - -#define NTLB_ENTRIES 48 /* Fixed on all R4XX0 variants... */ - -#define NTLB_ENTRIES_HALF 24 /* Fixed on all R4XX0 variants... */ - -static inline void r4k_flush_tlb_all(void) -{ - unsigned long flags; - unsigned long old_ctx; - int entry; - -#ifdef DEBUG_TLB - printk("[tlball]"); -#endif - - local_irq_save(flags); - /* Save old context and create impossible VPN2 value */ - old_ctx = (get_entryhi() & 0xff); - set_entryhi(KSEG0); - set_entrylo0(0); - set_entrylo1(0); - BARRIER; - - entry = get_wired(); - - /* Blast 'em all away. */ - while(entry < NTLB_ENTRIES) { - set_index(entry); - BARRIER; - tlb_write_indexed(); - BARRIER; - entry++; - } - BARRIER; - set_entryhi(old_ctx); - local_irq_restore(flags); -} - -static void r4k_flush_tlb_mm(struct mm_struct *mm) -{ - if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { - unsigned long flags; - -#ifdef DEBUG_TLB - printk("[tlbmm<%d>]", mm->context); -#endif - local_irq_save(flags); - get_new_cpu_mmu_context(mm, smp_processor_id()); - if(mm == current->mm) - set_entryhi(CPU_CONTEXT(smp_processor_id(), mm) & 0xff); - local_irq_restore(flags); - } -} - -static void r4k_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, - unsigned long end) -{ - struct mm_struct *mm = vma->vm_mm; - - if (CPU_CONTEXT(smp_processor_id(), mm) != 0) { - unsigned long flags; - int size; - -#ifdef DEBUG_TLB - printk("[tlbrange<%02x,%08lx,%08lx>]", (mm->context & 0xff), - start, end); -#endif - local_irq_save(flags); - size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; - size = (size + 1) >> 1; - if(size <= NTLB_ENTRIES_HALF) { - int oldpid = (get_entryhi() & 0xff); - int newpid = (CPU_CONTEXT(smp_processor_id(), mm) & 0xff); - - start &= (PAGE_MASK << 1); - end += ((PAGE_SIZE << 1) - 1); - end &= (PAGE_MASK << 1); - while(start < end) { - int idx; - - set_entryhi(start | newpid); - start += (PAGE_SIZE << 1); - BARRIER; - tlb_probe(); - BARRIER; - idx = get_index(); - set_entrylo0(0); - set_entrylo1(0); - set_entryhi(KSEG0); - BARRIER; - if(idx < 0) - continue; - tlb_write_indexed(); - BARRIER; - } - set_entryhi(oldpid); - } else { - get_new_cpu_mmu_context(mm, smp_processor_id()); - if(mm == current->mm) - set_entryhi(CPU_CONTEXT(smp_processor_id(), - mm) & 0xff); - } - local_irq_restore(flags); - } -} - -static void r4k_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) -{ - if (CPU_CONTEXT(smp_processor_id(), vma->vm_mm) != 0) { - unsigned long flags; - int oldpid, newpid, idx; - -#ifdef DEBUG_TLB - printk("[tlbpage<%d,%08lx>]", vma->vm_mm->context, page); -#endif - newpid = (CPU_CONTEXT(smp_processor_id(), vma->vm_mm) & 0xff); - page &= (PAGE_MASK << 1); - local_irq_save(flags); - oldpid = (get_entryhi() & 0xff); - set_entryhi(page | newpid); - BARRIER; - tlb_probe(); - BARRIER; - idx = get_index(); - set_entrylo0(0); - set_entrylo1(0); - set_entryhi(KSEG0); - if(idx < 0) - goto finish; - BARRIER; - tlb_write_indexed(); - - finish: - BARRIER; - set_entryhi(oldpid); - local_irq_restore(flags); - } -} - -static void r4k_flush_cache_l2(void) -{ -} - -/* We will need multiple versions of update_mmu_cache(), one that just - * updates the TLB with the new pte(s), and another which also checks - * for the R4k "end of page" hardware bug and does the needy. - */ -static void r4k_update_mmu_cache(struct vm_area_struct * vma, - unsigned long address, pte_t pte) -{ - unsigned long flags; - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - int idx, pid; - - /* - * Handle debugger faulting in for debugee. - */ - if (current->active_mm != vma->vm_mm) - return; - - local_irq_save(flags); - pid = (get_entryhi() & 0xff); - -#ifdef DEBUG_TLB - if((pid != (CPU_CONTEXT(smp_processor_id(), vma->vm_mm) & 0xff)) || - (CPU_CONTEXT(smp_processor_id(), vma->vm_mm) == 0)) { - printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%d - tlbpid=%d\n", (int) (CPU_CONTEXT(smp_processor_id(), - vma->vm_mm) & 0xff), pid); - } -#endif - - address &= (PAGE_MASK << 1); - set_entryhi(address | (pid)); - pgdp = pgd_offset(vma->vm_mm, address); - BARRIER; - tlb_probe(); - BARRIER; - pmdp = pmd_offset(pgdp, address); - idx = get_index(); - ptep = pte_offset(pmdp, address); - BARRIER; - set_entrylo0(pte_val(*ptep++) >> 6); - set_entrylo1(pte_val(*ptep) >> 6); - set_entryhi(address | (pid)); - BARRIER; - if(idx < 0) { - tlb_write_random(); - } else { - tlb_write_indexed(); - } - BARRIER; - set_entryhi(pid); - BARRIER; - local_irq_restore(flags); -} - -#if 0 -static void r4k_update_mmu_cache_hwbug(struct vm_area_struct * vma, - unsigned long address, pte_t pte) -{ - unsigned long flags; - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - int idx; - - local_irq_save(flags); - address &= (PAGE_MASK << 1); - set_entryhi(address | (get_entryhi() & 0xff)); - pgdp = pgd_offset(vma->vm_mm, address); - tlb_probe(); - pmdp = pmd_offset(pgdp, address); - idx = get_index(); - ptep = pte_offset(pmdp, address); - set_entrylo0(pte_val(*ptep++) >> 6); - set_entrylo1(pte_val(*ptep) >> 6); - BARRIER; - if(idx < 0) - tlb_write_random(); - else - tlb_write_indexed(); - BARRIER; - local_irq_restore(flags); -} -#endif - -static void r4k_show_regs(struct pt_regs *regs) -{ - /* Saved main processor registers. */ - printk("$0 : %016lx %016lx %016lx %016lx\n", - 0UL, regs->regs[1], regs->regs[2], regs->regs[3]); - printk("$4 : %016lx %016lx %016lx %016lx\n", - regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]); - printk("$8 : %016lx %016lx %016lx %016lx\n", - regs->regs[8], regs->regs[9], regs->regs[10], regs->regs[11]); - printk("$12 : %016lx %016lx %016lx %016lx\n", - regs->regs[12], regs->regs[13], regs->regs[14], regs->regs[15]); - printk("$16 : %016lx %016lx %016lx %016lx\n", - regs->regs[16], regs->regs[17], regs->regs[18], regs->regs[19]); - printk("$20 : %016lx %016lx %016lx %016lx\n", - regs->regs[20], regs->regs[21], regs->regs[22], regs->regs[23]); - printk("$24 : %016lx %016lx\n", - regs->regs[24], regs->regs[25]); - printk("$28 : %016lx %016lx %016lx %016lx\n", - regs->regs[28], regs->regs[29], regs->regs[30], regs->regs[31]); - printk("Hi : %016lx\n", regs->hi); - printk("Lo : %016lx\n", regs->lo); - - /* Saved cp0 registers. */ - printk("epc : %016lx %s\nbadvaddr: %016lx\n", - regs->cp0_epc, print_tainted(), regs->cp0_badvaddr); - printk("Status : %08x\nCause : %08x\n", - (unsigned int) regs->cp0_status, (unsigned int) regs->cp0_cause); -} - -/* Detect and size the various r4k caches. */ -static void __init probe_icache(unsigned long config) -{ - icache_size = 1 << (12 + ((config >> 9) & 7)); - ic_lsize = 16 << ((config >> 5) & 1); - - printk("Primary instruction cache %dkb, linesize %d bytes)\n", - icache_size >> 10, ic_lsize); -} - -static void __init probe_dcache(unsigned long config) -{ - dcache_size = 1 << (12 + ((config >> 6) & 7)); - dc_lsize = 16 << ((config >> 4) & 1); - - printk("Primary data cache %dkb, linesize %d bytes)\n", - dcache_size >> 10, dc_lsize); -} - - -/* If you even _breathe_ on this function, look at the gcc output - * and make sure it does not pop things on and off the stack for - * the cache sizing loop that executes in KSEG1 space or else - * you will crash and burn badly. You have been warned. - */ -static int __init probe_scache(unsigned long config) -{ - extern unsigned long stext; - unsigned long flags, addr, begin, end, pow2; - int tmp; - - tmp = ((config >> 17) & 1); - if(tmp) - return 0; - tmp = ((config >> 22) & 3); - switch(tmp) { - case 0: - sc_lsize = 16; - break; - case 1: - sc_lsize = 32; - break; - case 2: - sc_lsize = 64; - break; - case 3: - sc_lsize = 128; - break; - } - - begin = (unsigned long) &stext; - begin &= ~((4 * 1024 * 1024) - 1); - end = begin + (4 * 1024 * 1024); - - /* This is such a bitch, you'd think they would make it - * easy to do this. Away you daemons of stupidity! - */ - local_irq_save(flags); - - /* Fill each size-multiple cache line with a valid tag. */ - pow2 = (64 * 1024); - for(addr = begin; addr < end; addr = (begin + pow2)) { - unsigned long *p = (unsigned long *) addr; - __asm__ __volatile__("nop" : : "r" (*p)); /* whee... */ - pow2 <<= 1; - } - - /* Load first line with zero (therefore invalid) tag. */ - set_taglo(0); - set_taghi(0); - __asm__ __volatile__("nop; nop; nop; nop;"); /* avoid the hazard */ - __asm__ __volatile__("\n\t.set noreorder\n\t" - "cache 8, (%0)\n\t" - ".set reorder\n\t" : : "r" (begin)); - __asm__ __volatile__("\n\t.set noreorder\n\t" - "cache 9, (%0)\n\t" - ".set reorder\n\t" : : "r" (begin)); - __asm__ __volatile__("\n\t.set noreorder\n\t" - "cache 11, (%0)\n\t" - ".set reorder\n\t" : : "r" (begin)); - - /* Now search for the wrap around point. */ - pow2 = (128 * 1024); - tmp = 0; - for(addr = (begin + (128 * 1024)); addr < (end); addr = (begin + pow2)) { - __asm__ __volatile__("\n\t.set noreorder\n\t" - "cache 7, (%0)\n\t" - ".set reorder\n\t" : : "r" (addr)); - __asm__ __volatile__("nop; nop; nop; nop;"); /* hazard... */ - if(!get_taglo()) - break; - pow2 <<= 1; - } - local_irq_restore(flags); - addr -= begin; - printk("Secondary cache sized at %dK linesize %d\n", - (int) (addr >> 10), sc_lsize); - scache_size = addr; - return 1; -} - -static void __init setup_noscache_funcs(void) -{ - unsigned int prid; - - switch(dc_lsize) { - case 16: - _clear_page = r4k_clear_page_d16; - _copy_page = r4k_copy_page_d16; - _flush_cache_l1 = r4k_flush_cache_all_d16i16; - _flush_cache_mm = r4k_flush_cache_mm_d16i16; - _flush_cache_range = r4k_flush_cache_range_d16i16; - _flush_cache_page = r4k_flush_cache_page_d16i16; - break; - case 32: - prid = read_32bit_cp0_register(CP0_PRID) & 0xfff0; - if (prid == 0x2010) { /* R4600 V1.7 */ - _clear_page = r4k_clear_page_r4600_v1; - _copy_page = r4k_copy_page_r4600_v1; - } else if (prid == 0x2020) { /* R4600 V2.0 */ - _clear_page = r4k_clear_page_r4600_v2; - _copy_page = r4k_copy_page_r4600_v2; - } else { - _clear_page = r4k_clear_page_d32; - _copy_page = r4k_copy_page_d32; - } - _flush_cache_l1 = r4k_flush_cache_all_d32i32; - _flush_cache_mm = r4k_flush_cache_mm_d32i32; - _flush_cache_range = r4k_flush_cache_range_d32i32; - _flush_cache_page = r4k_flush_cache_page_d32i32; - break; - } - - switch(ic_lsize) { - case 16: - _flush_page_to_ram = r4k_flush_page_to_ram_d16; - break; - case 32: - _flush_page_to_ram = r4k_flush_page_to_ram_d32; - break; - } - - _dma_cache_wback_inv = r4k_dma_cache_wback_inv_pc; - _dma_cache_wback = r4k_dma_cache_wback; - _dma_cache_inv = r4k_dma_cache_inv_pc; -} - -static void __init setup_scache_funcs(void) -{ - switch(sc_lsize) { - case 16: - switch(dc_lsize) { - case 16: - _flush_cache_l1 = r4k_flush_cache_all_s16d16i16; - _flush_cache_mm = r4k_flush_cache_mm_s16d16i16; - _flush_cache_range = r4k_flush_cache_range_s16d16i16; - _flush_cache_page = r4k_flush_cache_page_s16d16i16; - break; - case 32: - panic("Invalid cache configuration detected"); - }; - _flush_page_to_ram = r4k_flush_page_to_ram_s16; - _clear_page = r4k_clear_page_s16; - _copy_page = r4k_copy_page_s16; - break; - case 32: - switch(dc_lsize) { - case 16: - _flush_cache_l1 = r4k_flush_cache_all_s32d16i16; - _flush_cache_mm = r4k_flush_cache_mm_s32d16i16; - _flush_cache_range = r4k_flush_cache_range_s32d16i16; - _flush_cache_page = r4k_flush_cache_page_s32d16i16; - break; - case 32: - _flush_cache_l1 = r4k_flush_cache_all_s32d32i32; - _flush_cache_mm = r4k_flush_cache_mm_s32d32i32; - _flush_cache_range = r4k_flush_cache_range_s32d32i32; - _flush_cache_page = r4k_flush_cache_page_s32d32i32; - break; - }; - _flush_page_to_ram = r4k_flush_page_to_ram_s32; - _clear_page = r4k_clear_page_s32; - _copy_page = r4k_copy_page_s32; - break; - case 64: - switch(dc_lsize) { - case 16: - _flush_cache_l1 = r4k_flush_cache_all_s64d16i16; - _flush_cache_mm = r4k_flush_cache_mm_s64d16i16; - _flush_cache_range = r4k_flush_cache_range_s64d16i16; - _flush_cache_page = r4k_flush_cache_page_s64d16i16; - break; - case 32: - _flush_cache_l1 = r4k_flush_cache_all_s64d32i32; - _flush_cache_mm = r4k_flush_cache_mm_s64d32i32; - _flush_cache_range = r4k_flush_cache_range_s64d32i32; - _flush_cache_page = r4k_flush_cache_page_s64d32i32; - break; - }; - _flush_page_to_ram = r4k_flush_page_to_ram_s64; - _clear_page = r4k_clear_page_s64; - _copy_page = r4k_copy_page_s64; - break; - case 128: - switch(dc_lsize) { - case 16: - _flush_cache_l1 = r4k_flush_cache_all_s128d16i16; - _flush_cache_mm = r4k_flush_cache_mm_s128d16i16; - _flush_cache_range = r4k_flush_cache_range_s128d16i16; - _flush_cache_page = r4k_flush_cache_page_s128d16i16; - break; - case 32: - _flush_cache_l1 = r4k_flush_cache_all_s128d32i32; - _flush_cache_mm = r4k_flush_cache_mm_s128d32i32; - _flush_cache_range = r4k_flush_cache_range_s128d32i32; - _flush_cache_page = r4k_flush_cache_page_s128d32i32; - break; - }; - _flush_page_to_ram = r4k_flush_page_to_ram_s128; - _clear_page = r4k_clear_page_s128; - _copy_page = r4k_copy_page_s128; - break; - } - _dma_cache_wback_inv = r4k_dma_cache_wback_inv_sc; - _dma_cache_wback = r4k_dma_cache_wback; - _dma_cache_inv = r4k_dma_cache_inv_sc; -} - -typedef int (*probe_func_t)(unsigned long); - -static inline void __init setup_scache(unsigned int config) -{ - probe_func_t probe_scache_kseg1; - int sc_present = 0; - - /* Maybe the cpu knows about a l2 cache? */ - probe_scache_kseg1 = (probe_func_t) (KSEG1ADDR(&probe_scache)); - sc_present = probe_scache_kseg1(config); - - if (sc_present) { - setup_scache_funcs(); - return; - } - - setup_noscache_funcs(); -} - -void __init ld_mmu_r4xx0(void) -{ - unsigned long config = read_32bit_cp0_register(CP0_CONFIG); - - printk("CPU revision is: %08x\n", read_32bit_cp0_register(CP0_PRID)); - -#ifdef CONFIG_MIPS_UNCACHED - set_cp0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); -#else - set_cp0_config(CONF_CM_CMASK, CONF_CM_CACHABLE_NONCOHERENT); -#endif /* UNCACHED */ - - probe_icache(config); - probe_dcache(config); - setup_scache(config); - - switch(mips_cputype) { - case CPU_R4600: /* QED style two way caches? */ - case CPU_R4700: - case CPU_R5000: - case CPU_NEVADA: - _flush_cache_page = r4k_flush_cache_page_d32i32_r4600; - } - - _flush_cache_sigtramp = r4k_flush_cache_sigtramp; - if ((read_32bit_cp0_register(CP0_PRID) & 0xfff0) == 0x2020) { - _flush_cache_sigtramp = r4600v20k_flush_cache_sigtramp; - } - - _flush_tlb_all = r4k_flush_tlb_all; - _flush_tlb_mm = r4k_flush_tlb_mm; - _flush_tlb_range = r4k_flush_tlb_range; - _flush_tlb_page = r4k_flush_tlb_page; - _flush_cache_l2 = r4k_flush_cache_l2; - - update_mmu_cache = r4k_update_mmu_cache; - - _show_regs = r4k_show_regs; - - flush_cache_l1(); - - /* - * You should never change this register: - * - On R4600 1.7 the tlbp never hits for pages smaller than - * the value in the c0_pagemask register. - * - The entire mm handling assumes the c0_pagemask register to - * be set for 4kb pages. - */ - write_32bit_cp0_register(CP0_PAGEMASK, PM_4K); - _flush_tlb_all(); -} diff -Nru a/arch/mips64/mm/sc-ip22.c b/arch/mips64/mm/sc-ip22.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips64/mm/sc-ip22.c Tue Jul 1 18:44:39 2003 @@ -0,0 +1,177 @@ +/* + * sc-ip22.c: Indy cache management functions. + * + * Copyright (C) 1997, 2001 Ralf Baechle (ralf@gnu.org), + * derived from r4xx0.c by David S. Miller (dm@engr.sgi.com). + */ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/* Secondary cache size in bytes, if present. */ +static unsigned long scache_size; + +#undef DEBUG_CACHE + +#define SC_SIZE 0x00080000 +#define SC_LINE 32 +#define CI_MASK (SC_SIZE - SC_LINE) +#define SC_INDEX(n) ((n) & CI_MASK) + +static inline void indy_sc_wipe(unsigned long first, unsigned long last) +{ + unsigned long tmp; + + __asm__ __volatile__( + ".set\tpush\t\t\t# indy_sc_wipe\n\t" + ".set\tnoreorder\n\t" + ".set\tmips3\n\t" + ".set\tnoat\n\t" + "mfc0\t%2, $12\n\t" + "li\t$1, 0x80\t\t\t# Go 64 bit\n\t" + "mtc0\t$1, $12\n\t" + + "dli\t$1, 0x9000000080000000\n\t" + "or\t%0, $1\t\t\t# first line to flush\n\t" + "or\t%1, $1\t\t\t# last line to flush\n\t" + ".set\tat\n\t" + + "1:\tsw\t$0, 0(%0)\n\t" + "bne\t%0, %1, 1b\n\t" + " daddu\t%0, 32\n\t" + + "mtc0\t%2, $12\t\t\t# Back to 32 bit\n\t" + "nop; nop; nop; nop;\n\t" + ".set\tpop" + : "=r" (first), "=r" (last), "=&r" (tmp) + : "0" (first), "1" (last)); +} + +static void indy_sc_wback_invalidate(unsigned long addr, unsigned long size) +{ + unsigned long first_line, last_line; + unsigned int flags; + +#ifdef DEBUG_CACHE + printk("indy_sc_wback_invalidate[%08lx,%08lx]", addr, size); +#endif + + if (!size) + return; + + /* Which lines to flush? */ + first_line = SC_INDEX(addr); + last_line = SC_INDEX(addr + size - 1); + + local_irq_save(flags); + if (first_line <= last_line) { + indy_sc_wipe(first_line, last_line); + goto out; + } + + indy_sc_wipe(first_line, SC_SIZE - SC_LINE); + indy_sc_wipe(0, last_line); +out: + local_irq_restore(flags); +} + +static void indy_sc_enable(void) +{ + unsigned long addr, tmp1, tmp2; + + /* This is really cool... */ +#ifdef DEBUG_CACHE + printk("Enabling R4600 SCACHE\n"); +#endif + __asm__ __volatile__( + ".set\tpush\n\t" + ".set\tnoreorder\n\t" + ".set\tmips3\n\t" + "mfc0\t%2, $12\n\t" + "nop; nop; nop; nop;\n\t" + "li\t%1, 0x80\n\t" + "mtc0\t%1, $12\n\t" + "nop; nop; nop; nop;\n\t" + "li\t%0, 0x1\n\t" + "dsll\t%0, 31\n\t" + "lui\t%1, 0x9000\n\t" + "dsll32\t%1, 0\n\t" + "or\t%0, %1, %0\n\t" + "sb\t$0, 0(%0)\n\t" + "mtc0\t$0, $12\n\t" + "nop; nop; nop; nop;\n\t" + "mtc0\t%2, $12\n\t" + "nop; nop; nop; nop;\n\t" + ".set\tpop" + : "=r" (tmp1), "=r" (tmp2), "=r" (addr)); +} + +static void indy_sc_disable(void) +{ + unsigned long tmp1, tmp2, tmp3; + +#ifdef DEBUG_CACHE + printk("Disabling R4600 SCACHE\n"); +#endif + __asm__ __volatile__( + ".set\tpush\n\t" + ".set\tnoreorder\n\t" + ".set\tmips3\n\t" + "li\t%0, 0x1\n\t" + "dsll\t%0, 31\n\t" + "lui\t%1, 0x9000\n\t" + "dsll32\t%1, 0\n\t" + "or\t%0, %1, %0\n\t" + "mfc0\t%2, $12\n\t" + "nop; nop; nop; nop\n\t" + "li\t%1, 0x80\n\t" + "mtc0\t%1, $12\n\t" + "nop; nop; nop; nop\n\t" + "sh\t$0, 0(%0)\n\t" + "mtc0\t$0, $12\n\t" + "nop; nop; nop; nop\n\t" + "mtc0\t%2, $12\n\t" + "nop; nop; nop; nop\n\t" + ".set\tpop" + : "=r" (tmp1), "=r" (tmp2), "=r" (tmp3)); +} + +static inline int __init indy_sc_probe(void) +{ + unsigned int size = ip22_eeprom_read(&sgimc->eeprom, 17); + if (size == 0) + return 0; + + size <<= PAGE_SHIFT; + printk(KERN_INFO "R4600/R5000 SCACHE size %ldK, linesize 32 bytes.\n", + size >> 10); + scache_size = size; + + return 1; +} + +/* XXX Check with wje if the Indy caches can differenciate between + writeback + invalidate and just invalidate. */ +struct bcache_ops indy_sc_ops = { + .bc_enable = indy_sc_enable, + .bc_disable = indy_sc_disable, + .bc_wback_inv = indy_sc_wback_invalidate, + .bc_inv = indy_sc_wback_invalidate +}; + +void __init indy_sc_init(void) +{ + if (indy_sc_probe()) { + indy_sc_enable(); + bcops = &indy_sc_ops; + } +} diff -Nru a/arch/mips64/mm/sc-r5k.c b/arch/mips64/mm/sc-r5k.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips64/mm/sc-r5k.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,115 @@ +/* + * Copyright (C) 1997, 2001 Ralf Baechle (ralf@gnu.org), + * derived from r4xx0.c by David S. Miller (dm@engr.sgi.com). + */ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/* Secondary cache size in bytes, if present. */ +static unsigned long scache_size; + +#define SC_LINE 32 +#define SC_PAGE (128*SC_LINE) + +#define cache_op(base,op) \ +__asm__ __volatile__(" \ + .set noreorder; \ + .set mips3; \ + cache %1, (%0); \ + .set mips0; \ + .set reorder" \ + : \ + : "r" (base), \ + "i" (op)); + +static inline void blast_r5000_scache(void) +{ + unsigned long start = KSEG0; + unsigned long end = KSEG0 + scache_size; + + while(start < end) { + cache_op(start, R5K_Page_Invalidate_S); + start += SC_PAGE; + } +} + +static void r5k_dma_cache_inv_sc(unsigned long addr, unsigned long size) +{ + unsigned long end, a; + + if (size >= scache_size) { + blast_r5000_scache(); + return; + } + + /* On the R5000 secondary cache we cannot + * invalidate less than a page at a time. + * The secondary cache is physically indexed, write-through. + */ + a = addr & ~(SC_PAGE - 1); + end = (addr + size - 1) & ~(SC_PAGE - 1); + while (a <= end) { + cache_op(a, R5K_Page_Invalidate_S); + a += SC_PAGE; + } +} + +static void r5k_sc_enable(void) +{ + unsigned long flags; + + local_irq_save(flags); + change_c0_config(R5K_CONF_SE, R5K_CONF_SE); + blast_r5000_scache(); + local_irq_restore(flags); +} + +static void r5k_sc_disable(void) +{ + unsigned long flags; + + local_irq_save(flags); + blast_r5000_scache(); + change_c0_config(R5K_CONF_SE, 0); + local_irq_restore(flags); +} + +static inline int __init r5k_sc_probe(void) +{ + unsigned long config = read_c0_config(); + + if (config & CONF_SC) + return(0); + + scache_size = (512 * 1024) << ((config & R5K_CONF_SS) >> 20); + + printk("R5000 SCACHE size %ldkB, linesize 32 bytes.\n", + scache_size >> 10); + + return 1; +} + +static struct bcache_ops r5k_sc_ops = { + .bc_enable = r5k_sc_enable, + .bc_disable = r5k_sc_disable, + .bc_wback_inv = r5k_dma_cache_inv_sc, + .bc_inv = r5k_dma_cache_inv_sc +}; + +void __init r5k_sc_init(void) +{ + if (r5k_sc_probe()) { + r5k_sc_enable(); + bcops = &r5k_sc_ops; + } +} diff -Nru a/arch/mips64/mm/sc-rm7k.c b/arch/mips64/mm/sc-rm7k.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips64/mm/sc-rm7k.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,191 @@ +/* + * sc-rm7k.c: RM7000 cache management functions. + * + * Copyright (C) 1997, 2001, 2003 Ralf Baechle (ralf@gnu.org), + */ +#include +#include +#include + +#include +#include +#include +#include +#include + +/* Primary cache parameters. */ +#define sc_lsize 32 +#define tc_pagesize (32*128) + +/* Secondary cache parameters. */ +#define scache_size (256*1024) /* Fixed to 256KiB on RM7000 */ + +extern unsigned long icache_way_size, dcache_way_size; + +#include + +int rm7k_tcache_enabled; + +/* + * Writeback and invalidate the primary cache dcache before DMA. + * (XXX These need to be fixed ...) + */ +static void rm7k_sc_wback_inv(unsigned long addr, unsigned long size) +{ + unsigned long end, a; + +#ifdef DEBUG_CACHE + printk("rm7k_sc_wback_inv[%08lx,%08lx]", addr, size); +#endif + + a = addr & ~(sc_lsize - 1); + end = (addr + size - 1) & ~(sc_lsize - 1); + while (1) { + flush_scache_line(a); /* Hit_Writeback_Inv_SD */ + if (a == end) + break; + a += sc_lsize; + } + + if (!rm7k_tcache_enabled) + return; + + a = addr & ~(tc_pagesize - 1); + end = (addr + size - 1) & ~(tc_pagesize - 1); + while(1) { + invalidate_tcache_page(a); /* Page_Invalidate_T */ + if (a == end) + break; + a += tc_pagesize; + } +} + +static void rm7k_sc_inv(unsigned long addr, unsigned long size) +{ + unsigned long end, a; + +#ifdef DEBUG_CACHE + printk("rm7k_sc_inv[%08lx,%08lx]", addr, size); +#endif + + a = addr & ~(sc_lsize - 1); + end = (addr + size - 1) & ~(sc_lsize - 1); + while (1) { + invalidate_scache_line(a); /* Hit_Invalidate_SD */ + if (a == end) + break; + a += sc_lsize; + } + + if (!rm7k_tcache_enabled) + return; + + a = addr & ~(tc_pagesize - 1); + end = (addr + size - 1) & ~(tc_pagesize - 1); + while(1) { + invalidate_tcache_page(a); /* Page_Invalidate_T */ + if (a == end) + break; + a += tc_pagesize; + } +} + +/* + * This function is executed in the uncached segment KSEG1. + * It must not touch the stack, because the stack pointer still points + * into KSEG0. + * + * Three options: + * - Write it in assembly and guarantee that we don't use the stack. + * - Disable caching for KSEG0 before calling it. + * - Pray that GCC doesn't randomly start using the stack. + * + * This being Linux, we obviously take the least sane of those options - + * following DaveM's lead in c-r4k.c + * + * It seems we get our kicks from relying on unguaranteed behaviour in GCC + */ +static __init void rm7k_sc_enable(void) +{ + int i; + + set_c0_config(1<<3); /* CONF_SE */ + + write_c0_taglo(0); + write_c0_taghi(0); + + for (i=0; i> 31) & 1) + return 0; + + printk(KERN_INFO "Secondary cache size %ldK, linesize 32 bytes.\n", + (scache_size >> 10), sc_lsize); + + if ((config >> 3) & 1) + return; + + printk(KERN_INFO "Enabling secondary cache..."); + func(); + printk(" done\n"); + + /* + * While we're at it let's deal with the tertiary cache. + */ + if ((config >> 17) & 1) + return 1; + + /* + * We can't enable the L3 cache yet. There may be board-specific + * magic necessary to turn it on, and blindly asking the CPU to + * start using it would may give cache errors. + * + * Also, board-specific knowledge may allow us to use the + * CACHE Flash_Invalidate_T instruction if the tag RAM supports + * it, and may specify the size of the L3 cache so we don't have + * to probe it. + */ + printk(KERN_INFO "Tertiary cache present, %s enabled\n", + config&(1<<12) ? "already" : "not (yet)"); + + if ((config >> 12) & 1) + rm7k_tcache_enabled = 1; + + return 1; +} + +struct bcache_ops rm7k_sc_ops = { + .bc_enable = rm7k_sc_enable, + .bc_disable = rm7k_sc_disable, + .bc_wback_inv = rm7k_sc_wback_inv, + .bc_inv = rm7k_sc_inv +}; + +void __init rm7k_sc_init(void) +{ + if (rm7k_sc_probe()) { + rm7k_sc_enable(); + bcops = &rm7k_sc_ops; + } +} diff -Nru a/arch/mips64/mm/tlb-andes.c b/arch/mips64/mm/tlb-andes.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips64/mm/tlb-andes.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,257 @@ +/* + * 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) 1997, 1998, 1999 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 1999 Silicon Graphics, Inc. + * Copyright (C) 2000 Kanoj Sarcar (kanoj@sgi.com) + */ +#include +#include +#include +#include +#include +#include +#include +#include + +extern void except_vec1_r10k(void); + +#define NTLB_ENTRIES 64 +#define NTLB_ENTRIES_HALF 32 + +void local_flush_tlb_all(void) +{ + unsigned long flags; + unsigned long old_ctx; + unsigned long entry; + + local_irq_save(flags); + /* Save old context and create impossible VPN2 value */ + old_ctx = read_c0_entryhi() & ASID_MASK; + write_c0_entryhi(CKSEG0); + write_c0_entrylo0(0); + write_c0_entrylo1(0); + + entry = read_c0_wired(); + + /* Blast 'em all away. */ + while (entry < NTLB_ENTRIES) { + write_c0_index(entry); + tlb_write_indexed(); + entry++; + } + write_c0_entryhi(old_ctx); + local_irq_restore(flags); +} + +void local_flush_tlb_mm(struct mm_struct *mm) +{ + int cpu = smp_processor_id(); + if (cpu_context(cpu, mm) != 0) { + drop_mmu_context(mm,cpu); + } +} + +void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, + unsigned long end) +{ + struct mm_struct *mm = vma->vm_mm; + int cpu = smp_processor_id(); + + if (cpu_context(cpu, mm) != 0) { + unsigned long flags; + int size; + + local_irq_save(flags); + size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + size = (size + 1) >> 1; + if (size <= NTLB_ENTRIES_HALF) { + int oldpid = (read_c0_entryhi() & ASID_MASK); + int newpid = (cpu_context(smp_processor_id(), mm) + & ASID_MASK); + + start &= (PAGE_MASK << 1); + end += ((PAGE_SIZE << 1) - 1); + end &= (PAGE_MASK << 1); + while(start < end) { + int idx; + + write_c0_entryhi(start | newpid); + start += (PAGE_SIZE << 1); + tlb_probe(); + idx = read_c0_index(); + write_c0_entrylo0(0); + write_c0_entrylo1(0); + write_c0_entryhi(KSEG0); + if(idx < 0) + continue; + tlb_write_indexed(); + } + write_c0_entryhi(oldpid); + } else { + drop_mmu_context(mm, cpu); + } + local_irq_restore(flags); + } +} + +void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) +{ + unsigned long flags; + int size; + + size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + size = (size + 1) >> 1; + + local_irq_save(flags); + if (size <= NTLB_ENTRIES_HALF) { + int pid = read_c0_entryhi(); + + start &= (PAGE_MASK << 1); + end += ((PAGE_SIZE << 1) - 1); + end &= (PAGE_MASK << 1); + + while (start < end) { + int idx; + + write_c0_entryhi(start); + start += (PAGE_SIZE << 1); + tlb_probe(); + idx = read_c0_index(); + write_c0_entrylo0(0); + write_c0_entrylo1(0); + write_c0_entryhi(KSEG0 + (idx << (PAGE_SHIFT+1))); + if (idx < 0) + continue; + tlb_write_indexed(); + } + write_c0_entryhi(pid); + } else { + local_flush_tlb_all(); + } + local_irq_restore(flags); +} + +void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) +{ + if (cpu_context(smp_processor_id(), vma->vm_mm) != 0) { + unsigned long flags; + int oldpid, newpid, idx; + + newpid = (cpu_context(smp_processor_id(), vma->vm_mm) & + ASID_MASK); + page &= (PAGE_MASK << 1); + local_irq_save(flags); + oldpid = (read_c0_entryhi() & ASID_MASK); + write_c0_entryhi(page | newpid); + tlb_probe(); + idx = read_c0_index(); + write_c0_entrylo0(0); + write_c0_entrylo1(0); + write_c0_entryhi(KSEG0); + if (idx < 0) + goto finish; + tlb_write_indexed(); + + finish: + write_c0_entryhi(oldpid); + local_irq_restore(flags); + } +} + +/* + * This one is only used for pages with the global bit set so we don't care + * much about the ASID. + */ +void local_flush_tlb_one(unsigned long page) +{ + unsigned long flags; + int oldpid, idx; + + local_irq_save(flags); + page &= (PAGE_MASK << 1); + oldpid = read_c0_entryhi() & 0xff; + write_c0_entryhi(page); + tlb_probe(); + idx = read_c0_index(); + write_c0_entrylo0(0); + write_c0_entrylo1(0); + if (idx >= 0) { + /* Make sure all entries differ. */ + write_c0_entryhi(KSEG0+(idx<<(PAGE_SHIFT+1))); + tlb_write_indexed(); + } + write_c0_entryhi(oldpid); + + local_irq_restore(flags); +} + +/* XXX Simplify this. On the R10000 writing a TLB entry for an virtual + address that already exists will overwrite the old entry and not result + in TLB malfunction or TLB shutdown. */ +void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte) +{ + unsigned long flags; + pgd_t *pgdp; + pmd_t *pmdp; + pte_t *ptep; + int idx, pid; + + /* + * Handle debugger faulting in for debugee. + */ + if (current->active_mm != vma->vm_mm) + return; + + pid = read_c0_entryhi() & ASID_MASK; + + if ((pid != (cpu_context(smp_processor_id(), vma->vm_mm) & ASID_MASK)) + || (cpu_context(smp_processor_id(), vma->vm_mm) == 0)) { + printk(KERN_WARNING + "%s: Wheee, bogus tlbpid mmpid=%d tlbpid=%d\n", + __FUNCTION__, (int) (cpu_context(smp_processor_id(), + vma->vm_mm) & ASID_MASK), pid); + } + + local_irq_save(flags); + address &= (PAGE_MASK << 1); + write_c0_entryhi(address | (pid)); + pgdp = pgd_offset(vma->vm_mm, address); + tlb_probe(); + pmdp = pmd_offset(pgdp, address); + idx = read_c0_index(); + ptep = pte_offset_map(pmdp, address); + write_c0_entrylo0(pte_val(*ptep++) >> 6); + write_c0_entrylo1(pte_val(*ptep) >> 6); + write_c0_entryhi(address | (pid)); + if (idx < 0) { + tlb_write_random(); + } else { + tlb_write_indexed(); + } + write_c0_entryhi(pid); + local_irq_restore(flags); +} + +void __init andes_tlb_init(void) +{ + /* + * You should never change this register: + * - On R4600 1.7 the tlbp never hits for pages smaller than + * the value in the c0_pagemask register. + * - The entire mm handling assumes the c0_pagemask register to + * be set for 4kb pages. + */ + write_c0_pagemask(PM_4K); + write_c0_wired(0); + write_c0_framemask(0); + + /* From this point on the ARC firmware is dead. */ + local_flush_tlb_all(); + + /* Did I tell you that ARC SUCKS? */ + + memcpy((void *)KSEG1 + 0x080, except_vec1_r10k, 0x80); +} diff -Nru a/arch/mips64/mm/tlb-dbg-r4k.c b/arch/mips64/mm/tlb-dbg-r4k.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips64/mm/tlb-dbg-r4k.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,71 @@ +/* + * 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) 1999 Ralf Baechle + * Copyright (C) 1999 Silicon Graphics, Inc. + * + * TLB debugging routines. These perform horribly slow but can easily be + * modified for debugging purposes. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write, + unsigned long address); + +asmlinkage void tlb_refill_debug(struct pt_regs regs) +{ + show_regs(®s); + panic(__FUNCTION__ " called. This Does Not Happen (TM)."); +} + +asmlinkage void xtlb_refill_debug(struct pt_regs *regs) +{ + unsigned long addr; + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + + addr = regs->cp0_badvaddr & ~((PAGE_SIZE << 1) - 1); + pgd = pgd_offset(current->active_mm, addr); + pmd = pmd_offset(pgd, addr); + pte = pte_offset(pmd, addr); + + write_c0_entrylo0(pte_val(pte[0]) >> 6); + write_c0_entrylo1(pte_val(pte[1]) >> 6); + __asm__ __volatile__("nop;nop;nop"); + + tlb_write_random(); +} + +asmlinkage void xtlb_mod_debug(struct pt_regs *regs) +{ + unsigned long addr; + + addr = regs->cp0_badvaddr; + do_page_fault(regs, 1, addr); +} + +asmlinkage void xtlb_tlbl_debug(struct pt_regs *regs) +{ + unsigned long addr; + + addr = regs->cp0_badvaddr; + do_page_fault(regs, 0, addr); +} + +asmlinkage void xtlb_tlbs_debug(struct pt_regs *regs) +{ + unsigned long addr; + + addr = regs->cp0_badvaddr; + do_page_fault(regs, 1, addr); +} diff -Nru a/arch/mips64/mm/tlb-glue-r4k.S b/arch/mips64/mm/tlb-glue-r4k.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips64/mm/tlb-glue-r4k.S Tue Jul 1 18:44:40 2003 @@ -0,0 +1,41 @@ +/* + * 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) 1999 Ralf Baechle + * Copyright (C) 1999 Silicon Graphics, Inc. + */ +#include +#include +#include +#include + + .macro __BUILD_cli + CLI + .endm + + .macro __BUILD_sti + STI + .endm + + .macro __BUILD_kmode + KMODE + .endm + + .macro tlb_handler name interruptible writebit + NESTED(__\name, PT_SIZE, sp) + SAVE_ALL + dmfc0 a2, CP0_BADVADDR + __BUILD_\interruptible + li a1, \writebit + sd a2, PT_BVADDR(sp) + move a0, sp + jal do_page_fault + j ret_from_exception + END(__\name) + .endm + + tlb_handler xtlb_mod kmode 1 + tlb_handler xtlb_tlbl kmode 0 + tlb_handler xtlb_tlbs kmode 1 diff -Nru a/arch/mips64/mm/tlb-glue-sb1.S b/arch/mips64/mm/tlb-glue-sb1.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips64/mm/tlb-glue-sb1.S Tue Jul 1 18:44:40 2003 @@ -0,0 +1,66 @@ +/* + * 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) 1999 Ralf Baechle + * Copyright (C) 1999 Silicon Graphics, Inc. + */ +#include +#include +#include +#include +#include +#include + + .macro __BUILD_cli + CLI + .endm + + .macro __BUILD_sti + STI + .endm + + .macro __BUILD_kmode + KMODE + .endm + + .macro tlb_handler name interruptible writebit + NESTED(__\name, PT_SIZE, sp) + SAVE_ALL + dmfc0 a2, CP0_BADVADDR + __BUILD_\interruptible + li a1, \writebit + sd a2, PT_BVADDR(sp) + move a0, sp + jal do_page_fault + j ret_from_exception + END(__\name) + .endm + + .macro tlb_handler_m3 name interruptible writebit + NESTED(__\name, PT_SIZE, sp) + dmfc0 k0, CP0_BADVADDR + dmfc0 k1, CP0_ENTRYHI + xor k0, k1 + dsrl k0, k0, PAGE_SHIFT + 1 + bnez k0, 1f + SAVE_ALL + dmfc0 a2, CP0_BADVADDR + __BUILD_\interruptible + li a1, \writebit + sd a2, PT_BVADDR(sp) + move a0, sp + jal do_page_fault +1: + j ret_from_exception + END(__\name) + .endm + + tlb_handler xtlb_mod kmode 1 +#if BCM1250_M3_WAR + tlb_handler_m3 xtlb_tlbl kmode 0 +#else + tlb_handler xtlb_tlbl kmode 0 +#endif + tlb_handler xtlb_tlbs kmode 1 diff -Nru a/arch/mips64/mm/tlb-r4k.c b/arch/mips64/mm/tlb-r4k.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips64/mm/tlb-r4k.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,415 @@ +/* + * Carsten Langgaard, carstenl@mips.com + * Copyright (C) 2002 MIPS Technologies, Inc. All rights reserved. + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * MIPS64 CPU variant specific MMU routines. + * These routine are not optimized in any way, they are done in a generic way + * so they can be used on all MIPS64 compliant CPUs, and also done in an + * attempt not to break anything for the R4xx0 style CPUs. + */ +#include +#include +#include + +#include +#include +#include +#include +#include + +#undef DEBUG_TLB +#undef DEBUG_TLBUPDATE + +extern void except_vec1_r4k(void); + +/* CP0 hazard avoidance. */ +#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \ + "nop; nop; nop; nop; nop; nop;\n\t" \ + ".set reorder\n\t") + +void local_flush_tlb_all(void) +{ + unsigned long flags; + unsigned long old_ctx; + int entry; + +#ifdef DEBUG_TLB + printk("[tlball]"); +#endif + + local_irq_save(flags); + /* Save old context and create impossible VPN2 value */ + old_ctx = read_c0_entryhi() & ASID_MASK; + write_c0_entryhi(XKPHYS); + write_c0_entrylo0(0); + write_c0_entrylo1(0); + BARRIER; + + entry = read_c0_wired(); + + /* Blast 'em all away. */ + while(entry < current_cpu_data.tlbsize) { + /* Make sure all entries differ. */ + write_c0_entryhi(XKPHYS+entry*0x2000); + write_c0_index(entry); + BARRIER; + tlb_write_indexed(); + BARRIER; + entry++; + } + BARRIER; + write_c0_entryhi(old_ctx); + local_irq_restore(flags); +} + +void local_flush_tlb_mm(struct mm_struct *mm) +{ + int cpu = smp_processor_id(); + + if (cpu_context(cpu, mm) != 0) { +#ifdef DEBUG_TLB + printk("[tlbmm<%d>]", cpu_context(cpu, mm)); +#endif + drop_mmu_context(mm,cpu); + } +} + +void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, + unsigned long end) +{ + struct mm_struct *mm = vma->vm_mm; + int cpu = smp_processor_id(); + + if (cpu_context(cpu, mm) != 0) { + unsigned long flags; + int size; + +#ifdef DEBUG_TLB + printk("[tlbrange<%02x,%08lx,%08lx>]", cpu_context(cpu, mm) & ASID_MASK, + start, end); +#endif + local_irq_save(flags); + size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + size = (size + 1) >> 1; + if(size <= current_cpu_data.tlbsize/2) { + int oldpid = read_c0_entryhi() & ASID_MASK; + int newpid = cpu_asid(cpu, mm); + + start &= (PAGE_MASK << 1); + end += ((PAGE_SIZE << 1) - 1); + end &= (PAGE_MASK << 1); + while (start < end) { + int idx; + + write_c0_entryhi(start | newpid); + start += (PAGE_SIZE << 1); + BARRIER; + tlb_probe(); + BARRIER; + idx = read_c0_index(); + write_c0_entrylo0(0); + write_c0_entrylo1(0); + if(idx < 0) + continue; + /* Make sure all entries differ. */ + write_c0_entryhi(XKPHYS+idx*0x2000); + BARRIER; + tlb_write_indexed(); + BARRIER; + } + write_c0_entryhi(oldpid); + } else { + drop_mmu_context(mm, cpu); + } + local_irq_restore(flags); + } +} + +void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) +{ + unsigned long flags; + int size; + +#ifdef DEBUG_TLB + printk("[tlbkernelrange<%08lx,%08lx>]", start, end); +#endif + local_irq_save(flags); + size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + size = (size + 1) >> 1; + if (size <= current_cpu_data.tlbsize/2) { + int pid = read_c0_entryhi(); + + start &= (PAGE_MASK << 1); + end += ((PAGE_SIZE << 1) - 1); + end &= (PAGE_MASK << 1); + + while (start < end) { + int idx; + + write_c0_entryhi(start); + start += (PAGE_SIZE << 1); + BARRIER; + tlb_probe(); + BARRIER; + idx = read_c0_index(); + write_c0_entrylo0(0); + write_c0_entrylo1(0); + if (idx < 0) + continue; + /* Make sure all entries differ. */ + write_c0_entryhi(XKPHYS+idx*0x2000); + BARRIER; + tlb_write_indexed(); + BARRIER; + } + write_c0_entryhi(pid); + } else { + local_flush_tlb_all(); + } + local_irq_restore(flags); +} + +void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) +{ + int cpu = smp_processor_id(); + + if (cpu_context(cpu, vma->vm_mm) != 0) { + unsigned long flags; + unsigned long oldpid, newpid, idx; + +#ifdef DEBUG_TLB + printk("[tlbpage<%d,%08lx>]", cpu_asid(cpu, vma->vm_mm), page); +#endif + newpid = cpu_asid(cpu, vma->vm_mm); + page &= (PAGE_MASK << 1); + local_irq_save(flags); + oldpid = read_c0_entryhi() & ASID_MASK; + write_c0_entryhi(page | newpid); + BARRIER; + tlb_probe(); + BARRIER; + idx = read_c0_index(); + write_c0_entrylo0(0); + write_c0_entrylo1(0); + if(idx < 0) + goto finish; + /* Make sure all entries differ. */ + write_c0_entryhi(XKPHYS+idx*0x2000); + BARRIER; + tlb_write_indexed(); + finish: + BARRIER; + write_c0_entryhi(oldpid); + local_irq_restore(flags); + } +} + +/* + * This one is only used for pages with the global bit set so we don't care + * much about the ASID. + */ +void local_flush_tlb_one(unsigned long page) +{ + unsigned long flags; + int oldpid, idx; + + local_irq_save(flags); + page &= (PAGE_MASK << 1); + oldpid = read_c0_entryhi() & 0xff; + write_c0_entryhi(page); + BARRIER; + tlb_probe(); + BARRIER; + idx = read_c0_index(); + write_c0_entrylo0(0); + write_c0_entrylo1(0); + if (idx >= 0) { + /* Make sure all entries differ. */ + write_c0_entryhi(KSEG0+(idx<<(PAGE_SHIFT+1))); + BARRIER; + tlb_write_indexed(); + } + BARRIER; + write_c0_entryhi(oldpid); + + local_irq_restore(flags); +} + +/* + * Updates the TLB with the new pte(s). + */ +void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte) +{ + unsigned long flags; + pgd_t *pgdp; + pmd_t *pmdp; + pte_t *ptep; + int idx, pid; + + /* + * Handle debugger faulting in for debugee. + */ + if (current->active_mm != vma->vm_mm) + return; + + pid = read_c0_entryhi() & ASID_MASK; + +#ifdef DEBUG_TLB + if ((pid != cpu_asid(smp_processor_id(), vma->vm_mm))) || + (cpu_context(smp_processor_id(), vma->vm_mm) == 0)) { + printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%d " + "tlbpid=%d\n", (int) cpu_asid(smp_processor_id(), + vma->vm_mm), pid); + } +#endif + + local_irq_save(flags); + address &= (PAGE_MASK << 1); + write_c0_entryhi(address | (pid)); + pgdp = pgd_offset(vma->vm_mm, address); + BARRIER; + tlb_probe(); + BARRIER; + pmdp = pmd_offset(pgdp, address); + idx = read_c0_index(); + ptep = pte_offset_map(pmdp, address); + BARRIER; + write_c0_entrylo0(pte_val(*ptep++) >> 6); + write_c0_entrylo1(pte_val(*ptep) >> 6); + write_c0_entryhi(address | (pid)); + BARRIER; + if(idx < 0) { + tlb_write_random(); + } else { + tlb_write_indexed(); + } + BARRIER; + write_c0_entryhi(pid); + BARRIER; + local_irq_restore(flags); +} + +void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, + unsigned long entryhi, unsigned long pagemask) +{ + unsigned long flags; + unsigned long wired; + unsigned long old_pagemask; + unsigned long old_ctx; + + local_irq_save(flags); + /* Save old context and create impossible VPN2 value */ + old_ctx = read_c0_entryhi() & ASID_MASK; + old_pagemask = read_c0_pagemask(); + wired = read_c0_wired(); + write_c0_wired(wired + 1); + write_c0_index(wired); + BARRIER; + write_c0_pagemask(pagemask); + write_c0_entryhi(entryhi); + write_c0_entrylo0(entrylo0); + write_c0_entrylo1(entrylo1); + BARRIER; + tlb_write_indexed(); + BARRIER; + + write_c0_entryhi(old_ctx); + BARRIER; + write_c0_pagemask(old_pagemask); + local_flush_tlb_all(); + local_irq_restore(flags); +} + +/* + * Used for loading TLB entries before trap_init() has started, when we + * don't actually want to add a wired entry which remains throughout the + * lifetime of the system + */ + +static int temp_tlb_entry __initdata; + +__init int add_temporary_entry(unsigned long entrylo0, unsigned long entrylo1, + unsigned long entryhi, unsigned long pagemask) +{ + int ret = 0; + unsigned long flags; + unsigned long wired; + unsigned long old_pagemask; + unsigned long old_ctx; + + local_irq_save(flags); + /* Save old context and create impossible VPN2 value */ + old_ctx = read_c0_entryhi() & ASID_MASK; + old_pagemask = read_c0_pagemask(); + wired = read_c0_wired(); + if (--temp_tlb_entry < wired) { + printk(KERN_WARNING "No TLB space left for add_temporary_entry\n"); + ret = -ENOSPC; + goto out; + } + + write_c0_index(temp_tlb_entry); + BARRIER; + write_c0_pagemask(pagemask); + write_c0_entryhi(entryhi); + write_c0_entrylo0(entrylo0); + write_c0_entrylo1(entrylo1); + BARRIER; + tlb_write_indexed(); + BARRIER; + + write_c0_entryhi(old_ctx); + BARRIER; + write_c0_pagemask(old_pagemask); +out: + local_irq_restore(flags); + return ret; +} + +static void __init probe_tlb(unsigned long config) +{ + unsigned long config1; + + if (!(config & (1 << 31))) { + /* + * Not a MIPS64 complainant CPU. + * Config 1 register not supported, we assume R4k style. + */ + current_cpu_data.tlbsize = 48; + } else { + config1 = read_c0_config1(); + if (!((config >> 7) & 3)) + panic("No MMU present"); + else + current_cpu_data.tlbsize = ((config1 >> 25) & 0x3f) + 1; + } + + printk("Number of TLB entries %d.\n", current_cpu_data.tlbsize); +} + +void __init r4k_tlb_init(void) +{ + unsigned long config = read_c0_config(); + + probe_tlb(config); + write_c0_pagemask(PM_4K); + write_c0_wired(0); + temp_tlb_entry = current_cpu_data.tlbsize - 1; + local_flush_tlb_all(); + + memcpy((void *)(KSEG0 + 0x80), except_vec1_r4k, 0x80); + flush_icache_range(KSEG0, KSEG0 + 0x80); +} diff -Nru a/arch/mips64/mm/tlb-sb1.c b/arch/mips64/mm/tlb-sb1.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips64/mm/tlb-sb1.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,342 @@ +/* + * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) + * Copyright (C) 1997, 2001 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 2000, 2001 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#include +#include +#include +#include + +extern void except_vec1_sb1(void); + +/* Dump the current entry* and pagemask registers */ +static inline void dump_cur_tlb_regs(void) +{ + unsigned int entryhihi, entryhilo, entrylo0hi, entrylo0lo, entrylo1hi; + unsigned int entrylo1lo, pagemask; + + __asm__ __volatile__ ( + ".set push \n" + ".set noreorder \n" + "#.set mips64 \n" + ".set mips4 \n" + ".set noat \n" + " tlbr \n" + " dmfc0 $1, $10 \n" + " dsrl32 %0, $1, 0 \n" + " sll %1, $1, 0 \n" + " dmfc0 $1, $2 \n" + " dsrl32 %2, $1, 0 \n" + " sll %3, $1, 0 \n" + " dmfc0 $1, $3 \n" + " dsrl32 %4, $1, 0 \n" + " sll %5, $1, 0 \n" + " mfc0 %6, $5 \n" + ".set pop \n" + : "=r" (entryhihi), + "=r" (entryhilo), + "=r" (entrylo0hi), + "=r" (entrylo0lo), + "=r" (entrylo1hi), + "=r" (entrylo1lo), + "=r" (pagemask)); + printk("%08X%08X %08X%08X %08X%08X %08X", + entryhihi, entryhilo, + entrylo0hi, entrylo0lo, + entrylo1hi, entrylo1lo, + pagemask); +} + +void sb1_dump_tlb(void) +{ + unsigned long old_ctx; + unsigned long flags; + int entry; + local_irq_save(flags); + old_ctx = read_c0_entryhi(); + printk("Current TLB registers state:\n" + " EntryHi EntryLo0 EntryLo1 PageMask Index\n" + "--------------------------------------------------------------------\n"); + dump_cur_tlb_regs(); + printk(" %08X\n", read_c0_index()); + printk("\n\nFull TLB Dump:\n" + "Idx EntryHi EntryLo0 EntryLo1 PageMask\n" + "--------------------------------------------------------------\n"); + for (entry = 0; entry < current_cpu_data.tlbsize; entry++) { + write_c0_index(entry); + printk("\n%02i ", entry); + dump_cur_tlb_regs(); + } + printk("\n"); + write_c0_entryhi(old_ctx); + local_irq_restore(flags); +} + +void local_flush_tlb_all(void) +{ + unsigned long flags; + unsigned long old_ctx; + int entry; + + local_irq_save(flags); + /* Save old context and create impossible VPN2 value */ + old_ctx = read_c0_entryhi() & ASID_MASK; + write_c0_entrylo0(0); + write_c0_entrylo1(0); + for (entry = 0; entry < current_cpu_data.tlbsize; entry++) { + write_c0_entryhi(KSEG0 + (PAGE_SIZE << 1) * entry); + write_c0_index(entry); + tlb_write_indexed(); + } + write_c0_entryhi(old_ctx); + local_irq_restore(flags); +} + + +/* + * Use a bogus region of memory (starting at 0) to sanitize the TLB's. + * Use increments of the maximum page size (16MB), and check for duplicate + * entries before doing a given write. Then, when we're safe from collisions + * with the firmware, go back and give all the entries invalid addresses with + * the normal flush routine. + */ +void sb1_sanitize_tlb(void) +{ + int entry; + long addr = 0; + + long inc = 1<<24; /* 16MB */ + /* Save old context and create impossible VPN2 value */ + write_c0_entrylo0(0); + write_c0_entrylo1(0); + for (entry = 0; entry < current_cpu_data.tlbsize; entry++) { + do { + addr += inc; + write_c0_entryhi(addr); + tlb_probe(); + } while ((int)(read_c0_index()) >= 0); + write_c0_index(entry); + tlb_write_indexed(); + } + /* Now that we know we're safe from collisions, we can safely flush + the TLB with the "normal" routine. */ + local_flush_tlb_all(); +} + +void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, + unsigned long end) +{ + struct mm_struct *mm = vma->vm_mm; + unsigned long flags; + int cpu; + + local_irq_save(flags); + cpu = smp_processor_id(); + if (cpu_context(cpu, mm) != 0) { + int size; + size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + size = (size + 1) >> 1; + if (size <= (current_cpu_data.tlbsize/2)) { + int oldpid = read_c0_entryhi() & ASID_MASK; + int newpid = cpu_asid(cpu, mm); + + start &= (PAGE_MASK << 1); + end += ((PAGE_SIZE << 1) - 1); + end &= (PAGE_MASK << 1); + while (start < end) { + int idx; + + write_c0_entryhi(start | newpid); + start += (PAGE_SIZE << 1); + tlb_probe(); + idx = read_c0_index(); + write_c0_entrylo0(0); + write_c0_entrylo1(0); + write_c0_entryhi(KSEG0 + (idx << (PAGE_SHIFT+1))); + if (idx < 0) + continue; + tlb_write_indexed(); + } + write_c0_entryhi(oldpid); + } else { + drop_mmu_context(mm, cpu); + } + } + local_irq_restore(flags); +} + +void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) +{ + unsigned long flags; + int size; + + size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + size = (size + 1) >> 1; + + local_irq_save(flags); + if (size <= (current_cpu_data.tlbsize/2)) { + int pid = read_c0_entryhi(); + + start &= (PAGE_MASK << 1); + end += ((PAGE_SIZE << 1) - 1); + end &= (PAGE_MASK << 1); + + while (start < end) { + int idx; + + write_c0_entryhi(start); + start += (PAGE_SIZE << 1); + tlb_probe(); + idx = read_c0_index(); + write_c0_entrylo0(0); + write_c0_entrylo1(0); + write_c0_entryhi(KSEG0 + (idx << (PAGE_SHIFT+1))); + if (idx < 0) + continue; + tlb_write_indexed(); + } + write_c0_entryhi(pid); + } else { + local_flush_tlb_all(); + } + local_irq_restore(flags); +} + +void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) +{ + unsigned long flags; + int cpu = smp_processor_id(); + + local_irq_save(flags); + if (cpu_context(cpu, vma->vm_mm) != 0) { + int oldpid, newpid, idx; + newpid = cpu_asid(cpu, vma->vm_mm); + page &= (PAGE_MASK << 1); + oldpid = read_c0_entryhi() & ASID_MASK; + write_c0_entryhi(page | newpid); + tlb_probe(); + idx = read_c0_index(); + write_c0_entrylo0(0); + write_c0_entrylo1(0); + if(idx < 0) + goto finish; + /* Make sure all entries differ. */ + write_c0_entryhi(KSEG0+(idx<<(PAGE_SHIFT+1))); + tlb_write_indexed(); + finish: + write_c0_entryhi(oldpid); + } + local_irq_restore(flags); +} + +/* + * This one is only used for pages with the global bit set so we don't care + * much about the ASID. + */ +void local_flush_tlb_one(unsigned long page) +{ + unsigned long flags; + int oldpid, idx; + + local_irq_save(flags); + page &= (PAGE_MASK << 1); + oldpid = read_c0_entryhi() & 0xff; + write_c0_entryhi(page); + tlb_probe(); + idx = read_c0_index(); + write_c0_entrylo0(0); + write_c0_entrylo1(0); + if (idx >= 0) { + /* Make sure all entries differ. */ + write_c0_entryhi(KSEG0+(idx<<(PAGE_SHIFT+1))); + tlb_write_indexed(); + } + write_c0_entryhi(oldpid); + + local_irq_restore(flags); +} + +/* All entries common to a mm share an asid. To effectively flush + these entries, we just bump the asid. */ +void local_flush_tlb_mm(struct mm_struct *mm) +{ + int cpu = smp_processor_id(); + if (cpu_context(cpu, mm) != 0) { + drop_mmu_context(mm, cpu); + } +} + +/* Stolen from mips32 routines */ + +void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte) +{ + unsigned long flags; + pgd_t *pgdp; + pmd_t *pmdp; + pte_t *ptep; + int idx, pid; + + /* + * Handle debugger faulting in for debugee. + */ + if (current->active_mm != vma->vm_mm) + return; + + local_irq_save(flags); + + pid = read_c0_entryhi() & ASID_MASK; + address &= (PAGE_MASK << 1); + write_c0_entryhi(address | (pid)); + pgdp = pgd_offset(vma->vm_mm, address); + tlb_probe(); + pmdp = pmd_offset(pgdp, address); + idx = read_c0_index(); + ptep = pte_offset_map(pmdp, address); + write_c0_entrylo0(pte_val(*ptep++) >> 6); + write_c0_entrylo1(pte_val(*ptep) >> 6); + if (idx < 0) { + tlb_write_random(); + } else { + tlb_write_indexed(); + } + local_irq_restore(flags); +} + +/* + * This is called from loadmmu.c. We have to set up all the + * memory management function pointers, as well as initialize + * the caches and tlbs + */ +void sb1_tlb_init(void) +{ + u32 config1; + + write_c0_pagemask(PM_4K); + config1 = read_c0_config1(); + current_cpu_data.tlbsize = ((config1 >> 25) & 0x3f) + 1; + + /* + * We don't know what state the firmware left the TLB's in, so this is + * the ultra-conservative way to flush the TLB's and avoid machine + * check exceptions due to duplicate TLB entries + */ + sb1_sanitize_tlb(); + + memcpy((void *)KSEG0 + 0x080, except_vec1_sb1, 0x80); + flush_icache_range(KSEG0, KSEG0 + 0x80); +} diff -Nru a/arch/mips64/mm/tlbex-r4k.S b/arch/mips64/mm/tlbex-r4k.S --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/mips64/mm/tlbex-r4k.S Tue Jul 1 18:44:40 2003 @@ -0,0 +1,208 @@ +/* + * 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) 2000 Silicon Graphics, Inc. + * Written by Ulf Carlsson (ulfc@engr.sgi.com) + * Copyright (C) 2002 Maciej W. Rozycki + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + + .data + .comm pgd_current, NR_CPUS * 8, 8 + + /* + * After this macro runs we have a pointer to the pte of the address + * that caused the fault in PTR. + */ + .macro LOAD_PTE2, ptr, tmp, kaddr +#ifdef CONFIG_SMP + dmfc0 \ptr, CP0_CONTEXT + dmfc0 \tmp, CP0_BADVADDR + dsra \ptr, 23 # get pgd_current[cpu] +#else + dmfc0 \tmp, CP0_BADVADDR + dla \ptr, pgd_current +#endif + bltz \tmp, \kaddr + ld \ptr, (\ptr) + dsrl \tmp, (PGDIR_SHIFT-3) # get pgd offset in bytes + andi \tmp, ((PTRS_PER_PGD - 1)<<3) + daddu \ptr, \tmp # add in pgd offset + dmfc0 \tmp, CP0_BADVADDR + ld \ptr, (\ptr) # get pmd pointer + dsrl \tmp, (PMD_SHIFT-3) # get pmd offset in bytes + andi \tmp, ((PTRS_PER_PMD - 1)<<3) + daddu \ptr, \tmp # add in pmd offset + dmfc0 \tmp, CP0_XCONTEXT + ld \ptr, (\ptr) # get pte pointer + andi \tmp, 0xff0 # get pte offset + daddu \ptr, \tmp + .endm + + + /* + * Ditto for the kernel table. + */ + .macro LOAD_KPTE2, ptr, tmp, not_vmalloc + /* + * First, determine that the address is in/above vmalloc range. + */ + dmfc0 \tmp, CP0_BADVADDR + dli \ptr, VMALLOC_START + + /* + * Now find offset into kptbl. + */ + dsubu \tmp, \tmp, \ptr + dla \ptr, kptbl + dsrl \tmp, (PAGE_SHIFT+1) # get vpn2 + dsll \tmp, 4 # byte offset of pte + daddu \ptr, \ptr, \tmp + + /* + * Determine that fault address is within vmalloc range. + */ + dla \tmp, ekptbl + slt \tmp, \ptr, \tmp + beqz \tmp, \not_vmalloc # not vmalloc + nop + .endm + + + /* + * This places the even/odd pte pair in the page table at the pte + * entry pointed to by PTE into ENTRYLO0 and ENTRYLO1. + */ + .macro PTE_RELOAD, pte0, pte1 + dsrl \pte0, 6 # convert to entrylo0 + dmtc0 \pte0, CP0_ENTRYLO0 # load it + dsrl \pte1, 6 # convert to entrylo1 + dmtc0 \pte1, CP0_ENTRYLO1 # load it + .endm + + + .text + .set noreorder + .set mips3 + + __INIT + + .align 5 +LEAF(except_vec0_generic) + .set noat + PANIC("Unused vector called") +1: b 1b + nop +END(except_vec0_generic) + + + /* + * TLB refill handlers for the R4000 and SB1. + * Attention: We may only use 32 instructions / 128 bytes. + */ + .align 5 +LEAF(except_vec1_r4k) + .set noat + dla k0, handle_vec1_r4k + jr k0 + nop +END(except_vec1_r4k) + +LEAF(except_vec1_sb1) +#if BCM1250_M3_WAR + dmfc0 k0, CP0_BADVADDR + dmfc0 k1, CP0_ENTRYHI + xor k0, k1 + dsrl k0, k0, PAGE_SHIFT+1 + bnez k0, 1f +#endif + .set noat + dla k0, handle_vec1_r4k + jr k0 + nop + +1: eret + nop +END(except_vec1_sb1) + + __FINIT + + .align 5 +LEAF(handle_vec1_r4k) + .set noat + LOAD_PTE2 k1 k0 9f + ld k0, 0(k1) # get even pte + ld k1, 8(k1) # get odd pte + PTE_RELOAD k0 k1 + b 1f + tlbwr +1: nop + eret + +9: # handle the vmalloc range + LOAD_KPTE2 k1 k0 invalid_vmalloc_address + ld k0, 0(k1) # get even pte + ld k1, 8(k1) # get odd pte + PTE_RELOAD k0 k1 + b 1f + tlbwr +1: nop + eret +END(handle_vec1_r4k) + + + __INIT + + /* + * TLB refill handler for the R10000. + * Attention: We may only use 32 instructions / 128 bytes. + */ + .align 5 +LEAF(except_vec1_r10k) + .set noat + dla k0, handle_vec1_r10k + jr k0 + nop +END(except_vec1_r10k) + + __FINIT + + .align 5 +LEAF(handle_vec1_r10k) + .set noat + LOAD_PTE2 k1 k0 9f + ld k0, 0(k1) # get even pte + ld k1, 8(k1) # get odd pte + PTE_RELOAD k0 k1 + nop + tlbwr + eret + +9: # handle the vmalloc range + LOAD_KPTE2 k1 k0 invalid_vmalloc_address + ld k0, 0(k1) # get even pte + ld k1, 8(k1) # get odd pte + PTE_RELOAD k0 k1 + nop + tlbwr + eret +END(handle_vec1_r10k) + + + .align 5 +LEAF(invalid_vmalloc_address) + .set noat + PANIC("Invalid kernel address") +1: b 1b + nop +END(invalid_vmalloc_address) diff -Nru a/arch/mips64/mm/umap.c b/arch/mips64/mm/umap.c --- a/arch/mips64/mm/umap.c Tue Jul 1 18:44:32 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,221 +0,0 @@ -/* - * 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 Linus Torvalds - * Copyright (C) 1997 Miguel de Icaza - * Copyright (C) 2001 Ralf Baechle - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -static inline void remove_mapping_pte_range (pmd_t *pmd, unsigned long address, - unsigned long size) -{ - pte_t *pte; - unsigned long end; - - if (pmd_none (*pmd)) - return; - if (pmd_bad (*pmd)){ - printk ("remove_graphics_pte_range: bad pmd (%08lx)\n", - pmd_val (*pmd)); - pmd_clear (pmd); - return; - } - pte = pte_offset (pmd, address); - address &= ~PMD_MASK; - end = address + size; - if (end > PMD_SIZE) - end = PMD_SIZE; - do { - pte_t entry = *pte; - if (pte_present (entry)) - set_pte (pte, pte_modify (entry, PAGE_NONE)); - address += PAGE_SIZE; - pte++; - } while (address < end); - -} - -static inline void remove_mapping_pmd_range (pgd_t *pgd, unsigned long address, - unsigned long size) -{ - pmd_t *pmd; - unsigned long end; - - if (pgd_none (*pgd)) - return; - - if (pgd_bad (*pgd)){ - printk ("remove_graphics_pmd_range: bad pgd (%08lx)\n", - pgd_val (*pgd)); - pgd_clear (pgd); - return; - } - pmd = pmd_offset (pgd, address); - address &= ~PGDIR_MASK; - end = address + size; - if (end > PGDIR_SIZE) - end = PGDIR_SIZE; - do { - remove_mapping_pte_range (pmd, address, end - address); - address = (address + PMD_SIZE) & PMD_MASK; - pmd++; - } while (address < end); - -} - -/* - * This routine is called from the page fault handler to remove a - * range of active mappings at this point - */ -void remove_mapping (struct vm_area_struct *vma, struct task_struct *task, unsigned long start, - unsigned long end) -{ - unsigned long beg = start; - pgd_t *dir; - - down_write (&task->mm->mmap_sem); - dir = pgd_offset (task->mm, start); - flush_cache_range (vma, beg, end); - while (start < end){ - remove_mapping_pmd_range (dir, start, end - start); - start = (start + PGDIR_SIZE) & PGDIR_MASK; - dir++; - } - flush_tlb_range (vma, beg, end); - up_write (&task->mm->mmap_sem); -} - -EXPORT_SYMBOL(remove_mapping); - -void *vmalloc_uncached (unsigned long size) -{ - return __vmalloc (size, GFP_KERNEL | __GFP_HIGHMEM, - PAGE_KERNEL_UNCACHED); -} - -static inline void free_pte(pte_t page) -{ - if (pte_present(page)) { - unsigned long pfn = pte_pfn(page); - struct page *ptpage; - if (!pfn_valid(pfn)) - return; - ptpage = pfn_to_page(pfn); - if (PageReserved(ptpage)) - return; - __free_page(ptpage); - if (current->mm->rss <= 0) - return; - current->mm->rss--; - return; - } - swap_free(pte_to_swp_entry(page)); -} - -static inline void forget_pte(pte_t page) -{ - if (!pte_none(page)) { - printk("forget_pte: old mapping existed!\n"); - free_pte(page); - } -} - -/* - * maps a range of vmalloc()ed memory into the requested pages. the old - * mappings are removed. - */ -static inline void vmap_pte_range (pte_t *pte, unsigned long address, - unsigned long size, unsigned long vaddr) -{ - unsigned long end; - pgd_t *vdir; - pmd_t *vpmd; - pte_t *vpte; - - address &= ~PMD_MASK; - end = address + size; - if (end > PMD_SIZE) - end = PMD_SIZE; - do { - pte_t oldpage = *pte; - struct page * page; - pte_clear(pte); - - vdir = pgd_offset_k (vaddr); - vpmd = pmd_offset (vdir, vaddr); - vpte = pte_offset (vpmd, vaddr); - page = pte_page (*vpte); - - set_pte(pte, mk_pte(page, PAGE_USERIO)); - forget_pte(oldpage); - address += PAGE_SIZE; - vaddr += PAGE_SIZE; - pte++; - } while (address < end); -} - -static inline int vmap_pmd_range (pmd_t *pmd, unsigned long address, - unsigned long size, unsigned long vaddr) -{ - unsigned long end; - - address &= ~PGDIR_MASK; - end = address + size; - if (end > PGDIR_SIZE) - end = PGDIR_SIZE; - vaddr -= address; - do { - pte_t * pte = pte_alloc(current->mm, pmd, address); - if (!pte) - return -ENOMEM; - vmap_pte_range(pte, address, end - address, address + vaddr); - address = (address + PMD_SIZE) & PMD_MASK; - pmd++; - } while (address < end); - return 0; -} - -int vmap_page_range (struct vm_area_struct *vma, unsigned long from, unsigned long size, - unsigned long vaddr) -{ - int error = 0; - pgd_t * dir; - unsigned long beg = from; - unsigned long end = from + size; - - vaddr -= from; - dir = pgd_offset(current->mm, from); - flush_cache_range(vma, beg, end); - while (from < end) { - pmd_t *pmd = pmd_alloc(current->mm, dir, from); - error = -ENOMEM; - if (!pmd) - break; - error = vmap_pmd_range(pmd, from, end - from, vaddr + from); - if (error) - break; - from = (from + PGDIR_SIZE) & PGDIR_MASK; - dir++; - } - flush_tlb_range(vma, beg, end); - return error; -} diff -Nru a/arch/mips64/sgi-ip22/Makefile b/arch/mips64/sgi-ip22/Makefile --- a/arch/mips64/sgi-ip22/Makefile Tue Jul 1 18:44:31 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,9 +0,0 @@ -# -# Makefile for the SGI specific kernel interface routines -# under Linux. -# - -EXTRA_AFLAGS := $(CFLAGS) - -lib-y += ip22-berr.o ip22-mc.o ip22-sc.o ip22-hpc.o ip22-int.o ip22-rtc.o \ - ip22-setup.o system.o ip22-timer.o ip22-irq.o ip22-reset.o time.o diff -Nru a/arch/mips64/sgi-ip22/ip22-berr.c b/arch/mips64/sgi-ip22/ip22-berr.c --- a/arch/mips64/sgi-ip22/ip22-berr.c Tue Jul 1 18:44:35 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,125 +0,0 @@ -/* - * 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, 1995, 1996, 1999, 2000 by Ralf Baechle - * Copyright (C) 1999, 2000 by Silicon Graphics - */ -#include -#include -#include - -#include -#include -#include -#include -#include - -extern asmlinkage void handle_ibe(void); -extern asmlinkage void handle_dbe(void); - -extern const struct exception_table_entry __start___dbe_table[]; -extern const struct exception_table_entry __stop___dbe_table[]; - -static inline unsigned long -search_one_table(const struct exception_table_entry *first, - const struct exception_table_entry *last, - unsigned long value) -{ - while (first <= last) { - const struct exception_table_entry *mid; - long diff; - - mid = (last - first) / 2 + first; - diff = mid->insn - value; - if (diff == 0) - return mid->nextinsn; - else if (diff < 0) - first = mid+1; - else - last = mid-1; - } - return 0; -} - -extern spinlock_t modlist_lock; - -static inline unsigned long -search_dbe_table(unsigned long addr) -{ - unsigned long ret = 0; - -#ifndef CONFIG_MODULES - /* There is only the kernel to search. */ - ret = search_one_table(__start___dbe_table, __stop___dbe_table-1, addr); - return ret; -#else - unsigned long flags; - - /* The kernel is the last "module" -- no need to treat it special. */ - struct module *mp; - struct archdata *ap; - - spin_lock_irqsave(&modlist_lock, flags); - for (mp = module_list; mp != NULL; mp = mp->next) { - if (!mod_member_present(mp, archdata_end) || - !mod_archdata_member_present(mp, struct archdata, - dbe_table_end)) - continue; - ap = (struct archdata *)(mod->archdata_start); - - if (ap->dbe_table_start == NULL || - !(mp->flags & (MOD_RUNNING | MOD_INITIALIZING))) - continue; - ret = search_one_table(ap->dbe_table_start, - ap->dbe_table_end - 1, addr); - if (ret) - break; - } - spin_unlock_irqrestore(&modlist_lock, flags); - return ret; -#endif -} - -void do_ibe(struct pt_regs *regs) -{ - printk("Got ibe at 0x%lx\n", regs->cp0_epc); - show_regs(regs); - dump_tlb_addr(regs->cp0_epc); - force_sig(SIGBUS, current); - while(1); -} - -void do_dbe(struct pt_regs *regs) -{ - unsigned long fixup; - - fixup = search_dbe_table(regs->cp0_epc); - if (fixup) { - long new_epc; - - new_epc = fixup_exception(dpf_reg, fixup, regs->cp0_epc); - regs->cp0_epc = new_epc; - return; - } - - printk("Got dbe at 0x%lx\n", regs->cp0_epc); - show_regs(regs); - dump_tlb_all(); - while(1); - force_sig(SIGBUS, current); -} - -void __init -bus_error_init(void) -{ - int dummy; - - set_except_vector(6, handle_ibe); - set_except_vector(7, handle_dbe); - - /* At this time nothing uses the DBE protection mechanism on the - Indy, so this here is needed to make the kernel link. */ - get_dbe(dummy, (int *)KSEG0); -} diff -Nru a/arch/mips64/sgi-ip22/ip22-hpc.c b/arch/mips64/sgi-ip22/ip22-hpc.c --- a/arch/mips64/sgi-ip22/ip22-hpc.c Tue Jul 1 18:44:39 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,104 +0,0 @@ -/* - * ip22-hpc.c: Routines for generic manipulation of the HPC controllers. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * Copyright (C) 1998, 1999, 2001 Ralf Baechle - */ -#include -#include - -#include -#include -#include -#include - -#undef DEBUG_SGIHPC - -struct hpc3_regs *hpc3c0, *hpc3c1; -struct hpc3_miscregs *hpc3mregs; - -/* We need software copies of these because they are write only. */ -unsigned int sgi_hpc_write1, sgi_hpc_write2; - -/* Machine specific identifier knobs. */ -int sgi_has_ioc2 = 0; -int sgi_guiness = 0; -int sgi_boardid; - -void __init sgihpc_init(void) -{ - unsigned long sid, crev, brev; - - hpc3c0 = (struct hpc3_regs *) (KSEG1 + HPC3_CHIP0_PBASE); - hpc3c1 = (struct hpc3_regs *) (KSEG1 + HPC3_CHIP1_PBASE); - hpc3mregs = (struct hpc3_miscregs *) (KSEG1 + HPC3_MREGS_PBASE); - sid = hpc3mregs->sysid; - - sid &= 0xff; - crev = (sid & 0xe0) >> 5; - brev = (sid & 0x1e) >> 1; - -#ifdef DEBUG_SGIHPC - prom_printf("sgihpc_init: crev<%2x> brev<%2x>\n", crev, brev); - prom_printf("sgihpc_init: "); -#endif - - /* This test works now thanks to William J. Earl */ - if ((sid & 1) == 0 ) { -#ifdef DEBUG_SGIHPC - prom_printf("GUINESS "); -#endif - sgi_guiness = 1; - mips_machtype = MACH_SGI_INDY; - } else { -#ifdef DEBUG_SGIHPC - prom_printf("FULLHOUSE "); -#endif - mips_machtype = MACH_SGI_INDIGO2; - sgi_guiness = 0; - } - sgi_boardid = brev; - -#ifdef DEBUG_SGIHPC - prom_printf("sgi_boardid<%d> ", sgi_boardid); -#endif - - if(crev == 1) { - if((sid & 1) || (brev >= 2)) { -#ifdef DEBUG_SGIHPC - prom_printf("IOC2 "); -#endif - sgi_has_ioc2 = 1; - } else { -#ifdef DEBUG_SGIHPC - prom_printf("IOC1 revision 1 "); -#endif - } - } else { -#ifdef DEBUG_SGIHPC - prom_printf("IOC1 revision 0 "); -#endif - } -#ifdef DEBUG_SGIHPC - prom_printf("\n"); -#endif - - sgi_hpc_write1 = (HPC3_WRITE1_PRESET | - HPC3_WRITE1_KMRESET | - HPC3_WRITE1_ERESET | - HPC3_WRITE1_LC0OFF); - - sgi_hpc_write2 = (HPC3_WRITE2_EASEL | - HPC3_WRITE2_NTHRESH | - HPC3_WRITE2_TPSPEED | - HPC3_WRITE2_EPSEL | - HPC3_WRITE2_U0AMODE | - HPC3_WRITE2_U1AMODE); - - if(!sgi_guiness) - sgi_hpc_write1 |= HPC3_WRITE1_GRESET; - hpc3mregs->write1 = sgi_hpc_write1; - hpc3mregs->write2 = sgi_hpc_write2; - - hpc3c0->pbus_piocfgs[0][6] |= HPC3_PIOPCFG_HW; -} diff -Nru a/arch/mips64/sgi-ip22/ip22-int.c b/arch/mips64/sgi-ip22/ip22-int.c --- a/arch/mips64/sgi-ip22/ip22-int.c Tue Jul 1 18:44:32 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,616 +0,0 @@ -/* - * indy_int.c: Routines for generic manipulation of the INT[23] ASIC - * found on INDY workstations.. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * Copyright (C) 1997, 1998 Ralf Baechle (ralf@gnu.org) - * Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu) - Indigo2 changes - */ -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/* - * Linux has a controller-independent x86 interrupt architecture. - * every controller has a 'controller-template', that is used - * by the main code to do the right thing. Each driver-visible - * interrupt source is transparently wired to the apropriate - * controller. Thus drivers need not be aware of the - * interrupt-controller. - * - * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC, - * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC. - * (IO-APICs assumed to be messaging to Pentium local-APICs) - * - * the code is designed to be easily extended with new/different - * interrupt controllers, without having to do assembly magic. - */ - -struct sgi_int2_regs *sgi_i2regs; -struct sgi_int3_regs *sgi_i3regs; -struct sgi_ioc_ints *ioc_icontrol; -struct sgi_ioc_timers *ioc_timers; -volatile unsigned char *ioc_tclear; - -static char lc0msk_to_irqnr[256]; -static char lc1msk_to_irqnr[256]; -static char lc2msk_to_irqnr[256]; -static char lc3msk_to_irqnr[256]; - -extern asmlinkage void indyIRQ(void); - -#ifdef CONFIG_REMOTE_DEBUG -extern void rs_kgdb_hook(int); -#endif - -unsigned long spurious_count = 0; - -/* Local IRQ's are layed out logically like this: - * - * 0 --> 7 == local 0 interrupts - * 8 --> 15 == local 1 interrupts - * 16 --> 23 == vectored level 2 interrupts - * 24 --> 31 == vectored level 3 interrupts (not used) - */ -void disable_local_irq(unsigned int irq_nr) -{ - unsigned long flags; - - save_and_cli(flags); - switch(irq_nr) { - case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: - ioc_icontrol->imask0 &= ~(1 << irq_nr); - break; - - case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: - ioc_icontrol->imask1 &= ~(1 << (irq_nr - 8)); - break; - - case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23: - ioc_icontrol->cmeimask0 &= ~(1 << (irq_nr - 16)); - break; - - default: - /* This way we'll see if anyone would ever want vectored - * level 3 interrupts. Highly unlikely. - */ - printk("Yeeee, got passed irq_nr %d at disable_irq\n", irq_nr); - panic("INVALID IRQ level!"); - }; - restore_flags(flags); -} - -void enable_local_irq(unsigned int irq_nr) -{ - unsigned long flags; - save_and_cli(flags); - switch(irq_nr) { - case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: - ioc_icontrol->imask0 |= (1 << irq_nr); - break; - - case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: - ioc_icontrol->imask1 |= (1 << (irq_nr - 8)); - break; - - case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23: - enable_local_irq(7); - ioc_icontrol->cmeimask0 |= (1 << (irq_nr - 16)); - break; - - default: - printk("Yeeee, got passed irq_nr %d at disable_irq\n", irq_nr); - panic("INVALID IRQ level!"); - }; - restore_flags(flags); -} - -void disable_gio_irq(unsigned int irq_nr) -{ - /* XXX TODO XXX */ -} - -void enable_gio_irq(unsigned int irq_nr) -{ - /* XXX TODO XXX */ -} - -void disable_hpcdma_irq(unsigned int irq_nr) -{ - /* XXX TODO XXX */ -} - -void enable_hpcdma_irq(unsigned int irq_nr) -{ - /* XXX TODO XXX */ -} - -void disable_irq(unsigned int irq_nr) -{ - unsigned int n = irq_nr; - if(n >= SGINT_END) { - printk("whee, invalid irq_nr %d\n", irq_nr); - panic("IRQ, you lose..."); - } - if(n >= SGINT_LOCAL0 && n < SGINT_GIO) { - disable_local_irq(n - SGINT_LOCAL0); - } else if(n >= SGINT_GIO && n < SGINT_HPCDMA) { - disable_gio_irq(n - SGINT_GIO); - } else if(n >= SGINT_HPCDMA && n < SGINT_END) { - disable_hpcdma_irq(n - SGINT_HPCDMA); - } else { - panic("how did I get here?"); - } -} - -void enable_irq(unsigned int irq_nr) -{ - unsigned int n = irq_nr; - if(n >= SGINT_END) { - printk("whee, invalid irq_nr %d\n", irq_nr); - panic("IRQ, you lose..."); - } - if(n >= SGINT_LOCAL0 && n < SGINT_GIO) { - enable_local_irq(n - SGINT_LOCAL0); - } else if(n >= SGINT_GIO && n < SGINT_HPCDMA) { - enable_gio_irq(n - SGINT_GIO); - } else if(n >= SGINT_HPCDMA && n < SGINT_END) { - enable_hpcdma_irq(n - SGINT_HPCDMA); - } else { - panic("how did I get here?"); - } -} - -#if 0 -/* - * Currently unused. - */ -static void local_unex(int irq, void *data, struct pt_regs *regs) -{ - printk("Whee: unexpected local IRQ at %08lx\n", - (unsigned long) regs->cp0_epc); - printk("DUMP: stat0<%x> stat1<%x> vmeistat<%x>\n", - ioc_icontrol->istat0, ioc_icontrol->istat1, - ioc_icontrol->vmeistat); -} -#endif - -static struct irqaction *local_irq_action[24] = { - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL -}; - -int setup_indy_irq(int irq, struct irqaction * new) -{ - printk("setup_indy_irq: Yeee, don't know how to setup irq<%d> for %s %p\n", - irq, new->name, new->handler); - return 0; -} - -static struct irqaction r4ktimer_action = { - NULL, 0, 0, "R4000 timer/counter", NULL, NULL, -}; - -static struct irqaction indy_berr_action = { - NULL, 0, 0, "IP22 Bus Error", NULL, NULL, -}; - -static struct irqaction *irq_action[16] = { - NULL, NULL, NULL, NULL, - NULL, NULL, &indy_berr_action, &r4ktimer_action, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL -}; - -int show_interrupts(struct seq_file *p, void *v) -{ - int i; - int num = 0; - struct irqaction * action; - unsigned long flags; - - for (i = 0 ; i < 16 ; i++, num++) { - local_irq_save(flags); - action = irq_action[i]; - if (!action) - goto skip_1; - seq_printf(p, "%2d: %8d %c %s", - num, kstat_cpu(0).irqs[num], - (action->flags & SA_INTERRUPT) ? '+' : ' ', - action->name); - for (action=action->next; action; action = action->next) { - seq_printf(p, ",%s %s", - (action->flags & SA_INTERRUPT) ? " +" : "", - action->name); - } - seq_puts(p, " [on-chip]\n"); -skip_1: - local_irq_restore(flags); - } - for (i = 0 ; i < 24 ; i++, num++) { - local_irq_save(flags); - action = local_irq_action[i]; - if (!action) - goto skip_2; - seq_printf(p, "%2d: %8d %c %s", - num, kstat_cpu(0).irqs[num], - (action->flags & SA_INTERRUPT) ? '+' : ' ', - action->name); - for (action=action->next; action; action = action->next) { - seq_printf(p, ",%s %s", - (action->flags & SA_INTERRUPT) ? " +" : "", - action->name); - } - seq_puts(p, " [local]\n"); -skip_2: - local_irq_restore(flags); - } - return 0; -} - -/* - * do_IRQ handles IRQ's that have been installed without the - * SA_INTERRUPT flag: it uses the full signal-handling return - * and runs with other interrupts enabled. All relatively slow - * IRQ's should use this format: notably the keyboard/timer - * routines. - */ -asmlinkage void do_IRQ(int irq, struct pt_regs * regs) -{ - struct irqaction *action; - int do_random, cpu; - - cpu = smp_processor_id(); - irq_enter(cpu, irq); - kstat_cpu(0).irqs[irq]++; - - panic(KERN_DEBUG "Got irq %d, press a key.", irq); - - /* - * mask and ack quickly, we don't want the irq controller - * thinking we're snobs just because some other CPU has - * disabled global interrupts (we have already done the - * INT_ACK cycles, it's too late to try to pretend to the - * controller that we aren't taking the interrupt). - * - * Commented out because we've already done this in the - * machinespecific part of the handler. It's reasonable to - * do this here in a highlevel language though because that way - * we could get rid of a good part of duplicated code ... - */ - /* mask_and_ack_irq(irq); */ - - action = *(irq + irq_action); - if (action) { - if (!(action->flags & SA_INTERRUPT)) - local_irq_enable(); - action = *(irq + irq_action); - do_random = 0; - do { - do_random |= action->flags; - action->handler(irq, action->dev_id, regs); - action = action->next; - } while (action); - if (do_random & SA_SAMPLE_RANDOM) - add_interrupt_randomness(irq); - local_irq_disable(); - } - irq_exit(cpu, irq); - - /* unmasking and bottom half handling is done magically for us. */ -} - -int request_local_irq(unsigned int lirq, void (*func)(int, void *, struct pt_regs *), - unsigned long iflags, const char *dname, void *devid) -{ - struct irqaction *action; - - lirq -= SGINT_LOCAL0; - if(lirq >= 24 || !func) - return -EINVAL; - - action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL); - if(!action) - return -ENOMEM; - - action->handler = func; - action->flags = iflags; - action->mask = 0; - action->name = dname; - action->dev_id = devid; - action->next = 0; - local_irq_action[lirq] = action; - enable_irq(lirq + SGINT_LOCAL0); - return 0; -} - -void free_local_irq(unsigned int lirq, void *dev_id) -{ - struct irqaction *action; - - lirq -= SGINT_LOCAL0; - if(lirq >= 24) { - printk("Aieee: trying to free bogus local irq %d\n", - lirq + SGINT_LOCAL0); - return; - } - action = local_irq_action[lirq]; - local_irq_action[lirq] = NULL; - disable_irq(lirq + SGINT_LOCAL0); - kfree(action); -} - -int request_irq(unsigned int irq, - void (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, - const char * devname, - void *dev_id) -{ - int retval; - struct irqaction * action; - - if (irq >= SGINT_END) - return -EINVAL; - if (!handler) - return -EINVAL; - - if((irq >= SGINT_LOCAL0) && (irq < SGINT_GIO)) - return request_local_irq(irq, handler, irqflags, devname, dev_id); - - action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL); - if (!action) - return -ENOMEM; - - action->handler = handler; - action->flags = irqflags; - action->mask = 0; - action->name = devname; - action->next = NULL; - action->dev_id = dev_id; - - retval = setup_indy_irq(irq, action); - - if (retval) - kfree(action); - return retval; -} - -void free_irq(unsigned int irq, void *dev_id) -{ - struct irqaction * action, **p; - unsigned long flags; - - if (irq >= SGINT_END) { - printk("Trying to free IRQ%d\n",irq); - return; - } - if((irq >= SGINT_LOCAL0) && (irq < SGINT_GIO)) { - free_local_irq(irq, dev_id); - return; - } - for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) { - if (action->dev_id != dev_id) - continue; - - /* Found it - now free it */ - save_and_cli(flags); - *p = action->next; - restore_flags(flags); - kfree(action); - return; - } - printk("Trying to free free IRQ%d\n",irq); -} - -void indy_local0_irqdispatch(struct pt_regs *regs) -{ - struct irqaction *action; - unsigned char mask = ioc_icontrol->istat0; - unsigned char mask2 = 0; - int irq, cpu = smp_processor_id();; - - mask &= ioc_icontrol->imask0; - if(mask & ISTAT0_LIO2) { - mask2 = ioc_icontrol->vmeistat; - mask2 &= ioc_icontrol->cmeimask0; - irq = lc2msk_to_irqnr[mask2]; - action = local_irq_action[irq]; - } else { - irq = lc0msk_to_irqnr[mask]; - action = local_irq_action[irq]; - } - - irq_enter(cpu, irq); - kstat_cpu(0).irqs[irq + 16]++; - action->handler(irq, action->dev_id, regs); - irq_exit(cpu, irq); -} - -void indy_local1_irqdispatch(struct pt_regs *regs) -{ - struct irqaction *action; - unsigned char mask = ioc_icontrol->istat1; - unsigned char mask2 = 0; - int irq, cpu = smp_processor_id();; - - mask &= ioc_icontrol->imask1; - if(mask & ISTAT1_LIO3) { - printk("WHee: Got an LIO3 irq, winging it...\n"); - mask2 = ioc_icontrol->vmeistat; - mask2 &= ioc_icontrol->cmeimask1; - irq = lc3msk_to_irqnr[ioc_icontrol->vmeistat]; - action = local_irq_action[irq]; - } else { - irq = lc1msk_to_irqnr[mask]; - action = local_irq_action[irq]; - } - irq_enter(cpu, irq); - kstat_cpu(0).irqs[irq + 24]++; - action->handler(irq, action->dev_id, regs); - irq_exit(cpu, irq); -} - -void indy_buserror_irq(struct pt_regs *regs) -{ - int cpu = smp_processor_id(); - int irq = 6; - - irq_enter(cpu, irq); - kstat_cpu(0).irqs[irq]++; - printk("Got a bus error IRQ, shouldn't happen yet\n"); - show_regs(regs); - printk("Spinning...\n"); - while(1); - irq_exit(cpu, irq); -} - -/* Misc. crap just to keep the kernel linking... */ -unsigned long probe_irq_on (void) -{ - return 0; -} - -int probe_irq_off (unsigned long irqs) -{ - return 0; -} - -static inline void sgint_init(void) -{ - int i; -#ifdef CONFIG_REMOTE_DEBUG - char *ctype; -#endif - - sgi_i2regs = (struct sgi_int2_regs *) (KSEG1 + SGI_INT2_BASE); - sgi_i3regs = (struct sgi_int3_regs *) (KSEG1 + SGI_INT3_BASE); - - /* Init local mask --> irq tables. */ - for(i = 0; i < 256; i++) { - if(i & 0x80) { - lc0msk_to_irqnr[i] = 7; - lc1msk_to_irqnr[i] = 15; - lc2msk_to_irqnr[i] = 23; - lc3msk_to_irqnr[i] = 31; - } else if(i & 0x40) { - lc0msk_to_irqnr[i] = 6; - lc1msk_to_irqnr[i] = 14; - lc2msk_to_irqnr[i] = 22; - lc3msk_to_irqnr[i] = 30; - } else if(i & 0x20) { - lc0msk_to_irqnr[i] = 5; - lc1msk_to_irqnr[i] = 13; - lc2msk_to_irqnr[i] = 21; - lc3msk_to_irqnr[i] = 29; - } else if(i & 0x10) { - lc0msk_to_irqnr[i] = 4; - lc1msk_to_irqnr[i] = 12; - lc2msk_to_irqnr[i] = 20; - lc3msk_to_irqnr[i] = 28; - } else if(i & 0x08) { - lc0msk_to_irqnr[i] = 3; - lc1msk_to_irqnr[i] = 11; - lc2msk_to_irqnr[i] = 19; - lc3msk_to_irqnr[i] = 27; - } else if(i & 0x04) { - lc0msk_to_irqnr[i] = 2; - lc1msk_to_irqnr[i] = 10; - lc2msk_to_irqnr[i] = 18; - lc3msk_to_irqnr[i] = 26; - } else if(i & 0x02) { - lc0msk_to_irqnr[i] = 1; - lc1msk_to_irqnr[i] = 9; - lc2msk_to_irqnr[i] = 17; - lc3msk_to_irqnr[i] = 25; - } else if(i & 0x01) { - lc0msk_to_irqnr[i] = 0; - lc1msk_to_irqnr[i] = 8; - lc2msk_to_irqnr[i] = 16; - lc3msk_to_irqnr[i] = 24; - } else { - lc0msk_to_irqnr[i] = 0; - lc1msk_to_irqnr[i] = 0; - lc2msk_to_irqnr[i] = 0; - lc3msk_to_irqnr[i] = 0; - } - } - - /* Indy uses an INT3, Indigo2 uses an INT2 */ - if (sgi_guiness) { - ioc_icontrol = &sgi_i3regs->ints; - ioc_timers = &sgi_i3regs->timers; - ioc_tclear = &sgi_i3regs->tclear; - } else { - ioc_icontrol = &sgi_i2regs->ints; - ioc_timers = &sgi_i2regs->timers; - ioc_tclear = &sgi_i2regs->tclear; - } - - /* Mask out all interrupts. */ - ioc_icontrol->imask0 = 0; - ioc_icontrol->imask1 = 0; - ioc_icontrol->cmeimask0 = 0; - ioc_icontrol->cmeimask1 = 0; - - /* Now safe to set the exception vector. */ - set_except_vector(0, indyIRQ); - -#ifdef CONFIG_REMOTE_DEBUG - ctype = prom_getcmdline(); - for(i = 0; i < strlen(ctype); i++) { - if(ctype[i]=='k' && ctype[i+1]=='g' && - ctype[i+2]=='d' && ctype[i+3]=='b' && - ctype[i+4]=='=' && ctype[i+5]=='t' && - ctype[i+6]=='t' && ctype[i+7]=='y' && - ctype[i+8]=='d' && - (ctype[i+9] == '1' || ctype[i+9] == '2')) { - printk("KGDB: Using serial line /dev/ttyd%d for " - "session\n", (ctype[i+9] - '0')); - if(ctype[i+9]=='1') - rs_kgdb_hook(1); - else if(ctype[i+9]=='2') - rs_kgdb_hook(0); - else { - printk("KGDB: whoops bogon tty line " - "requested, disabling session\n"); - } - - } - } -#endif -} - -void __init init_IRQ(void) -{ - sgint_init(); -} diff -Nru a/arch/mips64/sgi-ip22/ip22-irq.S b/arch/mips64/sgi-ip22/ip22-irq.S --- a/arch/mips64/sgi-ip22/ip22-irq.S Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,128 +0,0 @@ -/* - * 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. - * - * indyIRQ.S: Interrupt exception dispatch code for FullHouse and - * Guiness. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - */ -#include -#include -#include -#include - -/* A lot of complication here is taken away because: - * - * 1) We handle one interrupt and return, sitting in a loop and moving across - * all the pending IRQ bits in the cause register is _NOT_ the answer, the - * common case is one pending IRQ so optimize in that direction. - * - * 2) We need not check against bits in the status register IRQ mask, that - * would make this routine slow as hell. - * - * 3) Linux only thinks in terms of all IRQs on or all IRQs off, nothing in - * between like BSD spl() brain-damage. - * - * Furthermore, the IRQs on the INDY look basically (barring software IRQs - * which we don't use at all) like: - * - * MIPS IRQ Source - * -------- ------ - * 0 Software (ignored) - * 1 Software (ignored) - * 2 Local IRQ level zero - * 3 Local IRQ level one - * 4 8254 Timer zero - * 5 8254 Timer one - * 6 Bus Error - * 7 R4k timer (what we use) - * - * We handle the IRQ according to _our_ priority which is: - * - * Highest ---- R4k Timer - * Local IRQ zero - * Local IRQ one - * Bus Error - * 8254 Timer zero - * Lowest ---- 8254 Timer one - * - * then we just return, if multiple IRQs are pending then we will just take - * another exception, big deal. - */ - - .text - .set noreorder - .set noat - .align 5 - NESTED(indyIRQ, PT_SIZE, sp) - SAVE_ALL - CLI - .set at - mfc0 s0, CP0_CAUSE # get irq mask - - /* First we check for r4k counter/timer IRQ. */ - andi a0, s0, CAUSEF_IP7 - beq a0, zero, 1f - andi a0, s0, CAUSEF_IP2 # delay slot, check local level zero - - /* Wheee, a timer interrupt. */ - move a0, sp - jal indy_timer_interrupt - nop # delay slot - - j ret_from_irq - nop # delay slot - -1: - beq a0, zero, 1f - andi a0, s0, CAUSEF_IP3 # delay slot, check local level one - - /* Wheee, local level zero interrupt. */ - jal indy_local0_irqdispatch - move a0, sp # delay slot - - j ret_from_irq - nop # delay slot - -1: - beq a0, zero, 1f - andi a0, s0, CAUSEF_IP6 # delay slot, check bus error - - /* Wheee, local level one interrupt. */ - move a0, sp - jal indy_local1_irqdispatch - nop - - j ret_from_irq - nop - -1: - beq a0, zero, 1f - nop - - /* Wheee, an asynchronous bus error... */ - move a0, sp - jal indy_buserror_irq - nop - - j ret_from_irq - nop - -1: - /* Here by mistake? This is possible, what can happen - * is that by the time we take the exception the IRQ - * pin goes low, so just leave if this is the case. - */ - andi a0, s0, (CAUSEF_IP4 | CAUSEF_IP5) - beq a0, zero, 1f - - /* Must be one of the 8254 timers... */ - move a0, sp - jal indy_8254timer_irq - nop -1: - j ret_from_irq - nop - END(indyIRQ) diff -Nru a/arch/mips64/sgi-ip22/ip22-mc.c b/arch/mips64/sgi-ip22/ip22-mc.c --- a/arch/mips64/sgi-ip22/ip22-mc.c Tue Jul 1 18:44:38 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,158 +0,0 @@ -/* - * 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) 1996 David S. Miller (dm@engr.sgi.com) - * Copyright (C) 2001 Ralf Baechle (ralf@gnu.org) - */ -#include -#include - -#include -#include -#include -#include - -/* #define DEBUG_SGIMC */ - -struct sgimc_misc_ctrl *mcmisc_regs; -u32 *rpsscounter; -struct sgimc_dma_ctrl *dmactrlregs; - -static inline char *mconfig_string(unsigned long val) -{ - switch(val & SGIMC_MCONFIG_RMASK) { - case SGIMC_MCONFIG_FOURMB: - return "4MB"; - - case SGIMC_MCONFIG_EIGHTMB: - return "8MB"; - - case SGIMC_MCONFIG_SXTEENMB: - return "16MB"; - - case SGIMC_MCONFIG_TTWOMB: - return "32MB"; - - case SGIMC_MCONFIG_SFOURMB: - return "64MB"; - - case SGIMC_MCONFIG_OTEIGHTMB: - return "128MB"; - - default: - return "wheee, unknown"; - }; -} - -void __init sgimc_init(void) -{ - unsigned long tmpreg; - - mcmisc_regs = (struct sgimc_misc_ctrl *)(KSEG1+0x1fa00000); - rpsscounter = (u32 *) (KSEG1 + 0x1fa01004); - dmactrlregs = (struct sgimc_dma_ctrl *) (KSEG1+0x1fa02000); - - printk("MC: SGI memory controller Revision %d\n", - (int) mcmisc_regs->systemid & SGIMC_SYSID_MASKREV); - -#if 0 /* XXX Until I figure out what this bit really indicates XXX */ - /* XXX Is this systemid bit reliable? */ - if(mcmisc_regs->systemid & SGIMC_SYSID_EPRESENT) { - EISA_bus = 1; - printk("with EISA\n"); - } else { - EISA_bus = 0; - printk("no EISA\n"); - } -#endif - -#ifdef DEBUG_SGIMC - prom_printf("sgimc_init: memconfig0<%s> mconfig1<%s>\n", - mconfig_string(mcmisc_regs->mconfig0), - mconfig_string(mcmisc_regs->mconfig1)); - - prom_printf("mcdump: cpuctrl0<%08lx> cpuctrl1<%08lx>\n", - mcmisc_regs->cpuctrl0, mcmisc_regs->cpuctrl1); - prom_printf("mcdump: divider<%08lx>, gioparm<%04x>\n", - mcmisc_regs->divider, mcmisc_regs->gioparm); -#endif - - /* Place the MC into a known state. This must be done before - * interrupts are first enabled etc. - */ - - /* Step 1: The CPU/GIO error status registers will not latch - * up a new error status until the register has been - * cleared by the cpu. These status registers are - * cleared by writing any value to them. - */ - mcmisc_regs->cstat = mcmisc_regs->gstat = 0; - - /* Step 2: Enable all parity checking in cpu control register - * zero. - */ - tmpreg = mcmisc_regs->cpuctrl0; - tmpreg |= (SGIMC_CCTRL0_EPERRGIO | SGIMC_CCTRL0_EPERRMEM | - SGIMC_CCTRL0_R4KNOCHKPARR); - mcmisc_regs->cpuctrl0 = tmpreg; - - /* Step 3: Setup the MC write buffer depth, this is controlled - * in cpu control register 1 in the lower 4 bits. - */ - tmpreg = mcmisc_regs->cpuctrl1; - tmpreg &= ~0xf; - tmpreg |= 0xd; - mcmisc_regs->cpuctrl1 = tmpreg; - - /* Step 4: Initialize the RPSS divider register to run as fast - * as it can correctly operate. The register is laid - * out as follows: - * - * ---------------------------------------- - * | RESERVED | INCREMENT | DIVIDER | - * ---------------------------------------- - * 31 16 15 8 7 0 - * - * DIVIDER determines how often a 'tick' happens, - * INCREMENT determines by how the RPSS increment - * registers value increases at each 'tick'. Thus, - * for IP22 we get INCREMENT=1, DIVIDER=1 == 0x101 - */ - mcmisc_regs->divider = 0x101; - - /* Step 5: Initialize GIO64 arbitrator configuration register. - * - * NOTE: If you dork with startup code the HPC init code in - * sgihpc_init() must run before us because of how we - * need to know Guiness vs. FullHouse and the board - * revision on this machine. You have been warned. - */ - - /* First the basic invariants across all gio64 implementations. */ - tmpreg = SGIMC_GIOPARM_HPC64; /* All 1st HPC's interface at 64bits. */ - tmpreg |= SGIMC_GIOPARM_ONEBUS; /* Only one physical GIO bus exists. */ - - if(sgi_guiness) { - /* Guiness specific settings. */ - tmpreg |= SGIMC_GIOPARM_EISA64; /* MC talks to EISA at 64bits */ - tmpreg |= SGIMC_GIOPARM_MASTEREISA; /* EISA bus can act as master */ - } else { - /* Fullhouse specific settings. */ - if(sgi_boardid < 2) { - tmpreg |= SGIMC_GIOPARM_HPC264; /* 2nd HPC at 64bits */ - tmpreg |= SGIMC_GIOPARM_PLINEEXP0; /* exp0 pipelines */ - tmpreg |= SGIMC_GIOPARM_MASTEREXP1;/* exp1 masters */ - tmpreg |= SGIMC_GIOPARM_RTIMEEXP0; /* exp0 is realtime */ - } else { - tmpreg |= SGIMC_GIOPARM_HPC264; /* 2nd HPC 64bits */ - tmpreg |= SGIMC_GIOPARM_PLINEEXP0; /* exp[01] pipelined */ - tmpreg |= SGIMC_GIOPARM_PLINEEXP1; - tmpreg |= SGIMC_GIOPARM_MASTEREISA;/* EISA masters */ - /* someone forgot this poor little guy... */ - tmpreg |= SGIMC_GIOPARM_GFX64; /* GFX at 64 bits */ - } - } - mcmisc_regs->gioparm = tmpreg; /* poof */ -} diff -Nru a/arch/mips64/sgi-ip22/ip22-reset.c b/arch/mips64/sgi-ip22/ip22-reset.c --- a/arch/mips64/sgi-ip22/ip22-reset.c Tue Jul 1 18:44:36 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,238 +0,0 @@ -/* - * 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. - * - * Reset an IP22. - * - * Copyright (C) 1997, 1998, 1999, 2001 by Ralf Baechle - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Just powerdown if init hasn't done after POWERDOWN_TIMEOUT seconds. - * I'm not shure if this feature is a good idea, for now it's here just to - * make the power button make behave just like under IRIX. - */ -#define POWERDOWN_TIMEOUT 120 - -/* - * Blink frequency during reboot grace period and when paniced. - */ -#define POWERDOWN_FREQ (HZ / 4) -#define PANIC_FREQ (HZ / 8) - -static unsigned char sgi_volume; - -static struct timer_list power_timer, blink_timer, debounce_timer, volume_timer; -static int shuting_down, has_paniced; - -void machine_restart(char *command) __attribute__((noreturn)); -void machine_halt(void) __attribute__((noreturn)); -void machine_power_off(void) __attribute__((noreturn)); - -/* XXX How to pass the reboot command to the firmware??? */ -void machine_restart(char *command) -{ - if (shuting_down) - machine_power_off(); - ArcReboot(); -} - -void machine_halt(void) -{ - if (shuting_down) - machine_power_off(); - ArcEnterInteractiveMode(); -} - -void machine_power_off(void) -{ - struct indy_clock *clock = (struct indy_clock *)INDY_CLOCK_REGS; - - cli(); - - clock->cmd |= 0x08; /* Disable watchdog */ - clock->whsec = 0; - clock->wsec = 0; - - while(1) { - hpc3mregs->panel=0xfe; - /* Good bye cruel world ... */ - - /* If we're still running, we probably got sent an alarm - interrupt. Read the flag to clear it. */ - clock->halarm; - } -} - -static void power_timeout(unsigned long data) -{ - machine_power_off(); -} - -static void blink_timeout(unsigned long data) -{ - /* XXX Fix this for Fullhouse */ - sgi_hpc_write1 ^= (HPC3_WRITE1_LC0OFF|HPC3_WRITE1_LC1OFF); - hpc3mregs->write1 = sgi_hpc_write1; - - mod_timer(&blink_timer, jiffies+data); -} - -static void debounce(unsigned long data) -{ - del_timer(&debounce_timer); - if (ioc_icontrol->istat1 & 2) { /* Interrupt still being sent. */ - debounce_timer.expires = jiffies + 5; /* 0.05s */ - add_timer(&debounce_timer); - - hpc3mregs->panel = 0xf3; - - return; - } - - if (has_paniced) - ArcReboot(); - - enable_irq(9); -} - -static inline void power_button(void) -{ - if (has_paniced) - return; - - if (shuting_down || kill_proc(1, SIGINT, 1)) { - /* No init process or button pressed twice. */ - machine_power_off(); - } - - shuting_down = 1; - blink_timer.data = POWERDOWN_FREQ; - blink_timeout(POWERDOWN_FREQ); - - init_timer(&power_timer); - power_timer.function = power_timeout; - power_timer.expires = jiffies + POWERDOWN_TIMEOUT * HZ; - add_timer(&power_timer); -} - -void inline ip22_volume_set(unsigned char volume) -{ - sgi_volume = volume; - - hpc3c0->pbus_extregs[2][0] = sgi_volume; - hpc3c0->pbus_extregs[2][1] = sgi_volume; -} - -void inline ip22_volume_get(unsigned char *volume) -{ - *volume = sgi_volume; -} - -static inline void volume_up_button(unsigned long data) -{ - del_timer(&volume_timer); - - if (sgi_volume < 0xff) - sgi_volume++; - - hpc3c0->pbus_extregs[2][0] = sgi_volume; - hpc3c0->pbus_extregs[2][1] = sgi_volume; - - if (ioc_icontrol->istat1 & 2) { - volume_timer.expires = jiffies + 1; - add_timer(&volume_timer); - } - -} - -static inline void volume_down_button(unsigned long data) -{ - del_timer(&volume_timer); - - if (sgi_volume > 0) - sgi_volume--; - - hpc3c0->pbus_extregs[2][0] = sgi_volume; - hpc3c0->pbus_extregs[2][1] = sgi_volume; - - if (ioc_icontrol->istat1 & 2) { - volume_timer.expires = jiffies + 1; - add_timer(&volume_timer); - } -} - -static void panel_int(int irq, void *dev_id, struct pt_regs *regs) -{ - unsigned int buttons; - - buttons = hpc3mregs->panel; - hpc3mregs->panel = 3; /* power_interrupt | power_supply_on */ - - if (ioc_icontrol->istat1 & 2) { /* Wait until interrupt goes away */ - disable_irq(9); - init_timer(&debounce_timer); - debounce_timer.function = debounce; - debounce_timer.expires = jiffies + 5; - add_timer(&debounce_timer); - } - - if (!(buttons & 2)) /* Power button was pressed */ - power_button(); - if (!(buttons & 0x40)) { /* Volume up button was pressed */ - init_timer(&volume_timer); - volume_timer.function = volume_up_button; - volume_timer.expires = jiffies + 1; - add_timer(&volume_timer); - } - if (!(buttons & 0x10)) { /* Volume down button was pressed */ - init_timer(&volume_timer); - volume_timer.function = volume_down_button; - volume_timer.expires = jiffies + 1; - add_timer(&volume_timer); - } -} - -static int panic_event(struct notifier_block *this, unsigned long event, - void *ptr) -{ - if (has_paniced) - return NOTIFY_DONE; - has_paniced = 1; - - blink_timer.data = PANIC_FREQ; - blink_timeout(PANIC_FREQ); - - return NOTIFY_DONE; -} - -static struct notifier_block panic_block = { - panic_event, - NULL, - 0 -}; - -void ip22_reboot_setup(void) -{ - static int setup_done; - - if (setup_done) - return; - setup_done = 1; - - request_irq(9, panel_int, 0, "Front Panel", NULL); - init_timer(&blink_timer); - blink_timer.function = blink_timeout; - notifier_chain_register(&panic_notifier_list, &panic_block); -} diff -Nru a/arch/mips64/sgi-ip22/ip22-rtc.c b/arch/mips64/sgi-ip22/ip22-rtc.c --- a/arch/mips64/sgi-ip22/ip22-rtc.c Tue Jul 1 18:44:35 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,36 +0,0 @@ -/* - * 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. - * - * RTC routines for Indy style attached Dallas chip. - * - * Copyright (C) 1998, 2001 by Ralf Baechle - */ -#include -#include - -static unsigned char indy_rtc_read_data(unsigned long addr) -{ - volatile unsigned int *rtcregs = (void *)INDY_CLOCK_REGS; - - return rtcregs[addr]; -} - -static void indy_rtc_write_data(unsigned char data, unsigned long addr) -{ - volatile unsigned int *rtcregs = (void *)INDY_CLOCK_REGS; - - rtcregs[addr] = data; -} - -static int indy_rtc_bcd_mode(void) -{ - return 0; -} - -struct rtc_ops indy_rtc_ops = { - &indy_rtc_read_data, - &indy_rtc_write_data, - &indy_rtc_bcd_mode -}; diff -Nru a/arch/mips64/sgi-ip22/ip22-sc.c b/arch/mips64/sgi-ip22/ip22-sc.c --- a/arch/mips64/sgi-ip22/ip22-sc.c Tue Jul 1 18:44:38 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,164 +0,0 @@ -/* - * indy_sc.c: Indy cache management functions. - * - * Copyright (C) 1997 Ralf Baechle (ralf@gnu.org), - * derived from r4xx0.c by David S. Miller (dm@engr.sgi.com). - */ -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -/* Secondary cache size in bytes, if present. */ -static unsigned long scache_size; - -#undef DEBUG_CACHE - -#define SC_SIZE 0x00080000 -#define SC_LINE 32 -#define CI_MASK (SC_SIZE - SC_LINE) -#define SC_INDEX(n) ((n) & CI_MASK) - -static inline void indy_sc_wipe(unsigned long first, unsigned long last) -{ - __asm__ __volatile__( - ".set\tnoreorder\n\t" - "or\t%0, %4\t\t\t# first line to flush\n\t" - "or\t%1, %4\t\t\t# last line to flush\n" - "1:\tsw $0, 0(%0)\n\t" - "bne\t%0, %1, 1b\n\t" - "daddu\t%0, 32\n\t" - ".set reorder" - : "=r" (first), "=r" (last) - : "0" (first), "1" (last), "r" (0x9000000080000000) - : "$1"); -} - -static void indy_sc_wback_invalidate(unsigned long addr, unsigned long size) -{ - unsigned long first_line, last_line; - unsigned int flags; - -#ifdef DEBUG_CACHE - printk("indy_sc_wback_invalidate[%08lx,%08lx]", addr, size); -#endif - - if (!size) - return; - - /* Which lines to flush? */ - first_line = SC_INDEX(addr); - last_line = SC_INDEX(addr + size - 1); - - local_irq_save(flags); - if (first_line <= last_line) { - indy_sc_wipe(first_line, last_line); - goto out; - } - - indy_sc_wipe(first_line, SC_SIZE - SC_LINE); - indy_sc_wipe(0, last_line); -out: - local_irq_restore(flags); -} - -static void inline indy_sc_enable(void) -{ -#ifdef DEBUG_CACHE - printk("Enabling R4600 SCACHE\n"); -#endif - *(volatile unsigned char *) 0x9000000080000000 = 0; -} - -static void indy_sc_disable(void) -{ -#ifdef DEBUG_CACHE - printk("Disabling R4600 SCACHE\n"); -#endif - *(volatile unsigned short *) 0x9000000080000000 = 0; -} - -static inline __init int indy_sc_probe(void) -{ - volatile u32 *cpu_control; - unsigned short cmd = 0xc220; - unsigned long data = 0; - int i, n; - -#ifdef __MIPSEB__ - cpu_control = (volatile u32 *) KSEG1ADDR(0x1fa00034); -#else - cpu_control = (volatile u32 *) KSEG1ADDR(0x1fa00030); -#endif -#define DEASSERT(bit) (*(cpu_control) &= (~(bit))) -#define ASSERT(bit) (*(cpu_control) |= (bit)) -#define DELAY for(n = 0; n < 100000; n++) __asm__ __volatile__("") - DEASSERT(SGIMC_EEPROM_PRE); - DEASSERT(SGIMC_EEPROM_SDATAO); - DEASSERT(SGIMC_EEPROM_SECLOCK); - DEASSERT(SGIMC_EEPROM_PRE); - DELAY; - ASSERT(SGIMC_EEPROM_CSEL); ASSERT(SGIMC_EEPROM_SECLOCK); - for(i = 0; i < 11; i++) { - if(cmd & (1<<15)) - ASSERT(SGIMC_EEPROM_SDATAO); - else - DEASSERT(SGIMC_EEPROM_SDATAO); - DEASSERT(SGIMC_EEPROM_SECLOCK); - ASSERT(SGIMC_EEPROM_SECLOCK); - cmd <<= 1; - } - DEASSERT(SGIMC_EEPROM_SDATAO); - for(i = 0; i < (sizeof(unsigned short) * 8); i++) { - unsigned int tmp; - - DEASSERT(SGIMC_EEPROM_SECLOCK); - DELAY; - ASSERT(SGIMC_EEPROM_SECLOCK); - DELAY; - data <<= 1; - tmp = *cpu_control; - if(tmp & SGIMC_EEPROM_SDATAI) - data |= 1; - } - DEASSERT(SGIMC_EEPROM_SECLOCK); - DEASSERT(SGIMC_EEPROM_CSEL); - ASSERT(SGIMC_EEPROM_PRE); - ASSERT(SGIMC_EEPROM_SECLOCK); - - data <<= PAGE_SHIFT; - if (data == 0) - return 0; - - scache_size = data; - - printk("R4600/R5000 SCACHE size %ldK, linesize 32 bytes.\n", - scache_size >> 10); - - return 1; -} - -/* XXX Check with wje if the Indy caches can differenciate between - writeback + invalidate and just invalidate. */ -static struct bcache_ops indy_sc_ops = { - indy_sc_enable, - indy_sc_disable, - indy_sc_wback_invalidate, - indy_sc_wback_invalidate -}; - -void __init indy_sc_init(void) -{ - if (indy_sc_probe()) { - indy_sc_enable(); - bcops = &indy_sc_ops; - } -} diff -Nru a/arch/mips64/sgi-ip22/ip22-setup.c b/arch/mips64/sgi-ip22/ip22-setup.c --- a/arch/mips64/sgi-ip22/ip22-setup.c Tue Jul 1 18:44:36 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,189 +0,0 @@ -/* - * 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. - * - * SGI IP22 specific setup. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * Copyright (C) 1997, 1998, 1999 Ralf Baechle (ralf@gnu.org) - * Copyright (C) 1999 Silcon Graphics, Inc. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern struct rtc_ops indy_rtc_ops; -extern void ip22_reboot_setup(void); -extern void ip22_volume_set(unsigned char); - -#define sgi_kh ((struct hpc_keyb *) (KSEG1 + 0x1fbd9800 + 64)) - -#define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */ - -static void ip22_request_region(void) -{ - /* No I/O ports are being used on the Indy. */ -} - -static int ip22_request_irq(void (*handler)(int, void *, struct pt_regs *)) -{ - /* Dirty hack, this get's called as a callback from the keyboard - driver. We piggyback the initialization of the front panel - button handling on it even though they're technically not - related with the keyboard driver in any way. Doing it from - indy_setup wouldn't work since kmalloc isn't initialized yet. */ - ip22_reboot_setup(); - - return request_irq(SGI_KEYBOARD_IRQ, handler, 0, "keyboard", NULL); -} - -static int ip22_aux_request_irq(void (*handler)(int, void *, struct pt_regs *)) -{ - /* Nothing to do, interrupt is shared with the keyboard hw */ - return 0; -} - -static void ip22_aux_free_irq(void) -{ - /* Nothing to do, interrupt is shared with the keyboard hw */ -} - -static unsigned char ip22_read_input(void) -{ - return sgi_kh->data; -} - -static void ip22_write_output(unsigned char val) -{ - int status; - - do { - status = sgi_kh->command; - } while (status & KBD_STAT_IBF); - sgi_kh->data = val; -} - -static void ip22_write_command(unsigned char val) -{ - int status; - - do { - status = sgi_kh->command; - } while (status & KBD_STAT_IBF); - sgi_kh->command = val; -} - -static unsigned char ip22_read_status(void) -{ - return sgi_kh->command; -} - -struct kbd_ops sgi_kbd_ops = { - ip22_request_region, - ip22_request_irq, - - ip22_aux_request_irq, - ip22_aux_free_irq, - - ip22_read_input, - ip22_write_output, - ip22_write_command, - ip22_read_status -}; - -int __init page_is_ram(unsigned long pagenr) -{ - if ((pagenr< 0x08002000) - return 1; - return 0; -} - -void __init ip22_setup(void) -{ -#ifdef CONFIG_SERIAL_CONSOLE - char *ctype; -#endif - TLBMISS_HANDLER_SETUP(); - - /* Init the INDY HPC I/O controller. Need to call this before - * fucking with the memory controller because it needs to know the - * boardID and whether this is a Guiness or a FullHouse machine. - */ - sgihpc_init(); - - /* Init INDY memory controller. */ - sgimc_init(); - - /* Now enable boardcaches, if any. */ - indy_sc_init(); - -#ifdef CONFIG_SERIAL_CONSOLE - /* ARCS console environment variable is set to "g?" for - * graphics console, it is set to "d" for the first serial - * line and "d2" for the second serial line. - */ - ctype = ArcGetEnvironmentVariable("console"); - if(*ctype == 'd') { - if(*(ctype+1)=='2') - console_setup ("ttyS1"); - else - console_setup ("ttyS0"); - } -#endif -#ifdef CONFIG_ARC_CONSOLE - console_setup("ttyS0"); -#endif - - ip22_volume_set(simple_strtoul(ArcGetEnvironmentVariable("volume"), - NULL, 10)); - -#ifdef CONFIG_VT -#ifdef CONFIG_SGI_NEWPORT_CONSOLE - conswitchp = &newport_con; - - screen_info = (struct screen_info) { - 0, 0, /* orig-x, orig-y */ - 0, /* unused */ - 0, /* orig_video_page */ - 0, /* orig_video_mode */ - 160, /* orig_video_cols */ - 0, 0, 0, /* unused, ega_bx, unused */ - 64, /* orig_video_lines */ - 0, /* orig_video_isVGA */ - 16 /* orig_video_points */ - }; -#else - conswitchp = &dummy_con; -#endif -#endif - rtc_ops = &indy_rtc_ops; - kbd_ops = &sgi_kbd_ops; -#ifdef CONFIG_PSMOUSE - aux_device_present = 0xaa; -#endif -#ifdef CONFIG_VIDEO_VINO - init_vino(); -#endif -} diff -Nru a/arch/mips64/sgi-ip22/ip22-timer.c b/arch/mips64/sgi-ip22/ip22-timer.c --- a/arch/mips64/sgi-ip22/ip22-timer.c Tue Jul 1 18:44:35 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,262 +0,0 @@ -/* - * indy_timer.c: Setting up the clock on the INDY 8254 controller. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * Copytight (C) 1997, 1998 Ralf Baechle (ralf@gnu.org) - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -/* Because of a bug in the i8254 timer we need to use the onchip r4k - * counter as our system wide timer interrupt running at 100HZ. - */ -static unsigned long r4k_offset; /* Amount to increment compare reg each time */ -static unsigned long r4k_cur; /* What counter should be at next timer irq */ - -static inline void ack_r4ktimer(unsigned long newval) -{ - write_32bit_cp0_register(CP0_COMPARE, newval); -} - -static int set_rtc_mmss(unsigned long nowtime) -{ - struct indy_clock *clock = (struct indy_clock *)INDY_CLOCK_REGS; - int retval = 0; - int real_seconds, real_minutes, clock_minutes; - -#define FROB_FROM_CLOCK(x) (((x) & 0xf) | ((((x) & 0xf0) >> 4) * 10)); -#define FROB_TO_CLOCK(x) ((((((x) & 0xff) / 10)<<4) | (((x) & 0xff) % 10)) & 0xff) - - clock->cmd &= ~(0x80); - clock_minutes = clock->min; - clock->cmd |= (0x80); - - clock_minutes = FROB_FROM_CLOCK(clock_minutes); - real_seconds = nowtime % 60; - real_minutes = nowtime / 60; - - if(((abs(real_minutes - clock_minutes) + 15)/30) & 1) - real_minutes += 30; /* correct for half hour time zone */ - - real_minutes %= 60; - if(abs(real_minutes - clock_minutes) < 30) { - /* Force clock oscillator to be on. */ - clock->month &= ~(0x80); - - /* Write real_seconds and real_minutes into the Dallas. */ - clock->cmd &= ~(0x80); - clock->sec = real_seconds; - clock->min = real_minutes; - clock->cmd |= (0x80); - } else - return -1; - -#undef FROB_FROM_CLOCK -#undef FROB_TO_CLOCK - - return retval; -} - -static long last_rtc_update; -unsigned long missed_heart_beats; - -void indy_timer_interrupt(struct pt_regs *regs) -{ - unsigned long count; - int irq = 7; - - write_seqlock(&xtime_lock); - /* Ack timer and compute new compare. */ - count = read_32bit_cp0_register(CP0_COUNT); - /* This has races. */ - if ((count - r4k_cur) >= r4k_offset) { - /* If this happens to often we'll need to compensate. */ - missed_heart_beats++; - r4k_cur = count + r4k_offset; - } - else - r4k_cur += r4k_offset; - ack_r4ktimer(r4k_cur); - kstat_cpu(0).irqs[irq]++; - do_timer(regs); - - /* We update the Dallas time of day approx. every 11 minutes, - * because of how the numbers work out we need to make - * absolutely sure we do this update within 500ms before the - * next second starts, thus the following code. - */ - 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)) { - if (set_rtc_mmss(xtime.tv_sec) == 0) - last_rtc_update = xtime.tv_sec; - else - /* do it again in 60s */ - last_rtc_update = xtime.tv_sec - 600; - } - write_sequnlock(&xtime_lock); -} - -static unsigned long dosample(volatile unsigned char *tcwp, - volatile unsigned char *tc2p) -{ - unsigned long ct0, ct1; - unsigned char msb, lsb; - - /* Start the counter. */ - *tcwp = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CALL | SGINT_TCWORD_MRGEN); - *tc2p = (SGINT_TCSAMP_COUNTER & 0xff); - *tc2p = (SGINT_TCSAMP_COUNTER >> 8); - - /* Get initial counter invariant */ - ct0 = read_32bit_cp0_register(CP0_COUNT); - - /* Latch and spin until top byte of counter2 is zero */ - do { - *tcwp = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CLAT); - lsb = *tc2p; - msb = *tc2p; - ct1 = read_32bit_cp0_register(CP0_COUNT); - } while(msb); - - /* Stop the counter. */ - *tcwp = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CALL | SGINT_TCWORD_MSWST); - - /* Return the difference, this is how far the r4k counter increments - * for every one HZ. - */ - return ct1 - ct0; -} - -static unsigned long __init get_indy_time(void) -{ - struct indy_clock *clock = (struct indy_clock *)INDY_CLOCK_REGS; - unsigned int year, mon, day, hour, min, sec; - - /* Freeze it. */ - clock->cmd &= ~(0x80); - - /* Read regs. */ - sec = clock->sec; - min = clock->min; - hour = (clock->hr & 0x3f); - day = (clock->date & 0x3f); - mon = (clock->month & 0x1f); - year = clock->year; - - /* Unfreeze clock. */ - clock->cmd |= 0x80; - - /* Frob the bits. */ -#define FROB1(x) (((x) & 0xf) + ((((x) & 0xf0) >> 4) * 10)); -#define FROB2(x) (((x) & 0xf) + (((((x) & 0xf0) >> 4) & 0x3) * 10)); - - /* XXX Should really check that secs register is the same - * XXX as when we first read it and if not go back and - * XXX read the regs above again. - */ - sec = FROB1(sec); min = FROB1(min); day = FROB1(day); - mon = FROB1(mon); year = FROB1(year); - hour = FROB2(hour); - -#undef FROB1 -#undef FROB2 - - /* Wheee... */ - if(year < 45) - year += 30; - if ((year += 1940) < 1970) - year += 100; - - return mktime(year, mon, day, hour, min, sec); -} - -#define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5) - -void __init indy_timer_init(void) -{ - struct sgi_ioc_timers *p; - volatile unsigned char *tcwp, *tc2p; - - /* Figure out the r4k offset, the algorithm is very simple and works - * in _all_ cases as long as the 8254 counter register itself works ok - * (as an interrupt driving timer it does not because of bug, this is - * why we are using the onchip r4k counter/compare register to serve - * this purpose, but for r4k_offset calculation it will work ok for us). - * There are other very complicated ways of performing this calculation - * but this one works just fine so I am not going to futz around. ;-) - */ - p = ioc_timers; - tcwp = &p->tcword; - tc2p = &p->tcnt2; - - printk("calculating r4koff... "); - dosample(tcwp, tc2p); /* First sample. */ - dosample(tcwp, tc2p); /* Eat one. */ - r4k_offset = dosample(tcwp, tc2p); /* Second sample. */ - - printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset); - - r4k_cur = (read_32bit_cp0_register(CP0_COUNT) + r4k_offset); - write_32bit_cp0_register(CP0_COMPARE, r4k_cur); - set_cp0_status(ST0_IM, ALLINTS); - sti(); - - write_seqlock_irq(&xtime_lock); - xtime.tv_sec = get_indy_time(); /* Read time from RTC. */ - xtime.tv_usec = 0; - write_sequnlock_irq(&xtime_lock); -} - -void indy_8254timer_irq(void) -{ - int cpu = smp_processor_id(); - int irq = 4; - - irq_enter(cpu, irq); - kstat_cpu(0).irqs[irq]++; - panic("indy_8254timer_irq: Whoops, should not have gotten this IRQ\n"); - irq_exit(cpu, irq); -} - -void do_gettimeofday(struct timeval *tv) -{ - unsigned long seq; - - do { - seq = read_seqbegin(&xtime_lock); - *tv = xtime; - } while (read_seqretry(&xtime_lock, seq)); -} - -void do_settimeofday(struct timeval *tv) -{ - write_seqlock_irq(&xtime_lock); - xtime = *tv; - time_adjust = 0; /* stop active adjtime() */ - time_status |= STA_UNSYNC; - time_maxerror = NTP_PHASE_LIMIT; - time_esterror = NTP_PHASE_LIMIT; - write_sequnlock_irq(&xtime_lock); -} diff -Nru a/arch/mips64/sgi-ip22/system.c b/arch/mips64/sgi-ip22/system.c --- a/arch/mips64/sgi-ip22/system.c Tue Jul 1 18:44:31 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,123 +0,0 @@ -/* - * 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. - * - * system.c: Probe the system type using ARCS prom interface library. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.org) - */ -#include -#include -#include -#include - -#include -#include -#include - -struct smatch { - char *name; - int type; -}; - -static struct smatch sgi_cputable[] = { - { "MIPS-R2000", CPU_R2000 }, - { "MIPS-R3000", CPU_R3000 }, - { "MIPS-R3000A", CPU_R3000A }, - { "MIPS-R4000", CPU_R4000SC }, - { "MIPS-R4400", CPU_R4400SC }, - { "MIPS-R4600", CPU_R4600 }, - { "MIPS-R8000", CPU_R8000 }, - { "MIPS-R5000", CPU_R5000 }, - { "MIPS-R5000A", CPU_R5000A } -}; - -#define NUM_CPUS 9 /* for now */ - -static int __init string_to_cpu(char *s) -{ - int i; - - for(i = 0; i < NUM_CPUS; i++) { - if(!strcmp(s, sgi_cputable[i].name)) - return sgi_cputable[i].type; - } - panic("\nYeee, could not determine MIPS cpu type <%s>", s); - return 0; -} - -/* - * We' call this early before loadmmu(). If we do the other way around - * the firmware will crash and burn. - */ -void __init sgi_sysinit(void) -{ - pcomponent *p, *toplev, *cpup = 0; - int cputype = -1; - - - /* The root component tells us what machine architecture we - * have here. - */ - p = ArcGetChild(PROM_NULL_COMPONENT); - - /* Now scan for cpu(s). */ - toplev = p = ArcGetChild(p); - while(p) { - int ncpus = 0; - - if(p->type == Cpu) { - if (++ncpus > 1) - panic("\nYeee, SGI MP not ready yet"); - printk("CPU: %s ", p->iname); - cpup = p; - cputype = string_to_cpu(cpup->iname); - } - p = ArcGetPeer(p); - } - if (cputype == -1) { - panic("\nYeee, could not find cpu ARCS component"); - } - p = ArcGetChild(cpup); - while(p) { - switch(p->class) { - case processor: - switch(p->type) { - case Fpu: - printk("FPU<%s> ", p->iname); - break; - - default: - break; - }; - break; - - case cache: - switch(p->type) { - case picache: - printk("ICACHE "); - break; - - case pdcache: - printk("DCACHE "); - break; - - case sccache: - printk("SCACHE "); - break; - - default: - break; - - }; - break; - - default: - break; - }; - p = ArcGetPeer(p); - } - printk("\n"); -} diff -Nru a/arch/mips64/sgi-ip22/time.c b/arch/mips64/sgi-ip22/time.c --- a/arch/mips64/sgi-ip22/time.c Tue Jul 1 18:44:32 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,19 +0,0 @@ -/* - * 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. - * - * time.c: Generic SGI time_init() code, this will dispatch to the - * appropriate per-architecture time/counter init code. - * - * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - */ -#include - -extern void indy_timer_init(void); - -void __init time_init(void) -{ - /* XXX assume INDY for now XXX */ - indy_timer_init(); -} diff -Nru a/arch/mips64/sgi-ip27/Makefile b/arch/mips64/sgi-ip27/Makefile --- a/arch/mips64/sgi-ip27/Makefile Tue Jul 1 18:44:38 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,9 +0,0 @@ -# -# Makefile for the IP27 specific kernel interface routines under Linux. -# - -EXTRA_AFLAGS := $(CFLAGS) - -obj-y := ip27-berr.o ip27-console.o ip27-irq.o ip27-init.o ip27-irq-glue.o \ - ip27-klconfig.o ip27-klnuma.o ip27-memory.o ip27-nmi.o ip27-pci.o \ - ip27-pci-dma.o ip27-reset.o ip27-setup.o ip27-timer.o diff -Nru a/arch/mips64/sgi-ip27/TODO b/arch/mips64/sgi-ip27/TODO --- a/arch/mips64/sgi-ip27/TODO Tue Jul 1 18:44:36 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,23 +0,0 @@ -1. Need to figure out why PCI writes to the IOC3 hang, and if it is okay -not to write to the IOC3 ever. -2. Need to figure out RRB allocation in bridge_startup(). -3. Need to figure out why address swaizzling is needed in inw/outw for -Qlogic scsi controllers. -4. Need to integrate ip27-klconfig.c:find_lboard and -ip27-init.c:find_lbaord_real. DONE -5. Is it okay to set calias space on all nodes as 0, instead of 8k as -in irix? -6. Investigate why things do not work without the setup_test() call -being invoked on all nodes in ip27-memory.c. -7. Too many CLIs in the locore handlers : -For the low level handlers set up by set_except_vector(), -__tlb_refill_debug_tramp, __xtlb_refill_debug_tramp and cacheerror, -investigate whether the code should do CLI, STI or KMODE. -8. Too many do_page_faults invoked - investigate. -9. start_thread must turn off UX64 ... and define tlb_refill_debug. -10. Need a bad pmd table, bad pte table. __bad_pmd_table/__bad_pagetable -does not agree with pgd_bad/pmd_bad. -11. All intrs (ip27_do_irq handlers) are targetted at cpu A on the node. -This might need to change later. Only the timer intr is set up to be -received on both Cpu A and B. (ip27_do_irq()/bridge_startup()) -13. Cache flushing (specially the SMP version) has to be investigated. diff -Nru a/arch/mips64/sgi-ip27/ip27-berr.c b/arch/mips64/sgi-ip27/ip27-berr.c --- a/arch/mips64/sgi-ip27/ip27-berr.c Tue Jul 1 18:44:33 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,172 +0,0 @@ -/* - * 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, 1995, 1996, 1999, 2000 by Ralf Baechle - * Copyright (C) 1999, 2000 by Silicon Graphics - */ -#include -#include -#include - -#include -#include -#include -#include -#include - -extern void dump_tlb_addr(unsigned long addr); -extern void dump_tlb_all(void); - -extern asmlinkage void handle_ibe(void); -extern asmlinkage void handle_dbe(void); - -extern const struct exception_table_entry __start___dbe_table[]; -extern const struct exception_table_entry __stop___dbe_table[]; - -static inline unsigned long -search_one_table(const struct exception_table_entry *first, - const struct exception_table_entry *last, - unsigned long value) -{ - while (first <= last) { - const struct exception_table_entry *mid; - long diff; - - mid = (last - first) / 2 + first; - diff = mid->insn - value; - if (diff == 0) - return mid->nextinsn; - else if (diff < 0) - first = mid+1; - else - last = mid-1; - } - return 0; -} - -extern spinlock_t modlist_lock; - -static inline unsigned long -search_dbe_table(unsigned long addr) -{ - unsigned long ret; - -#ifndef CONFIG_MODULES - /* There is only the kernel to search. */ - ret = search_one_table(__start___dbe_table, __stop___dbe_table-1, addr); - return ret; -#else - unsigned long flags; - - /* The kernel is the last "module" -- no need to treat it special. */ - struct module *mp; - struct archdata *ap; - - spin_lock_irqsave(&modlist_lock, flags); - for (mp = module_list; mp != NULL; mp = mp->next) { - if (!mod_member_present(mp, archdata_end) || - !mod_archdata_member_present(mp, struct archdata, - dbe_table_end)) - continue; - ap = (struct archdata *)(mod->archdata_start); - - if (ap->dbe_table_start == NULL || - !(mp->flags & (MOD_RUNNING | MOD_INITIALIZING))) - continue; - ret = search_one_table(ap->dbe_table_start, - ap->dbe_table_end - 1, addr); - if (ret) - break; - } - spin_unlock_irqrestore(&modlist_lock, flags); - return ret; -#endif -} - -void do_ibe(struct pt_regs *regs) -{ - printk("Got ibe at 0x%lx\n", regs->cp0_epc); - show_regs(regs); - dump_tlb_addr(regs->cp0_epc); - force_sig(SIGBUS, current); - while(1); -} - -static void dump_hub_information(unsigned long errst0, unsigned long errst1) -{ - static char *err_type[2][8] = { - { NULL, "Uncached Partial Read PRERR", "DERR", "Read Timeout", - NULL, NULL, NULL, NULL }, - { "WERR", "Uncached Partial Write", "PWERR", "Write Timeout", - NULL, NULL, NULL, NULL } - }; - int wrb = errst1 & PI_ERR_ST1_WRBRRB_MASK; - - if (!(errst0 & PI_ERR_ST0_VALID_MASK)) { - printk("Hub does not contain valid error information\n"); - return; - } - - - printk("Hub has valid error information:\n"); - if (errst0 & PI_ERR_ST0_OVERRUN_MASK) - printk("Overrun is set. Error stack may contain additional " - "information.\n"); - printk("Hub error address is %08lx\n", - (errst0 & PI_ERR_ST0_ADDR_MASK) >> (PI_ERR_ST0_ADDR_SHFT - 3)); - printk("Incoming message command 0x%lx\n", - (errst0 & PI_ERR_ST0_CMD_MASK) >> PI_ERR_ST0_CMD_SHFT); - printk("Supplemental field of incoming message is 0x%lx\n", - (errst0 & PI_ERR_ST0_SUPPL_MASK) >> PI_ERR_ST0_SUPPL_SHFT); - printk("T5 Rn (for RRB only) is 0x%lx\n", - (errst0 & PI_ERR_ST0_REQNUM_MASK) >> PI_ERR_ST0_REQNUM_SHFT); - printk("Error type is %s\n", err_type[wrb] - [(errst0 & PI_ERR_ST0_TYPE_MASK) >> PI_ERR_ST0_TYPE_SHFT] - ? : "invalid"); -} - -void do_dbe(struct pt_regs *regs) -{ - unsigned long fixup, errst0, errst1; - int cpu = LOCAL_HUB_L(PI_CPU_NUM); - - fixup = search_dbe_table(regs->cp0_epc); - if (fixup) { - long new_epc; - - new_epc = fixup_exception(dpf_reg, fixup, regs->cp0_epc); - regs->cp0_epc = new_epc; - return; - } - - printk("Slice %c got dbe at 0x%lx\n", 'A' + cpu, regs->cp0_epc); - printk("Hub information:\n"); - printk("ERR_INT_PEND = 0x%06lx\n", LOCAL_HUB_L(PI_ERR_INT_PEND)); - errst0 = LOCAL_HUB_L(cpu ? PI_ERR_STATUS0_B : PI_ERR_STATUS0_A); - errst1 = LOCAL_HUB_L(cpu ? PI_ERR_STATUS1_B : PI_ERR_STATUS1_A); - dump_hub_information(errst0, errst1); - show_regs(regs); - dump_tlb_all(); - while(1); - force_sig(SIGBUS, current); -} - -void __init -bus_error_init(void) -{ - /* XXX Initialize all the Hub & Bridge error handling here. */ - int cpu = LOCAL_HUB_L(PI_CPU_NUM); - int cpuoff = cpu << 8; - - set_except_vector(6, handle_ibe); - set_except_vector(7, handle_dbe); - - LOCAL_HUB_S(PI_ERR_INT_PEND, - cpu ? PI_ERR_CLEAR_ALL_B : PI_ERR_CLEAR_ALL_A); - LOCAL_HUB_S(PI_ERR_INT_MASK_A + cpuoff, 0); - LOCAL_HUB_S(PI_ERR_STACK_ADDR_A + cpuoff, 0); - LOCAL_HUB_S(PI_ERR_STACK_SIZE, 0); /* Disable error stack */ - LOCAL_HUB_S(PI_SYSAD_ERRCHK_EN, PI_SYSAD_CHECK_ALL); -} diff -Nru a/arch/mips64/sgi-ip27/ip27-console.c b/arch/mips64/sgi-ip27/ip27-console.c --- a/arch/mips64/sgi-ip27/ip27-console.c Tue Jul 1 18:44:36 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,58 +0,0 @@ -/* - * 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) 2001 Ralf Baechle - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -void prom_putchar(char c) -{ - struct ioc3 *ioc3; - struct ioc3_uartregs *uart; - - ioc3 = (struct ioc3 *)KL_CONFIG_CH_CONS_INFO(master_nasid)->memory_base; - uart = &ioc3->sregs.uarta; - - while ((uart->iu_lsr & 0x20) == 0); - uart->iu_thr = c; -} - -char __init prom_getchar(void) -{ - return 0; -} - -static void -ip27prom_console_write(struct console *con, const char *s, unsigned n) -{ - prom_printf("%s", s); -} - -static kdev_t -ip27prom_console_dev(struct console *c) -{ - return MKDEV(TTY_MAJOR, 64 + c->index); -} - -static struct console ip27_prom_console = { - .name = "prom", - .write = ip27prom_console_write, - .device = ip27prom_console_dev, - .flags = CON_PRINTBUFFER, - .index = -1, -}; - -__init void ip27_setup_console(void) -{ - register_console(&ip27_prom_console); -} diff -Nru a/arch/mips64/sgi-ip27/ip27-init.c b/arch/mips64/sgi-ip27/ip27-init.c --- a/arch/mips64/sgi-ip27/ip27-init.c Tue Jul 1 18:44:38 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,840 +0,0 @@ -/* - * 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) 2000 - 2001 by Kanoj Sarcar (kanoj@sgi.com) - * Copyright (C) 2000 - 2001 by Silicon Graphics, Inc. - */ - -#include -#include -#include -#include -#include /* for numnodes */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define CPU_NONE (cpuid_t)-1 - -/* - * The following should work till 64 nodes, ie 128p SN0s. - */ -#define CNODEMASK_CLRALL(p) (p) = 0 -#define CNODEMASK_TSTB(p, bit) ((p) & (1ULL << (bit))) -#define CNODEMASK_SETB(p, bit) ((p) |= 1ULL << (bit)) - -cpumask_t boot_cpumask; -hubreg_t region_mask = 0; -static int fine_mode = 0; -int maxcpus; -static spinlock_t hub_mask_lock = SPIN_LOCK_UNLOCKED; -static cnodemask_t hub_init_mask; -static atomic_t numstarted = ATOMIC_INIT(1); -static int router_distance; -nasid_t master_nasid = INVALID_NASID; - -cnodeid_t nasid_to_compact_node[MAX_NASIDS]; -nasid_t compact_to_nasid_node[MAX_COMPACT_NODES]; -cnodeid_t cpuid_to_compact_node[MAXCPUS]; -char node_distances[MAX_COMPACT_NODES][MAX_COMPACT_NODES]; - -hubreg_t get_region(cnodeid_t cnode) -{ - if (fine_mode) - return COMPACT_TO_NASID_NODEID(cnode) >> NASID_TO_FINEREG_SHFT; - else - return COMPACT_TO_NASID_NODEID(cnode) >> NASID_TO_COARSEREG_SHFT; -} - -static void gen_region_mask(hubreg_t *region_mask, int maxnodes) -{ - cnodeid_t cnode; - - (*region_mask) = 0; - for (cnode = 0; cnode < maxnodes; cnode++) { - (*region_mask) |= 1ULL << get_region(cnode); - } -} - -int is_fine_dirmode(void) -{ - return (((LOCAL_HUB_L(NI_STATUS_REV_ID) & NSRI_REGIONSIZE_MASK) - >> NSRI_REGIONSIZE_SHFT) & REGIONSIZE_FINE); -} - -nasid_t get_actual_nasid(lboard_t *brd) -{ - klhub_t *hub; - - if (!brd) - return INVALID_NASID; - - /* find out if we are a completely disabled brd. */ - hub = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB); - if (!hub) - return INVALID_NASID; - if (!(hub->hub_info.flags & KLINFO_ENABLE)) /* disabled node brd */ - return hub->hub_info.physid; - else - return brd->brd_nasid; -} - -/* Tweak this for maximum number of CPUs to activate */ -static int max_cpus = NR_CPUS; - -int do_cpumask(cnodeid_t cnode, nasid_t nasid, cpumask_t *boot_cpumask, - int *highest) -{ - static int tot_cpus_found = 0; - lboard_t *brd; - klcpu_t *acpu; - int cpus_found = 0; - cpuid_t cpuid; - - brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27); - - do { - acpu = (klcpu_t *)find_first_component(brd, KLSTRUCT_CPU); - while (acpu) { - cpuid = acpu->cpu_info.virtid; - /* cnode is not valid for completely disabled brds */ - if (get_actual_nasid(brd) == brd->brd_nasid) - cpuid_to_compact_node[cpuid] = cnode; - if (cpuid > *highest) - *highest = cpuid; - /* Only let it join in if it's marked enabled */ - if ((acpu->cpu_info.flags & KLINFO_ENABLE) && - (tot_cpus_found != max_cpus)) { - CPUMASK_SETB(*boot_cpumask, cpuid); - cpus_found++; - tot_cpus_found++; - } - acpu = (klcpu_t *)find_component(brd, (klinfo_t *)acpu, - KLSTRUCT_CPU); - } - brd = KLCF_NEXT(brd); - if (brd) - brd = find_lboard(brd,KLTYPE_IP27); - else - break; - } while (brd); - - return cpus_found; -} - -cpuid_t cpu_node_probe(cpumask_t *boot_cpumask, int *numnodes) -{ - int i, cpus = 0, highest = 0; - gda_t *gdap = GDA; - nasid_t nasid; - - /* - * Initialize the arrays to invalid nodeid (-1) - */ - for (i = 0; i < MAX_COMPACT_NODES; i++) - compact_to_nasid_node[i] = INVALID_NASID; - for (i = 0; i < MAX_NASIDS; i++) - nasid_to_compact_node[i] = INVALID_CNODEID; - for (i = 0; i < MAXCPUS; i++) - cpuid_to_compact_node[i] = INVALID_CNODEID; - - *numnodes = 0; - for (i = 0; i < MAX_COMPACT_NODES; i++) { - if ((nasid = gdap->g_nasidtable[i]) == INVALID_NASID) { - break; - } else { - compact_to_nasid_node[i] = nasid; - nasid_to_compact_node[nasid] = i; - (*numnodes)++; - cpus += do_cpumask(i, nasid, boot_cpumask, &highest); - } - } - - /* - * Cpus are numbered in order of cnodes. Currently, disabled - * cpus are not numbered. - */ - - return(highest + 1); -} - -int cpu_enabled(cpuid_t cpu) -{ - if (cpu == CPU_NONE) - return 0; - return (CPUMASK_TSTB(boot_cpumask, cpu) != 0); -} - -void mlreset (void) -{ - int i; - void init_topology_matrix(void); - void dump_topology(void); - - - master_nasid = get_nasid(); - fine_mode = is_fine_dirmode(); - - /* - * Probe for all CPUs - this creates the cpumask and - * sets up the mapping tables. - */ - CPUMASK_CLRALL(boot_cpumask); - maxcpus = cpu_node_probe(&boot_cpumask, &numnodes); - printk("Discovered %d cpus on %d nodes\n", maxcpus, numnodes); - - init_topology_matrix(); - dump_topology(); - - gen_region_mask(®ion_mask, numnodes); - CNODEMASK_CLRALL(hub_init_mask); - - setup_replication_mask(numnodes); - - /* - * Set all nodes' calias sizes to 8k - */ - for (i = 0; i < numnodes; i++) { - nasid_t nasid; - - nasid = COMPACT_TO_NASID_NODEID(i); - - /* - * Always have node 0 in the region mask, otherwise - * CALIAS accesses get exceptions since the hub - * thinks it is a node 0 address. - */ - REMOTE_HUB_S(nasid, PI_REGION_PRESENT, (region_mask | 1)); -#ifdef CONFIG_REPLICATE_EXHANDLERS - REMOTE_HUB_S(nasid, PI_CALIAS_SIZE, PI_CALIAS_SIZE_8K); -#else - REMOTE_HUB_S(nasid, PI_CALIAS_SIZE, PI_CALIAS_SIZE_0); -#endif - -#ifdef LATER - /* - * Set up all hubs to have a big window pointing at - * widget 0. Memory mode, widget 0, offset 0 - */ - REMOTE_HUB_S(nasid, IIO_ITTE(SWIN0_BIGWIN), - ((HUB_PIO_MAP_TO_MEM << IIO_ITTE_IOSP_SHIFT) | - (0 << IIO_ITTE_WIDGET_SHIFT))); -#endif - } -} - - -void intr_clear_bits(nasid_t nasid, volatile hubreg_t *pend, int base_level, - char *name) -{ - volatile hubreg_t bits; - int i; - - /* Check pending interrupts */ - if ((bits = HUB_L(pend)) != 0) - for (i = 0; i < N_INTPEND_BITS; i++) - if (bits & (1 << i)) - LOCAL_HUB_CLR_INTR(base_level + i); -} - -void intr_clear_all(nasid_t nasid) -{ - REMOTE_HUB_S(nasid, PI_INT_MASK0_A, 0); - REMOTE_HUB_S(nasid, PI_INT_MASK0_B, 0); - REMOTE_HUB_S(nasid, PI_INT_MASK1_A, 0); - REMOTE_HUB_S(nasid, PI_INT_MASK1_B, 0); - intr_clear_bits(nasid, REMOTE_HUB_ADDR(nasid, PI_INT_PEND0), - INT_PEND0_BASELVL, "INT_PEND0"); - intr_clear_bits(nasid, REMOTE_HUB_ADDR(nasid, PI_INT_PEND1), - INT_PEND1_BASELVL, "INT_PEND1"); -} - -void sn_mp_setup(void) -{ - cnodeid_t cnode; -#if 0 - cpuid_t cpu; -#endif - - for (cnode = 0; cnode < numnodes; cnode++) { -#if 0 - init_platform_nodepda(); -#endif - intr_clear_all(COMPACT_TO_NASID_NODEID(cnode)); - } -#if 0 - for (cpu = 0; cpu < maxcpus; cpu++) { - init_platform_pda(); - } -#endif -} - -void per_hub_init(cnodeid_t cnode) -{ - extern void pcibr_setup(cnodeid_t); - cnodemask_t done; - nasid_t nasid; - - nasid = COMPACT_TO_NASID_NODEID(cnode); - - spin_lock(&hub_mask_lock); - /* Test our bit. */ - if (!(done = CNODEMASK_TSTB(hub_init_mask, cnode))) { - /* Turn our bit on in the mask. */ - CNODEMASK_SETB(hub_init_mask, cnode); - /* - * Do the actual initialization if it hasn't been done yet. - * We don't need to hold a lock for this work. - */ - /* - * Set CRB timeout at 5ms, (< PI timeout of 10ms) - */ - REMOTE_HUB_S(nasid, IIO_ICTP, 0x800); - REMOTE_HUB_S(nasid, IIO_ICTO, 0xff); - hub_rtc_init(cnode); - pcibr_setup(cnode); -#ifdef CONFIG_REPLICATE_EXHANDLERS - /* - * If this is not a headless node initialization, - * copy over the caliased exception handlers. - */ - if (get_compact_nodeid() == cnode) { - extern char except_vec0, except_vec1_r10k; - extern char except_vec2_generic, except_vec3_generic; - - memcpy((void *)(KSEG0 + 0x100), &except_vec2_generic, - 0x80); - memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, - 0x80); - memcpy((void *)KSEG0, &except_vec0, 0x80); - memcpy((void *)KSEG0 + 0x080, &except_vec1_r10k, 0x80); - memcpy((void *)(KSEG0 + 0x100), (void *) KSEG0, 0x80); - memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, - 0x100); - flush_cache_l1(); - flush_cache_l2(); - } -#endif - } - spin_unlock(&hub_mask_lock); -} - -/* - * This is similar to hard_smp_processor_id(). - */ -cpuid_t getcpuid(void) -{ - klcpu_t *klcpu; - - klcpu = nasid_slice_to_cpuinfo(get_nasid(),LOCAL_HUB_L(PI_CPU_NUM)); - return klcpu->cpu_info.virtid; -} - -void per_cpu_init(void) -{ - extern void install_cpu_nmi_handler(int slice); - extern void load_mmu(void); - static int is_slave = 0; - int cpu = smp_processor_id(); - cnodeid_t cnode = get_compact_nodeid(); - - current_cpu_data.asid_cache = ASID_FIRST_VERSION; - TLBMISS_HANDLER_SETUP(); -#if 0 - intr_init(); -#endif - set_cp0_status(ST0_IM, 0); - per_hub_init(cnode); - cpu_time_init(); - if (smp_processor_id()) /* master can't do this early, no kmalloc */ - install_cpuintr(cpu); - /* Install our NMI handler if symmon hasn't installed one. */ - install_cpu_nmi_handler(cputoslice(cpu)); -#if 0 - install_tlbintr(cpu); -#endif - set_cp0_status(SRB_DEV0 | SRB_DEV1, SRB_DEV0 | SRB_DEV1); - if (is_slave) { - set_cp0_status(ST0_BEV, 0); - if (mips4_available) - set_cp0_status(ST0_XX, ST0_XX); - set_cp0_status(ST0_KX|ST0_SX|ST0_UX, ST0_KX|ST0_SX|ST0_UX); - sti(); - load_mmu(); - atomic_inc(&numstarted); - } else { - is_slave = 1; - } -} - -cnodeid_t get_compact_nodeid(void) -{ - nasid_t nasid; - - nasid = get_nasid(); - /* - * Map the physical node id to a virtual node id (virtual node ids - * are contiguous). - */ - return NASID_TO_COMPACT_NODEID(nasid); -} - -#ifdef CONFIG_SMP - -/* - * Takes as first input the PROM assigned cpu id, and the kernel - * assigned cpu id as the second. - */ -static void alloc_cpupda(cpuid_t cpu, int cpunum) -{ - cnodeid_t node; - nasid_t nasid; - - node = get_cpu_cnode(cpu); - nasid = COMPACT_TO_NASID_NODEID(node); - - cputonasid(cpunum) = nasid; - cputocnode(cpunum) = node; - cputoslice(cpunum) = get_cpu_slice(cpu); - cpu_data[cpunum].p_cpuid = cpu; -} - -void __init smp_callin(void) -{ -#if 0 - calibrate_delay(); - smp_store_cpu_info(cpuid); -#endif -} - -int __init start_secondary(void) -{ - extern int cpu_idle(void); - extern atomic_t smp_commenced; - - smp_callin(); - while (!atomic_read(&smp_commenced)); - return cpu_idle(); -} - -static volatile cpumask_t boot_barrier; - -void cboot(void) -{ - CPUMASK_CLRB(boot_barrier, getcpuid()); /* needs atomicity */ - per_cpu_init(); -#if 0 - ecc_init(); - bte_lateinit(); - init_mfhi_war(); -#endif - _flush_tlb_all(); - flush_cache_l1(); - flush_cache_l2(); - start_secondary(); -} - -void allowboot(void) -{ - int num_cpus = 0; - cpuid_t cpu, mycpuid = getcpuid(); - cnodeid_t cnode; - extern void bootstrap(void); - - sn_mp_setup(); - /* Master has already done per_cpu_init() */ - install_cpuintr(smp_processor_id()); -#if 0 - bte_lateinit(); - ecc_init(); -#endif - - replicate_kernel_text(numnodes); - boot_barrier = boot_cpumask; - /* Launch slaves. */ - for (cpu = 0; cpu < maxcpus; cpu++) { - if (cpu == mycpuid) { - alloc_cpupda(cpu, num_cpus); - num_cpus++; - /* We're already started, clear our bit */ - CPUMASK_CLRB(boot_barrier, cpu); - continue; - } - - /* Skip holes in CPU space */ - if (CPUMASK_TSTB(boot_cpumask, cpu)) { - struct task_struct *p; - - /* - * The following code is purely to make sure - * Linux can schedule processes on this slave. - */ - kernel_thread(0, NULL, CLONE_IDLETASK); - p = prev_task(&init_task); - sprintf(p->comm, "%s%d", "Idle", num_cpus); - init_tasks[num_cpus] = p; - alloc_cpupda(cpu, num_cpus); - del_from_runqueue(p); - p->processor = num_cpus; - p->cpus_runnable = 1 << num_cpus; /* we schedule the first task manually */ - unhash_process(p); - /* Attach to the address space of init_task. */ - atomic_inc(&init_mm.mm_count); - p->active_mm = &init_mm; - - /* - * Launch a slave into bootstrap(). - * It doesn't take an argument, and we - * set sp to the kernel stack of the newly - * created idle process, gp to the proc struct - * (so that current-> works). - */ - LAUNCH_SLAVE(cputonasid(num_cpus),cputoslice(num_cpus), - (launch_proc_t)MAPPED_KERN_RW_TO_K0(bootstrap), - 0, (void *)((unsigned long)p + - KERNEL_STACK_SIZE - 32), (void *)p); - - /* - * Now optimistically set the mapping arrays. We - * need to wait here, verify the cpu booted up, then - * fire up the next cpu. - */ - __cpu_number_map[cpu] = num_cpus; - __cpu_logical_map[num_cpus] = cpu; - num_cpus++; - /* - * Wait this cpu to start up and initialize its hub, - * and discover the io devices it will control. - * - * XXX: We really want to fire up launch all the CPUs - * at once. We have to preserve the order of the - * devices on the bridges first though. - */ - while(atomic_read(&numstarted) != num_cpus); - } - } - - -#ifdef LATER - Wait logic goes here. -#endif - for (cnode = 0; cnode < numnodes; cnode++) { -#if 0 - if (cnodetocpu(cnode) == -1) { - printk("Initializing headless hub,cnode %d", cnode); - per_hub_init(cnode); - } -#endif - } -#if 0 - cpu_io_setup(); - init_mfhi_war(); -#endif - smp_num_cpus = num_cpus; -} - -#else /* CONFIG_SMP */ -void cboot(void) {} -#endif /* CONFIG_SMP */ - - -#define rou_rflag rou_flags - -void -router_recurse(klrou_t *router_a, klrou_t *router_b, int depth) -{ - klrou_t *router; - lboard_t *brd; - int port; - - if (router_a->rou_rflag == 1) - return; - - if (depth >= router_distance) - return; - - router_a->rou_rflag = 1; - - for (port = 1; port <= MAX_ROUTER_PORTS; port++) { - if (router_a->rou_port[port].port_nasid == INVALID_NASID) - continue; - - brd = (lboard_t *)NODE_OFFSET_TO_K0( - router_a->rou_port[port].port_nasid, - router_a->rou_port[port].port_offset); - - if (brd->brd_type == KLTYPE_ROUTER) { - router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd), brd->brd_compts[0]); - if (router == router_b) { - if (depth < router_distance) - router_distance = depth; - } - else - router_recurse(router, router_b, depth + 1); - } - } - - router_a->rou_rflag = 0; -} - -int -node_distance(nasid_t nasid_a, nasid_t nasid_b) -{ - nasid_t nasid; - cnodeid_t cnode; - lboard_t *brd, *dest_brd; - int port; - klrou_t *router, *router_a = NULL, *router_b = NULL; - - /* Figure out which routers nodes in question are connected to */ - for (cnode = 0; cnode < numnodes; cnode++) { - nasid = COMPACT_TO_NASID_NODEID(cnode); - - if (nasid == -1) continue; - - brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid), - KLTYPE_ROUTER); - - if (!brd) - continue; - - do { - if (brd->brd_flags & DUPLICATE_BOARD) - continue; - - router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd), brd->brd_compts[0]); - router->rou_rflag = 0; - - for (port = 1; port <= MAX_ROUTER_PORTS; port++) { - if (router->rou_port[port].port_nasid == INVALID_NASID) - continue; - - dest_brd = (lboard_t *)NODE_OFFSET_TO_K0( - router->rou_port[port].port_nasid, - router->rou_port[port].port_offset); - - if (dest_brd->brd_type == KLTYPE_IP27) { - if (dest_brd->brd_nasid == nasid_a) - router_a = router; - if (dest_brd->brd_nasid == nasid_b) - router_b = router; - } - } - - } while ( (brd = find_lboard_class(KLCF_NEXT(brd), KLTYPE_ROUTER)) ); - } - - if (router_a == NULL) { - printk("node_distance: router_a NULL\n"); - return -1; - } - if (router_b == NULL) { - printk("node_distance: router_b NULL\n"); - return -1; - } - - if (nasid_a == nasid_b) - return 0; - - if (router_a == router_b) - return 1; - - router_distance = 100; - router_recurse(router_a, router_b, 2); - - return router_distance; -} - -void -init_topology_matrix(void) -{ - nasid_t nasid, nasid2; - cnodeid_t row, col; - - for (row = 0; row < MAX_COMPACT_NODES; row++) - for (col = 0; col < MAX_COMPACT_NODES; col++) - node_distances[row][col] = -1; - - for (row = 0; row < numnodes; row++) { - nasid = COMPACT_TO_NASID_NODEID(row); - for (col = 0; col < numnodes; col++) { - nasid2 = COMPACT_TO_NASID_NODEID(col); - node_distances[row][col] = node_distance(nasid, nasid2); - } - } -} - -void -dump_topology(void) -{ - nasid_t nasid; - cnodeid_t cnode; - lboard_t *brd, *dest_brd; - int port; - int router_num = 0; - klrou_t *router; - cnodeid_t row, col; - - printk("************** Topology ********************\n"); - - printk(" "); - for (col = 0; col < numnodes; col++) - printk("%02d ", col); - printk("\n"); - for (row = 0; row < numnodes; row++) { - printk("%02d ", row); - for (col = 0; col < numnodes; col++) - printk("%2d ", node_distances[row][col]); - printk("\n"); - } - - for (cnode = 0; cnode < numnodes; cnode++) { - nasid = COMPACT_TO_NASID_NODEID(cnode); - - if (nasid == -1) continue; - - brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid), - KLTYPE_ROUTER); - - if (!brd) - continue; - - do { - if (brd->brd_flags & DUPLICATE_BOARD) - continue; - printk("Router %d:", router_num); - router_num++; - - router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd), brd->brd_compts[0]); - - for (port = 1; port <= MAX_ROUTER_PORTS; port++) { - if (router->rou_port[port].port_nasid == INVALID_NASID) - continue; - - dest_brd = (lboard_t *)NODE_OFFSET_TO_K0( - router->rou_port[port].port_nasid, - router->rou_port[port].port_offset); - - if (dest_brd->brd_type == KLTYPE_IP27) - printk(" %d", dest_brd->brd_nasid); - if (dest_brd->brd_type == KLTYPE_ROUTER) - printk(" r"); - } - printk("\n"); - - } while ( (brd = find_lboard_class(KLCF_NEXT(brd), KLTYPE_ROUTER)) ); - } -} - -#if 0 -#define brd_widgetnum brd_slot -#define NODE_OFFSET_TO_KLINFO(n,off) ((klinfo_t*) TO_NODE_CAC(n,off)) -void -dump_klcfg(void) -{ - cnodeid_t cnode; - int i; - nasid_t nasid; - lboard_t *lbptr; - gda_t *gdap; - - gdap = (gda_t *)GDA_ADDR(get_nasid()); - if (gdap->g_magic != GDA_MAGIC) { - printk("dumpklcfg_cmd: Invalid GDA MAGIC\n"); - return; - } - - for (cnode = 0; cnode < MAX_COMPACT_NODES; cnode ++) { - nasid = gdap->g_nasidtable[cnode]; - - if (nasid == INVALID_NASID) - continue; - - printk("\nDumpping klconfig Nasid %d:\n", nasid); - - lbptr = KL_CONFIG_INFO(nasid); - - while (lbptr) { - printk(" %s, Nasid %d, Module %d, widget 0x%x, partition %d, NIC 0x%x lboard 0x%lx", - "board name here", /* BOARD_NAME(lbptr->brd_type), */ - lbptr->brd_nasid, lbptr->brd_module, - lbptr->brd_widgetnum, - lbptr->brd_partition, - (lbptr->brd_nic), lbptr); - if (lbptr->brd_flags & DUPLICATE_BOARD) - printk(" -D"); - printk("\n"); - for (i = 0; i < lbptr->brd_numcompts; i++) { - klinfo_t *kli; - kli = NODE_OFFSET_TO_KLINFO(NASID_GET(lbptr), lbptr->brd_compts[i]); - printk(" type %2d, flags 0x%04x, diagval %3d, physid %4d, virtid %2d: %s\n", - kli->struct_type, - kli->flags, - kli->diagval, - kli->physid, - kli->virtid, - "comp. name here"); - /* COMPONENT_NAME(kli->struct_type)); */ - } - lbptr = KLCF_NEXT(lbptr); - } - } - printk("\n"); - - /* Useful to print router maps also */ - - for (cnode = 0; cnode < MAX_COMPACT_NODES; cnode ++) { - klrou_t *kr; - int i; - - nasid = gdap->g_nasidtable[cnode]; - if (nasid == INVALID_NASID) - continue; - lbptr = KL_CONFIG_INFO(nasid); - - while (lbptr) { - - lbptr = find_lboard_class(lbptr, KLCLASS_ROUTER); - if(!lbptr) - break; - if (!KL_CONFIG_DUPLICATE_BOARD(lbptr)) { - printk("%llx -> \n", lbptr->brd_nic); - kr = (klrou_t *)find_first_component(lbptr, - KLSTRUCT_ROU); - for (i = 1; i <= MAX_ROUTER_PORTS; i++) { - printk("[%d, %llx]; ", - kr->rou_port[i].port_nasid, - kr->rou_port[i].port_offset); - } - printk("\n"); - } - lbptr = KLCF_NEXT(lbptr); - } - printk("\n"); - } - - dump_topology(); -} -#endif - diff -Nru a/arch/mips64/sgi-ip27/ip27-irq-glue.S b/arch/mips64/sgi-ip27/ip27-irq-glue.S --- a/arch/mips64/sgi-ip27/ip27-irq-glue.S Tue Jul 1 18:44:33 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,64 +0,0 @@ -/* - * 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) 1999 Ralf Baechle - * Copyright (C) 1999 Silicon Graphics, Inc. - */ -#include -#include -#include -#include - - .text - .set noat - .align 5 -NESTED(ip27_irq, PT_SIZE, sp) - SAVE_ALL - CLI - .set at - - /* IP27 may signal interrupt which we're not interested in. - Mask them out. */ - mfc0 s0, CP0_CAUSE - mfc0 t0, CP0_STATUS - and s0, t0 - - /* First check for RT interrupt. */ - andi a0, s0, CAUSEF_IP4 - beqz a0, 1f - - /* Ok, a timer interrupt. */ - move a0, sp - jal rt_timer_interrupt - - j ret_from_irq - -1: andi a0, s0, (CAUSEF_IP2 | CAUSEF_IP3) - beqz a0, 1f - - /* ... a device interrupt ... */ - move a0, sp - jal ip27_do_irq - - j ret_from_irq - -1: -#if 1 - mfc0 a1, CP0_STATUS - srl a1, a1, 8 - andi a1, 0xff - - mfc0 a2, CP0_CAUSE - srl a2, a2, 8 - andi a2, 0xff - - move a3, s0 - PRINT("Spurious interrupt, c0_status = %02x, c0_cause = %02x, pending %02x.\n") - ld a1, PT_EPC(sp) -0: b 0b -#endif - - j ret_from_irq - END(ip27_irq) diff -Nru a/arch/mips64/sgi-ip27/ip27-irq.c b/arch/mips64/sgi-ip27/ip27-irq.c --- a/arch/mips64/sgi-ip27/ip27-irq.c Tue Jul 1 18:44:35 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,769 +0,0 @@ -/* - * ip27-irq.c: Highlevel interrupt handling for IP27 architecture. - * - * Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org) - * Copyright (C) 1999, 2000 Silicon Graphics, Inc. - * Copyright (C) 1999 - 2001 Kanoj Sarcar - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#undef DEBUG_IRQ -#ifdef DEBUG_IRQ -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - -/* These should die */ -unsigned char bus_to_wid[256]; /* widget id for linux pci bus */ -unsigned char bus_to_nid[256]; /* nasid for linux pci bus */ -unsigned char num_bridges; /* number of bridges in the system */ - -/* - * Linux has a controller-independent x86 interrupt architecture. - * every controller has a 'controller-template', that is used - * by the main code to do the right thing. Each driver-visible - * interrupt source is transparently wired to the apropriate - * controller. Thus drivers need not be aware of the - * interrupt-controller. - * - * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC, - * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC. - * (IO-APICs assumed to be messaging to Pentium local-APICs) - * - * the code is designed to be easily extended with new/different - * interrupt controllers, without having to do assembly magic. - */ - -extern asmlinkage void ip27_irq(void); -extern int irq_to_bus[], irq_to_slot[], bus_to_cpu[]; -int intr_connect_level(int cpu, int bit); -int intr_disconnect_level(int cpu, int bit); - -unsigned long spurious_count = 0; - -/* - * There is a single intpend register per node, and we want to have - * distinct levels for intercpu intrs for both cpus A and B on a node. - */ -int node_level_to_irq[MAX_COMPACT_NODES][PERNODE_LEVELS]; - -/* - * use these macros to get the encoded nasid and widget id - * from the irq value - */ -#define IRQ_TO_BUS(i) irq_to_bus[(i)] -#define IRQ_TO_CPU(i) bus_to_cpu[IRQ_TO_BUS(i)] -#define NASID_FROM_PCI_IRQ(i) bus_to_nid[IRQ_TO_BUS(i)] -#define WID_FROM_PCI_IRQ(i) bus_to_wid[IRQ_TO_BUS(i)] -#define SLOT_FROM_PCI_IRQ(i) irq_to_slot[i] - -static inline int alloc_level(cpuid_t cpunum, int irq) -{ - cnodeid_t nodenum = CPUID_TO_COMPACT_NODEID(cpunum); - int j = LEAST_LEVEL + 3; /* resched & crosscall entries taken */ - - while (++j < PERNODE_LEVELS) { - if (node_level_to_irq[nodenum][j] == -1) { - node_level_to_irq[nodenum][j] = irq; - return j; - } - } - printk("Cpu %ld flooded with devices\n", cpunum); - while(1); - return -1; -} - -static inline int find_level(cpuid_t *cpunum, int irq) -{ - int j; - cnodeid_t nodenum = INVALID_CNODEID; - - while (++nodenum < MAX_COMPACT_NODES) { - j = LEAST_LEVEL + 3; /* resched & crosscall entries taken */ - while (++j < PERNODE_LEVELS) - if (node_level_to_irq[nodenum][j] == irq) { - *cpunum = 0; /* XXX Fixme */ - return(j); - } - } - printk("Could not identify cpu/level for irq %d\n", irq); - while(1); - return(-1); -} - - -void disable_irq(unsigned int irq_nr) -{ - panic("disable_irq() called ..."); -} - -void enable_irq(unsigned int irq_nr) -{ - panic("enable_irq() called ..."); -} - -/* This is stupid for an Origin which can have thousands of IRQs ... */ -static struct irqaction *irq_action[NR_IRQS]; - -int show_interrupts(struct seq_file *p, void *v) -{ - int i; - struct irqaction * action; - unsigned long flags; - - for (i = 0 ; i < NR_IRQS ; i++) { - local_irq_save(flags); - action = irq_action[i]; - if (!action) - goto skip; - seq_printf(p, "%2d: %8d %c %s", i, kstat_cpu(0).irqs[i], - (action->flags & SA_INTERRUPT) ? '+' : ' ', - action->name); - for (action=action->next; action; action = action->next) { - seq_printf(p, ",%s %s", - (action->flags & SA_INTERRUPT) - ? " +" : "", - action->name); - } - seq_putc(p, '\n'); -skip: - local_irq_restore(flags); - } - return 0; -} - -/* - * do_IRQ handles all normal device IRQ's (the special SMP cross-CPU interrupts - * have their own specific handlers). - */ -static void do_IRQ(cpuid_t thiscpu, int irq, struct pt_regs * regs) -{ - struct irqaction *action; - int do_random; - - irq_enter(thiscpu, irq); - kstat_cpu(thiscpu).irqs[irq]++; - - action = *(irq + irq_action); - if (action) { - if (!(action->flags & SA_INTERRUPT)) - local_irq_enable(); - do_random = 0; - do { - do_random |= action->flags; - action->handler(irq, action->dev_id, regs); - action = action->next; - } while (action); - if (do_random & SA_SAMPLE_RANDOM) - add_interrupt_randomness(irq); - local_irq_disable(); - } - irq_exit(thiscpu, irq); - - if (softirq_pending(thiscpu)) - do_softirq(); -} - -/* - * Find first bit set - */ -static int ms1bit(unsigned long x) -{ - int b; - - if (x >> 32) b = 32, x >>= 32; - else b = 0; - if (x >> 16) b += 16, x >>= 16; - if (x >> 8) b += 8, x >>= 8; - if (x >> 4) b += 4, x >>= 4; - if (x >> 2) b += 2, x >>= 2; - - return b + (int) (x >> 1); -} - -/* - * This code is unnecessarily complex, because we do SA_INTERRUPT - * intr enabling. Basically, once we grab the set of intrs we need - * to service, we must mask _all_ these interrupts; firstly, to make - * sure the same intr does not intr again, causing recursion that - * can lead to stack overflow. Secondly, we can not just mask the - * one intr we are do_IRQing, because the non-masked intrs in the - * first set might intr again, causing multiple servicings of the - * same intr. This effect is mostly seen for intercpu intrs. - * Kanoj 05.13.00 - */ -void ip27_do_irq(struct pt_regs *regs) -{ - int irq, swlevel; - hubreg_t pend0, mask0; - cpuid_t thiscpu = smp_processor_id(); - int pi_int_mask0 = ((cputoslice(thiscpu) == 0) ? - PI_INT_MASK0_A : PI_INT_MASK0_B); - - /* copied from Irix intpend0() */ - while (((pend0 = LOCAL_HUB_L(PI_INT_PEND0)) & - (mask0 = LOCAL_HUB_L(pi_int_mask0))) != 0) { - pend0 &= mask0; /* Pick intrs we should look at */ - if (pend0) { - /* Prevent any of the picked intrs from recursing */ - LOCAL_HUB_S(pi_int_mask0, mask0 & ~(pend0)); - do { - swlevel = ms1bit(pend0); - LOCAL_HUB_CLR_INTR(swlevel); - /* "map" swlevel to irq */ - irq = LEVEL_TO_IRQ(thiscpu, swlevel); - do_IRQ(thiscpu, irq, regs); - /* clear bit in pend0 */ - pend0 ^= 1ULL << swlevel; - } while(pend0); - /* Now allow the set of serviced intrs again */ - LOCAL_HUB_S(pi_int_mask0, mask0); - LOCAL_HUB_L(PI_INT_PEND0); - } - } -} - - -/* Startup one of the (PCI ...) IRQs routes over a bridge. */ -static unsigned int bridge_startup(unsigned int irq) -{ - bridgereg_t device; - bridge_t *bridge; - int pin, swlevel; - cpuid_t cpu; - nasid_t master = NASID_FROM_PCI_IRQ(irq); - - bridge = (bridge_t *) NODE_SWIN_BASE(master, WID_FROM_PCI_IRQ(irq)); - pin = SLOT_FROM_PCI_IRQ(irq); - cpu = IRQ_TO_CPU(irq); - - DBG("bridge_startup(): irq= 0x%x pin=%d\n", irq, pin); - /* - * "map" irq to a swlevel greater than 6 since the first 6 bits - * of INT_PEND0 are taken - */ - swlevel = alloc_level(cpu, irq); - intr_connect_level(cpu, swlevel); - - bridge->b_int_addr[pin].addr = (0x20000 | swlevel | (master << 8)); - bridge->b_int_enable |= (1 << pin); - /* more stuff in int_enable reg */ - bridge->b_int_enable |= 0x7ffffe00; - - /* - * XXX This only works if b_int_device is initialized to 0! - * We program the bridge to have a 1:1 mapping between devices - * (slots) and intr pins. - */ - device = bridge->b_int_device; - device |= (pin << (pin*3)); - bridge->b_int_device = device; - - bridge->b_widget.w_tflush; /* Flush */ - - return 0; /* Never anything pending. */ -} - -/* Shutdown one of the (PCI ...) IRQs routes over a bridge. */ -static unsigned int bridge_shutdown(unsigned int irq) -{ - bridge_t *bridge; - int pin, swlevel; - cpuid_t cpu; - - bridge = (bridge_t *) NODE_SWIN_BASE(NASID_FROM_PCI_IRQ(irq), - WID_FROM_PCI_IRQ(irq)); - DBG("bridge_shutdown: irq 0x%x\n", irq); - pin = SLOT_FROM_PCI_IRQ(irq); - - /* - * map irq to a swlevel greater than 6 since the first 6 bits - * of INT_PEND0 are taken - */ - swlevel = find_level(&cpu, irq); - intr_disconnect_level(cpu, swlevel); - LEVEL_TO_IRQ(cpu, swlevel) = -1; - - bridge->b_int_enable &= ~(1 << pin); - bridge->b_widget.w_tflush; /* Flush */ - - return 0; /* Never anything pending. */ -} - -void irq_debug(void) -{ - bridge_t *bridge = (bridge_t *) 0x9200000008000000; - - printk("bridge->b_int_status = 0x%x\n", bridge->b_int_status); - printk("bridge->b_int_enable = 0x%x\n", bridge->b_int_enable); - printk("PI_INT_PEND0 = 0x%lx\n", LOCAL_HUB_L(PI_INT_PEND0)); - printk("PI_INT_MASK0_A = 0x%lx\n", LOCAL_HUB_L(PI_INT_MASK0_A)); -} - -int setup_irq(unsigned int irq, struct irqaction *new) -{ - int shared = 0; - struct irqaction *old, **p; - unsigned long flags; - - DBG("setup_irq: 0x%x\n", irq); - if (irq >= NR_IRQS) { - printk("IRQ array overflow %d\n", irq); - while(1); - } - if (new->flags & SA_SAMPLE_RANDOM) - rand_initialize_irq(irq); - - save_and_cli(flags); - p = irq_action + irq; - if ((old = *p) != NULL) { - /* Can't share interrupts unless both agree to */ - if (!(old->flags & new->flags & SA_SHIRQ)) { - restore_flags(flags); - return -EBUSY; - } - - /* Add new interrupt at end of irq queue */ - do { - p = &old->next; - old = *p; - } while (old); - shared = 1; - } - - *p = new; - - if ((!shared) && (irq >= BASE_PCI_IRQ)) { - bridge_startup(irq); - } - restore_flags(flags); - - return 0; -} - -int request_irq(unsigned int irq, - void (*handler)(int, void *, struct pt_regs *), - unsigned long irqflags, const char * devname, void *dev_id) -{ - int retval; - struct irqaction *action; - - DBG("request_irq(): irq= 0x%x\n", irq); - if (!handler) - return -EINVAL; - - action = (struct irqaction *)kmalloc(sizeof(*action), GFP_KERNEL); - if (!action) - return -ENOMEM; - - action->handler = handler; - action->flags = irqflags; - action->mask = 0; - action->name = devname; - action->next = NULL; - action->dev_id = dev_id; - - DBG("request_irq(): %s devid= 0x%x\n", devname, dev_id); - retval = setup_irq(irq, action); - DBG("request_irq(): retval= %d\n", retval); - if (retval) - kfree(action); - return retval; -} - -void free_irq(unsigned int irq, void *dev_id) -{ - struct irqaction * action, **p; - unsigned long flags; - - if (irq >= NR_IRQS) { - printk("Trying to free IRQ%d\n", irq); - return; - } - for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) { - if (action->dev_id != dev_id) - continue; - - /* Found it - now free it */ - save_and_cli(flags); - *p = action->next; - if (irq >= BASE_PCI_IRQ) - bridge_shutdown(irq); - restore_flags(flags); - kfree(action); - return; - } - printk("Trying to free free IRQ%d\n",irq); -} - -/* Useless ISA nonsense. */ -unsigned long probe_irq_on (void) -{ - panic("probe_irq_on called!\n"); - return 0; -} - -int probe_irq_off (unsigned long irqs) -{ - return 0; -} - -void __init init_IRQ(void) -{ - set_except_vector(0, ip27_irq); -} - -#ifdef CONFIG_SMP - -/* - * This following are the global intr on off routines, copied almost - * entirely from i386 code. - */ - -int global_irq_holder = NO_PROC_ID; -spinlock_t global_irq_lock = SPIN_LOCK_UNLOCKED; - -extern void show_stack(unsigned long* esp); - -static void show(char * str) -{ - int i; - int cpu = smp_processor_id(); - - printk("\n%s, CPU %d:\n", str, cpu); - printk("irq: %d [",irqs_running()); - for(i=0;i < smp_num_cpus;i++) - printk(" %d",local_irq_count(i)); - printk(" ]\nbh: %d [",spin_is_locked(&global_bh_lock) ? 1 : 0); - for(i=0;i < smp_num_cpus;i++) - printk(" %d",local_bh_count(i)); - - printk(" ]\nStack dumps:"); - for(i = 0; i < smp_num_cpus; i++) { - if (i == cpu) - continue; - printk("\nCPU %d:",i); - printk("Code not developed yet\n"); - /* show_stack(0); */ - } - printk("\nCPU %d:",cpu); - printk("Code not developed yet\n"); - /* show_stack(NULL); */ - printk("\n"); -} - -#define MAXCOUNT 100000000 -#define SYNC_OTHER_CORES(x) udelay(x+1) - -static inline void wait_on_irq(int cpu) -{ - int count = MAXCOUNT; - - for (;;) { - - /* - * Wait until all interrupts are gone. Wait - * for bottom half handlers unless we're - * already executing in one.. - */ - if (!irqs_running()) - if (local_bh_count(cpu) || !spin_is_locked(&global_bh_lock)) - break; - - /* Duh, we have to loop. Release the lock to avoid deadlocks */ - spin_unlock(&global_irq_lock); - - for (;;) { - if (!--count) { - show("wait_on_irq"); - count = ~0; - } - local_irq_enable(); - SYNC_OTHER_CORES(cpu); - local_irq_disable(); - if (irqs_running()) - continue; - if (spin_is_locked(&global_irq_lock)) - continue; - if (!local_bh_count(cpu) && spin_is_locked(&global_bh_lock)) - continue; - if (spin_trylock(&global_irq_lock)) - break; - } - } -} - -void synchronize_irq(void) -{ - if (irqs_running()) { - /* Stupid approach */ - cli(); - sti(); - } -} - -static inline void get_irqlock(int cpu) -{ - if (!spin_trylock(&global_irq_lock)) { - /* do we already hold the lock? */ - if ((unsigned char) cpu == global_irq_holder) - return; - /* Uhhuh.. Somebody else got it. Wait.. */ - spin_lock(&global_irq_lock); - } - /* - * We also to make sure that nobody else is running - * in an interrupt context. - */ - wait_on_irq(cpu); - - /* - * Ok, finally.. - */ - global_irq_holder = cpu; -} - -void __global_cli(void) -{ - unsigned int flags; - - local_save_flags(flags); - if (flags & ST0_IE) { - int cpu = smp_processor_id(); - local_irq_disable(); - if (!local_irq_count(cpu)) - get_irqlock(cpu); - } -} - -void __global_sti(void) -{ - int cpu = smp_processor_id(); - - if (!local_irq_count(cpu)) - release_irqlock(cpu); - local_irq_enable(); -} - -/* - * SMP flags value to restore to: - * 0 - global cli - * 1 - global sti - * 2 - local cli - * 3 - local sti - */ -unsigned long __global_save_flags(void) -{ - int retval; - int local_enabled; - unsigned long flags; - int cpu = smp_processor_id(); - - local_save_flags(flags); - local_enabled = (flags & ST0_IE); - /* default to local */ - retval = 2 + local_enabled; - - /* check for global flags if we're not in an interrupt */ - if (!local_irq_count(cpu)) { - if (local_enabled) - retval = 1; - if (global_irq_holder == cpu) - retval = 0; - } - return retval; -} - -void __global_restore_flags(unsigned long flags) -{ - switch (flags) { - case 0: - __global_cli(); - break; - case 1: - __global_sti(); - break; - case 2: - local_irq_disable(); - break; - case 3: - local_irq_enable(); - break; - default: - printk("global_restore_flags: %08lx\n", flags); - } -} - -#endif /* CONFIG_SMP */ - -/* - * Get values that vary depending on which CPU and bit we're operating on. - */ -static hub_intmasks_t *intr_get_ptrs(cpuid_t cpu, int bit, int *new_bit, - hubreg_t **intpend_masks, int *ip) -{ - hub_intmasks_t *hub_intmasks; - - hub_intmasks = &cpu_data[cpu].p_intmasks; - if (bit < N_INTPEND_BITS) { - *intpend_masks = hub_intmasks->intpend0_masks; - *ip = 0; - *new_bit = bit; - } else { - *intpend_masks = hub_intmasks->intpend1_masks; - *ip = 1; - *new_bit = bit - N_INTPEND_BITS; - } - return hub_intmasks; -} - -int intr_connect_level(int cpu, int bit) -{ - int ip; - int slice = cputoslice(cpu); - volatile hubreg_t *mask_reg; - hubreg_t *intpend_masks; - nasid_t nasid = COMPACT_TO_NASID_NODEID(cputocnode(cpu)); - - (void)intr_get_ptrs(cpu, bit, &bit, &intpend_masks, &ip); - - /* Make sure it's not already pending when we connect it. */ - REMOTE_HUB_CLR_INTR(nasid, bit + ip * N_INTPEND_BITS); - - intpend_masks[0] |= (1ULL << (u64)bit); - - if (ip == 0) { - mask_reg = REMOTE_HUB_ADDR(nasid, PI_INT_MASK0_A + - PI_INT_MASK_OFFSET * slice); - } else { - mask_reg = REMOTE_HUB_ADDR(nasid, PI_INT_MASK1_A + - PI_INT_MASK_OFFSET * slice); - } - HUB_S(mask_reg, intpend_masks[0]); - return(0); -} - -int intr_disconnect_level(int cpu, int bit) -{ - int ip; - int slice = cputoslice(cpu); - volatile hubreg_t *mask_reg; - hubreg_t *intpend_masks; - nasid_t nasid = COMPACT_TO_NASID_NODEID(cputocnode(cpu)); - - (void)intr_get_ptrs(cpu, bit, &bit, &intpend_masks, &ip); - intpend_masks[0] &= ~(1ULL << (u64)bit); - if (ip == 0) { - mask_reg = REMOTE_HUB_ADDR(nasid, PI_INT_MASK0_A + - PI_INT_MASK_OFFSET * slice); - } else { - mask_reg = REMOTE_HUB_ADDR(nasid, PI_INT_MASK1_A + - PI_INT_MASK_OFFSET * slice); - } - HUB_S(mask_reg, intpend_masks[0]); - return(0); -} - - -void handle_resched_intr(int irq, void *dev_id, struct pt_regs *regs) -{ - /* Nothing, the return from intr will work for us */ -} - -extern void smp_call_function_interrupt(void); - -void install_cpuintr(int cpu) -{ -#ifdef CONFIG_SMP -#if (CPUS_PER_NODE == 2) - static int done = 0; - - /* - * This is a hack till we have a pernode irqlist. Currently, - * just have the master cpu set up the handlers for the per - * cpu irqs. - */ - if (done == 0) { - int j; - - if (request_irq(CPU_RESCHED_A_IRQ, handle_resched_intr, - 0, "resched", 0)) - panic("intercpu intr unconnectible\n"); - if (request_irq(CPU_RESCHED_B_IRQ, handle_resched_intr, - 0, "resched", 0)) - panic("intercpu intr unconnectible\n"); - if (request_irq(CPU_CALL_A_IRQ, smp_call_function_interrupt, - 0, "callfunc", 0)) - panic("intercpu intr unconnectible\n"); - if (request_irq(CPU_CALL_B_IRQ, smp_call_function_interrupt, - 0, "callfunc", 0)) - panic("intercpu intr unconnectible\n"); - - for (j = 0; j < PERNODE_LEVELS; j++) - LEVEL_TO_IRQ(0, j) = -1; - LEVEL_TO_IRQ(0, FAST_IRQ_TO_LEVEL(CPU_RESCHED_A_IRQ)) = - CPU_RESCHED_A_IRQ; - LEVEL_TO_IRQ(0, FAST_IRQ_TO_LEVEL(CPU_RESCHED_B_IRQ)) = - CPU_RESCHED_B_IRQ; - LEVEL_TO_IRQ(0, FAST_IRQ_TO_LEVEL(CPU_CALL_A_IRQ)) = - CPU_CALL_A_IRQ; - LEVEL_TO_IRQ(0, FAST_IRQ_TO_LEVEL(CPU_CALL_B_IRQ)) = - CPU_CALL_B_IRQ; - for (j = 1; j < MAX_COMPACT_NODES; j++) - memcpy(&node_level_to_irq[j][0], - &node_level_to_irq[0][0], - sizeof(node_level_to_irq[0][0])*PERNODE_LEVELS); - - done = 1; - } - - intr_connect_level(cpu, FAST_IRQ_TO_LEVEL(CPU_RESCHED_A_IRQ + - cputoslice(cpu))); - intr_connect_level(cpu, FAST_IRQ_TO_LEVEL(CPU_CALL_A_IRQ + - cputoslice(cpu))); -#else /* CPUS_PER_NODE */ -#error Must redefine this for more than 2 CPUS. -#endif /* CPUS_PER_NODE */ -#endif /* CONFIG_SMP */ -} - -void install_tlbintr(int cpu) -{ -#if 0 - int intr_bit = N_INTPEND_BITS + TLB_INTR_A + cputoslice(cpu); - - intr_connect_level(cpu, intr_bit); -#endif -} diff -Nru a/arch/mips64/sgi-ip27/ip27-klconfig.c b/arch/mips64/sgi-ip27/ip27-klconfig.c --- a/arch/mips64/sgi-ip27/ip27-klconfig.c Tue Jul 1 18:44:36 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,135 +0,0 @@ -/* - * Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org) - * Copyright (C) 1999, 2000 Silicon Graphics, Inc. - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -klinfo_t *find_component(lboard_t *brd, klinfo_t *kli, unsigned char struct_type) -{ - int index, j; - - if (kli == (klinfo_t *)NULL) { - index = 0; - } else { - for (j = 0; j < KLCF_NUM_COMPS(brd); j++) - if (kli == KLCF_COMP(brd, j)) - break; - index = j; - if (index == KLCF_NUM_COMPS(brd)) { - printk("find_component: Bad pointer: 0x%p\n", kli); - return (klinfo_t *)NULL; - } - index++; /* next component */ - } - - for (; index < KLCF_NUM_COMPS(brd); index++) { - kli = KLCF_COMP(brd, index); - if (KLCF_COMP_TYPE(kli) == struct_type) - return kli; - } - - /* Didn't find it. */ - return (klinfo_t *)NULL; -} - -klinfo_t *find_first_component(lboard_t *brd, unsigned char struct_type) -{ - return find_component(brd, (klinfo_t *)NULL, struct_type); -} - -lboard_t * find_lboard(lboard_t *start, unsigned char brd_type) -{ - /* Search all boards stored on this node. */ - while (start) { - if (start->brd_type == brd_type) - return start; - start = KLCF_NEXT(start); - } - /* Didn't find it. */ - return (lboard_t *)NULL; -} - -lboard_t * find_lboard_class(lboard_t *start, unsigned char brd_type) -{ - /* Search all boards stored on this node. */ - while (start) { - if (KLCLASS(start->brd_type) == KLCLASS(brd_type)) - return start; - start = KLCF_NEXT(start); - } - - /* Didn't find it. */ - return (lboard_t *)NULL; -} - -cnodeid_t get_cpu_cnode(cpuid_t cpu) -{ - return CPUID_TO_COMPACT_NODEID(cpu); -} - -klcpu_t * nasid_slice_to_cpuinfo(nasid_t nasid, int slice) -{ - lboard_t *brd; - klcpu_t *acpu; - - if (!(brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27))) - return (klcpu_t *)NULL; - - if (!(acpu = (klcpu_t *)find_first_component(brd, KLSTRUCT_CPU))) - return (klcpu_t *)NULL; - - do { - if ((acpu->cpu_info.physid) == slice) - return acpu; - } while ((acpu = (klcpu_t *)find_component(brd, (klinfo_t *)acpu, - KLSTRUCT_CPU))); - return (klcpu_t *)NULL; -} - -klcpu_t * sn_get_cpuinfo(cpuid_t cpu) -{ - nasid_t nasid; - int slice; - klcpu_t *acpu; - gda_t *gdap = GDA; - cnodeid_t cnode; - - if (!(cpu < MAXCPUS)) { - printk("sn_get_cpuinfo: illegal cpuid 0x%lx\n", cpu); - return NULL; - } - - cnode = get_cpu_cnode(cpu); - if (cnode == INVALID_CNODEID) - return NULL; - - if ((nasid = gdap->g_nasidtable[cnode]) == INVALID_NASID) - return NULL; - - for (slice = 0; slice < CPUS_PER_NODE; slice++) { - acpu = nasid_slice_to_cpuinfo(nasid, slice); - if (acpu && acpu->cpu_info.virtid == cpu) - return acpu; - } - return NULL; -} - -int get_cpu_slice(cpuid_t cpu) -{ - klcpu_t *acpu; - - if ((acpu = sn_get_cpuinfo(cpu)) == NULL) - return -1; - return acpu->cpu_info.physid; -} diff -Nru a/arch/mips64/sgi-ip27/ip27-klnuma.c b/arch/mips64/sgi-ip27/ip27-klnuma.c --- a/arch/mips64/sgi-ip27/ip27-klnuma.c Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,143 +0,0 @@ -/* - * Ported from IRIX to Linux by Kanoj Sarcar, 06/08/00. - * Copyright 2000 - 2001 Silicon Graphics, Inc. - * Copyright 2000 - 2001 Kanoj Sarcar (kanoj@sgi.com) - */ -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern char _end; -static cpumask_t ktext_repmask; - -/* - * XXX - This needs to be much smarter about where it puts copies of the - * kernel. For example, we should never put a copy on a headless node, - * and we should respect the topology of the machine. - */ -void __init setup_replication_mask(int maxnodes) -{ - static int numa_kernel_replication_ratio; - cnodeid_t cnode; - - /* Set only the master cnode's bit. The master cnode is always 0. */ - CPUMASK_CLRALL(ktext_repmask); - CPUMASK_SETB(ktext_repmask, 0); - - numa_kernel_replication_ratio = 0; -#ifdef CONFIG_REPLICATE_KTEXT -#ifndef CONFIG_MAPPED_KERNEL -#error Kernel replication works with mapped kernel support. No calias support. -#endif - numa_kernel_replication_ratio = 1; -#endif - - for (cnode = 1; cnode < numnodes; cnode++) { - /* See if this node should get a copy of the kernel */ - if (numa_kernel_replication_ratio && - !(cnode % numa_kernel_replication_ratio)) { - - /* Advertise that we have a copy of the kernel */ - CPUMASK_SETB(ktext_repmask, cnode); - } - } - - /* Set up a GDA pointer to the replication mask. */ - GDA->g_ktext_repmask = &ktext_repmask; -} - - -static __init void set_ktext_source(nasid_t client_nasid, nasid_t server_nasid) -{ - kern_vars_t *kvp; - cnodeid_t client_cnode; - - client_cnode = NASID_TO_COMPACT_NODEID(client_nasid); - - kvp = &(PLAT_NODE_DATA(client_cnode)->kern_vars); - - KERN_VARS_ADDR(client_nasid) = (unsigned long)kvp; - - kvp->kv_magic = KV_MAGIC; - - kvp->kv_ro_nasid = server_nasid; - kvp->kv_rw_nasid = master_nasid; - kvp->kv_ro_baseaddr = NODE_CAC_BASE(server_nasid); - kvp->kv_rw_baseaddr = NODE_CAC_BASE(master_nasid); - printk("REPLICATION: ON nasid %d, ktext from nasid %d, kdata from nasid %d\n", client_nasid, server_nasid, master_nasid); -} - -/* XXX - When the BTE works, we should use it instead of this. */ -static __init void copy_kernel(nasid_t dest_nasid) -{ - extern char _stext, _etext; - unsigned long dest_kern_start, source_start, source_end, kern_size; - - source_start = (unsigned long)&_stext; - source_end = (unsigned long)&_etext; - kern_size = source_end - source_start; - - dest_kern_start = CHANGE_ADDR_NASID(MAPPED_KERN_RO_TO_K0(source_start), - dest_nasid); - memcpy((void *)dest_kern_start, (void *)source_start, kern_size); -} - -void __init replicate_kernel_text(int maxnodes) -{ - cnodeid_t cnode; - nasid_t client_nasid; - nasid_t server_nasid; - - server_nasid = master_nasid; - - /* Record where the master node should get its kernel text */ - set_ktext_source(master_nasid, master_nasid); - - for (cnode = 1; cnode < maxnodes; cnode++) { - client_nasid = COMPACT_TO_NASID_NODEID(cnode); - - /* Check if this node should get a copy of the kernel */ - if (CPUMASK_TSTB(ktext_repmask, cnode)) { - server_nasid = client_nasid; - copy_kernel(server_nasid); - } - - /* Record where this node should get its kernel text */ - set_ktext_source(client_nasid, server_nasid); - } -} - -/* - * Return pfn of first free page of memory on a node. PROM may allocate - * data structures on the first couple of pages of the first slot of each - * node. If this is the case, getfirstfree(node) > getslotstart(node, 0). - */ -pfn_t node_getfirstfree(cnodeid_t cnode) -{ - unsigned long loadbase = CKSEG0; - nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode); - unsigned long offset; - -#ifdef CONFIG_MAPPED_KERNEL - loadbase = CKSSEG + 16777216; -#endif - offset = PAGE_ALIGN((unsigned long)(&_end)) - loadbase; - if ((cnode == 0) || (CPUMASK_TSTB(ktext_repmask, cnode))) - return (TO_NODE(nasid, offset) >> PAGE_SHIFT); - else - return (KDM_TO_PHYS(PAGE_ALIGN(SYMMON_STK_ADDR(nasid, 0))) >> - PAGE_SHIFT); -} - diff -Nru a/arch/mips64/sgi-ip27/ip27-memory.c b/arch/mips64/sgi-ip27/ip27-memory.c --- a/arch/mips64/sgi-ip27/ip27-memory.c Tue Jul 1 18:44:33 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,337 +0,0 @@ -/* - * 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) 2000 by Ralf Baechle - * Copyright (C) 2000 by Silicon Graphics, Inc. - * - * On SGI IP27 the ARC memory configuration data is completly bogus but - * alternate easier to use mechanisms are available. - */ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* ip27-klnuma.c */ -extern pfn_t node_getfirstfree(cnodeid_t cnode); - -#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) -#define SLOT_IGNORED 0xffff - -short slot_lastfilled_cache[MAX_COMPACT_NODES]; -unsigned short slot_psize_cache[MAX_COMPACT_NODES][MAX_MEM_SLOTS]; -static pfn_t numpages; - -plat_pg_data_t *plat_node_data[MAX_COMPACT_NODES]; -bootmem_data_t plat_node_bdata[MAX_COMPACT_NODES]; - -int numa_debug(void) -{ - printk("NUMA debug\n"); - *(int *)0 = 0; - return(0); -} - -/* - * Return the number of pages of memory provided by the given slot - * on the specified node. - */ -pfn_t slot_getsize(cnodeid_t node, int slot) -{ - return (pfn_t) slot_psize_cache[node][slot]; -} - -/* - * Return highest slot filled - */ -int node_getlastslot(cnodeid_t node) -{ - return (int) slot_lastfilled_cache[node]; -} - -/* - * Return the pfn of the last free page of memory on a node. - */ -pfn_t node_getmaxclick(cnodeid_t node) -{ - pfn_t slot_psize; - int slot; - - /* - * Start at the top slot. When we find a slot with memory in it, - * that's the winner. - */ - for (slot = (node_getnumslots(node) - 1); slot >= 0; slot--) { - if ((slot_psize = slot_getsize(node, slot))) { - if (slot_psize == SLOT_IGNORED) - continue; - /* Return the basepfn + the slot size, minus 1. */ - return slot_getbasepfn(node, slot) + slot_psize - 1; - } - } - - /* - * If there's no memory on the node, return 0. This is likely - * to cause problems. - */ - return (pfn_t)0; -} - -static pfn_t slot_psize_compute(cnodeid_t node, int slot) -{ - nasid_t nasid; - lboard_t *brd; - klmembnk_t *banks; - unsigned long size; - - nasid = COMPACT_TO_NASID_NODEID(node); - /* Find the node board */ - brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27); - if (!brd) - return 0; - - /* Get the memory bank structure */ - banks = (klmembnk_t *)find_first_component(brd, KLSTRUCT_MEMBNK); - if (!banks) - return 0; - - /* Size in _Megabytes_ */ - size = (unsigned long)banks->membnk_bnksz[slot/4]; - - /* hack for 128 dimm banks */ - if (size <= 128) { - if (slot%4 == 0) { - size <<= 20; /* size in bytes */ - return(size >> PAGE_SHIFT); - } else { - return 0; - } - } else { - size /= 4; - size <<= 20; - return(size >> PAGE_SHIFT); - } -} - -pfn_t szmem(pfn_t fpage, pfn_t maxpmem) -{ - cnodeid_t node; - int slot, numslots; - pfn_t num_pages = 0, slot_psize; - pfn_t slot0sz = 0, nodebytes; /* Hack to detect problem configs */ - int ignore; - - for (node = 0; node < numnodes; node++) { - numslots = node_getnumslots(node); - ignore = nodebytes = 0; - for (slot = 0; slot < numslots; slot++) { - slot_psize = slot_psize_compute(node, slot); - if (slot == 0) slot0sz = slot_psize; - /* - * We need to refine the hack when we have replicated - * kernel text. - */ - nodebytes += SLOT_SIZE; - if ((nodebytes >> PAGE_SHIFT) * (sizeof(struct page)) > - (slot0sz << PAGE_SHIFT)) - ignore = 1; - if (ignore && slot_psize) { - printk("Ignoring slot %d onwards on node %d\n", - slot, node); - slot_psize_cache[node][slot] = SLOT_IGNORED; - slot = numslots; - continue; - } - num_pages += slot_psize; - slot_psize_cache[node][slot] = - (unsigned short) slot_psize; - if (slot_psize) - slot_lastfilled_cache[node] = slot; - } - } - if (maxpmem) - return((maxpmem > num_pages) ? num_pages : maxpmem); - else - return num_pages; -} - -/* - * Currently, the intranode memory hole support assumes that each slot - * contains at least 32 MBytes of memory. We assume all bootmem data - * fits on the first slot. - */ -void __init prom_meminit(void) -{ - extern void mlreset(void); - cnodeid_t node; - pfn_t slot_firstpfn, slot_lastpfn, slot_freepfn; - unsigned long bootmap_size; - int node_datasz; - - node_datasz = PFN_UP(sizeof(plat_pg_data_t)); - mlreset(); - numpages = szmem(0, 0); - for (node = (numnodes - 1); node >= 0; node--) { - slot_firstpfn = slot_getbasepfn(node, 0); - slot_lastpfn = slot_firstpfn + slot_getsize(node, 0); - slot_freepfn = node_getfirstfree(node); - /* Foll line hack for non discontigmem; remove once discontigmem - * becomes the default. */ - max_low_pfn = (slot_lastpfn - slot_firstpfn); - - /* - * Allocate the node data structure on the node first. - */ - plat_node_data[node] = (plat_pg_data_t *)(__va(slot_freepfn \ - << PAGE_SHIFT)); - NODE_DATA(node)->bdata = plat_node_bdata + node; - slot_freepfn += node_datasz; - bootmap_size = init_bootmem_node(NODE_DATA(node), slot_freepfn, - slot_firstpfn, slot_lastpfn); - free_bootmem_node(NODE_DATA(node), slot_firstpfn << PAGE_SHIFT, - (slot_lastpfn - slot_firstpfn) << PAGE_SHIFT); - reserve_bootmem_node(NODE_DATA(node), slot_firstpfn << PAGE_SHIFT, - ((slot_freepfn - slot_firstpfn) << PAGE_SHIFT) + bootmap_size); - } - printk("Total memory probed : 0x%lx pages\n", numpages); -} - -int __init page_is_ram(unsigned long pagenr) -{ - return 1; -} - -void __init -prom_free_prom_memory (void) -{ - /* We got nothing to free here ... */ -} - -#ifdef CONFIG_DISCONTIGMEM - -static pfn_t pagenr = 0; - -void __init paging_init(void) -{ - pmd_t *pmd = kpmdtbl; - pte_t *pte = kptbl; - - cnodeid_t node; - unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0}; - int i; - - /* Initialize the entire pgd. */ - pgd_init((unsigned long)swapper_pg_dir); - pmd_init((unsigned long)invalid_pmd_table, (unsigned long)invalid_pte_table); - memset((void *)invalid_pte_table, 0, sizeof(pte_t) * PTRS_PER_PTE); - - /* This is for vmalloc */ - memset((void *)kptbl, 0, PAGE_SIZE << KPTBL_PAGE_ORDER); - memset((void *)kpmdtbl, 0, PAGE_SIZE); - pgd_set(swapper_pg_dir, kpmdtbl); - for (i = 0; i < (1 << KPTBL_PAGE_ORDER); pmd++,i++,pte+=PTRS_PER_PTE) - pmd_val(*pmd) = (unsigned long)pte; - - for (node = 0; node < numnodes; node++) { - pfn_t start_pfn = slot_getbasepfn(node, 0); - pfn_t end_pfn = node_getmaxclick(node); - - zones_size[ZONE_DMA] = end_pfn + 1 - start_pfn; - free_area_init_node(node, NODE_DATA(node), 0, zones_size, - start_pfn, 0); - } -} - -void __init mem_init(void) -{ - extern char _stext, _etext, _fdata, _edata; - extern char __init_begin, __init_end; - extern unsigned long setup_zero_pages(void); - cnodeid_t nid; - unsigned long tmp; - unsigned long codesize, datasize, initsize; - int slot, numslots; - struct page *pg, *pslot; - - num_physpages = numpages; /* memory already sized by szmem */ - max_mapnr = pagenr; /* already found during paging_init */ - high_memory = (void *) __va(max_mapnr << PAGE_SHIFT); - - for (nid = 0; nid < numnodes; nid++) { - - /* - * Hack till free_area_init_core() zeroes free_pages - */ - for (tmp = 0; tmp < MAX_NR_ZONES; tmp++) - PLAT_NODE_DATA(nid)->gendata.node_zones[tmp].free_pages=0; - /* - * This will free up the bootmem, ie, slot 0 memory. - */ - totalram_pages += free_all_bootmem_node(NODE_DATA(nid)); - - /* - * We need to manually do the other slots. - */ - pg = NODE_DATA(nid)->node_mem_map + slot_getsize(nid, 0); - numslots = node_getlastslot(nid); - for (slot = 1; slot <= numslots; slot++) { - pslot = NODE_DATA(nid)->node_mem_map + - slot_getbasepfn(nid, slot) - slot_getbasepfn(nid, 0); - - /* - * Mark holes in previous slot. May also want to - * free up the pages that hold the memmap entries. - */ - while (pg < pslot) { - pg++; - } - - /* - * Free valid memory in current slot. - */ - pslot += slot_getsize(nid, slot); - while (pg < pslot) { - /* if (!page_is_ram(pgnr)) continue; */ - /* commented out until page_is_ram works */ - ClearPageReserved(pg); - atomic_set(&pg->count, 1); - __free_page(pg); - totalram_pages++; - pg++; pgnr++; - } - } - } - - totalram_pages -= setup_zero_pages(); /* This comes from node 0 */ - - codesize = (unsigned long) &_etext - (unsigned long) &_stext; - datasize = (unsigned long) &_edata - (unsigned long) &_fdata; - initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin; - - tmp = (unsigned long) nr_free_pages(); - printk("Memory: %luk/%luk available (%ldk kernel code, %ldk reserved, " - "%ldk data, %ldk init)\n", - tmp << (PAGE_SHIFT-10), - num_physpages << (PAGE_SHIFT-10), - codesize >> 10, - (num_physpages - tmp) << (PAGE_SHIFT-10), - datasize >> 10, - initsize >> 10); -} - -#endif /* CONFIG_DISCONTIGMEM */ diff -Nru a/arch/mips64/sgi-ip27/ip27-nmi.c b/arch/mips64/sgi-ip27/ip27-nmi.c --- a/arch/mips64/sgi-ip27/ip27-nmi.c Tue Jul 1 18:44:31 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,168 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if 0 -#define NODE_NUM_CPUS(n) CNODE_NUM_CPUS(n) -#else -#define NODE_NUM_CPUS(n) CPUS_PER_NODE -#endif - -#define CNODEID_NONE (cnodeid_t)-1 -#define enter_panic_mode() spin_lock(&nmi_lock) - -typedef unsigned long machreg_t; - -spinlock_t nmi_lock = SPIN_LOCK_UNLOCKED; - -/* - * Lets see what else we need to do here. Set up sp, gp? - */ -void nmi_dump(void) -{ - void cont_nmi_dump(void); - - cont_nmi_dump(); -} - -void install_cpu_nmi_handler(int slice) -{ - nmi_t *nmi_addr; - - nmi_addr = (nmi_t *)NMI_ADDR(get_nasid(), slice); - if (nmi_addr->call_addr) - return; - nmi_addr->magic = NMI_MAGIC; - nmi_addr->call_addr = (void *)nmi_dump; - nmi_addr->call_addr_c = - (void *)(~((unsigned long)(nmi_addr->call_addr))); - nmi_addr->call_parm = 0; -} - -/* - * Copy the cpu registers which have been saved in the IP27prom format - * into the eframe format for the node under consideration. - */ - -void -nmi_cpu_eframe_save(nasid_t nasid, - int slice) -{ - int i, numberof_nmi_cpu_regs; - machreg_t *prom_format; - - /* Get the total number of registers being saved by the prom */ - numberof_nmi_cpu_regs = sizeof(struct reg_struct) / sizeof(machreg_t); - - /* Get the pointer to the current cpu's register set. */ - prom_format = - (machreg_t *)(TO_UNCAC(TO_NODE(nasid, IP27_NMI_KREGS_OFFSET)) + - slice * IP27_NMI_KREGS_CPU_SIZE); - - printk("NMI nasid %d: slice %d\n", nasid, slice); - for (i = 0; i < numberof_nmi_cpu_regs; i++) - printk("0x%lx ", prom_format[i]); - printk("\n\n"); -} - -/* - * Copy the cpu registers which have been saved in the IP27prom format - * into the eframe format for the node under consideration. - */ -void -nmi_node_eframe_save(cnodeid_t cnode) -{ - int cpu; - nasid_t nasid; - - /* Make sure that we have a valid node */ - if (cnode == CNODEID_NONE) - return; - - nasid = COMPACT_TO_NASID_NODEID(cnode); - if (nasid == INVALID_NASID) - return; - - /* Save the registers into eframe for each cpu */ - for(cpu = 0; cpu < NODE_NUM_CPUS(cnode); cpu++) - nmi_cpu_eframe_save(nasid, cpu); -} - -/* - * Save the nmi cpu registers for all cpus in the system. - */ -void -nmi_eframes_save(void) -{ - cnodeid_t cnode; - - for(cnode = 0 ; cnode < numnodes; cnode++) - nmi_node_eframe_save(cnode); -} - -void -cont_nmi_dump(void) -{ -#ifndef REAL_NMI_SIGNAL - static atomic_t nmied_cpus = ATOMIC_INIT(0); - - atomic_inc(&nmied_cpus); -#endif - /* - * Use enter_panic_mode to allow only 1 cpu to proceed - */ - enter_panic_mode(); - -#ifdef REAL_NMI_SIGNAL - /* - * Wait up to 15 seconds for the other cpus to respond to the NMI. - * If a cpu has not responded after 10 sec, send it 1 additional NMI. - * This is for 2 reasons: - * - sometimes a MMSC fail to NMI all cpus. - * - on 512p SN0 system, the MMSC will only send NMIs to - * half the cpus. Unfortunately, we don't know which cpus may be - * NMIed - it depends on how the site chooses to configure. - * - * Note: it has been measure that it takes the MMSC up to 2.3 secs to - * send NMIs to all cpus on a 256p system. - */ - for (i=0; i < 1500; i++) { - for (node=0; node < numnodes; node++) - if (NODEPDA(node)->dump_count == 0) - break; - if (node == numnodes) - break; - if (i == 1000) { - for (node=0; node < numnodes; node++) - if (NODEPDA(node)->dump_count == 0) { - cpu = CNODE_TO_CPU_BASE(node); - for (n=0; n < CNODE_NUM_CPUS(node); cpu++, n++) { - CPUMASK_SETB(nmied_cpus, cpu); - /* - * cputonasid, cputoslice - * needs kernel cpuid - */ - SEND_NMI((cputonasid(cpu)), (cputoslice(cpu))); - } - } - - } - udelay(10000); - } -#else - while (atomic_read(&nmied_cpus) != smp_num_cpus); -#endif - - /* - * Save the nmi cpu registers for all cpu in the eframe format. - */ - nmi_eframes_save(); - LOCAL_HUB_S(NI_PORT_RESET, NPR_PORTRESET | NPR_LOCALRESET); -} diff -Nru a/arch/mips64/sgi-ip27/ip27-pci-dma.c b/arch/mips64/sgi-ip27/ip27-pci-dma.c --- a/arch/mips64/sgi-ip27/ip27-pci-dma.c Tue Jul 1 18:44:36 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,164 +0,0 @@ -/* - * Dynamic DMA mapping support. - * - * On the Origin there is dynamic DMA address translation for all PCI DMA. - * However we don't use this facility yet but rely on the 2gb direct - * mapped DMA window for PCI64. So consistent alloc/free are merely page - * allocation/freeing. The rest of the dynamic DMA mapping interface is - * implemented in . So this code will fail with more than - * 2gb of memory. - */ -#include -#include -#include -#include -#include - -/* Pure 2^n version of get_order */ -extern __inline__ int __get_order(unsigned long size) -{ - int order; - - size = (size-1) >> (PAGE_SHIFT-1); - order = -1; - do { - size >>= 1; - order++; - } while (size); - return order; -} - -void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, - dma_addr_t *dma_handle) -{ - void *ret; - int gfp = GFP_ATOMIC; - int order = __get_order(size); - - if (hwdev == NULL || hwdev->dma_mask != 0xffffffff) - gfp |= GFP_DMA; - ret = (void *)__get_free_pages(gfp, order); - - if (ret != NULL) { - memset(ret, 0, size); - *dma_handle = (bus_to_baddr[hwdev->bus->number] | __pa(ret)); - } - - return ret; -} - -void pci_free_consistent(struct pci_dev *hwdev, size_t size, - void *vaddr, dma_addr_t dma_handle) -{ - free_pages((unsigned long)vaddr, __get_order(size)); -} - -/* - * Map a single buffer of the indicated size for DMA in streaming mode. - * The 32-bit bus address to use is returned. - * - * Once the device is given the dma address, the device owns this memory - * until either pci_unmap_single or pci_dma_sync_single is performed. - */ -dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size, - int direction) -{ - if (direction == PCI_DMA_NONE) - BUG(); - - return (bus_to_baddr[hwdev->bus->number] | __pa(ptr)); -} - -/* - * Unmap a single streaming mode DMA translation. The dma_addr and size - * must match what was provided for in a previous pci_map_single call. All - * other usages are undefined. - * - * After this call, reads by the cpu to the buffer are guaranteed to see - * whatever the device wrote there. - */ -void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, - size_t size, int direction) -{ - if (direction == PCI_DMA_NONE) - BUG(); - - /* Nothing to do */ -} - -/* - * Map a set of buffers described by scatterlist in streaming - * mode for DMA. This is the scather-gather version of the - * above pci_map_single interface. Here the scatter gather list - * elements are each tagged with the appropriate dma address - * and length. They are obtained via sg_dma_{address,length}(SG). - * - * NOTE: An implementation may be able to use a smaller number of - * DMA address/length pairs than there are SG table elements. - * (for example via virtual mapping capabilities) - * The routine returns the number of addr/length pairs actually - * used, at most nents. - * - * Device ownership issues as mentioned above for pci_map_single are - * the same here. - */ -int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, - int direction) -{ - int i; - - if (direction == PCI_DMA_NONE) - BUG(); - - /* Make sure that gcc doesn't leave the empty loop body. */ - for (i = 0; i < nents; i++, sg++) { - sg->address = (char *)(bus_to_baddr[hwdev->bus->number] | __pa(sg->address)); - } - - return nents; -} - -/* - * Unmap a set of streaming mode DMA translations. - * Again, cpu read rules concerning calls here are the same as for - * pci_unmap_single() above. - */ -void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, - int direction) -{ - if (direction == PCI_DMA_NONE) - BUG(); - - /* Nothing to do */ -} - -/* - * Make physical memory consistent for a single - * streaming mode DMA translation after a transfer. - * - * If you perform a pci_map_single() but wish to interrogate the - * buffer using the cpu, yet do not wish to teardown the PCI dma - * mapping, you must call this function before doing so. At the - * next point you give the PCI dma address back to the card, the - * device again owns the buffer. - */ -void pci_dma_sync_single(struct pci_dev *hwdev, dma_addr_t dma_handle, - size_t size, int direction) -{ - if (direction == PCI_DMA_NONE) - BUG(); -} - -/* - * Make physical memory consistent for a set of streaming - * mode DMA translations after a transfer. - * - * The same as pci_dma_sync_single but for a scatter-gather list, - * same rules and usage. - */ -void pci_dma_sync_sg(struct pci_dev *hwdev, struct scatterlist *sg, - int nelems, int direction) -{ - if (direction == PCI_DMA_NONE) - BUG(); -} diff -Nru a/arch/mips64/sgi-ip27/ip27-pci.c b/arch/mips64/sgi-ip27/ip27-pci.c --- a/arch/mips64/sgi-ip27/ip27-pci.c Tue Jul 1 18:44:36 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,406 +0,0 @@ -/* - * 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) 1999, 2000 Ralf Baechle (ralf@gnu.org) - * Copyright (C) 1999, 2000 Silicon Graphics, Inc. - */ -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Max #PCI busses we can handle; ie, max #PCI bridges. - */ -#define MAX_PCI_BUSSES 40 - -/* - * Max #PCI devices (like scsi controllers) we handle on a bus. - */ -#define MAX_DEVICES_PER_PCIBUS 8 - -/* - * No locking needed until PCI initialization is done parallely. - */ -int irqstore[MAX_PCI_BUSSES][MAX_DEVICES_PER_PCIBUS]; -int lastirq = BASE_PCI_IRQ; - -/* - * Translate from irq to software PCI bus number and PCI slot. - */ -int irq_to_bus[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS]; -int irq_to_slot[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS]; - -/* - * The Bridge ASIC supports both type 0 and type 1 access. Type 1 is - * not really documented, so right now I can't write code which uses it. - * Therefore we use type 0 accesses for now even though they won't work - * correcly for PCI-to-PCI bridges. - */ -#define CF0_READ_PCI_CFG(dev,where,value,bm,mask) \ -do { \ - bridge_t *bridge; \ - int slot = PCI_SLOT(dev->devfn); \ - int fn = PCI_FUNC(dev->devfn); \ - volatile u32 *addr; \ - u32 cf, __bit; \ - unsigned int bus_id = (unsigned) dev->bus->number; \ - \ - bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id], \ - bus_to_wid[bus_id]); \ - \ - if (dev->vendor == PCI_VENDOR_ID_SGI \ - && dev->device == PCI_DEVICE_ID_SGI_IOC3 \ - && ((where >= 0x14 && where < 0x40) || (where >= 0x48))) { \ - *value = 0; \ - return PCIBIOS_SUCCESSFUL; \ - } \ - \ - __bit = (((where) & (bm)) << 3); \ - addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; \ - if (get_dbe(cf, addr)) \ - return PCIBIOS_DEVICE_NOT_FOUND; \ - *value = (cf >> __bit) & (mask); \ - return PCIBIOS_SUCCESSFUL; \ -} while (0) - -static int -pci_conf0_read_config_byte(struct pci_dev *dev, int where, u8 *value) -{ - CF0_READ_PCI_CFG(dev,where,value,3,0xff); -} - -static int -pci_conf0_read_config_word(struct pci_dev *dev, int where, u16 *value) -{ - CF0_READ_PCI_CFG(dev,where,value,2,0xffff); -} - -static int -pci_conf0_read_config_dword(struct pci_dev *dev, int where, u32 *value) -{ - CF0_READ_PCI_CFG(dev,where,value,0,0xffffffff); -} - -#define CF0_WRITE_PCI_CFG(dev,where,value,bm,mask) \ -do { \ - bridge_t *bridge; \ - int slot = PCI_SLOT(dev->devfn); \ - int fn = PCI_FUNC(dev->devfn); \ - volatile u32 *addr; \ - u32 cf, __bit; \ - unsigned int bus_id = (unsigned) dev->bus->number; \ - \ - bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id], \ - bus_to_wid[bus_id]); \ - \ - if (dev->vendor == PCI_VENDOR_ID_SGI \ - && dev->device == PCI_DEVICE_ID_SGI_IOC3 \ - && ((where >= 0x14 && where < 0x40) || (where >= 0x48))) \ - return PCIBIOS_SUCCESSFUL; \ - \ - __bit = (((where) & (bm)) << 3); \ - addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; \ - if (get_dbe(cf, addr)) \ - return PCIBIOS_DEVICE_NOT_FOUND; \ - cf &= (~mask); \ - cf |= (value); \ - put_dbe(cf, addr); \ - return PCIBIOS_SUCCESSFUL; \ -} while (0) - -static int -pci_conf0_write_config_byte(struct pci_dev *dev, int where, u8 value) -{ - CF0_WRITE_PCI_CFG(dev,where,value,3,0xff); -} - -static int -pci_conf0_write_config_word(struct pci_dev *dev, int where, u16 value) -{ - CF0_WRITE_PCI_CFG(dev,where,value,2,0xffff); -} - -static int -pci_conf0_write_config_dword(struct pci_dev *dev, int where, u32 value) -{ - CF0_WRITE_PCI_CFG(dev,where,value,0,0xffffffff); -} - - -static struct pci_ops bridge_pci_ops = { - pci_conf0_read_config_byte, - pci_conf0_read_config_word, - pci_conf0_read_config_dword, - pci_conf0_write_config_byte, - pci_conf0_write_config_word, - pci_conf0_write_config_dword -}; - -void __init pcibios_init(void) -{ - struct pci_ops *ops = &bridge_pci_ops; - int i; - - ioport_resource.end = ~0UL; - - for (i=0; ibus->self) { /* Move up the chain of bridges. */ - pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)); - dev = dev->bus->self; - } - *pinp = pin; - - return PCI_SLOT(dev->devfn); -} - -/* - * All observed requests have pin == 1. We could have a global here, that - * gets incremented and returned every time - unfortunately, pci_map_irq - * may be called on the same device over and over, and need to return the - * same value. On O2000, pin can be 0 or 1, and PCI slots can be [0..7]. - * - * A given PCI device, in general, should be able to intr any of the cpus - * on any one of the hubs connected to its xbow. - */ -static int __init -pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin) -{ - if ((dev->bus->number >= MAX_PCI_BUSSES) - || (pin != 1) - || (slot >= MAX_DEVICES_PER_PCIBUS)) - panic("Increase supported PCI busses %d,%d,%d\n", - dev->bus->number, slot, pin); - - /* - * Already assigned? Then return previously assigned value ... - */ - if (irqstore[dev->bus->number][slot]) - return irqstore[dev->bus->number][slot]; - - irq_to_bus[lastirq] = dev->bus->number; - irq_to_slot[lastirq] = slot; - irqstore[dev->bus->number][slot] = lastirq; - lastirq++; - return lastirq - 1; -} - -void __init -pcibios_update_irq(struct pci_dev *dev, int irq) -{ - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); -} - -#warning pcibios_update_resource() is now a generic implementation - please check - -void __init -pcibios_fixup_bus(struct pci_bus *b) -{ - pci_fixup_irqs(pci_swizzle, pci_map_irq); -} - -int __init -pcibios_enable_device(struct pci_dev *dev) -{ - /* Not needed, since we enable all devices at startup. */ - return 0; -} - -void __init -pcibios_align_resource(void *data, struct resource *res, - unsigned long size, unsigned long align) -{ -} - -unsigned __init int pcibios_assign_all_busses(void) -{ - return 0; -} - -char * __init -pcibios_setup(char *str) -{ - /* Nothing to do for now. */ - - return str; -} - -/* - * Device might live on a subordinate PCI bus. XXX Walk up the chain of buses - * to find the slot number in sense of the bridge device register. - * XXX This also means multiple devices might rely on conflicting bridge - * settings. - */ - -static void __init -pci_disable_swapping(struct pci_dev *dev) -{ - unsigned int bus_id = (unsigned) dev->bus->number; - bridge_t *bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id], - bus_to_wid[bus_id]); - int slot = PCI_SLOT(dev->devfn); - - /* Turn off byte swapping */ - bridge->b_device[slot].reg &= ~BRIDGE_DEV_SWAP_DIR; - bridge->b_widget.w_tflush; /* Flush */ -} - -static void __init -pci_enable_swapping(struct pci_dev *dev) -{ - unsigned int bus_id = (unsigned) dev->bus->number; - bridge_t *bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id], - bus_to_wid[bus_id]); - int slot = PCI_SLOT(dev->devfn); - - /* Turn on byte swapping */ - bridge->b_device[slot].reg |= BRIDGE_DEV_SWAP_DIR; - bridge->b_widget.w_tflush; /* Flush */ -} - -static void __init -pci_fixup_ioc3(struct pci_dev *d) -{ - unsigned long bus_id = (unsigned) d->bus->number; - - printk("PCI: Fixing base addresses for IOC3 device %s\n", d->slot_name); - - d->resource[0].start |= NODE_OFFSET(bus_to_nid[bus_id]); - d->resource[0].end |= NODE_OFFSET(bus_to_nid[bus_id]); - - pci_disable_swapping(d); -} - -static void __init -pci_fixup_isp1020(struct pci_dev *d) -{ - unsigned short command; - - d->resource[0].start |= ((unsigned long)(bus_to_nid[d->bus->number])<<32); - printk("PCI: Fixing isp1020 in [bus:slot.fn] %s\n", d->slot_name); - - /* - * Configure device to allow bus mastering, i/o and memory mapping. - * Older qlogicisp driver expects to have the IO space enable - * bit set. Things stop working if we program the controllers as not - * having PCI_COMMAND_MEMORY, so we have to fudge the mem_flags. - */ - - pci_set_master(d); - pci_read_config_word(d, PCI_COMMAND, &command); - command |= PCI_COMMAND_MEMORY; - command |= PCI_COMMAND_IO; - pci_write_config_word(d, PCI_COMMAND, command); - d->resource[1].flags |= 1; - - pci_enable_swapping(d); -} - -static void __init -pci_fixup_isp2x00(struct pci_dev *d) -{ - unsigned int bus_id = (unsigned) d->bus->number; - bridge_t *bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id], - bus_to_wid[bus_id]); - bridgereg_t devreg; - int i; - int slot = PCI_SLOT(d->devfn); - unsigned int start; - unsigned short command; - - printk("PCI: Fixing isp2x00 in [bus:slot.fn] %s\n", d->slot_name); - - /* set the resource struct for this device */ - start = (u32) (u64)bridge; /* yes, we want to lose the upper 32 bits here */ - start |= BRIDGE_DEVIO(slot); - - d->resource[0].start = start; - d->resource[0].end = d->resource[0].start + 0xff; - d->resource[0].flags = IORESOURCE_IO; - - d->resource[1].start = start; - d->resource[1].end = d->resource[0].start + 0xfff; - d->resource[1].flags = IORESOURCE_MEM; - - /* - * set the bridge device(x) reg for this device - */ - devreg = bridge->b_device[slot].reg; - /* point device(x) to it appropriate small window */ - devreg &= ~BRIDGE_DEV_OFF_MASK; - devreg |= (start >> 20) & BRIDGE_DEV_OFF_MASK; - bridge->b_device[slot].reg = devreg; - - pci_enable_swapping(d); - - /* set card's base addr reg */ - //pci_conf0_write_config_dword(d, PCI_BASE_ADDRESS_0, 0x500001); - //pci_conf0_write_config_dword(d, PCI_BASE_ADDRESS_1, 0x8b00000); - //pci_conf0_write_config_dword(d, PCI_ROM_ADDRESS, 0x8b20000); - - /* I got these from booting irix on system...*/ - pci_conf0_write_config_dword(d, PCI_BASE_ADDRESS_0, 0x200001); - //pci_conf0_write_config_dword(d, PCI_BASE_ADDRESS_1, 0xf800000); - pci_conf0_write_config_dword(d, PCI_ROM_ADDRESS, 0x10200000); - - pci_conf0_write_config_dword(d, PCI_BASE_ADDRESS_1, start); - //pci_conf0_write_config_dword(d, PCI_ROM_ADDRESS, (start | 0x20000)); - - /* set cache line size */ - pci_conf0_write_config_dword(d, PCI_CACHE_LINE_SIZE, 0xf080); - - /* set pci bus timeout */ - bridge->b_bus_timeout |= BRIDGE_BUS_PCI_RETRY_HLD(0x3); - bridge->b_wid_tflush; - printk("PCI: bridge bus timeout= 0x%x \n", bridge->b_bus_timeout); - - /* set host error field */ - bridge->b_int_host_err = 0x44; - bridge->b_wid_tflush; - - bridge->b_wid_tflush; /* wait until Bridge PIO complete */ - for (i=0; i<8; i++) - printk("PCI: device(%d)= 0x%x\n",i,bridge->b_device[i].reg); - - /* configure device to allow bus mastering, i/o and memory mapping */ - pci_set_master(d); - pci_read_config_word(d, PCI_COMMAND, &command); - command |= PCI_COMMAND_MEMORY; - command |= PCI_COMMAND_IO; - pci_write_config_word(d, PCI_COMMAND, command); - /*d->resource[1].flags |= 1;*/ -} - -struct pci_fixup pcibios_fixups[] = { - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, - pci_fixup_ioc3 }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1020, - pci_fixup_isp1020 }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2100, - pci_fixup_isp2x00 }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2200, - pci_fixup_isp2x00 }, - { 0 } -}; diff -Nru a/arch/mips64/sgi-ip27/ip27-reset.c b/arch/mips64/sgi-ip27/ip27-reset.c --- a/arch/mips64/sgi-ip27/ip27-reset.c Tue Jul 1 18:44:35 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,76 +0,0 @@ -/* - * 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. - * - * Reset an IP27. - * - * Copyright (C) 1997, 1998, 1999, 2000 by Ralf Baechle - * Copyright (C) 1999, 2000 Silicon Graphics, Inc. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -void machine_restart(char *command) __attribute__((noreturn)); -void machine_halt(void) __attribute__((noreturn)); -void machine_power_off(void) __attribute__((noreturn)); - -#define noreturn while(1); /* Silence gcc. */ - -/* XXX How to pass the reboot command to the firmware??? */ -void machine_restart(char *command) -{ -#if 0 - int i; -#endif - - printk("Reboot started from CPU %d\n", smp_processor_id()); -#ifdef CONFIG_SMP - smp_send_stop(); -#endif -#if 0 - for (i = 0; i < numnodes; i++) - REMOTE_HUB_S(COMPACT_TO_NASID_NODEID(i), PROMOP_REG, - PROMOP_REBOOT); -#else - LOCAL_HUB_S(NI_PORT_RESET, NPR_PORTRESET | NPR_LOCALRESET); -#endif - noreturn; -} - -void machine_halt(void) -{ - int i; - -#ifdef CONFIG_SMP - smp_send_stop(); -#endif - for (i = 0; i < numnodes; i++) - REMOTE_HUB_S(COMPACT_TO_NASID_NODEID(i), PROMOP_REG, - PROMOP_RESTART); - LOCAL_HUB_S(NI_PORT_RESET, NPR_PORTRESET | NPR_LOCALRESET); - noreturn; -} - -void machine_power_off(void) -{ - /* To do ... */ - noreturn; -} - -void ip27_reboot_setup(void) -{ - /* Nothing to do on IP27. */ -} diff -Nru a/arch/mips64/sgi-ip27/ip27-rtc.c b/arch/mips64/sgi-ip27/ip27-rtc.c --- a/arch/mips64/sgi-ip27/ip27-rtc.c Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,319 +0,0 @@ -/* - * Driver for the SGS-Thomson M48T35 Timekeeper RAM chip - * - * Real Time Clock interface for Linux - * - * TODO: Implement periodic interrupts. - * - * Copyright (C) 2000 Silicon Graphics, Inc. - * Written by Ulf Carlsson (ulfc@engr.sgi.com) - * - * Based on code written by Paul Gortmaker. - * - * This driver allows use of the real time clock (built into - * nearly all computers) from user space. It exports the /dev/rtc - * interface supporting various ioctl() and also the /proc/rtc - * pseudo-file for status information. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - */ - -#define RTC_VERSION "1.09b" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -static int rtc_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg); - -static int rtc_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data); - -static void get_rtc_time(struct rtc_time *rtc_tm); - -static atomic_t rtc_ready = ATOMIC_INIT(1); -static unsigned long rtc_freq; /* Current periodic IRQ rate */ -static struct m48t35_rtc *rtc; - -/* - * If this driver ever becomes modularised, it will be really nice - * to make the epoch retain its value across module reload... - */ - -static unsigned long epoch = 1970; /* year corresponding to 0x00 */ - -static const unsigned char days_in_mo[] = -{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; - -static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) -{ - - struct rtc_time wtime; - - switch (cmd) { - case RTC_RD_TIME: /* Read the time/date from RTC */ - { - get_rtc_time(&wtime); - break; - } - case RTC_SET_TIME: /* Set the RTC */ - { - struct rtc_time rtc_tm; - unsigned char mon, day, hrs, min, sec, leap_yr; - unsigned int yrs; - unsigned long flags; - - if (!capable(CAP_SYS_TIME)) - return -EACCES; - - if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, - sizeof(struct rtc_time))) - return -EFAULT; - - yrs = rtc_tm.tm_year + 1900; - mon = rtc_tm.tm_mon + 1; /* tm_mon starts at zero */ - day = rtc_tm.tm_mday; - hrs = rtc_tm.tm_hour; - min = rtc_tm.tm_min; - sec = rtc_tm.tm_sec; - - if (yrs < 1970) - return -EINVAL; - - leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400)); - - if ((mon > 12) || (day == 0)) - return -EINVAL; - - if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr))) - return -EINVAL; - - if ((hrs >= 24) || (min >= 60) || (sec >= 60)) - return -EINVAL; - - if ((yrs -= epoch) > 255) /* They are unsigned */ - return -EINVAL; - - save_flags(flags); - cli(); - if (yrs > 169) { - restore_flags(flags); - return -EINVAL; - } - if (yrs >= 100) - yrs -= 100; - - BIN_TO_BCD(sec); - BIN_TO_BCD(min); - BIN_TO_BCD(hrs); - BIN_TO_BCD(day); - BIN_TO_BCD(mon); - BIN_TO_BCD(yrs); - - rtc->control &= ~M48T35_RTC_SET; - rtc->year = yrs; - rtc->month = mon; - rtc->date = day; - rtc->hour = hrs; - rtc->min = min; - rtc->sec = sec; - rtc->control &= ~M48T35_RTC_SET; - - restore_flags(flags); - return 0; - } - default: - return -EINVAL; - } - return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0; -} - -/* - * We enforce only one user at a time here with the open/close. - * Also clear the previous interrupt data on an open, and clean - * up things on a close. - */ - -static int rtc_open(struct inode *inode, struct file *file) -{ - if( atomic_dec_and_test( &rtc_ready ) ) - { - atomic_inc( &rtc_ready ); - return -EBUSY; - } - return 0; -} - -static int rtc_release(struct inode *inode, struct file *file) -{ - atomic_inc( &rtc_ready ); - return 0; -} - -/* - * The various file operations we support. - */ - -static struct file_operations rtc_fops = { - .owner = THIS_MODULE, - .ioctl = rtc_ioctl, - .open = rtc_open, - .release = rtc_release, -}; - -static struct miscdevice rtc_dev= -{ - RTC_MINOR, - "rtc", - &rtc_fops -}; - -static int __init rtc_init(void) -{ - unsigned long flags; - nasid_t nid; - - nid = get_nasid(); - rtc = (struct m48t35_rtc *) - KL_CONFIG_CH_CONS_INFO(nid)->memory_base + IOC3_BYTEBUS_DEV0; - - printk(KERN_INFO "Real Time Clock Driver v%s\n", RTC_VERSION); - if (misc_register(&rtc_dev)) { - printk(KERN_ERR "rtc: cannot register misc device.\n"); - return -ENODEV; - } - if (!create_proc_read_entry ("rtc", 0, NULL, rtc_read_proc, NULL)) { - printk(KERN_ERR "rtc: cannot create /proc/rtc.\n"); - misc_deregister(&rtc_dev); - return -ENOENT; - } - - save_flags(flags); - cli(); - restore_flags(flags); - rtc_freq = 1024; - return 0; -} - -static void __exit rtc_exit (void) -{ - /* interrupts and timer disabled at this point by rtc_release */ - - remove_proc_entry ("rtc", NULL); - misc_deregister(&rtc_dev); -} - -module_init(rtc_init); -module_exit(rtc_exit); - -/* - * Info exported via "/proc/rtc". - */ - -static int rtc_get_status(char *buf) -{ - char *p; - struct rtc_time tm; - - /* - * Just emulate the standard /proc/rtc - */ - - p = buf; - - get_rtc_time(&tm); - - /* - * There is no way to tell if the luser has the RTC set for local - * time or for Universal Standard Time (GMT). Probably local though. - */ - p += sprintf(p, - "rtc_time\t: %02d:%02d:%02d\n" - "rtc_date\t: %04d-%02d-%02d\n" - "rtc_epoch\t: %04lu\n" - "24hr\t\t: yes\n", - tm.tm_hour, tm.tm_min, tm.tm_sec, - tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, epoch); - - return p - buf; -} - -static int rtc_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len = rtc_get_status(page); - if (len <= off+count) *eof = 1; - *start = page + off; - len -= off; - if (len>count) len = count; - if (len<0) len = 0; - return len; -} - -static void get_rtc_time(struct rtc_time *rtc_tm) -{ - - unsigned long flags; - - /* - * Do we need to wait for the last update to finish? - */ - - /* - * Only the values that we read from the RTC are set. We leave - * tm_wday, tm_yday and tm_isdst untouched. Even though the - * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated - * by the RTC when initially set to a non-zero value. - */ - save_flags(flags); - cli(); - rtc->control |= M48T35_RTC_READ; - rtc_tm->tm_sec = rtc->sec; - rtc_tm->tm_min = rtc->min; - rtc_tm->tm_hour = rtc->hour; - rtc_tm->tm_mday = rtc->date; - rtc_tm->tm_mon = rtc->month; - rtc_tm->tm_year = rtc->year; - rtc->control &= ~M48T35_RTC_READ; - restore_flags(flags); - - BCD_TO_BIN(rtc_tm->tm_sec); - BCD_TO_BIN(rtc_tm->tm_min); - BCD_TO_BIN(rtc_tm->tm_hour); - BCD_TO_BIN(rtc_tm->tm_mday); - BCD_TO_BIN(rtc_tm->tm_mon); - BCD_TO_BIN(rtc_tm->tm_year); - - /* - * Account for differences between how the RTC uses the values - * and how they are defined in a struct rtc_time; - */ - if ((rtc_tm->tm_year += (epoch - 1900)) <= 69) - rtc_tm->tm_year += 100; - - rtc_tm->tm_mon--; -} diff -Nru a/arch/mips64/sgi-ip27/ip27-setup.c b/arch/mips64/sgi-ip27/ip27-setup.c --- a/arch/mips64/sgi-ip27/ip27-setup.c Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,310 +0,0 @@ -/* - * 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. - * - * SGI IP27 specific setup. - * - * Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org) - * Copyright (C) 1999, 2000 Silcon Graphics, Inc. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Check against user dumbness. */ -#ifdef CONFIG_VT -#error CONFIG_VT not allowed for IP27. -#endif - -#undef DEBUG_SETUP -#ifdef DEBUG_SETUP -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - -unsigned long mips_io_port_base = IO_BASE; - -/* - * get_nasid() returns the physical node id number of the caller. - */ -nasid_t -get_nasid(void) -{ - return (nasid_t)((LOCAL_HUB_L(NI_STATUS_REV_ID) & NSRI_NODEID_MASK) - >> NSRI_NODEID_SHFT); -} - -/* Extracted from the IOC3 meta driver. FIXME. */ -static inline void ioc3_sio_init(void) -{ - struct ioc3 *ioc3; - nasid_t nid; - long loops; - - nid = get_nasid(); - ioc3 = (struct ioc3 *) KL_CONFIG_CH_CONS_INFO(nid)->memory_base; - - ioc3->sscr_a = 0; /* PIO mode for uarta. */ - ioc3->sscr_b = 0; /* PIO mode for uartb. */ - ioc3->sio_iec = ~0; - ioc3->sio_ies = (SIO_IR_SA_INT | SIO_IR_SB_INT); - - loops=1000000; while(loops--); - ioc3->sregs.uarta.iu_fcr = 0; - ioc3->sregs.uartb.iu_fcr = 0; - loops=1000000; while(loops--); -} - -static inline void ioc3_eth_init(void) -{ - struct ioc3 *ioc3; - nasid_t nid; - - nid = get_nasid(); - ioc3 = (struct ioc3 *) KL_CONFIG_CH_CONS_INFO(nid)->memory_base; - - ioc3->eier = 0; -} - -/* Try to catch kernel missconfigurations and give user an indication what - option to select. */ -static void __init verify_mode(void) -{ - int n_mode; - - n_mode = LOCAL_HUB_L(NI_STATUS_REV_ID) & NSRI_MORENODES_MASK; - printk("Machine is in %c mode.\n", n_mode ? 'N' : 'M'); -#ifdef CONFIG_SGI_SN0_N_MODE - if (!n_mode) - panic("Kernel compiled for M mode."); -#else - if (n_mode) - panic("Kernel compiled for N mode."); -#endif -} - -#define XBOW_WIDGET_PART_NUM 0x0 -#define XXBOW_WIDGET_PART_NUM 0xd000 /* Xbridge */ -#define BASE_XBOW_PORT 8 /* Lowest external port */ - -unsigned int bus_to_cpu[256]; -unsigned long bus_to_baddr[256]; - -void __init pcibr_setup(cnodeid_t nid) -{ - int i, start, num; - unsigned long masterwid; - bridge_t *bridge; - volatile u64 hubreg; - nasid_t nasid, masternasid; - xwidget_part_num_t partnum; - widgetreg_t widget_id; - static spinlock_t pcibr_setup_lock = SPIN_LOCK_UNLOCKED; - - /* - * If the master is doing this for headless node, nothing to do. - * This is because currently we require at least one of the hubs - * (master hub) connected to the xbow to have at least one enabled - * cpu to receive intrs. Else we need an array bus_to_intrnasid[] - * that bridge_startup() needs to use to target intrs. All dma is - * routed thru the widget of the master hub. The master hub wid - * is selectable by WIDGET_A below. - */ - if (nid != get_compact_nodeid()) - return; - /* - * find what's on our local node - */ - spin_lock(&pcibr_setup_lock); - start = num_bridges; /* Remember where we start from */ - nasid = COMPACT_TO_NASID_NODEID(nid); - hubreg = REMOTE_HUB_L(nasid, IIO_LLP_CSR); - if (hubreg & IIO_LLP_CSR_IS_UP) { - /* link is up */ - widget_id = *(volatile widgetreg_t *) - (RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID); - partnum = XWIDGET_PART_NUM(widget_id); - printk("Cpu %d, Nasid 0x%x, pcibr_setup(): found partnum= 0x%x", - smp_processor_id(), nasid, partnum); - if (partnum == BRIDGE_WIDGET_PART_NUM) { - /* - * found direct connected bridge so must be Origin200 - */ - printk("...is bridge\n"); - num_bridges = 1; - bus_to_wid[0] = 0x8; - bus_to_nid[0] = 0; - masterwid = 0xa; - bus_to_baddr[0] = 0xa100000000000000UL; - } else if (partnum == XBOW_WIDGET_PART_NUM) { - lboard_t *brd; - klxbow_t *xbow_p; - /* - * found xbow, so may have multiple bridges - * need to probe xbow - */ - printk("...is xbow\n"); - - if ((brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), - KLTYPE_MIDPLANE8)) == NULL) - printk("argh\n"); - else - printk("brd = 0x%lx\n", (unsigned long) brd); - if ((xbow_p = (klxbow_t *) - find_component(brd, NULL, KLSTRUCT_XBOW)) == NULL) - printk("argh\n"); - else { - /* - * Okay, here's a xbow. Lets arbitrate and find - * out if we should initialize it. Set enabled - * hub connected at highest or lowest widget as - * master. - */ -#ifdef WIDGET_A - i = HUB_WIDGET_ID_MAX + 1; - do { - i--; - } while ((!XBOW_PORT_TYPE_HUB(xbow_p, i)) || - (!XBOW_PORT_IS_ENABLED(xbow_p, i))); -#else - i = HUB_WIDGET_ID_MIN - 1; - do { - i++; - } while ((!XBOW_PORT_TYPE_HUB(xbow_p, i)) || - (!XBOW_PORT_IS_ENABLED(xbow_p, i))); -#endif - masterwid = i; - masternasid = XBOW_PORT_NASID(xbow_p, i); - if (nasid == masternasid) - for (i=HUB_WIDGET_ID_MIN; i<=HUB_WIDGET_ID_MAX; i++) { - if (!XBOW_PORT_IS_ENABLED(xbow_p, i)) - continue; - if (XBOW_PORT_TYPE_IO(xbow_p, i)) { - widget_id = *(volatile widgetreg_t *) - (RAW_NODE_SWIN_BASE(nasid, i) + WIDGET_ID); - partnum = XWIDGET_PART_NUM(widget_id); - if (partnum == BRIDGE_WIDGET_PART_NUM) { - printk("widget 0x%x is a bridge\n", i); - bus_to_wid[num_bridges] = i; - bus_to_nid[num_bridges] = nasid; - bus_to_baddr[num_bridges] = ((masterwid << 60) | (1UL << 56)); /* Barrier set */ - num_bridges++; - } - } - } - } - } else if (partnum == XXBOW_WIDGET_PART_NUM) { - /* - * found xbridge, assume ibrick for now - */ - printk("...is xbridge\n"); - bus_to_wid[0] = 0xb; - bus_to_wid[1] = 0xe; - bus_to_wid[2] = 0xf; - - bus_to_nid[0] = 0; - bus_to_nid[1] = 0; - bus_to_nid[2] = 0; - - bus_to_baddr[0] = 0xa100000000000000UL; - bus_to_baddr[1] = 0xa100000000000000UL; - bus_to_baddr[2] = 0xa100000000000000UL; - masterwid = 0xa; - num_bridges = 3; - } - } - num = num_bridges - start; - spin_unlock(&pcibr_setup_lock); - /* - * set bridge registers - */ - for (i = start; i < (start + num); i++) { - - DBG("pcibr_setup: bus= %d bus_to_wid[%2d]= %d bus_to_nid[%2d]= %d\n", - i, i, bus_to_wid[i], i, bus_to_nid[i]); - - bus_to_cpu[i] = smp_processor_id(); - /* - * point to this bridge - */ - bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[i],bus_to_wid[i]); - /* - * Clear all pending interrupts. - */ - bridge->b_int_rst_stat = (BRIDGE_IRR_ALL_CLR); - /* - * Until otherwise set up, assume all interrupts are from slot 0 - */ - bridge->b_int_device = (u32) 0x0; - /* - * swap pio's to pci mem and io space (big windows) - */ - bridge->b_wid_control |= BRIDGE_CTRL_IO_SWAP; - bridge->b_wid_control |= BRIDGE_CTRL_MEM_SWAP; - - /* - * Hmm... IRIX sets additional bits in the address which - * are documented as reserved in the bridge docs. - */ - bridge->b_int_mode = 0x0; /* Don't clear ints */ - bridge->b_wid_int_upper = 0x8000 | (masterwid << 16); - bridge->b_wid_int_lower = 0x01800090; /* PI_INT_PEND_MOD off*/ - bridge->b_dir_map = (masterwid << 20); /* DMA */ - bridge->b_int_enable = 0; - - bridge->b_wid_tflush; /* wait until Bridge PIO complete */ - } -} - -extern void ip27_setup_console(void); - -void __init ip27_setup(void) -{ - nasid_t nid; - hubreg_t p, e; - - ip27_setup_console(); - - num_bridges = 0; - /* - * hub_rtc init and cpu clock intr enabled for later calibrate_delay. - */ - DBG("ip27_setup(): Entered.\n"); - nid = get_nasid(); - printk("IP27: Running on node %d.\n", nid); - - p = LOCAL_HUB_L(PI_CPU_PRESENT_A) & 1; - e = LOCAL_HUB_L(PI_CPU_ENABLE_A) & 1; - printk("Node %d has %s primary CPU%s.\n", nid, - p ? "a" : "no", - e ? ", CPU is running" : ""); - - p = LOCAL_HUB_L(PI_CPU_PRESENT_B) & 1; - e = LOCAL_HUB_L(PI_CPU_ENABLE_B) & 1; - printk("Node %d has %s secondary CPU%s.\n", nid, - p ? "a" : "no", - e ? ", CPU is running" : ""); - - verify_mode(); - ioc3_sio_init(); - ioc3_eth_init(); - per_cpu_init(); -} diff -Nru a/arch/mips64/sgi-ip27/ip27-timer.c b/arch/mips64/sgi-ip27/ip27-timer.c --- a/arch/mips64/sgi-ip27/ip27-timer.c Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,294 +0,0 @@ -/* - * Copytight (C) 1999, 2000 Ralf Baechle (ralf@gnu.org) - * Copytight (C) 1999, 2000 Silicon Graphics, Inc. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * This is a hack; we really need to figure these values out dynamically - * - * Since 800 ns works very well with various HUB frequencies, such as - * 360, 380, 390 and 400 MHZ, we use 800 ns rtc cycle time. - * - * Ralf: which clock rate is used to feed the counter? - */ -#define NSEC_PER_CYCLE 800 -#define NSEC_PER_SEC 1000000000 -#define CYCLES_PER_SEC (NSEC_PER_SEC/NSEC_PER_CYCLE) -#define CYCLES_PER_JIFFY (CYCLES_PER_SEC/HZ) - -static unsigned long ct_cur[NR_CPUS]; /* What counter should be at next timer irq */ -static long last_rtc_update; /* Last time the rtc clock got updated */ - -extern volatile unsigned long wall_jiffies; - - -static int set_rtc_mmss(unsigned long nowtime) -{ - int retval = 0; - int real_seconds, real_minutes, cmos_minutes; - struct m48t35_rtc *rtc; - nasid_t nid; - - nid = get_nasid(); - rtc = (struct m48t35_rtc *)(KL_CONFIG_CH_CONS_INFO(nid)->memory_base + - IOC3_BYTEBUS_DEV0); - - rtc->control |= M48T35_RTC_READ; - cmos_minutes = rtc->min; - BCD_TO_BIN(cmos_minutes); - rtc->control &= ~M48T35_RTC_READ; - - /* - * Since we're only adjusting minutes and seconds, don't interfere with - * hour overflow. This avoids messing with unknown time zones but - * requires your RTC not to be off by more than 15 minutes - */ - real_seconds = nowtime % 60; - real_minutes = nowtime / 60; - if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) - real_minutes += 30; /* correct for half hour time zone */ - real_minutes %= 60; - - if (abs(real_minutes - cmos_minutes) < 30) { - BIN_TO_BCD(real_seconds); - BIN_TO_BCD(real_minutes); - rtc->control |= M48T35_RTC_SET; - rtc->sec = real_seconds; - rtc->min = real_minutes; - rtc->control &= ~M48T35_RTC_SET; - } else { - printk(KERN_WARNING - "set_rtc_mmss: can't update from %d to %d\n", - cmos_minutes, real_minutes); - retval = -1; - } - - return retval; -} - -void rt_timer_interrupt(struct pt_regs *regs) -{ - int cpu = smp_processor_id(); - int cpuA = ((cputoslice(cpu)) == 0); - int irq = 7; /* XXX Assign number */ - - write_seqlock(&xtime_lock); - -again: - LOCAL_HUB_S(cpuA ? PI_RT_PEND_A : PI_RT_PEND_B, 0); /* Ack */ - ct_cur[cpu] += CYCLES_PER_JIFFY; - LOCAL_HUB_S(cpuA ? PI_RT_COMPARE_A : PI_RT_COMPARE_B, ct_cur[cpu]); - - if (LOCAL_HUB_L(PI_RT_COUNT) >= ct_cur[cpu]) - goto again; - - kstat_cpu(cpu).irqs[irq]++; /* kstat only for bootcpu? */ - - if (cpu == 0) - do_timer(regs); - -#ifdef CONFIG_SMP - { - int user = user_mode(regs); - - /* - * update_process_times() expects us to have done irq_enter(). - * Besides, if we don't timer interrupts ignore the global - * interrupt lock, which is the WrongThing (tm) to do. - * Picked from i386 code. - */ - irq_enter(cpu, 0); - update_process_times(user); - irq_exit(cpu, 0); - } -#endif /* CONFIG_SMP */ - - /* - * If we have an externally synchronized Linux clock, then update - * RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be - * called as close as possible to when a second starts. - */ - if ((time_status & STA_UNSYNC) == 0 && - xtime.tv_sec > last_rtc_update + 660) { - if (xtime.tv_usec >= 1000000 - ((unsigned) tick) / 2) { - if (set_rtc_mmss(xtime.tv_sec + 1) == 0) - last_rtc_update = xtime.tv_sec; - else - last_rtc_update = xtime.tv_sec - 600; - } else if (xtime.tv_usec <= ((unsigned) tick) / 2) { - if (set_rtc_mmss(xtime.tv_sec) == 0) - last_rtc_update = xtime.tv_sec; - else - last_rtc_update = xtime.tv_sec - 600; - } - } - - write_sequnlock(&xtime_lock); - - if (softirq_pending(cpu)) - do_softirq(); -} - -unsigned long inline do_gettimeoffset(void) -{ - unsigned long ct_cur1; - ct_cur1 = REMOTE_HUB_L(cputonasid(0), PI_RT_COUNT) + CYCLES_PER_JIFFY; - return (ct_cur1 - ct_cur[0]) * NSEC_PER_CYCLE / 1000; -} - -void do_gettimeofday(struct timeval *tv) -{ - unsigned long flags; - unsigned long usec, sec; - unsigned long seq; - - do { - seq = read_seqbegin_irqsave(&xtime_lock, flags); - - usec = do_gettimeoffset(); - { - unsigned long lost = jiffies - wall_jiffies; - if (lost) - usec += lost * (1000000 / HZ); - } - sec = xtime.tv_sec; - usec += xtime.tv_usec; - } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); - - while (usec >= 1000000) { - usec -= 1000000; - sec++; - } - - tv->tv_sec = sec; - tv->tv_usec = usec; -} - -void do_settimeofday(struct timeval *tv) -{ - write_seqlock_irq(&xtime_lock); - tv->tv_usec -= do_gettimeoffset(); - tv->tv_usec -= (jiffies - wall_jiffies) * (1000000 / HZ); - - while (tv->tv_usec < 0) { - tv->tv_usec += 1000000; - tv->tv_sec--; - } - - xtime = *tv; - time_adjust = 0; /* stop active adjtime() */ - time_status |= STA_UNSYNC; - time_maxerror = NTP_PHASE_LIMIT; - time_esterror = NTP_PHASE_LIMIT; - write_sequnlock_irq(&xtime_lock); -} - -/* Includes for ioc3_init(). */ -#include -#include -#include -#include -#include - -static __init unsigned long get_m48t35_time(void) -{ - unsigned int year, month, date, hour, min, sec; - struct m48t35_rtc *rtc; - nasid_t nid; - - nid = get_nasid(); - rtc = (struct m48t35_rtc *)(KL_CONFIG_CH_CONS_INFO(nid)->memory_base + - IOC3_BYTEBUS_DEV0); - - rtc->control |= M48T35_RTC_READ; - sec = rtc->sec; - min = rtc->min; - hour = rtc->hour; - date = rtc->date; - month = rtc->month; - year = rtc->year; - rtc->control &= ~M48T35_RTC_READ; - - BCD_TO_BIN(sec); - BCD_TO_BIN(min); - BCD_TO_BIN(hour); - BCD_TO_BIN(date); - BCD_TO_BIN(month); - BCD_TO_BIN(year); - - year += 1970; - - return mktime(year, month, date, hour, min, sec); -} - -void __init time_init(void) -{ - xtime.tv_sec = get_m48t35_time(); - xtime.tv_usec = 0; -} - -void __init cpu_time_init(void) -{ - lboard_t *board; - klcpu_t *cpu; - int cpuid; - - /* Don't use ARCS. ARCS is fragile. Klconfig is simple and sane. */ - board = find_lboard(KL_CONFIG_INFO(get_nasid()), KLTYPE_IP27); - if (!board) - panic("Can't find board info for myself."); - - cpuid = LOCAL_HUB_L(PI_CPU_NUM) ? IP27_CPU0_INDEX : IP27_CPU1_INDEX; - cpu = (klcpu_t *) KLCF_COMP(board, cpuid); - if (!cpu) - panic("No information about myself?"); - - printk("CPU %d clock is %dMHz.\n", smp_processor_id(), cpu->cpu_speed); - - set_cp0_status(SRB_TIMOCLK, SRB_TIMOCLK); -} - -void __init hub_rtc_init(cnodeid_t cnode) -{ - /* - * We only need to initialize the current node. - * If this is not the current node then it is a cpuless - * node and timeouts will not happen there. - */ - if (get_compact_nodeid() == cnode) { - int cpu = smp_processor_id(); - LOCAL_HUB_S(PI_RT_EN_A, 1); - LOCAL_HUB_S(PI_RT_EN_B, 1); - LOCAL_HUB_S(PI_PROF_EN_A, 0); - LOCAL_HUB_S(PI_PROF_EN_B, 0); - ct_cur[cpu] = CYCLES_PER_JIFFY; - LOCAL_HUB_S(PI_RT_COMPARE_A, ct_cur[cpu]); - LOCAL_HUB_S(PI_RT_COUNT, 0); - LOCAL_HUB_S(PI_RT_PEND_A, 0); - LOCAL_HUB_S(PI_RT_COMPARE_B, ct_cur[cpu]); - LOCAL_HUB_S(PI_RT_COUNT, 0); - LOCAL_HUB_S(PI_RT_PEND_B, 0); - } -} diff -Nru a/arch/mips64/sgi-ip32/Makefile b/arch/mips64/sgi-ip32/Makefile --- a/arch/mips64/sgi-ip32/Makefile Tue Jul 1 18:44:35 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,13 +0,0 @@ -# -# Makefile for the SGI specific kernel interface routines -# under Linux. -# - -extra-y := ip32-irq-glue.o - -obj-y += ip32-irq.o ip32-rtc.o ip32-setup.o ip32-irq-glue.o \ - ip32-berr.o ip32-timer.o crime.o - -obj-$(CONFIG_PCI) += ip32-pci.o ip32-pci-dma.o - -EXTRA_AFLAGS := $(CFLAGS) diff -Nru a/arch/mips64/sgi-ip32/crime.c b/arch/mips64/sgi-ip32/crime.c --- a/arch/mips64/sgi-ip32/crime.c Tue Jul 1 18:44:32 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,50 +0,0 @@ -/* - * 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) 2001 Keith M Wesolowski - */ -#include -#include -#include -#include -#include -#include - -void __init crime_init (void) -{ - u64 id = crime_read_64 (CRIME_ID); - u64 rev = id & CRIME_ID_REV; - - id = (id & CRIME_ID_IDBITS) >> 4; - - printk ("CRIME id %1lx rev %ld detected at %016lx\n", id, rev, - (unsigned long) CRIME_BASE); -} - -/* XXX Like on Sun, these give us various useful information to printk. */ -void crime_memerr_intr (unsigned int irq, void *dev_id, struct pt_regs *regs) -{ - u64 memerr = crime_read_64 (CRIME_MEM_ERROR_STAT); - u64 addr = crime_read_64 (CRIME_MEM_ERROR_ADDR); - memerr &= CRIME_MEM_ERROR_STAT_MASK; - - printk ("CRIME memory error at physaddr 0x%08lx status %08lx\n", - addr << 2, memerr); - - crime_write_64 (CRIME_MEM_ERROR_STAT, 0); -} - -void crime_cpuerr_intr (unsigned int irq, void *dev_id, struct pt_regs *regs) -{ - u64 cpuerr = crime_read_64 (CRIME_CPU_ERROR_STAT); - u64 addr = crime_read_64 (CRIME_CPU_ERROR_ADDR); - cpuerr &= CRIME_CPU_ERROR_MASK; - addr <<= 2UL; - - printk ("CRIME CPU interface error detected at %09lx status %08lx\n", - addr, cpuerr); - - crime_write_64 (CRIME_CPU_ERROR_STAT, 0); -} diff -Nru a/arch/mips64/sgi-ip32/ip32-berr.c b/arch/mips64/sgi-ip32/ip32-berr.c --- a/arch/mips64/sgi-ip32/ip32-berr.c Tue Jul 1 18:44:36 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,97 +0,0 @@ -/* - * 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, 1995, 1996, 1999, 2000 by Ralf Baechle - * Copyright (C) 1999, 2000 by Silicon Graphics - */ -#include -#include -#include -#include -#include -#include - -/* XXX I have no idea what this does --kmw */ - -extern asmlinkage void handle_ibe(void); -extern asmlinkage void handle_dbe(void); - -extern const struct exception_table_entry __start___dbe_table[]; -extern const struct exception_table_entry __stop___dbe_table[]; - -static inline unsigned long -search_one_table(const struct exception_table_entry *first, - const struct exception_table_entry *last, - unsigned long value) -{ - while (first <= last) { - const struct exception_table_entry *mid; - long diff; - - mid = (last - first) / 2 + first; - diff = mid->insn - value; - if (diff == 0) - return mid->nextinsn; - else if (diff < 0) - first = mid+1; - else - last = mid-1; - } - return 0; -} - -static inline unsigned long -search_dbe_table(unsigned long addr) -{ - unsigned long ret; - - /* There is only the kernel to search. */ - ret = search_one_table(__start___dbe_table, __stop___dbe_table-1, addr); - if (ret) return ret; - - return 0; -} - -void do_ibe(struct pt_regs *regs) -{ - printk("Got ibe at 0x%lx\n", regs->cp0_epc); - show_regs(regs); - dump_tlb_addr(regs->cp0_epc); - force_sig(SIGBUS, current); - while(1); -} - -void do_dbe(struct pt_regs *regs) -{ - unsigned long fixup; - - fixup = search_dbe_table(regs->cp0_epc); - if (fixup) { - long new_epc; - - new_epc = fixup_exception(dpf_reg, fixup, regs->cp0_epc); - regs->cp0_epc = new_epc; - return; - } - - printk("Got dbe at 0x%lx\n", regs->cp0_epc); - show_regs(regs); - dump_tlb_all(); - while(1); - force_sig(SIGBUS, current); -} - -void __init -bus_error_init(void) -{ - int dummy; - - set_except_vector(6, handle_ibe); - set_except_vector(7, handle_dbe); - - /* At this time nothing uses the DBE protection mechanism on the - O2, so this here is needed to make the kernel link. */ - get_dbe(dummy, (int *)KSEG0); -} diff -Nru a/arch/mips64/sgi-ip32/ip32-irq-glue.S b/arch/mips64/sgi-ip32/ip32-irq-glue.S --- a/arch/mips64/sgi-ip32/ip32-irq-glue.S Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,87 +0,0 @@ -/* - * Low level interrupt handler for the SGI O2 aka IP32 aka Moosehead - * - * 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) 2000 Harald Koerfgen - * Copyright (C) 2001 Keith M Wesolowski - */ -#include -#include -#include -#include -#include -#include - - .text - .set noreorder - .set noat - .align 5 - NESTED(ip32_handle_int, PT_SIZE, ra) - .set noat - SAVE_ALL - CLI # TEST: interrupts should be off - .set at - .set noreorder - - mfc0 s0,CP0_CAUSE - - andi t1, s0, IE_IRQ0 - bnez t1, handle_irq0 - andi t1, s0, IE_IRQ1 - bnez t1, handle_irq1 - andi t1, s0, IE_IRQ2 - bnez t1, handle_irq2 - andi t1, s0, IE_IRQ3 - bnez t1, handle_irq3 - andi t1, s0, IE_IRQ4 - bnez t1, handle_irq4 - andi t1, s0, IE_IRQ5 - bnez t1, handle_irq5 - nop - - /* Either someone has triggered the "software interrupts" - * or we lost an interrupt somehow. Ignore it. - */ - j ret_from_irq - nop - -handle_irq0: - jal ip32_irq0 - move a0, sp - j ret_from_irq - nop - -handle_irq1: - jal ip32_irq1 - move a0, sp - j ret_from_irq - nop - -handle_irq2: - jal ip32_irq2 - move a0, sp - j ret_from_irq - nop - -handle_irq3: - jal ip32_irq3 - move a0, sp - j ret_from_irq - nop - -handle_irq4: - jal ip32_irq4 - move a0, sp - j ret_from_irq - nop - -handle_irq5: - jal ip32_irq5 - move a0, sp - j ret_from_irq - nop - - END(ip32_handle_int) diff -Nru a/arch/mips64/sgi-ip32/ip32-irq.c b/arch/mips64/sgi-ip32/ip32-irq.c --- a/arch/mips64/sgi-ip32/ip32-irq.c Tue Jul 1 18:44:35 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,556 +0,0 @@ -/* - * Code to handle IP32 IRQs - * - * 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) 2000 Harald Koerfgen - * Copyright (C) 2001 Keith M Wesolowski - */ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#undef DEBUG_IRQ -#ifdef DEBUG_IRQ -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - -/* O2 irq map - * - * IP0 -> software (ignored) - * IP1 -> software (ignored) - * IP2 -> (irq0) C crime 1.1 all interrupts; crime 1.5 ??? - * IP3 -> (irq1) X unknown - * IP4 -> (irq2) X unknown - * IP5 -> (irq3) X unknown - * IP6 -> (irq4) X unknown - * IP7 -> (irq5) 0 CPU count/compare timer (system timer) - * - * crime: (C) - * - * CRIME_INT_STAT 31:0: - * - * 0 -> 1 Video in 1 - * 1 -> 2 Video in 2 - * 2 -> 3 Video out - * 3 -> 4 Mace ethernet - * 4 -> S SuperIO sub-interrupt - * 5 -> M Miscellaneous sub-interrupt - * 6 -> A Audio sub-interrupt - * 7 -> 8 PCI bridge errors - * 8 -> 9 PCI SCSI aic7xxx 0 - * 9 -> 10 PCI SCSI aic7xxx 1 - * 10 -> 11 PCI slot 0 - * 11 -> 12 unused (PCI slot 1) - * 12 -> 13 unused (PCI slot 2) - * 13 -> 14 unused (PCI shared 0) - * 14 -> 15 unused (PCI shared 1) - * 15 -> 16 unused (PCI shared 2) - * 16 -> 17 GBE0 (E) - * 17 -> 18 GBE1 (E) - * 18 -> 19 GBE2 (E) - * 19 -> 20 GBE3 (E) - * 20 -> 21 CPU errors - * 21 -> 22 Memory errors - * 22 -> 23 RE empty edge (E) - * 23 -> 24 RE full edge (E) - * 24 -> 25 RE idle edge (E) - * 25 -> 26 RE empty level - * 26 -> 27 RE full level - * 27 -> 28 RE idle level - * 28 -> 29 unused (software 0) (E) - * 29 -> 30 unused (software 1) (E) - * 30 -> 31 unused (software 2) - crime 1.5 CPU SysCorError (E) - * 31 -> 32 VICE - * - * S, M, A: Use the MACE ISA interrupt register - * MACE_ISA_INT_STAT 31:0 - * - * 0-7 -> 33-40 Audio - * 8 -> 41 RTC - * 9 -> 42 Keyboard - * 10 -> X Keyboard polled - * 11 -> 44 Mouse - * 12 -> X Mouse polled - * 13-15 -> 46-48 Count/compare timers - * 16-19 -> 49-52 Parallel (16 E) - * 20-25 -> 53-58 Serial 1 (22 E) - * 26-31 -> 59-64 Serial 2 (28 E) - * - * Note that this means IRQs 5-7, 43, and 45 do not exist. This is a - * different IRQ map than IRIX uses, but that's OK as Linux irq handling - * is quite different anyway. - */ - -/* Some initial interrupts to set up */ -extern void crime_memerr_intr (unsigned int irq, void *dev_id, - struct pt_regs *regs); -extern void crime_cpuerr_intr (unsigned int irq, void *dev_id, - struct pt_regs *regs); - -struct irqaction memerr_irq = { crime_memerr_intr, SA_INTERRUPT, - 0, "CRIME memory error", NULL, - NULL }; -struct irqaction cpuerr_irq = { crime_cpuerr_intr, SA_INTERRUPT, - 0, "CRIME CPU error", NULL, - NULL }; - -unsigned long spurious_count = 0; -extern void ip32_handle_int (void); -extern void do_IRQ (unsigned int irq, struct pt_regs *regs); - -/* For interrupts wired from a single device to the CPU. Only the clock - * uses this it seems, which is IRQ 0 and IP7. - */ - -static void enable_cpu_irq (unsigned int irq) -{ - set_cp0_status (STATUSF_IP7); -} - -static unsigned int startup_cpu_irq (unsigned int irq) { - enable_cpu_irq (irq); - return 0; -} - -static void disable_cpu_irq (unsigned int irq) -{ - clear_cp0_status (STATUSF_IP7); -} - -static void end_cpu_irq (unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_cpu_irq (irq); -} - -#define shutdown_cpu_irq disable_cpu_irq -#define mask_and_ack_cpu_irq disable_cpu_irq - -static struct hw_interrupt_type ip32_cpu_interrupt = { - "IP32 CPU", - startup_cpu_irq, - shutdown_cpu_irq, - enable_cpu_irq, - disable_cpu_irq, - mask_and_ack_cpu_irq, - end_cpu_irq, - NULL -}; - -/* - * This is for pure CRIME interrupts - ie not MACE. The advantage? - * We get to split the register in half and do faster lookups. - */ - -static void enable_crime_irq (unsigned int irq) -{ - u64 crime_mask; - unsigned long flags; - - save_and_cli (flags); - crime_mask = crime_read_64 (CRIME_INT_MASK); - crime_mask |= 1 << (irq - 1); - crime_write_64 (CRIME_INT_MASK, crime_mask); - restore_flags (flags); -} - -static unsigned int startup_crime_irq (unsigned int irq) -{ - enable_crime_irq (irq); - return 0; /* This is probably not right; we could have pending irqs */ -} - -static void disable_crime_irq (unsigned int irq) -{ - u64 crime_mask; - unsigned long flags; - - save_and_cli (flags); - crime_mask = crime_read_64 (CRIME_INT_MASK); - crime_mask &= ~(1 << (irq - 1)); - crime_write_64 (CRIME_INT_MASK, crime_mask); - restore_flags (flags); -} - -static void mask_and_ack_crime_irq (unsigned int irq) -{ - u64 crime_mask; - unsigned long flags; - - /* Edge triggered interrupts must be cleared. */ - if ((irq <= CRIME_GBE0_IRQ && irq >= CRIME_GBE3_IRQ) - || (irq <= CRIME_RE_EMPTY_E_IRQ && irq >= CRIME_RE_IDLE_E_IRQ) - || (irq <= CRIME_SOFT0_IRQ && irq >= CRIME_SOFT2_IRQ)) { - save_and_cli (flags); - crime_mask = crime_read_64 (CRIME_HARD_INT); - crime_mask &= ~(1 << (irq - 1)); - crime_write_64 (CRIME_HARD_INT, crime_mask); - restore_flags (flags); - } - disable_crime_irq (irq); -} - -static void end_crime_irq (unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_crime_irq (irq); -} - -#define shutdown_crime_irq disable_crime_irq - -static struct hw_interrupt_type ip32_crime_interrupt = { - "IP32 CRIME", - startup_crime_irq, - shutdown_crime_irq, - enable_crime_irq, - disable_crime_irq, - mask_and_ack_crime_irq, - end_crime_irq, - NULL -}; - -/* This is for MACE PCI interrupts. We can decrease bus traffic by masking - * as close to the source as possible. This also means we can take the - * next chunk of the CRIME register in one piece. - */ - -static void enable_macepci_irq (unsigned int irq) -{ - u32 mace_mask; - u64 crime_mask; - unsigned long flags; - - save_and_cli (flags); - mace_mask = mace_read_32 (MACEPCI_CONTROL); - mace_mask |= MACEPCI_CONTROL_INT (irq - 9); - mace_write_32 (MACEPCI_CONTROL, mace_mask); - /* In case the CRIME interrupt isn't enabled, we must enable it; - * however, we never disable interrupts at that level. - */ - crime_mask = crime_read_64 (CRIME_INT_MASK); - crime_mask |= 1 << (irq - 1); - crime_write_64 (CRIME_INT_MASK, crime_mask); - restore_flags (flags); -} - -static unsigned int startup_macepci_irq (unsigned int irq) { - enable_macepci_irq (irq); - return 0; /* XXX */ -} - -static void disable_macepci_irq (unsigned int irq) -{ - u32 mace_mask; - unsigned long flags; - - save_and_cli (flags); - mace_mask = mace_read_32 (MACEPCI_CONTROL); - mace_mask &= ~MACEPCI_CONTROL_INT (irq - 9); - mace_write_32 (MACEPCI_CONTROL, mace_mask); - restore_flags (flags); -} - -static void end_macepci_irq (unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_macepci_irq (irq); -} - -#define shutdown_macepci_irq disable_macepci_irq -#define mask_and_ack_macepci_irq disable_macepci_irq - -static struct hw_interrupt_type ip32_macepci_interrupt = { - "IP32 MACE PCI", - startup_macepci_irq, - shutdown_macepci_irq, - enable_macepci_irq, - disable_macepci_irq, - mask_and_ack_macepci_irq, - end_macepci_irq, - NULL -}; - -/* This is used for MACE ISA interrupts. That means bits 4-6 in the - * CRIME register. - */ - -static void enable_maceisa_irq (unsigned int irq) -{ - u64 crime_mask; - u32 mace_mask; - unsigned int crime_int = 0; - unsigned long flags; - - DBG ("maceisa enable: %u\n", irq); - - switch (irq) { - case MACEISA_AUDIO_SW_IRQ ... MACEISA_AUDIO3_MERR_IRQ: - crime_int = MACE_AUDIO_INT; - break; - case MACEISA_RTC_IRQ ... MACEISA_TIMER2_IRQ: - crime_int = MACE_MISC_INT; - break; - case MACEISA_PARALLEL_IRQ ... MACEISA_SERIAL2_RDMAOR_IRQ: - crime_int = MACE_SUPERIO_INT; - break; - } - DBG ("crime_int %016lx enabled\n", crime_int); - save_and_cli (flags); - crime_mask = crime_read_64 (CRIME_INT_MASK); - crime_mask |= crime_int; - crime_write_64 (CRIME_INT_MASK, crime_mask); - mace_mask = mace_read_32 (MACEISA_INT_MASK); - mace_mask |= 1 << (irq - 33); - mace_write_32 (MACEISA_INT_MASK, mace_mask); - restore_flags (flags); -} - -static unsigned int startup_maceisa_irq (unsigned int irq) { - enable_maceisa_irq (irq); - return 0; -} - -static void disable_maceisa_irq (unsigned int irq) -{ - u32 mace_mask; - unsigned long flags; - - save_and_cli (flags); - mace_mask = mace_read_32 (MACEISA_INT_MASK); - mace_mask &= ~(1 << (irq - 33)); - mace_write_32 (MACEISA_INT_MASK, mace_mask); - restore_flags (flags); -} - -static void mask_and_ack_maceisa_irq (unsigned int irq) -{ - u32 mace_mask; - unsigned long flags; - - switch (irq) { - case MACEISA_PARALLEL_IRQ: - case MACEISA_SERIAL1_TDMAPR_IRQ: - case MACEISA_SERIAL2_TDMAPR_IRQ: - save_and_cli (flags); - mace_mask = mace_read_32 (MACEISA_INT_STAT); - mace_mask &= ~(1 << (irq - 33)); - mace_write_32 (MACEISA_INT_STAT, mace_mask); - restore_flags (flags); - break; - } - disable_maceisa_irq (irq); -} - -static void end_maceisa_irq (unsigned irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_maceisa_irq (irq); -} - -#define shutdown_maceisa_irq disable_maceisa_irq - -static struct hw_interrupt_type ip32_maceisa_interrupt = { - "IP32 MACE ISA", - startup_maceisa_irq, - shutdown_maceisa_irq, - enable_maceisa_irq, - disable_maceisa_irq, - mask_and_ack_maceisa_irq, - end_maceisa_irq, - NULL -}; - -/* This is used for regular non-ISA, non-PCI MACE interrupts. That means - * bits 0-3 and 7 in the CRIME register. - */ - -static void enable_mace_irq (unsigned int irq) -{ - u64 crime_mask; - unsigned long flags; - - save_and_cli (flags); - crime_mask = crime_read_64 (CRIME_INT_MASK); - crime_mask |= 1 << (irq - 1); - crime_write_64 (CRIME_INT_MASK, crime_mask); - restore_flags (flags); -} - -static unsigned int startup_mace_irq (unsigned int irq) -{ - enable_mace_irq (irq); - return 0; -} - -static void disable_mace_irq (unsigned int irq) -{ - u64 crime_mask; - unsigned long flags; - - save_and_cli (flags); - crime_mask = crime_read_64 (CRIME_INT_MASK); - crime_mask &= ~(1 << (irq - 1)); - crime_write_64 (CRIME_INT_MASK, crime_mask); - restore_flags (flags); -} - -static void end_mace_irq (unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_mace_irq (irq); -} - -#define shutdown_mace_irq disable_mace_irq -#define mask_and_ack_mace_irq disable_mace_irq - -static struct hw_interrupt_type ip32_mace_interrupt = { - "IP32 MACE", - startup_mace_irq, - shutdown_mace_irq, - enable_mace_irq, - disable_mace_irq, - mask_and_ack_mace_irq, - end_mace_irq, - NULL -}; - -static void ip32_unknown_interrupt (struct pt_regs *regs) -{ - u64 crime; - u32 mace; - - printk ("Unknown interrupt occurred!\n"); - printk ("cp0_status: %08x\tcp0_cause: %08x\n", - read_32bit_cp0_register (CP0_STATUS), - read_32bit_cp0_register (CP0_CAUSE)); - crime = crime_read_64 (CRIME_INT_MASK); - printk ("CRIME interrupt mask: %016lx\n", crime); - crime = crime_read_64 (CRIME_INT_STAT); - printk ("CRIME interrupt status: %016lx\n", crime); - crime = crime_read_64 (CRIME_HARD_INT); - printk ("CRIME hardware interrupt register: %016lx\n", crime); - mace = mace_read_32 (MACEISA_INT_MASK); - printk ("MACE ISA interrupt mask: %08x\n", mace); - mace = mace_read_32 (MACEISA_INT_STAT); - printk ("MACE ISA interrupt status: %08x\n", mace); - mace = mace_read_32 (MACEPCI_CONTROL); - printk ("MACE PCI control register: %08x\n", mace); - - printk ("Register dump:\n"); - show_regs (regs); - - printk ("Please mail this report to linux-mips@oss.sgi.com\n"); - printk ("Spinning..."); - while (1) ; -} - -void __init ip32_irq_init(void) -{ - unsigned int irq; - extern void init_generic_irq (void); - - /* Install our interrupt handler, then clear and disable all - * CRIME and MACE interrupts. - */ - crime_write_64 (CRIME_INT_MASK, 0); - crime_write_64 (CRIME_HARD_INT, 0); - crime_write_64 (CRIME_SOFT_INT, 0); - mace_write_32 (MACEISA_INT_STAT, 0); - mace_write_32 (MACEISA_INT_MASK, 0); - set_except_vector(0, ip32_handle_int); - - init_generic_irq (); - - for (irq = 0; irq <= IP32_IRQ_MAX; irq++) { - hw_irq_controller *controller; - - if (irq == CLOCK_IRQ) - controller = &ip32_cpu_interrupt; - else if (irq <= MACE_PCI_BRIDGE_IRQ && irq >= MACE_VID_IN1_IRQ) - controller = &ip32_mace_interrupt; - else if (irq <= MACEPCI_SHARED2_IRQ && irq >= MACEPCI_SCSI0_IRQ) - controller = &ip32_macepci_interrupt; - else if (irq <= CRIME_VICE_IRQ && irq >= CRIME_GBE0_IRQ) - controller = &ip32_crime_interrupt; - else - controller = &ip32_maceisa_interrupt; - - irq_desc[irq].status = IRQ_DISABLED; - irq_desc[irq].action = 0; - irq_desc[irq].depth = 0; - irq_desc[irq].handler = controller; - } - setup_irq (CRIME_MEMERR_IRQ, &memerr_irq); - setup_irq (CRIME_CPUERR_IRQ, &cpuerr_irq); -} - -/* CRIME 1.1 appears to deliver all interrupts to this one pin. */ -void ip32_irq0 (struct pt_regs *regs) -{ - u64 crime_int = crime_read_64 (CRIME_INT_STAT); - int irq = 0; - - if (crime_int & CRIME_MACE_INT_MASK) { - crime_int &= CRIME_MACE_INT_MASK; - irq = ffs (crime_int); - } else if (crime_int & CRIME_MACEISA_INT_MASK) { - u32 mace_int; - mace_int = mace_read_32 (MACEISA_INT_STAT); - if (mace_int == 0) - irq = 0; - else - irq = ffs (mace_int) + 32; - } else if (crime_int & CRIME_MACEPCI_INT_MASK) { - crime_int &= CRIME_MACEPCI_INT_MASK; - crime_int >>= 8; - irq = ffs (crime_int) + 8; - } else if (crime_int & 0xffff0000) { - crime_int >>= 16; - irq = ffs (crime_int) + 16; - } - if (irq == 0) - ip32_unknown_interrupt (regs); - DBG ("*irq %u*\n", irq); - do_IRQ (irq, regs); -} - -void ip32_irq1 (struct pt_regs *regs) -{ - ip32_unknown_interrupt (regs); -} - -void ip32_irq2 (struct pt_regs *regs) -{ - ip32_unknown_interrupt (regs); -} - -void ip32_irq3 (struct pt_regs *regs) -{ - ip32_unknown_interrupt (regs); -} - -void ip32_irq4 (struct pt_regs *regs) -{ - ip32_unknown_interrupt (regs); -} - -void ip32_irq5 (struct pt_regs *regs) -{ - do_IRQ (CLOCK_IRQ, regs); -} diff -Nru a/arch/mips64/sgi-ip32/ip32-pci-dma.c b/arch/mips64/sgi-ip32/ip32-pci-dma.c --- a/arch/mips64/sgi-ip32/ip32-pci-dma.c Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,41 +0,0 @@ -/* - * 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) 2000 Ani Joshi - * Copyright (C) 2000 Ralf Baechle - * swiped from i386, and cloned for MIPS by Geert, polished by Ralf. - */ -#include -#include -#include -#include - -#include -#include -#include - -void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, - dma_addr_t * dma_handle) -{ - void *ret; - int gfp = GFP_ATOMIC; - - if (hwdev == NULL || hwdev->dma_mask != 0xffffffff) - gfp |= GFP_DMA; - ret = (void *) __get_free_pages(gfp, get_order(size)); - - if (ret != NULL) { - memset(ret, 0, size); - dma_cache_wback_inv((unsigned long) ret, size); - *dma_handle = virt_to_bus(ret); - } - return ret; -} - -void pci_free_consistent(struct pci_dev *hwdev, size_t size, - void *vaddr, dma_addr_t dma_handle) -{ - free_pages((unsigned long) vaddr, get_order(size)); -} diff -Nru a/arch/mips64/sgi-ip32/ip32-pci.c b/arch/mips64/sgi-ip32/ip32-pci.c --- a/arch/mips64/sgi-ip32/ip32-pci.c Tue Jul 1 18:44:39 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,425 +0,0 @@ -/* - * 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) 2000, 2001 Keith M Wesolowski - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#undef DEBUG_MACE_PCI - -/* - * O2 has up to 5 PCI devices connected into the MACE bridge. The device - * map looks like this: - * - * 0 aic7xxx 0 - * 1 aic7xxx 1 - * 2 expansion slot - * 3 N/C - * 4 N/C - */ - -#define chkslot(dev) \ -do { \ - if ((dev)->bus->number > 0 || PCI_SLOT ((dev)->devfn) < 1 \ - || PCI_SLOT ((dev)->devfn) > 3) \ - return PCIBIOS_DEVICE_NOT_FOUND; \ -} while (0) - -#define mkaddr(dev, where) \ -((((dev)->devfn & 0xffUL) << 8) | ((where) & 0xfcUL)) - -void macepci_error (int irq, void *dev, struct pt_regs *regs); - -static int macepci_read_config_byte (struct pci_dev *dev, int where, - u8 *val) -{ - *val = 0xff; - chkslot (dev); - mace_write_32 (MACEPCI_CONFIG_ADDR, mkaddr (dev, where)); - *val = mace_read_8 (MACEPCI_CONFIG_DATA + ((where & 3UL) ^ 3UL)); - - return PCIBIOS_SUCCESSFUL; -} - -static int macepci_read_config_word (struct pci_dev *dev, int where, - u16 *val) -{ - *val = 0xffff; - chkslot (dev); - if (where & 1) - return PCIBIOS_BAD_REGISTER_NUMBER; - mace_write_32 (MACEPCI_CONFIG_ADDR, mkaddr (dev, where)); - *val = mace_read_16 (MACEPCI_CONFIG_DATA + ((where & 2UL) ^ 2UL)); - - return PCIBIOS_SUCCESSFUL; -} - -static int macepci_read_config_dword (struct pci_dev *dev, int where, - u32 *val) -{ - *val = 0xffffffff; - chkslot (dev); - if (where & 3) - return PCIBIOS_BAD_REGISTER_NUMBER; - mace_write_32 (MACEPCI_CONFIG_ADDR, mkaddr (dev, where)); - *val = mace_read_32 (MACEPCI_CONFIG_DATA); - - return PCIBIOS_SUCCESSFUL; -} - -static int macepci_write_config_byte (struct pci_dev *dev, int where, - u8 val) -{ - chkslot (dev); - mace_write_32 (MACEPCI_CONFIG_ADDR, mkaddr (dev, where)); - mace_write_8 (MACEPCI_CONFIG_DATA + ((where & 3UL) ^ 3UL), val); - - return PCIBIOS_SUCCESSFUL; -} - -static int macepci_write_config_word (struct pci_dev *dev, int where, - u16 val) -{ - chkslot (dev); - if (where & 1) - return PCIBIOS_BAD_REGISTER_NUMBER; - mace_write_32 (MACEPCI_CONFIG_ADDR, mkaddr (dev, where)); - mace_write_16 (MACEPCI_CONFIG_DATA + ((where & 2UL) ^ 2UL), val); - - return PCIBIOS_SUCCESSFUL; -} - -static int macepci_write_config_dword (struct pci_dev *dev, int where, - u32 val) -{ - chkslot (dev); - if (where & 3) - return PCIBIOS_BAD_REGISTER_NUMBER; - mace_write_32 (MACEPCI_CONFIG_ADDR, mkaddr (dev, where)); - mace_write_32 (MACEPCI_CONFIG_DATA, val); - - return PCIBIOS_SUCCESSFUL; -} - -static struct pci_ops macepci_ops = { - macepci_read_config_byte, - macepci_read_config_word, - macepci_read_config_dword, - macepci_write_config_byte, - macepci_write_config_word, - macepci_write_config_dword -}; - -struct pci_fixup pcibios_fixups[] = { { 0 } }; - -void __init pcibios_init (void) -{ - struct pci_dev *dev = NULL; - u32 start, size; - u16 cmd; - u32 base_io = 0x3000; /* The first i/o address to assign after SCSI */ - u32 base_mem = 0x80100000; /* Likewise */ - u32 rev = mace_read_32 (MACEPCI_REV); - int i; - - printk ("MACE: PCI rev %d detected at %016lx\n", rev, - (u64) MACE_BASE + MACE_PCI); - - /* These are *bus* addresses */ - ioport_resource.start = 0; - ioport_resource.end = 0xffffffffUL; - iomem_resource.start = 0x80000000UL; - iomem_resource.end = 0xffffffffUL; - - /* Clear any outstanding errors and enable interrupts */ - mace_write_32 (MACEPCI_ERROR_ADDR, 0); - mace_write_32 (MACEPCI_ERROR_FLAGS, 0); - mace_write_32 (MACEPCI_CONTROL, 0xff008500); - crime_write_64 (CRIME_HARD_INT, 0UL); - crime_write_64 (CRIME_SOFT_INT, 0UL); - crime_write_64 (CRIME_INT_STAT, 0x000000000000ff00UL); - - if (request_irq (MACE_PCI_BRIDGE_IRQ, macepci_error, 0, - "MACE PCI error", NULL)) - panic ("PCI bridge can't get interrupt; can't happen.\n"); - - pci_scan_bus (0, &macepci_ops, NULL); - -#ifdef DEBUG_MACE_PCI - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - printk ("Device: %d/%d/%d ARCS-assigned bus resource map\n", - dev->bus->number, PCI_SLOT (dev->devfn), - PCI_FUNC (dev->devfn)); - for (i=0; i < DEVICE_COUNT_RESOURCE; i++) { - if (dev->resource[i].start == 0) - continue; - printk ("%d: %016lx - %016lx (flags %04lx)\n", - i, dev->resource[i].start, - dev->resource[i].end, dev->resource[i].flags); - } - } -#endif - /* - * Assign sane resources to and enable all devices. The requirement - * for the SCSI controllers is well-known: a 256-byte I/O region - * which we must assign, and a 1-page memory region which is - * assigned by the system firmware. - */ - dev = NULL; - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - switch (PCI_SLOT (dev->devfn)) { - case 1: /* SCSI bus 0 */ - dev->resource[0].start = 0x1000UL; - dev->resource[0].end = 0x10ffUL; - break; - case 2: /* SCSI bus 1 */ - dev->resource[0].start = 0x2000UL; - dev->resource[0].end = 0x20ffUL; - break; - default: /* Slots - I guess we have only 1 */ - for (i=0; i < 6; i++) { - size = dev->resource[i].end - - dev->resource[i].start; - if (!size - || !(dev->resource[i].flags - & (IORESOURCE_IO|IORESOURCE_MEM))) { - dev->resource[i].start - = dev->resource[i].end = 0UL; - continue; - } - if (dev->resource[i].flags & IORESOURCE_IO) { - dev->resource[i].start = base_io; - base_io += PAGE_ALIGN (size); - } else { - dev->resource[i].start = base_mem; - base_mem += 0x100000UL; - } - dev->resource[i].end = - dev->resource[i].start + size; - } - break; - } - for (i=0; i < 6; i++) { - if (dev->resource[i].start == 0) - continue; - start = dev->resource[i].start; - if (dev->resource[i].flags & IORESOURCE_IO) - start |= 1; - pci_write_config_dword (dev, - PCI_BASE_ADDRESS_0 + (i << 2), (u32) start); - } - pci_write_config_byte (dev, PCI_CACHE_LINE_SIZE, 0x20); - pci_write_config_byte (dev, PCI_LATENCY_TIMER, 0x30); - pci_read_config_word (dev, PCI_COMMAND, &cmd); - cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_PARITY); - pci_write_config_word (dev, PCI_COMMAND, cmd); - pci_set_master (dev); - } - -#ifdef DEBUG_MACE_PCI - printk ("Triggering PCI bridge interrupt...\n"); - mace_write_32 (MACEPCI_ERROR_FLAGS, MACEPCI_ERROR_INTERRUPT_TEST); - - dev = NULL; - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - printk ("Device: %d/%d/%d final bus resource map\n", - dev->bus->number, PCI_SLOT (dev->devfn), - PCI_FUNC (dev->devfn)); - for (i=0; i < DEVICE_COUNT_RESOURCE; i++) { - if (dev->resource[i].start == 0) - continue; - printk ("%d: %016lx - %016lx (flags %04lx)\n", - i, dev->resource[i].start, - dev->resource[i].end, dev->resource[i].flags); - } - } -#endif -} - -/* - * Given a PCI slot number (a la PCI_SLOT(...)) and the interrupt pin of - * the device (1-4 => A-D), tell what irq to use. Note that we don't - * in theory have slots 4 and 5, and we never normally use the shared - * irqs. I suppose a device without a pin A will thank us for doing it - * right if there exists such a broken piece of crap. - */ -static int __init macepci_map_irq (struct pci_dev *dev, u8 slot, u8 pin) -{ - chkslot (dev); - if (pin == 0) - pin = 1; - switch (slot) { - case 1: - return MACEPCI_SCSI0_IRQ; - case 2: - return MACEPCI_SCSI1_IRQ; - case 3: - switch (pin) { - case 2: - return MACEPCI_SHARED0_IRQ; - case 3: - return MACEPCI_SHARED1_IRQ; - case 4: - return MACEPCI_SHARED2_IRQ; - case 1: - default: - return MACEPCI_SLOT0_IRQ; - } - case 4: - switch (pin) { - case 2: - return MACEPCI_SHARED2_IRQ; - case 3: - return MACEPCI_SHARED0_IRQ; - case 4: - return MACEPCI_SHARED1_IRQ; - case 1: - default: - return MACEPCI_SLOT1_IRQ; - } - return MACEPCI_SLOT1_IRQ; - case 5: - switch (pin) { - case 2: - return MACEPCI_SHARED1_IRQ; - case 3: - return MACEPCI_SHARED2_IRQ; - case 4: - return MACEPCI_SHARED0_IRQ; - case 1: - default: - return MACEPCI_SLOT2_IRQ; - } - default: - return 0; - } -} - -/* - * It's not entirely clear what this does in a system with no bridges. - * In any case, bridges are not supported by Linux in O2. - */ -static u8 __init macepci_swizzle (struct pci_dev *dev, u8 *pinp) -{ - if (PCI_SLOT (dev->devfn) == 2) - *pinp = 2; - else - *pinp = 1; - return PCI_SLOT (dev->devfn); -} - -/* All devices are enabled during initialization. */ -int pcibios_enable_device (struct pci_dev *dev) -{ - return PCIBIOS_SUCCESSFUL; -} - -char * __init pcibios_setup (char *str) -{ - return str; -} - -void __init pcibios_align_resource (void *data, struct resource *res, - unsigned long size, unsigned long align) -{ -} - -void __init pcibios_update_irq (struct pci_dev *dev, int irq) -{ - pci_write_config_byte (dev, PCI_INTERRUPT_LINE, irq); -} - -void __init pcibios_fixup_bus (struct pci_bus *b) -{ - pci_fixup_irqs (macepci_swizzle, macepci_map_irq); -} - -/* - * Handle errors from the bridge. This includes master and target aborts, - * various command and address errors, and the interrupt test. This gets - * registered on the bridge error irq. It's conceivable that some of these - * conditions warrant a panic. Anybody care to say which ones? - */ -void macepci_error (int irq, void *dev, struct pt_regs *regs) { - u32 flags, error_addr; - char space; - - flags = mace_read_32 (MACEPCI_ERROR_FLAGS); - error_addr = mace_read_32 (MACEPCI_ERROR_ADDR); - - if (flags & MACEPCI_ERROR_MEMORY_ADDR) - space = 'M'; - else if (flags & MACEPCI_ERROR_CONFIG_ADDR) - space = 'C'; - else space = 'X'; - - if (flags & MACEPCI_ERROR_MASTER_ABORT) { - printk ("MACEPCI: Master abort at 0x%08x (%c)\n", error_addr, - space); - mace_write_32 (MACEPCI_ERROR_FLAGS, flags - & ~MACEPCI_ERROR_MASTER_ABORT); - } - if (flags & MACEPCI_ERROR_TARGET_ABORT) { - printk ("MACEPCI: Target abort at 0x%08x (%c)\n", error_addr, - space); - mace_write_32 (MACEPCI_ERROR_FLAGS, flags - & ~MACEPCI_ERROR_TARGET_ABORT); - } - if (flags & MACEPCI_ERROR_DATA_PARITY_ERR) { - printk ("MACEPCI: Data parity error at 0x%08x (%c)\n", - error_addr, space); - mace_write_32 (MACEPCI_ERROR_FLAGS, flags - & ~MACEPCI_ERROR_DATA_PARITY_ERR); - } - if (flags & MACEPCI_ERROR_RETRY_ERR) { - printk ("MACEPCI: Retry error at 0x%08x (%c)\n", error_addr, - space); - mace_write_32 (MACEPCI_ERROR_FLAGS, flags - & ~MACEPCI_ERROR_RETRY_ERR); - } - if (flags & MACEPCI_ERROR_ILLEGAL_CMD) { - printk ("MACEPCI: Illegal command at 0x%08x (%c)\n", - error_addr, space); - mace_write_32 (MACEPCI_ERROR_FLAGS, - flags & ~MACEPCI_ERROR_ILLEGAL_CMD); - } - if (flags & MACEPCI_ERROR_SYSTEM_ERR) { - printk ("MACEPCI: System error at 0x%08x (%c)\n", - error_addr, space); - mace_write_32 (MACEPCI_ERROR_FLAGS, flags - & ~MACEPCI_ERROR_SYSTEM_ERR); - } - if (flags & MACEPCI_ERROR_PARITY_ERR) { - printk ("MACEPCI: Parity error at 0x%08x (%c)\n", error_addr, - space); - mace_write_32 (MACEPCI_ERROR_FLAGS, flags - & ~MACEPCI_ERROR_PARITY_ERR); - } - if (flags & MACEPCI_ERROR_OVERRUN) { - printk ("MACEPCI: Overrun error at 0x%08x (%c)\n", - error_addr, space); - mace_write_32 (MACEPCI_ERROR_FLAGS, flags - & ~MACEPCI_ERROR_OVERRUN); - } - if (flags & MACEPCI_ERROR_SIG_TABORT) { - printk ("MACEPCI: Signaled target abort (clearing)\n"); - mace_write_32 (MACEPCI_ERROR_FLAGS, flags - & ~MACEPCI_ERROR_SIG_TABORT); - } - if (flags & MACEPCI_ERROR_INTERRUPT_TEST) { - printk ("MACEPCI: Interrupt test triggered (clearing)\n"); - mace_write_32 (MACEPCI_ERROR_FLAGS, flags - & ~MACEPCI_ERROR_INTERRUPT_TEST); - } -} diff -Nru a/arch/mips64/sgi-ip32/ip32-rtc.c b/arch/mips64/sgi-ip32/ip32-rtc.c --- a/arch/mips64/sgi-ip32/ip32-rtc.c Tue Jul 1 18:44:36 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,32 +0,0 @@ -/* - * RTC routines for IP32 style attached Dallas chip. - * - * 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) 2000 Harald Koerfgen - */ -#include -#include - -static unsigned char ip32_rtc_read_data(unsigned long addr) -{ - return (unsigned char) mace_read_8 (MACEISA_RTC_BASE + (addr << 8)); -} - -static void ip32_rtc_write_data(unsigned char data, unsigned long addr) -{ - mace_write_8 (MACEISA_RTC_BASE + (addr << 8), data); -} - -static int ip32_rtc_bcd_mode(void) -{ - return 0; -} - -struct rtc_ops ip32_rtc_ops = { - &ip32_rtc_read_data, - &ip32_rtc_write_data, - &ip32_rtc_bcd_mode -}; diff -Nru a/arch/mips64/sgi-ip32/ip32-setup.c b/arch/mips64/sgi-ip32/ip32-setup.c --- a/arch/mips64/sgi-ip32/ip32-setup.c Tue Jul 1 18:44:37 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,62 +0,0 @@ -/* - * IP32 basic setup - * - * 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) 2000 Harald Koerfgen - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern struct rtc_ops ip32_rtc_ops; -extern u32 cc_interval; - -void __init ip32_init (int argc, char **argv, char **envp) { - arc_meminit (); -} - -void __init ip32_setup(void) -{ -#ifdef CONFIG_SERIAL_CONSOLE - char *ctype; -#endif - TLBMISS_HANDLER_SETUP (); - -#ifdef CONFIG_SERIAL_CONSOLE - ctype = ArcGetEnvironmentVariable("console"); - if (*ctype == 'd') { - if (ctype[1] == '2') - console_setup ("ttyS1"); - else - console_setup ("ttyS0"); - } -#endif - -#ifdef CONFIG_VT - conswitchp = &dummy_con; -#endif - - rtc_ops = &ip32_rtc_ops; - - crime_init (); -} - -int __init page_is_ram (unsigned long pagenr) -{ - /* XXX: to do? */ - return 1; -} diff -Nru a/arch/mips64/sgi-ip32/ip32-timer.c b/arch/mips64/sgi-ip32/ip32-timer.c --- a/arch/mips64/sgi-ip32/ip32-timer.c Tue Jul 1 18:44:37 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,47 +0,0 @@ -/* - * IP32 timer calibration - * - * 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) 2001 Keith M Wesolowski - */ -#include -#include -#include -#include -#include -#include -#include - -extern u32 cc_interval; - -/* An arbitrary time; this can be decreased if reliability looks good */ -#define WAIT_MS 10 -#define PER_MHZ (1000000 / 2 / HZ) - -void __init ip32_timer_setup (struct irqaction *irq) { - u64 crime_time; - u32 cc_tick; - - printk("Calibrating system timer... "); - - crime_time = crime_read_64 (CRIME_TIME) & CRIME_TIME_MASK; - cc_tick = read_32bit_cp0_register (CP0_COUNT); - - while ((crime_read_64 (CRIME_TIME) & CRIME_TIME_MASK) - crime_time - < WAIT_MS * 1000000 / CRIME_NS_PER_TICK) - ; - cc_tick = read_32bit_cp0_register (CP0_COUNT) - cc_tick; - cc_interval = cc_tick / HZ * (1000 / WAIT_MS); - /* The round-off seems unnecessary; in testing, the error of the - * above procedure is < 100 ticks, which means it gets filtered - * out by the HZ adjustment. - */ - cc_interval = (cc_interval / PER_MHZ) * PER_MHZ; - - printk("%d MHz CPU detected\n", (int) (cc_interval / PER_MHZ)); - - setup_irq (CLOCK_IRQ, irq); -} diff -Nru a/arch/mips64/tools/Makefile b/arch/mips64/tools/Makefile --- a/arch/mips64/tools/Makefile Tue Jul 1 18:44:32 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,23 +0,0 @@ -# -# Makefile for MIPS kernel build tools. -# -# Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) -# Copyright (C) 1997, 1999 Ralf Baechle (ralf@gnu.org) -# Copyright (C) 1999 Silicon Graphics, Inc. -# -TARGET := $(TOPDIR)/include/asm-$(ARCH)/offset.h - -$(TARGET): offset.h - cmp -s $^ $@ || (cp $^ $(TARGET).new && mv $(TARGET).new $(TARGET)) - -offset.h: offset.s - sed -n '/^@@@/s///p' $^ >$@ - -offset.s: offset.c $(TOPDIR)/include/linux/autoconf.h - -clean: - rm -f offset.[hs] $(TARGET).new - -mrproper: - rm -f offset.[hs] $(TARGET).new - rm -f $(TARGET) diff -Nru a/arch/mips64/tools/offset.c b/arch/mips64/tools/offset.c --- a/arch/mips64/tools/offset.c Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,150 +0,0 @@ -/* - * offset.c: Calculate pt_regs and task_struct offsets. - * - * Copyright (C) 1996 David S. Miller - * Copyright (C) 1997, 1998, 1999, 2000 Ralf Baechle - * Copyright (C) 1999, 2000 Silicon Graphics, Inc. - */ -#include -#include - -#include -#include - -#define text(t) __asm__("\n@@@" t) -#define _offset(type, member) (&(((type *)NULL)->member)) - -#define offset(string, ptr, member) \ - __asm__("\n@@@" string "%0" : : "i" (_offset(ptr, member))) -#define size(string, size) \ - __asm__("\n@@@" string "%0" : : "i" (sizeof(size))) -#define linefeed text("") - -text("/* DO NOT TOUCH, AUTOGENERATED BY OFFSET.C */"); -linefeed; -text("#ifndef _MIPS_OFFSET_H"); -text("#define _MIPS_OFFSET_H"); -linefeed; - -void output_ptreg_defines(void) -{ - text("/* MIPS pt_regs offsets. */"); - offset("#define PT_R0 ", struct pt_regs, regs[0]); - offset("#define PT_R1 ", struct pt_regs, regs[1]); - offset("#define PT_R2 ", struct pt_regs, regs[2]); - offset("#define PT_R3 ", struct pt_regs, regs[3]); - offset("#define PT_R4 ", struct pt_regs, regs[4]); - offset("#define PT_R5 ", struct pt_regs, regs[5]); - offset("#define PT_R6 ", struct pt_regs, regs[6]); - offset("#define PT_R7 ", struct pt_regs, regs[7]); - offset("#define PT_R8 ", struct pt_regs, regs[8]); - offset("#define PT_R9 ", struct pt_regs, regs[9]); - offset("#define PT_R10 ", struct pt_regs, regs[10]); - offset("#define PT_R11 ", struct pt_regs, regs[11]); - offset("#define PT_R12 ", struct pt_regs, regs[12]); - offset("#define PT_R13 ", struct pt_regs, regs[13]); - offset("#define PT_R14 ", struct pt_regs, regs[14]); - offset("#define PT_R15 ", struct pt_regs, regs[15]); - offset("#define PT_R16 ", struct pt_regs, regs[16]); - offset("#define PT_R17 ", struct pt_regs, regs[17]); - offset("#define PT_R18 ", struct pt_regs, regs[18]); - offset("#define PT_R19 ", struct pt_regs, regs[19]); - offset("#define PT_R20 ", struct pt_regs, regs[20]); - offset("#define PT_R21 ", struct pt_regs, regs[21]); - offset("#define PT_R22 ", struct pt_regs, regs[22]); - offset("#define PT_R23 ", struct pt_regs, regs[23]); - offset("#define PT_R24 ", struct pt_regs, regs[24]); - offset("#define PT_R25 ", struct pt_regs, regs[25]); - offset("#define PT_R26 ", struct pt_regs, regs[26]); - offset("#define PT_R27 ", struct pt_regs, regs[27]); - offset("#define PT_R28 ", struct pt_regs, regs[28]); - offset("#define PT_R29 ", struct pt_regs, regs[29]); - offset("#define PT_R30 ", struct pt_regs, regs[30]); - offset("#define PT_R31 ", struct pt_regs, regs[31]); - offset("#define PT_LO ", struct pt_regs, lo); - offset("#define PT_HI ", struct pt_regs, hi); - offset("#define PT_EPC ", struct pt_regs, cp0_epc); - offset("#define PT_BVADDR ", struct pt_regs, cp0_badvaddr); - offset("#define PT_STATUS ", struct pt_regs, cp0_status); - offset("#define PT_CAUSE ", struct pt_regs, cp0_cause); - size("#define PT_SIZE ", struct pt_regs); - linefeed; -} - -void output_task_defines(void) -{ - text("/* MIPS task_struct offsets. */"); - offset("#define TASK_STATE ", struct task_struct, state); - offset("#define TASK_FLAGS ", struct task_struct, flags); -#error offset("#define TASK_SIGPENDING ", struct task_struct, sigpending); -#error offset("#define TASK_NEED_RESCHED ", struct task_struct, need_resched); -#error offset("#define TASK_PTRACE ", struct task_struct, ptrace); - offset("#define TASK_COUNTER ", struct task_struct, counter); - offset("#define TASK_NICE ", struct task_struct, nice); - offset("#define TASK_MM ", struct task_struct, mm); - offset("#define TASK_PROCESSOR ", struct task_struct, processor); - size("#define TASK_STRUCT_SIZE ", struct task_struct); - linefeed; -} - -void output_thread_defines(void) -{ - text("/* MIPS specific thread_struct offsets. */"); - offset("#define THREAD_REG16 ", struct task_struct, thread.reg16); - offset("#define THREAD_REG17 ", struct task_struct, thread.reg17); - offset("#define THREAD_REG18 ", struct task_struct, thread.reg18); - offset("#define THREAD_REG19 ", struct task_struct, thread.reg19); - offset("#define THREAD_REG20 ", struct task_struct, thread.reg20); - offset("#define THREAD_REG21 ", struct task_struct, thread.reg21); - offset("#define THREAD_REG22 ", struct task_struct, thread.reg22); - offset("#define THREAD_REG23 ", struct task_struct, thread.reg23); - offset("#define THREAD_REG29 ", struct task_struct, thread.reg29); - offset("#define THREAD_REG30 ", struct task_struct, thread.reg30); - offset("#define THREAD_REG31 ", struct task_struct, thread.reg31); - offset("#define THREAD_STATUS ", struct task_struct, \ - thread.cp0_status); - offset("#define THREAD_FPU ", struct task_struct, thread.fpu); - offset("#define THREAD_BVADDR ", struct task_struct, \ - thread.cp0_badvaddr); - offset("#define THREAD_BUADDR ", struct task_struct, \ - thread.cp0_baduaddr); - offset("#define THREAD_ECODE ", struct task_struct, \ - thread.error_code); - offset("#define THREAD_TRAPNO ", struct task_struct, thread.trap_no); - offset("#define THREAD_MFLAGS ", struct task_struct, thread.mflags); - offset("#define THREAD_CURDS ", struct task_struct, \ - thread.current_ds); - offset("#define THREAD_TRAMP ", struct task_struct, \ - thread.irix_trampoline); - offset("#define THREAD_OLDCTX ", struct task_struct, \ - thread.irix_oldctx); - linefeed; -} - -void output_mm_defines(void) -{ - text("/* Linux mm_struct offsets. */"); - offset("#define MM_USERS ", struct mm_struct, mm_users); - offset("#define MM_PGD ", struct mm_struct, pgd); - offset("#define MM_CONTEXT ", struct mm_struct, context); - linefeed; -} - -void output_sc_defines(void) -{ - text("/* Linux sigcontext offsets. */"); - offset("#define SC_REGS ", struct sigcontext, sc_regs); - offset("#define SC_FPREGS ", struct sigcontext, sc_fpregs); - offset("#define SC_MDHI ", struct sigcontext, sc_mdhi); - offset("#define SC_MDLO ", struct sigcontext, sc_mdlo); - offset("#define SC_PC ", struct sigcontext, sc_pc); - offset("#define SC_STATUS ", struct sigcontext, sc_status); - offset("#define SC_OWNEDFP ", struct sigcontext, sc_ownedfp); - offset("#define SC_FPC_CSR ", struct sigcontext, sc_fpc_csr); - offset("#define SC_FPC_EIR ", struct sigcontext, sc_fpc_eir); - offset("#define SC_CAUSE ", struct sigcontext, sc_cause); - offset("#define SC_BADVADDR ", struct sigcontext, sc_badvaddr); - linefeed; -} - -text("#endif /* !(_MIPS_OFFSET_H) */"); diff -Nru a/arch/mips64/vmlinux.lds.S b/arch/mips64/vmlinux.lds.S --- a/arch/mips64/vmlinux.lds.S Tue Jul 1 18:44:34 2003 +++ b/arch/mips64/vmlinux.lds.S Tue Jul 1 18:44:34 2003 @@ -1,18 +1,38 @@ #include +#undef mips /* CPP really sucks for this job */ +#define mips mips OUTPUT_ARCH(mips) ENTRY(kernel_entry) +jiffies = jiffies_64; SECTIONS { +#ifdef CONFIG_BOOT_ELF64 /* Read-only sections, merged into text segment: */ - .init : { *(.init) } =0 - .text : - { + /* . = 0xc000000000000000; */ + + /* This is the value for an Origin kernel, taken from an IRIX kernel. */ + /* . = 0xc00000000001c000; */ + + /* Set the vaddr for the text segment to a value + >= 0xa800 0000 0001 9000 if no symmon is going to configured + >= 0xa800 0000 0030 0000 otherwise */ + + /* . = 0xa800000000300000; */ + /* . = 0xa800000000300000; */ + . = 0xffffffff80300000; +#endif + . = LOADADDR; + /* read-only */ + _text = .; /* Text and read-only data */ + .text : { *(.text) - /* .gnu.warning sections are handled specially by elf32.em. */ + *(.fixup) *(.gnu.warning) } =0 + _etext = .; /* End of text section */ + . = ALIGN(16); /* Exception table */ __start___ex_table = .; __ex_table : { *(__ex_table) } @@ -23,30 +43,74 @@ __stop___dbe_table = .; RODATA - - _etext = .; - . = ALIGN(16384); - . = . + MAPPED_OFFSET; /* for CONFIG_MAPPED_KERNEL */ - .data.init_task : { *(.data.init_task) } + . = ALIGN(64); + + /* writeable */ + .data : { /* Data */ + *(.data) + + /* Align the initial ramdisk image (INITRD) on page boundaries. */ + . = ALIGN(4096); + __rd_start = .; + *(.initrd) + . = ALIGN(4096); + __rd_end = .; + + CONSTRUCTORS + } + _gp = . + 0x8000; + .lit8 : { *(.lit8) } + .lit4 : { *(.lit4) } + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata : { *(.sdata) } + + . = ALIGN(4096); + __nosave_begin = .; + .data_nosave : { *(.data.nosave) } + . = ALIGN(4096); + __nosave_end = .; - /* Startup code */ . = ALIGN(4096); + .data.page_aligned : { *(.data.idt) } + + . = ALIGN(32); + .data.cacheline_aligned : { *(.data.cacheline_aligned) } + + _edata = .; /* End of data section */ + + . = ALIGN(16384); /* init_task */ + . = . + MAPPED_OFFSET; /* for CONFIG_MAPPED_KERNEL */ + .data.init_task : { *(.data.init_task) } + + /* will be freed after init */ + . = ALIGN(4096); /* Init code and data */ __init_begin = .; - .text.init : { *(.text.init) } - .data.init : { *(.data.init) } + /* /DISCARD/ doesn't work for .reginfo */ + .reginfo : { *(.reginfo) } + .init.text : { + _sinittext = .; + *(.init.text) + _einittext = .; + } + .init.data : { *(.init.data) } . = ALIGN(16); __setup_start = .; - .setup.init : { *(.setup.init) } + .init.setup : { *(.init.setup) } __setup_end = .; + __start___param = .; + __param : { *(__param) } + __stop___param = .; __initcall_start = .; .initcall.init : { - *(.initcall1.init) - *(.initcall2.init) - *(.initcall3.init) - *(.initcall4.init) - *(.initcall5.init) - *(.initcall6.init) + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) *(.initcall7.init) } __initcall_end = .; @@ -54,68 +118,40 @@ .con_initcall.init : { *(.con_initcall.init) } __con_initcall_end = .; SECURITY_INIT - . = ALIGN(4096); /* Align double page for init_task_union */ - __init_end = .; - . = ALIGN(4096); - .data.page_aligned : { *(.data.idt) } - + __initramfs_start = .; + .init.ramfs : { *(.init.ramfs) } + __initramfs_end = .; . = ALIGN(32); - .data.cacheline_aligned : { *(.data.cacheline_aligned) } + __per_cpu_start = .; + .data.percpu : { *(.data.percpu) } + __per_cpu_end = .; + . = ALIGN(4096); + __init_end = .; + /* freed after init ends here */ - .fini : { *(.fini) } =0 - .reginfo : { *(.reginfo) } - /* Adjust the address for the data segment. We want to adjust up to - the same address within the page on the next page up. It would - be more correct to do this: - . = .; - The current expression does not correctly handle the case of a - text segment ending precisely at the end of a page; it causes the - data segment to skip a page. The above expression does not have - this problem, but it will currently (2/95) cause BFD to allocate - a single segment, combining both text and data, for this case. - This will prevent the text segment from being shared among - multiple executions of the program; I think that is more - important than losing a page of the virtual address space (note - that no actual memory is lost; the page which is skipped can not - be referenced). */ - . = .; - .data : - { - _fdata = . ; - *(.data) - CONSTRUCTORS + __bss_start = .; /* BSS */ + .sbss : { + *(.sbss) + *(.scommon) } - .data1 : { *(.data1) } - .lit8 : { *(.lit8) } - .lit4 : { *(.lit4) } - .ctors : { *(.ctors) } - .dtors : { *(.dtors) } - .got : { *(.got.plt) *(.got) } - .dynamic : { *(.dynamic) } - /* We want the small data sections together, so single-instruction offsets - can access them all, and initialized data all before uninitialized, so - we can shorten the on-disk segment size. */ - .sdata : { *(.sdata) } - _edata = .; + .bss : { + *(.bss) + *(COMMON) + } + __bss_stop = .; - .sbss : { *(.sbss) *(.scommon) } - .bss : - { - *(.dynbss) - *(.bss) - *(COMMON) _end = . ; - } /* Sections to be discarded */ - /DISCARD/ : - { - *(.text.exit) - *(.data.exit) + /DISCARD/ : { + *(.exit.text) + *(.exit.data) *(.exitcall.exit) } + /* This is the MIPS specific mdebug section. */ + .mdebug : { *(.mdebug) } /* These are needed for ELF backends which have not yet been converted to the new style linker. */ .stab 0 : { *(.stab) } @@ -133,4 +169,6 @@ /* These must appear regardless of . */ .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) } .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) } + .comment : { *(.comment) } + .note : { *(.note) } } diff -Nru a/arch/parisc/Kconfig b/arch/parisc/Kconfig --- a/arch/parisc/Kconfig Tue Jul 1 18:44:35 2003 +++ b/arch/parisc/Kconfig Tue Jul 1 18:44:35 2003 @@ -182,33 +182,7 @@ source "drivers/ide/Kconfig" - -menu "SCSI support" - -config SCSI - tristate "SCSI support" - ---help--- - If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or - any other SCSI device under Linux, say Y and make sure that you know - the name of your SCSI host adapter (the card inside your computer - that "speaks" the SCSI protocol, also called SCSI controller), - because you will be asked for it. - - You also need to say Y here if you want support for the parallel - port version of the 100 MB IOMEGA ZIP drive. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called scsi_mod. If you want to compile it as - a module, say M here and read and - . However, do not compile this as a - module if your root file system (the one containing the directory /) - is located on a SCSI device. - -source drivers/scsi/Kconfig - - -endmenu +source "drivers/scsi/Kconfig" source "drivers/md/Kconfig" diff -Nru a/arch/ppc/Kconfig b/arch/ppc/Kconfig --- a/arch/ppc/Kconfig Tue Jul 1 18:44:39 2003 +++ b/arch/ppc/Kconfig Tue Jul 1 18:44:39 2003 @@ -1175,33 +1175,8 @@ source "drivers/ide/Kconfig" - -menu "SCSI support" - -config SCSI - tristate "SCSI support" - ---help--- - If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or - any other SCSI device under Linux, say Y and make sure that you know - the name of your SCSI host adapter (the card inside your computer - that "speaks" the SCSI protocol, also called SCSI controller), - because you will be asked for it. - - You also need to say Y here if you want support for the parallel - port version of the 100 MB IOMEGA ZIP drive. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called scsi_mod. If you want to compile it as - a module, say M here and read and - . However, do not compile this as a - module if your root file system (the one containing the directory /) - is located on a SCSI device. - source "drivers/scsi/Kconfig" -endmenu - source "drivers/message/fusion/Kconfig" source "drivers/ieee1394/Kconfig" @@ -1218,14 +1193,7 @@ source "drivers/video/Kconfig" -menu "Old CD-ROM drivers (not SCSI, not IDE)" - -config CD_NO_IDESCSI - bool "Support non-SCSI/IDE/ATAPI CDROM drives" - source "drivers/cdrom/Kconfig" - -endmenu source "drivers/input/Kconfig" diff -Nru a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S --- a/arch/ppc/kernel/entry.S Tue Jul 1 18:44:37 2003 +++ b/arch/ppc/kernel/entry.S Tue Jul 1 18:44:37 2003 @@ -173,8 +173,10 @@ cmpli 0,r0,NR_syscalls bge- 66f rlwinm r10,r1,0,0,18 /* current_thread_info() */ - lwz r10,TI_FLAGS(r10) - andi. r10,r10,_TIF_SYSCALL_TRACE + lwz r11,TI_FLAGS(r10) + rlwinm r11,r11,0,~_TIF_FORCE_NOERROR + stw r11,TI_FLAGS(r10) + andi. r11,r11,_TIF_SYSCALL_TRACE bne- syscall_dotrace syscall_dotrace_cont: lis r10,sys_call_table@h @@ -192,11 +194,12 @@ mr r6,r3 li r11,-_LAST_ERRNO cmpl 0,r3,r11 + rlwinm r12,r1,0,0,18 /* current_thread_info() */ blt+ 30f + lwz r11,TI_FLAGS(r12) + andi. r11,r11,_TIF_FORCE_NOERROR + bne 30f neg r3,r3 - cmpi 0,r3,ERESTARTNOHAND - bne 22f - li r3,EINTR 22: lwz r10,_CCR(r1) /* Set SO bit in CR */ oris r10,r10,0x1000 stw r10,_CCR(r1) @@ -205,7 +208,6 @@ 30: LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */ SYNC MTMSRD(r10) - rlwinm r12,r1,0,0,18 /* current_thread_info() */ lwz r9,TI_FLAGS(r12) andi. r0,r9,(_TIF_SYSCALL_TRACE|_TIF_SIGPENDING|_TIF_NEED_RESCHED) bne- syscall_exit_work diff -Nru a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c --- a/arch/ppc/kernel/process.c Tue Jul 1 18:44:35 2003 +++ b/arch/ppc/kernel/process.c Tue Jul 1 18:44:35 2003 @@ -69,8 +69,6 @@ /* only used to get secondary processor up */ struct task_struct *current_set[NR_CPUS] = {&init_task, }; -static void show_tsk_stack(struct task_struct *tsk, unsigned long sp); - #undef SHOW_TASK_SWITCHES #undef CHECK_STACK @@ -296,7 +294,7 @@ break; } printk("\n"); - show_tsk_stack(current, regs->gpr[1]); + show_stack(current, (unsigned long *) regs->gpr[1]); } void exit_thread(void) @@ -494,26 +492,29 @@ return error; } -void show_trace_task(struct task_struct *tsk) -{ - show_tsk_stack(tsk, tsk->thread.ksp); -} - void dump_stack(void) { - show_tsk_stack(current, _get_SP()); + show_stack(current, NULL); } -static void show_tsk_stack(struct task_struct *tsk, unsigned long sp) +void show_stack(struct task_struct *tsk, unsigned long *stack) { - unsigned long stack_top, prev_sp, ret; + unsigned long sp, stack_top, prev_sp, ret; int count = 0; unsigned long next_exc = 0; struct pt_regs *regs; extern char ret_from_except, ret_from_except_full, ret_from_syscall; + sp = (unsigned long) stack; if (tsk == NULL) - return; + tsk = current; + if (sp == 0) { + if (tsk == current) + asm("mr %0,1" : "=r" (sp)); + else + sp = tsk->thread.ksp; + } + prev_sp = (unsigned long) (tsk->thread_info + 1); stack_top = (unsigned long) tsk->thread_info + THREAD_SIZE; while (count < 16 && sp > prev_sp && sp < stack_top && (sp & 3) == 0) { diff -Nru a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig --- a/arch/ppc64/Kconfig Tue Jul 1 18:44:35 2003 +++ b/arch/ppc64/Kconfig Tue Jul 1 18:44:35 2003 @@ -253,32 +253,7 @@ source "drivers/ide/Kconfig" - -menu "SCSI device support" - -config SCSI - tristate "SCSI device support" - ---help--- - If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or - any other SCSI device under Linux, say Y and make sure that you know - the name of your SCSI host adapter (the card inside your computer - that "speaks" the SCSI protocol, also called SCSI controller), - because you will be asked for it. - - You also need to say Y here if you want support for the parallel - port version of the 100 MB IOMEGA ZIP drive. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called scsi_mod. If you want to compile it as - a module, say M here and read and - . However, do not compile this as a - module if your root file system (the one containing the directory /) - is located on a SCSI device. - source "drivers/scsi/Kconfig" - -endmenu source "drivers/md/Kconfig" diff -Nru a/arch/ppc64/kernel/cputable.c b/arch/ppc64/kernel/cputable.c --- a/arch/ppc64/kernel/cputable.c Tue Jul 1 18:44:31 2003 +++ b/arch/ppc64/kernel/cputable.c Tue Jul 1 18:44:31 2003 @@ -37,7 +37,8 @@ struct cpu_spec cpu_specs[] = { { /* Power3 */ 0xffff0000, 0x00400000, "Power3 (630)", - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | + CPU_FTR_DABR | CPU_FTR_IABR, COMMON_USER_PPC64, 128, 128, __setup_cpu_power3, @@ -45,7 +46,8 @@ }, { /* Power3+ */ 0xffff0000, 0x00410000, "Power3 (630+)", - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | + CPU_FTR_DABR | CPU_FTR_IABR, COMMON_USER_PPC64, 128, 128, __setup_cpu_power3, @@ -53,7 +55,8 @@ }, { /* Northstar */ 0xffff0000, 0x00330000, "Northstar", - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | + CPU_FTR_DABR | CPU_FTR_IABR, COMMON_USER_PPC64, 128, 128, __setup_cpu_power3, @@ -61,7 +64,8 @@ }, { /* Pulsar */ 0xffff0000, 0x00340000, "Pulsar", - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | + CPU_FTR_DABR | CPU_FTR_IABR, COMMON_USER_PPC64, 128, 128, __setup_cpu_power3, @@ -69,7 +73,8 @@ }, { /* I-star */ 0xffff0000, 0x00360000, "I-star", - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | + CPU_FTR_DABR | CPU_FTR_IABR, COMMON_USER_PPC64, 128, 128, __setup_cpu_power3, @@ -77,7 +82,8 @@ }, { /* S-star */ 0xffff0000, 0x00370000, "S-star", - CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE, + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | + CPU_FTR_DABR | CPU_FTR_IABR, COMMON_USER_PPC64, 128, 128, __setup_cpu_power3, @@ -86,7 +92,7 @@ { /* Power4 */ 0xffff0000, 0x00350000, "Power4", CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | - CPU_FTR_PPCAS_ARCH_V2, + CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_DABR, COMMON_USER_PPC64, 128, 128, __setup_cpu_power4, @@ -95,7 +101,7 @@ { /* Power4+ */ 0xffff0000, 0x00380000, "Power4+", CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | - CPU_FTR_PPCAS_ARCH_V2, + CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_DABR, COMMON_USER_PPC64, 128, 128, __setup_cpu_power4, @@ -104,7 +110,7 @@ { /* default match */ 0x00000000, 0x00000000, "(Power4-Compatible)", CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | - CPU_FTR_PPCAS_ARCH_V2, + CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_DABR, COMMON_USER_PPC64, 128, 128, __setup_cpu_power4, diff -Nru a/arch/ppc64/kernel/entry.S b/arch/ppc64/kernel/entry.S --- a/arch/ppc64/kernel/entry.S Tue Jul 1 18:44:31 2003 +++ b/arch/ppc64/kernel/entry.S Tue Jul 1 18:44:31 2003 @@ -141,9 +141,6 @@ cmpl 0,r3,r10 blt 30f neg r3,r3 - cmpi 0,r3,ERESTARTNOHAND - bne 22f - li r3,EINTR 22: ld r10,_CCR(r1) /* Set SO bit in CR */ oris r10,r10,0x1000 std r10,_CCR(r1) @@ -199,9 +196,6 @@ cmpl 0,r3,r10 blt 60f neg r3,r3 - cmpi 0,r3,ERESTARTNOHAND - bne 57f - li r3,EINTR 57: ld r10,_CCR(r1) /* Set SO bit in CR */ oris r10,r10,0x1000 std r10,_CCR(r1) diff -Nru a/arch/ppc64/kernel/pSeries_pci.c b/arch/ppc64/kernel/pSeries_pci.c --- a/arch/ppc64/kernel/pSeries_pci.c Tue Jul 1 18:44:39 2003 +++ b/arch/ppc64/kernel/pSeries_pci.c Tue Jul 1 18:44:39 2003 @@ -295,6 +295,7 @@ int *buid_vals; char *model; enum phb_types phb_type; + struct property *of_prop; model = (char *)get_property(dev, "model", NULL); @@ -341,6 +342,21 @@ return NULL; } + of_prop = (struct property *)alloc_bootmem(sizeof(struct property) + + sizeof(phb->global_number)); + + if (!of_prop) { + kfree(phb); + return NULL; + } + + memset(of_prop, 0, sizeof(struct property)); + of_prop->name = "linux,pci-domain"; + of_prop->length = sizeof(phb->global_number); + of_prop->value = (unsigned char *)&of_prop[1]; + memcpy(of_prop->value, &phb->global_number, sizeof(phb->global_number)); + prom_add_property(dev, of_prop); + phb->first_busno = bus_range[0]; phb->last_busno = bus_range[1]; @@ -352,26 +368,12 @@ if (buid_vals == NULL) { phb->buid = 0; } else { - struct pci_bus check; - if (sizeof(check.number) == 1 || sizeof(check.primary) == 1 || - sizeof(check.secondary) == 1 || sizeof(check.subordinate) == 1) { - udbg_printf("pSeries_pci: this system has large bus numbers and the kernel was not\n" - "built with the patch that fixes include/linux/pci.h struct pci_bus so\n" - "number, primary, secondary and subordinate are ints.\n"); - panic("pSeries_pci: this system has large bus numbers and the kernel was not\n" - "built with the patch that fixes include/linux/pci.h struct pci_bus so\n" - "number, primary, secondary and subordinate are ints.\n"); - } - if (len < 2 * sizeof(int)) // Support for new OF that only has 1 integer for buid. phb->buid = (unsigned long)buid_vals[0]; else phb->buid = (((unsigned long)buid_vals[0]) << 32UL) | (((unsigned long)buid_vals[1]) & 0xffffffff); - - phb->first_busno += (phb->global_number << 8); - phb->last_busno += (phb->global_number << 8); } return phb; diff -Nru a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c --- a/arch/ppc64/kernel/pci.c Tue Jul 1 18:44:37 2003 +++ b/arch/ppc64/kernel/pci.c Tue Jul 1 18:44:37 2003 @@ -380,6 +380,19 @@ return hose->global_number; } +/* Set the name of the bus as it appears in /proc/bus/pci */ +int pci_name_bus(char *name, struct pci_bus *bus) +{ + struct pci_controller *hose = PCI_GET_PHB_PTR(bus); + + if (hose->buid) + sprintf(name, "%04x:%02x", pci_domain_nr(bus), bus->number); + else + sprintf(name, "%02x", bus->number); + + return 0; +} + /* * Platform support for /proc/bus/pci/X/Y mmap()s, * modelled on the sparc64 implementation by Dave Miller. diff -Nru a/arch/ppc64/kernel/pci.h b/arch/ppc64/kernel/pci.h --- a/arch/ppc64/kernel/pci.h Tue Jul 1 18:44:31 2003 +++ b/arch/ppc64/kernel/pci.h Tue Jul 1 18:44:31 2003 @@ -42,14 +42,6 @@ void pci_fix_bus_sysdata(void); struct device_node *fetch_dev_dn(struct pci_dev *dev); -/******************************************************************* - * Helper macros for extracting data from pci structures. - * PCI_GET_PHB_PTR(struct pci_dev*) returns the Phb pointer. - * PCI_GET_PHB_NUMBER(struct pci_dev*) returns the Phb number. - * PCI_GET_BUS_NUMBER(struct pci_dev*) returns the bus number. - *******************************************************************/ #define PCI_GET_PHB_PTR(dev) (((struct device_node *)(dev)->sysdata)->phb) -#define PCI_GET_PHB_NUMBER(dev) (((dev)->bus->number&0x00FFFF00)>>8) -#define PCI_GET_BUS_NUMBER(dev) ((dev)->bus->number&0x0000FF) #endif /* __PPC_KERNEL_PCI_H__ */ diff -Nru a/arch/ppc64/kernel/pci_dn.c b/arch/ppc64/kernel/pci_dn.c --- a/arch/ppc64/kernel/pci_dn.c Tue Jul 1 18:44:39 2003 +++ b/arch/ppc64/kernel/pci_dn.c Tue Jul 1 18:44:39 2003 @@ -196,23 +196,11 @@ { struct list_head *ln; struct pci_bus *bus; - struct pci_controller *phb; - int newnum; for (ln=bus_list->next; ln != bus_list; ln=ln->next) { bus = pci_bus_b(ln); - if (bus->self) { + if (bus->self) bus->sysdata = bus->self->sysdata; - /* Also fixup the bus number on large bus systems to - * include the PHB# in the next byte - */ - phb = PCI_GET_DN(bus)->phb; - if (phb && phb->buid) { - newnum = (phb->global_number << 8) | bus->number; - bus->number = newnum; - sprintf(bus->name, "PCI Bus #%x", bus->number); - } - } pci_fixup_bus_sysdata_list(&bus->children); } } diff -Nru a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c --- a/arch/ppc64/kernel/prom.c Tue Jul 1 18:44:36 2003 +++ b/arch/ppc64/kernel/prom.c Tue Jul 1 18:44:36 2003 @@ -1538,137 +1538,185 @@ return mem_start; } -/* This routine walks the interrupt tree for a given device node and gather - * all necessary informations according to the draft interrupt mapping - * for CHRP. The current version was only tested on Apple "Core99" machines - * and may not handle cascaded controllers correctly. +/* + * Find the interrupt parent of a node. */ -__init -static unsigned long -finish_node_interrupts(struct device_node *np, unsigned long mem_start) +static struct device_node * __init +intr_parent(struct device_node *p) { - /* Finish this node */ - unsigned int *isizep, *asizep, *interrupts, *map, *map_mask, *reg; - phandle *parent, map_parent; - struct device_node *node, *parent_node; - int l, isize, ipsize, asize, map_size, regpsize; + phandle *parp; - /* Currently, we don't look at all nodes with no "interrupts" property */ + parp = (phandle *) get_property(p, "interrupt-parent", NULL); + if (parp == NULL) + return p->parent; + return find_phandle(*parp); +} + +/* + * Find out the size of each entry of the interrupts property + * for a node. + */ +static int __init +prom_n_intr_cells(struct device_node *np) +{ + struct device_node *p; + unsigned int *icp; - interrupts = (unsigned int *)get_property(np, "interrupts", &l); - if (interrupts == NULL) - return mem_start; - ipsize = l>>2; + for (p = np; (p = intr_parent(p)) != NULL; ) { + icp = (unsigned int *) + get_property(p, "#interrupt-cells", NULL); + if (icp != NULL) + return *icp; + if (get_property(p, "interrupt-controller", NULL) != NULL + || get_property(p, "interrupt-map", NULL) != NULL) { + printk("oops, node %s doesn't have #interrupt-cells\n", + p->full_name); + return 1; + } + } +#ifdef DEBUG_IRQ + printk("prom_n_intr_cells failed for %s\n", np->full_name); +#endif + return 1; +} + +/* + * Map an interrupt from a device up to the platform interrupt + * descriptor. + */ +static int __init +map_interrupt(unsigned int **irq, struct device_node **ictrler, + struct device_node *np, unsigned int *ints, int nintrc) +{ + struct device_node *p, *ipar; + unsigned int *imap, *imask, *ip; + int i, imaplen, match; + int newintrc, newaddrc; + unsigned int *reg; + int naddrc; + + reg = (unsigned int *) get_property(np, "reg", NULL); + naddrc = prom_n_addr_cells(np); + p = intr_parent(np); + while (p != NULL) { + if (get_property(p, "interrupt-controller", NULL) != NULL) + /* this node is an interrupt controller, stop here */ + break; + imap = (unsigned int *) + get_property(p, "interrupt-map", &imaplen); + if (imap == NULL) { + p = intr_parent(p); + continue; + } + imask = (unsigned int *) + get_property(p, "interrupt-map-mask", NULL); + if (imask == NULL) { + printk("oops, %s has interrupt-map but no mask\n", + p->full_name); + return 0; + } + imaplen /= sizeof(unsigned int); + match = 0; + ipar = NULL; + while (imaplen > 0 && !match) { + /* check the child-interrupt field */ + match = 1; + for (i = 0; i < naddrc && match; ++i) + match = ((reg[i] ^ imap[i]) & imask[i]) == 0; + for (; i < naddrc + nintrc && match; ++i) + match = ((ints[i-naddrc] ^ imap[i]) & imask[i]) == 0; + imap += naddrc + nintrc; + imaplen -= naddrc + nintrc; + /* grab the interrupt parent */ + ipar = find_phandle((phandle) *imap++); + --imaplen; + if (ipar == NULL) { + printk("oops, no int parent %x in map of %s\n", + imap[-1], p->full_name); + return 0; + } + /* find the parent's # addr and intr cells */ + ip = (unsigned int *) + get_property(ipar, "#interrupt-cells", NULL); + if (ip == NULL) { + printk("oops, no #interrupt-cells on %s\n", + ipar->full_name); + return 0; + } + newintrc = *ip; + ip = (unsigned int *) + get_property(ipar, "#address-cells", NULL); + newaddrc = (ip == NULL)? 0: *ip; + imap += newaddrc + newintrc; + imaplen -= newaddrc + newintrc; + } + if (imaplen < 0) { + printk("oops, error decoding int-map on %s, len=%d\n", + p->full_name, imaplen); + return 0; + } + if (!match) { +#ifdef DEBUG_IRQ + printk("oops, no match in %s int-map for %s\n", + p->full_name, np->full_name); +#endif + return 0; + } + p = ipar; + naddrc = newaddrc; + nintrc = newintrc; + ints = imap - nintrc; + reg = ints - naddrc; + } +#ifdef DEBUG_IRQ + if (p == NULL) + printk("hmmm, int tree for %s doesn't have ctrler\n", + np->full_name); +#endif + *irq = ints; + *ictrler = p; + return nintrc; +} - reg = (unsigned int *)get_property(np, "reg", &l); - regpsize = l>>2; +/* + * New version of finish_node_interrupts. + */ +static unsigned long __init +finish_node_interrupts(struct device_node *np, unsigned long mem_start) +{ + unsigned int *ints; + int intlen, intrcells; + int i, j, n; + unsigned int *irq; + struct device_node *ic; - /* We assume default interrupt cell size is 1 (bugus ?) */ - isize = 1; - node = np; - - do { - /* We adjust the cell size if the current parent contains an #interrupt-cells - * property */ - isizep = (unsigned int *)get_property(node, "#interrupt-cells", &l); - if (isizep) - isize = *isizep; - - /* We don't do interrupt cascade (ISA) for now, we stop on the first - * controller found - */ - if (get_property(node, "interrupt-controller", &l)) { - int i,j; - - np->intrs = (struct interrupt_info *) mem_start; - np->n_intrs = ipsize / isize; - mem_start += np->n_intrs * sizeof(struct interrupt_info); - for (i = 0; i < np->n_intrs; ++i) { - np->intrs[i].line = openpic_to_irq(virt_irq_create_mapping(*interrupts++)); - np->intrs[i].sense = 1; - if (isize > 1) - np->intrs[i].sense = *interrupts++; - for (j=2; j>2; - map_mask = (unsigned int *)get_property(node, "interrupt-map-mask", &l); - asizep = (unsigned int *)get_property(node, "#address-cells", &l); - if (asizep && l == sizeof(unsigned int)) - asize = *asizep; - else - asize = 0; - found = 0; - while (map_size>0 && !found) { - found = 1; - for (i=0; i=regpsize) || ((mask & *map) != (mask & reg[i]))) - found = 0; - map++; - map_size--; - } - for (i=0; iparent; - } while (node); + intrcells = prom_n_intr_cells(np); + intlen /= intrcells * sizeof(unsigned int); + np->n_intrs = intlen; + np->intrs = (struct interrupt_info *) mem_start; + mem_start += intlen * sizeof(struct interrupt_info); + + for (i = 0; i < intlen; ++i) { + np->intrs[i].line = 0; + np->intrs[i].sense = 1; + n = map_interrupt(&irq, &ic, np, ints, intrcells); + if (n <= 0) + continue; + np->intrs[i].line = openpic_to_irq(virt_irq_create_mapping(irq[0])); + if (n > 1) + np->intrs[i].sense = irq[1]; + if (n > 2) { + printk("hmmm, got %d intr cells for %s:", n, + np->full_name); + for (j = 0; j < n; ++j) + printk(" %d", irq[j]); + printk("\n"); + } + ints += intrcells; + } return mem_start; } diff -Nru a/arch/ppc64/kernel/smp.c b/arch/ppc64/kernel/smp.c --- a/arch/ppc64/kernel/smp.c Tue Jul 1 18:44:36 2003 +++ b/arch/ppc64/kernel/smp.c Tue Jul 1 18:44:36 2003 @@ -57,7 +57,7 @@ static struct smp_ops_t *smp_ops; -volatile unsigned int cpu_callin_map[NR_CPUS]; +static volatile unsigned int cpu_callin_map[NR_CPUS]; extern unsigned char stab_array[]; diff -Nru a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c --- a/arch/ppc64/kernel/sys_ppc32.c Tue Jul 1 18:44:36 2003 +++ b/arch/ppc64/kernel/sys_ppc32.c Tue Jul 1 18:44:36 2003 @@ -1147,7 +1147,7 @@ u32 totalhigh; u32 freehigh; u32 mem_unit; - char _f[20-2*sizeof(long)-sizeof(int)]; + char _f[20-2*sizeof(int)-sizeof(int)]; }; extern asmlinkage long sys_sysinfo(struct sysinfo *info); diff -Nru a/arch/ppc64/xmon/ppc-opc.c b/arch/ppc64/xmon/ppc-opc.c --- a/arch/ppc64/xmon/ppc-opc.c Tue Jul 1 18:44:35 2003 +++ b/arch/ppc64/xmon/ppc-opc.c Tue Jul 1 18:44:35 2003 @@ -394,18 +394,13 @@ /*ARGSUSED*/ static unsigned long -insert_bat (insn, value, errmsg) - unsigned long insn; - long value; - const char **errmsg; +insert_bat(unsigned long insn, long value, const char **errmsg) { return insn | (((insn >> 21) & 0x1f) << 16); } static long -extract_bat (insn, invalid) - unsigned long insn; - int *invalid; +extract_bat(unsigned long insn, int *invalid) { if (invalid != (int *) NULL && ((insn >> 21) & 0x1f) != ((insn >> 16) & 0x1f)) @@ -421,18 +416,13 @@ /*ARGSUSED*/ static unsigned long -insert_bba (insn, value, errmsg) - unsigned long insn; - long value; - const char **errmsg; +insert_bba(unsigned long insn, long value, const char **errmsg) { return insn | (((insn >> 16) & 0x1f) << 11); } static long -extract_bba (insn, invalid) - unsigned long insn; - int *invalid; +extract_bba(unsigned long insn, int *invalid) { if (invalid != (int *) NULL && ((insn >> 16) & 0x1f) != ((insn >> 11) & 0x1f)) @@ -445,19 +435,14 @@ /*ARGSUSED*/ static unsigned long -insert_bd (insn, value, errmsg) - unsigned long insn; - long value; - const char **errmsg; +insert_bd(unsigned long insn, long value, const char **errmsg) { return insn | (value & 0xfffc); } /*ARGSUSED*/ static long -extract_bd (insn, invalid) - unsigned long insn; - int *invalid; +extract_bd(unsigned long insn, int *invalid) { if ((insn & 0x8000) != 0) return (insn & 0xfffc) - 0x10000; @@ -474,10 +459,7 @@ /*ARGSUSED*/ static unsigned long -insert_bdm (insn, value, errmsg) - unsigned long insn; - long value; - const char **errmsg; +insert_bdm(unsigned long insn, long value, const char **errmsg) { if ((value & 0x8000) != 0) insn |= 1 << 21; @@ -485,9 +467,7 @@ } static long -extract_bdm (insn, invalid) - unsigned long insn; - int *invalid; +extract_bdm(unsigned long insn, int *invalid) { if (invalid != (int *) NULL && ((insn & (1 << 21)) == 0 @@ -505,10 +485,7 @@ /*ARGSUSED*/ static unsigned long -insert_bdp (insn, value, errmsg) - unsigned long insn; - long value; - const char **errmsg; +insert_bdp(unsigned long insn, long value, const char **errmsg) { if ((value & 0x8000) == 0) insn |= 1 << 21; @@ -516,9 +493,7 @@ } static long -extract_bdp (insn, invalid) - unsigned long insn; - int *invalid; +extract_bdp(unsigned long insn, int *invalid) { if (invalid != (int *) NULL && ((insn & (1 << 21)) == 0 @@ -561,10 +536,7 @@ the field to an illegal value. */ static unsigned long -insert_bo (insn, value, errmsg) - unsigned long insn; - long value; - const char **errmsg; +insert_bo(unsigned long insn, long value, const char **errmsg) { if (errmsg != (const char **) NULL && ! valid_bo (value)) @@ -573,9 +545,7 @@ } static long -extract_bo (insn, invalid) - unsigned long insn; - int *invalid; +extract_bo(unsigned long insn, int *invalid) { long value; @@ -591,10 +561,7 @@ extracting it, we force it to be even. */ static unsigned long -insert_boe (insn, value, errmsg) - unsigned long insn; - long value; - const char **errmsg; +insert_boe(unsigned long insn, long value, const char **errmsg) { if (errmsg != (const char **) NULL) { @@ -607,9 +574,7 @@ } static long -extract_boe (insn, invalid) - unsigned long insn; - int *invalid; +extract_boe(unsigned long insn, int *invalid) { long value; @@ -625,19 +590,14 @@ /*ARGSUSED*/ static unsigned long -insert_ds (insn, value, errmsg) - unsigned long insn; - long value; - const char **errmsg; +insert_ds(unsigned long insn, long value, const char **errmsg) { return insn | (value & 0xfffc); } /*ARGSUSED*/ static long -extract_ds (insn, invalid) - unsigned long insn; - int *invalid; +extract_ds(unsigned long insn, int *invalid) { if ((insn & 0x8000) != 0) return (insn & 0xfffc) - 0x10000; @@ -650,19 +610,14 @@ /*ARGSUSED*/ static unsigned long -insert_li (insn, value, errmsg) - unsigned long insn; - long value; - const char **errmsg; +insert_li(unsigned long insn, long value, const char **errmsg) { return insn | (value & 0x3fffffc); } /*ARGSUSED*/ static long -extract_li (insn, invalid) - unsigned long insn; - int *invalid; +extract_li(unsigned long insn, int *invalid) { if ((insn & 0x2000000) != 0) return (insn & 0x3fffffc) - 0x4000000; @@ -676,10 +631,7 @@ instruction which uses a field of this type. */ static unsigned long -insert_mbe (insn, value, errmsg) - unsigned long insn; - long value; - const char **errmsg; +insert_mbe(unsigned long insn, long value, const char **errmsg) { unsigned long uval; int mb, me; @@ -718,9 +670,7 @@ } static long -extract_mbe (insn, invalid) - unsigned long insn; - int *invalid; +extract_mbe(unsigned long insn, int *invalid) { long ret; int mb, me; @@ -742,19 +692,14 @@ /*ARGSUSED*/ static unsigned long -insert_mb6 (insn, value, errmsg) - unsigned long insn; - long value; - const char **errmsg; +insert_mb6(unsigned long insn, long value, const char **errmsg) { return insn | ((value & 0x1f) << 6) | (value & 0x20); } /*ARGSUSED*/ static long -extract_mb6 (insn, invalid) - unsigned long insn; - int *invalid; +extract_mb6(unsigned long insn, int *invalid) { return ((insn >> 6) & 0x1f) | (insn & 0x20); } @@ -763,10 +708,7 @@ 0. */ static unsigned long -insert_nb (insn, value, errmsg) - unsigned long insn; - long value; - const char **errmsg; +insert_nb(unsigned long insn, long value, const char **errmsg) { if (value < 0 || value > 32) *errmsg = "value out of range"; @@ -777,9 +719,7 @@ /*ARGSUSED*/ static long -extract_nb (insn, invalid) - unsigned long insn; - int *invalid; +extract_nb(unsigned long insn, int *invalid) { long ret; @@ -796,18 +736,13 @@ /*ARGSUSED*/ static unsigned long -insert_nsi (insn, value, errmsg) - unsigned long insn; - long value; - const char **errmsg; +insert_nsi(unsigned long insn, long value, const char **errmsg) { return insn | ((- value) & 0xffff); } static long -extract_nsi (insn, invalid) - unsigned long insn; - int *invalid; +extract_nsi(unsigned long insn, int *invalid) { if (invalid != (int *) NULL) *invalid = 1; @@ -822,10 +757,7 @@ equal the RT field. */ static unsigned long -insert_ral (insn, value, errmsg) - unsigned long insn; - long value; - const char **errmsg; +insert_ral(unsigned long insn, long value, const char **errmsg) { if (value == 0 || value == ((insn >> 21) & 0x1f)) @@ -837,10 +769,7 @@ restrictions. */ static unsigned long -insert_ram (insn, value, errmsg) - unsigned long insn; - long value; - const char **errmsg; +insert_ram(unsigned long insn, long value, const char **errmsg) { if (value >= ((insn >> 21) & 0x1f)) *errmsg = "index register in load range"; @@ -852,10 +781,7 @@ field may not be zero. */ static unsigned long -insert_ras (insn, value, errmsg) - unsigned long insn; - long value; - const char **errmsg; +insert_ras(unsigned long insn, long value, const char **errmsg) { if (value == 0) *errmsg = "invalid register operand when updating"; @@ -870,18 +796,13 @@ /*ARGSUSED*/ static unsigned long -insert_rbs (insn, value, errmsg) - unsigned long insn; - long value; - const char **errmsg; +insert_rbs(unsigned long insn, long value, const char **errmsg) { return insn | (((insn >> 21) & 0x1f) << 11); } static long -extract_rbs (insn, invalid) - unsigned long insn; - int *invalid; +extract_rbs(unsigned long insn, int *invalid) { if (invalid != (int *) NULL && ((insn >> 21) & 0x1f) != ((insn >> 11) & 0x1f)) @@ -893,19 +814,14 @@ /*ARGSUSED*/ static unsigned long -insert_sh6 (insn, value, errmsg) - unsigned long insn; - long value; - const char **errmsg; +insert_sh6(unsigned long insn, long value, const char **errmsg) { return insn | ((value & 0x1f) << 11) | ((value & 0x20) >> 4); } /*ARGSUSED*/ static long -extract_sh6 (insn, invalid) - unsigned long insn; - int *invalid; +extract_sh6(unsigned long insn, int *invalid) { return ((insn >> 11) & 0x1f) | ((insn << 4) & 0x20); } @@ -914,18 +830,13 @@ lower 5 bits are stored in the upper 5 and vice- versa. */ static unsigned long -insert_spr (insn, value, errmsg) - unsigned long insn; - long value; - const char **errmsg; +insert_spr(unsigned long insn, long value, const char **errmsg) { return insn | ((value & 0x1f) << 16) | ((value & 0x3e0) << 6); } static long -extract_spr (insn, invalid) - unsigned long insn; - int *invalid; +extract_spr(unsigned long insn, int *invalid) { return ((insn >> 16) & 0x1f) | ((insn >> 6) & 0x3e0); } @@ -941,10 +852,7 @@ #define TB (268) static unsigned long -insert_tbr (insn, value, errmsg) - unsigned long insn; - long value; - const char **errmsg; +insert_tbr(unsigned long insn, long value, const char **errmsg) { if (value == 0) value = TB; @@ -952,9 +860,7 @@ } static long -extract_tbr (insn, invalid) - unsigned long insn; - int *invalid; +extract_tbr(unsigned long insn, int *invalid) { long ret; diff -Nru a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c --- a/arch/ppc64/xmon/xmon.c Tue Jul 1 18:44:37 2003 +++ b/arch/ppc64/xmon/xmon.c Tue Jul 1 18:44:37 2003 @@ -26,6 +26,7 @@ #include #include #include +#include #include "nonstdio.h" #include "privinst.h" @@ -469,9 +470,9 @@ } } - if (cpu_has_dabr() && dabr.enabled) + if ((cur_cpu_spec->cpu_features & CPU_FTR_DABR) && dabr.enabled) set_dabr(dabr.address); - if (cpu_has_iabr() && iabr.enabled) + if ((cur_cpu_spec->cpu_features & CPU_FTR_IABR) && iabr.enabled) set_iabr(iabr.address); } @@ -485,9 +486,9 @@ if (systemcfg->platform != PLATFORM_PSERIES) return; - if (cpu_has_dabr()) + if ((cur_cpu_spec->cpu_features & CPU_FTR_DABR)) set_dabr(0); - if (cpu_has_iabr()) + if ((cur_cpu_spec->cpu_features & CPU_FTR_IABR)) set_iabr(0); bp = bpts; @@ -777,7 +778,7 @@ cmd = inchar(); switch (cmd) { case 'd': /* bd - hardware data breakpoint */ - if (cpu_has_dabr()) { + if (!(cur_cpu_spec->cpu_features & CPU_FTR_DABR)) { printf("Not implemented on this cpu\n"); break; } @@ -797,7 +798,7 @@ dabr.address = (dabr.address & ~7) | mode; break; case 'i': /* bi - hardware instr breakpoint */ - if (cpu_has_iabr()) { + if (!(cur_cpu_spec->cpu_features & CPU_FTR_IABR)) { printf("Not implemented on POWER4\n"); break; } diff -Nru a/arch/s390/Kconfig b/arch/s390/Kconfig --- a/arch/s390/Kconfig Tue Jul 1 18:44:34 2003 +++ b/arch/s390/Kconfig Tue Jul 1 18:44:34 2003 @@ -45,6 +45,34 @@ depends on ARCH_S390X = 'n' default y +choice + prompt "Processor type" + default MARCH_G5 + +config MARCH_G5 + bool "S/390 model G5 and G6" + depends on ARCH_S390_31 + help + Select this to build a 31 bit kernel that works + on all S/390 and zSeries machines. + +config MARCH_Z900 + bool "IBM eServer zSeries model z800 and z900" + help + Select this to optimize for zSeries machines. This + will enable some optimizations that are not available + on older 31 bit only CPUs. + +config MARCH_Z990 + bool "IBM eServer zSeries model z990" + help + Select this enable optimizations for model z990. + This will be slightly faster but does not work on + older machines such as the z900. + +endchoice + + config SMP bool "Symmetric multi-processing support" ---help--- @@ -90,7 +118,7 @@ config MATHEMU bool "IEEE FPU emulation" - depends on ARCH_S390X = n + depends on MARCH_G5 help This option is required for IEEE compliant floating point arithmetic on older S/390 machines. Say Y unless you know your machine doesn't @@ -130,7 +158,7 @@ tristate "QDIO support" ---help--- This driver provides the Queued Direct I/O base support for the - IBM S/390 (G5 and G6) and eServer zSeries (z800 and z900). + IBM S/390 (G5 and G6) and eServer zSeries (z800, z900 and z990). For details please refer to the documentation provided by IBM at @@ -231,14 +259,7 @@ source "drivers/base/Kconfig" -menu "SCSI support" - -config SCSI - tristate "SCSI support" - source "drivers/scsi/Kconfig" - -endmenu source "drivers/s390/Kconfig" diff -Nru a/arch/s390/Makefile b/arch/s390/Makefile --- a/arch/s390/Makefile Tue Jul 1 18:44:32 2003 +++ b/arch/s390/Makefile Tue Jul 1 18:44:32 2003 @@ -13,10 +13,13 @@ # Copyright (C) 1994 by Linus Torvalds # +check_gcc = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi) + ifdef CONFIG_ARCH_S390_31 LDFLAGS := -m elf_s390 LDFLAGS_BLOB := --format binary --oformat elf32-s390 CFLAGS += -m31 +AFLAGS += -m31 UTS_MACHINE := s390 endif @@ -25,12 +28,20 @@ MODFLAGS += -fpic -D__PIC__ LDFLAGS_BLOB := --format binary --oformat elf64-s390 CFLAGS += -m64 +AFLAGS += -m64 UTS_MACHINE := s390x endif +cflags-$(CONFIG_MARCH_G5) += $(call check_gcc,-march=g5,) +cflags-$(CONFIG_MARCH_Z900) += $(call check_gcc,-march=z900,) +cflags-$(CONFIG_MARCH_Z990) += $(call check_gcc,-march=trex,) + +CFLAGS += $(cflags-y) +CFLAGS += $(call check_gcc,-finline-limit=10000,) +CFLAGS += -pipe -fno-strength-reduce -Wno-sign-compare + OBJCOPYFLAGS := -O binary LDFLAGS_vmlinux := -e start -CFLAGS += -pipe -fno-strength-reduce -finline-limit-10000 -Wno-sign-compare head-$(CONFIG_ARCH_S390_31) += arch/$(ARCH)/kernel/head.o head-$(CONFIG_ARCH_S390X) += arch/$(ARCH)/kernel/head64.o diff -Nru a/arch/s390/defconfig b/arch/s390/defconfig --- a/arch/s390/defconfig Tue Jul 1 18:44:37 2003 +++ b/arch/s390/defconfig Tue Jul 1 18:44:37 2003 @@ -41,6 +41,9 @@ # # CONFIG_ARCH_S390X is not set CONFIG_ARCH_S390_31=y +CONFIG_MARCH_G5=y +# CONFIG_MARCH_Z900 is not set +# CONFIG_MARCH_Z990 is not set CONFIG_SMP=y CONFIG_NR_CPUS=32 CONFIG_MATHEMU=y @@ -68,6 +71,11 @@ # CONFIG_PCMCIA is not set # +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# # SCSI support # # CONFIG_SCSI is not set @@ -166,6 +174,7 @@ # CONFIG_INET6_AH is not set # CONFIG_INET6_ESP is not set # CONFIG_INET6_IPCOMP is not set +# CONFIG_IPV6_TUNNEL is not set # CONFIG_XFRM_USER is not set # @@ -260,7 +269,14 @@ CONFIG_LCS=m CONFIG_CTC=m CONFIG_IUCV=m -CONFIG_CCWGROUP=m +CONFIG_QETH=y + +# +# Gigabit Ethernet default settings +# +# CONFIG_QETH_IPV6 is not set +# CONFIG_QETH_PERF_STATS is not set +CONFIG_CCWGROUP=y # # File systems diff -Nru a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile --- a/arch/s390/kernel/Makefile Tue Jul 1 18:44:39 2003 +++ b/arch/s390/kernel/Makefile Tue Jul 1 18:44:39 2003 @@ -23,11 +23,6 @@ obj-$(CONFIG_ARCH_S390_31) += entry.o reipl.o obj-$(CONFIG_ARCH_S390X) += entry64.o reipl64.o -ifdef CONFIG_ARCH_S390X -$(obj)%.o: $(patsubst arch/s390/%,arch/s390x/%,$(src))%.c - $(call if_changed_dep,cc_o_c) -endif - # # This is just to get the dependencies... # diff -Nru a/arch/s390/kernel/compat_ioctl.c b/arch/s390/kernel/compat_ioctl.c --- a/arch/s390/kernel/compat_ioctl.c Tue Jul 1 18:44:36 2003 +++ b/arch/s390/kernel/compat_ioctl.c Tue Jul 1 18:44:36 2003 @@ -42,12 +42,15 @@ #include #include #include +#include #include #include #include +#include #include #include +#include #include #include diff -Nru a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c --- a/arch/s390/kernel/compat_linux.c Tue Jul 1 18:44:37 2003 +++ b/arch/s390/kernel/compat_linux.c Tue Jul 1 18:44:37 2003 @@ -373,12 +373,45 @@ unsigned int __unused5; }; - -/* - * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation.. - * - * This is really horribly ugly. - */ +extern int sem_ctls[]; +#define sc_semopm (sem_ctls[2]) +#define SEMOPM_FAST 64 /* ~ 372 bytes on stack */ + +static long +do_sys32_semtimedop (int semid, struct sembuf *tsops, int nsops, + struct compat_timespec *timeout32) +{ + struct sembuf *sops, fast_sops[SEMOPM_FAST]; + struct timespec t; + mm_segment_t oldfs; + long ret; + + /* parameter checking precedence should mirror sys_semtimedop() */ + if (nsops < 1 || semid < 0) + return -EINVAL; + if (nsops > sc_semopm) + return -E2BIG; + if (nsops <= SEMOPM_FAST) + sops = fast_sops; + else { + sops = kmalloc(nsops * sizeof(*sops), GFP_KERNEL); + if (sops == NULL) + return -ENOMEM; + } + if (copy_from_user(sops, tsops, nsops * sizeof(*tsops)) || + get_compat_timespec(&t, timeout32)) + ret = -EFAULT; + else { + oldfs = get_fs(); + set_fs(KERNEL_DS); + ret = sys_semtimedop(semid, sops, nsops, &t); + set_fs(oldfs); + } + if (sops != fast_sops) + kfree(sops); + return ret; +} + #define IPCOP_MASK(__x) (1UL << (__x)) static int do_sys32_semctl(int first, int second, int third, void *uptr) { @@ -763,7 +796,12 @@ return err; } -asmlinkage int sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth) +/* + * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation. + * + * This is really horribly ugly. + */ +asmlinkage int sys32_ipc (u32 call, int first, int second, int third, u32 ptr) { int version, err; @@ -773,11 +811,22 @@ if(version) return -EINVAL; - if (call <= SEMCTL) + if (call <= SEMTIMEDOP) switch (call) { + case SEMTIMEDOP: + if (third) { + err = do_sys32_semtimedop(first, + (struct sembuf *)AA(ptr), + second, + (struct compat_timespec *) + AA((u32)third)); + goto out; + } + /* else fall through for normal semop() */ case SEMOP: /* struct sembuf is the same on 32 and 64bit :)) */ - err = sys_semop (first, (struct sembuf *)AA(ptr), second); + err = sys_semtimedop (first, (struct sembuf *)AA(ptr), + second, NULL); goto out; case SEMGET: err = sys_semget (first, second, third); @@ -2193,7 +2242,6 @@ sorts of things, like timeval and itimerval. */ extern struct timezone sys_tz; -extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz); asmlinkage int sys32_gettimeofday(struct compat_timeval *tv, struct timezone *tz) { @@ -2210,13 +2258,27 @@ return 0; } +static inline long get_ts32(struct timespec *o, struct compat_timeval *i) +{ + long usec; + + if (!access_ok(VERIFY_READ, i, sizeof(*i))) + return -EFAULT; + if (__get_user(o->tv_sec, &i->tv_sec)) + return -EFAULT; + if (__get_user(usec, &i->tv_usec)) + return -EFAULT; + o->tv_nsec = usec * 1000; + return 0; +} + asmlinkage int sys32_settimeofday(struct compat_timeval *tv, struct timezone *tz) { - struct timeval ktv; + struct timespec kts; struct timezone ktz; if (tv) { - if (get_tv32(&ktv, tv)) + if (get_ts32(&kts, tv)) return -EFAULT; } if (tz) { @@ -2224,7 +2286,7 @@ return -EFAULT; } - return do_sys_settimeofday(tv ? &ktv : NULL, tz ? &ktz : NULL); + return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL); } asmlinkage int sys_utimes(char *, struct timeval *); diff -Nru a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S --- a/arch/s390/kernel/entry.S Tue Jul 1 18:44:32 2003 +++ b/arch/s390/kernel/entry.S Tue Jul 1 18:44:32 2003 @@ -267,7 +267,7 @@ st %r7,SP_R2(%r15) basr %r14,%r1 clc SP_R2(4,%r15),BASED(.Lnr_syscalls) - bl BASED(sysc_tracego) + bnl BASED(sysc_tracenogo) l %r7,SP_R2(%r15) # strace might have changed the sll %r7,2 # system call l %r8,sys_call_table-entry_base(%r7,%r13) @@ -276,6 +276,7 @@ l %r2,SP_ORIG_R2(%r15) basr %r14,%r8 # call sys_xxx st %r2,SP_R2(%r15) # store return value +sysc_tracenogo: tm __TI_flags+3(%r9),_TIF_SYSCALL_TRACE bno BASED(sysc_return) l %r1,BASED(.Ltrace) @@ -486,7 +487,7 @@ st %r7,SP_R2(%r15) basr %r14,%r1 clc SP_R2(4,%r15),BASED(.Lnr_syscalls) - bl BASED(pgm_svc_go) + bnl BASED(pgm_svc_nogo) l %r7,SP_R2(%r15) # strace changed the syscall sll %r7,2 l %r8,sys_call_table-entry_base(%r7,%r13) @@ -495,6 +496,7 @@ l %r2,SP_ORIG_R2(%r15) basr %r14,%r8 # call sys_xxx st %r2,SP_R2(%r15) # store return value +pgm_svc_nogo: tm __TI_flags+3(%r9),_TIF_SYSCALL_TRACE bno BASED(pgm_svcret) l %r1,BASED(.Ltrace) diff -Nru a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S --- a/arch/s390/kernel/entry64.S Tue Jul 1 18:44:32 2003 +++ b/arch/s390/kernel/entry64.S Tue Jul 1 18:44:32 2003 @@ -254,7 +254,7 @@ brasl %r14,syscall_trace larl %r1,.Lnr_syscalls clc SP_R2(8,%r15),0(%r1) - jl sysc_tracego + jnl sysc_tracenogo lg %r7,SP_R2(%r15) # strace might have changed the sll %r7,2 # system call lgf %r8,0(%r7,%r10) @@ -263,6 +263,7 @@ lg %r2,SP_ORIG_R2(%r15) basr %r14,%r8 # call sys_xxx stg %r2,SP_R2(%r15) # store return value +sysc_tracenogo: tm __TI_flags+7(%r9),_TIF_SYSCALL_TRACE jno sysc_return larl %r14,sysc_return # return point is sysc_return @@ -481,7 +482,7 @@ # pgm_svcper: SAVE_ALL __LC_SVC_OLD_PSW,1 - llgh %r8,__LC_SVC_INT_CODE # get svc number from lowcore + llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore stosm 48(%r15),0x03 # reenable interrupts GET_THREAD_INFO # load pointer to task_struct to R9 slag %r7,%r7,2 # *4 and test for svc 0 @@ -490,15 +491,15 @@ clg %r1,.Lnr_syscalls-.Lconst(%r14) slag %r7,%r1,2 pgm_svcstd: - larl %r7,sys_call_table + larl %r10,sys_call_table #ifdef CONFIG_S390_SUPPORT tm SP_PSW+3(%r15),0x01 # are we running in 31 bit mode ? jo pgm_svcper_noemu - larl %r7,sys_call_table_emu # use 31 bit emulation system calls + larl %r10,sys_call_table_emu # use 31 bit emulation system calls pgm_svcper_noemu: #endif tm __TI_flags+3(%r9),_TIF_SYSCALL_TRACE - lgf %r8,0(%r8,%r7) # load address of system call routine + lgf %r8,0(%r7,%r10) # load address of system call routine jo pgm_tracesys basr %r14,%r8 # call sys_xxxx stg %r2,SP_R2(%r15) # store return value (change R2 on stack) @@ -522,19 +523,20 @@ # call trace before and after sys_call # pgm_tracesys: - lgfr %r7,%r7 + srlg %r7,%r7,2 stg %r7,SP_R2(%r15) brasl %r14,syscall_trace clc SP_R2(8,%r15),.Lnr_syscalls - jnl pgm_svc_go - lg %r2,SP_R2(%r15) - sllg %r2,%r2,3 # strace wants to change the syscall - lgf %r8,0(%r2,%r7) + jnl pgm_svc_nogo + lg %r7,SP_R2(%r15) + sllg %r7,%r7,2 # strace wants to change the syscall + lgf %r8,0(%r7,%r10) pgm_svc_go: lmg %r3,%r6,SP_R3(%r15) lg %r2,SP_ORIG_R2(%r15) basr %r14,%r8 # call sys_xxx stg %r2,SP_R2(%r15) # store return value +pgm_svc_nogo: tm __TI_flags+7(%r9),_TIF_SYSCALL_TRACE jno pgm_svcret larl %r14,pgm_svcret # return point is sysc_return diff -Nru a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S --- a/arch/s390/kernel/head.S Tue Jul 1 18:44:33 2003 +++ b/arch/s390/kernel/head.S Tue Jul 1 18:44:33 2003 @@ -533,6 +533,10 @@ bne .Lnop390-.LPG1(%r13) oi 3(%r12),4 # set P/390 flag .Lnop390: + chi %r0,0x2084 # new stidp format? + bne .Loldfmt-.LPG1(%r13) + oi 3(%r12),64 # set new stidp flag +.Loldfmt: # # find out if we have an IEEE fpu diff -Nru a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S --- a/arch/s390/kernel/head64.S Tue Jul 1 18:44:34 2003 +++ b/arch/s390/kernel/head64.S Tue Jul 1 18:44:34 2003 @@ -553,6 +553,10 @@ bne 1f-.LPG1(%r13) oi 7(%r12),4 # set P/390 flag 1: + chi %r0,0x2084 # new stidp format? + bne 2f-.LPG1(%r13) + oi 7(%r12),64 # set new stidp flag +2: # # find out if we have the MVPG instruction diff -Nru a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c --- a/arch/s390/kernel/module.c Tue Jul 1 18:44:37 2003 +++ b/arch/s390/kernel/module.c Tue Jul 1 18:44:37 2003 @@ -67,12 +67,14 @@ switch (ELF_R_TYPE (rela->r_info)) { case R_390_GOT12: /* 12 bit GOT offset. */ case R_390_GOT16: /* 16 bit GOT offset. */ + case R_390_GOT20: /* 20 bit GOT offset. */ case R_390_GOT32: /* 32 bit GOT offset. */ case R_390_GOT64: /* 64 bit GOT offset. */ case R_390_GOTENT: /* 32 bit PC rel. to GOT entry shifted by 1. */ case R_390_GOTPLT12: /* 12 bit offset to jump slot. */ - case R_390_GOTPLT16: /* 16 bit offset to jump slot. */ - case R_390_GOTPLT32: /* 32 bit offset to jump slot. */ + case R_390_GOTPLT16: /* 16 bit offset to jump slot. */ + case R_390_GOTPLT20: /* 20 bit offset to jump slot. */ + case R_390_GOTPLT32: /* 32 bit offset to jump slot. */ case R_390_GOTPLT64: /* 64 bit offset to jump slot. */ case R_390_GOTPLTENT: /* 32 bit rel. offset to jump slot >> 1. */ if (info->got_offset == -1UL) { @@ -201,6 +203,7 @@ case R_390_8: /* Direct 8 bit. */ case R_390_12: /* Direct 12 bit. */ case R_390_16: /* Direct 16 bit. */ + case R_390_20: /* Direct 20 bit. */ case R_390_32: /* Direct 32 bit. */ case R_390_64: /* Direct 64 bit. */ val += rela->r_addend; @@ -211,6 +214,10 @@ (*(unsigned short *) loc & 0xf000); else if (r_type == R_390_16) *(unsigned short *) loc = val; + else if (r_type == R_390_20) + *(unsigned int *) loc = + (*(unsigned int *) loc & 0xf00000ff) | + (val & 0xfff) << 16 | (val & 0xff000) >> 4; else if (r_type == R_390_32) *(unsigned int *) loc = val; else if (r_type == R_390_64) @@ -235,12 +242,14 @@ break; case R_390_GOT12: /* 12 bit GOT offset. */ case R_390_GOT16: /* 16 bit GOT offset. */ + case R_390_GOT20: /* 20 bit GOT offset. */ case R_390_GOT32: /* 32 bit GOT offset. */ case R_390_GOT64: /* 64 bit GOT offset. */ case R_390_GOTENT: /* 32 bit PC rel. to GOT entry shifted by 1. */ case R_390_GOTPLT12: /* 12 bit offset to jump slot. */ - case R_390_GOTPLT16: /* 16 bit offset to jump slot. */ - case R_390_GOTPLT32: /* 32 bit offset to jump slot. */ + case R_390_GOTPLT20: /* 20 bit offset to jump slot. */ + case R_390_GOTPLT16: /* 16 bit offset to jump slot. */ + case R_390_GOTPLT32: /* 32 bit offset to jump slot. */ case R_390_GOTPLT64: /* 64 bit offset to jump slot. */ case R_390_GOTPLTENT: /* 32 bit rel. offset to jump slot >> 1. */ if (info->got_initialized == 0) { @@ -259,6 +268,11 @@ else if (r_type == R_390_GOT16 || r_type == R_390_GOTPLT16) *(unsigned short *) loc = val; + else if (r_type == R_390_GOT20 || + r_type == R_390_GOTPLT20) + *(unsigned int *) loc = + (*(unsigned int *) loc & 0xf00000ff) | + (val & 0xfff) << 16 | (val & 0xff000) >> 4; else if (r_type == R_390_GOT32 || r_type == R_390_GOTPLT32) *(unsigned int *) loc = val; diff -Nru a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c --- a/arch/s390/kernel/smp.c Tue Jul 1 18:44:31 2003 +++ b/arch/s390/kernel/smp.c Tue Jul 1 18:44:31 2003 @@ -419,8 +419,6 @@ boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr; current_thread_info()->cpu = 0; num_cpus = 1; - cpu_possible_map = 1; - cpu_online_map = 1; for (curr_cpu = 0; curr_cpu <= 65535 && num_cpus < max_cpus; curr_cpu++) { if ((__u16) curr_cpu == boot_cpu_addr) diff -Nru a/arch/s390/kernel/sys_s390.c b/arch/s390/kernel/sys_s390.c --- a/arch/s390/kernel/sys_s390.c Tue Jul 1 18:44:34 2003 +++ b/arch/s390/kernel/sys_s390.c Tue Jul 1 18:44:34 2003 @@ -184,8 +184,7 @@ * This is really horribly ugly. */ asmlinkage __SYS_RETTYPE sys_ipc (uint call, int first, int second, - unsigned long third, void *ptr, - unsigned long fifth) + unsigned long third, void *ptr) { struct ipc_kludge tmp; int ret; @@ -195,8 +194,8 @@ return sys_semtimedop (first, (struct sembuf *) ptr, second, NULL); case SEMTIMEDOP: - return sys_semtimedop(first, (struct sembuf *) ptr, second, - (const struct timespec *) fifth); + return sys_semtimedop (first, (struct sembuf *) ptr, second, + (const struct timespec *) third); case SEMGET: return sys_semget (first, second, third); case SEMCTL: { diff -Nru a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S --- a/arch/s390/kernel/syscalls.S Tue Jul 1 18:44:32 2003 +++ b/arch/s390/kernel/syscalls.S Tue Jul 1 18:44:32 2003 @@ -118,7 +118,7 @@ SYSCALL(sys_newlstat,sys_newlstat,compat_sys_newlstat_wrapper) SYSCALL(sys_newfstat,sys_newfstat,compat_sys_newfstat_wrapper) NI_SYSCALL /* old uname syscall */ -NI_SYSCALL /* 110 iopl for i386 */ +NI_SYSCALL /* reserved for sys_lookup_dcache */ SYSCALL(sys_vhangup,sys_vhangup,sys_vhangup) NI_SYSCALL /* old "idle" system call */ NI_SYSCALL /* vm86old for i386 */ diff -Nru a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c --- a/arch/s390/kernel/traps.c Tue Jul 1 18:44:34 2003 +++ b/arch/s390/kernel/traps.c Tue Jul 1 18:44:34 2003 @@ -78,7 +78,7 @@ #endif /* CONFIG_ARCH_S390X */ -void show_trace(unsigned long * stack) +void show_trace(struct task_struct *task, unsigned long * stack) { unsigned long backchain, low_addr, high_addr, ret_addr; @@ -109,10 +109,10 @@ */ if (tsk->state == TASK_RUNNING) return; - show_trace((unsigned long *) tsk->thread.ksp); + show_trace(tsk, (unsigned long *) tsk->thread.ksp); } -void show_stack(unsigned long *sp) +void show_stack(struct task_struct *task, unsigned long *sp) { unsigned long *stack; int i; @@ -132,7 +132,7 @@ printk("%p ", (void *)*stack++); } printk("\n"); - show_trace(sp); + show_trace(task, sp); } /* @@ -140,7 +140,7 @@ */ void dump_stack(void) { - show_stack(0); + show_stack(current, 0); } void show_registers(struct pt_regs *regs) diff -Nru a/arch/sh/Kconfig b/arch/sh/Kconfig --- a/arch/sh/Kconfig Tue Jul 1 18:44:39 2003 +++ b/arch/sh/Kconfig Tue Jul 1 18:44:39 2003 @@ -777,68 +777,9 @@ source "drivers/ide/Kconfig" - -menu "SCSI device support" - -config SCSI - tristate "SCSI device support" - ---help--- - If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or - any other SCSI device under Linux, say Y and make sure that you know - the name of your SCSI host adapter (the card inside your computer - that "speaks" the SCSI protocol, also called SCSI controller), - because you will be asked for it. - - You also need to say Y here if you want support for the parallel - port version of the 100 MB IOMEGA ZIP drive. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called scsi_mod. If you want to compile it as - a module, say M here and read and - . However, do not compile this as a - module if your root file system (the one containing the directory /) - is located on a SCSI device. - source "drivers/scsi/Kconfig" -endmenu - - -menu "Old CD-ROM drivers (not SCSI, not IDE)" - -config CD_NO_IDESCSI - bool "Support non-SCSI/IDE/ATAPI CDROM drives" - ---help--- - If you have a CD-ROM drive that is neither SCSI nor IDE/ATAPI, say Y - here, otherwise N. Read the CD-ROM-HOWTO, available from - . - - Note that the answer to this question doesn't directly affect the - kernel: saying N will just cause the configurator to skip all - the questions about these CD-ROM drives. If you are unsure what you - have, say Y and find out whether you have one of the following - drives. - - For each of these drivers, a file Documentation/cdrom/{driver_name} - exists. Especially in cases where you do not know exactly which kind - of drive you have you should read there. Most of these drivers use a - file drivers/cdrom/{driver_name}.h where you can define your - interface parameters and switch some internal goodies. - - All these CD-ROM drivers are also usable as a module ( = code which - can be inserted in and removed from the running kernel whenever you - want). If you want to compile them as module, say M instead of Y and - read . - - If you want to use any of these CD-ROM drivers, you also have to - answer Y or M to "ISO 9660 CD-ROM file system support" below (this - answer will get "defaulted" for you if you enable any of the Linux - CD-ROM drivers). - source "drivers/cdrom/Kconfig" - -endmenu source "drivers/md/Kconfig" diff -Nru a/arch/sparc/Kconfig b/arch/sparc/Kconfig --- a/arch/sparc/Kconfig Tue Jul 1 18:44:31 2003 +++ b/arch/sparc/Kconfig Tue Jul 1 18:44:31 2003 @@ -481,32 +481,7 @@ source "drivers/isdn/Kconfig" - -menu "SCSI support" - -config SCSI - tristate "SCSI support" - ---help--- - If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or - any other SCSI device under Linux, say Y and make sure that you know - the name of your SCSI host adapter (the card inside your computer - that "speaks" the SCSI protocol, also called SCSI controller), - because you will be asked for it. - - You also need to say Y here if you want support for the parallel - port version of the 100 MB IOMEGA ZIP drive. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called scsi_mod. If you want to compile it as - a module, say M here and read and - . However, do not compile this as a - module if your root file system (the one containing the directory /) - is located on a SCSI device. - source "drivers/scsi/Kconfig" - -endmenu source "drivers/fc4/Kconfig" diff -Nru a/arch/sparc/Makefile b/arch/sparc/Makefile --- a/arch/sparc/Makefile Tue Jul 1 18:44:32 2003 +++ b/arch/sparc/Makefile Tue Jul 1 18:44:32 2003 @@ -52,7 +52,9 @@ CORE_Y := $(patsubst %/, %/built-in.o, $(CORE_Y)) DRIVERS_Y := $(patsubst %/, %/built-in.o, $(drivers-y)) NET_Y := $(patsubst %/, %/built-in.o, $(net-y)) -LIBS_Y := $(patsubst %/, %/lib.a, $(libs-y)) +LIBS_Y1 := $(patsubst %/, %/lib.a, $(libs-y)) +LIBS_Y2 := $(patsubst %/, %/built-in.o, $(libs-y)) +LIBS_Y := $(LIBS_Y1) $(LIBS_Y2) export INIT_Y CORE_Y DRIVERS_Y NET_Y LIBS_Y HEAD_Y # Default target diff -Nru a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c --- a/arch/sparc/kernel/process.c Tue Jul 1 18:44:32 2003 +++ b/arch/sparc/kernel/process.c Tue Jul 1 18:44:32 2003 @@ -287,17 +287,14 @@ rw->ins[4], rw->ins[5], rw->ins[6], rw->ins[7]); } -void show_trace_task(struct task_struct *tsk) +void show_stack(struct task_struct *tsk, unsigned long *_ksp) { unsigned long pc, fp; unsigned long task_base = (unsigned long) tsk; struct reg_window *rw; int count = 0; - if (!tsk) - return; - - fp = tsk->thread_info->ksp; + fp = (unsigned long) _ksp; do { /* Bogus frame pointer? */ if (fp < (task_base + sizeof(struct task_struct)) || @@ -309,6 +306,13 @@ fp = rw->ins[6]; } while (++count < 16); printk("\n"); +} + +void show_trace_task(struct task_struct *tsk) +{ + if (tsk) + show_stack(tsk, + (unsigned long *) tsk->thread_info->ksp); } /* diff -Nru a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S --- a/arch/sparc/kernel/systbls.S Tue Jul 1 18:44:35 2003 +++ b/arch/sparc/kernel/systbls.S Tue Jul 1 18:44:35 2003 @@ -64,9 +64,9 @@ /*215*/ .long sys_ipc, sys_sigreturn, sys_clone, sys_nis_syscall, sys_adjtimex /*220*/ .long sys_sigprocmask, sys_ni_syscall, sys_delete_module, sys_ni_syscall, sys_getpgid /*225*/ .long sys_bdflush, sys_sysfs, sys_nis_syscall, sys_setfsuid16, sys_setfsgid16 -/*230*/ .long sys_select, sys_time, sys_nis_syscall, sys_stime, sys_nis_syscall +/*230*/ .long sys_select, sys_time, sys_nis_syscall, sys_stime, sys_statfs64 /* "We are the Knights of the Forest of Ni!!" */ -/*235*/ .long sys_nis_syscall, sys_llseek, sys_mlock, sys_munlock, sys_mlockall +/*235*/ .long sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys_mlockall /*240*/ .long sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler /*245*/ .long sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep /*250*/ .long sparc_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl diff -Nru a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig --- a/arch/sparc64/Kconfig Tue Jul 1 18:44:37 2003 +++ b/arch/sparc64/Kconfig Tue Jul 1 18:44:37 2003 @@ -675,32 +675,7 @@ source "drivers/ide/Kconfig" - -menu "SCSI support" - -config SCSI - tristate "SCSI support" - ---help--- - If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or - any other SCSI device under Linux, say Y and make sure that you know - the name of your SCSI host adapter (the card inside your computer - that "speaks" the SCSI protocol, also called SCSI controller), - because you will be asked for it. - - You also need to say Y here if you want support for the parallel - port version of the 100 MB IOMEGA ZIP drive. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called scsi_mod. If you want to compile it as - a module, say M here and read and - . However, do not compile this as a - module if your root file system (the one containing the directory /) - is located on a SCSI device. - source "drivers/scsi/Kconfig" - -endmenu source "drivers/fc4/Kconfig" diff -Nru a/arch/sparc64/defconfig b/arch/sparc64/defconfig --- a/arch/sparc64/defconfig Tue Jul 1 18:44:34 2003 +++ b/arch/sparc64/defconfig Tue Jul 1 18:44:34 2003 @@ -27,7 +27,7 @@ CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y CONFIG_OBSOLETE_MODPARM=y -# CONFIG_MODVERSIONS is not set +CONFIG_MODVERSIONS=y CONFIG_KMOD=y # @@ -162,7 +162,9 @@ # CONFIG_SERIAL_SUNCORE=y CONFIG_SERIAL_SUNZILOG=y +CONFIG_SERIAL_SUNZILOG_CONSOLE=y CONFIG_SERIAL_SUNSU=y +CONFIG_SERIAL_SUNSU_CONSOLE=y CONFIG_SERIAL_SUNSAB=m CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y @@ -197,8 +199,8 @@ CONFIG_MD_LINEAR=m CONFIG_MD_RAID0=m CONFIG_MD_RAID1=m -# CONFIG_MD_RAID5 is not set -# CONFIG_MD_MULTIPATH is not set +CONFIG_MD_RAID5=m +CONFIG_MD_MULTIPATH=m CONFIG_BLK_DEV_DM=m # CONFIG_BLK_DEV_RAM is not set @@ -243,26 +245,27 @@ # CONFIG_BLK_DEV_AEC62XX is not set CONFIG_BLK_DEV_ALI15X3=y # CONFIG_WDC_ALI15X3 is not set -# CONFIG_BLK_DEV_AMD74XX is not set -# CONFIG_BLK_DEV_CMD64X is not set -# CONFIG_BLK_DEV_TRIFLEX is not set -# CONFIG_BLK_DEV_CY82C693 is not set -# CONFIG_BLK_DEV_CS5520 is not set -# CONFIG_BLK_DEV_HPT34X is not set -# CONFIG_BLK_DEV_HPT366 is not set -# CONFIG_BLK_DEV_SC1200 is not set -# CONFIG_BLK_DEV_PIIX is not set -# CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_OPTI621 is not set -# CONFIG_BLK_DEV_PDC202XX_OLD is not set -# CONFIG_BLK_DEV_PDC202XX_NEW is not set -# CONFIG_BLK_DEV_SVWKS is not set -# CONFIG_BLK_DEV_SIIMAGE is not set -# CONFIG_BLK_DEV_SLC90E66 is not set -# CONFIG_BLK_DEV_TRM290 is not set -# CONFIG_BLK_DEV_VIA82CXXX is not set +CONFIG_BLK_DEV_AMD74XX=m +CONFIG_BLK_DEV_CMD64X=m +CONFIG_BLK_DEV_TRIFLEX=m +CONFIG_BLK_DEV_CY82C693=m +CONFIG_BLK_DEV_CS5520=m +CONFIG_BLK_DEV_HPT34X=m +CONFIG_BLK_DEV_HPT366=m +CONFIG_BLK_DEV_SC1200=m +CONFIG_BLK_DEV_PIIX=m +CONFIG_BLK_DEV_NS87415=m +CONFIG_BLK_DEV_OPTI621=m +CONFIG_BLK_DEV_PDC202XX_OLD=m +CONFIG_BLK_DEV_PDC202XX_NEW=m +CONFIG_BLK_DEV_SVWKS=m +CONFIG_BLK_DEV_SIIMAGE=m +CONFIG_BLK_DEV_SLC90E66=m +CONFIG_BLK_DEV_TRM290=m +CONFIG_BLK_DEV_VIA82CXXX=m CONFIG_IDEDMA_AUTO=y # CONFIG_IDEDMA_IVB is not set +CONFIG_BLK_DEV_PDC202XX=y CONFIG_BLK_DEV_IDE_MODES=y # @@ -408,14 +411,18 @@ CONFIG_UNIX=y CONFIG_NET_KEY=m CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set +CONFIG_IP_MULTICAST=y # CONFIG_IP_ADVANCED_ROUTER is not set # CONFIG_IP_PNP is not set CONFIG_NET_IPIP=m CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y CONFIG_ARPD=y CONFIG_INET_ECN=y -# CONFIG_SYN_COOKIES is not set +CONFIG_SYN_COOKIES=y CONFIG_INET_AH=y CONFIG_INET_ESP=y CONFIG_INET_IPCOMP=y @@ -436,6 +443,7 @@ CONFIG_IP_NF_MATCH_MARK=m CONFIG_IP_NF_MATCH_MULTIPORT=m CONFIG_IP_NF_MATCH_TOS=m +CONFIG_IP_NF_MATCH_RECENT=m CONFIG_IP_NF_MATCH_ECN=m CONFIG_IP_NF_MATCH_DSCP=m CONFIG_IP_NF_MATCH_AH_ESP=m @@ -553,9 +561,9 @@ CONFIG_BRIDGE_EBT_DNAT=m CONFIG_BRIDGE_EBT_REDIRECT=m CONFIG_BRIDGE_EBT_MARK_T=m -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set +CONFIG_X25=m +CONFIG_LAPB=m +CONFIG_NET_DIVERT=y # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set # CONFIG_NET_FASTROUTE is not set @@ -661,11 +669,13 @@ # # Ethernet (1000 Mbit) # -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_E1000 is not set +CONFIG_ACENIC=m +# CONFIG_ACENIC_OMIT_TIGON_I is not set +CONFIG_DL2K=m +CONFIG_E1000=m +CONFIG_E1000_NAPI=y CONFIG_MYRI_SBUS=m -# CONFIG_NS83820 is not set +CONFIG_NS83820=m CONFIG_HAMACHI=m CONFIG_YELLOWFIN=m CONFIG_R8169=m @@ -710,8 +720,11 @@ # # Wireless 802.11b ISA/PCI cards support # -# CONFIG_AIRO is not set -# CONFIG_HERMES is not set +CONFIG_AIRO=m +CONFIG_HERMES=m +CONFIG_PLX_HERMES=m +CONFIG_TMD_HERMES=m +CONFIG_PCI_HERMES=m CONFIG_NET_WIRELESS=y # @@ -934,7 +947,6 @@ # CONFIG_KEYBOARD_NEWTON is not set CONFIG_INPUT_MOUSE=y CONFIG_MOUSE_PS2=y -CONFIG_MOUSE_PS2_SYNAPTICS=y CONFIG_MOUSE_SERIAL=y # CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_TOUCHSCREEN is not set diff -Nru a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S --- a/arch/sparc64/kernel/systbls.S Tue Jul 1 18:44:34 2003 +++ b/arch/sparc64/kernel/systbls.S Tue Jul 1 18:44:34 2003 @@ -65,8 +65,8 @@ .word sys32_ipc, sys32_sigreturn, sys_clone, sys_nis_syscall, sys32_adjtimex /*220*/ .word compat_sys_sigprocmask, sys_ni_syscall, sys32_delete_module, sys_ni_syscall, sys_getpgid .word sys32_bdflush, sys32_sysfs, sys_nis_syscall, sys32_setfsuid16, sys32_setfsgid16 -/*230*/ .word sys32_select, sys_time, sys_nis_syscall, sys_stime, sys_ni_syscall - .word sys_ni_syscall, sys_llseek, sys_mlock, sys_munlock, sys_mlockall +/*230*/ .word sys32_select, sys_time, sys_nis_syscall, sys_stime, sys_statfs64 + .word sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys_mlockall /*240*/ .word sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler .word sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys32_sched_rr_get_interval, compat_sys_nanosleep /*250*/ .word sys32_mremap, sys32_sysctl, sys_getsid, sys_fdatasync, sys32_nfsservctl @@ -124,11 +124,8 @@ .word sys_ipc, sys_nis_syscall, sys_clone, sys_nis_syscall, sys_adjtimex /*220*/ .word sys_nis_syscall, sys_ni_syscall, sys_delete_module, sys_ni_syscall, sys_getpgid .word sys_bdflush, sys_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid - - /* 234 and 235 were for the hugetlb syscalls. They can be reused */ - -/*230*/ .word sys_select, sys_nis_syscall, sys_nis_syscall, sys_stime, sys_nis_syscall - .word sys_nis_syscall, sys_llseek, sys_mlock, sys_munlock, sys_mlockall +/*230*/ .word sys_select, sys_nis_syscall, sys_nis_syscall, sys_stime, sys_statfs64 + .word sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys_mlockall /*240*/ .word sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler .word sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep /*250*/ .word sys64_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl diff -Nru a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c --- a/arch/sparc64/kernel/traps.c Tue Jul 1 18:44:39 2003 +++ b/arch/sparc64/kernel/traps.c Tue Jul 1 18:44:39 2003 @@ -1569,12 +1569,15 @@ printk("\n"); } -void show_trace_raw(struct thread_info *tp, unsigned long ksp) +void show_stack(struct task_struct *tsk, unsigned long *_ksp) { - unsigned long pc, fp, thread_base; + unsigned long pc, fp, thread_base, ksp; + struct thread_info *tp = tsk->thread_info; struct reg_window *rw; int count = 0; + ksp = (unsigned long) _ksp; + if (tp == current_thread_info()) flushw_all(); @@ -1596,17 +1599,17 @@ void show_trace_task(struct task_struct *tsk) { if (tsk) - show_trace_raw(tsk->thread_info, - tsk->thread_info->ksp); + show_stack(tsk, + (unsigned long *) tsk->thread_info->ksp); } void dump_stack(void) { - unsigned long ksp; + unsigned long *ksp; __asm__ __volatile__("mov %%fp, %0" : "=r" (ksp)); - show_trace_raw(current_thread_info(), ksp); + show_stack(current, ksp); } void die_if_kernel(char *str, struct pt_regs *regs) diff -Nru a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c --- a/arch/sparc64/mm/fault.c Tue Jul 1 18:44:38 2003 +++ b/arch/sparc64/mm/fault.c Tue Jul 1 18:44:38 2003 @@ -149,16 +149,14 @@ die_if_kernel("Oops", regs); } -extern void show_trace_raw(struct thread_info *, unsigned long); - static void bad_kernel_pc(struct pt_regs *regs) { - unsigned long ksp; + unsigned long *ksp; printk(KERN_CRIT "OOPS: Bogus kernel PC [%016lx] in fault handler\n", regs->tpc); __asm__("mov %%sp, %0" : "=r" (ksp)); - show_trace_raw(current_thread_info(), ksp); + show_stack(current, ksp); unhandled_fault(regs->tpc, current, regs); } diff -Nru a/arch/sparc64/prom/init.c b/arch/sparc64/prom/init.c --- a/arch/sparc64/prom/init.c Tue Jul 1 18:44:39 2003 +++ b/arch/sparc64/prom/init.c Tue Jul 1 18:44:39 2003 @@ -36,6 +36,7 @@ int ints[3]; int node; int i = 0; + int bufadjust; prom_vers = PROM_P1275; @@ -63,9 +64,19 @@ if (strncmp (buffer, "OBP ", 4)) goto strange_version; - /* Version field is expected to be 'OBP xx.yy.zz date...' */ + /* + * Version field is expected to be 'OBP xx.yy.zz date...' + * However, Sun can't stick to this format very well, so + * we need to check for 'OBP xx.yy.zz date...' and adjust + * accordingly. -spot + */ + + if (strncmp (buffer, "OBP ", 5)) + bufadjust = 4; + else + bufadjust = 5; - p = buffer + 4; + p = buffer + bufadjust; while (p && isdigit(*p) && i < 3) { ints[i++] = simple_strtoul(p, NULL, 0); if ((p = strchr(p, '.')) != NULL) @@ -77,7 +88,7 @@ prom_rev = ints[1]; prom_prev = (ints[0] << 16) | (ints[1] << 8) | ints[2]; - printk ("PROMLIB: Sun IEEE Boot Prom %s\n", buffer + 4); + printk ("PROMLIB: Sun IEEE Boot Prom %s\n", buffer + bufadjust); prom_meminit(); diff -Nru a/arch/sparc64/solaris/fs.c b/arch/sparc64/solaris/fs.c --- a/arch/sparc64/solaris/fs.c Tue Jul 1 18:44:33 2003 +++ b/arch/sparc64/solaris/fs.c Tue Jul 1 18:44:33 2003 @@ -390,7 +390,7 @@ static int report_statvfs(struct vfsmount *mnt, struct inode *inode, u32 buf) { - struct statfs s; + struct kstatfs s; int error; struct sol_statvfs *ss = (struct sol_statvfs *)A(buf); @@ -424,7 +424,7 @@ static int report_statvfs64(struct vfsmount *mnt, struct inode *inode, u32 buf) { - struct statfs s; + struct kstatfs s; int error; struct sol_statvfs64 *ss = (struct sol_statvfs64 *)A(buf); diff -Nru a/arch/v850/Kconfig b/arch/v850/Kconfig --- a/arch/v850/Kconfig Tue Jul 1 18:44:34 2003 +++ b/arch/v850/Kconfig Tue Jul 1 18:44:34 2003 @@ -265,15 +265,6 @@ source "drivers/ide/Kconfig" -config SCSI - tristate "SCSI device support" - help - If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or - any other SCSI device under Linux, say Y and make sure that you know - the name of your SCSI host adapter (the card inside your computer - that "speaks" the SCSI protocol, also called SCSI controller), - because you will be asked for it. - source "drivers/scsi/Kconfig" endmenu diff -Nru a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig --- a/arch/x86_64/Kconfig Tue Jul 1 18:44:37 2003 +++ b/arch/x86_64/Kconfig Tue Jul 1 18:44:37 2003 @@ -407,32 +407,7 @@ source "drivers/ide/Kconfig" - -menu "SCSI device support" - -config SCSI - tristate "SCSI device support" - ---help--- - If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or - any other SCSI device under Linux, say Y and make sure that you know - the name of your SCSI host adapter (the card inside your computer - that "speaks" the SCSI protocol, also called SCSI controller), - because you will be asked for it. - - You also need to say Y here if you want support for the parallel - port version of the 100 MB IOMEGA ZIP drive. - - This driver is also available as a module ( = code which can be - inserted in and removed from the running kernel whenever you want). - The module will be called scsi_mod. If you want to compile it as - a module, say M here and read and - . However, do not compile this as a - module if your root file system (the one containing the directory /) - is located on a SCSI device. - source "drivers/scsi/Kconfig" - -endmenu source "drivers/md/Kconfig" diff -Nru a/arch/x86_64/defconfig b/arch/x86_64/defconfig --- a/arch/x86_64/defconfig Tue Jul 1 18:44:36 2003 +++ b/arch/x86_64/defconfig Tue Jul 1 18:44:36 2003 @@ -7,6 +7,7 @@ CONFIG_RWSEM_GENERIC_SPINLOCK=y CONFIG_X86_CMPXCHG=y CONFIG_EARLY_PRINTK=y +CONFIG_HPET_TIMER=y CONFIG_GENERIC_ISA_DMA=y # @@ -64,7 +65,8 @@ # # Power management options # -# CONFIG_PM is not set +CONFIG_PM=y +CONFIG_SOFTWARE_SUSPEND=y # # ACPI Support @@ -72,12 +74,15 @@ CONFIG_ACPI=y # CONFIG_ACPI_HT_ONLY is not set CONFIG_ACPI_BOOT=y +CONFIG_ACPI_SLEEP=y +CONFIG_ACPI_SLEEP_PROC_FS=y CONFIG_ACPI_AC=y CONFIG_ACPI_BATTERY=y CONFIG_ACPI_BUTTON=y CONFIG_ACPI_FAN=y CONFIG_ACPI_PROCESSOR=y CONFIG_ACPI_THERMAL=y +# CONFIG_ACPI_ASUS is not set CONFIG_ACPI_TOSHIBA=y CONFIG_ACPI_DEBUG=y CONFIG_ACPI_BUS=y @@ -107,6 +112,11 @@ CONFIG_UID16=y # +# Generic Driver Options +# +# CONFIG_FW_LOADER is not set + +# # Memory Technology Devices (MTD) # # CONFIG_MTD is not set @@ -151,6 +161,7 @@ # CONFIG_IDEDISK_STROKE is not set CONFIG_BLK_DEV_IDECD=y # CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set # CONFIG_IDE_TASK_IOCTL is not set # @@ -198,7 +209,58 @@ # # SCSI device support # -# CONFIG_SCSI is not set +CONFIG_SCSI=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_REPORT_LUNS is not set +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI low-level drivers +# +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_AM53C974 is not set +# CONFIG_SCSI_MEGARAID is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_CPQFCTS is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_SYM53C8XX is not set +# CONFIG_SCSI_PCI2000 is not set +# CONFIG_SCSI_PCI2220I is not set +# CONFIG_SCSI_QLOGIC_ISP is not set +# CONFIG_SCSI_QLOGIC_FC is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set # # Multi-device support (RAID and LVM) @@ -213,6 +275,11 @@ # # Fusion MPT device support # +CONFIG_FUSION=y +CONFIG_FUSION_BOOT=y +CONFIG_FUSION_MAX_SGE=40 +# CONFIG_FUSION_ISENSE is not set +# CONFIG_FUSION_CTL is not set # # IEEE 1394 (FireWire) support (EXPERIMENTAL) @@ -246,7 +313,12 @@ # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set -# CONFIG_IPV6 is not set +CONFIG_IPV6=y +CONFIG_IPV6_PRIVACY=y +# CONFIG_INET6_AH is not set +# CONFIG_INET6_ESP is not set +# CONFIG_INET6_IPCOMP is not set +# CONFIG_IPV6_TUNNEL is not set # CONFIG_XFRM_USER is not set # @@ -307,6 +379,7 @@ CONFIG_AMD8111_ETH=y # CONFIG_ADAPTEC_STARFIRE is not set # CONFIG_B44 is not set +# CONFIG_TC35815 is not set # CONFIG_DGRS is not set # CONFIG_EEPRO100 is not set # CONFIG_E100 is not set @@ -356,6 +429,7 @@ # # Token Ring devices (depends on LLC=y) # +# CONFIG_NET_FC is not set # CONFIG_RCPCI is not set # CONFIG_SHAPER is not set @@ -405,6 +479,7 @@ CONFIG_SERIO_I8042=y # CONFIG_SERIO_SERPORT is not set # CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set # # Input Device Drivers @@ -434,6 +509,7 @@ # CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y +# CONFIG_SERIAL_8250_ACPI is not set # CONFIG_SERIAL_8250_EXTENDED is not set # @@ -467,7 +543,11 @@ # # IPMI # -# CONFIG_IPMI_HANDLER is not set +CONFIG_IPMI_HANDLER=y +CONFIG_IPMI_PANIC_EVENT=y +CONFIG_IPMI_DEVICE_INTERFACE=y +CONFIG_IPMI_KCS=y +CONFIG_IPMI_WATCHDOG=y # # Watchdog Cards @@ -487,10 +567,15 @@ # CONFIG_FTAPE is not set CONFIG_AGP=y CONFIG_AGP_AMD_8151=y -# CONFIG_DRM is not set +CONFIG_DRM=y +# CONFIG_DRM_TDFX is not set +# CONFIG_DRM_GAMMA is not set +# CONFIG_DRM_R128 is not set +CONFIG_DRM_RADEON=y +# CONFIG_DRM_MGA is not set # CONFIG_MWAVE is not set CONFIG_RAW_DRIVER=y -# CONFIG_HANGCHECK_TIMER is not set +CONFIG_HANGCHECK_TIMER=y # # Misc devices @@ -613,7 +698,35 @@ # # Sound # -# CONFIG_SOUND is not set +CONFIG_SOUND=y + +# +# Advanced Linux Sound Architecture +# +# CONFIG_SND is not set + +# +# Open Sound System +# +CONFIG_SOUND_PRIME=y +# CONFIG_SOUND_BT878 is not set +# CONFIG_SOUND_CMPCI is not set +# CONFIG_SOUND_EMU10K1 is not set +# CONFIG_SOUND_FUSION is not set +# CONFIG_SOUND_CS4281 is not set +# CONFIG_SOUND_ES1370 is not set +# CONFIG_SOUND_ES1371 is not set +# CONFIG_SOUND_ESSSOLO1 is not set +# CONFIG_SOUND_MAESTRO is not set +# CONFIG_SOUND_MAESTRO3 is not set +CONFIG_SOUND_ICH=y +# CONFIG_SOUND_RME96XX is not set +# CONFIG_SOUND_SONICVIBES is not set +# CONFIG_SOUND_TRIDENT is not set +# CONFIG_SOUND_MSNDCLAS is not set +# CONFIG_SOUND_MSNDPIN is not set +# CONFIG_SOUND_VIA82CXXX is not set +# CONFIG_SOUND_OSS is not set # # USB support @@ -629,7 +742,8 @@ # # Profiling support # -# CONFIG_PROFILING is not set +CONFIG_PROFILING=y +CONFIG_OPROFILE=y # # Kernel hacking @@ -653,7 +767,21 @@ # # Cryptographic options # -# CONFIG_CRYPTO is not set +CONFIG_CRYPTO=y +# CONFIG_CRYPTO_HMAC is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_MD4 is not set +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_SHA1 is not set +# CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_DES is not set +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_TWOFISH is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_AES is not set +# CONFIG_CRYPTO_DEFLATE is not set +# CONFIG_CRYPTO_TEST is not set # # Library routines diff -Nru a/arch/x86_64/ia32/Makefile b/arch/x86_64/ia32/Makefile --- a/arch/x86_64/ia32/Makefile Tue Jul 1 18:44:34 2003 +++ b/arch/x86_64/ia32/Makefile Tue Jul 1 18:44:34 2003 @@ -10,7 +10,7 @@ # The DSO images are built using a special linker script. $(obj)/vsyscall.so: $(src)/vsyscall.lds $(obj)/vsyscall.o - $(CC) -m32 -nostdlib -shared -s -Wl,-soname=linux-vsyscall.so.1 \ + $(CC) -m32 -nostdlib -shared -s -Wl,-soname=linux-gate.so.1 \ -o $@ -Wl,-T,$^ clean-files += vsyscall.so diff -Nru a/arch/x86_64/ia32/ia32_binfmt.c b/arch/x86_64/ia32/ia32_binfmt.c --- a/arch/x86_64/ia32/ia32_binfmt.c Tue Jul 1 18:44:31 2003 +++ b/arch/x86_64/ia32/ia32_binfmt.c Tue Jul 1 18:44:31 2003 @@ -30,10 +30,12 @@ #define AT_SYSINFO 32 #define AT_SYSINFO_EHDR 33 +#if 0 /* disabled for now because the code has still problems */ #define ARCH_DLINFO do { \ NEW_AUX_ENT(AT_SYSINFO, (u32)(u64)VSYSCALL32_VSYSCALL); \ NEW_AUX_ENT(AT_SYSINFO_EHDR, VSYSCALL32_BASE); \ } while(0) +#endif struct file; struct elf_phdr; diff -Nru a/arch/x86_64/ia32/ia32_ioctl.c b/arch/x86_64/ia32/ia32_ioctl.c --- a/arch/x86_64/ia32/ia32_ioctl.c Tue Jul 1 18:44:35 2003 +++ b/arch/x86_64/ia32/ia32_ioctl.c Tue Jul 1 18:44:35 2003 @@ -552,7 +552,7 @@ set_fs(old_fs); if (err >= 0 && - put_user(((u32)(long)kptr), compat_ptr(arg))) + put_user((u32)(u64)kptr, (u32 *)arg)) err = -EFAULT; return err; diff -Nru a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S --- a/arch/x86_64/ia32/ia32entry.S Tue Jul 1 18:44:34 2003 +++ b/arch/x86_64/ia32/ia32entry.S Tue Jul 1 18:44:34 2003 @@ -47,7 +47,6 @@ ENTRY(ia32_cstar_target) swapgs movl %esp,%r8d - movq %r8,%gs:pda_oldrsp movq %gs:pda_kernelstack,%rsp sti SAVE_ARGS 8,1 @@ -67,7 +66,6 @@ .section __ex_table,"a" .quad 1b,cstar_badarg .previous - movq %r9,R9-ARGOFFSET(%rsp) GET_THREAD_INFO(%r10) bt $TIF_SYSCALL_TRACE,threadinfo_flags(%r10) jc ia32_tracesys diff -Nru a/arch/x86_64/ia32/ptrace32.c b/arch/x86_64/ia32/ptrace32.c --- a/arch/x86_64/ia32/ptrace32.c Tue Jul 1 18:44:33 2003 +++ b/arch/x86_64/ia32/ptrace32.c Tue Jul 1 18:44:33 2003 @@ -210,6 +210,7 @@ return child; } out: + if (child) put_task_struct(child); return NULL; diff -Nru a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c --- a/arch/x86_64/ia32/sys_ia32.c Tue Jul 1 18:44:34 2003 +++ b/arch/x86_64/ia32/sys_ia32.c Tue Jul 1 18:44:34 2003 @@ -946,10 +946,30 @@ struct sysinfo s; int ret; mm_segment_t old_fs = get_fs (); + int bitcount = 0; set_fs (KERNEL_DS); ret = sys_sysinfo(&s); set_fs (old_fs); + + /* Check to see if any memory value is too large for 32-bit and scale + * down if needed + */ + if ((s.totalram >> 32) || (s.totalswap >> 32)) { + while (s.mem_unit < PAGE_SIZE) { + s.mem_unit <<= 1; + bitcount++; + } + s.totalram >>= bitcount; + s.freeram >>= bitcount; + s.sharedram >>= bitcount; + s.bufferram >>= bitcount; + s.totalswap >>= bitcount; + s.freeswap >>= bitcount; + s.totalhigh >>= bitcount; + s.freehigh >>= bitcount; + } + if (verify_area(VERIFY_WRITE, info, sizeof(struct sysinfo32)) || __put_user (s.uptime, &info->uptime) || __put_user (s.loads[0], &info->loads[0]) || diff -Nru a/arch/x86_64/kernel/acpi/boot.c b/arch/x86_64/kernel/acpi/boot.c --- a/arch/x86_64/kernel/acpi/boot.c Tue Jul 1 18:44:33 2003 +++ b/arch/x86_64/kernel/acpi/boot.c Tue Jul 1 18:44:33 2003 @@ -100,7 +100,7 @@ if (madt->lapic_address) acpi_lapic_addr = (u64) madt->lapic_address; - printk(KERN_INFO PREFIX "Local APIC address 0x%08x\n", + printk(KERN_INFO PREFIX "Local APIC address 0x%016x\n", madt->lapic_address); return 0; diff -Nru a/arch/x86_64/kernel/acpi/wakeup.S b/arch/x86_64/kernel/acpi/wakeup.S --- a/arch/x86_64/kernel/acpi/wakeup.S Tue Jul 1 18:44:36 2003 +++ b/arch/x86_64/kernel/acpi/wakeup.S Tue Jul 1 18:44:36 2003 @@ -209,7 +209,7 @@ movw $0x0e00 + '!', %ds:(0xb801a) movq saved_eip, %rax - jmp %rax + jmp *%rax .code32 diff -Nru a/arch/x86_64/kernel/i8259.c b/arch/x86_64/kernel/i8259.c --- a/arch/x86_64/kernel/i8259.c Tue Jul 1 18:44:32 2003 +++ b/arch/x86_64/kernel/i8259.c Tue Jul 1 18:44:32 2003 @@ -26,9 +26,6 @@ #include -/* When we have things working, we can switch to always use - IOAPIC. --pavel */ - /* * Common place to define all x86 IRQ vectors * diff -Nru a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c --- a/arch/x86_64/kernel/io_apic.c Tue Jul 1 18:44:35 2003 +++ b/arch/x86_64/kernel/io_apic.c Tue Jul 1 18:44:35 2003 @@ -712,9 +712,9 @@ void __init print_IO_APIC(void) { int apic, i; - struct IO_APIC_reg_00 reg_00; - struct IO_APIC_reg_01 reg_01; - struct IO_APIC_reg_02 reg_02; + union IO_APIC_reg_00 reg_00; + union IO_APIC_reg_01 reg_01; + union IO_APIC_reg_02 reg_02; unsigned long flags; printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries); @@ -731,49 +731,49 @@ for (apic = 0; apic < nr_ioapics; apic++) { spin_lock_irqsave(&ioapic_lock, flags); - *(int *)®_00 = io_apic_read(apic, 0); - *(int *)®_01 = io_apic_read(apic, 1); - if (reg_01.version >= 0x10) - *(int *)®_02 = io_apic_read(apic, 2); + reg_00.raw = io_apic_read(apic, 0); + reg_01.raw = io_apic_read(apic, 1); + if (reg_01.bits.version >= 0x10) + reg_02.raw = io_apic_read(apic, 2); spin_unlock_irqrestore(&ioapic_lock, flags); printk("\n"); printk(KERN_DEBUG "IO APIC #%d......\n", mp_ioapics[apic].mpc_apicid); - printk(KERN_DEBUG ".... register #00: %08X\n", *(int *)®_00); - printk(KERN_DEBUG "....... : physical APIC id: %02X\n", reg_00.ID); - if (reg_00.__reserved_1 || reg_00.__reserved_2) + printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw); + printk(KERN_DEBUG "....... : physical APIC id: %02X\n", reg_00.bits.ID); + if (reg_00.bits.__reserved_1 || reg_00.bits.__reserved_2) UNEXPECTED_IO_APIC(); printk(KERN_DEBUG ".... register #01: %08X\n", *(int *)®_01); - printk(KERN_DEBUG "....... : max redirection entries: %04X\n", reg_01.entries); - if ( (reg_01.entries != 0x0f) && /* older (Neptune) boards */ - (reg_01.entries != 0x17) && /* typical ISA+PCI boards */ - (reg_01.entries != 0x1b) && /* Compaq Proliant boards */ - (reg_01.entries != 0x1f) && /* dual Xeon boards */ - (reg_01.entries != 0x22) && /* bigger Xeon boards */ - (reg_01.entries != 0x2E) && - (reg_01.entries != 0x3F) && - (reg_01.entries != 0x03) + printk(KERN_DEBUG "....... : max redirection entries: %04X\n", reg_01.bits.entries); + if ( (reg_01.bits.entries != 0x0f) && /* older (Neptune) boards */ + (reg_01.bits.entries != 0x17) && /* typical ISA+PCI boards */ + (reg_01.bits.entries != 0x1b) && /* Compaq Proliant boards */ + (reg_01.bits.entries != 0x1f) && /* dual Xeon boards */ + (reg_01.bits.entries != 0x22) && /* bigger Xeon boards */ + (reg_01.bits.entries != 0x2E) && + (reg_01.bits.entries != 0x3F) && + (reg_01.bits.entries != 0x03) ) UNEXPECTED_IO_APIC(); - printk(KERN_DEBUG "....... : PRQ implemented: %X\n", reg_01.PRQ); - printk(KERN_DEBUG "....... : IO APIC version: %04X\n", reg_01.version); - if ( (reg_01.version != 0x01) && /* 82489DX IO-APICs */ - (reg_01.version != 0x02) && /* 82801BA IO-APICs (ICH2) */ - (reg_01.version != 0x10) && /* oldest IO-APICs */ - (reg_01.version != 0x11) && /* Pentium/Pro IO-APICs */ - (reg_01.version != 0x13) && /* Xeon IO-APICs */ - (reg_01.version != 0x20) /* Intel P64H (82806 AA) */ + printk(KERN_DEBUG "....... : PRQ implemented: %X\n", reg_01.bits.PRQ); + printk(KERN_DEBUG "....... : IO APIC version: %04X\n", reg_01.bits.version); + if ( (reg_01.bits.version != 0x01) && /* 82489DX IO-APICs */ + (reg_01.bits.version != 0x02) && /* 82801BA IO-APICs (ICH2) */ + (reg_01.bits.version != 0x10) && /* oldest IO-APICs */ + (reg_01.bits.version != 0x11) && /* Pentium/Pro IO-APICs */ + (reg_01.bits.version != 0x13) && /* Xeon IO-APICs */ + (reg_01.bits.version != 0x20) /* Intel P64H (82806 AA) */ ) UNEXPECTED_IO_APIC(); - if (reg_01.__reserved_1 || reg_01.__reserved_2) + if (reg_01.bits.__reserved_1 || reg_01.bits.__reserved_2) UNEXPECTED_IO_APIC(); - if (reg_01.version >= 0x10) { - printk(KERN_DEBUG ".... register #02: %08X\n", *(int *)®_02); - printk(KERN_DEBUG "....... : arbitration: %02X\n", reg_02.arbitration); - if (reg_02.__reserved_1 || reg_02.__reserved_2) + if (reg_01.bits.version >= 0x10) { + printk(KERN_DEBUG ".... register #02: %08X\n", reg_02.raw); + printk(KERN_DEBUG "....... : arbitration: %02X\n", reg_02.bits.arbitration); + if (reg_02.bits.__reserved_1 || reg_02.bits.__reserved_2) UNEXPECTED_IO_APIC(); } @@ -782,7 +782,7 @@ printk(KERN_DEBUG " NR Log Phy Mask Trig IRR Pol" " Stat Dest Deli Vect: \n"); - for (i = 0; i <= reg_01.entries; i++) { + for (i = 0; i <= reg_01.bits.entries; i++) { struct IO_APIC_route_entry entry; spin_lock_irqsave(&ioapic_lock, flags); @@ -963,7 +963,7 @@ static void __init enable_IO_APIC(void) { - struct IO_APIC_reg_01 reg_01; + union IO_APIC_reg_01 reg_01; int i; unsigned long flags; @@ -980,9 +980,9 @@ */ for (i = 0; i < nr_ioapics; i++) { spin_lock_irqsave(&ioapic_lock, flags); - *(int *)®_01 = io_apic_read(i, 1); + reg_01.raw = io_apic_read(i, 1); spin_unlock_irqrestore(&ioapic_lock, flags); - nr_ioapic_registers[i] = reg_01.entries+1; + nr_ioapic_registers[i] = reg_01.bits.entries+1; } /* @@ -1013,7 +1013,7 @@ static void __init setup_ioapic_ids_from_mpc (void) { - struct IO_APIC_reg_00 reg_00; + union IO_APIC_reg_00 reg_00; unsigned long phys_id_present_map = phys_cpu_present_map; int apic; int i; @@ -1029,7 +1029,7 @@ /* Read the register 0 value */ spin_lock_irqsave(&ioapic_lock, flags); - *(int *)®_00 = io_apic_read(apic, 0); + reg_00.raw = io_apic_read(apic, 0); spin_unlock_irqrestore(&ioapic_lock, flags); old_id = mp_ioapics[apic].mpc_apicid; @@ -1038,8 +1038,8 @@ printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n", apic, mp_ioapics[apic].mpc_apicid); printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n", - reg_00.ID); - mp_ioapics[apic].mpc_apicid = reg_00.ID; + reg_00.bits.ID); + mp_ioapics[apic].mpc_apicid = reg_00.bits.ID; } /* @@ -1083,18 +1083,18 @@ printk(KERN_INFO "...changing IO-APIC physical APIC ID to %d ...", mp_ioapics[apic].mpc_apicid); - reg_00.ID = mp_ioapics[apic].mpc_apicid; + reg_00.bits.ID = mp_ioapics[apic].mpc_apicid; spin_lock_irqsave(&ioapic_lock, flags); - io_apic_write(apic, 0, *(int *)®_00); + io_apic_write(apic, 0, reg_00.raw); spin_unlock_irqrestore(&ioapic_lock, flags); /* * Sanity check */ spin_lock_irqsave(&ioapic_lock, flags); - *(int *)®_00 = io_apic_read(apic, 0); + reg_00.raw = io_apic_read(apic, 0); spin_unlock_irqrestore(&ioapic_lock, flags); - if (reg_00.ID != mp_ioapics[apic].mpc_apicid) + if (reg_00.bits.ID != mp_ioapics[apic].mpc_apicid) panic("could not set ID!\n"); else printk(" ok.\n"); @@ -1637,7 +1637,7 @@ int __init io_apic_get_unique_id (int ioapic, int apic_id) { - struct IO_APIC_reg_00 reg_00; + union IO_APIC_reg_00 reg_00; static unsigned long apic_id_map = 0; unsigned long flags; int i = 0; @@ -1655,13 +1655,13 @@ apic_id_map = phys_cpu_present_map; spin_lock_irqsave(&ioapic_lock, flags); - *(int *)®_00 = io_apic_read(ioapic, 0); + reg_00.raw = io_apic_read(ioapic, 0); spin_unlock_irqrestore(&ioapic_lock, flags); if (apic_id >= IO_APIC_MAX_ID) { printk(KERN_WARNING "IOAPIC[%d]: Invalid apic_id %d, trying " - "%d\n", ioapic, apic_id, reg_00.ID); - apic_id = reg_00.ID; + "%d\n", ioapic, apic_id, reg_00.bits.ID); + apic_id = reg_00.bits.ID; } /* @@ -1686,16 +1686,16 @@ apic_id_map |= (1 << apic_id); - if (reg_00.ID != apic_id) { - reg_00.ID = apic_id; + if (reg_00.bits.ID != apic_id) { + reg_00.bits.ID = apic_id; spin_lock_irqsave(&ioapic_lock, flags); - io_apic_write(ioapic, 0, *(int *)®_00); - *(int *)®_00 = io_apic_read(ioapic, 0); + io_apic_write(ioapic, 0, reg_00.raw); + reg_00.raw = io_apic_read(ioapic, 0); spin_unlock_irqrestore(&ioapic_lock, flags); /* Sanity check */ - if (reg_00.ID != apic_id) + if (reg_00.bits.ID != apic_id) panic("IOAPIC[%d]: Unable change apic_id!\n", ioapic); } @@ -1707,27 +1707,27 @@ int __init io_apic_get_version (int ioapic) { - struct IO_APIC_reg_01 reg_01; + union IO_APIC_reg_01 reg_01; unsigned long flags; spin_lock_irqsave(&ioapic_lock, flags); - *(int *)®_01 = io_apic_read(ioapic, 1); + reg_01.raw = io_apic_read(ioapic, 1); spin_unlock_irqrestore(&ioapic_lock, flags); - return reg_01.version; + return reg_01.bits.version; } int __init io_apic_get_redir_entries (int ioapic) { - struct IO_APIC_reg_01 reg_01; + union IO_APIC_reg_01 reg_01; unsigned long flags; spin_lock_irqsave(&ioapic_lock, flags); - *(int *)®_01 = io_apic_read(ioapic, 1); + reg_01.raw = io_apic_read(ioapic, 1); spin_unlock_irqrestore(&ioapic_lock, flags); - return reg_01.entries; + return reg_01.bits.entries; } diff -Nru a/arch/x86_64/kernel/module.c b/arch/x86_64/kernel/module.c --- a/arch/x86_64/kernel/module.c Tue Jul 1 18:44:37 2003 +++ b/arch/x86_64/kernel/module.c Tue Jul 1 18:44:37 2003 @@ -31,9 +31,6 @@ #define DEBUGP(fmt...) -/* TODO this should be in vmlist, but we must fix get_vm_area first to - handle out of bounds entries properly. - Also need to fix /proc/kcore, /dev/kmem */ static struct vm_struct *mod_vmlist; void module_free(struct module *mod, void *module_region) diff -Nru a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c --- a/arch/x86_64/kernel/nmi.c Tue Jul 1 18:44:34 2003 +++ b/arch/x86_64/kernel/nmi.c Tue Jul 1 18:44:34 2003 @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -32,9 +33,15 @@ #include #include -extern void default_do_nmi(struct pt_regs *); +/* nmi_active: + * +1: the lapic NMI watchdog is active, but can be disabled + * 0: the lapic NMI watchdog has not been set up, and cannot + * be enabled + * -1: the lapic NMI watchdog is disabled, but can be enabled + */ +static int nmi_active; -unsigned int nmi_watchdog = NMI_LOCAL_APIC; +unsigned int nmi_watchdog = NMI_IO_APIC; static unsigned int nmi_hz = HZ; unsigned int nmi_perfctr_msr; /* the MSR to reset in NMI handler */ int nmi_watchdog_disabled; @@ -90,6 +97,7 @@ printk("CPU#%d: NMI appears to be stuck (%d)!\n", cpu, cpu_pda[cpu].__nmi_count); + nmi_active = 0; return -1; } } @@ -117,14 +125,6 @@ __setup("nmi_watchdog=", setup_nmi_watchdog); -/* nmi_active: - * +1: the lapic NMI watchdog is active, but can be disabled - * 0: the lapic NMI watchdog has not been set up, and cannot - * be enabled - * -1: the lapic NMI watchdog is disabled, but can be enabled - */ -static int nmi_active; - void disable_lapic_nmi_watchdog(void) { if (nmi_active <= 0) @@ -149,21 +149,45 @@ } } + +void disable_timer_nmi_watchdog(void) +{ + if ((nmi_watchdog != NMI_IO_APIC) || (nmi_active <= 0)) + return; + + disable_irq(0); + unset_nmi_callback(); + nmi_active = -1; + nmi_watchdog = NMI_NONE; +} + +void enable_timer_nmi_watchdog(void) +{ + if (nmi_active < 0) { + nmi_watchdog = NMI_IO_APIC; + touch_nmi_watchdog(); + nmi_active = 1; + enable_irq(0); + } +} + #ifdef CONFIG_PM #include +static int nmi_pm_active; /* nmi_active before suspend */ + static int lapic_nmi_suspend(struct sys_device *dev, u32 state) { + nmi_pm_active = nmi_active; disable_lapic_nmi_watchdog(); return 0; } static int lapic_nmi_resume(struct sys_device *dev) { -#if 0 + if (nmi_pm_active > 0) enable_lapic_nmi_watchdog(); -#endif return 0; } @@ -235,6 +259,8 @@ case X86_VENDOR_AMD: if (boot_cpu_data.x86 < 6) return; + if (strstr(boot_cpu_data.x86_model_id, "Screwdriver")) + return; setup_k7_watchdog(); break; default: @@ -348,3 +374,5 @@ EXPORT_SYMBOL(nmi_watchdog); EXPORT_SYMBOL(disable_lapic_nmi_watchdog); EXPORT_SYMBOL(enable_lapic_nmi_watchdog); +EXPORT_SYMBOL(disable_timer_nmi_watchdog); +EXPORT_SYMBOL(enable_timer_nmi_watchdog); diff -Nru a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c --- a/arch/x86_64/kernel/pci-gart.c Tue Jul 1 18:44:34 2003 +++ b/arch/x86_64/kernel/pci-gart.c Tue Jul 1 18:44:34 2003 @@ -236,7 +236,7 @@ static int dump; if (dump || !iommu_leak_tab) return; dump = 1; - show_stack(NULL); + show_stack(NULL,NULL); /* Very crude. dump some from the end of the table too */ printk("Dumping %d pages from end of IOMMU:\n", iommu_leak_pages); for (i = 0; i < iommu_leak_pages; i+=2) { diff -Nru a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c --- a/arch/x86_64/kernel/setup.c Tue Jul 1 18:44:31 2003 +++ b/arch/x86_64/kernel/setup.c Tue Jul 1 18:44:31 2003 @@ -93,11 +93,11 @@ struct resource standard_io_resources[] = { { "dma1", 0x00, 0x1f, IORESOURCE_BUSY }, - { "pic1", 0x20, 0x3f, IORESOURCE_BUSY }, + { "pic1", 0x20, 0x21, IORESOURCE_BUSY }, { "timer", 0x40, 0x5f, IORESOURCE_BUSY }, { "keyboard", 0x60, 0x6f, IORESOURCE_BUSY }, { "dma page reg", 0x80, 0x8f, IORESOURCE_BUSY }, - { "pic2", 0xa0, 0xbf, IORESOURCE_BUSY }, + { "pic2", 0xa0, 0xa1, IORESOURCE_BUSY }, { "dma2", 0xc0, 0xdf, IORESOURCE_BUSY }, { "fpu", 0xf0, 0xff, IORESOURCE_BUSY } }; diff -Nru a/arch/x86_64/kernel/suspend.c b/arch/x86_64/kernel/suspend.c --- a/arch/x86_64/kernel/suspend.c Tue Jul 1 18:44:35 2003 +++ b/arch/x86_64/kernel/suspend.c Tue Jul 1 18:44:35 2003 @@ -121,11 +121,12 @@ struct tss_struct * t = init_tss + cpu; set_tss_desc(cpu,t); /* This just modifies memory; should not be neccessary. But... This is neccessary, because 386 hardware has concept of busy TSS or some similar stupidity. */ - ((struct n_desc_struct *) &cpu_gdt_table[cpu][GDT_ENTRY_TSS])->b &= 0xfffffdff; + + cpu_gdt_table[cpu][GDT_ENTRY_TSS].type = 9; syscall_init(); /* This sets MSR_*STAR and related */ load_TR_desc(); /* This does ltr */ - load_LDT(¤t->mm->context); /* This does lldt */ + load_LDT(¤t->active_mm->context); /* This does lldt */ /* * Now maybe reload the debug registers diff -Nru a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c --- a/arch/x86_64/kernel/time.c Tue Jul 1 18:44:36 2003 +++ b/arch/x86_64/kernel/time.c Tue Jul 1 18:44:36 2003 @@ -47,6 +47,7 @@ unsigned long hpet_tick; /* HPET clocks / interrupt */ unsigned long vxtime_hz = 1193182; int report_lost_ticks; /* command line option */ +unsigned long long monotonic_base; struct vxtime_data __vxtime __section_vxtime; /* for vsyscalls */ @@ -137,6 +138,18 @@ tv->tv_sec--; } + wall_to_monotonic.tv_sec += xtime.tv_sec - tv->tv_sec; + wall_to_monotonic.tv_nsec += xtime.tv_nsec - tv->tv_nsec; + + if (wall_to_monotonic.tv_nsec > NSEC_PER_SEC) { + wall_to_monotonic.tv_nsec -= NSEC_PER_SEC; + wall_to_monotonic.tv_sec++; + } + if (wall_to_monotonic.tv_nsec < 0) { + wall_to_monotonic.tv_nsec += NSEC_PER_SEC; + wall_to_monotonic.tv_sec--; + } + xtime.tv_sec = tv->tv_sec; xtime.tv_nsec = tv->tv_nsec; @@ -219,6 +232,47 @@ spin_unlock(&rtc_lock); } + +/* monotonic_clock(): returns # of nanoseconds passed since time_init() + * Note: This function is required to return accurate + * time even in the absence of multiple timer ticks. + */ +unsigned long long monotonic_clock(void) +{ + unsigned long seq; + u32 last_offset, this_offset, offset; + unsigned long long base; + + if (vxtime.mode == VXTIME_HPET) { + do { + seq = read_seqbegin(&xtime_lock); + + last_offset = vxtime.last; + base = monotonic_base; + this_offset = hpet_readl(HPET_T0_CMP) - hpet_tick; + + } while (read_seqretry(&xtime_lock, seq)); + offset = (this_offset - last_offset); + offset *=(NSEC_PER_SEC/HZ)/hpet_tick; + return base + offset; + }else{ + do { + seq = read_seqbegin(&xtime_lock); + + last_offset = vxtime.last_tsc; + base = monotonic_base; + } while (read_seqretry(&xtime_lock, seq)); + sync_core(); + rdtscll(this_offset); + offset = (this_offset - last_offset)*1000/cpu_khz; + return base + offset; + } + + +} +EXPORT_SYMBOL(monotonic_clock); + + static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { static unsigned long rtc_update = 0; @@ -253,6 +307,9 @@ lost = (offset - vxtime.last) / hpet_tick - 1; } + monotonic_base += + (offset - vxtime.last)*(NSEC_PER_SEC/HZ) / hpet_tick; + vxtime.last = offset; } else { offset = (((tsc - vxtime.last_tsc) * @@ -266,6 +323,8 @@ offset %= (USEC_PER_SEC / HZ); } + monotonic_base += (tsc - vxtime.last_tsc)*1000000/cpu_khz ; + vxtime.last_tsc = tsc - vxtime.quot * delay / vxtime.tsc_quot; if ((((tsc - vxtime.last_tsc) * @@ -543,6 +602,9 @@ xtime.tv_sec = get_cmos_time(); xtime.tv_nsec = 0; + + wall_to_monotonic.tv_sec = -xtime.tv_sec; + wall_to_monotonic.tv_nsec = -xtime.tv_nsec; if (!hpet_init()) { vxtime_hz = (1000000000000000L + hpet_period / 2) / diff -Nru a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c --- a/arch/x86_64/kernel/traps.c Tue Jul 1 18:44:31 2003 +++ b/arch/x86_64/kernel/traps.c Tue Jul 1 18:44:31 2003 @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -206,7 +207,7 @@ show_trace((unsigned long *)rsp); } -void show_stack(unsigned long * rsp) +void show_stack(struct task_struct *tsk, unsigned long * rsp) { unsigned long *stack; int i; @@ -214,7 +215,7 @@ unsigned long *irqstack_end = (unsigned long *) (cpu_pda[cpu].irqstackptr); unsigned long *irqstack = (unsigned long *) (cpu_pda[cpu].irqstackptr - IRQSTACKSIZE); - // debugging aid: "show_stack(NULL);" prints the + // debugging aid: "show_stack(NULL, NULL);" prints the // back trace for this cpu. if(rsp==NULL) @@ -269,7 +270,7 @@ if (in_kernel) { printk("Stack: "); - show_stack((unsigned long*)rsp); + show_stack(NULL, (unsigned long*)rsp); printk("\nCode: "); if(regs->rip < PAGE_OFFSET) @@ -831,3 +832,4 @@ */ cpu_init(); } + diff -Nru a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c --- a/arch/x86_64/kernel/x8664_ksyms.c Tue Jul 1 18:44:32 2003 +++ b/arch/x86_64/kernel/x8664_ksyms.c Tue Jul 1 18:44:32 2003 @@ -30,6 +30,7 @@ #include #include #include +#include extern spinlock_t rtc_lock; @@ -212,3 +213,6 @@ #endif EXPORT_SYMBOL(clear_page); + +EXPORT_SYMBOL(flush_tlb_page); +EXPORT_SYMBOL_GPL(flush_tlb_all); diff -Nru a/arch/x86_64/oprofile/Makefile b/arch/x86_64/oprofile/Makefile --- a/arch/x86_64/oprofile/Makefile Tue Jul 1 18:44:33 2003 +++ b/arch/x86_64/oprofile/Makefile Tue Jul 1 18:44:33 2003 @@ -15,7 +15,7 @@ oprofile-objs := $(DRIVER_OBJS) init.o oprofile-$(CONFIG_X86_LOCAL_APIC) += nmi_int.o op_model_athlon.o - +oprofile-$(CONFIG_X86_IO_APIC) += nmi_timer_int.o INCL := $(obj)/op_counter.h $(obj)/op_x86_model.h $(obj)/nmi_int.c: ${INCL} @@ -24,9 +24,11 @@ @ln -sf ../../i386/oprofile/op_model_athlon.c $(obj)/op_model_athlon.c $(obj)/init.c: ${INCL} @ln -sf ../../i386/oprofile/init.c $(obj)/init.c +$(obj)/nmi_timer_int.c: ${INCL} + @ln -sf ../../i386/oprofile/nmi_timer_int.c $(obj)/nmi_timer_int.c $(obj)/op_counter.h: @ln -sf ../../i386/oprofile/op_counter.h $(obj)/op_counter.h $(obj)/op_x86_model.h: @ln -sf ../../i386/oprofile/op_x86_model.h $(obj)/op_x86_model.h clean-files += op_x86_model.h op_counter.h init.c \ - op_model_athlon.c nmi_int.c + op_model_athlon.c nmi_int.c nmi_timer_int.c diff -Nru a/drivers/Makefile b/drivers/Makefile --- a/drivers/Makefile Tue Jul 1 18:44:37 2003 +++ b/drivers/Makefile Tue Jul 1 18:44:37 2003 @@ -33,7 +33,6 @@ obj-$(CONFIG_ZORRO) += zorro/ obj-$(CONFIG_PPC_PMAC) += macintosh/ obj-$(CONFIG_MAC) += macintosh/ -obj-$(CONFIG_SGI) += sgi/ obj-$(CONFIG_PARIDE) += block/paride/ obj-$(CONFIG_TC) += tc/ obj-$(CONFIG_USB) += usb/ diff -Nru a/drivers/acpi/osl.c b/drivers/acpi/osl.c --- a/drivers/acpi/osl.c Tue Jul 1 18:44:37 2003 +++ b/drivers/acpi/osl.c Tue Jul 1 18:44:37 2003 @@ -466,7 +466,8 @@ } result = raw_pci_ops->read(pci_id->segment, pci_id->bus, - pci_id->device, pci_id->function, reg, size, value); + PCI_DEVFN(pci_id->device, pci_id->function), + reg, size, value); return (result ? AE_ERROR : AE_OK); } @@ -491,7 +492,8 @@ } result = raw_pci_ops->write(pci_id->segment, pci_id->bus, - pci_id->device, pci_id->function, reg, size, value); + PCI_DEVFN(pci_id->device, pci_id->function), + reg, size, value); return (result ? AE_ERROR : AE_OK); } @@ -933,8 +935,8 @@ } /* Assumes no unreadable holes inbetween */ -BOOLEAN -acpi_os_readable(void *ptr, u32 len) +u8 +acpi_os_readable(void *ptr, acpi_size len) { #if defined(__i386__) || defined(__x86_64__) char tmp; @@ -943,8 +945,8 @@ return 1; } -BOOLEAN -acpi_os_writable(void *ptr, u32 len) +u8 +acpi_os_writable(void *ptr, acpi_size len) { /* could do dummy write (racy) or a kernel page table lookup. The later may be difficult at early boot when kmap doesn't work yet. */ diff -Nru a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c --- a/drivers/acpi/pci_root.c Tue Jul 1 18:44:33 2003 +++ b/drivers/acpi/pci_root.c Tue Jul 1 18:44:33 2003 @@ -246,8 +246,6 @@ switch (status) { case AE_OK: root->id.segment = (u16) value; - printk("_SEG exists! Unsupported. Abort.\n"); - BUG(); break; case AE_NOT_FOUND: ACPI_DEBUG_PRINT((ACPI_DB_INFO, @@ -309,7 +307,7 @@ * PCI namespace does not get created until this call is made (and * thus the root bridge's pci_dev does not exist). */ - root->bus = pcibios_scan_root(root->id.bus); + root->bus = pci_acpi_scan_root(device, root->id.segment, root->id.bus); if (!root->bus) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Bus %02x:%02x not present in PCI namespace\n", diff -Nru a/drivers/atm/atmtcp.c b/drivers/atm/atmtcp.c --- a/drivers/atm/atmtcp.c Tue Jul 1 18:44:36 2003 +++ b/drivers/atm/atmtcp.c Tue Jul 1 18:44:36 2003 @@ -153,9 +153,10 @@ static int atmtcp_v_ioctl(struct atm_dev *dev,unsigned int cmd,void *arg) { - unsigned long flags; struct atm_cirange ci; struct atm_vcc *vcc; + struct hlist_node *node; + struct sock *s; if (cmd != ATM_SETCIRANGE) return -ENOIOCTLCMD; if (copy_from_user(&ci,(void *) arg,sizeof(ci))) return -EFAULT; @@ -163,14 +164,18 @@ if (ci.vci_bits == ATM_CI_MAX) ci.vci_bits = MAX_VCI_BITS; if (ci.vpi_bits > MAX_VPI_BITS || ci.vpi_bits < 0 || ci.vci_bits > MAX_VCI_BITS || ci.vci_bits < 0) return -EINVAL; - spin_lock_irqsave(&dev->lock, flags); - for (vcc = dev->vccs; vcc; vcc = vcc->next) + read_lock(&vcc_sklist_lock); + sk_for_each(s, node, &vcc_sklist) { + vcc = atm_sk(s); + if (vcc->dev != dev) + continue; if ((vcc->vpi >> ci.vpi_bits) || (vcc->vci >> ci.vci_bits)) { - spin_unlock_irqrestore(&dev->lock, flags); + read_unlock(&vcc_sklist_lock); return -EBUSY; } - spin_unlock_irqrestore(&dev->lock, flags); + } + read_unlock(&vcc_sklist_lock); dev->ci_range = ci; return 0; } @@ -233,9 +238,10 @@ static void atmtcp_c_close(struct atm_vcc *vcc) { - unsigned long flags; struct atm_dev *atmtcp_dev; struct atmtcp_dev_data *dev_data; + struct sock *s; + struct hlist_node *node; struct atm_vcc *walk; atmtcp_dev = (struct atm_dev *) vcc->dev_data; @@ -246,19 +252,24 @@ kfree(dev_data); shutdown_atm_dev(atmtcp_dev); vcc->dev_data = NULL; - spin_lock_irqsave(&atmtcp_dev->lock, flags); - for (walk = atmtcp_dev->vccs; walk; walk = walk->next) + read_lock(&vcc_sklist_lock); + sk_for_each(s, node, &vcc_sklist) { + walk = atm_sk(s); + if (walk->dev != atmtcp_dev) + continue; wake_up(&walk->sleep); - spin_unlock_irqrestore(&atmtcp_dev->lock, flags); + } + read_unlock(&vcc_sklist_lock); } static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb) { - unsigned long flags; struct atm_dev *dev; struct atmtcp_hdr *hdr; - struct atm_vcc *out_vcc; + struct sock *s; + struct hlist_node *node; + struct atm_vcc *out_vcc = NULL; struct sk_buff *new_skb; int result = 0; @@ -270,13 +281,17 @@ (struct atmtcp_control *) skb->data); goto done; } - spin_lock_irqsave(&dev->lock, flags); - for (out_vcc = dev->vccs; out_vcc; out_vcc = out_vcc->next) + read_lock(&vcc_sklist_lock); + sk_for_each(s, node, &vcc_sklist) { + out_vcc = atm_sk(s); + if (out_vcc->dev != dev) + continue; if (out_vcc->vpi == ntohs(hdr->vpi) && out_vcc->vci == ntohs(hdr->vci) && out_vcc->qos.rxtp.traffic_class != ATM_NONE) break; - spin_unlock_irqrestore(&dev->lock, flags); + } + read_unlock(&vcc_sklist_lock); if (!out_vcc) { atomic_inc(&vcc->stats->tx_err); goto done; @@ -366,7 +381,7 @@ if (itf != -1) dev = atm_dev_lookup(itf); if (dev) { if (dev->ops != &atmtcp_v_dev_ops) { - atm_dev_release(dev); + atm_dev_put(dev); return -EMEDIUMTYPE; } if (PRIV(dev)->vcc) return -EBUSY; @@ -378,7 +393,8 @@ if (error) return error; } PRIV(dev)->vcc = vcc; - bind_vcc(vcc,&atmtcp_control_dev); + vcc->dev = &atmtcp_control_dev; + vcc_insert_socket(vcc->sk); set_bit(ATM_VF_META,&vcc->flags); set_bit(ATM_VF_READY,&vcc->flags); vcc->dev_data = dev; @@ -402,7 +418,7 @@ dev = atm_dev_lookup(itf); if (!dev) return -ENODEV; if (dev->ops != &atmtcp_v_dev_ops) { - atm_dev_release(dev); + atm_dev_put(dev); return -EMEDIUMTYPE; } dev_data = PRIV(dev); @@ -410,7 +426,7 @@ dev_data->persist = 0; if (PRIV(dev)->vcc) return 0; kfree(dev_data); - atm_dev_release(dev); + atm_dev_put(dev); shutdown_atm_dev(dev); return 0; } diff -Nru a/drivers/atm/eni.c b/drivers/atm/eni.c --- a/drivers/atm/eni.c Tue Jul 1 18:44:33 2003 +++ b/drivers/atm/eni.c Tue Jul 1 18:44:33 2003 @@ -1887,10 +1887,11 @@ static int get_ci(struct atm_vcc *vcc,short *vpi,int *vci) { - unsigned long flags; + struct sock *s; + struct hlist_node *node; struct atm_vcc *walk; - spin_lock_irqsave(&vcc->dev->lock, flags); + read_lock(&vcc_sklist_lock); if (*vpi == ATM_VPI_ANY) *vpi = 0; if (*vci == ATM_VCI_ANY) { for (*vci = ATM_NOT_RSV_VCI; *vci < NR_VCI; (*vci)++) { @@ -1898,40 +1899,48 @@ ENI_DEV(vcc->dev)->rx_map[*vci]) continue; if (vcc->qos.txtp.traffic_class != ATM_NONE) { - for (walk = vcc->dev->vccs; walk; - walk = walk->next) + sk_for_each(s, node, &vcc_sklist) { + walk = atm_sk(s); + if (walk->dev != vcc->dev) + continue; if (test_bit(ATM_VF_ADDR,&walk->flags) && walk->vci == *vci && walk->qos.txtp.traffic_class != ATM_NONE) break; - if (walk) continue; + } + if (node) + continue; } break; } - spin_unlock_irqrestore(&vcc->dev->lock, flags); + read_unlock(&vcc_sklist_lock); return *vci == NR_VCI ? -EADDRINUSE : 0; } if (*vci == ATM_VCI_UNSPEC) { - spin_unlock_irqrestore(&vcc->dev->lock, flags); + read_unlock(&vcc_sklist_lock); return 0; } if (vcc->qos.rxtp.traffic_class != ATM_NONE && ENI_DEV(vcc->dev)->rx_map[*vci]) { - spin_unlock_irqrestore(&vcc->dev->lock, flags); + read_unlock(&vcc_sklist_lock); return -EADDRINUSE; } if (vcc->qos.txtp.traffic_class == ATM_NONE) { - spin_unlock_irqrestore(&vcc->dev->lock, flags); + read_unlock(&vcc_sklist_lock); return 0; } - for (walk = vcc->dev->vccs; walk; walk = walk->next) + sk_for_each(s, node, &vcc_sklist) { + walk = atm_sk(s); + if (walk->dev != vcc->dev) + continue; if (test_bit(ATM_VF_ADDR,&walk->flags) && walk->vci == *vci && walk->qos.txtp.traffic_class != ATM_NONE) { - spin_unlock_irqrestore(&vcc->dev->lock, flags); + read_unlock(&vcc_sklist_lock); return -EADDRINUSE; } - spin_unlock_irqrestore(&vcc->dev->lock, flags); + } + read_unlock(&vcc_sklist_lock); return 0; } @@ -2139,7 +2148,8 @@ static int eni_proc_read(struct atm_dev *dev,loff_t *pos,char *page) { - unsigned long flags; + struct hlist_node *node; + struct sock *s; static const char *signal[] = { "LOST","unknown","okay" }; struct eni_dev *eni_dev = ENI_DEV(dev); struct atm_vcc *vcc; @@ -2212,11 +2222,15 @@ return sprintf(page,"%10sbacklog %u packets\n","", skb_queue_len(&tx->backlog)); } - spin_lock_irqsave(&dev->lock, flags); - for (vcc = dev->vccs; vcc; vcc = vcc->next) { - struct eni_vcc *eni_vcc = ENI_VCC(vcc); + read_lock(&vcc_sklist_lock); + sk_for_each(s, node, &vcc_sklist) { + struct eni_vcc *eni_vcc; int length; + vcc = atm_sk(s); + if (vcc->dev != dev) + continue; + eni_vcc = ENI_VCC(vcc); if (--left) continue; length = sprintf(page,"vcc %4d: ",vcc->vci); if (eni_vcc->rx) { @@ -2231,10 +2245,10 @@ length += sprintf(page+length,"tx[%d], txing %d bytes", eni_vcc->tx->index,eni_vcc->txing); page[length] = '\n'; - spin_unlock_irqrestore(&dev->lock, flags); + read_unlock(&vcc_sklist_lock); return length+1; } - spin_unlock_irqrestore(&dev->lock, flags); + read_unlock(&vcc_sklist_lock); for (i = 0; i < eni_dev->free_len; i++) { struct eni_free *fe = eni_dev->free_list+i; unsigned long offset; diff -Nru a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c --- a/drivers/atm/fore200e.c Tue Jul 1 18:44:39 2003 +++ b/drivers/atm/fore200e.c Tue Jul 1 18:44:39 2003 @@ -1069,18 +1069,23 @@ static struct atm_vcc* fore200e_find_vcc(struct fore200e* fore200e, struct rpd* rpd) { - unsigned long flags; + struct sock *s; struct atm_vcc* vcc; + struct hlist_node *node; - spin_lock_irqsave(&fore200e->atm_dev->lock, flags); - for (vcc = fore200e->atm_dev->vccs; vcc; vcc = vcc->next) { - - if (vcc->vpi == rpd->atm_header.vpi && vcc->vci == rpd->atm_header.vci) - break; + read_lock(&vcc_sklist_lock); + sk_for_each(s, node, &vcc_sklist) { + vcc = atm_sk(s); + if (vcc->dev != fore200e->atm_dev) + continue; + if (vcc->vpi == rpd->atm_header.vpi && vcc->vci == rpd->atm_header.vci) { + read_unlock(&vcc_sklist_lock); + return vcc; + } } - spin_unlock_irqrestore(&fore200e->atm_dev->lock, flags); - - return vcc; + read_unlock(&vcc_sklist_lock); + + return NULL; } @@ -1350,20 +1355,26 @@ static int fore200e_walk_vccs(struct atm_vcc *vcc, short *vpi, int *vci) { - unsigned long flags; struct atm_vcc* walk; + struct sock *s; + struct hlist_node *node; /* find a free VPI */ - spin_lock_irqsave(&vcc->dev->lock, flags); + read_lock(&vcc_sklist_lock); if (*vpi == ATM_VPI_ANY) { - for (*vpi = 0, walk = vcc->dev->vccs; walk; walk = walk->next) { + *vpi = 0; +restart_vpi_search: + sk_for_each(s, node, &vcc_sklist) { + walk = atm_sk(s); + if (walk->dev != vcc->dev) + continue; if ((walk->vci == *vci) && (walk->vpi == *vpi)) { (*vpi)++; - walk = vcc->dev->vccs; + goto restart_vpi_search; } } } @@ -1371,16 +1382,21 @@ /* find a free VCI */ if (*vci == ATM_VCI_ANY) { - for (*vci = ATM_NOT_RSV_VCI, walk = vcc->dev->vccs; walk; walk = walk->next) { + *vci = ATM_NOT_RSV_VCI; +restart_vci_search: + sk_for_each(s, node, &vcc_sklist) { + walk = atm_sk(s); + if (walk->dev != vcc->dev) + continue; if ((walk->vpi = *vpi) && (walk->vci == *vci)) { *vci = walk->vci + 1; - walk = vcc->dev->vccs; + goto restart_vci_search; } } } - spin_unlock_irqrestore(&vcc->dev->lock, flags); + read_unlock(&vcc_sklist_lock); return 0; } @@ -2642,7 +2658,8 @@ static int fore200e_proc_read(struct atm_dev *dev,loff_t* pos,char* page) { - unsigned long flags; + struct sock *s; + struct hlist_node *node; struct fore200e* fore200e = FORE200E_DEV(dev); int len, left = *pos; @@ -2889,8 +2906,12 @@ len = sprintf(page,"\n" " VCCs:\n address\tVPI.VCI:AAL\t(min/max tx PDU size) (min/max rx PDU size)\n"); - spin_lock_irqsave(&fore200e->atm_dev->lock, flags); - for (vcc = fore200e->atm_dev->vccs; vcc; vcc = vcc->next) { + read_lock(&vcc_sklist_lock); + sk_for_each(s, node, &vcc_sklist) { + vcc = atm_sk(s); + + if (vcc->dev != fore200e->atm_dev) + continue; fore200e_vcc = FORE200E_VCC(vcc); @@ -2904,7 +2925,7 @@ fore200e_vcc->rx_max_pdu ); } - spin_unlock_irqrestore(&fore200e->atm_dev->lock, flags); + read_unlock(&vcc_sklist_lock); return len; } diff -Nru a/drivers/atm/he.c b/drivers/atm/he.c --- a/drivers/atm/he.c Tue Jul 1 18:44:32 2003 +++ b/drivers/atm/he.c Tue Jul 1 18:44:32 2003 @@ -79,7 +79,6 @@ #include #define USE_TASKLET -#define USE_HE_FIND_VCC #undef USE_SCATTERGATHER #undef USE_CHECKSUM_HW /* still confused about this */ #define USE_RBPS @@ -328,25 +327,25 @@ he_writel_rcm(dev, val, 0x00000 | (cid << 3) | 7) static __inline__ struct atm_vcc* -he_find_vcc(struct he_dev *he_dev, unsigned cid) +__find_vcc(struct he_dev *he_dev, unsigned cid) { - unsigned long flags; struct atm_vcc *vcc; + struct hlist_node *node; + struct sock *s; short vpi; int vci; vpi = cid >> he_dev->vcibits; vci = cid & ((1 << he_dev->vcibits) - 1); - spin_lock_irqsave(&he_dev->atm_dev->lock, flags); - for (vcc = he_dev->atm_dev->vccs; vcc; vcc = vcc->next) - if (vcc->vci == vci && vcc->vpi == vpi - && vcc->qos.rxtp.traffic_class != ATM_NONE) { - spin_unlock_irqrestore(&he_dev->atm_dev->lock, flags); + sk_for_each(s, node, &vcc_sklist) { + vcc = atm_sk(s); + if (vcc->dev == he_dev->atm_dev && + vcc->vci == vci && vcc->vpi == vpi && + vcc->qos.rxtp.traffic_class != ATM_NONE) { return vcc; - } - - spin_unlock_irqrestore(&he_dev->atm_dev->lock, flags); + } + } return NULL; } @@ -1566,17 +1565,6 @@ reg |= RX_ENABLE; he_writel(he_dev, reg, RC_CONFIG); -#ifndef USE_HE_FIND_VCC - he_dev->he_vcc_table = kmalloc(sizeof(struct he_vcc_table) * - (1 << (he_dev->vcibits + he_dev->vpibits)), GFP_KERNEL); - if (he_dev->he_vcc_table == NULL) { - hprintk("failed to alloc he_vcc_table\n"); - return -ENOMEM; - } - memset(he_dev->he_vcc_table, 0, sizeof(struct he_vcc_table) * - (1 << (he_dev->vcibits + he_dev->vpibits))); -#endif - for (i = 0; i < HE_NUM_CS_STPER; ++i) { he_dev->cs_stper[i].inuse = 0; he_dev->cs_stper[i].pcr = -1; @@ -1712,11 +1700,6 @@ he_dev->tpd_base, he_dev->tpd_base_phys); #endif -#ifndef USE_HE_FIND_VCC - if (he_dev->he_vcc_table) - kfree(he_dev->he_vcc_table); -#endif - if (he_dev->pci_dev) { pci_read_config_word(he_dev->pci_dev, PCI_COMMAND, &command); command &= ~(PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); @@ -1798,6 +1781,7 @@ int pdus_assembled = 0; int updated = 0; + read_lock(&vcc_sklist_lock); while (he_dev->rbrq_head != rbrq_tail) { ++updated; @@ -1823,13 +1807,10 @@ buf_len = RBRQ_BUFLEN(he_dev->rbrq_head) * 4; cid = RBRQ_CID(he_dev->rbrq_head); -#ifdef USE_HE_FIND_VCC if (cid != lastcid) - vcc = he_find_vcc(he_dev, cid); + vcc = __find_vcc(he_dev, cid); lastcid = cid; -#else - vcc = HE_LOOKUP_VCC(he_dev, cid); -#endif + if (vcc == NULL) { hprintk("vcc == NULL (cid 0x%x)\n", cid); if (!RBRQ_HBUF_ERR(he_dev->rbrq_head)) @@ -1966,6 +1947,7 @@ RBRQ_MASK(++he_dev->rbrq_head)); } + read_unlock(&vcc_sklist_lock); if (updated) { if (updated > he_dev->rbrq_peak) @@ -2565,10 +2547,6 @@ #endif spin_unlock_irqrestore(&he_dev->global_lock, flags); - -#ifndef USE_HE_FIND_VCC - HE_LOOKUP_VCC(he_dev, cid) = vcc; -#endif } open_failed: @@ -2634,9 +2612,6 @@ if (timeout == 0) hprintk("close rx timeout cid 0x%x\n", cid); -#ifndef USE_HE_FIND_VCC - HE_LOOKUP_VCC(he_dev, cid) = NULL; -#endif HPRINTK("close rx cid 0x%x complete\n", cid); } diff -Nru a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c --- a/drivers/atm/idt77252.c Tue Jul 1 18:44:35 2003 +++ b/drivers/atm/idt77252.c Tue Jul 1 18:44:35 2003 @@ -2403,37 +2403,43 @@ static int idt77252_find_vcc(struct atm_vcc *vcc, short *vpi, int *vci) { - unsigned long flags; + struct sock *s; struct atm_vcc *walk; - spin_lock_irqsave(&vcc->dev->lock, flags); + read_lock(&vcc_sklist_lock); if (*vpi == ATM_VPI_ANY) { *vpi = 0; - walk = vcc->dev->vccs; - while (walk) { + s = sk_head(&vcc_sklist); + while (s) { + walk = atm_sk(s); + if (walk->dev != vcc->dev) + continue; if ((walk->vci == *vci) && (walk->vpi == *vpi)) { (*vpi)++; - walk = vcc->dev->vccs; + s = sk_head(&vcc_sklist); continue; } - walk = walk->next; + s = sk_next(s); } } if (*vci == ATM_VCI_ANY) { *vci = ATM_NOT_RSV_VCI; - walk = vcc->dev->vccs; - while (walk) { + s = sk_head(&vcc_sklist); + while (s) { + walk = atm_sk(s); + if (walk->dev != vcc->dev) + continue; if ((walk->vci == *vci) && (walk->vpi == *vpi)) { (*vci)++; - walk = vcc->dev->vccs; + s = sk_head(&vcc_sklist); continue; } - walk = walk->next; + s = sk_next(s); } } - spin_unlock_irqrestore(&vcc->dev->lock, flags); + read_unlock(&vcc_sklist_lock); return 0; } diff -Nru a/drivers/block/loop.c b/drivers/block/loop.c --- a/drivers/block/loop.c Tue Jul 1 18:44:35 2003 +++ b/drivers/block/loop.c Tue Jul 1 18:44:35 2003 @@ -2,7 +2,7 @@ * linux/drivers/block/loop.c * * Written by Theodore Ts'o, 3/29/93 - * + * * Copyright 1993 by Theodore Ts'o. Redistribution of this file is * permitted under the GNU General Public License. * @@ -21,12 +21,12 @@ * Loadable modules and other fixes by AK, 1998 * * Make real block number available to downstream transfer functions, enables - * CBC (and relatives) mode encryption requiring unique IVs per data block. + * CBC (and relatives) mode encryption requiring unique IVs per data block. * Reed H. Petty, rhp@draper.net * * Maximum number of loop devices now dynamic via max_loop module parameter. * Russell Kroll 19990701 - * + * * Maximum number of loop devices when compiled-in now selectable by passing * max_loop=<1-255> to the kernel on boot. * Erik I. Bolsø, , Oct 31, 1999 @@ -40,19 +40,10 @@ * Heinz Mauelshagen , Feb 2002 * * Still To Fix: - * - Advisory locking is ignored here. - * - Should use an own CAP_* category instead of CAP_SYS_ADMIN + * - Advisory locking is ignored here. + * - Should use an own CAP_* category instead of CAP_SYS_ADMIN * - * WARNING/FIXME: - * - The block number as IV passing to low level transfer functions is broken: - * it passes the underlying device's block number instead of the - * offset. This makes it change for a given block when the file is - * moved/restored/copied and also doesn't work over NFS. - * AV, Feb 12, 2000: we pass the logical block number now. It fixes the - * problem above. Encryption modules that used to rely on the old scheme - * should just call ->i_mapping->bmap() to calculate the physical block - * number. - */ + */ #include #include @@ -60,12 +51,10 @@ #include #include #include -#include #include #include #include #include -#include #include #include #include @@ -120,49 +109,60 @@ return 0; } -static int xor_status(struct loop_device *lo, const struct loop_info64 *info) +static int xor_init(struct loop_device *lo, const struct loop_info64 *info) { if (info->lo_encrypt_key_size <= 0) return -EINVAL; return 0; } -struct loop_func_table none_funcs = { +static struct loop_func_table none_funcs = { .number = LO_CRYPT_NONE, .transfer = transfer_none, }; -struct loop_func_table xor_funcs = { +static struct loop_func_table xor_funcs = { .number = LO_CRYPT_XOR, .transfer = transfer_xor, - .init = xor_status + .init = xor_init }; -/* xfer_funcs[0] is special - its release function is never called */ -struct loop_func_table *xfer_funcs[MAX_LO_CRYPT] = { +/* xfer_funcs[0] is special - its release function is never called */ +static struct loop_func_table *xfer_funcs[MAX_LO_CRYPT] = { &none_funcs, - &xor_funcs + &xor_funcs }; -static int figure_loop_size(struct loop_device *lo) +static int +figure_loop_size(struct loop_device *lo) { - loff_t size = lo->lo_backing_file->f_dentry->d_inode->i_mapping->host->i_size; + loff_t size, offset, loopsize; sector_t x; + + /* Compute loopsize in bytes */ + size = lo->lo_backing_file->f_dentry->d_inode->i_mapping->host->i_size; + offset = lo->lo_offset; + loopsize = size - offset; + if (lo->lo_sizelimit > 0 && lo->lo_sizelimit < loopsize) + loopsize = lo->lo_sizelimit; + /* * Unfortunately, if we want to do I/O on the device, * the number of 512-byte sectors has to fit into a sector_t. */ - size = (size - lo->lo_offset) >> 9; + size = loopsize >> 9; x = (sector_t)size; + if ((loff_t)x != size) return -EFBIG; - set_capacity(disks[lo->lo_number], size); + set_capacity(disks[lo->lo_number], x); return 0; } -static inline int lo_do_transfer(struct loop_device *lo, int cmd, char *rbuf, - char *lbuf, int size, sector_t rblock) +static inline int +lo_do_transfer(struct loop_device *lo, int cmd, char *rbuf, + char *lbuf, int size, sector_t rblock) { if (!lo->transfer) return 0; @@ -189,9 +189,11 @@ data = kmap(bvec->bv_page) + bvec->bv_offset; len = bvec->bv_len; while (len > 0) { - sector_t IV = index * (PAGE_CACHE_SIZE/bsize) + offset/bsize; + sector_t IV; int transfer_result; + IV = ((sector_t)index << (PAGE_CACHE_SHIFT - 9))+(offset >> 9); + size = PAGE_CACHE_SIZE - offset; if (size > len) size = len; @@ -202,7 +204,8 @@ if (aops->prepare_write(file, page, offset, offset+size)) goto unlock; kaddr = kmap(page); - transfer_result = lo_do_transfer(lo, WRITE, kaddr + offset, data, size, IV); + transfer_result = lo_do_transfer(lo, WRITE, kaddr + offset, + data, size, IV); if (transfer_result) { /* * The transfer failed, but we still write the data to @@ -271,7 +274,9 @@ unsigned long count = desc->count; struct lo_read_data *p = (struct lo_read_data*)desc->buf; struct loop_device *lo = p->lo; - int IV = page->index * (PAGE_CACHE_SIZE/p->bsize) + offset/p->bsize; + sector_t IV; + + IV = ((sector_t) page->index << (PAGE_CACHE_SHIFT - 9))+(offset >> 9); if (size > count) size = count; @@ -326,20 +331,6 @@ return ret; } -static inline unsigned long -loop_get_iv(struct loop_device *lo, unsigned long sector) -{ - int bs = lo->lo_blocksize; - unsigned long offset, IV; - - IV = sector / (bs >> 9) + lo->lo_offset / bs; - offset = ((sector % (bs >> 9)) << 9) + lo->lo_offset % bs; - if (offset >= bs) - IV++; - - return IV; -} - static int do_bio_filebacked(struct loop_device *lo, struct bio *bio) { loff_t pos; @@ -503,11 +494,13 @@ static int loop_transfer_bio(struct loop_device *lo, struct bio *to_bio, struct bio *from_bio) { - unsigned long IV = loop_get_iv(lo, from_bio->bi_sector); + sector_t IV; struct bio_vec *from_bvec, *to_bvec; char *vto, *vfrom; int ret = 0, i; + IV = from_bio->bi_sector + (lo->lo_offset >> 9); + __bio_for_each_segment(from_bvec, from_bio, i, 0) { to_bvec = &to_bio->bi_io_vec[i]; @@ -614,9 +607,12 @@ daemonize("loop%d", lo->lo_number); - current->flags |= PF_IOTHREAD; /* loop can be used in an encrypted device - hence, it mustn't be stopped at all because it could - be indirectly used during suspension */ + /* + * loop can be used in an encrypted device, + * hence, it mustn't be stopped at all + * because it could be indirectly used during suspension + */ + current->flags |= PF_IOTHREAD; set_user_nice(current, -20); @@ -724,6 +720,7 @@ lo->lo_backing_file = file; lo->transfer = NULL; lo->ioctl = NULL; + lo->lo_sizelimit = 0; if (figure_loop_size(lo)) { error = -EFBIG; fput(file); @@ -771,36 +768,42 @@ return error; } -static int loop_release_xfer(struct loop_device *lo) +static int +loop_release_xfer(struct loop_device *lo) { - int err = 0; - if (lo->lo_encrypt_type) { - struct loop_func_table *xfer= xfer_funcs[lo->lo_encrypt_type]; - if (xfer && xfer->release) - err = xfer->release(lo); - if (xfer && xfer->unlock) - xfer->unlock(lo); - lo->lo_encrypt_type = 0; + int err = 0; + struct loop_func_table *xfer = lo->lo_encryption; + + if (xfer) { + if (xfer->release) + err = xfer->release(lo); + lo->transfer = NULL; + lo->lo_encryption = NULL; + module_put(xfer->owner); } return err; } static int -loop_init_xfer(struct loop_device *lo, int type, const struct loop_info64 *i) +loop_init_xfer(struct loop_device *lo, struct loop_func_table *xfer, + const struct loop_info64 *i) { - int err = 0; - if (type) { - struct loop_func_table *xfer = xfer_funcs[type]; + int err = 0; + + if (xfer) { + struct module *owner = xfer->owner; + + if (!try_module_get(owner)) + return -EINVAL; if (xfer->init) err = xfer->init(lo, i); - if (!err) { - lo->lo_encrypt_type = type; - if (xfer->lock) - xfer->lock(lo); - } + if (err) + module_put(owner); + else + lo->lo_encryption = xfer; } return err; -} +} static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev) { @@ -809,9 +812,11 @@ if (lo->lo_state != Lo_bound) return -ENXIO; + if (lo->lo_refcnt > 1) /* we needed one fd for the ioctl */ return -EBUSY; - if (filp==NULL) + + if (filp == NULL) return -EINVAL; spin_lock_irq(&lo->lo_lock); @@ -828,8 +833,9 @@ lo->transfer = NULL; lo->ioctl = NULL; lo->lo_device = NULL; - lo->lo_encrypt_type = 0; + lo->lo_encryption = NULL; lo->lo_offset = 0; + lo->lo_sizelimit = 0; lo->lo_encrypt_key_size = 0; lo->lo_flags = 0; lo->lo_queue.queuedata = NULL; @@ -849,49 +855,57 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info) { int err; - unsigned int type; - loff_t offset; + struct loop_func_table *xfer; - if (lo->lo_encrypt_key_size && lo->lo_key_owner != current->uid && + if (lo->lo_encrypt_key_size && lo->lo_key_owner != current->uid && !capable(CAP_SYS_ADMIN)) return -EPERM; if (lo->lo_state != Lo_bound) return -ENXIO; if ((unsigned int) info->lo_encrypt_key_size > LO_KEY_SIZE) return -EINVAL; - type = info->lo_encrypt_type; - if (type >= MAX_LO_CRYPT || xfer_funcs[type] == NULL) - return -EINVAL; - if (type == LO_CRYPT_XOR && info->lo_encrypt_key_size == 0) - return -EINVAL; err = loop_release_xfer(lo); - if (!err) - err = loop_init_xfer(lo, type, info); + if (err) + return err; - offset = lo->lo_offset; - if (offset != info->lo_offset) { - lo->lo_offset = info->lo_offset; - if (figure_loop_size(lo)){ - err = -EFBIG; - lo->lo_offset = offset; - } - } + if (info->lo_encrypt_type) { + unsigned int type = info->lo_encrypt_type; + + if (type >= MAX_LO_CRYPT) + return -EINVAL; + xfer = xfer_funcs[type]; + if (xfer == NULL) + return -EINVAL; + } else + xfer = NULL; + err = loop_init_xfer(lo, xfer, info); if (err) - return err; + return err; + + if (lo->lo_offset != info->lo_offset || + lo->lo_sizelimit != info->lo_sizelimit) { + lo->lo_offset = info->lo_offset; + lo->lo_sizelimit = info->lo_sizelimit; + if (figure_loop_size(lo)) + return -EFBIG; + } strlcpy(lo->lo_name, info->lo_name, LO_NAME_SIZE); - lo->transfer = xfer_funcs[type]->transfer; - lo->ioctl = xfer_funcs[type]->ioctl; + if (!xfer) + xfer = &none_funcs; + lo->transfer = xfer->transfer; + lo->ioctl = xfer->ioctl; + lo->lo_encrypt_key_size = info->lo_encrypt_key_size; lo->lo_init[0] = info->lo_init[0]; lo->lo_init[1] = info->lo_init[1]; if (info->lo_encrypt_key_size) { - memcpy(lo->lo_encrypt_key, info->lo_encrypt_key, + memcpy(lo->lo_encrypt_key, info->lo_encrypt_key, info->lo_encrypt_key_size); - lo->lo_key_owner = current->uid; + lo->lo_key_owner = current->uid; } return 0; @@ -915,9 +929,11 @@ info->lo_inode = stat.ino; info->lo_rdevice = lo->lo_device ? stat.rdev : stat.dev; info->lo_offset = lo->lo_offset; + info->lo_sizelimit = lo->lo_sizelimit; info->lo_flags = lo->lo_flags; strlcpy(info->lo_name, lo->lo_name, LO_NAME_SIZE); - info->lo_encrypt_type = lo->lo_encrypt_type; + info->lo_encrypt_type = + lo->lo_encryption ? lo->lo_encryption->number : 0; if (lo->lo_encrypt_key_size && capable(CAP_SYS_ADMIN)) { info->lo_encrypt_key_size = lo->lo_encrypt_key_size; memcpy(info->lo_encrypt_key, lo->lo_encrypt_key, @@ -929,11 +945,13 @@ static void loop_info64_from_old(const struct loop_info *info, struct loop_info64 *info64) { + memset(info64, 0, sizeof(*info64)); info64->lo_number = info->lo_number; info64->lo_device = info->lo_device; info64->lo_inode = info->lo_inode; info64->lo_rdevice = info->lo_rdevice; info64->lo_offset = info->lo_offset; + info64->lo_sizelimit = 0; info64->lo_encrypt_type = info->lo_encrypt_type; info64->lo_encrypt_key_size = info->lo_encrypt_key_size; info64->lo_flags = info->lo_flags; @@ -946,6 +964,7 @@ static int loop_info64_to_old(const struct loop_info64 *info64, struct loop_info *info) { + memset(info, 0, sizeof(*info)); info->lo_number = info64->lo_number; info->lo_device = info64->lo_device; info->lo_inode = info64->lo_inode; @@ -1060,30 +1079,22 @@ static int lo_open(struct inode *inode, struct file *file) { struct loop_device *lo = inode->i_bdev->bd_disk->private_data; - int type; down(&lo->lo_ctl_mutex); - - type = lo->lo_encrypt_type; - if (type && xfer_funcs[type] && xfer_funcs[type]->lock) - xfer_funcs[type]->lock(lo); lo->lo_refcnt++; up(&lo->lo_ctl_mutex); + return 0; } static int lo_release(struct inode *inode, struct file *file) { struct loop_device *lo = inode->i_bdev->bd_disk->private_data; - int type; down(&lo->lo_ctl_mutex); - type = lo->lo_encrypt_type; --lo->lo_refcnt; - if (xfer_funcs[type] && xfer_funcs[type]->unlock) - xfer_funcs[type]->unlock(lo); - up(&lo->lo_ctl_mutex); + return 0; } @@ -1103,38 +1114,45 @@ int loop_register_transfer(struct loop_func_table *funcs) { - if ((unsigned)funcs->number > MAX_LO_CRYPT || xfer_funcs[funcs->number]) + unsigned int n = funcs->number; + + if (n >= MAX_LO_CRYPT || xfer_funcs[n]) return -EINVAL; - xfer_funcs[funcs->number] = funcs; - return 0; + xfer_funcs[n] = funcs; + return 0; } int loop_unregister_transfer(int number) { - struct loop_device *lo; + unsigned int n = number; + struct loop_device *lo; + struct loop_func_table *xfer; - if ((unsigned)number >= MAX_LO_CRYPT) - return -EINVAL; - for (lo = &loop_dev[0]; lo < &loop_dev[max_loop]; lo++) { - int type = lo->lo_encrypt_type; - if (type == number) { - xfer_funcs[type]->release(lo); - lo->transfer = NULL; - lo->lo_encrypt_type = 0; - } + if (n == 0 || n >= MAX_LO_CRYPT || (xfer = xfer_funcs[n]) == NULL) + return -EINVAL; + + xfer_funcs[n] = NULL; + + for (lo = &loop_dev[0]; lo < &loop_dev[max_loop]; lo++) { + down(&lo->lo_ctl_mutex); + + if (lo->lo_encryption == xfer) + loop_release_xfer(lo); + + up(&lo->lo_ctl_mutex); } - xfer_funcs[number] = NULL; - return 0; + + return 0; } EXPORT_SYMBOL(loop_register_transfer); EXPORT_SYMBOL(loop_unregister_transfer); -int __init loop_init(void) +int __init loop_init(void) { int i; - if ((max_loop < 1) || (max_loop > 256)) { + if (max_loop < 1 || max_loop > 256) { printk(KERN_WARNING "loop: invalid max_loop (must be between" " 1 and 256), using default (8)\n"); max_loop = 8; @@ -1143,22 +1161,22 @@ if (register_blkdev(LOOP_MAJOR, "loop")) return -EIO; - devfs_mk_dir("loop"); - loop_dev = kmalloc(max_loop * sizeof(struct loop_device), GFP_KERNEL); if (!loop_dev) - return -ENOMEM; + goto out_mem1; disks = kmalloc(max_loop * sizeof(struct gendisk *), GFP_KERNEL); if (!disks) - goto out_mem; + goto out_mem2; for (i = 0; i < max_loop; i++) { disks[i] = alloc_disk(1); if (!disks[i]) - goto out_mem2; + goto out_mem3; } + devfs_mk_dir("loop"); + for (i = 0; i < max_loop; i++) { struct loop_device *lo = &loop_dev[i]; struct gendisk *disk = disks[i]; @@ -1180,19 +1198,22 @@ printk(KERN_INFO "loop: loaded (max %d devices)\n", max_loop); return 0; -out_mem2: +out_mem3: while (i--) put_disk(disks[i]); kfree(disks); -out_mem: +out_mem2: kfree(loop_dev); +out_mem1: + unregister_blkdev(LOOP_MAJOR, "loop"); printk(KERN_ERR "loop: ran out of memory\n"); return -ENOMEM; } -void loop_exit(void) +void loop_exit(void) { int i; + for (i = 0; i < max_loop; i++) { del_gendisk(disks[i]); put_disk(disks[i]); diff -Nru a/drivers/block/nbd.c b/drivers/block/nbd.c --- a/drivers/block/nbd.c Tue Jul 1 18:44:33 2003 +++ b/drivers/block/nbd.c Tue Jul 1 18:44:33 2003 @@ -28,6 +28,9 @@ * the transmit lock. * 02-10-11 Allow hung xmit to be aborted via SIGKILL & various fixes. * + * 03-06-22 Make nbd work with new linux 2.5 block layer design. This fixes + * memory corruption from module removal and possible memory corruption + * from sending/receiving disk data. * * possible FIXME: make set_sock / set_blksize / set_size / do_it one syscall * why not: would need verify_area and friends, would share yet another @@ -63,6 +66,16 @@ static struct nbd_device nbd_dev[MAX_NBD]; +/* + * Use just one lock (or at most 1 per NIC). Two arguments for this: + * 1. Each NIC is essentially a synchronization point for all servers + * accessed through that NIC so there's no need to have more locks + * than NICs anyway. + * 2. More locks lead to more "Dirty cache line bouncing" which will slow + * down each lock to the point where they're actually slower than just + * a single lock. + * Thanks go to Jens Axboe and Al Viro for their LKML emails explaining this! + */ static spinlock_t nbd_lock = SPIN_LOCK_UNLOCKED; #define DEBUG( s ) @@ -168,6 +181,17 @@ return result; } +static inline int sock_send_bvec(struct socket *sock, struct bio_vec *bvec, + int flags) +{ + int result; + void *kaddr = kmap(bvec->bv_page); + result = nbd_xmit(1, sock, kaddr + bvec->bv_offset, bvec->bv_len, + flags); + kunmap(bvec->bv_page); + return result; +} + #define FAIL( s ) { printk( KERN_ERR "NBD: " s "(result %d)\n", result ); goto error_out; } void nbd_send_req(struct nbd_device *lo, struct request *req) @@ -209,7 +233,7 @@ if ((i < (bio->bi_vcnt - 1)) || bio->bi_next) flags = MSG_MORE; DEBUG("data, "); - result = nbd_xmit(1, sock, page_address(bvec->bv_page) + bvec->bv_offset, bvec->bv_len, flags); + result = sock_send_bvec(sock, bvec, flags); if (result <= 0) FAIL("Send data failed."); } @@ -244,6 +268,16 @@ return NULL; } +static inline int sock_recv_bvec(struct socket *sock, struct bio_vec *bvec) +{ + int result; + void *kaddr = kmap(bvec->bv_page); + result = nbd_xmit(0, sock, kaddr + bvec->bv_offset, bvec->bv_len, + MSG_WAITALL); + kunmap(bvec->bv_page); + return result; +} + #define HARDFAIL( s ) { printk( KERN_ERR "NBD: " s "(result %d)\n", result ); lo->harderror = result; return NULL; } struct request *nbd_read_stat(struct nbd_device *lo) /* NULL returned = something went wrong, inform userspace */ @@ -251,10 +285,11 @@ int result; struct nbd_reply reply; struct request *req; + struct socket *sock = lo->sock; DEBUG("reading control, "); reply.magic = 0; - result = nbd_xmit(0, lo->sock, (char *) &reply, sizeof(reply), MSG_WAITALL); + result = nbd_xmit(0, sock, (char *) &reply, sizeof(reply), MSG_WAITALL); if (result <= 0) HARDFAIL("Recv control failed."); req = nbd_find_request(lo, reply.handle); @@ -268,14 +303,17 @@ FAIL("Other side returned error."); if (nbd_cmd(req) == NBD_CMD_READ) { - struct bio *bio = req->bio; + int i; + struct bio *bio; DEBUG("data, "); - do { - result = nbd_xmit(0, lo->sock, bio_data(bio), bio->bi_size, MSG_WAITALL); - if (result <= 0) - HARDFAIL("Recv data failed."); - bio = bio->bi_next; - } while(bio); + rq_for_each_bio(bio, req) { + struct bio_vec *bvec; + bio_for_each_segment(bvec, bio, i) { + result = sock_recv_bvec(sock, bvec); + if (result <= 0) + HARDFAIL("Recv data failed."); + } + } } DEBUG("done.\n"); return req; @@ -538,8 +576,6 @@ * (Just smiley confuses emacs :-) */ -static struct request_queue nbd_queue; - static int __init nbd_init(void) { int err = -ENOMEM; @@ -555,6 +591,17 @@ if (!disk) goto out; nbd_dev[i].disk = disk; + /* + * The new linux 2.5 block layer implementation requires + * every gendisk to have its very own request_queue struct. + * These structs are big so we dynamically allocate them. + */ + disk->queue = kmalloc(sizeof(struct request_queue), GFP_KERNEL); + if (!disk->queue) { + put_disk(disk); + goto out; + } + blk_init_queue(disk->queue, do_nbd_request, &nbd_lock); } if (register_blkdev(NBD_MAJOR, "nbd")) { @@ -564,7 +611,6 @@ #ifdef MODULE printk("nbd: registered device at major %d\n", NBD_MAJOR); #endif - blk_init_queue(&nbd_queue, do_nbd_request, &nbd_lock); devfs_mk_dir("nbd"); for (i = 0; i < MAX_NBD; i++) { struct gendisk *disk = nbd_dev[i].disk; @@ -582,7 +628,6 @@ disk->first_minor = i; disk->fops = &nbd_fops; disk->private_data = &nbd_dev[i]; - disk->queue = &nbd_queue; sprintf(disk->disk_name, "nbd%d", i); sprintf(disk->devfs_name, "nbd/%d", i); set_capacity(disk, 0x3ffffe); @@ -591,8 +636,10 @@ return 0; out: - while (i--) + while (i--) { + kfree(nbd_dev[i].disk->queue); put_disk(nbd_dev[i].disk); + } return err; } @@ -600,12 +647,22 @@ { int i; for (i = 0; i < MAX_NBD; i++) { - del_gendisk(nbd_dev[i].disk); - put_disk(nbd_dev[i].disk); + struct gendisk *disk = nbd_dev[i].disk; + if (disk) { + if (disk->queue) { + blk_cleanup_queue(disk->queue); + kfree(disk->queue); + disk->queue = NULL; + } + del_gendisk(disk); + put_disk(disk); + } } devfs_remove("nbd"); - blk_cleanup_queue(&nbd_queue); unregister_blkdev(NBD_MAJOR, "nbd"); +#ifdef MODULE + printk("nbd: unregistered device at major %d\n", NBD_MAJOR); +#endif } module_init(nbd_init); diff -Nru a/drivers/block/rd.c b/drivers/block/rd.c --- a/drivers/block/rd.c Tue Jul 1 18:44:36 2003 +++ b/drivers/block/rd.c Tue Jul 1 18:44:36 2003 @@ -271,9 +271,6 @@ { unsigned unit = minor(inode->i_rdev); - if (unit >= NUM_RAMDISKS) - return -ENODEV; - /* * Immunize device against invalidate_buffers() and prune_icache(). */ diff -Nru a/drivers/block/scsi_ioctl.c b/drivers/block/scsi_ioctl.c --- a/drivers/block/scsi_ioctl.c Tue Jul 1 18:44:39 2003 +++ b/drivers/block/scsi_ioctl.c Tue Jul 1 18:44:39 2003 @@ -450,7 +450,7 @@ close = 1; case CDROMEJECT: rq = blk_get_request(q, WRITE, __GFP_WAIT); - rq->flags = REQ_BLOCK_PC; + rq->flags |= REQ_BLOCK_PC; rq->data = NULL; rq->data_len = 0; rq->timeout = BLK_DEFAULT_TIMEOUT; diff -Nru a/drivers/cdrom/Kconfig b/drivers/cdrom/Kconfig --- a/drivers/cdrom/Kconfig Tue Jul 1 18:44:37 2003 +++ b/drivers/cdrom/Kconfig Tue Jul 1 18:44:37 2003 @@ -1,6 +1,39 @@ # # CDROM driver configuration # + +menu "Old CD-ROM drivers (not SCSI, not IDE)" + depends on ISA + +config CD_NO_IDESCSI + bool "Support non-SCSI/IDE/ATAPI CDROM drives" + ---help--- + If you have a CD-ROM drive that is neither SCSI nor IDE/ATAPI, say Y + here, otherwise N. Read the CD-ROM-HOWTO, available from + . + + Note that the answer to this question doesn't directly affect the + kernel: saying N will just cause the configurator to skip all + the questions about these CD-ROM drives. If you are unsure what you + have, say Y and find out whether you have one of the following + drives. + + For each of these drivers, a file Documentation/cdrom/{driver_name} + exists. Especially in cases where you do not know exactly which kind + of drive you have you should read there. Most of these drivers use a + file drivers/cdrom/{driver_name}.h where you can define your + interface parameters and switch some internal goodies. + + All these CD-ROM drivers are also usable as a module ( = code which + can be inserted in and removed from the running kernel whenever you + want). If you want to compile them as module, say M instead of Y and + read . + + If you want to use any of these CD-ROM drivers, you also have to + answer Y or M to "ISO 9660 CD-ROM file system support" below (this + answer will get "defaulted" for you if you enable any of the Linux + CD-ROM drivers). + config AZTCD tristate "Aztech/Orchid/Okano/Wearnes/TXC/CyDROM CDROM support" depends on CD_NO_IDESCSI @@ -248,3 +281,4 @@ The module will be called sonycd535. If you want to compile it as a module, say M here and read . +endmenu diff -Nru a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c --- a/drivers/char/agp/nvidia-agp.c Tue Jul 1 18:44:33 2003 +++ b/drivers/char/agp/nvidia-agp.c Tue Jul 1 18:44:33 2003 @@ -169,7 +169,8 @@ mem->is_flushed = TRUE; } for (i = 0, j = pg_start; i < mem->page_count; i++, j++) - agp_bridge->gatt_table[nvidia_private.pg_offset + j] = mem->memory[i]; + agp_bridge->gatt_table[nvidia_private.pg_offset + j] = + agp_bridge->driver->mask_memory(mem->memory[i], mem->type); agp_bridge->driver->tlb_flush(mem); return 0; diff -Nru a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c --- a/drivers/char/agp/sis-agp.c Tue Jul 1 18:44:31 2003 +++ b/drivers/char/agp/sis-agp.c Tue Jul 1 18:44:31 2003 @@ -151,6 +151,10 @@ .device_id = PCI_DEVICE_ID_SI_550, .chipset_name = "550", }, + { + .device_id = PCI_DEVICE_ID_SI_655, + .chipset_name = "655", + }, { }, /* dummy final entry, always present */ }; diff -Nru a/drivers/char/ip2main.c b/drivers/char/ip2main.c --- a/drivers/char/ip2main.c Tue Jul 1 18:44:39 2003 +++ b/drivers/char/ip2main.c Tue Jul 1 18:44:39 2003 @@ -707,40 +707,42 @@ } } #else /* LINUX_VERSION_CODE > 2.1.99 */ - struct pci_dev *pci_dev_i = NULL; - pci_dev_i = pci_find_device(PCI_VENDOR_ID_COMPUTONE, - PCI_DEVICE_ID_COMPUTONE_IP2EX, pci_dev_i); - if (pci_dev_i != NULL) { - unsigned int addr; - unsigned char pci_irq; + { + struct pci_dev *pci_dev_i = NULL; + pci_dev_i = pci_find_device(PCI_VENDOR_ID_COMPUTONE, + PCI_DEVICE_ID_COMPUTONE_IP2EX, pci_dev_i); + if (pci_dev_i != NULL) { + unsigned int addr; + unsigned char pci_irq; - ip2config.type[i] = PCI; - status = - pci_read_config_dword(pci_dev_i, PCI_BASE_ADDRESS_1, &addr); - if ( addr & 1 ) { - ip2config.addr[i]=(USHORT)(addr&0xfffe); - } else { - printk( KERN_ERR "IP2: PCI I/O address error\n"); - } - status = - pci_read_config_byte(pci_dev_i, PCI_INTERRUPT_LINE, &pci_irq); + ip2config.type[i] = PCI; + status = + pci_read_config_dword(pci_dev_i, PCI_BASE_ADDRESS_1, &addr); + if ( addr & 1 ) { + ip2config.addr[i]=(USHORT)(addr&0xfffe); + } else { + printk( KERN_ERR "IP2: PCI I/O address error\n"); + } + status = + pci_read_config_byte(pci_dev_i, PCI_INTERRUPT_LINE, &pci_irq); // If the PCI BIOS assigned it, lets try and use it. If we // can't acquire it or it screws up, deal with it then. -// if (!is_valid_irq(pci_irq)) { -// printk( KERN_ERR "IP2: Bad PCI BIOS IRQ(%d)\n",pci_irq); -// pci_irq = 0; -// } - ip2config.irq[i] = pci_irq; - } else { // ann error - ip2config.addr[i] = 0; - if (status == PCIBIOS_DEVICE_NOT_FOUND) { - printk( KERN_ERR "IP2: PCI board %d not found\n", i ); - } else { - pcibios_strerror(status); - } - } +// if (!is_valid_irq(pci_irq)) { +// printk( KERN_ERR "IP2: Bad PCI BIOS IRQ(%d)\n",pci_irq); +// pci_irq = 0; +// } + ip2config.irq[i] = pci_irq; + } else { // ann error + ip2config.addr[i] = 0; + if (status == PCIBIOS_DEVICE_NOT_FOUND) { + printk( KERN_ERR "IP2: PCI board %d not found\n", i ); + } else { + pcibios_strerror(status); + } + } + } #endif /* ! 2_0_X */ #else printk( KERN_ERR "IP2: PCI card specified but PCI support not\n"); diff -Nru a/drivers/char/lcd.c b/drivers/char/lcd.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/lcd.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,633 @@ +/* + * LCD, LED and Button interface for Cobalt + * + * 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) 1996, 1997 by Andrew Bose + * + * Linux kernel version history: + * March 2001: Ported from 2.0.34 by Liam Davies + * + */ + +#define RTC_IO_EXTENT 0x10 /*Only really two ports, but... */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "lcd.h" + +static int lcd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg); + +static int lcd_present = 1; + +int led_state = 0; + +#if defined(CONFIG_TULIP) && 0 + +#define MAX_INTERFACES 8 +static linkcheck_func_t linkcheck_callbacks[MAX_INTERFACES]; +static void *linkcheck_cookies[MAX_INTERFACES]; + +int lcd_register_linkcheck_func(int iface_num, void *func, void *cookie) +{ + if (iface_num < 0 || + iface_num >= MAX_INTERFACES || + linkcheck_callbacks[iface_num] != NULL) + return -1; + linkcheck_callbacks[iface_num] = (linkcheck_func_t) func; + linkcheck_cookies[iface_num] = cookie; + return 0; +} +#endif + +static int lcd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + struct lcd_display button_display; + unsigned long address, a; + int index; + + switch (cmd) { + case LCD_On: + udelay(150); + BusyCheck(); + LCDWriteInst(0x0F); + break; + + case LCD_Off: + udelay(150); + BusyCheck(); + LCDWriteInst(0x08); + break; + + case LCD_Reset: + udelay(150); + LCDWriteInst(0x3F); + udelay(150); + LCDWriteInst(0x3F); + udelay(150); + LCDWriteInst(0x3F); + udelay(150); + LCDWriteInst(0x3F); + udelay(150); + LCDWriteInst(0x01); + udelay(150); + LCDWriteInst(0x06); + break; + + case LCD_Clear: + udelay(150); + BusyCheck(); + LCDWriteInst(0x01); + break; + + case LCD_Cursor_Left: + udelay(150); + BusyCheck(); + LCDWriteInst(0x10); + break; + + case LCD_Cursor_Right: + udelay(150); + BusyCheck(); + LCDWriteInst(0x14); + break; + + case LCD_Cursor_Off: + udelay(150); + BusyCheck(); + LCDWriteInst(0x0C); + break; + + case LCD_Cursor_On: + udelay(150); + BusyCheck(); + LCDWriteInst(0x0F); + break; + + case LCD_Blink_Off: + udelay(150); + BusyCheck(); + LCDWriteInst(0x0E); + break; + + case LCD_Get_Cursor_Pos:{ + struct lcd_display display; + + udelay(150); + BusyCheck(); + display.cursor_address = ( LCDReadInst ); + display.cursor_address = ( display.cursor_address & 0x07F ); + if(copy_to_user((struct lcd_display*)arg, &display, sizeof(struct lcd_display))) + return -EFAULT; + + break; + } + + + case LCD_Set_Cursor_Pos: { + struct lcd_display display; + + if(copy_from_user(&display, (struct lcd_display*)arg, sizeof(struct lcd_display))) + return -EFAULT; + + a = (display.cursor_address | kLCD_Addr ); + + udelay(150); + BusyCheck(); + LCDWriteInst( a ); + + break; + } + + case LCD_Get_Cursor: { + struct lcd_display display; + + udelay(150); + BusyCheck(); + display.character = LCDReadData; + + if(copy_to_user((struct lcd_display*)arg, &display, sizeof(struct lcd_display))) + return -EFAULT; + udelay(150); + BusyCheck(); + LCDWriteInst(0x10); + + break; + } + + case LCD_Set_Cursor:{ + struct lcd_display display; + + if(copy_from_user(&display, (struct lcd_display*)arg, sizeof(struct lcd_display))) + return -EFAULT; + + udelay(150); + BusyCheck(); + LCDWriteData( display.character ); + udelay(150); + BusyCheck(); + LCDWriteInst(0x10); + + break; + } + + + case LCD_Disp_Left: + udelay(150); + BusyCheck(); + LCDWriteInst(0x18); + break; + + case LCD_Disp_Right: + udelay(150); + BusyCheck(); + LCDWriteInst(0x1C); + break; + + case LCD_Home: + udelay(150); + BusyCheck(); + LCDWriteInst(0x02); + break; + + case LCD_Write: { + struct lcd_display display; + + + if(copy_from_user(&display, (struct lcd_display*)arg, sizeof(struct lcd_display))) + return -EFAULT; + + udelay(150); + BusyCheck(); + LCDWriteInst(0x80); + udelay(150); + BusyCheck(); + + for (index = 0; index < (display.size1); index++) { + udelay(150); + BusyCheck(); + LCDWriteData( display.line1[index]); + BusyCheck(); + } + + udelay(150); + BusyCheck(); + LCDWriteInst(0xC0); + udelay(150); + BusyCheck(); + for (index = 0; index < (display.size2); index++) { + udelay(150); + BusyCheck(); + LCDWriteData( display.line2[index]); + } + + break; + } + + case LCD_Read: { + struct lcd_display display; + + BusyCheck(); + for (address = kDD_R00; address <= kDD_R01; address++) { + a = (address | kLCD_Addr ); + + udelay(150); + BusyCheck(); + LCDWriteInst( a ); + udelay(150); + BusyCheck(); + display.line1[address] = LCDReadData; + } + + display.line1[ 0x27 ] = '\0'; + + for (address = kDD_R10; address <= kDD_R11; address++) { + a = (address | kLCD_Addr ); + + udelay(150); + BusyCheck(); + LCDWriteInst( a ); + + udelay(150); + BusyCheck(); + display.line2[address - 0x40 ] = LCDReadData; + } + + display.line2[ 0x27 ] = '\0'; + + if(copy_to_user((struct lcd_display*)arg, &display, + sizeof(struct lcd_display))) + return -EFAULT; + break; + } + +// set all GPIO leds to led_display.leds + + case LED_Set: { + struct lcd_display led_display; + + + if(copy_from_user(&led_display, (struct lcd_display*)arg, + sizeof(struct lcd_display))) + return -EFAULT; + + led_state = led_display.leds; + LEDSet(led_state); + + break; + } + + +// set only bit led_display.leds + + case LED_Bit_Set: { + int i; + int bit=1; + struct lcd_display led_display; + + + if(copy_from_user(&led_display, (struct lcd_display*)arg, + sizeof(struct lcd_display))) + return -EFAULT; + + for (i=0;i<(int)led_display.leds;i++) + { + bit = 2*bit; + } + + led_state = led_state | bit; + LEDSet(led_state); + break; + } + +// clear only bit led_display.leds + + case LED_Bit_Clear: { + int i; + int bit=1; + struct lcd_display led_display; + + + if(copy_from_user(&led_display, (struct lcd_display*)arg, + sizeof(struct lcd_display))) + return -EFAULT; + + for (i=0;i<(int)led_display.leds;i++) + { + bit = 2*bit; + } + + led_state = led_state & ~bit; + LEDSet(led_state); + break; + } + + + case BUTTON_Read: { + button_display.buttons = GPIRead; + if(copy_to_user((struct lcd_display*)arg, &button_display, sizeof(struct lcd_display))) + return -EFAULT; + break; + } + + case LINK_Check: { + button_display.buttons = *((volatile unsigned long *) (0xB0100060) ); + if(copy_to_user((struct lcd_display*)arg, &button_display, sizeof(struct lcd_display))) + return -EFAULT; + break; + } + + case LINK_Check_2: { + int iface_num; + + /* panel-utils should pass in the desired interface status is wanted for + * in "buttons" of the structure. We will set this to non-zero if the + * link is in fact up for the requested interface. --DaveM + */ + if(copy_from_user(&button_display, (struct lcd_display *)arg, sizeof(button_display))) + return -EFAULT; + iface_num = button_display.buttons; +#if defined(CONFIG_TULIP) && 0 + if (iface_num >= 0 && + iface_num < MAX_INTERFACES && + linkcheck_callbacks[iface_num] != NULL) { + button_display.buttons = + linkcheck_callbacks[iface_num](linkcheck_cookies[iface_num]); + } else +#endif + button_display.buttons = 0; + + if(__copy_to_user((struct lcd_display*)arg, &button_display, sizeof(struct lcd_display))) + return -EFAULT; + break; + } + +// Erase the flash + + case FLASH_Erase: { + + int ctr=0; + + // Chip Erase Sequence + WRITE_FLASH( kFlash_Addr1, kFlash_Data1 ); + WRITE_FLASH( kFlash_Addr2, kFlash_Data2 ); + WRITE_FLASH( kFlash_Addr1, kFlash_Erase3 ); + WRITE_FLASH( kFlash_Addr1, kFlash_Data1 ); + WRITE_FLASH( kFlash_Addr2, kFlash_Data2 ); + WRITE_FLASH( kFlash_Addr1, kFlash_Erase6 ); + + printk( "Erasing Flash.\n"); + + while ( (!dqpoll(0x00000000,0xFF)) && (!timeout(0x00000000)) ) { + ctr++; + } + + printk("\n"); + printk("\n"); + printk("\n"); + + if (READ_FLASH(0x07FFF0)==0xFF) { printk("Erase Successful\r\n"); } + else if (timeout) { printk("Erase Timed Out\r\n"); } + + break; + } + +// burn the flash + + case FLASH_Burn: { + + volatile unsigned long burn_addr; + unsigned long flags; + int i; + unsigned char *rom; + + + struct lcd_display display; + + if(copy_from_user(&display, (struct lcd_display*)arg, sizeof(struct lcd_display))) + return -EFAULT; + rom = (unsigned char *) kmalloc((128),GFP_ATOMIC); + if ( rom == NULL ) { + printk ("broken\n"); + return 1; + } + + printk("Churning and Burning -"); + save_flags(flags); + for (i=0; iRomImage[0]); + + if(!access_ok(VERIFY_WRITE, user_bytes, FLASH_SIZE)) + return -EFAULT; + + printk("Reading Flash"); + for (i=0; i 0) + return -EINVAL; + + lcd_waiters++; + while(((buttons_now = (long)button_pressed()) == 0) && + !(signal_pending(current))) { + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(2 * HZ); + } + lcd_waiters--; + + if(signal_pending(current)) + return -ERESTARTSYS; + return buttons_now; +} + +/* + * The various file operations we support. + */ + +static struct file_operations lcd_fops = { + read: lcd_read, + ioctl: lcd_ioctl, + open: lcd_open, +}; + +static struct miscdevice lcd_dev= +{ + LCD_MINOR, + "lcd", + &lcd_fops +}; + +int lcd_init(void) +{ +unsigned long data; + + printk("%s\n", LCD_DRIVER); + misc_register(&lcd_dev); + + /* Check region? Naaah! Just snarf it up. */ +/* request_region(RTC_PORT(0), RTC_IO_EXTENT, "lcd");*/ + + udelay(150); + data = LCDReadData; + if ( (data & 0x000000FF) == (0x00) ) { + lcd_present = 0; + printk("LCD Not Present\n"); + } + else { + lcd_present = 1; + WRITE_GAL( kGal_DevBank2PReg, kGal_DevBank2Cfg ); + WRITE_GAL( kGal_DevBank3PReg, kGal_DevBank3Cfg ); + } + + return 0; +} + + +// +// Function: dqpoll +// +// Description: Polls the data lines to see if the flash is busy +// +// In: address, byte data +// +// Out: 0 = busy, 1 = write or erase complete +// +// + +int dqpoll( volatile unsigned long address, volatile unsigned char data ) { + +volatile unsigned char dq7; + +dq7 = data & 0x80; + +return ( (READ_FLASH(address) & 0x80) == dq7 ); + +} + + +// +// Function: timeout +// +// Description: Checks to see if erase or write has timed out +// By polling dq5 +// +// In: address +// +// +// Out: 0 = not timed out, 1 = timed out + +int timeout( volatile unsigned long address ) { + + +return ( (READ_FLASH(address) & 0x20) == 0x20 ); + +} + + + diff -Nru a/drivers/char/n_tty.c b/drivers/char/n_tty.c --- a/drivers/char/n_tty.c Tue Jul 1 18:44:31 2003 +++ b/drivers/char/n_tty.c Tue Jul 1 18:44:31 2003 @@ -325,7 +325,7 @@ { if (tty->erasing) { put_char('/', tty); - tty->column += 2; + tty->column++; tty->erasing = 0; } } diff -Nru a/drivers/char/watchdog/mixcomwd.c b/drivers/char/watchdog/mixcomwd.c --- a/drivers/char/watchdog/mixcomwd.c Tue Jul 1 18:44:33 2003 +++ b/drivers/char/watchdog/mixcomwd.c Tue Jul 1 18:44:33 2003 @@ -95,7 +95,12 @@ mixcomwd_ping(); if (nowayout) { - MOD_INC_USE_COUNT; + /* + * fops_get() code via open() has already done + * a try_module_get() so it is safe to do the + * __module_get(). + */ + __module_get(THIS_MODULE); } else { if(mixcomwd_timer_alive) { del_timer(&mixcomwd_timer); @@ -211,30 +216,34 @@ { int id; - if(check_region(port+MIXCOM_WATCHDOG_OFFSET,1)) { + port += MIXCOM_WATCHDOG_OFFSET; + if (!request_region(port, 1, "MixCOM watchdog")) { return 0; } - id=inb_p(port + MIXCOM_WATCHDOG_OFFSET) & 0x3f; + id=inb_p(port) & 0x3f; if(id!=MIXCOM_ID) { + release_region(port, 1); return 0; } - return 1; + return port; } static int __init flashcom_checkcard(int port) { int id; - if(check_region(port + FLASHCOM_WATCHDOG_OFFSET,1)) { + port += FLASHCOM_WATCHDOG_OFFSET; + if (!request_region(port, 1, "MixCOM watchdog")) { return 0; } - id=inb_p(port + FLASHCOM_WATCHDOG_OFFSET); + id=inb_p(port); if(id!=FLASHCOM_ID) { + release_region(port, 1); return 0; } - return 1; + return port; } static int __init mixcomwd_init(void) @@ -244,17 +253,17 @@ int found=0; for (i = 0; !found && mixcomwd_ioports[i] != 0; i++) { - if (mixcomwd_checkcard(mixcomwd_ioports[i])) { + watchdog_port = mixcomwd_checkcard(mixcomwd_ioports[i]); + if (watchdog_port) { found = 1; - watchdog_port = mixcomwd_ioports[i] + MIXCOM_WATCHDOG_OFFSET; } } /* The FlashCOM card can be set up at 0x300 -> 0x378, in 0x8 jumps */ for (i = 0x300; !found && i < 0x380; i+=0x8) { - if (flashcom_checkcard(i)) { + watchdog_port = flashcom_checkcard(i); + if (watchdog_port) { found = 1; - watchdog_port = i + FLASHCOM_WATCHDOG_OFFSET; } } @@ -263,9 +272,6 @@ return -ENODEV; } - if (!request_region(watchdog_port,1,"MixCOM watchdog")) - return -EIO; - ret = misc_register(&mixcomwd_miscdev); if (ret) { diff -Nru a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig --- a/drivers/i2c/Kconfig Tue Jul 1 18:44:33 2003 +++ b/drivers/i2c/Kconfig Tue Jul 1 18:44:33 2003 @@ -42,6 +42,26 @@ . The module will be called i2c-algo-bit. +config I2C_PROSAVAGE + tristate "S3/VIA (Pro)Savage" + depends on I2C_ALGOBIT && PCI && EXPERIMENTAL + help + If you say yes to this option, support will be included for the + I2C bus and DDC bus of the S3VIA embedded Savage4 and ProSavage8 + graphics processors. + chipsets supported: + S3/VIA KM266/VT8375 aka ProSavage8 + S3/VIA KM133/VT8365 aka Savage4 + + This can also be built as a module which can be inserted and removed + while the kernel is running. If you want to compile it as a module, + say M here and read . + The module will be called i2c-prosavage. + + You will also need the latest user-space utilties: you can find them + in the lm_sensors package, which you can download at + http://www.lm-sensors.nu + config I2C_PHILIPSPAR tristate "Philips style parallel port adapter" depends on I2C_ALGOBIT && PARPORT diff -Nru a/drivers/i2c/Makefile b/drivers/i2c/Makefile --- a/drivers/i2c/Makefile Tue Jul 1 18:44:31 2003 +++ b/drivers/i2c/Makefile Tue Jul 1 18:44:31 2003 @@ -5,6 +5,7 @@ obj-$(CONFIG_I2C) += i2c-core.o obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o obj-$(CONFIG_I2C_ALGOBIT) += i2c-algo-bit.o +obj-$(CONFIG_I2C_PROSAVAGE) += i2c-prosavage.o obj-$(CONFIG_I2C_PHILIPSPAR) += i2c-philips-par.o obj-$(CONFIG_I2C_ELV) += i2c-elv.o obj-$(CONFIG_I2C_VELLEMAN) += i2c-velleman.o diff -Nru a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig --- a/drivers/i2c/busses/Kconfig Tue Jul 1 18:44:37 2003 +++ b/drivers/i2c/busses/Kconfig Tue Jul 1 18:44:37 2003 @@ -4,6 +4,22 @@ menu "I2C Hardware Sensors Mainboard support" +config I2C_ALI1535 + tristate " ALI 1535" + depends on I2C && PCI && EXPERIMENTAL + help + If you say yes to this option, support will be included for the SMB + Host controller on Acer Labs Inc. (ALI) M1535 South Bridges. The SMB + controller is part of the 7101 device, which is an ACPI-compliant + Power Management Unit (PMU). + + This can also be built as a module. If so, the module will be + called i2c-ali1535. + + You will also need the latest user-space utilties: you can find them + in the lm_sensors package, which you can download at + http://www.lm-sensors.nu + config I2C_ALI15X3 tristate " ALI 15x3" depends on I2C && PCI && EXPERIMENTAL diff -Nru a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile --- a/drivers/i2c/busses/Makefile Tue Jul 1 18:44:31 2003 +++ b/drivers/i2c/busses/Makefile Tue Jul 1 18:44:31 2003 @@ -2,6 +2,7 @@ # Makefile for the kernel hardware sensors bus drivers. # +obj-$(CONFIG_I2C_ALI1535) += i2c-ali1535.o obj-$(CONFIG_I2C_ALI15X3) += i2c-ali15x3.o obj-$(CONFIG_I2C_AMD756) += i2c-amd756.o obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o diff -Nru a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/i2c/busses/i2c-ali1535.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,555 @@ +/* + i2c-ali1535.c - Part of lm_sensors, Linux kernel modules for hardware + monitoring + Copyright (c) 2000 Frodo Looijaard , + Philip Edelbrock , + Mark D. Studebaker , + Dan Eaton and + Stephen Rousset + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + This is the driver for the SMB Host controller on + Acer Labs Inc. (ALI) M1535 South Bridge. + + The M1535 is a South bridge for portable systems. + It is very similar to the M15x3 South bridges also produced + by Acer Labs Inc. Some of the registers within the part + have moved and some have been redefined slightly. Additionally, + the sequencing of the SMBus transactions has been modified + to be more consistent with the sequencing recommended by + the manufacturer and observed through testing. These + changes are reflected in this driver and can be identified + by comparing this driver to the i2c-ali15x3 driver. + For an overview of these chips see http://www.acerlabs.com + + The SMB controller is part of the 7101 device, which is an + ACPI-compliant Power Management Unit (PMU). + + The whole 7101 device has to be enabled for the SMB to work. + You can't just enable the SMB alone. + The SMB and the ACPI have separate I/O spaces. + We make sure that the SMB is enabled. We leave the ACPI alone. + + This driver controls the SMB Host only. + + This driver does not use interrupts. +*/ + + +/* Note: we assume there can only be one ALI1535, with one SMBus interface */ + +/* #define DEBUG 1 */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* ALI1535 SMBus address offsets */ +#define SMBHSTSTS (0 + ali1535_smba) +#define SMBHSTTYP (1 + ali1535_smba) +#define SMBHSTPORT (2 + ali1535_smba) +#define SMBHSTCMD (7 + ali1535_smba) +#define SMBHSTADD (3 + ali1535_smba) +#define SMBHSTDAT0 (4 + ali1535_smba) +#define SMBHSTDAT1 (5 + ali1535_smba) +#define SMBBLKDAT (6 + ali1535_smba) + +/* PCI Address Constants */ +#define SMBCOM 0x004 +#define SMBREV 0x008 +#define SMBCFG 0x0D1 +#define SMBBA 0x0E2 +#define SMBHSTCFG 0x0F0 +#define SMBCLK 0x0F2 + +/* Other settings */ +#define MAX_TIMEOUT 500 /* times 1/100 sec */ +#define ALI1535_SMB_IOSIZE 32 + +#define ALI1535_SMB_DEFAULTBASE 0x8040 + +/* ALI1535 address lock bits */ +#define ALI1535_LOCK 0x06 /* dwe */ + +/* ALI1535 command constants */ +#define ALI1535_QUICK 0x00 +#define ALI1535_BYTE 0x10 +#define ALI1535_BYTE_DATA 0x20 +#define ALI1535_WORD_DATA 0x30 +#define ALI1535_BLOCK_DATA 0x40 +#define ALI1535_I2C_READ 0x60 + +#define ALI1535_DEV10B_EN 0x80 /* Enable 10-bit addressing in */ + /* I2C read */ +#define ALI1535_T_OUT 0x08 /* Time-out Command (write) */ +#define ALI1535_A_HIGH_BIT9 0x08 /* Bit 9 of 10-bit address in */ + /* Alert-Response-Address */ + /* (read) */ +#define ALI1535_KILL 0x04 /* Kill Command (write) */ +#define ALI1535_A_HIGH_BIT8 0x04 /* Bit 8 of 10-bit address in */ + /* Alert-Response-Address */ + /* (read) */ + +#define ALI1535_D_HI_MASK 0x03 /* Mask for isolating bits 9-8 */ + /* of 10-bit address in I2C */ + /* Read Command */ + +/* ALI1535 status register bits */ +#define ALI1535_STS_IDLE 0x04 +#define ALI1535_STS_BUSY 0x08 /* host busy */ +#define ALI1535_STS_DONE 0x10 /* transaction complete */ +#define ALI1535_STS_DEV 0x20 /* device error */ +#define ALI1535_STS_BUSERR 0x40 /* bus error */ +#define ALI1535_STS_FAIL 0x80 /* failed bus transaction */ +#define ALI1535_STS_ERR 0xE0 /* all the bad error bits */ + +#define ALI1535_BLOCK_CLR 0x04 /* reset block data index */ + +/* ALI1535 device address register bits */ +#define ALI1535_RD_ADDR 0x01 /* Read/Write Bit in Device */ + /* Address field */ + /* -> Write = 0 */ + /* -> Read = 1 */ +#define ALI1535_SMBIO_EN 0x04 /* SMB I/O Space enable */ + + +static unsigned short ali1535_smba; +DECLARE_MUTEX(i2c_ali1535_sem); + +/* Detect whether a ALI1535 can be found, and initialize it, where necessary. + Note the differences between kernels with the old PCI BIOS interface and + newer kernels with the real PCI interface. In compat.h some things are + defined to make the transition easier. */ +static int ali1535_setup(struct pci_dev *dev) +{ + int retval = -ENODEV; + unsigned char temp; + + /* Check the following things: + - SMB I/O address is initialized + - Device is enabled + - We can use the addresses + */ + + /* Determine the address of the SMBus area */ + pci_read_config_word(dev, SMBBA, &ali1535_smba); + ali1535_smba &= (0xffff & ~(ALI1535_SMB_IOSIZE - 1)); + if (ali1535_smba == 0) { + dev_warn(&dev->dev, + "ALI1535_smb region uninitialized - upgrade BIOS?\n"); + goto exit; + } + + if (!request_region(ali1535_smba, ALI1535_SMB_IOSIZE, "ali1535-smb")) { + dev_err(&dev->dev, "ALI1535_smb region 0x%x already in use!\n", + ali1535_smba); + goto exit; + } + + /* check if whole device is enabled */ + pci_read_config_byte(dev, SMBCFG, &temp); + if ((temp & ALI1535_SMBIO_EN) == 0) { + dev_err(&dev->dev, "SMB device not enabled - upgrade BIOS?\n"); + goto exit_free; + } + + /* Is SMB Host controller enabled? */ + pci_read_config_byte(dev, SMBHSTCFG, &temp); + if ((temp & 1) == 0) { + dev_err(&dev->dev, "SMBus controller not enabled - upgrade BIOS?\n"); + goto exit_free; + } + + /* set SMB clock to 74KHz as recommended in data sheet */ + pci_write_config_byte(dev, SMBCLK, 0x20); + + /* + The interrupt routing for SMB is set up in register 0x77 in the + 1533 ISA Bridge device, NOT in the 7101 device. + Don't bother with finding the 1533 device and reading the register. + if ((....... & 0x0F) == 1) + dev_dbg(&dev->dev, "ALI1535 using Interrupt 9 for SMBus.\n"); + */ + pci_read_config_byte(dev, SMBREV, &temp); + dev_dbg(&dev->dev, "SMBREV = 0x%X\n", temp); + dev_dbg(&dev->dev, "ALI1535_smba = 0x%X\n", ali1535_smba); + + retval = 0; +exit: + return retval; + +exit_free: + release_region(ali1535_smba, ALI1535_SMB_IOSIZE); + return retval; +} + +static void ali1535_do_pause(unsigned int amount) +{ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(amount); +} + +static int ali1535_transaction(struct i2c_adapter *adap) +{ + int temp; + int result = 0; + int timeout = 0; + + dev_dbg(&adap->dev, "Transaction (pre): STS=%02x, TYP=%02x, " + "CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n", + inb_p(SMBHSTSTS), inb_p(SMBHSTTYP), inb_p(SMBHSTCMD), + inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); + + /* get status */ + temp = inb_p(SMBHSTSTS); + + /* Make sure the SMBus host is ready to start transmitting */ + /* Check the busy bit first */ + if (temp & ALI1535_STS_BUSY) { + /* If the host controller is still busy, it may have timed out + * in the previous transaction, resulting in a "SMBus Timeout" + * printk. I've tried the following to reset a stuck busy bit. + * 1. Reset the controller with an KILL command. (this + * doesn't seem to clear the controller if an external + * device is hung) + * 2. Reset the controller and the other SMBus devices with a + * T_OUT command. (this clears the host busy bit if an + * external device is hung, but it comes back upon a new + * access to a device) + * 3. Disable and reenable the controller in SMBHSTCFG. Worst + * case, nothing seems to work except power reset. + */ + + /* Try resetting entire SMB bus, including other devices - This + * may not work either - it clears the BUSY bit but then the + * BUSY bit may come back on when you try and use the chip + * again. If that's the case you are stuck. + */ + dev_info(&adap->dev, + "Resetting entire SMB Bus to clear busy condition (%02x)\n", + temp); + outb_p(ALI1535_T_OUT, SMBHSTTYP); + temp = inb_p(SMBHSTSTS); + } + + /* now check the error bits and the busy bit */ + if (temp & (ALI1535_STS_ERR | ALI1535_STS_BUSY)) { + /* do a clear-on-write */ + outb_p(0xFF, SMBHSTSTS); + if ((temp = inb_p(SMBHSTSTS)) & + (ALI1535_STS_ERR | ALI1535_STS_BUSY)) { + /* This is probably going to be correctable only by a + * power reset as one of the bits now appears to be + * stuck */ + /* This may be a bus or device with electrical problems. */ + dev_err(&adap->dev, + "SMBus reset failed! (0x%02x) - controller or " + "device on bus is probably hung\n", temp); + return -1; + } + } else { + /* check and clear done bit */ + if (temp & ALI1535_STS_DONE) { + outb_p(temp, SMBHSTSTS); + } + } + + /* start the transaction by writing anything to the start register */ + outb_p(0xFF, SMBHSTPORT); + + /* We will always wait for a fraction of a second! */ + timeout = 0; + do { + ali1535_do_pause(1); + temp = inb_p(SMBHSTSTS); + } while (((temp & ALI1535_STS_BUSY) && !(temp & ALI1535_STS_IDLE)) + && (timeout++ < MAX_TIMEOUT)); + + /* If the SMBus is still busy, we give up */ + if (timeout >= MAX_TIMEOUT) { + result = -1; + dev_err(&adap->dev, "SMBus Timeout!\n"); + } + + if (temp & ALI1535_STS_FAIL) { + result = -1; + dev_dbg(&adap->dev, "Error: Failed bus transaction\n"); + } + + /* Unfortunately the ALI SMB controller maps "no response" and "bus + * collision" into a single bit. No reponse is the usual case so don't + * do a printk. This means that bus collisions go unreported. + */ + if (temp & ALI1535_STS_BUSERR) { + result = -1; + dev_dbg(&adap->dev, + "Error: no response or bus collision ADD=%02x\n", + inb_p(SMBHSTADD)); + } + + /* haven't ever seen this */ + if (temp & ALI1535_STS_DEV) { + result = -1; + dev_err(&adap->dev, "Error: device error\n"); + } + + /* check to see if the "command complete" indication is set */ + if (!(temp & ALI1535_STS_DONE)) { + result = -1; + dev_err(&adap->dev, "Error: command never completed\n"); + } + + dev_dbg(&adap->dev, "Transaction (post): STS=%02x, TYP=%02x, " + "CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n", + inb_p(SMBHSTSTS), inb_p(SMBHSTTYP), inb_p(SMBHSTCMD), + inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); + + /* take consequent actions for error conditions */ + if (!(temp & ALI1535_STS_DONE)) { + /* issue "kill" to reset host controller */ + outb_p(ALI1535_KILL,SMBHSTTYP); + outb_p(0xFF,SMBHSTSTS); + } else if (temp & ALI1535_STS_ERR) { + /* issue "timeout" to reset all devices on bus */ + outb_p(ALI1535_T_OUT,SMBHSTTYP); + outb_p(0xFF,SMBHSTSTS); + } + + return result; +} + +/* Return -1 on error. */ +static s32 ali1535_access(struct i2c_adapter *adap, u16 addr, + unsigned short flags, char read_write, u8 command, + int size, union i2c_smbus_data *data) +{ + int i, len; + int temp; + int timeout; + s32 result = 0; + + down(&i2c_ali1535_sem); + /* make sure SMBus is idle */ + temp = inb_p(SMBHSTSTS); + for (timeout = 0; + (timeout < MAX_TIMEOUT) && !(temp & ALI1535_STS_IDLE); + timeout++) { + ali1535_do_pause(1); + temp = inb_p(SMBHSTSTS); + } + if (timeout >= MAX_TIMEOUT) + dev_warn(&adap->dev, "Idle wait Timeout! STS=0x%02x\n", temp); + + /* clear status register (clear-on-write) */ + outb_p(0xFF, SMBHSTSTS); + + switch (size) { + case I2C_SMBUS_PROC_CALL: + dev_err(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n"); + result = -1; + goto EXIT; + case I2C_SMBUS_QUICK: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + size = ALI1535_QUICK; + outb_p(size, SMBHSTTYP); /* output command */ + break; + case I2C_SMBUS_BYTE: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + size = ALI1535_BYTE; + outb_p(size, SMBHSTTYP); /* output command */ + if (read_write == I2C_SMBUS_WRITE) + outb_p(command, SMBHSTCMD); + break; + case I2C_SMBUS_BYTE_DATA: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + size = ALI1535_BYTE_DATA; + outb_p(size, SMBHSTTYP); /* output command */ + outb_p(command, SMBHSTCMD); + if (read_write == I2C_SMBUS_WRITE) + outb_p(data->byte, SMBHSTDAT0); + break; + case I2C_SMBUS_WORD_DATA: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + size = ALI1535_WORD_DATA; + outb_p(size, SMBHSTTYP); /* output command */ + outb_p(command, SMBHSTCMD); + if (read_write == I2C_SMBUS_WRITE) { + outb_p(data->word & 0xff, SMBHSTDAT0); + outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1); + } + break; + case I2C_SMBUS_BLOCK_DATA: + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), + SMBHSTADD); + size = ALI1535_BLOCK_DATA; + outb_p(size, SMBHSTTYP); /* output command */ + outb_p(command, SMBHSTCMD); + if (read_write == I2C_SMBUS_WRITE) { + len = data->block[0]; + if (len < 0) { + len = 0; + data->block[0] = len; + } + if (len > 32) { + len = 32; + data->block[0] = len; + } + outb_p(len, SMBHSTDAT0); + /* Reset SMBBLKDAT */ + outb_p(inb_p(SMBHSTTYP) | ALI1535_BLOCK_CLR, SMBHSTTYP); + for (i = 1; i <= len; i++) + outb_p(data->block[i], SMBBLKDAT); + } + break; + } + + if (ali1535_transaction(adap)) { + /* Error in transaction */ + result = -1; + goto EXIT; + } + + if ((read_write == I2C_SMBUS_WRITE) || (size == ALI1535_QUICK)) { + result = 0; + goto EXIT; + } + + switch (size) { + case ALI1535_BYTE: /* Result put in SMBHSTDAT0 */ + data->byte = inb_p(SMBHSTDAT0); + break; + case ALI1535_BYTE_DATA: + data->byte = inb_p(SMBHSTDAT0); + break; + case ALI1535_WORD_DATA: + data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8); + break; + case ALI1535_BLOCK_DATA: + len = inb_p(SMBHSTDAT0); + if (len > 32) + len = 32; + data->block[0] = len; + /* Reset SMBBLKDAT */ + outb_p(inb_p(SMBHSTTYP) | ALI1535_BLOCK_CLR, SMBHSTTYP); + for (i = 1; i <= data->block[0]; i++) { + data->block[i] = inb_p(SMBBLKDAT); + dev_dbg(&adap->dev, "Blk: len=%d, i=%d, data=%02x\n", + len, i, data->block[i]); + } + break; + } +EXIT: + up(&i2c_ali1535_sem); + return result; +} + + +u32 ali1535_func(struct i2c_adapter *adapter) +{ + return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_BLOCK_DATA; +} + +static struct i2c_algorithm smbus_algorithm = { + .name = "Non-i2c SMBus adapter", + .id = I2C_ALGO_SMBUS, + .smbus_xfer = ali1535_access, + .functionality = ali1535_func, +}; + +static struct i2c_adapter ali1535_adapter = { + .owner = THIS_MODULE, + .id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_ALI1535, + .algo = &smbus_algorithm, + .dev = { + .name = "unset", + } +}; + +static struct pci_device_id ali1535_ids[] __devinitdata = { + { + .vendor = PCI_VENDOR_ID_AL, + .device = PCI_DEVICE_ID_AL_M7101, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + { }, +}; + +static int __devinit ali1535_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + if (ali1535_setup(dev)) { + dev_warn(&dev->dev, + "ALI1535 not detected, module not inserted.\n"); + return -ENODEV; + } + + /* set up the driverfs linkage to our parent device */ + ali1535_adapter.dev.parent = &dev->dev; + + snprintf(ali1535_adapter.dev.name, DEVICE_NAME_SIZE, + "SMBus ALI1535 adapter at %04x", ali1535_smba); + return i2c_add_adapter(&ali1535_adapter); +} + +static void __devexit ali1535_remove(struct pci_dev *dev) +{ + i2c_del_adapter(&ali1535_adapter); +} + +static struct pci_driver ali1535_driver = { + .name = "ali1535_smbus", + .id_table = ali1535_ids, + .probe = ali1535_probe, + .remove = __devexit_p(ali1535_remove), +}; + +static int __init i2c_ali1535_init(void) +{ + printk(KERN_INFO "i2c-ali1535 version %s (%s)\n", I2C_VERSION, I2C_DATE); + return pci_module_init(&ali1535_driver); +} + +static void __exit i2c_ali1535_exit(void) +{ + pci_unregister_driver(&ali1535_driver); + release_region(ali1535_smba, ALI1535_SMB_IOSIZE); +} + +MODULE_AUTHOR("Frodo Looijaard , " + "Philip Edelbrock , " + "Mark D. Studebaker " + "and Dan Eaton "); +MODULE_DESCRIPTION("ALI1535 SMBus driver"); +MODULE_LICENSE("GPL"); + +module_init(i2c_ali1535_init); +module_exit(i2c_ali1535_exit); diff -Nru a/drivers/i2c/i2c-prosavage.c b/drivers/i2c/i2c-prosavage.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/i2c/i2c-prosavage.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,362 @@ +/* + * kernel/busses/i2c-prosavage.c + * + * i2c bus driver for S3/VIA 8365/8375 graphics processor. + * Copyright (c) 2003 Henk Vergonet + * Based on code written by: + * Frodo Looijaard , + * Philip Edelbrock , + * Ralph Metzler , and + * Mark D. Studebaker + * Simon Vogl + * and others + * + * Please read the lm_sensors documentation for details on use. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +/* 18-05-2003 HVE - created + * 14-06-2003 HVE - adapted for lm_sensors2 + * 17-06-2003 HVE - linux 2.5.xx compatible + * 18-06-2003 HVE - codingstyle + * 21-06-2003 HVE - compatibility lm_sensors2 and linux 2.5.xx + * codingstyle, mmio enabled + * + * This driver interfaces to the I2C bus of the VIA north bridge embedded + * ProSavage4/8 devices. Usefull for gaining access to the TV Encoder chips. + * + * Graphics cores: + * S3/VIA KM266/VT8375 aka ProSavage8 + * S3/VIA KM133/VT8365 aka Savage4 + * + * Two serial busses are implemented: + * SERIAL1 - I2C serial communications interface + * SERIAL2 - DDC2 monitor communications interface + * + * Tested on a FX41 mainboard, see http://www.shuttle.com + * + * + * TODO: + * - integration with prosavage framebuffer device + * (Additional documentation needed :( + */ + +#include +#include +#include +#include +#include +#include + +#include + + +/* + * driver configuration + */ +#define DRIVER_ID "i2c-prosavage" +#define DRIVER_VERSION "20030621" + +/* lm_sensors2 / kernel 2.5.xx compatibility */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) +#define ADAPTER_NAME(x) (x).name +#else +#define ADAPTER_NAME(x) (x).dev.name +#endif /* LINUX_VERSION_CODE */ + +#define MAX_BUSSES 2 + +struct s_i2c_bus { + u8 *mmvga; + int i2c_reg; + int adap_ok; + struct i2c_adapter adap; + struct i2c_algo_bit_data algo; +}; + +struct s_i2c_chip { + u8 *mmio; + struct s_i2c_bus i2c_bus[MAX_BUSSES]; +}; + + +/* + * i2c configuration + */ +#ifndef I2C_HW_B_S3VIA +#define I2C_HW_B_S3VIA 0x18 /* S3VIA ProSavage adapter */ +#endif + +/* delays */ +#define CYCLE_DELAY 10 +#define TIMEOUT (HZ / 2) + + +/* + * S3/VIA 8365/8375 registers + */ +#ifndef PCI_VENDOR_ID_S3 +#define PCI_VENDOR_ID_S3 0x5333 +#endif +#ifndef PCI_DEVICE_ID_S3_SAVAGE4 +#define PCI_DEVICE_ID_S3_SAVAGE4 0x8a25 +#endif +#ifndef PCI_DEVICE_ID_S3_PROSAVAGE8 +#define PCI_DEVICE_ID_S3_PROSAVAGE8 0x8d04 +#endif + +#define VGA_CR_IX 0x3d4 +#define VGA_CR_DATA 0x3d5 + +#define CR_SERIAL1 0xa0 /* I2C serial communications interface */ +#define MM_SERIAL1 0xff20 +#define CR_SERIAL2 0xb1 /* DDC2 monitor communications interface */ + +/* based on vt8365 documentation */ +#define I2C_ENAB 0x10 +#define I2C_SCL_OUT 0x01 +#define I2C_SDA_OUT 0x02 +#define I2C_SCL_IN 0x04 +#define I2C_SDA_IN 0x08 + +#define SET_CR_IX(p, val) *((p)->mmvga + VGA_CR_IX) = (u8)(val) +#define SET_CR_DATA(p, val) *((p)->mmvga + VGA_CR_DATA) = (u8)(val) +#define GET_CR_DATA(p) *((p)->mmvga + VGA_CR_DATA) + + +/* + * Serial bus line handling + * + * serial communications register as parameter in private data + * + * TODO: locks with other code sections accessing video registers? + */ +static void bit_s3via_setscl(void *bus, int val) +{ + struct s_i2c_bus *p = (struct s_i2c_bus *)bus; + unsigned int r; + + SET_CR_IX(p, p->i2c_reg); + r = GET_CR_DATA(p); + r |= I2C_ENAB; + if (val) { + r |= I2C_SCL_OUT; + } else { + r &= ~I2C_SCL_OUT; + } + SET_CR_DATA(p, r); +} + +static void bit_s3via_setsda(void *bus, int val) +{ + struct s_i2c_bus *p = (struct s_i2c_bus *)bus; + unsigned int r; + + SET_CR_IX(p, p->i2c_reg); + r = GET_CR_DATA(p); + r |= I2C_ENAB; + if (val) { + r |= I2C_SDA_OUT; + } else { + r &= ~I2C_SDA_OUT; + } + SET_CR_DATA(p, r); +} + +static int bit_s3via_getscl(void *bus) +{ + struct s_i2c_bus *p = (struct s_i2c_bus *)bus; + + SET_CR_IX(p, p->i2c_reg); + return (0 != (GET_CR_DATA(p) & I2C_SCL_IN)); +} + +static int bit_s3via_getsda(void *bus) +{ + struct s_i2c_bus *p = (struct s_i2c_bus *)bus; + + SET_CR_IX(p, p->i2c_reg); + return (0 != (GET_CR_DATA(p) & I2C_SDA_IN)); +} + + +/* + * adapter initialisation + */ +static int i2c_register_bus(struct s_i2c_bus *p, u8 *mmvga, u32 i2c_reg) +{ + int ret; + p->adap.owner = THIS_MODULE; + p->adap.id = I2C_HW_B_S3VIA; + p->adap.algo_data = &p->algo; + p->algo.setsda = bit_s3via_setsda; + p->algo.setscl = bit_s3via_setscl; + p->algo.getsda = bit_s3via_getsda; + p->algo.getscl = bit_s3via_getscl; + p->algo.udelay = CYCLE_DELAY; + p->algo.mdelay = CYCLE_DELAY; + p->algo.timeout = TIMEOUT; + p->algo.data = p; + p->mmvga = mmvga; + p->i2c_reg = i2c_reg; + + ret = i2c_bit_add_bus(&p->adap); + if (ret) { + return ret; + } + + p->adap_ok = 1; + return 0; +} + + +/* + * Cleanup stuff + */ +static void __devexit prosavage_remove(struct pci_dev *dev) +{ + struct s_i2c_chip *chip; + int i, ret; + + chip = (struct s_i2c_chip *)pci_get_drvdata(dev); + + if (!chip) { + return; + } + for (i = MAX_BUSSES - 1; i >= 0; i--) { + if (chip->i2c_bus[i].adap_ok == 0) + continue; + + ret = i2c_bit_del_bus(&chip->i2c_bus[i].adap); + if (ret) { + printk(DRIVER_ID ": %s not removed\n", + ADAPTER_NAME(chip->i2c_bus[i].adap)); + } + } + if (chip->mmio) { + iounmap(chip->mmio); + } + kfree(chip); +} + + +/* + * Detect chip and initialize it + */ +static int __devinit prosavage_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + int ret; + unsigned long base, len; + struct s_i2c_chip *chip; + struct s_i2c_bus *bus; + + pci_set_drvdata(dev, kmalloc(sizeof(struct s_i2c_chip), GFP_KERNEL)); + chip = (struct s_i2c_chip *)pci_get_drvdata(dev); + if (chip == NULL) { + return -ENOMEM; + } + + memset(chip, 0, sizeof(struct s_i2c_chip)); + + base = dev->resource[0].start & PCI_BASE_ADDRESS_MEM_MASK; + len = dev->resource[0].end - base + 1; + chip->mmio = ioremap_nocache(base, len); + + if (chip->mmio == NULL) { + printk (DRIVER_ID ": ioremap failed\n"); + prosavage_remove(dev); + return -ENODEV; + } + + + /* + * Chip initialisation + */ + /* Unlock Extended IO Space ??? */ + + + /* + * i2c bus registration + */ + bus = &chip->i2c_bus[0]; + snprintf(ADAPTER_NAME(bus->adap), sizeof(ADAPTER_NAME(bus->adap)), + "ProSavage I2C bus at %02x:%02x.%x", + dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); + ret = i2c_register_bus(bus, chip->mmio + 0x8000, CR_SERIAL1); + if (ret) { + goto err_adap; + } + /* + * ddc bus registration + */ + bus = &chip->i2c_bus[1]; + snprintf(ADAPTER_NAME(bus->adap), sizeof(ADAPTER_NAME(bus->adap)), + "ProSavage DDC bus at %02x:%02x.%x", + dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); + ret = i2c_register_bus(bus, chip->mmio + 0x8000, CR_SERIAL2); + if (ret) { + goto err_adap; + } + return 0; +err_adap: + printk (DRIVER_ID ": %s failed\n", ADAPTER_NAME(bus->adap)); + prosavage_remove(dev); + return ret; +} + + +/* + * Data for PCI driver interface + */ +static struct pci_device_id prosavage_pci_tbl[] __devinitdata = { + { + .vendor = PCI_VENDOR_ID_S3, + .device = PCI_DEVICE_ID_S3_SAVAGE4, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + },{ + .vendor = PCI_VENDOR_ID_S3, + .device = PCI_DEVICE_ID_S3_PROSAVAGE8, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + },{ 0, } +}; + +static struct pci_driver prosavage_driver = { + .name = "prosavage-smbus", + .id_table = prosavage_pci_tbl, + .probe = prosavage_probe, + .remove = __devexit_p(prosavage_remove), +}; + +static int __init i2c_prosavage_init(void) +{ + printk(DRIVER_ID " version %s (%s)\n", I2C_VERSION, DRIVER_VERSION); + return pci_module_init(&prosavage_driver); +} + +static void __exit i2c_prosavage_exit(void) +{ + pci_unregister_driver(&prosavage_driver); +} + +MODULE_DEVICE_TABLE(pci, prosavage_pci_tbl); +MODULE_AUTHOR("Henk Vergonet"); +MODULE_DESCRIPTION("ProSavage VIA 8365/8375 smbus driver"); +MODULE_LICENSE("GPL"); + +module_init (i2c_prosavage_init); +module_exit (i2c_prosavage_exit); diff -Nru a/drivers/ide/Kconfig b/drivers/ide/Kconfig --- a/drivers/ide/Kconfig Tue Jul 1 18:44:34 2003 +++ b/drivers/ide/Kconfig Tue Jul 1 18:44:34 2003 @@ -277,9 +277,9 @@ If you are unsure, say N here. config IDE_TASKFILE_IO - bool 'IDE Taskfile IO' - depends on BLK_DEV_IDE - default y + bool 'IDE Taskfile IO (EXPERIMENTAL)' + depends on BLK_DEV_IDE && EXPERIMENTAL + default n ---help--- Use new taskfile IO code. diff -Nru a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c --- a/drivers/ide/ide-cd.c Tue Jul 1 18:44:34 2003 +++ b/drivers/ide/ide-cd.c Tue Jul 1 18:44:34 2003 @@ -2805,7 +2805,7 @@ CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS | CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R| CDC_DVD_RAM | - CDC_GENERIC_PACKET, + CDC_GENERIC_PACKET | CDC_MO_DRIVE, .generic_packet = ide_cdrom_packet, }; @@ -2838,6 +2838,8 @@ devinfo->mask |= CDC_PLAY_AUDIO; if (!CDROM_CONFIG_FLAGS(drive)->close_tray) devinfo->mask |= CDC_CLOSE_TRAY; + if (!CDROM_CONFIG_FLAGS(drive)->mo_drive) + devinfo->mask |= CDC_MO_DRIVE; return register_cdrom(devinfo); } @@ -2884,6 +2886,7 @@ int nslots = 1; if (drive->media == ide_optical) { + CDROM_CONFIG_FLAGS(drive)->mo_drive = 1; printk("%s: ATAPI magneto-optical drive\n", drive->name); return nslots; } diff -Nru a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h --- a/drivers/ide/ide-cd.h Tue Jul 1 18:44:39 2003 +++ b/drivers/ide/ide-cd.h Tue Jul 1 18:44:39 2003 @@ -85,7 +85,8 @@ __u8 audio_play : 1; /* can do audio related commands */ __u8 close_tray : 1; /* can close the tray */ __u8 writing : 1; /* pseudo write in progress */ - __u8 reserved : 3; + __u8 mo_drive : 1; /* drive is an MO device */ + __u8 reserved : 2; byte max_speed; /* Max speed of the drive */ }; #define CDROM_CONFIG_FLAGS(drive) (&(((struct cdrom_info *)(drive->driver_data))->config_flags)) diff -Nru a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c --- a/drivers/ide/ide-dma.c Tue Jul 1 18:44:35 2003 +++ b/drivers/ide/ide-dma.c Tue Jul 1 18:44:35 2003 @@ -248,8 +248,11 @@ #if 1 if (sector_count > 256) BUG(); - + if (sector_count > 128) { +#else + while (sector_count > 128) { +#endif memset(&sg[nents], 0, sizeof(*sg)); sg[nents].page = virt_to_page(virt_addr); sg[nents].offset = (unsigned long) virt_addr & ~PAGE_MASK; @@ -263,22 +266,7 @@ sg[nents].offset = (unsigned long) virt_addr & ~PAGE_MASK; sg[nents].length = sector_count * SECTOR_SIZE; nents++; -#else - while (sector_count > 128) { - memset(&sg[nents], 0, sizeof(*sg)); - sg[nents].address = virt_to_page(virt_addr); - sg[nents].offset = (unsigned long)virt_addr & ~PAGE_MASK; - sg[nents].length = 128 * SECTOR_SIZE; - nents++; - virt_addr = virt_addr + (128 * SECTOR_SIZE); - sector_count -= 128; - }; - memset(&sg[nents], 0, sizeof(*sg)); - sg[nents].page = virt_to_page(virt_addr); - sg[nents].offset = (unsigned long) virt_addr & ~PAGE_MASK; - sg[nents].length = sector_count * SECTOR_SIZE; - nents++; -#endif + return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction); } @@ -523,8 +511,7 @@ if (HWIF(drive)->ide_dma_host_off(drive)) return 1; - if (drive->queue_setup) - HWIF(drive)->ide_dma_queued_off(drive); + HWIF(drive)->ide_dma_queued_off(drive); return 0; } @@ -585,8 +572,9 @@ if (HWIF(drive)->ide_dma_host_on(drive)) return 1; - if (drive->queue_setup) - HWIF(drive)->ide_dma_queued_on(drive); +#ifdef CONFIG_BLK_DEV_IDE_TCQ_DEFAULT + HWIF(drive)->ide_dma_queued_on(drive); +#endif return 0; } diff -Nru a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c --- a/drivers/ide/ide-io.c Tue Jul 1 18:44:37 2003 +++ b/drivers/ide/ide-io.c Tue Jul 1 18:44:37 2003 @@ -1264,7 +1264,7 @@ #endif /* CONFIG_BLK_DEV_IDEPCI */ } spin_unlock_irqrestore(&ide_lock, flags); - return IRQ_HANDLED; + return IRQ_NONE; } drive = hwgroup->drive; if (!drive) { @@ -1286,7 +1286,7 @@ * enough advance overhead that the latter isn't a problem. */ spin_unlock_irqrestore(&ide_lock, flags); - return IRQ_HANDLED; + return IRQ_NONE; } if (!hwgroup->busy) { hwgroup->busy = 1; /* paranoia */ diff -Nru a/drivers/ide/ide-pnp.c b/drivers/ide/ide-pnp.c --- a/drivers/ide/ide-pnp.c Tue Jul 1 18:44:36 2003 +++ b/drivers/ide/ide-pnp.c Tue Jul 1 18:44:36 2003 @@ -4,7 +4,7 @@ * This file provides autodetection for ISA PnP IDE interfaces. * It was tested with "ESS ES1868 Plug and Play AudioDrive" IDE interface. * - * Copyright (C) 2000 Andrey Panin + * Copyright (C) 2000 Andrey Panin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff -Nru a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c --- a/drivers/ide/ide-probe.c Tue Jul 1 18:44:35 2003 +++ b/drivers/ide/ide-probe.c Tue Jul 1 18:44:35 2003 @@ -634,64 +634,8 @@ return drive->present; } -static int hwif_check_region(ide_hwif_t *hwif, unsigned long addr, int num) -{ - int err; - - if(hwif->mmio) - err = check_mem_region(addr, num); - else - err = check_region(addr, num); - - if(err) - { - printk("%s: %s resource 0x%lX-0x%lX not free.\n", - hwif->name, hwif->mmio?"MMIO":"I/O", addr, addr+num-1); - } - return err; -} - - -/** - * hwif_check_regions - check resources for IDE - * @hwif: interface to use - * - * Checks if all the needed resources for an interface are free - * providing the interface is PIO. Right now core IDE code does - * this work which is deeply wrong. MMIO leaves it to the controller - * driver, PIO will migrate this way over time - */ - -static int hwif_check_regions (ide_hwif_t *hwif) -{ - u32 i = 0; - int addr_errs = 0; - - if (hwif->mmio == 2) - return 0; - addr_errs = hwif_check_region(hwif, hwif->io_ports[IDE_DATA_OFFSET], 1); - for (i = IDE_ERROR_OFFSET; i <= IDE_STATUS_OFFSET; i++) - addr_errs += hwif_check_region(hwif, hwif->io_ports[i], 1); - if (hwif->io_ports[IDE_CONTROL_OFFSET]) - addr_errs += hwif_check_region(hwif, hwif->io_ports[IDE_CONTROL_OFFSET], 1); -#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC) - if (hwif->io_ports[IDE_IRQ_OFFSET]) - addr_errs += hwif_check_region(hwif, hwif->io_ports[IDE_IRQ_OFFSET], 1); -#endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */ - /* If any errors are return, we drop the hwif interface. */ - hwif->straight8 = 0; - return(addr_errs); -} - -//EXPORT_SYMBOL(hwif_check_regions); - -#define hwif_request_region(addr, num, name) \ - ((hwif->mmio) ? request_mem_region((addr),(num),(name)) : request_region((addr),(num),(name))) - static void hwif_register (ide_hwif_t *hwif) { - u32 i = 0; - /* register with global device tree */ strlcpy(hwif->gendev.bus_id,hwif->name,BUS_ID_SIZE); snprintf(hwif->gendev.name,DEVICE_NAME_SIZE,"IDE Controller"); @@ -701,24 +645,6 @@ else hwif->gendev.parent = NULL; /* Would like to do = &device_legacy */ device_register(&hwif->gendev); - - if (hwif->mmio == 2) - return; - if (hwif->io_ports[IDE_CONTROL_OFFSET]) - hwif_request_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1, hwif->name); -#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC) - if (hwif->io_ports[IDE_IRQ_OFFSET]) - hwif_request_region(hwif->io_ports[IDE_IRQ_OFFSET], 1, hwif->name); -#endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */ - if (((unsigned long)hwif->io_ports[IDE_DATA_OFFSET] | 7) == - ((unsigned long)hwif->io_ports[IDE_STATUS_OFFSET])) { - hwif_request_region(hwif->io_ports[IDE_DATA_OFFSET], 8, hwif->name); - hwif->straight8 = 1; - return; - } - - for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) - hwif_request_region(hwif->io_ports[i], 1, hwif->name); } //EXPORT_SYMBOL(hwif_register); @@ -778,7 +704,7 @@ #ifdef CONFIG_BLK_DEV_PDC4030 (hwif->chipset != ide_pdc4030 || hwif->channel == 0) && #endif /* CONFIG_BLK_DEV_PDC4030 */ - (hwif_check_regions(hwif))) { + (ide_hwif_request_regions(hwif))) { u16 msgout = 0; for (unit = 0; unit < MAX_DRIVES; ++unit) { ide_drive_t *drive = &hwif->drives[unit]; @@ -869,6 +795,11 @@ if (irqd) enable_irq(irqd); + if (!hwif->present) { + ide_hwif_release_regions(hwif); + return; + } + for (unit = 0; unit < MAX_DRIVES; ++unit) { ide_drive_t *drive = &hwif->drives[unit]; int enable_dma = 1; @@ -983,7 +914,6 @@ blk_init_queue(q, do_ide_request, &ide_lock); q->queuedata = HWGROUP(drive); - drive->queue_setup = 1; blk_queue_segment_boundary(q, 0xffff); if (!hwif->rqsize) @@ -1005,10 +935,6 @@ static void ide_init_drive(ide_drive_t *drive) { ide_toggle_bounce(drive, 1); - -#ifdef CONFIG_BLK_DEV_IDE_TCQ_DEFAULT - HWIF(drive)->ide_dma_queued_on(drive); -#endif } /* diff -Nru a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c --- a/drivers/ide/ide-taskfile.c Tue Jul 1 18:44:31 2003 +++ b/drivers/ide/ide-taskfile.c Tue Jul 1 18:44:31 2003 @@ -954,6 +954,9 @@ return startstop; } + if (!drive->unmask) + local_irq_disable(); + return task_out_intr(drive); } EXPORT_SYMBOL(pre_task_out_intr); @@ -1030,6 +1033,9 @@ return startstop; } + if (!drive->unmask) + local_irq_disable(); + return task_mulout_intr(drive); } EXPORT_SYMBOL(pre_task_mulout_intr); @@ -1361,8 +1367,6 @@ EXPORT_SYMBOL(ide_init_drive_taskfile); -#if 1 - int ide_diag_taskfile (ide_drive_t *drive, ide_task_t *args, unsigned long data_size, u8 *buf) { struct request rq; @@ -1400,69 +1404,6 @@ rq.special = args; return ide_do_drive_cmd(drive, &rq, ide_wait); } - -#else - -int ide_diag_taskfile (ide_drive_t *drive, ide_task_t *args, unsigned long data_size, u8 *buf) -{ - struct request *rq; - unsigned long flags; - ide_hwgroup_t *hwgroup = HWGROUP(drive); - struct list_head *queue_head = &drive->queue.queue_head; - DECLARE_COMPLETION(wait); - - if (HWIF(drive)->chipset == ide_pdc4030 && buf != NULL) - return -ENOSYS; /* special drive cmds not supported */ - - memset(rq, 0, sizeof(*rq)); - rq->flags = REQ_DRIVE_TASKFILE; - rq->buffer = buf; - - /* - * (ks) We transfer currently only whole sectors. - * This is suffient for now. But, it would be great, - * if we would find a solution to transfer any size. - * To support special commands like READ LONG. - */ - if (args->command_type != IDE_DRIVE_TASK_NO_DATA) { - if (data_size == 0) { - ata_nsector_t nsector; - nsector.b.low = args->hobRegister[IDE_NSECTOR_OFFSET_HOB]; - nsector.b.high = args->tfRegister[IDE_NSECTOR_OFFSET]; - rq.nr_sectors = nsector.all; - } else { - rq.nr_sectors = data_size / SECTOR_SIZE; - } - rq.current_nr_sectors = rq.nr_sectors; - // rq.hard_cur_sectors = rq.nr_sectors; - } - - if (args->tf_out_flags.all == 0) { - /* - * clean up kernel settings for driver sanity, regardless. - * except for discrete diag services. - */ - args->posthandler = ide_post_handler_parser( - (struct hd_drive_task_hdr *) args->tfRegister, - (struct hd_drive_hob_hdr *) args->hobRegister); - } - rq->special = args; - rq->errors = 0; - rq->rq_status = RQ_ACTIVE; - rq->rq_disk = drive->disk; - rq->waiting = &wait; - - spin_lock_irqsave(&ide_lock, flags); - queue_head = queue_head->prev; - list_add(&rq->queue, queue_head); - ide_do_request(hwgroup, 0); - spin_unlock_irqrestore(&ide_lock, flags); - - wait_for_completion(&wait); /* wait for it to be serviced */ - return rq->errors ? -EIO : 0; /* return -EIO if errors */ -} - -#endif EXPORT_SYMBOL(ide_diag_taskfile); diff -Nru a/drivers/ide/ide-tcq.c b/drivers/ide/ide-tcq.c --- a/drivers/ide/ide-tcq.c Tue Jul 1 18:44:39 2003 +++ b/drivers/ide/ide-tcq.c Tue Jul 1 18:44:39 2003 @@ -501,8 +501,10 @@ * bit 14 and 1 must be set in word 83 of the device id to indicate * support for dma queued protocol, and bit 15 must be cleared */ - if ((drive->id->command_set_2 & tcq_bits) ^ tcq_mask) + if ((drive->id->command_set_2 & tcq_bits) ^ tcq_mask) { + printk(KERN_INFO "%s: TCQ not supported\n", drive->name); return -EIO; + } args = kmalloc(sizeof(*args), GFP_ATOMIC); if (!args) @@ -655,21 +657,24 @@ int __ide_dma_queued_on(ide_drive_t *drive) { + ide_hwif_t *hwif = HWIF(drive); + + if (drive->media != ide_disk) + return 1; if (!drive->using_dma) return 1; - if (HWIF(drive)->chipset == ide_pdc4030) + if (hwif->chipset == ide_pdc4030) return 1; if (ide_tcq_check_blacklist(drive)) { printk(KERN_WARNING "%s: tcq forbidden by blacklist\n", drive->name); return 1; } - if (drive->next != drive) { + if (hwif->drives[0].present && hwif->drives[1].present) { printk(KERN_WARNING "%s: only one drive on a channel supported" " for tcq\n", drive->name); return 1; } - if (ata_pending_commands(drive)) { printk(KERN_WARNING "ide-tcq; can't toggle tcq feature on " "busy drive\n"); @@ -681,6 +686,8 @@ int __ide_dma_queued_off(ide_drive_t *drive) { + if (drive->media != ide_disk) + return 1; if (ata_pending_commands(drive)) { printk("ide-tcq; can't toggle tcq feature on busy drive\n"); return 1; diff -Nru a/drivers/ide/ide.c b/drivers/ide/ide.c --- a/drivers/ide/ide.c Tue Jul 1 18:44:34 2003 +++ b/drivers/ide/ide.c Tue Jul 1 18:44:34 2003 @@ -216,7 +216,7 @@ EXPORT_SYMBOL(idescsi); extern ide_driver_t idedefault_driver; -static void setup_driver_defaults (ide_drive_t *drive); +static void setup_driver_defaults(ide_driver_t *driver); /* * Do not even *think* about calling this! @@ -275,7 +275,6 @@ drive->using_dma = 0; drive->is_flash = 0; drive->driver = &idedefault_driver; - setup_driver_defaults(drive); drive->vdma = 0; INIT_LIST_HEAD(&drive->list); } @@ -308,6 +307,8 @@ return; /* already initialized */ magic_cookie = 0; + setup_driver_defaults(&idedefault_driver); + /* Initialise all interface structures */ for (index = 0; index < MAX_HWIFS; ++index) init_hwif_data(index); @@ -507,12 +508,87 @@ }; #endif +static struct resource* hwif_request_region(ide_hwif_t *hwif, + unsigned long addr, int num) +{ + struct resource *res; + + if (hwif->mmio) + res = request_mem_region(addr, num, hwif->name); + else + res = request_region(addr, num, hwif->name); + + if (!res) + printk(KERN_ERR "%s: %s resource 0x%lX-0x%lX not free.\n", + hwif->name, hwif->mmio ? "MMIO" : "I/O", + addr, addr+num-1); + return res; +} #define hwif_release_region(addr, num) \ ((hwif->mmio) ? release_mem_region((addr),(num)) : release_region((addr),(num))) /** - * hwif_unregister - free IDE resources + * ide_hwif_request_regions - request resources for IDE + * @hwif: interface to use + * + * Requests all the needed resources for an interface. + * Right now core IDE code does this work which is deeply wrong. + * MMIO leaves it to the controller driver, + * PIO will migrate this way over time. + */ +int ide_hwif_request_regions(ide_hwif_t *hwif) +{ + unsigned long addr; + unsigned int i; + + if (hwif->mmio == 2) + return 0; + addr = hwif->io_ports[IDE_CONTROL_OFFSET]; + if (addr && !hwif_request_region(hwif, addr, 1)) + goto control_region_busy; +#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC) + addr = hwif->io_ports[IDE_IRQ_OFFSET]; + if (addr && !hwif_request_region(hwif, addr, 1)) + goto irq_region_busy; +#endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */ + hwif->straight8 = 0; + addr = hwif->io_ports[IDE_DATA_OFFSET]; + if ((addr | 7) == hwif->io_ports[IDE_STATUS_OFFSET]) { + if (!hwif_request_region(hwif, addr, 8)) + goto data_region_busy; + hwif->straight8 = 1; + return 0; + } + for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { + addr = hwif->io_ports[i]; + if (!hwif_request_region(hwif, addr, 1)) { + while (--i) + hwif_release_region(addr, 1); + goto data_region_busy; + } + } + return 0; + +data_region_busy: +#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC) + addr = hwif->io_ports[IDE_IRQ_OFFSET]; + if (addr) + hwif_release_region(addr, 1); +irq_region_busy: +#endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */ + addr = hwif->io_ports[IDE_CONTROL_OFFSET]; + if (addr) + hwif_release_region(addr, 1); +control_region_busy: + /* If any errors are return, we drop the hwif interface. */ + return -EBUSY; +} + +EXPORT_SYMBOL(ide_hwif_request_regions); + +/** + * ide_hwif_release_regions - free IDE resources * * Note that we only release the standard ports, * and do not even try to handle any extra ports @@ -522,8 +598,7 @@ * importantly our caller should be doing this so we need to * restructure this as a helper function for drivers. */ - -void hwif_unregister (ide_hwif_t *hwif) +void ide_hwif_release_regions(ide_hwif_t *hwif) { u32 i = 0; @@ -547,7 +622,7 @@ } } -EXPORT_SYMBOL(hwif_unregister); +EXPORT_SYMBOL(ide_hwif_release_regions); extern void init_hwif_data(unsigned int index); @@ -634,7 +709,7 @@ * and do not even try to handle any extra ports * allocated for weird IDE interface chipsets. */ - hwif_unregister(hwif); + ide_hwif_release_regions(hwif); /* * Remove us from the hwgroup, and free @@ -673,8 +748,8 @@ blk_cleanup_queue(&drive->queue); } if (hwif->next == hwif) { - kfree(hwgroup); BUG_ON(hwgroup->hwif != hwif); + kfree(hwgroup); } else { /* There is another interface in hwgroup. * Unlink us, and set hwgroup->drive and ->hwif to @@ -1134,13 +1209,12 @@ * * Automatically remove all the driver specific settings for this * drive. This function may sleep and must not be called from IRQ - * context. Takes the settings_lock + * context. The caller must hold ide_setting_sem. */ static void auto_remove_settings (ide_drive_t *drive) { ide_settings_t *setting; - down(&ide_setting_sem); repeat: setting = drive->settings; while (setting) { @@ -1150,7 +1224,6 @@ } setting = setting->next; } - up(&ide_setting_sem); } /** @@ -2099,10 +2172,9 @@ #ifdef CONFIG_BLK_DEV_IDEPCI hwif->udma_four = 1; goto done; -#else /* !CONFIG_BLK_DEV_IDEPCI */ - hwif->udma_four = 0; +#else goto bad_hwif; -#endif /* CONFIG_BLK_DEV_IDEPCI */ +#endif case -6: /* dma */ hwif->autodma = 1; goto done; @@ -2346,10 +2418,8 @@ return ide_abort(drive, msg); } -static void setup_driver_defaults (ide_drive_t *drive) +static void setup_driver_defaults (ide_driver_t *d) { - ide_driver_t *d = drive->driver; - if (d->cleanup == NULL) d->cleanup = default_cleanup; if (d->shutdown == NULL) d->shutdown = default_shutdown; if (d->flushcache == NULL) d->flushcache = default_flushcache; @@ -2377,7 +2447,6 @@ return 1; } drive->driver = driver; - setup_driver_defaults(drive); spin_unlock_irqrestore(&ide_lock, flags); spin_lock(&drives_lock); list_add_tail(&drive->list, &driver->drives); @@ -2408,9 +2477,11 @@ { unsigned long flags; + down(&ide_setting_sem); spin_lock_irqsave(&ide_lock, flags); if (drive->usage || drive->driver == &idedefault_driver || DRIVER(drive)->busy) { spin_unlock_irqrestore(&ide_lock, flags); + up(&ide_setting_sem); return 1; } #if defined(CONFIG_BLK_DEV_IDEPNP) && defined(CONFIG_PNP) && defined(MODULE) @@ -2422,8 +2493,8 @@ #endif auto_remove_settings(drive); drive->driver = &idedefault_driver; - setup_driver_defaults(drive); spin_unlock_irqrestore(&ide_lock, flags); + up(&ide_setting_sem); spin_lock(&drives_lock); list_del_init(&drive->list); spin_unlock(&drives_lock); @@ -2446,6 +2517,8 @@ struct list_head *list_loop; struct list_head *tmp_storage; + setup_driver_defaults(driver); + spin_lock(&drivers_lock); list_add(&driver->drivers, &drivers); spin_unlock(&drivers_lock); @@ -2520,13 +2593,9 @@ */ int __init ide_init (void) { - static char banner_printed; - if (!banner_printed) { - printk(KERN_INFO "Uniform Multi-Platform E-IDE driver " REVISION "\n"); - devfs_mk_dir("ide"); - system_bus_speed = ide_system_bus_speed(); - banner_printed = 1; - } + printk(KERN_INFO "Uniform Multi-Platform E-IDE driver " REVISION "\n"); + devfs_mk_dir("ide"); + system_bus_speed = ide_system_bus_speed(); bus_register(&ide_bus_type); diff -Nru a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c --- a/drivers/ide/legacy/ide-cs.c Tue Jul 1 18:44:36 2003 +++ b/drivers/ide/legacy/ide-cs.c Tue Jul 1 18:44:36 2003 @@ -473,7 +473,7 @@ static struct pcmcia_driver ide_cs_driver = { .owner = THIS_MODULE, .drv = { - .name = "ide_cs", + .name = "ide-cs", }, .attach = ide_attach, .detach = ide_detach, diff -Nru a/drivers/ide/legacy/pdc4030.c b/drivers/ide/legacy/pdc4030.c --- a/drivers/ide/legacy/pdc4030.c Tue Jul 1 18:44:35 2003 +++ b/drivers/ide/legacy/pdc4030.c Tue Jul 1 18:44:35 2003 @@ -613,8 +613,6 @@ */ taskfile_output_data(drive, buffer, nsect<<7); } while (mcount); - - return 0; } #endif @@ -624,7 +622,9 @@ static ide_startstop_t promise_write_pollfunc (ide_drive_t *drive) { ide_hwgroup_t *hwgroup = HWGROUP(drive); +#ifdef CONFIG_IDE_TASKFILE_IO struct request *rq = hwgroup->rq; +#endif if (HWIF(drive)->INB(IDE_NSECTOR_REG) != 0) { if (time_before(jiffies, hwgroup->poll_timeout)) { @@ -818,7 +818,8 @@ Feature register. FIXME: Is promise_selectproc now redundant?? */ - int drive_number = (HWIF(drive)->channel << 1) + drive->select.b.unit; + ide_hwif_t *hwif = HWIF(drive); + int drive_number = (hwif->channel << 1) + drive->select.b.unit; #ifdef CONFIG_IDE_TASKFILE_IO struct hd_drive_task_hdr taskfile; ide_task_t args; diff -Nru a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c --- a/drivers/ide/pci/sc1200.c Tue Jul 1 18:44:36 2003 +++ b/drivers/ide/pci/sc1200.c Tue Jul 1 18:44:36 2003 @@ -32,17 +32,6 @@ #include "ide_modes.h" #include "sc1200.h" -#define DISPLAY_SC1200_TIMINGS - -#if defined(DISPLAY_SC1200_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static int sc1200_get_info(char *, char **, off_t, int); -extern int (*sc1200_display_info)(char *, char **, off_t, int); /* ide-proc.c */ -extern char *ide_media_verbose(ide_drive_t *); -static u8 sc1200_proc = 0; - #define SC1200_REV_A 0x00 #define SC1200_REV_B1 0x01 #define SC1200_REV_B3 0x02 @@ -80,6 +69,17 @@ } return pci_clock; } + +#define DISPLAY_SC1200_TIMINGS + +#if defined(DISPLAY_SC1200_TIMINGS) && defined(CONFIG_PROC_FS) +#include +#include + +static int sc1200_get_info(char *, char **, off_t, int); +extern int (*sc1200_display_info)(char *, char **, off_t, int); /* ide-proc.c */ +extern char *ide_media_verbose(ide_drive_t *); +static u8 sc1200_proc = 0; static struct pci_dev *bmide_dev; diff -Nru a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c --- a/drivers/ide/setup-pci.c Tue Jul 1 18:44:34 2003 +++ b/drivers/ide/setup-pci.c Tue Jul 1 18:44:34 2003 @@ -702,8 +702,9 @@ * Can we trust the reported IRQ? */ pciirq = dev->irq; - - if ((dev->class & ~(0xfa)) != ((PCI_CLASS_STORAGE_IDE << 8) | 5)) { + + /* Is it an "IDE storage" device in non-PCI mode? */ + if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 5) != 5) { if (noisy) printk(KERN_INFO "%s: not 100%% native mode: " "will probe irqs later\n", d->name); diff -Nru a/drivers/ieee1394/Makefile b/drivers/ieee1394/Makefile --- a/drivers/ieee1394/Makefile Tue Jul 1 18:44:39 2003 +++ b/drivers/ieee1394/Makefile Tue Jul 1 18:44:39 2003 @@ -18,6 +18,9 @@ clean-files := oui.c +quiet_cmd_oui2c = OUI2C $@ + cmd_oui2c = $(CONFIG_SHELL) $(obj)/oui2c.sh < $(obj)/oui.db > $@ + $(obj)/oui.o: $(obj)/oui.c $(obj)/oui.c: $(obj)/oui.db $(obj)/oui2c.sh - $(CONFIG_SHELL) $(obj)/oui2c.sh < $(obj)/oui.db > $@ + $(call if_changed,oui2c) diff -Nru a/drivers/ieee1394/amdtp.c b/drivers/ieee1394/amdtp.c --- a/drivers/ieee1394/amdtp.c Tue Jul 1 18:44:35 2003 +++ b/drivers/ieee1394/amdtp.c Tue Jul 1 18:44:35 2003 @@ -732,7 +732,7 @@ /* Fill IEEE1394 headers */ packet->db->header_desc.header[0] = - (SPEED_100 << 16) | (0x01 << 14) | + (IEEE1394_SPEED_100 << 16) | (0x01 << 14) | (s->iso_channel << 8) | (TCODE_ISO_DATA << 4); packet->db->header_desc.header[1] = size << 16; diff -Nru a/drivers/ieee1394/cmp.c b/drivers/ieee1394/cmp.c --- a/drivers/ieee1394/cmp.c Tue Jul 1 18:44:36 2003 +++ b/drivers/ieee1394/cmp.c Tue Jul 1 18:44:36 2003 @@ -138,7 +138,7 @@ } ch->host = host; - ch->u.ompr.rate = SPEED_100; + ch->u.ompr.rate = IEEE1394_SPEED_100; ch->u.ompr.bcast_channel_base = 63; ch->u.ompr.nplugs = 2; diff -Nru a/drivers/ieee1394/csr.h b/drivers/ieee1394/csr.h --- a/drivers/ieee1394/csr.h Tue Jul 1 18:44:31 2003 +++ b/drivers/ieee1394/csr.h Tue Jul 1 18:44:31 2003 @@ -2,6 +2,10 @@ #ifndef _IEEE1394_CSR_H #define _IEEE1394_CSR_H +#ifdef CONFIG_PREEMPT +#include +#endif + #define CSR_REGISTER_BASE 0xfffff0000000ULL /* register offsets relative to CSR_REGISTER_BASE */ diff -Nru a/drivers/ieee1394/dma.c b/drivers/ieee1394/dma.c --- a/drivers/ieee1394/dma.c Tue Jul 1 18:44:35 2003 +++ b/drivers/ieee1394/dma.c Tue Jul 1 18:44:35 2003 @@ -31,7 +31,7 @@ prog->n_pages = n_bytes / PAGE_SIZE; prog->kvirt = pci_alloc_consistent(dev, prog->n_pages * PAGE_SIZE, &prog->bus_addr); - if(!prog->kvirt) { + if (!prog->kvirt) { printk(KERN_ERR "dma_prog_region_alloc: pci_alloc_consistent() failed\n"); dma_prog_region_free(prog); return -ENOMEM; @@ -44,7 +44,7 @@ void dma_prog_region_free(struct dma_prog_region *prog) { - if(prog->kvirt) { + if (prog->kvirt) { pci_free_consistent(prog->dev, prog->n_pages * PAGE_SIZE, prog->kvirt, prog->bus_addr); } @@ -75,7 +75,7 @@ n_pages = n_bytes / PAGE_SIZE; dma->kvirt = vmalloc_32(n_pages * PAGE_SIZE); - if(!dma->kvirt) { + if (!dma->kvirt) { printk(KERN_ERR "dma_region_alloc: vmalloc_32() failed\n"); goto err; } @@ -87,7 +87,7 @@ /* allocate scatter/gather list */ dma->sglist = kmalloc(dma->n_pages * sizeof(struct scatterlist), GFP_KERNEL); - if(!dma->sglist) { + if (!dma->sglist) { printk(KERN_ERR "dma_region_alloc: kmalloc(sglist) failed\n"); goto err; } @@ -96,7 +96,7 @@ memset(dma->sglist, 0, dma->n_pages * sizeof(struct scatterlist)); /* fill scatter/gather list with pages */ - for(i = 0; i < dma->n_pages; i++) { + for (i = 0; i < dma->n_pages; i++) { unsigned long va = (unsigned long) dma->kvirt + i * PAGE_SIZE; dma->sglist[i].page = vmalloc_to_page((void *)va); @@ -106,7 +106,7 @@ /* map sglist to the IOMMU */ dma->n_dma_pages = pci_map_sg(dev, &dma->sglist[0], dma->n_pages, direction); - if(dma->n_dma_pages == 0) { + if (dma->n_dma_pages == 0) { printk(KERN_ERR "dma_region_alloc: pci_map_sg() failed\n"); goto err; } @@ -123,18 +123,18 @@ void dma_region_free(struct dma_region *dma) { - if(dma->n_dma_pages) { + if (dma->n_dma_pages) { pci_unmap_sg(dma->dev, dma->sglist, dma->n_pages, dma->direction); dma->n_dma_pages = 0; dma->dev = NULL; } - if(dma->sglist) { + if (dma->sglist) { kfree(dma->sglist); dma->sglist = NULL; } - if(dma->kvirt) { + if (dma->kvirt) { vfree(dma->kvirt); dma->kvirt = NULL; dma->n_pages = 0; @@ -148,8 +148,8 @@ int i; unsigned long off = offset; - for(i = 0; i < dma->n_dma_pages; i++) { - if(off < sg_dma_len(&dma->sglist[i])) { + for (i = 0; i < dma->n_dma_pages; i++) { + if (off < sg_dma_len(&dma->sglist[i])) { *rem = off; return i; } @@ -173,7 +173,7 @@ int first, last; unsigned long rem; - if(!len) + if (!len) len = 1; first = dma_region_find(dma, offset, &rem); @@ -193,10 +193,10 @@ struct dma_region *dma = (struct dma_region*) area->vm_private_data; - if(!dma->kvirt) + if (!dma->kvirt) goto out; - if( (address < (unsigned long) area->vm_start) || + if ( (address < (unsigned long) area->vm_start) || (address > (unsigned long) area->vm_start + (PAGE_SIZE * dma->n_pages)) ) goto out; @@ -216,16 +216,16 @@ { unsigned long size; - if(!dma->kvirt) + if (!dma->kvirt) return -EINVAL; /* must be page-aligned */ - if(vma->vm_pgoff != 0) + if (vma->vm_pgoff != 0) return -EINVAL; /* check the length */ size = vma->vm_end - vma->vm_start; - if(size > (PAGE_SIZE * dma->n_pages)) + if (size > (PAGE_SIZE * dma->n_pages)) return -EINVAL; vma->vm_ops = &dma_region_vm_ops; diff -Nru a/drivers/ieee1394/dma.h b/drivers/ieee1394/dma.h --- a/drivers/ieee1394/dma.h Tue Jul 1 18:44:37 2003 +++ b/drivers/ieee1394/dma.h Tue Jul 1 18:44:37 2003 @@ -76,7 +76,7 @@ /* round up a number of bytes to be a multiple of the PAGE_SIZE */ static inline unsigned long round_up_to_page(unsigned long len) { - if(len % PAGE_SIZE) + if (len % PAGE_SIZE) len += PAGE_SIZE - (len % PAGE_SIZE); return len; } diff -Nru a/drivers/ieee1394/dv1394-private.h b/drivers/ieee1394/dv1394-private.h --- a/drivers/ieee1394/dv1394-private.h Tue Jul 1 18:44:36 2003 +++ b/drivers/ieee1394/dv1394-private.h Tue Jul 1 18:44:36 2003 @@ -97,7 +97,7 @@ omi->q[3] = 0; /* IT packet header */ - omi->q[4] = cpu_to_le32( (0x0 << 16) /* DMA_SPEED_100 */ + omi->q[4] = cpu_to_le32( (0x0 << 16) /* IEEE1394_SPEED_100 */ | (tag << 14) | (channel << 8) | (TCODE_ISO_DATA << 4) @@ -129,10 +129,10 @@ u32 temp = 0; temp |= 1 << 28; /* OUTPUT_LAST */ - if(want_timestamp) /* controller will update timestamp at DMA time */ + if (want_timestamp) /* controller will update timestamp at DMA time */ temp |= 1 << 27; - if(want_interrupt) + if (want_interrupt) temp |= 3 << 20; temp |= 3 << 18; /* must take branch */ diff -Nru a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c --- a/drivers/ieee1394/dv1394.c Tue Jul 1 18:44:36 2003 +++ b/drivers/ieee1394/dv1394.c Tue Jul 1 18:44:36 2003 @@ -201,14 +201,14 @@ static struct frame* frame_new(unsigned int frame_num, struct video_card *video) { struct frame *f = kmalloc(sizeof(*f), GFP_KERNEL); - if(!f) + if (!f) return NULL; f->video = video; f->frame_num = frame_num; f->header_pool = pci_alloc_consistent(f->video->ohci->dev, PAGE_SIZE, &f->header_pool_dma); - if(!f->header_pool) { + if (!f->header_pool) { printk(KERN_ERR "dv1394: failed to allocate CIP header pool\n"); kfree(f); return NULL; @@ -224,7 +224,7 @@ f->descriptor_pool = pci_alloc_consistent(f->video->ohci->dev, f->descriptor_pool_size, &f->descriptor_pool_dma); - if(!f->descriptor_pool) { + if (!f->descriptor_pool) { pci_free_consistent(f->video->ohci->dev, PAGE_SIZE, f->header_pool, f->header_pool_dma); kfree(f); return NULL; @@ -284,12 +284,12 @@ - if(video->pal_or_ntsc == DV1394_PAL) + if (video->pal_or_ntsc == DV1394_PAL) packets_per_frame = DV1394_PAL_PACKETS_PER_FRAME; else packets_per_frame = DV1394_NTSC_PACKETS_PER_FRAME; - while( full_packets < packets_per_frame ) { + while ( full_packets < packets_per_frame ) { empty_packet = first_packet = last_packet = mid_packet = 0; data_p = f->data + full_packets * 480; @@ -300,7 +300,7 @@ /* note: these should NOT cross a page boundary (DMA restriction) */ - if(f->n_packets >= MAX_PACKETS) { + if (f->n_packets >= MAX_PACKETS) { printk(KERN_ERR "dv1394: FATAL ERROR: max packet count exceeded\n"); return; } @@ -316,7 +316,7 @@ /* the whole CIP pool fits on one page, so no worries about boundaries */ - if( ((unsigned long) &(f->header_pool[f->n_packets]) - (unsigned long) f->header_pool) + if ( ((unsigned long) &(f->header_pool[f->n_packets]) - (unsigned long) f->header_pool) > PAGE_SIZE) { printk(KERN_ERR "dv1394: FATAL ERROR: no room to allocate CIP header\n"); return; @@ -331,7 +331,7 @@ /* is this an empty packet? */ - if(video->cip_accum > (video->cip_d - video->cip_n)) { + if (video->cip_accum > (video->cip_d - video->cip_n)) { empty_packet = 1; payload_size = 8; video->cip_accum -= (video->cip_d - video->cip_n); @@ -364,7 +364,7 @@ the timestamp before DMA starts on the next frame. */ - if(f->n_packets == 0) { + if (f->n_packets == 0) { first_packet = 1; } else if ( full_packets == (packets_per_frame-1) ) { last_packet = 1; @@ -383,12 +383,12 @@ need a timestamp. */ /* first packet in the frame needs a timestamp */ - if(first_packet) { + if (first_packet) { f->cip_syt1 = cip; - if(empty_packet) + if (empty_packet) first_packet_empty = 1; - } else if(first_packet_empty && (f->n_packets == 1) ) { + } else if (first_packet_empty && (f->n_packets == 1) ) { /* if the first packet was empty, the second packet's CIP header also needs a timestamp */ f->cip_syt2 = cip; @@ -402,7 +402,7 @@ 0xFFFF /* the timestamp is filled in later */); /* advance counter, only for full packets */ - if( ! empty_packet ) + if ( ! empty_packet ) video->continuity_counter++; /******************************/ @@ -412,7 +412,7 @@ /* first descriptor - OUTPUT_MORE_IMMEDIATE, for the controller's IT header */ fill_output_more_immediate( &(block->u.out.omi), 1, video->channel, 0, payload_size); - if(empty_packet) { + if (empty_packet) { /* second descriptor - OUTPUT_LAST for CIP header */ fill_output_last( &(block->u.out.u.empty.ol), @@ -425,18 +425,18 @@ sizeof(struct CIP_header), /* data size */ cip_dma); - if(first_packet) + if (first_packet) f->frame_begin_timestamp = &(block->u.out.u.empty.ol.q[3]); - else if(mid_packet) + else if (mid_packet) f->mid_frame_timestamp = &(block->u.out.u.empty.ol.q[3]); - else if(last_packet) { + else if (last_packet) { f->frame_end_timestamp = &(block->u.out.u.empty.ol.q[3]); f->frame_end_branch = &(block->u.out.u.empty.ol.q[2]); } branch_address = &(block->u.out.u.empty.ol.q[2]); n_descriptors = 3; - if(first_packet) + if (first_packet) f->first_n_descriptors = n_descriptors; } else { /* full packet */ @@ -452,7 +452,7 @@ we need to split it into two DMA descriptors */ /* does the 480-byte data payload cross a page boundary? */ - if( (PAGE_SIZE- ((unsigned long)data_p % PAGE_SIZE) ) < 480 ) { + if ( (PAGE_SIZE- ((unsigned long)data_p % PAGE_SIZE) ) < 480 ) { /* page boundary crossed */ @@ -479,11 +479,11 @@ dma_region_offset_to_bus(&video->dv_buf, data_p + PAGE_SIZE - (data_p % PAGE_SIZE) - (unsigned long) video->dv_buf.kvirt)); - if(first_packet) + if (first_packet) f->frame_begin_timestamp = &(block->u.out.u.full.u.cross.ol.q[3]); - else if(mid_packet) + else if (mid_packet) f->mid_frame_timestamp = &(block->u.out.u.full.u.cross.ol.q[3]); - else if(last_packet) { + else if (last_packet) { f->frame_end_timestamp = &(block->u.out.u.full.u.cross.ol.q[3]); f->frame_end_branch = &(block->u.out.u.full.u.cross.ol.q[2]); } @@ -491,7 +491,7 @@ branch_address = &(block->u.out.u.full.u.cross.ol.q[2]); n_descriptors = 5; - if(first_packet) + if (first_packet) f->first_n_descriptors = n_descriptors; full_packets++; @@ -514,11 +514,11 @@ dma_region_offset_to_bus(&video->dv_buf, data_p - (unsigned long) video->dv_buf.kvirt)); - if(first_packet) + if (first_packet) f->frame_begin_timestamp = &(block->u.out.u.full.u.nocross.ol.q[3]); - else if(mid_packet) + else if (mid_packet) f->mid_frame_timestamp = &(block->u.out.u.full.u.nocross.ol.q[3]); - else if(last_packet) { + else if (last_packet) { f->frame_end_timestamp = &(block->u.out.u.full.u.nocross.ol.q[3]); f->frame_end_branch = &(block->u.out.u.full.u.nocross.ol.q[2]); } @@ -526,7 +526,7 @@ branch_address = &(block->u.out.u.full.u.nocross.ol.q[2]); n_descriptors = 4; - if(first_packet) + if (first_packet) f->first_n_descriptors = n_descriptors; full_packets++; @@ -538,7 +538,7 @@ /* note: we are not linked into the active DMA chain yet */ - if(last_branch_address) { + if (last_branch_address) { *(last_branch_address) = cpu_to_le32(block_dma | n_descriptors); } @@ -564,7 +564,7 @@ video->n_clear_frames--; last_frame = video->first_clear_frame - 1; - if(last_frame == -1) + if (last_frame == -1) last_frame = video->n_frames-1; video->first_clear_frame = (video->first_clear_frame + 1) % video->n_frames; @@ -578,11 +578,11 @@ (unsigned long) f->frame_end_timestamp, (unsigned long) f->frame_end_branch); - if(video->active_frame != -1) { + if (video->active_frame != -1) { /* if DMA is already active, we are almost done */ /* just link us onto the active DMA chain */ - if(video->frames[last_frame]->frame_end_branch) { + if (video->frames[last_frame]->frame_end_branch) { u32 temp; /* point the previous frame's tail to this frame's head */ @@ -650,11 +650,11 @@ f->assigned_timestamp = (ts_cyc&0xF) << 12; /* now actually write the timestamp into the appropriate CIP headers */ - if(f->cip_syt1) { + if (f->cip_syt1) { f->cip_syt1->b[6] = f->assigned_timestamp >> 8; f->cip_syt1->b[7] = f->assigned_timestamp & 0xFF; } - if(f->cip_syt2) { + if (f->cip_syt2) { f->cip_syt2->b[6] = f->assigned_timestamp >> 8; f->cip_syt2->b[7] = f->assigned_timestamp & 0xFF; } @@ -706,10 +706,10 @@ { /* check if DMA is really running */ int i = 0; - while(i < 20) { + while (i < 20) { mb(); mdelay(1); - if(reg_read(video->ohci, video->ohci_IsoXmitContextControlSet) & (1 << 10)) { + if (reg_read(video->ohci, video->ohci_IsoXmitContextControlSet) & (1 << 10)) { printk("DMA ACTIVE after %d msec\n", i); break; } @@ -721,7 +721,7 @@ reg_read(video->ohci, video->ohci_IsoXmitCommandPtr) ); - if( ! (reg_read(video->ohci, video->ohci_IsoXmitContextControlSet) & (1 << 10)) ) { + if ( ! (reg_read(video->ohci, video->ohci_IsoXmitContextControlSet) & (1 << 10)) ) { printk("DMA did NOT go active after 20ms, event = %x\n", reg_read(video->ohci, video->ohci_IsoXmitContextControlSet) & 0x1F); } else @@ -821,14 +821,14 @@ { int i; - for(i = 0; i < 1000; ++i) { + for (i = 0; i < 1000; ++i) { mdelay(1); - if(reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 10)) { + if (reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 10)) { printk("DMA ACTIVE after %d msec\n", i); break; } } - if( reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 11) ) { + if ( reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 11) ) { printk("DEAD, event = %x\n", reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & 0x1F); } else @@ -836,7 +836,7 @@ } #endif } - else if( reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 11) ) { + else if ( reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 11) ) { debug_printk("DEAD, event = %x\n", reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & 0x1F); @@ -912,36 +912,36 @@ int retval = -EINVAL; debug_printk("dv1394: initialising %d\n", video->id); - if(init->api_version != DV1394_API_VERSION) + if (init->api_version != DV1394_API_VERSION) return -EINVAL; /* first sanitize all the parameters */ - if( (init->n_frames < 2) || (init->n_frames > DV1394_MAX_FRAMES) ) + if ( (init->n_frames < 2) || (init->n_frames > DV1394_MAX_FRAMES) ) return -EINVAL; - if( (init->format != DV1394_NTSC) && (init->format != DV1394_PAL) ) + if ( (init->format != DV1394_NTSC) && (init->format != DV1394_PAL) ) return -EINVAL; - if( (init->syt_offset == 0) || (init->syt_offset > 50) ) + if ( (init->syt_offset == 0) || (init->syt_offset > 50) ) /* default SYT offset is 3 cycles */ init->syt_offset = 3; - if( (init->channel > 63) || (init->channel < 0) ) + if ( (init->channel > 63) || (init->channel < 0) ) init->channel = 63; chan_mask = (u64)1 << init->channel; /* calculate what size DMA buffer is needed */ - if(init->format == DV1394_NTSC) + if (init->format == DV1394_NTSC) new_buf_size = DV1394_NTSC_FRAME_SIZE * init->n_frames; else new_buf_size = DV1394_PAL_FRAME_SIZE * init->n_frames; /* round up to PAGE_SIZE */ - if(new_buf_size % PAGE_SIZE) new_buf_size += PAGE_SIZE - (new_buf_size % PAGE_SIZE); + if (new_buf_size % PAGE_SIZE) new_buf_size += PAGE_SIZE - (new_buf_size % PAGE_SIZE); /* don't allow the user to allocate the DMA buffer more than once */ - if(video->dv_buf.kvirt && video->dv_buf_size != new_buf_size) { + if (video->dv_buf.kvirt && video->dv_buf_size != new_buf_size) { printk("dv1394: re-sizing the DMA buffer is not allowed\n"); return -EINVAL; } @@ -953,7 +953,7 @@ /* try to claim the ISO channel */ spin_lock_irqsave(&video->ohci->IR_channel_lock, flags); - if(video->ohci->ISO_channel_usage & chan_mask) { + if (video->ohci->ISO_channel_usage & chan_mask) { spin_unlock_irqrestore(&video->ohci->IR_channel_lock, flags); retval = -EBUSY; goto err; @@ -981,7 +981,7 @@ video->current_packet = -1; video->first_frame = 0; - if(video->pal_or_ntsc == DV1394_NTSC) { + if (video->pal_or_ntsc == DV1394_NTSC) { video->cip_n = init->cip_n != 0 ? init->cip_n : CIP_N_NTSC; video->cip_d = init->cip_d != 0 ? init->cip_d : CIP_D_NTSC; video->frame_size = DV1394_NTSC_FRAME_SIZE; @@ -995,7 +995,7 @@ /* find and claim DMA contexts on the OHCI card */ - if(video->ohci_it_ctx == -1) { + if (video->ohci_it_ctx == -1) { ohci1394_init_iso_tasklet(&video->it_tasklet, OHCI_ISO_TRANSMIT, it_tasklet_func, (unsigned long) video); @@ -1009,7 +1009,7 @@ debug_printk("dv1394: claimed IT DMA context %d\n", video->ohci_it_ctx); } - if(video->ohci_ir_ctx == -1) { + if (video->ohci_ir_ctx == -1) { ohci1394_init_iso_tasklet(&video->ir_tasklet, OHCI_ISO_RECEIVE, ir_tasklet_func, (unsigned long) video); @@ -1023,20 +1023,20 @@ } /* allocate struct frames */ - for(i = 0; i < init->n_frames; i++) { + for (i = 0; i < init->n_frames; i++) { video->frames[i] = frame_new(i, video); - if(!video->frames[i]) { + if (!video->frames[i]) { printk(KERN_ERR "dv1394: Cannot allocate frame structs\n"); retval = -ENOMEM; goto err; } } - if(!video->dv_buf.kvirt) { + if (!video->dv_buf.kvirt) { /* allocate the ringbuffer */ retval = dma_region_alloc(&video->dv_buf, new_buf_size, video->ohci->dev, PCI_DMA_TODEVICE); - if(retval) + if (retval) goto err; video->dv_buf_size = new_buf_size; @@ -1047,10 +1047,10 @@ } /* set up the frame->data pointers */ - for(i = 0; i < video->n_frames; i++) + for (i = 0; i < video->n_frames; i++) video->frames[i]->data = (unsigned long) video->dv_buf.kvirt + i * video->frame_size; - if(!video->packet_buf.kvirt) { + if (!video->packet_buf.kvirt) { /* allocate packet buffer */ video->packet_buf_size = sizeof(struct packet) * video->n_frames * MAX_PACKETS; if (video->packet_buf_size % PAGE_SIZE) @@ -1058,7 +1058,7 @@ retval = dma_region_alloc(&video->packet_buf, video->packet_buf_size, video->ohci->dev, PCI_DMA_FROMDEVICE); - if(retval) + if (retval) goto err; debug_printk("dv1394: Allocated %d packets in buffer, total %u pages (%u DMA pages), %lu bytes\n", @@ -1124,11 +1124,11 @@ video->dma_running = 0; - if( (video->ohci_it_ctx == -1) && (video->ohci_ir_ctx == -1) ) + if ( (video->ohci_it_ctx == -1) && (video->ohci_ir_ctx == -1) ) goto out; /* stop DMA if in progress */ - if( (video->active_frame != -1) || + if ( (video->active_frame != -1) || (reg_read(video->ohci, video->ohci_IsoXmitContextControlClear) & (1 << 10)) || (reg_read(video->ohci, video->ohci_IsoRcvContextControlClear) & (1 << 10)) ) { @@ -1142,12 +1142,12 @@ /* wait until DMA really stops */ i = 0; - while(i < 1000) { + while (i < 1000) { /* wait 0.1 millisecond */ udelay(100); - if( (reg_read(video->ohci, video->ohci_IsoXmitContextControlClear) & (1 << 10)) || + if ( (reg_read(video->ohci, video->ohci_IsoXmitContextControlClear) & (1 << 10)) || (reg_read(video->ohci, video->ohci_IsoRcvContextControlClear) & (1 << 10)) ) { /* still active */ debug_printk("dv1394: stop_dma: DMA not stopped yet\n" ); @@ -1160,7 +1160,7 @@ i++; } - if(i == 1000) { + if (i == 1000) { printk(KERN_ERR "dv1394: stop_dma: DMA still going after %d ms!\n", i/10); } } @@ -1183,7 +1183,7 @@ stop_dma(video); /* release the DMA contexts */ - if(video->ohci_it_ctx != -1) { + if (video->ohci_it_ctx != -1) { video->ohci_IsoXmitContextControlSet = 0; video->ohci_IsoXmitContextControlClear = 0; video->ohci_IsoXmitCommandPtr = 0; @@ -1197,7 +1197,7 @@ video->ohci_it_ctx = -1; } - if(video->ohci_ir_ctx != -1) { + if (video->ohci_ir_ctx != -1) { video->ohci_IsoRcvContextControlSet = 0; video->ohci_IsoRcvContextControlClear = 0; video->ohci_IsoRcvCommandPtr = 0; @@ -1213,7 +1213,7 @@ } /* release the ISO channel */ - if(video->channel != -1) { + if (video->channel != -1) { u64 chan_mask; unsigned long flags; @@ -1227,8 +1227,8 @@ } /* free the frame structs */ - for(i = 0; i < DV1394_MAX_FRAMES; i++) { - if(video->frames[i]) + for (i = 0; i < DV1394_MAX_FRAMES; i++) { + if (video->frames[i]) frame_delete(video->frames[i]); video->frames[i] = NULL; } @@ -1238,7 +1238,7 @@ /* we can't free the DMA buffer unless it is guaranteed that no more user-space mappings exist */ - if(free_dv_buf) { + if (free_dv_buf) { dma_region_free(&video->dv_buf); video->dv_buf_size = 0; } @@ -1282,9 +1282,9 @@ /* serialize mmap */ down(&video->sem); - if( ! video_card_initialized(video) ) { + if ( ! video_card_initialized(video) ) { retval = do_dv1394_init_default(video); - if(retval) + if (retval) goto out; } @@ -1306,14 +1306,14 @@ poll_wait(file, &video->waitq, wait); spin_lock_irqsave(&video->spinlock, flags); - if( video->n_frames == 0 ) { + if ( video->n_frames == 0 ) { - } else if( video->active_frame == -1 ) { + } else if ( video->active_frame == -1 ) { /* nothing going on */ mask |= POLLOUT; } else { /* any clear/ready buffers? */ - if(video->n_clear_frames >0) + if (video->n_clear_frames >0) mask |= POLLOUT | POLLIN; } spin_unlock_irqrestore(&video->spinlock, flags); @@ -1345,17 +1345,17 @@ int target_frame; /* serialize this to prevent multi-threaded mayhem */ - if(file->f_flags & O_NONBLOCK) { - if(down_trylock(&video->sem)) + if (file->f_flags & O_NONBLOCK) { + if (down_trylock(&video->sem)) return -EAGAIN; } else { - if(down_interruptible(&video->sem)) + if (down_interruptible(&video->sem)) return -ERESTARTSYS; } - if( !video_card_initialized(video) ) { + if ( !video_card_initialized(video) ) { ret = do_dv1394_init_default(video); - if(ret) { + if (ret) { up(&video->sem); return ret; } @@ -1364,7 +1364,7 @@ ret = 0; add_wait_queue(&video->waitq, &wait); - while(count > 0) { + while (count > 0) { /* must set TASK_INTERRUPTIBLE *before* checking for free buffers; otherwise we could miss a wakeup if the interrupt @@ -1378,7 +1378,7 @@ spin_unlock_irqrestore(&video->spinlock, flags); - if(video->frames[target_frame]->state == FRAME_CLEAR) { + if (video->frames[target_frame]->state == FRAME_CLEAR) { /* how much room is left in the target frame buffer */ cnt = video->frame_size - (video->write_off - target_frame * video->frame_size); @@ -1388,12 +1388,12 @@ cnt = 0; } - if(cnt > count) + if (cnt > count) cnt = count; if (cnt <= 0) { /* no room left, gotta wait */ - if(file->f_flags & O_NONBLOCK) { + if (file->f_flags & O_NONBLOCK) { if (!ret) ret = -EAGAIN; break; @@ -1409,8 +1409,8 @@ continue; /* start over from 'while(count > 0)...' */ } - if(copy_from_user(video->dv_buf.kvirt + video->write_off, buffer, cnt)) { - if(!ret) + if (copy_from_user(video->dv_buf.kvirt + video->write_off, buffer, cnt)) { + if (!ret) ret = -EFAULT; break; } @@ -1421,7 +1421,7 @@ buffer += cnt; ret += cnt; - if(video->write_off == video->frame_size * ((target_frame + 1) % video->n_frames)) + if (video->write_off == video->frame_size * ((target_frame + 1) % video->n_frames)) frame_prepare(video, target_frame); } @@ -1442,17 +1442,17 @@ int target_frame; /* serialize this to prevent multi-threaded mayhem */ - if(file->f_flags & O_NONBLOCK) { - if(down_trylock(&video->sem)) + if (file->f_flags & O_NONBLOCK) { + if (down_trylock(&video->sem)) return -EAGAIN; } else { - if(down_interruptible(&video->sem)) + if (down_interruptible(&video->sem)) return -ERESTARTSYS; } - if( !video_card_initialized(video) ) { + if ( !video_card_initialized(video) ) { ret = do_dv1394_init_default(video); - if(ret) { + if (ret) { up(&video->sem); return ret; } @@ -1466,7 +1466,7 @@ ret = 0; add_wait_queue(&video->waitq, &wait); - while(count > 0) { + while (count > 0) { /* must set TASK_INTERRUPTIBLE *before* checking for free buffers; otherwise we could miss a wakeup if the interrupt @@ -1480,7 +1480,7 @@ spin_unlock_irqrestore(&video->spinlock, flags); - if(target_frame >= 0 && + if (target_frame >= 0 && video->n_clear_frames > 0 && video->frames[target_frame]->state == FRAME_CLEAR) { @@ -1492,12 +1492,12 @@ cnt = 0; } - if(cnt > count) + if (cnt > count) cnt = count; if (cnt <= 0) { /* no room left, gotta wait */ - if(file->f_flags & O_NONBLOCK) { + if (file->f_flags & O_NONBLOCK) { if (!ret) ret = -EAGAIN; break; @@ -1513,8 +1513,8 @@ continue; /* start over from 'while(count > 0)...' */ } - if(copy_to_user(buffer, video->dv_buf.kvirt + video->write_off, cnt)) { - if(!ret) + if (copy_to_user(buffer, video->dv_buf.kvirt + video->write_off, cnt)) { + if (!ret) ret = -EFAULT; break; } @@ -1525,7 +1525,7 @@ buffer += cnt; ret += cnt; - if(video->write_off == video->frame_size * ((target_frame + 1) % video->n_frames)) { + if (video->write_off == video->frame_size * ((target_frame + 1) % video->n_frames)) { spin_lock_irqsave(&video->spinlock, flags); video->n_clear_frames--; video->first_clear_frame = (video->first_clear_frame + 1) % video->n_frames; @@ -1555,11 +1555,11 @@ DECLARE_WAITQUEUE(wait, current); /* serialize this to prevent multi-threaded mayhem */ - if(file->f_flags & O_NONBLOCK) { - if(down_trylock(&video->sem)) + if (file->f_flags & O_NONBLOCK) { + if (down_trylock(&video->sem)) return -EAGAIN; } else { - if(down_interruptible(&video->sem)) + if (down_interruptible(&video->sem)) return -ERESTARTSYS; } @@ -1568,20 +1568,20 @@ case DV1394_IOC_SUBMIT_FRAMES: { unsigned int n_submit; - if( !video_card_initialized(video) ) { + if ( !video_card_initialized(video) ) { ret = do_dv1394_init_default(video); - if(ret) + if (ret) goto out; } n_submit = (unsigned int) arg; - if(n_submit > video->n_frames) { + if (n_submit > video->n_frames) { ret = -EINVAL; goto out; } - while(n_submit > 0) { + while (n_submit > 0) { add_wait_queue(&video->waitq, &wait); set_current_state(TASK_INTERRUPTIBLE); @@ -1589,11 +1589,11 @@ spin_lock_irqsave(&video->spinlock, flags); /* wait until video->first_clear_frame is really CLEAR */ - while(video->frames[video->first_clear_frame]->state != FRAME_CLEAR) { + while (video->frames[video->first_clear_frame]->state != FRAME_CLEAR) { spin_unlock_irqrestore(&video->spinlock, flags); - if(signal_pending(current)) { + if (signal_pending(current)) { remove_wait_queue(&video->waitq, &wait); set_current_state(TASK_RUNNING); ret = -EINTR; @@ -1622,7 +1622,7 @@ case DV1394_IOC_WAIT_FRAMES: { unsigned int n_wait; - if( !video_card_initialized(video) ) { + if ( !video_card_initialized(video) ) { ret = -EINVAL; goto out; } @@ -1633,7 +1633,7 @@ never actually have n_frames clear frames; at most only n_frames - 1 */ - if(n_wait > (video->n_frames-1) ) { + if (n_wait > (video->n_frames-1) ) { ret = -EINVAL; goto out; } @@ -1643,11 +1643,11 @@ spin_lock_irqsave(&video->spinlock, flags); - while(video->n_clear_frames < n_wait) { + while (video->n_clear_frames < n_wait) { spin_unlock_irqrestore(&video->spinlock, flags); - if(signal_pending(current)) { + if (signal_pending(current)) { remove_wait_queue(&video->waitq, &wait); set_current_state(TASK_RUNNING); ret = -EINTR; @@ -1671,7 +1671,7 @@ case DV1394_IOC_RECEIVE_FRAMES: { unsigned int n_recv; - if( !video_card_initialized(video) ) { + if ( !video_card_initialized(video) ) { ret = -EINVAL; goto out; } @@ -1679,7 +1679,7 @@ n_recv = (unsigned int) arg; /* at least one frame must be active */ - if(n_recv > (video->n_frames-1) ) { + if (n_recv > (video->n_frames-1) ) { ret = -EINVAL; goto out; } @@ -1702,9 +1702,9 @@ } case DV1394_IOC_START_RECEIVE: { - if( !video_card_initialized(video) ) { + if ( !video_card_initialized(video) ) { ret = do_dv1394_init_default(video); - if(ret) + if (ret) goto out; } @@ -1720,10 +1720,10 @@ case DV1394_IOC_INIT: { struct dv1394_init init; - if(arg == (unsigned long) NULL) { + if (arg == (unsigned long) NULL) { ret = do_dv1394_init_default(video); } else { - if(copy_from_user(&init, (void*)arg, sizeof(init))) { + if (copy_from_user(&init, (void*)arg, sizeof(init))) { ret = -EFAULT; goto out; } @@ -1741,7 +1741,7 @@ case DV1394_IOC_GET_STATUS: { struct dv1394_status status; - if( !video_card_initialized(video) ) { + if ( !video_card_initialized(video) ) { ret = -EINVAL; goto out; } @@ -1769,7 +1769,7 @@ spin_unlock_irqrestore(&video->spinlock, flags); - if(copy_to_user((void*)arg, &status, sizeof(status))) { + if (copy_to_user((void*)arg, &status, sizeof(status))) { ret = -EFAULT; goto out; } @@ -1797,7 +1797,7 @@ /* if the device was opened through devfs, then file->private_data has already been set to video by devfs */ - if(file->private_data) { + if (file->private_data) { video = (struct video_card*) file->private_data; } else { @@ -1807,11 +1807,11 @@ unsigned long flags; spin_lock_irqsave(&dv1394_cards_lock, flags); - if(!list_empty(&dv1394_cards)) { + if (!list_empty(&dv1394_cards)) { struct video_card *p; list_for_each(lh, &dv1394_cards) { p = list_entry(lh, struct video_card, list); - if((p->id) == ieee1394_file_to_instance(file)) { + if ((p->id) == ieee1394_file_to_instance(file)) { video = p; break; } @@ -1819,7 +1819,7 @@ } spin_unlock_irqrestore(&dv1394_cards_lock, flags); - if(!video) { + if (!video) { debug_printk("dv1394: OHCI card %d not found", ieee1394_file_to_instance(file)); return -ENODEV; } @@ -1829,7 +1829,7 @@ #ifndef DV1394_ALLOW_MORE_THAN_ONE_OPEN - if( test_and_set_bit(0, &video->open) ) { + if ( test_and_set_bit(0, &video->open) ) { /* video is already open by someone else */ return -EBUSY; } @@ -1971,10 +1971,10 @@ struct dv1394_procfs_entry *p; spin_lock( &dv1394_procfs_lock); - if(!list_empty(&dv1394_procfs)) { + if (!list_empty(&dv1394_procfs)) { list_for_each(lh, &dv1394_procfs) { p = list_entry(lh, struct dv1394_procfs_entry, list); - if(!strncmp(p->name, name, sizeof(p->name))) { + if (!strncmp(p->name, name, sizeof(p->name))) { spin_unlock( &dv1394_procfs_lock); return p; } @@ -1991,7 +1991,7 @@ struct dv1394_procfs_entry *parent; p = kmalloc(sizeof(struct dv1394_procfs_entry), GFP_KERNEL); - if(!p) { + if (!p) { printk(KERN_ERR "dv1394: cannot allocate dv1394_procfs_entry\n"); goto err; } @@ -2043,7 +2043,7 @@ struct dv1394_procfs_entry *p; p = kmalloc(sizeof(struct dv1394_procfs_entry), GFP_KERNEL); - if(!p) { + if (!p) { printk(KERN_ERR "dv1394: cannot allocate dv1394_procfs_entry\n"); goto err; } @@ -2104,7 +2104,7 @@ spin_lock(&video->spinlock); - if(!video->dma_running) + if (!video->dma_running) goto out; irq_printk("ContextControl = %08x, CommandPtr = %08x\n", @@ -2113,24 +2113,24 @@ ); - if( (video->ohci_it_ctx != -1) && + if ( (video->ohci_it_ctx != -1) && (reg_read(video->ohci, video->ohci_IsoXmitContextControlSet) & (1 << 10)) ) { struct frame *f; unsigned int frame, i; - if(video->active_frame == -1) + if (video->active_frame == -1) frame = 0; else frame = video->active_frame; /* check all the DMA-able frames */ - for(i = 0; i < video->n_frames; i++, frame = (frame+1) % video->n_frames) { + for (i = 0; i < video->n_frames; i++, frame = (frame+1) % video->n_frames) { irq_printk("IRQ checking frame %d...", frame); f = video->frames[frame]; - if(f->state != FRAME_READY) { + if (f->state != FRAME_READY) { irq_printk("clear, skipping\n"); /* we don't own this frame */ continue; @@ -2139,7 +2139,7 @@ irq_printk("DMA\n"); /* check the frame begin semaphore to see if we can free the previous frame */ - if( *(f->frame_begin_timestamp) ) { + if ( *(f->frame_begin_timestamp) ) { int prev_frame; struct frame *prev_f; @@ -2149,13 +2149,13 @@ irq_printk(" BEGIN\n"); prev_frame = frame - 1; - if(prev_frame == -1) + if (prev_frame == -1) prev_frame += video->n_frames; prev_f = video->frames[prev_frame]; /* make sure we can actually garbage collect this frame */ - if( (prev_f->state == FRAME_READY) && + if ( (prev_f->state == FRAME_READY) && prev_f->done && (!f->done) ) { frame_reset(prev_f); @@ -2173,7 +2173,7 @@ /* see if we need to set the timestamp for the next frame */ - if( *(f->mid_frame_timestamp) ) { + if ( *(f->mid_frame_timestamp) ) { struct frame *next_frame; u32 begin_ts, ts_cyc, ts_off; @@ -2188,7 +2188,7 @@ /* prepare next frame and assign timestamp */ next_frame = video->frames[ (frame+1) % video->n_frames ]; - if(next_frame->state == FRAME_READY) { + if (next_frame->state == FRAME_READY) { irq_printk(" MIDDLE - next frame is ready, good\n"); } else { debug_printk("dv1394: Underflow! At least one frame has been dropped.\n"); @@ -2207,11 +2207,11 @@ ts_off %= 3072; next_frame->assigned_timestamp = ((ts_cyc&0xF) << 12) + ts_off; - if(next_frame->cip_syt1) { + if (next_frame->cip_syt1) { next_frame->cip_syt1->b[6] = next_frame->assigned_timestamp >> 8; next_frame->cip_syt1->b[7] = next_frame->assigned_timestamp & 0xFF; } - if(next_frame->cip_syt2) { + if (next_frame->cip_syt2) { next_frame->cip_syt2->b[6] = next_frame->assigned_timestamp >> 8; next_frame->cip_syt2->b[7] = next_frame->assigned_timestamp & 0xFF; } @@ -2219,7 +2219,7 @@ } /* see if the frame looped */ - if( *(f->frame_end_timestamp) ) { + if ( *(f->frame_end_timestamp) ) { *(f->frame_end_timestamp) = 0; @@ -2230,10 +2230,10 @@ - } /* for(each frame) */ + } /* for (each frame) */ } - if(wake) { + if (wake) { kill_fasync(&video->fasync, SIGIO, POLL_OUT); /* wake readers/writers/ioctl'ers */ @@ -2251,10 +2251,10 @@ spin_lock(&video->spinlock); - if(!video->dma_running) + if (!video->dma_running) goto out; - if( (video->ohci_ir_ctx != -1) && + if ( (video->ohci_ir_ctx != -1) && (reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 10)) ) { @@ -2374,7 +2374,7 @@ prev_i = (next_i == 0) ? (MAX_PACKETS * video->n_frames - 1) : (next_i - 1); f = video->frames[prev_i / MAX_PACKETS]; prev = &(f->descriptor_pool[prev_i % MAX_PACKETS]); - if(prev_i % (MAX_PACKETS/2)) { + if (prev_i % (MAX_PACKETS/2)) { prev->u.in.il.q[0] &= ~(3 << 20); /* no interrupt */ } else { prev->u.in.il.q[0] |= 3 << 20; /* enable interrupt */ @@ -2394,7 +2394,7 @@ } /* receive interrupt */ - if(wake) { + if (wake) { kill_fasync(&video->fasync, SIGIO, POLL_IN); /* wake readers/writers/ioctl'ers */ @@ -2453,7 +2453,7 @@ int i; video = kmalloc(sizeof(struct video_card), GFP_KERNEL); - if(!video) { + if (!video) { printk(KERN_ERR "dv1394: cannot allocate video_card\n"); goto err; } @@ -2497,7 +2497,7 @@ goto err_free; #endif - for(i = 0; i < DV1394_MAX_FRAMES; i++) + for (i = 0; i < DV1394_MAX_FRAMES; i++) video->frames[i] = NULL; dma_region_init(&video->dv_buf); @@ -2574,10 +2574,10 @@ /* find the corresponding video_cards */ spin_lock_irqsave(&dv1394_cards_lock, flags); - if(!list_empty(&dv1394_cards)) { + if (!list_empty(&dv1394_cards)) { list_for_each_safe(lh, templh, &dv1394_cards) { video = list_entry(lh, struct video_card, list); - if((video->id >> 2) == ohci->id) + if ((video->id >> 2) == ohci->id) dv1394_un_init(video); } } @@ -2655,32 +2655,32 @@ /* find the corresponding video_cards */ spin_lock_irqsave(&dv1394_cards_lock, flags); - if(!list_empty(&dv1394_cards)) { + if (!list_empty(&dv1394_cards)) { list_for_each(lh, &dv1394_cards) { video = list_entry(lh, struct video_card, list); - if((video->id >> 2) == ohci->id) + if ((video->id >> 2) == ohci->id) break; } } spin_unlock_irqrestore(&dv1394_cards_lock, flags); - if(!video) + if (!video) return; spin_lock_irqsave(&video->spinlock, flags); - if(!video->dma_running) + if (!video->dma_running) goto out; /* check IT context */ - if(video->ohci_it_ctx != -1) { + if (video->ohci_it_ctx != -1) { u32 ctx; ctx = reg_read(video->ohci, video->ohci_IsoXmitContextControlSet); - /* if(RUN but not ACTIVE) */ - if( (ctx & (1<<15)) && + /* if (RUN but not ACTIVE) */ + if ( (ctx & (1<<15)) && !(ctx & (1<<10)) ) { debug_printk("dv1394: IT context stopped due to bus reset; waking it up\n"); @@ -2710,13 +2710,13 @@ } /* check IR context */ - if(video->ohci_ir_ctx != -1) { + if (video->ohci_ir_ctx != -1) { u32 ctx; ctx = reg_read(video->ohci, video->ohci_IsoRcvContextControlSet); - /* if(RUN but not ACTIVE) */ - if( (ctx & (1<<15)) && + /* if (RUN but not ACTIVE) */ + if ( (ctx & (1<<15)) && !(ctx & (1<<10)) ) { debug_printk("dv1394: IR context stopped due to bus reset; waking it up\n"); diff -Nru a/drivers/ieee1394/dv1394.h b/drivers/ieee1394/dv1394.h --- a/drivers/ieee1394/dv1394.h Tue Jul 1 18:44:36 2003 +++ b/drivers/ieee1394/dv1394.h Tue Jul 1 18:44:36 2003 @@ -64,7 +64,7 @@ ioctl(fd, DV1394_INIT, &init); - while(1) { + while (1) { read( , buf, DV1394_NTSC_FRAME_SIZE ); write( , buf, DV1394_NTSC_FRAME_SIZE ); } @@ -145,7 +145,7 @@ (checks of system call return values omitted for brevity; always check return values in your code!) - while( frames left ) { + while ( frames left ) { struct pollfd *pfd = ...; @@ -157,15 +157,15 @@ poll(pfd, 1, -1); (or select(); add a timeout if you want) - if(pfd->revents) { + if (pfd->revents) { struct dv1394_status status; ioctl(dv1394_fd, DV1394_GET_STATUS, &status); - if(status.dropped_frames > 0) { + if (status.dropped_frames > 0) { reset_dv1394(); } else { - for(int i = 0; i < status.n_clear_frames; i++) { + for (int i = 0; i < status.n_clear_frames; i++) { copy_DV_frame(); } } diff -Nru a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c --- a/drivers/ieee1394/eth1394.c Tue Jul 1 18:44:36 2003 +++ b/drivers/ieee1394/eth1394.c Tue Jul 1 18:44:36 2003 @@ -1,7 +1,7 @@ /* * eth1394.c -- Ethernet driver for Linux IEEE-1394 Subsystem * - * Copyright (C) 2001 Ben Collins + * Copyright (C) 2001-2003 Ben Collins * 2000 Bonin Franck * 2003 Steve Kinneberg * @@ -30,10 +30,10 @@ * TODO: * RFC 2734 related: * - Add Config ROM entry - * - Add MCAP and multicast + * - Add MCAP. Limited Multicast exists only to 224.0.0.1 and 224.0.0.2. * * Non-RFC 2734 related: - * - Fix bug related to fragmented broadcast datagrams + * - Handle fragmented skb's coming from the networking layer. * - Move generic GASP reception to core 1394 code * - Convert kmalloc/kfree for link fragments to use kmem_cache_* instead * - Stability improvements @@ -59,9 +59,12 @@ #include #include #include +#include #include #include #include +#include +#include #include #include #include @@ -76,17 +79,17 @@ #include "eth1394.h" #define ETH1394_PRINT_G(level, fmt, args...) \ - printk(level ETHER1394_DRIVER_NAME": "fmt, ## args) + printk(level "%s: " fmt, driver_name, ## args) #define ETH1394_PRINT(level, dev_name, fmt, args...) \ - printk(level ETHER1394_DRIVER_NAME": %s: " fmt, dev_name, ## args) + printk(level "%s: %s: " fmt, driver_name, dev_name, ## args) #define DEBUG(fmt, args...) \ - printk(KERN_ERR "eth1394:%s[%d]: "fmt"\n", __FUNCTION__, __LINE__, ## args) -#define TRACE() printk(KERN_ERR "eth1394:%s[%d] ---- TRACE\n", __FUNCTION__, __LINE__) + printk(KERN_ERR "%s:%s[%d]: " fmt "\n", driver_name, __FUNCTION__, __LINE__, ## args) +#define TRACE() printk(KERN_ERR "%s:%s[%d] ---- TRACE\n", driver_name, __FUNCTION__, __LINE__) static char version[] __devinitdata = - "$Rev: 951 $ Ben Collins "; + "$Rev: 986 $ Ben Collins "; struct fragment_info { struct list_head list; @@ -105,7 +108,7 @@ }; /* Our ieee1394 highlevel driver */ -#define ETHER1394_DRIVER_NAME "ether1394" +static const char driver_name[] = "eth1394"; static kmem_cache_t *packet_task_cache; @@ -119,6 +122,12 @@ sizeof (struct eth1394_sf_hdr) }; +/* Change this to IEEE1394_SPEED_S100 to make testing easier */ +#define ETH1394_SPEED_DEF IEEE1394_SPEED_MAX + +/* For now, this needs to be 1500, so that XP works with us */ +#define ETH1394_DATA_LEN ETH_DATA_LEN + static const u16 eth1394_speedto_maxpayload[] = { /* S100, S200, S400, S800, S1600, S3200 */ 512, 1024, 2048, 4096, 8192, 16384 @@ -156,15 +165,27 @@ static int ether1394_tx(struct sk_buff *skb, struct net_device *dev); static void ether1394_iso(struct hpsb_iso *iso); +static int ether1394_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); +static int ether1394_ethtool_ioctl(struct net_device *dev, void *useraddr); + +static void eth1394_iso_shutdown(struct eth1394_priv *priv) +{ + priv->bc_state = ETHER1394_BC_CLOSED; + + if (priv->iso != NULL) { + if (!in_interrupt()) + hpsb_iso_shutdown(priv->iso); + priv->iso = NULL; + } +} static int ether1394_init_bc(struct net_device *dev) { - int ret = 0; struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv; /* First time sending? Need a broadcast channel for ARP and for * listening on */ - if(priv->bc_state == ETHER1394_BC_CHECK) { + if (priv->bc_state == ETHER1394_BC_CHECK) { quadlet_t bc; /* Get the local copy of the broadcast channel and check its @@ -172,30 +193,25 @@ bc = priv->host->csr.broadcast_channel; - if((bc & 0xc0000000) != 0xc0000000) { + if ((bc & 0xc0000000) != 0xc0000000) { /* broadcast channel not validated yet */ ETH1394_PRINT(KERN_WARNING, dev->name, "Error BROADCAST_CHANNEL register valid " "bit not set, can't send IP traffic\n"); - if(!in_interrupt()) { - hpsb_iso_shutdown(priv->iso); - priv->bc_state = ETHER1394_BC_CLOSED; - } - ret = -EAGAIN; - goto fail; + + eth1394_iso_shutdown(priv); + + return -EAGAIN; } - if(priv->broadcast_channel != (bc & 0x3f)) { + if (priv->broadcast_channel != (bc & 0x3f)) { /* This really shouldn't be possible, but just in case * the IEEE 1394 spec changes regarding broadcast * channels in the future. */ - if(in_interrupt()) { - ret = -EAGAIN; - goto fail; - - } + eth1394_iso_shutdown(priv); - hpsb_iso_shutdown(priv->iso); + if (in_interrupt()) + return -EAGAIN; priv->broadcast_channel = bc & 0x3f; ETH1394_PRINT(KERN_INFO, dev->name, @@ -205,29 +221,25 @@ priv->iso = hpsb_iso_recv_init(priv->host, 16 * 4096, 16, priv->broadcast_channel, 1, ether1394_iso); - if(priv->iso == NULL) { + if (priv->iso == NULL) { ETH1394_PRINT(KERN_ERR, dev->name, "failed to change broadcast " "channel\n"); - ret = -EAGAIN; - goto fail; + return -EAGAIN; } } - if(hpsb_iso_recv_start(priv->iso, -1, (1 << 3), -1) < 0) { + if (hpsb_iso_recv_start(priv->iso, -1, (1 << 3), -1) < 0) { ETH1394_PRINT(KERN_ERR, dev->name, "Could not start data stream reception\n"); - if(!in_interrupt()) { - hpsb_iso_shutdown(priv->iso); - priv->bc_state = ETHER1394_BC_CLOSED; - } - ret = -EAGAIN; - goto fail; + + eth1394_iso_shutdown(priv); + + return -EAGAIN; } priv->bc_state = ETHER1394_BC_OPENED; } -fail: - return ret; + return 0; } /* This is called after an "ifup" */ @@ -237,13 +249,15 @@ unsigned long flags; int ret; - /* Set the spinlock before grabbing IRQ! */ - priv->lock = SPIN_LOCK_UNLOCKED; + /* Something bad happened, don't even try */ + if (priv->bc_state == ETHER1394_BC_CLOSED) + return -EAGAIN; + spin_lock_irqsave(&priv->lock, flags); ret = ether1394_init_bc(dev); spin_unlock_irqrestore(&priv->lock, flags); - if(ret) + if (ret) return ret; netif_start_queue (dev); @@ -280,9 +294,8 @@ struct eth1394_priv *priv = (struct eth1394_priv *)dev->priv; int phy_id = NODEID_TO_NODE(priv->host->node_id); - if ((new_mtu < 68) || (new_mtu > (priv->maxpayload[phy_id] - - (sizeof(union eth1394_hdr) + - ETHER1394_GASP_OVERHEAD)))) + if ((new_mtu < 68) || (new_mtu > min(ETH1394_DATA_LEN, (int)(priv->maxpayload[phy_id] - + (sizeof(union eth1394_hdr) + ETHER1394_GASP_OVERHEAD))))) return -EINVAL; dev->mtu = new_mtu; return 0; @@ -325,15 +338,8 @@ memset (priv->sspd, 0, sizeof (priv->sspd)); memset (priv->fifo, 0, sizeof (priv->fifo)); -#if 0 -/* Compile this out to make testing of fragmented broadcast datagrams - * easier. */ - priv->sspd[ALL_NODES] = SPEED_MAX; - priv->maxpayload[ALL_NODES] = eth1394_speedto_maxpayload[SPEED_MAX]; -#else - priv->sspd[ALL_NODES] = SPEED_100; - priv->maxpayload[ALL_NODES] = eth1394_speedto_maxpayload[SPEED_100]; -#endif + priv->sspd[ALL_NODES] = ETH1394_SPEED_DEF; + priv->maxpayload[ALL_NODES] = eth1394_speedto_maxpayload[priv->sspd[ALL_NODES]]; priv->bc_state = ETHER1394_BC_CHECK; @@ -344,8 +350,8 @@ /* We'll use our maxpayload as the default mtu */ if (set_mtu) { - dev->mtu = priv->maxpayload[phy_id] - (sizeof(union eth1394_hdr) + - ETHER1394_GASP_OVERHEAD); + dev->mtu = min(ETH1394_DATA_LEN, (int)(priv->maxpayload[phy_id] - + (sizeof(union eth1394_hdr) + ETHER1394_GASP_OVERHEAD))); /* Set our hardware address while we're at it */ *(u64*)dev->dev_addr = guid; @@ -354,11 +360,11 @@ spin_unlock_irqrestore (&priv->lock, flags); - for(i = 0; i < ALL_NODES; i++) { + for (i = 0; i < ALL_NODES; i++) { struct list_head *lh, *n; spin_lock_irqsave(&priv->pdg[i].lock, flags); - if(!set_mtu) { + if (!set_mtu) { list_for_each_safe(lh, n, &priv->pdg[i].list) { purge_partial_datagram(lh); } @@ -386,11 +392,12 @@ dev->header_cache_update= ether1394_header_cache_update; dev->hard_header_parse = ether1394_header_parse; dev->set_mac_address = ether1394_mac_addr; + dev->do_ioctl = ether1394_do_ioctl; /* Some constants */ dev->watchdog_timeo = ETHER1394_TIMEOUT; - dev->flags = IFF_BROADCAST; /* | IFF_MULTICAST someday */ - dev->features = NETIF_F_NO_CSUM|NETIF_F_SG|NETIF_F_HIGHDMA|NETIF_F_FRAGLIST; + dev->flags = IFF_BROADCAST | IFF_MULTICAST; + dev->features = NETIF_F_HIGHDMA; dev->addr_len = ETH1394_ALEN; dev->hard_header_len = ETH1394_HLEN; dev->type = ARPHRD_IEEE1394; @@ -421,8 +428,12 @@ * it for ourselves. That way we'd be a real networking device. */ dev = alloc_etherdev(sizeof (struct eth1394_priv)); - if (dev == NULL) + if (dev == NULL) { + ETH1394_PRINT_G (KERN_ERR, "Out of memory trying to allocate " + "etherdevice for IEEE 1394 device %s-%d\n", + host->driver->name, host->id); goto out; + } SET_MODULE_OWNER(dev); @@ -430,10 +441,10 @@ priv = (struct eth1394_priv *)dev->priv; - priv->host = host; spin_lock_init(&priv->lock); + priv->host = host; - for(i = 0; i < ALL_NODES; i++) { + for (i = 0; i < ALL_NODES; i++) { spin_lock_init(&priv->pdg[i].lock); INIT_LIST_HEAD(&priv->pdg[i].list); priv->pdg[i].sz = 0; @@ -441,8 +452,12 @@ hi = hpsb_create_hostinfo(ð1394_highlevel, host, sizeof(*hi)); - if (hi == NULL) + if (hi == NULL) { + ETH1394_PRINT_G (KERN_ERR, "Out of memory trying to create " + "hostinfo for IEEE 1394 device %s-%d\n", + host->driver->name, host->id); goto out; + } if (register_netdev (dev)) { ETH1394_PRINT (KERN_ERR, dev->name, "Error registering network driver\n"); @@ -472,8 +487,6 @@ if (hi) hpsb_destroy_hostinfo(ð1394_highlevel, host); - ETH1394_PRINT_G (KERN_ERR, "Out of memory\n"); - return; } @@ -485,11 +498,12 @@ if (hi != NULL) { struct eth1394_priv *priv = (struct eth1394_priv *)hi->dev->priv; - priv->bc_state = ETHER1394_BC_CLOSED; - unregister_netdev (hi->dev); - hpsb_iso_shutdown(priv->iso); + eth1394_iso_shutdown(priv); - kfree(hi->dev); + if (hi->dev) { + unregister_netdev (hi->dev); + kfree(hi->dev); + } } return; @@ -536,7 +550,7 @@ return(dev->hard_header_len); } - if(daddr) + if (daddr) { memcpy(eth->h_dest,daddr,dev->addr_len); return dev->hard_header_len; @@ -579,7 +593,7 @@ { struct net_device *dev = skb->dev; memcpy(haddr, dev->dev_addr, ETH1394_ALEN); - return ETH_ALEN; + return ETH1394_ALEN; } @@ -635,15 +649,15 @@ skb_pull (skb, ETH1394_HLEN); eth = (struct eth1394hdr*)skb->mac.raw; - if(*eth->h_dest & 1) { - if(memcmp(eth->h_dest, dev->broadcast, dev->addr_len)==0) + if (*eth->h_dest & 1) { + if (memcmp(eth->h_dest, dev->broadcast, dev->addr_len)==0) skb->pkt_type = PACKET_BROADCAST; #if 0 else skb->pkt_type = PACKET_MULTICAST; #endif } else { - if(memcmp(eth->h_dest, dev->dev_addr, dev->addr_len)) + if (memcmp(eth->h_dest, dev->dev_addr, dev->addr_len)) skb->pkt_type = PACKET_OTHERHOST; } @@ -671,7 +685,7 @@ /* Setup our hw addresses. We use these to build the * ethernet header. */ - if(destid == (LOCAL_BUS | ALL_NODES)) + if (destid == (LOCAL_BUS | ALL_NODES)) dest_hw = ~0ULL; /* broadcast */ else dest_hw = priv->eui[NODEID_TO_NODE(destid)]; @@ -716,7 +730,7 @@ *(u32*)arp_ptr = arp1394->sip; /* move sender IP addr */ arp_ptr += arp->ar_pln; /* skip over sender IP addr */ - if(arp->ar_op == 1) + if (arp->ar_op == 1) /* just set ARP req target unique ID to 0 */ memset(arp_ptr, 0, ETH1394_ALEN); else @@ -739,7 +753,7 @@ list_for_each(lh, frag_list) { fi = list_entry(lh, struct fragment_info, list); - if( ! ((offset > (fi->offset + fi->len - 1)) || + if ( ! ((offset > (fi->offset + fi->len - 1)) || ((offset + len - 1) < fi->offset))) return 1; } @@ -753,7 +767,7 @@ list_for_each(lh, pdgl) { pd = list_entry(lh, struct partial_datagram, list); - if(pd->dgl == dgl) + if (pd->dgl == dgl) return lh; } return NULL; @@ -767,32 +781,32 @@ list_for_each(lh, frag_info) { fi = list_entry(lh, struct fragment_info, list); - if((fi->offset + fi->len) == offset) { + if ((fi->offset + fi->len) == offset) { /* The new fragment can be tacked on to the end */ fi->len += len; /* Did the new fragment plug a hole? */ fi2 = list_entry(lh->next, struct fragment_info, list); - if((fi->offset + fi->len) == fi2->offset) { + if ((fi->offset + fi->len) == fi2->offset) { /* glue fragments together */ fi->len += fi2->len; list_del(lh->next); kfree(fi2); } return 0; - } else if((offset + len) == fi->offset) { + } else if ((offset + len) == fi->offset) { /* The new fragment can be tacked on to the beginning */ fi->offset = offset; fi->len += len; /* Did the new fragment plug a hole? */ fi2 = list_entry(lh->prev, struct fragment_info, list); - if((fi2->offset + fi2->len) == fi->offset) { + if ((fi2->offset + fi2->len) == fi->offset) { /* glue fragments together */ fi2->len += fi->len; list_del(lh); kfree(fi); } return 0; - } else if(offset > (fi->offset + fi->len)) { + } else if (offset > (fi->offset + fi->len)) { break; } else if ((offset + len) < fi->offset) { lh = lh->prev; @@ -801,7 +815,7 @@ } new = kmalloc(sizeof(struct fragment_info), GFP_ATOMIC); - if(!new) + if (!new) return -ENOMEM; new->offset = offset; @@ -820,12 +834,12 @@ struct partial_datagram *new; new = kmalloc(sizeof(struct partial_datagram), GFP_ATOMIC); - if(!new) + if (!new) return -ENOMEM; INIT_LIST_HEAD(&new->frag_info); - if(new_fragment(&new->frag_info, frag_off, frag_len) < 0) { + if (new_fragment(&new->frag_info, frag_off, frag_len) < 0) { kfree(new); return -ENOMEM; } @@ -834,7 +848,7 @@ new->dg_size = dg_size; new->skb = dev_alloc_skb(dg_size + dev->hard_header_len + 15); - if(!new->skb) { + if (!new->skb) { struct fragment_info *fi = list_entry(new->frag_info.next, struct fragment_info, list); @@ -857,7 +871,7 @@ { struct partial_datagram *pd = list_entry(lh, struct partial_datagram, list); - if(new_fragment(&pd->frag_info, frag_off, frag_len) < 0) { + if (new_fragment(&pd->frag_info, frag_off, frag_len) < 0) { return -ENOMEM; } @@ -915,7 +929,7 @@ hdr_len = hdr_type_len[hdr->common.lf]; - if(hdr->common.lf == ETH1394_HDR_LF_UF) { + if (hdr->common.lf == ETH1394_HDR_LF_UF) { /* An unfragmented datagram has been received by the ieee1394 * bus. Build an skbuff around it so we can pass it to the * high level network layer. */ @@ -945,15 +959,15 @@ hdr->words.word3 = ntohs(hdr->words.word3); /* The 4th header word is reserved so no need to do ntohs() */ - if(hdr->common.lf == ETH1394_HDR_LF_FF) { + if (hdr->common.lf == ETH1394_HDR_LF_FF) { ether_type = hdr->ff.ether_type; dgl = hdr->ff.dgl; - dg_size = hdr->ff.dg_size; + dg_size = hdr->ff.dg_size + 1; fg_off = 0; } else { hdr->words.word2 = ntohs(hdr->words.word2); dgl = hdr->sf.dgl; - dg_size = hdr->sf.dg_size; + dg_size = hdr->sf.dg_size + 1; fg_off = hdr->sf.fg_off; } spin_lock_irqsave(&pdg->lock, flags); @@ -961,8 +975,8 @@ pdgl = &(pdg->list); lh = find_partial_datagram(pdgl, dgl); - if(lh == NULL) { - if(pdg->sz == max_partial_datagrams) { + if (lh == NULL) { + if (pdg->sz == max_partial_datagrams) { /* remove the oldest */ purge_partial_datagram(pdgl->prev); pdg->sz--; @@ -971,7 +985,7 @@ retval = new_partial_datagram(dev, pdgl, dgl, dg_size, buf + hdr_len, fg_off, fg_len); - if(retval < 0) { + if (retval < 0) { spin_unlock_irqrestore(&pdg->lock, flags); goto bad_proto; } @@ -982,7 +996,7 @@ pd = list_entry(lh, struct partial_datagram, list); - if(fragment_overlap(&pd->frag_info, fg_off, fg_len)) { + if (fragment_overlap(&pd->frag_info, fg_off, fg_len)) { /* Overlapping fragments, obliterate old * datagram and start new one. */ purge_partial_datagram(lh); @@ -990,7 +1004,7 @@ dg_size, buf + hdr_len, fg_off, fg_len); - if(retval < 0) { + if (retval < 0) { pdg->sz--; spin_unlock_irqrestore(&pdg->lock, flags); goto bad_proto; @@ -999,7 +1013,7 @@ retval = update_partial_datagram(pdgl, lh, buf + hdr_len, fg_off, fg_len); - if(retval < 0) { + if (retval < 0) { /* Couldn't save off fragment anyway * so might as well obliterate the * datagram now. */ @@ -1013,11 +1027,11 @@ pd = list_entry(lh, struct partial_datagram, list); - if(hdr->common.lf == ETH1394_HDR_LF_FF) { + if (hdr->common.lf == ETH1394_HDR_LF_FF) { pd->ether_type = ether_type; } - if(is_datagram_complete(lh, dg_size)) { + if (is_datagram_complete(lh, dg_size)) { ether_type = pd->ether_type; pdg->sz--; skb = skb_get(pd->skb); @@ -1044,14 +1058,14 @@ spin_lock_irqsave(&priv->lock, flags); - if(!skb->protocol) { + if (!skb->protocol) { priv->stats.rx_errors++; priv->stats.rx_dropped++; dev_kfree_skb_any(skb); goto bad_proto; } - if(netif_rx(skb) == NET_RX_DROP) { + if (netif_rx(skb) == NET_RX_DROP) { priv->stats.rx_errors++; priv->stats.rx_dropped++; goto bad_proto; @@ -1062,7 +1076,7 @@ priv->stats.rx_bytes += skb->len; bad_proto: - if(netif_queue_stopped(dev)) + if (netif_queue_stopped(dev)) netif_wake_queue(dev); spin_unlock_irqrestore(&priv->lock, flags); @@ -1076,13 +1090,13 @@ { struct host_info *hi = hpsb_get_hostinfo(ð1394_highlevel, host); - if(hi == NULL) { + if (hi == NULL) { ETH1394_PRINT_G(KERN_ERR, "Could not find net device for host %s\n", host->driver->name); return RCODE_ADDRESS_ERROR; } - if(ether1394_data_handler(hi->dev, srcid, destid, (char*)data, len)) + if (ether1394_data_handler(hi->dev, srcid, destid, (char*)data, len)) return RCODE_ADDRESS_ERROR; else return RCODE_COMPLETE; @@ -1101,7 +1115,7 @@ int i; int nready; - if(hi == NULL) { + if (hi == NULL) { ETH1394_PRINT_G(KERN_ERR, "Could not find net device for host %s\n", iso->host->driver->name); return; @@ -1110,7 +1124,7 @@ dev = hi->dev; nready = hpsb_iso_n_ready(iso); - for(i = 0; i < nready; i++) { + for (i = 0; i < nready; i++) { struct hpsb_iso_packet_info *info = &iso->infos[iso->first_packet + i]; data = (quadlet_t*) (iso->data_buf.kvirt + info->offset); @@ -1124,7 +1138,7 @@ priv = (struct eth1394_priv *)dev->priv; - if(info->channel != (iso->host->csr.broadcast_channel & 0x3f) || + if (info->channel != (iso->host->csr.broadcast_channel & 0x3f) || specifier_id != ETHER1394_GASP_SPECIFIER_ID) { /* This packet is not for us */ continue; @@ -1185,13 +1199,13 @@ unsigned int adj_max_payload = max_payload - hdr_type_len[ETH1394_HDR_LF_UF]; /* Does it all fit in one packet? */ - if(dg_size <= adj_max_payload) { + if (dg_size <= adj_max_payload) { hdr->uf.lf = ETH1394_HDR_LF_UF; hdr->uf.ether_type = proto; } else { hdr->ff.lf = ETH1394_HDR_LF_FF; hdr->ff.ether_type = proto; - hdr->ff.dg_size = dg_size; + hdr->ff.dg_size = dg_size - 1; hdr->ff.dgl = dgl; adj_max_payload = max_payload - hdr_type_len[ETH1394_HDR_LF_FF]; } @@ -1229,7 +1243,7 @@ default: hdr->sf.fg_off += adj_max_payload; bufhdr = (union eth1394_hdr *)skb_pull(skb, adj_max_payload); - if(max_payload >= skb->len) + if (max_payload >= skb->len) hdr->common.lf = ETH1394_HDR_LF_LF; bufhdr->words.word1 = htons(hdr->words.word1); bufhdr->words.word2 = htons(hdr->words.word2); @@ -1245,7 +1259,7 @@ struct hpsb_packet *p; p = alloc_hpsb_packet(0); - if(p) { + if (p) { p->host = host; p->data = NULL; p->generation = get_hpsb_generation(host); @@ -1269,8 +1283,9 @@ p->header_size = 16; p->expect_response = 1; - if(hpsb_get_tlabel(p, !in_interrupt())) { - ETH1394_PRINT_G(KERN_ERR, "No more tlabels left"); + if (hpsb_get_tlabel(p, !in_interrupt())) { + ETH1394_PRINT_G(KERN_ERR, "No more tlabels left while sending " + "to node " NODE_BUS_FMT "\n", NODE_BUS_ARGS(node)); return -1; } p->header[0] = (p->node_id << 16) | (p->tlabel << 10) @@ -1309,41 +1324,45 @@ static inline void ether1394_free_packet(struct hpsb_packet *packet) { + if (packet->tcode != TCODE_STREAM_DATA) + hpsb_free_tlabel(packet); packet->data = NULL; free_hpsb_packet(packet); } static void ether1394_complete_cb(void *__ptask); + static int ether1394_send_packet(struct packet_task *ptask, unsigned int tx_len) { struct eth1394_priv *priv = ptask->priv; - struct hpsb_packet *packet; + struct hpsb_packet *packet = NULL; packet = ether1394_alloc_common_packet(priv->host); - if(!packet) + if (!packet) return -1; - if(ptask->tx_type == ETH1394_GASP) { + if (ptask->tx_type == ETH1394_GASP) { int length = tx_len + (2 * sizeof(quadlet_t)); ether1394_prep_gasp_packet(packet, priv, ptask->skb, length); - - } else { - if(ether1394_prep_write_packet(packet, priv->host, + } else if (ether1394_prep_write_packet(packet, priv->host, ptask->dest_node, ptask->addr, ptask->skb->data, - tx_len)) - goto fail; + tx_len)) { + goto fail; } ptask->packet = packet; hpsb_set_packet_complete_task(ptask->packet, ether1394_complete_cb, ptask); - if(hpsb_send_packet(packet)) { + if (hpsb_send_packet(packet)) return 0; - } + fail: + if (packet) + ether1394_free_packet(packet); + return -1; } @@ -1357,17 +1376,15 @@ unsigned long flags; /* Statistics */ - if(fail) { - spin_lock_irqsave(&priv->lock, flags); + spin_lock_irqsave(&priv->lock, flags); + if (fail) { priv->stats.tx_dropped++; priv->stats.tx_errors++; - spin_unlock_irqrestore(&priv->lock, flags); } else { - spin_lock_irqsave(&priv->lock, flags); priv->stats.tx_bytes += skb->len; priv->stats.tx_packets++; - spin_unlock_irqrestore(&priv->lock, flags); } + spin_unlock_irqrestore(&priv->lock, flags); dev_kfree_skb_any(skb); kmem_cache_free(packet_task_cache, ptask); @@ -1382,22 +1399,20 @@ struct hpsb_packet *packet = ptask->packet; int fail = 0; - if(packet->tcode != TCODE_STREAM_DATA) { + if (packet->tcode != TCODE_STREAM_DATA) fail = hpsb_packet_success(packet); - hpsb_free_tlabel(packet); - } ether1394_free_packet(packet); ptask->outstanding_pkts--; - if(ptask->outstanding_pkts > 0 && !fail) + if (ptask->outstanding_pkts > 0 && !fail) { int tx_len; /* Add the encapsulation header to the fragment */ tx_len = ether1394_encapsulate(ptask->skb, ptask->max_payload, &ptask->hdr); - if(ether1394_send_packet(ptask, tx_len)) + if (ether1394_send_packet(ptask, tx_len)) ether1394_dg_complete(ptask, 1); } else { ether1394_dg_complete(ptask, fail); @@ -1424,14 +1439,8 @@ struct packet_task *ptask; struct node_entry *ne; - if (skb_is_nonlinear(skb)) { - ret = skb_linearize(skb, kmflags); - if(ret) - goto fail; - } - ptask = kmem_cache_alloc(packet_task_cache, kmflags); - if(ptask == NULL) { + if (ptask == NULL) { ret = -ENOMEM; goto fail; } @@ -1445,11 +1454,9 @@ goto fail; } - if (priv->bc_state == ETHER1394_BC_CHECK) { - if(ether1394_init_bc(dev)) { - spin_unlock_irqrestore (&priv->lock, flags); - goto fail; - } + if ((ret = ether1394_init_bc(dev))) { + spin_unlock_irqrestore (&priv->lock, flags); + goto fail; } spin_unlock_irqrestore (&priv->lock, flags); @@ -1464,7 +1471,7 @@ skb_pull(skb, ETH1394_HLEN); ne = hpsb_guid_get_entry(be64_to_cpu(*(u64*)eth->h_dest)); - if(!ne) + if (!ne) dest_node = LOCAL_BUS | ALL_NODES; else dest_node = ne->nodeid; @@ -1479,7 +1486,7 @@ /* This check should be unnecessary, but we'll keep it for safety for * a while longer. */ - if(max_payload < 512) { + if (max_payload < 512) { ETH1394_PRINT(KERN_WARNING, dev->name, "max_payload too small: %d (setting to 512)\n", max_payload); @@ -1487,13 +1494,11 @@ } /* Set the transmission type for the packet. ARP packets and IP - * broadcast packets are sent via GASP, however, we cheat a little bit - * when detecting IP broadcast packets. This will need to change when - * we switch from using node id for the hardware address to the EUI - * which we should be using instead. IP multicast is not yet - * supported. */ - if((memcmp(eth->h_dest, dev->broadcast, ETH1394_ALEN) == 0) || - (proto == __constant_htons(ETH_P_ARP))) { + * broadcast packets are sent via GASP. */ + if (memcmp(eth->h_dest, dev->broadcast, ETH1394_ALEN) == 0 || + proto == __constant_htons(ETH_P_ARP) || + (proto == __constant_htons(ETH_P_IP) && + IN_MULTICAST(__constant_ntohl(skb->nh.iph->daddr)))) { tx_type = ETH1394_GASP; max_payload -= ETHER1394_GASP_OVERHEAD; } else { @@ -1504,7 +1509,7 @@ spin_lock_irqsave (&priv->lock, flags); dgl = priv->dgl[NODEID_TO_NODE(dest_node)]; - if(max_payload < dg_size + hdr_type_len[ETH1394_HDR_LF_UF]) + if (max_payload < dg_size + hdr_type_len[ETH1394_HDR_LF_UF]) priv->dgl[NODEID_TO_NODE(dest_node)]++; spin_unlock_irqrestore (&priv->lock, flags); @@ -1516,14 +1521,14 @@ ptask->priv = priv; ptask->tx_type = tx_type; - if(tx_type != ETH1394_GASP) { + if (tx_type != ETH1394_GASP) { u64 addr; /* This test is just temporary until ConfigROM support has * been added to eth1394. Until then, we need an ARP packet * after a bus reset from the current destination node so that * we can get FIFO information. */ - if(priv->fifo[NODEID_TO_NODE(dest_node)] == 0ULL) { + if (priv->fifo[NODEID_TO_NODE(dest_node)] == 0ULL) { ret = -EAGAIN; goto fail; } @@ -1545,19 +1550,17 @@ /* Add the encapsulation header to the fragment */ tx_len = ether1394_encapsulate(skb, max_payload, &ptask->hdr); dev->trans_start = jiffies; - if(ether1394_send_packet(ptask, tx_len)) + if (ether1394_send_packet(ptask, tx_len)) goto fail; netif_wake_queue(dev); return 0; fail: - if(ptask->packet) - ether1394_free_packet(ptask->packet); - if(ptask) + if (ptask) kmem_cache_free(packet_task_cache, ptask); - if(skb != NULL) { + + if (skb != NULL) dev_kfree_skb(skb); - } spin_lock_irqsave (&priv->lock, flags); priv->stats.tx_dropped++; @@ -1570,6 +1573,53 @@ return 0; /* returning non-zero causes serious problems */ } +static int ether1394_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + switch(cmd) { + case SIOCETHTOOL: + return ether1394_ethtool_ioctl(dev, (void *) ifr->ifr_data); + + case SIOCGMIIPHY: /* Get address of MII PHY in use. */ + case SIOCGMIIREG: /* Read MII PHY register. */ + case SIOCSMIIREG: /* Write MII PHY register. */ + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static int ether1394_ethtool_ioctl(struct net_device *dev, void *useraddr) +{ + u32 ethcmd; + + if (get_user(ethcmd, (u32 *)useraddr)) + return -EFAULT; + + switch (ethcmd) { + case ETHTOOL_GDRVINFO: { + struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; + strcpy (info.driver, driver_name); + strcpy (info.version, "$Rev: 986 $"); + /* FIXME XXX provide sane businfo */ + strcpy (info.bus_info, "ieee1394"); + if (copy_to_user (useraddr, &info, sizeof (info))) + return -EFAULT; + break; + } + case ETHTOOL_GSET: + case ETHTOOL_SSET: + case ETHTOOL_NWAY_RST: + case ETHTOOL_GLINK: + case ETHTOOL_GMSGLVL: + case ETHTOOL_SMSGLVL: + default: + return -EOPNOTSUPP; + } + + return 0; +} + /* Function for incoming 1394 packets */ static struct hpsb_address_ops addr_ops = { .write = ether1394_write, @@ -1577,7 +1627,7 @@ /* Ieee1394 highlevel driver functions */ static struct hpsb_highlevel eth1394_highlevel = { - .name = ETHER1394_DRIVER_NAME, + .name = driver_name, .add_host = ether1394_add_host, .remove_host = ether1394_remove_host, .host_reset = ether1394_host_reset, diff -Nru a/drivers/ieee1394/ieee1394.h b/drivers/ieee1394/ieee1394.h --- a/drivers/ieee1394/ieee1394.h Tue Jul 1 18:44:34 2003 +++ b/drivers/ieee1394/ieee1394.h Tue Jul 1 18:44:34 2003 @@ -46,14 +46,14 @@ #define ACKX_TIMEOUT (-4) -#define SPEED_100 0x00 -#define SPEED_200 0x01 -#define SPEED_400 0x02 -#define SPEED_800 0x03 -#define SPEED_1600 0x04 -#define SPEED_3200 0x05 +#define IEEE1394_SPEED_100 0x00 +#define IEEE1394_SPEED_200 0x01 +#define IEEE1394_SPEED_400 0x02 +#define IEEE1394_SPEED_800 0x03 +#define IEEE1394_SPEED_1600 0x04 +#define IEEE1394_SPEED_3200 0x05 /* The current highest tested speed supported by the subsystem */ -#define SPEED_MAX SPEED_800 +#define IEEE1394_SPEED_MAX IEEE1394_SPEED_800 /* Maps speed values above to a string representation */ extern const char *hpsb_speedto_str[]; diff -Nru a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c --- a/drivers/ieee1394/ieee1394_core.c Tue Jul 1 18:44:33 2003 +++ b/drivers/ieee1394/ieee1394_core.c Tue Jul 1 18:44:33 2003 @@ -289,7 +289,7 @@ for (i = 0; i < (nodecount * 64); i += 64) { for (j = 0; j < nodecount; j++) { - map[i+j] = SPEED_MAX; + map[i+j] = IEEE1394_SPEED_MAX; } } @@ -458,7 +458,7 @@ struct hpsb_packet *packet; int retval = 0; - if(rootid >= ALL_NODES || rootid < -1 || gapcnt > 0x3f || gapcnt < -1 || + if (rootid >= ALL_NODES || rootid < -1 || gapcnt > 0x3f || gapcnt < -1 || (rootid == -1 && gapcnt == -1)) { HPSB_DEBUG("Invalid Parameter: rootid = %d gapcnt = %d", rootid, gapcnt); @@ -470,22 +470,21 @@ return -ENOMEM; packet->host = host; - packet->header_size = 16; + packet->header_size = 8; packet->data_size = 0; packet->expect_response = 0; packet->no_waiter = 0; packet->type = hpsb_raw; packet->header[0] = 0; - if(rootid != -1) + if (rootid != -1) packet->header[0] |= rootid << 24 | 1 << 23; - if(gapcnt != -1) + if (gapcnt != -1) packet->header[0] |= gapcnt << 16 | 1 << 22; packet->header[1] = ~packet->header[0]; packet->generation = get_hpsb_generation(host); - HPSB_DEBUG("Sending PHY configuration packet (I hope)..."); if (!hpsb_send_packet(packet)) { retval = -EINVAL; goto fail; @@ -1030,12 +1029,12 @@ { int retval; - if( (blocknum < 0) || (blocknum > 15) ) + if ( (blocknum < 0) || (blocknum > 15) ) return -EINVAL; write_lock(&ieee1394_chardevs_lock); - if(ieee1394_chardevs[blocknum].file_ops == NULL) { + if (ieee1394_chardevs[blocknum].file_ops == NULL) { /* grab the minor block */ ieee1394_chardevs[blocknum].file_ops = file_ops; ieee1394_chardevs[blocknum].module = module; @@ -1054,12 +1053,12 @@ /* release a block of minor numbers */ void ieee1394_unregister_chardev(int blocknum) { - if( (blocknum < 0) || (blocknum > 15) ) + if ( (blocknum < 0) || (blocknum > 15) ) return; write_lock(&ieee1394_chardevs_lock); - if(ieee1394_chardevs[blocknum].file_ops) { + if (ieee1394_chardevs[blocknum].file_ops) { ieee1394_chardevs[blocknum].file_ops = NULL; ieee1394_chardevs[blocknum].module = NULL; } @@ -1139,7 +1138,7 @@ /* look up the driver */ - if(ieee1394_get_chardev(blocknum, &module, &file_ops) == 0) + if (ieee1394_get_chardev(blocknum, &module, &file_ops) == 0) return -ENODEV; /* redirect all subsequent requests to the driver's diff -Nru a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h --- a/drivers/ieee1394/ieee1394_core.h Tue Jul 1 18:44:32 2003 +++ b/drivers/ieee1394/ieee1394_core.h Tue Jul 1 18:44:32 2003 @@ -34,7 +34,7 @@ } __attribute__((packed)) state; /* These are core internal. */ - char tlabel; + signed char tlabel; char ack_code; char tcode; diff -Nru a/drivers/ieee1394/ieee1394_transactions.c b/drivers/ieee1394/ieee1394_transactions.c --- a/drivers/ieee1394/ieee1394_transactions.c Tue Jul 1 18:44:34 2003 +++ b/drivers/ieee1394/ieee1394_transactions.c Tue Jul 1 18:44:34 2003 @@ -95,7 +95,7 @@ packet->data_size = 0; packet->expect_response = 0; packet->type = hpsb_raw; /* No CRC added */ - packet->speed_code = SPEED_100; /* Force speed to be 100Mbps */ + packet->speed_code = IEEE1394_SPEED_100; /* Force speed to be 100Mbps */ } static void fill_async_stream_packet(struct hpsb_packet *packet, int length, @@ -147,7 +147,7 @@ spin_lock_irqsave(&tp->lock, flags); packet->tlabel = find_next_zero_bit(tp->pool, 64, tp->next); - if(packet->tlabel > 63) + if (packet->tlabel > 63) packet->tlabel = find_first_zero_bit(tp->pool, 64); tp->next = (packet->tlabel + 1) % 64; /* Should _never_ happen */ diff -Nru a/drivers/ieee1394/ieee1394_types.h b/drivers/ieee1394/ieee1394_types.h --- a/drivers/ieee1394/ieee1394_types.h Tue Jul 1 18:44:36 2003 +++ b/drivers/ieee1394/ieee1394_types.h Tue Jul 1 18:44:36 2003 @@ -40,7 +40,7 @@ (_tp)->next = 0; \ (_tp)->allocations = 0; \ sema_init(&(_tp)->count, 63); \ -} while(0) +} while (0) typedef u32 quadlet_t; diff -Nru a/drivers/ieee1394/iso.c b/drivers/ieee1394/iso.c --- a/drivers/ieee1394/iso.c Tue Jul 1 18:44:37 2003 +++ b/drivers/ieee1394/iso.c Tue Jul 1 18:44:37 2003 @@ -25,7 +25,7 @@ void hpsb_iso_shutdown(struct hpsb_iso *iso) { - if(iso->flags & HPSB_ISO_DRIVER_INIT) { + if (iso->flags & HPSB_ISO_DRIVER_INIT) { hpsb_iso_stop(iso); iso->host->driver->isoctl(iso, iso->type == HPSB_ISO_XMIT ? XMIT_SHUTDOWN : RECV_SHUTDOWN, 0); @@ -47,7 +47,7 @@ int dma_direction; /* make sure driver supports the ISO API */ - if(!host->driver->isoctl) { + if (!host->driver->isoctl) { printk(KERN_INFO "ieee1394: host driver '%s' does not support the rawiso API\n", host->driver->name); return NULL; @@ -55,23 +55,23 @@ /* sanitize parameters */ - if(buf_packets < 2) + if (buf_packets < 2) buf_packets = 2; - if(irq_interval < 1 || irq_interval > buf_packets / 2) + if (irq_interval < 1 || irq_interval > buf_packets / 2) irq_interval = buf_packets / 2; - if(channel < -1 || channel >= 64) + if (channel < -1 || channel >= 64) return NULL; /* channel = -1 is OK for multi-channel recv but not for xmit */ - if(type == HPSB_ISO_XMIT && channel < 0) + if (type == HPSB_ISO_XMIT && channel < 0) return NULL; /* allocate and write the struct hpsb_iso */ iso = kmalloc(sizeof(*iso) + buf_packets * sizeof(struct hpsb_iso_packet_info), GFP_KERNEL); - if(!iso) + if (!iso) return NULL; iso->infos = (struct hpsb_iso_packet_info *)(iso + 1); @@ -90,7 +90,7 @@ iso->first_packet = 0; spin_lock_init(&iso->lock); - if(iso->type == HPSB_ISO_XMIT) { + if (iso->type == HPSB_ISO_XMIT) { iso->n_ready_packets = iso->buf_packets; dma_direction = PCI_DMA_TODEVICE; } else { @@ -103,7 +103,7 @@ iso->prebuffer = 0; /* allocate the packet buffer */ - if(dma_region_alloc(&iso->data_buf, iso->buf_size, host->pdev, dma_direction)) + if (dma_region_alloc(&iso->data_buf, iso->buf_size, host->pdev, dma_direction)) goto err; return iso; @@ -137,13 +137,13 @@ struct hpsb_iso *iso = hpsb_iso_common_init(host, HPSB_ISO_XMIT, data_buf_size, buf_packets, channel, irq_interval, callback); - if(!iso) + if (!iso) return NULL; iso->speed = speed; /* tell the driver to start working */ - if(host->driver->isoctl(iso, XMIT_INIT, 0)) + if (host->driver->isoctl(iso, XMIT_INIT, 0)) goto err; iso->flags |= HPSB_ISO_DRIVER_INIT; @@ -164,11 +164,11 @@ struct hpsb_iso *iso = hpsb_iso_common_init(host, HPSB_ISO_RECV, data_buf_size, buf_packets, channel, irq_interval, callback); - if(!iso) + if (!iso) return NULL; /* tell the driver to start working */ - if(host->driver->isoctl(iso, RECV_INIT, 0)) + if (host->driver->isoctl(iso, RECV_INIT, 0)) goto err; iso->flags |= HPSB_ISO_DRIVER_INIT; @@ -181,21 +181,21 @@ int hpsb_iso_recv_listen_channel(struct hpsb_iso *iso, unsigned char channel) { - if(iso->type != HPSB_ISO_RECV || iso->channel != -1 || channel >= 64) + if (iso->type != HPSB_ISO_RECV || iso->channel != -1 || channel >= 64) return -EINVAL; return iso->host->driver->isoctl(iso, RECV_LISTEN_CHANNEL, channel); } int hpsb_iso_recv_unlisten_channel(struct hpsb_iso *iso, unsigned char channel) { - if(iso->type != HPSB_ISO_RECV || iso->channel != -1 || channel >= 64) + if (iso->type != HPSB_ISO_RECV || iso->channel != -1 || channel >= 64) return -EINVAL; return iso->host->driver->isoctl(iso, RECV_UNLISTEN_CHANNEL, channel); } int hpsb_iso_recv_set_channel_mask(struct hpsb_iso *iso, u64 mask) { - if(iso->type != HPSB_ISO_RECV || iso->channel != -1) + if (iso->type != HPSB_ISO_RECV || iso->channel != -1) return -EINVAL; return iso->host->driver->isoctl(iso, RECV_SET_CHANNEL_MASK, (unsigned long) &mask); } @@ -203,7 +203,7 @@ static int do_iso_xmit_start(struct hpsb_iso *iso, int cycle) { int retval = iso->host->driver->isoctl(iso, XMIT_START, cycle); - if(retval) + if (retval) return retval; iso->flags |= HPSB_ISO_DRIVER_STARTED; @@ -212,25 +212,25 @@ int hpsb_iso_xmit_start(struct hpsb_iso *iso, int cycle, int prebuffer) { - if(iso->type != HPSB_ISO_XMIT) + if (iso->type != HPSB_ISO_XMIT) return -1; - if(iso->flags & HPSB_ISO_DRIVER_STARTED) + if (iso->flags & HPSB_ISO_DRIVER_STARTED) return 0; - if(cycle < -1) + if (cycle < -1) cycle = -1; - else if(cycle >= 8000) + else if (cycle >= 8000) cycle %= 8000; iso->xmit_cycle = cycle; - if(prebuffer < 0) + if (prebuffer < 0) prebuffer = iso->buf_packets; - else if(prebuffer == 0) + else if (prebuffer == 0) prebuffer = 1; - if(prebuffer > iso->buf_packets) + if (prebuffer > iso->buf_packets) prebuffer = iso->buf_packets; iso->prebuffer = prebuffer; @@ -247,20 +247,20 @@ int retval = 0; int isoctl_args[3]; - if(iso->type != HPSB_ISO_RECV) + if (iso->type != HPSB_ISO_RECV) return -1; - if(iso->flags & HPSB_ISO_DRIVER_STARTED) + if (iso->flags & HPSB_ISO_DRIVER_STARTED) return 0; - if(cycle < -1) + if (cycle < -1) cycle = -1; - else if(cycle >= 8000) + else if (cycle >= 8000) cycle %= 8000; isoctl_args[0] = cycle; - if(tag_mask < 0) + if (tag_mask < 0) /* match all tags */ tag_mask = 0xF; isoctl_args[1] = tag_mask; @@ -268,7 +268,7 @@ isoctl_args[2] = sync; retval = iso->host->driver->isoctl(iso, RECV_START, (unsigned long) &isoctl_args[0]); - if(retval) + if (retval) return retval; iso->flags |= HPSB_ISO_DRIVER_STARTED; @@ -282,15 +282,15 @@ unsigned int offset, unsigned short len, unsigned int *out_offset, unsigned short *out_len) { - if(offset >= iso->buf_size) + if (offset >= iso->buf_size) return -EFAULT; /* make sure the packet does not go beyond the end of the buffer */ - if(offset + len > iso->buf_size) + if (offset + len > iso->buf_size) return -EFAULT; /* check for wrap-around */ - if(offset + len < offset) + if (offset + len < offset) return -EFAULT; /* now we can trust 'offset' and 'length' */ @@ -307,18 +307,18 @@ unsigned long flags; int rv; - if(iso->type != HPSB_ISO_XMIT) + if (iso->type != HPSB_ISO_XMIT) return -EINVAL; /* is there space in the buffer? */ - if(iso->n_ready_packets <= 0) { + if (iso->n_ready_packets <= 0) { return -EBUSY; } info = &iso->infos[iso->first_packet]; /* check for bogus offset/length */ - if(hpsb_iso_check_offset_len(iso, offset, len, &info->offset, &info->len)) + if (hpsb_iso_check_offset_len(iso, offset, len, &info->offset, &info->len)) return -EFAULT; info->tag = tag; @@ -327,7 +327,7 @@ spin_lock_irqsave(&iso->lock, flags); rv = iso->host->driver->isoctl(iso, XMIT_QUEUE, (unsigned long) info); - if(rv) + if (rv) goto out; /* increment cursors */ @@ -335,9 +335,9 @@ iso->xmit_cycle = (iso->xmit_cycle+1) % 8000; iso->n_ready_packets--; - if(iso->prebuffer != 0) { + if (iso->prebuffer != 0) { iso->prebuffer--; - if(iso->prebuffer <= 0) { + if (iso->prebuffer <= 0) { iso->prebuffer = 0; rv = do_iso_xmit_start(iso, iso->start_cycle); } @@ -350,7 +350,7 @@ int hpsb_iso_xmit_sync(struct hpsb_iso *iso) { - if(iso->type != HPSB_ISO_XMIT) + if (iso->type != HPSB_ISO_XMIT) return -EINVAL; return wait_event_interruptible(iso->waitq, hpsb_iso_n_ready(iso) == iso->buf_packets); @@ -371,7 +371,7 @@ iso->n_ready_packets++; iso->pkt_dma = (iso->pkt_dma + 1) % iso->buf_packets; - if(iso->n_ready_packets == iso->buf_packets || error != 0) { + if (iso->n_ready_packets == iso->buf_packets || error != 0) { /* the buffer has run empty! */ atomic_inc(&iso->overflows); } @@ -385,7 +385,7 @@ unsigned long flags; spin_lock_irqsave(&iso->lock, flags); - if(iso->n_ready_packets == iso->buf_packets) { + if (iso->n_ready_packets == iso->buf_packets) { /* overflow! */ atomic_inc(&iso->overflows); } else { @@ -410,14 +410,14 @@ unsigned int i; int rv = 0; - if(iso->type != HPSB_ISO_RECV) + if (iso->type != HPSB_ISO_RECV) return -1; spin_lock_irqsave(&iso->lock, flags); - for(i = 0; i < n_packets; i++) { + for (i = 0; i < n_packets; i++) { rv = iso->host->driver->isoctl(iso, RECV_RELEASE, (unsigned long) &iso->infos[iso->first_packet]); - if(rv) + if (rv) break; iso->first_packet = (iso->first_packet+1) % iso->buf_packets; @@ -431,6 +431,6 @@ { wake_up_interruptible(&iso->waitq); - if(iso->callback) + if (iso->callback) iso->callback(iso); } diff -Nru a/drivers/ieee1394/iso.h b/drivers/ieee1394/iso.h --- a/drivers/ieee1394/iso.h Tue Jul 1 18:44:37 2003 +++ b/drivers/ieee1394/iso.h Tue Jul 1 18:44:37 2003 @@ -66,7 +66,7 @@ /* wait for buffer space */ wait_queue_head_t waitq; - int speed; /* SPEED_100, 200, or 400 */ + int speed; /* IEEE1394_SPEED_100, 200, or 400 */ int channel; /* -1 if multichannel */ /* greatest # of packets between interrupts - controls diff -Nru a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c --- a/drivers/ieee1394/nodemgr.c Tue Jul 1 18:44:36 2003 +++ b/drivers/ieee1394/nodemgr.c Tue Jul 1 18:44:36 2003 @@ -1167,7 +1167,7 @@ return -ENOMEM; \ ++length; \ scratch = buffer + length; \ -} while(0) +} while (0) PUT_ENVP("VENDOR_ID=%06x", ud->vendor_id); PUT_ENVP("MODEL_ID=%06x", ud->model_id); @@ -1303,8 +1303,9 @@ snprintf(ne->device.name, DEVICE_NAME_SIZE, "IEEE-1394 device %d-" NODE_BUS_FMT, hi->host->id, NODE_BUS_ARGS(ne->nodeid)); - HPSB_DEBUG("Node " NODE_BUS_FMT " changed to " NODE_BUS_FMT, - NODE_BUS_ARGS(ne->nodeid), NODE_BUS_ARGS(nodeid)); + HPSB_DEBUG("Node changed: %d-" NODE_BUS_FMT " -> %d-" NODE_BUS_FMT, + ne->host->id, NODE_BUS_ARGS(ne->nodeid), + ne->host->id, NODE_BUS_ARGS(nodeid)); ne->nodeid = nodeid; update_ud_names++; @@ -1507,8 +1508,8 @@ nodemgr_remove_node)) { struct node_entry *ne = cleanup.ne; - HPSB_DEBUG("Device removed: ID:BUS[" NODE_BUS_FMT "] GUID[%016Lx]", - NODE_BUS_ARGS(ne->nodeid), (unsigned long long)ne->guid); + HPSB_DEBUG("Node removed: ID:BUS[%d-" NODE_BUS_FMT "] GUID[%016Lx]", + host->id, NODE_BUS_ARGS(ne->nodeid), (unsigned long long)ne->guid); nodemgr_remove_ne(ne); } @@ -1547,12 +1548,12 @@ /* If there is no bus manager then we should set the root node's * force_root bit to promote bus stability per the 1394 * spec. (8.4.2.6) */ - if (host->busmgr_id == 0x3f && host->node_count > 1) + if (host->busmgr_id == 0xffff && host->node_count > 1) { u16 root_node = host->node_count - 1; - struct node_entry *ne = hpsb_nodeid_get_entry(host, root_node); + struct node_entry *ne = find_entry_by_nodeid(host, root_node | LOCAL_BUS); - if (ne->busopt.cmc) + if (ne && ne->busopt.cmc) hpsb_send_phy_config(host, root_node, -1); else { HPSB_DEBUG("The root node is not cycle master capable; " @@ -1782,7 +1783,7 @@ if (hi != NULL) { #ifdef CONFIG_IEEE1394_VERBOSEDEBUG - HPSB_DEBUG ("NodeMgr: Processing host reset for %s", host->driver->name); + HPSB_DEBUG ("NodeMgr: Processing host reset for %s", hi->daemon_name); #endif up(&hi->reset_sem); } else diff -Nru a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c --- a/drivers/ieee1394/ohci1394.c Tue Jul 1 18:44:37 2003 +++ b/drivers/ieee1394/ohci1394.c Tue Jul 1 18:44:37 2003 @@ -164,7 +164,7 @@ printk(level "%s_%d: " fmt "\n" , OHCI1394_DRIVER_NAME, card , ## args) static char version[] __devinitdata = - "$Rev: 948 $ Ben Collins "; + "$Rev: 986 $ Ben Collins "; /* Module Parameters */ static int phys_dma = 1; @@ -428,7 +428,7 @@ d->buf_ind = 0; d->buf_offset = 0; - if(d->type == DMA_CTX_ISO) { + if (d->type == DMA_CTX_ISO) { /* Clear contextControl */ reg_write(ohci, d->ctrlClear, 0xffffffff); @@ -470,7 +470,7 @@ INIT_LIST_HEAD(&d->fifo_list); INIT_LIST_HEAD(&d->pending_list); - if(d->type == DMA_CTX_ISO) { + if (d->type == DMA_CTX_ISO) { /* enable interrupts */ reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1 << d->ctx); } @@ -490,8 +490,8 @@ DBGMSG(ohci->id,"Iso contexts reg: %08x implemented: %08x", reg, tmp); /* Count the number of contexts */ - for(i=0; i<32; i++) { - if(tmp & 1) ctx++; + for (i=0; i<32; i++) { + if (tmp & 1) ctx++; tmp >>= 1; } return ctx; @@ -810,8 +810,7 @@ } if (d->free_prgs == 0) - PRINT(KERN_INFO, ohci->id, - "Transmit DMA FIFO ctx=%d is full... waiting",d->ctx); + DBGMSG(ohci->id, "Transmit DMA FIFO ctx=%d is full... waiting", d->ctx); /* Is the context running ? (should be unless it is the first packet to be sent in this context) */ @@ -856,8 +855,8 @@ * case. I don't see anyone sending ISO packets from * interrupt context anyway... */ - if(ohci->it_legacy_context.ohci == NULL) { - if(in_interrupt()) { + if (ohci->it_legacy_context.ohci == NULL) { + if (in_interrupt()) { PRINT(KERN_ERR, ohci->id, "legacy IT context cannot be initialized during interrupt"); return 0; @@ -1074,7 +1073,7 @@ spin_unlock_irqrestore(&ohci->IR_channel_lock, flags); DBGMSG(ohci->id, "Listening disabled on channel %d", arg); - if(ohci->ir_legacy_channels == 0) { + if (ohci->ir_legacy_channels == 0) { free_dma_rcv_ctx(&ohci->ir_legacy_context); DBGMSG(ohci->id, "ISO receive legacy context deactivated"); } @@ -1162,7 +1161,7 @@ int ret = -ENOMEM; recv = kmalloc(sizeof(*recv), SLAB_KERNEL); - if(!recv) + if (!recv) return -ENOMEM; iso->hostdata = recv; @@ -1174,7 +1173,7 @@ /* use buffer-fill mode, unless irq_interval is 1 (note: multichannel requires buffer-fill) */ - if(iso->irq_interval == 1 && iso->channel != -1) { + if (iso->irq_interval == 1 && iso->channel != -1) { recv->dma_mode = PACKET_PER_BUFFER_MODE; } else { recv->dma_mode = BUFFER_FILL_MODE; @@ -1182,12 +1181,12 @@ /* set nblocks, buf_stride, block_irq_interval */ - if(recv->dma_mode == BUFFER_FILL_MODE) { + if (recv->dma_mode == BUFFER_FILL_MODE) { recv->buf_stride = PAGE_SIZE; /* one block per page of data in the DMA buffer, minus the final guard page */ recv->nblocks = iso->buf_size/PAGE_SIZE - 1; - if(recv->nblocks < 3) { + if (recv->nblocks < 3) { DBGMSG(ohci->id, "ohci_iso_recv_init: DMA buffer too small"); goto err; } @@ -1195,9 +1194,9 @@ /* iso->irq_interval is in packets - translate that to blocks */ /* (err, sort of... 1 is always the safest value) */ recv->block_irq_interval = iso->irq_interval / recv->nblocks; - if(recv->block_irq_interval*4 > recv->nblocks) + if (recv->block_irq_interval*4 > recv->nblocks) recv->block_irq_interval = recv->nblocks/4; - if(recv->block_irq_interval < 1) + if (recv->block_irq_interval < 1) recv->block_irq_interval = 1; } else { @@ -1211,10 +1210,10 @@ max_packet_size = iso->buf_size / iso->buf_packets; - for(recv->buf_stride = 8; recv->buf_stride < max_packet_size; + for (recv->buf_stride = 8; recv->buf_stride < max_packet_size; recv->buf_stride *= 2); - if(recv->buf_stride*iso->buf_packets > iso->buf_size || + if (recv->buf_stride*iso->buf_packets > iso->buf_size || recv->buf_stride > PAGE_SIZE) { /* this shouldn't happen, but anyway... */ DBGMSG(ohci->id, "ohci_iso_recv_init: problem choosing a buffer stride"); @@ -1243,7 +1242,7 @@ ohci_iso_recv_packetperbuf_task, (unsigned long) iso); - if(ohci1394_register_iso_tasklet(recv->ohci, &recv->task) < 0) + if (ohci1394_register_iso_tasklet(recv->ohci, &recv->task) < 0) goto err; recv->task_active = 1; @@ -1255,7 +1254,7 @@ recv->CommandPtr = OHCI1394_IsoRcvCommandPtr + 32 * ctx; recv->ContextMatch = OHCI1394_IsoRcvContextMatch + 32 * ctx; - if(iso->channel == -1) { + if (iso->channel == -1) { /* clear multi-channel selection mask */ reg_write(recv->ohci, OHCI1394_IRMultiChanMaskHiClear, 0xFFFFFFFF); reg_write(recv->ohci, OHCI1394_IRMultiChanMaskLoClear, 0xFFFFFFFF); @@ -1293,7 +1292,7 @@ { struct ohci_iso_recv *recv = iso->hostdata; - if(recv->task_active) { + if (recv->task_active) { ohci_iso_recv_stop(iso); ohci1394_unregister_iso_tasklet(recv->ohci, &recv->task); recv->task_active = 0; @@ -1363,7 +1362,7 @@ struct ohci_iso_recv *recv = iso->hostdata; int reg, i; - if(channel < 32) { + if (channel < 32) { reg = listen ? OHCI1394_IRMultiChanMaskLoSet : OHCI1394_IRMultiChanMaskLoClear; i = channel; } else { @@ -1383,14 +1382,14 @@ struct ohci_iso_recv *recv = iso->hostdata; int i; - for(i = 0; i < 64; i++) { - if(mask & (1ULL << i)) { - if(i < 32) + for (i = 0; i < 64; i++) { + if (mask & (1ULL << i)) { + if (i < 32) reg_write(recv->ohci, OHCI1394_IRMultiChanMaskLoSet, (1 << i)); else reg_write(recv->ohci, OHCI1394_IRMultiChanMaskHiSet, (1 << (i-32))); } else { - if(i < 32) + if (i < 32) reg_write(recv->ohci, OHCI1394_IRMultiChanMaskLoClear, (1 << i)); else reg_write(recv->ohci, OHCI1394_IRMultiChanMaskHiClear, (1 << (i-32))); @@ -1413,7 +1412,7 @@ /* always keep ISO headers */ command = (1 << 30); - if(recv->dma_mode == BUFFER_FILL_MODE) + if (recv->dma_mode == BUFFER_FILL_MODE) command |= (1 << 31); reg_write(recv->ohci, recv->ContextControlSet, command); @@ -1421,7 +1420,7 @@ /* match on specified tags */ contextMatch = tag_mask << 28; - if(iso->channel == -1) { + if (iso->channel == -1) { /* enable multichannel reception */ reg_write(recv->ohci, recv->ContextControlSet, (1 << 28)); } else { @@ -1429,7 +1428,7 @@ contextMatch |= iso->channel; } - if(cycle != -1) { + if (cycle != -1) { u32 seconds; /* enable cycleMatch */ @@ -1450,7 +1449,7 @@ contextMatch |= cycle << 12; } - if(sync != -1) { + if (sync != -1) { /* set sync flag on first DMA descriptor */ struct dma_cmd *cmd = &recv->block[recv->block_dma]; cmd->control |= DMA_CTL_WAIT; @@ -1482,7 +1481,7 @@ reg_read(recv->ohci, OHCI1394_IsochronousCycleTimer); /* check RUN */ - if(!(reg_read(recv->ohci, recv->ContextControlSet) & 0x8000)) { + if (!(reg_read(recv->ohci, recv->ContextControlSet) & 0x8000)) { PRINT(KERN_ERR, recv->ohci->id, "Error starting IR DMA (ContextControl 0x%08x)\n", reg_read(recv->ohci, recv->ContextControlSet)); @@ -1515,7 +1514,7 @@ | 1); /* Z=1 */ /* disable interrupt on previous DMA descriptor, except at intervals */ - if((prev_i % recv->block_irq_interval) == 0) { + if ((prev_i % recv->block_irq_interval) == 0) { prev->control |= cpu_to_le32(3 << 20); /* enable interrupt */ } else { prev->control &= cpu_to_le32(~(3<<20)); /* disable interrupt */ @@ -1535,7 +1534,7 @@ len = info->len; /* add the wasted space for padding to 4 bytes */ - if(len % 4) + if (len % 4) len += 4 - (len % 4); /* add 8 bytes for the OHCI DMA data format overhead */ @@ -1544,7 +1543,7 @@ recv->released_bytes += len; /* have we released enough memory for one block? */ - while(recv->released_bytes > recv->buf_stride) { + while (recv->released_bytes > recv->buf_stride) { ohci_iso_recv_release_block(recv, recv->block_reader); recv->block_reader = (recv->block_reader + 1) % recv->nblocks; recv->released_bytes -= recv->buf_stride; @@ -1554,7 +1553,7 @@ static inline void ohci_iso_recv_release(struct hpsb_iso *iso, struct hpsb_iso_packet_info *info) { struct ohci_iso_recv *recv = iso->hostdata; - if(recv->dma_mode == BUFFER_FILL_MODE) { + if (recv->dma_mode == BUFFER_FILL_MODE) { ohci_iso_recv_bufferfill_release(recv, info); } else { ohci_iso_recv_release_block(recv, info - iso->infos); @@ -1567,7 +1566,7 @@ int wake = 0; int runaway = 0; - while(1) { + while (1) { /* we expect the next parsable packet to begin at recv->dma_offset */ /* note: packet layout is as shown in section 10.6.1.1 of the OHCI spec */ @@ -1580,7 +1579,7 @@ unsigned int this_block = recv->dma_offset/recv->buf_stride; /* don't loop indefinitely */ - if(runaway++ > 100000) { + if (runaway++ > 100000) { atomic_inc(&iso->overflows); PRINT(KERN_ERR, recv->ohci->id, "IR DMA error - Runaway during buffer parsing!\n"); @@ -1588,7 +1587,7 @@ } /* stop parsing once we arrive at block_dma (i.e. don't get ahead of DMA) */ - if(this_block == recv->block_dma) + if (this_block == recv->block_dma) break; wake = 1; @@ -1600,7 +1599,7 @@ len = p[recv->dma_offset+2] | (p[recv->dma_offset+3] << 8); - if(len > 4096) { + if (len > 4096) { PRINT(KERN_ERR, recv->ohci->id, "IR DMA error - bogus 'len' value %u\n", len); } @@ -1613,7 +1612,7 @@ recv->dma_offset += 4; /* check for wrap-around */ - if(recv->dma_offset >= recv->buf_stride*recv->nblocks) { + if (recv->dma_offset >= recv->buf_stride*recv->nblocks) { recv->dma_offset -= recv->buf_stride*recv->nblocks; } @@ -1624,12 +1623,12 @@ recv->dma_offset += len; /* payload is padded to 4 bytes */ - if(len % 4) { + if (len % 4) { recv->dma_offset += 4 - (len%4); } /* check for wrap-around */ - if(recv->dma_offset >= recv->buf_stride*recv->nblocks) { + if (recv->dma_offset >= recv->buf_stride*recv->nblocks) { /* uh oh, the packet data wraps from the last to the first DMA block - make the packet contiguous by copying its "tail" into the @@ -1638,7 +1637,7 @@ int guard_off = recv->buf_stride*recv->nblocks; int tail_len = len - (guard_off - offset); - if(tail_len > 0 && tail_len < recv->buf_stride) { + if (tail_len > 0 && tail_len < recv->buf_stride) { memcpy(iso->data_buf.kvirt + guard_off, iso->data_buf.kvirt, tail_len); @@ -1655,14 +1654,14 @@ recv->dma_offset += 4; /* check for wrap-around */ - if(recv->dma_offset >= recv->buf_stride*recv->nblocks) { + if (recv->dma_offset >= recv->buf_stride*recv->nblocks) { recv->dma_offset -= recv->buf_stride*recv->nblocks; } hpsb_iso_packet_received(iso, offset, len, cycle, channel, tag, sy); } - if(wake) + if (wake) hpsb_iso_wake(iso); } @@ -1674,7 +1673,7 @@ int loop; /* loop over all blocks */ - for(loop = 0; loop < recv->nblocks; loop++) { + for (loop = 0; loop < recv->nblocks; loop++) { /* check block_dma to see if it's done */ @@ -1688,18 +1687,18 @@ unsigned char event = xferstatus & 0x1F; - if(!event) { + if (!event) { /* nothing has happened to this block yet */ break; } - if(event != 0x11) { + if (event != 0x11) { atomic_inc(&iso->overflows); PRINT(KERN_ERR, recv->ohci->id, "IR DMA error - OHCI error code 0x%02x\n", event); } - if(rescount != 0) { + if (rescount != 0) { /* the card is still writing to this block; we can't touch it until it's done */ break; @@ -1716,7 +1715,7 @@ /* advance block_dma */ recv->block_dma = (recv->block_dma + 1) % recv->nblocks; - if((recv->block_dma+1) % recv->nblocks == recv->block_reader) { + if ((recv->block_dma+1) % recv->nblocks == recv->block_reader) { atomic_inc(&iso->overflows); DBGMSG(recv->ohci->id, "ISO reception overflow - " "ran out of DMA blocks"); @@ -1735,7 +1734,7 @@ int wake = 0; /* loop over the entire buffer */ - for(count = 0; count < recv->nblocks; count++) { + for (count = 0; count < recv->nblocks; count++) { u32 packet_len = 0; /* pointer to the DMA descriptor */ @@ -1747,21 +1746,21 @@ unsigned char event = xferstatus & 0x1F; - if(!event) { + if (!event) { /* this packet hasn't come in yet; we are done for now */ goto out; } - if(event == 0x11) { + if (event == 0x11) { /* packet received successfully! */ /* rescount is the number of bytes *remaining* in the packet buffer, after the packet was written */ packet_len = recv->buf_stride - rescount; - } else if(event == 0x02) { + } else if (event == 0x02) { PRINT(KERN_ERR, recv->ohci->id, "IR DMA error - packet too long for buffer\n"); - } else if(event) { + } else if (event) { PRINT(KERN_ERR, recv->ohci->id, "IR DMA error - OHCI error code 0x%02x\n", event); } @@ -1800,7 +1799,7 @@ } out: - if(wake) + if (wake) hpsb_iso_wake(iso); } @@ -1844,7 +1843,7 @@ int ret = -ENOMEM; xmit = kmalloc(sizeof(*xmit), SLAB_KERNEL); - if(!xmit) + if (!xmit) return -ENOMEM; iso->hostdata = xmit; @@ -1855,13 +1854,13 @@ prog_size = sizeof(struct iso_xmit_cmd) * iso->buf_packets; - if(dma_prog_region_alloc(&xmit->prog, prog_size, xmit->ohci->dev)) + if (dma_prog_region_alloc(&xmit->prog, prog_size, xmit->ohci->dev)) goto err; ohci1394_init_iso_tasklet(&xmit->task, OHCI_ISO_TRANSMIT, ohci_iso_xmit_task, (unsigned long) iso); - if(ohci1394_register_iso_tasklet(xmit->ohci, &xmit->task) < 0) + if (ohci1394_register_iso_tasklet(xmit->ohci, &xmit->task) < 0) goto err; xmit->task_active = 1; @@ -1887,7 +1886,7 @@ reg_write(xmit->ohci, OHCI1394_IsoXmitIntMaskClear, 1 << xmit->task.context); /* halt DMA */ - if(ohci1394_stop_context(xmit->ohci, xmit->ContextControlClear, NULL)) { + if (ohci1394_stop_context(xmit->ohci, xmit->ContextControlClear, NULL)) { /* XXX the DMA context will lock up if you try to send too much data! */ PRINT(KERN_ERR, xmit->ohci->id, "you probably exceeded the OHCI card's bandwidth limit - " @@ -1899,7 +1898,7 @@ { struct ohci_iso_xmit *xmit = iso->hostdata; - if(xmit->task_active) { + if (xmit->task_active) { ohci_iso_xmit_stop(iso); ohci1394_unregister_iso_tasklet(xmit->ohci, &xmit->task); xmit->task_active = 0; @@ -1918,7 +1917,7 @@ int count; /* check the whole buffer if necessary, starting at pkt_dma */ - for(count = 0; count < iso->buf_packets; count++) { + for (count = 0; count < iso->buf_packets; count++) { int cycle; /* DMA descriptor */ @@ -1928,12 +1927,12 @@ u16 xferstatus = le32_to_cpu(cmd->output_last.status) >> 16; u8 event = xferstatus & 0x1F; - if(!event) { + if (!event) { /* packet hasn't been sent yet; we are done for now */ break; } - if(event != 0x11) + if (event != 0x11) PRINT(KERN_ERR, xmit->ohci->id, "IT DMA error - OHCI error code 0x%02x\n", event); @@ -1950,7 +1949,7 @@ cmd->output_last.status = 0; } - if(wake) + if (wake) hpsb_iso_wake(iso); } @@ -1967,7 +1966,7 @@ /* check that the packet doesn't cross a page boundary (we could allow this if we added OUTPUT_MORE descriptor support) */ - if(cross_bound(info->offset, info->len)) { + if (cross_bound(info->offset, info->len)) { PRINT(KERN_ERR, xmit->ohci->id, "rawiso xmit: packet %u crosses a page boundary", iso->first_packet); @@ -2030,7 +2029,7 @@ dma_prog_region_offset_to_bus(&xmit->prog, sizeof(struct iso_xmit_cmd) * next_i) | 3); /* disable interrupt, unless required by the IRQ interval */ - if(prev_i % iso->irq_interval) { + if (prev_i % iso->irq_interval) { prev->output_last.control &= cpu_to_le32(~(3 << 20)); /* no interrupt */ } else { prev->output_last.control |= cpu_to_le32(3 << 20); /* enable interrupt */ @@ -2062,7 +2061,7 @@ dma_prog_region_offset_to_bus(&xmit->prog, iso->pkt_dma * sizeof(struct iso_xmit_cmd)) | 3); /* cycle match */ - if(cycle != -1) { + if (cycle != -1) { u32 start = cycle & 0x1FFF; /* 'cycle' is only mod 8000, but we also need two 'seconds' bits - @@ -2088,7 +2087,7 @@ udelay(100); /* check the RUN bit */ - if(!(reg_read(xmit->ohci, xmit->ContextControlSet) & 0x8000)) { + if (!(reg_read(xmit->ohci, xmit->ContextControlSet) & 0x8000)) { PRINT(KERN_ERR, xmit->ohci->id, "Error starting IT DMA (ContextControl 0x%08x)\n", reg_read(xmit->ohci, xmit->ContextControlSet)); return -1; @@ -2694,7 +2693,7 @@ #ifdef OHCI1394_DEBUG if (datasize) - if(((le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])>>4)&0xf) == 0xa) + if (((le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])>>4)&0xf) == 0xa) DBGMSG(ohci->id, "Stream packet sent to channel %d tcode=0x%X " "ack=0x%X spd=%d dataLength=%d ctx=%d", @@ -2807,7 +2806,7 @@ DBGMSG(d->ohci->id, "Freeing dma_rcv_ctx %d", d->ctx); - if(d->ctrlClear) { + if (d->ctrlClear) { ohci1394_stop_context(d->ohci, d->ctrlClear, NULL); if (d->type == DMA_CTX_ISO) { @@ -2969,7 +2968,7 @@ DBGMSG(d->ohci->id, "Freeing dma_trm_ctx %d", d->ctx); - if(d->ctrlClear) { + if (d->ctrlClear) { ohci1394_stop_context(d->ohci, d->ctrlClear, NULL); if (d->type == DMA_CTX_ISO) { @@ -3261,7 +3260,7 @@ PRINT_G(KERN_ERR, fmt , ## args); \ ohci1394_pci_remove(dev); \ return err; \ -} while(0) +} while (0) static int __devinit ohci1394_pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) @@ -3624,8 +3623,8 @@ usage = &ohci->ir_ctx_usage; /* only one receive context can be multichannel (OHCI sec 10.4.1) */ - if(tasklet->type == OHCI_ISO_MULTICHANNEL_RECEIVE) { - if(test_and_set_bit(0, &ohci->ir_multichannel_used)) { + if (tasklet->type == OHCI_ISO_MULTICHANNEL_RECEIVE) { + if (test_and_set_bit(0, &ohci->ir_multichannel_used)) { return r; } } @@ -3660,7 +3659,7 @@ else { clear_bit(tasklet->context, &ohci->ir_ctx_usage); - if(tasklet->type == OHCI_ISO_MULTICHANNEL_RECEIVE) { + if (tasklet->type == OHCI_ISO_MULTICHANNEL_RECEIVE) { clear_bit(0, &ohci->ir_multichannel_used); } } diff -Nru a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c --- a/drivers/ieee1394/raw1394.c Tue Jul 1 18:44:31 2003 +++ b/drivers/ieee1394/raw1394.c Tue Jul 1 18:44:31 2003 @@ -601,7 +601,7 @@ if (fi->listen_channels & (1ULL << channel)) { req->req.error = RAW1394_ERROR_ALREADY; } else { - if(hpsb_listen_channel(&raw1394_highlevel, fi->host, channel)) { + if (hpsb_listen_channel(&raw1394_highlevel, fi->host, channel)) { req->req.error = RAW1394_ERROR_ALREADY; } else { fi->listen_channels |= 1ULL << channel; @@ -2008,7 +2008,7 @@ list_for_each(lh, &fi->req_complete) { req = list_entry(lh, struct pending_request, list); - if(req->req.type == RAW1394_REQ_RAWISO_ACTIVITY) { + if (req->req.type == RAW1394_REQ_RAWISO_ACTIVITY) { return 1; } } @@ -2024,17 +2024,17 @@ spin_lock_irqsave(&fi->reqlists_lock, flags); /* only one ISO activity event may be in the queue */ - if(!__rawiso_event_in_queue(fi)) { + if (!__rawiso_event_in_queue(fi)) { struct pending_request *req = __alloc_pending_request(SLAB_ATOMIC); - if(req) { + if (req) { req->file_info = fi; req->req.type = RAW1394_REQ_RAWISO_ACTIVITY; req->req.generation = get_hpsb_generation(fi->host); __queue_complete_req(req); } else { /* on allocation failure, signal an overflow */ - if(fi->iso_handle) { + if (fi->iso_handle) { atomic_inc(&fi->iso_handle->overflows); } } @@ -2054,7 +2054,7 @@ if (hi != NULL) { list_for_each(lh, &hi->file_info_list) { struct file_info *fi = list_entry(lh, struct file_info, list); - if(fi->iso_handle == iso) + if (fi->iso_handle == iso) queue_rawiso_event(fi); } } @@ -2079,7 +2079,7 @@ { struct raw1394_iso_status stat; - if(copy_from_user(&stat, uaddr, sizeof(stat))) + if (copy_from_user(&stat, uaddr, sizeof(stat))) return -EFAULT; fi->iso_handle = hpsb_iso_xmit_init(fi->host, @@ -2089,13 +2089,13 @@ stat.config.speed, stat.config.irq_interval, rawiso_activity_cb); - if(!fi->iso_handle) + if (!fi->iso_handle) return -ENOMEM; fi->iso_state = RAW1394_ISO_XMIT; raw1394_iso_fill_status(fi->iso_handle, &stat); - if(copy_to_user(uaddr, &stat, sizeof(stat))) + if (copy_to_user(uaddr, &stat, sizeof(stat))) return -EFAULT; /* queue an event to get things started */ @@ -2108,7 +2108,7 @@ { struct raw1394_iso_status stat; - if(copy_from_user(&stat, uaddr, sizeof(stat))) + if (copy_from_user(&stat, uaddr, sizeof(stat))) return -EFAULT; fi->iso_handle = hpsb_iso_recv_init(fi->host, @@ -2117,13 +2117,13 @@ stat.config.channel, stat.config.irq_interval, rawiso_activity_cb); - if(!fi->iso_handle) + if (!fi->iso_handle) return -ENOMEM; fi->iso_state = RAW1394_ISO_RECV; raw1394_iso_fill_status(fi->iso_handle, &stat); - if(copy_to_user(uaddr, &stat, sizeof(stat))) + if (copy_to_user(uaddr, &stat, sizeof(stat))) return -EFAULT; return 0; } @@ -2134,7 +2134,7 @@ struct hpsb_iso *iso = fi->iso_handle; raw1394_iso_fill_status(fi->iso_handle, &stat); - if(copy_to_user(uaddr, &stat, sizeof(stat))) + if (copy_to_user(uaddr, &stat, sizeof(stat))) return -EFAULT; /* reset overflow counter */ @@ -2150,20 +2150,20 @@ unsigned int packet = fi->iso_handle->first_packet; int i; - if(copy_from_user(&upackets, uaddr, sizeof(upackets))) + if (copy_from_user(&upackets, uaddr, sizeof(upackets))) return -EFAULT; - if(upackets.n_packets > hpsb_iso_n_ready(fi->iso_handle)) + if (upackets.n_packets > hpsb_iso_n_ready(fi->iso_handle)) return -EINVAL; /* ensure user-supplied buffer is accessible and big enough */ - if(verify_area(VERIFY_WRITE, upackets.infos, + if (verify_area(VERIFY_WRITE, upackets.infos, upackets.n_packets * sizeof(struct raw1394_iso_packet_info))) return -EFAULT; /* copy the packet_infos out */ - for(i = 0; i < upackets.n_packets; i++) { - if(__copy_to_user(&upackets.infos[i], + for (i = 0; i < upackets.n_packets; i++) { + if (__copy_to_user(&upackets.infos[i], &fi->iso_handle->infos[packet], sizeof(struct raw1394_iso_packet_info))) return -EFAULT; @@ -2180,28 +2180,28 @@ struct raw1394_iso_packets upackets; int i, rv; - if(copy_from_user(&upackets, uaddr, sizeof(upackets))) + if (copy_from_user(&upackets, uaddr, sizeof(upackets))) return -EFAULT; - if(upackets.n_packets > hpsb_iso_n_ready(fi->iso_handle)) + if (upackets.n_packets > hpsb_iso_n_ready(fi->iso_handle)) return -EINVAL; /* ensure user-supplied buffer is accessible and big enough */ - if(verify_area(VERIFY_READ, upackets.infos, + if (verify_area(VERIFY_READ, upackets.infos, upackets.n_packets * sizeof(struct raw1394_iso_packet_info))) return -EFAULT; /* copy the infos structs in and queue the packets */ - for(i = 0; i < upackets.n_packets; i++) { + for (i = 0; i < upackets.n_packets; i++) { struct raw1394_iso_packet_info info; - if(__copy_from_user(&info, &upackets.infos[i], + if (__copy_from_user(&info, &upackets.infos[i], sizeof(struct raw1394_iso_packet_info))) return -EFAULT; rv = hpsb_iso_xmit_queue_packet(fi->iso_handle, info.offset, info.len, info.tag, info.sy); - if(rv) + if (rv) return rv; } @@ -2210,7 +2210,7 @@ static void raw1394_iso_shutdown(struct file_info *fi) { - if(fi->iso_handle) + if (fi->iso_handle) hpsb_iso_shutdown(fi->iso_handle); fi->iso_handle = NULL; @@ -2222,7 +2222,7 @@ { struct file_info *fi = file->private_data; - if(fi->iso_state == RAW1394_ISO_INACTIVE) + if (fi->iso_state == RAW1394_ISO_INACTIVE) return -EINVAL; return dma_region_mmap(&fi->iso_handle->data_buf, file, vma); @@ -2249,7 +2249,7 @@ case RAW1394_IOC_ISO_RECV_START: { /* copy args from user-space */ int args[3]; - if(copy_from_user(&args[0], (void*) arg, sizeof(args))) + if (copy_from_user(&args[0], (void*) arg, sizeof(args))) return -EFAULT; return hpsb_iso_recv_start(fi->iso_handle, args[0], args[1], args[2]); } @@ -2263,7 +2263,7 @@ case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK: { /* copy the u64 from user-space */ u64 mask; - if(copy_from_user(&mask, (void*) arg, sizeof(mask))) + if (copy_from_user(&mask, (void*) arg, sizeof(mask))) return -EFAULT; return hpsb_iso_recv_set_channel_mask(fi->iso_handle, mask); } @@ -2286,7 +2286,7 @@ case RAW1394_IOC_ISO_XMIT_START: { /* copy two ints from user-space */ int args[2]; - if(copy_from_user(&args[0], (void*) arg, sizeof(args))) + if (copy_from_user(&args[0], (void*) arg, sizeof(args))) return -EFAULT; return hpsb_iso_xmit_start(fi->iso_handle, args[0], args[1]); } @@ -2374,7 +2374,7 @@ struct arm_addr *arm_addr = NULL; int another_host; - if(fi->iso_state != RAW1394_ISO_INACTIVE) + if (fi->iso_state != RAW1394_ISO_INACTIVE) raw1394_iso_shutdown(fi); for (i = 0; i < 64; i++) { diff -Nru a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c --- a/drivers/ieee1394/sbp2.c Tue Jul 1 18:44:32 2003 +++ b/drivers/ieee1394/sbp2.c Tue Jul 1 18:44:32 2003 @@ -79,7 +79,7 @@ #include "sbp2.h" static char version[] __devinitdata = - "$Rev: 942 $ Ben Collins "; + "$Rev: 967 $ Ben Collins "; /* * Module load parameter definitions @@ -93,7 +93,7 @@ * (probably due to PCI latency/throughput issues with the part). You can * bump down the speed if you are running into problems. */ -static int max_speed = SPEED_MAX; +static int max_speed = IEEE1394_SPEED_MAX; module_param(max_speed, int, 0644); MODULE_PARM_DESC(max_speed, "Force max speed (3 = 800mb, 2 = 400mb default, 1 = 200mb, 0 = 100mb)"); @@ -780,8 +780,8 @@ scsi_id->ne = ud->ne; scsi_id->hi = hi; - scsi_id->speed_code = SPEED_100; - scsi_id->max_payload_size = sbp2_speedto_max_payload[SPEED_100]; + scsi_id->speed_code = IEEE1394_SPEED_100; + scsi_id->max_payload_size = sbp2_speedto_max_payload[IEEE1394_SPEED_100]; atomic_set(&scsi_id->sbp2_login_complete, 0); INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_inuse); INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_completed); diff -Nru a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c --- a/drivers/ieee1394/video1394.c Tue Jul 1 18:44:32 2003 +++ b/drivers/ieee1394/video1394.c Tue Jul 1 18:44:32 2003 @@ -589,7 +589,7 @@ it_prg[i].begin.status = 0; it_prg[i].data[0] = cpu_to_le32( - (SPEED_100 << 16) + (IEEE1394_SPEED_100 << 16) | (/* tag */ 1 << 14) | (d->channel << 8) | (TCODE_ISO_DATA << 4)); @@ -705,7 +705,7 @@ struct dma_iso_ctx *d; int i; - if(copy_from_user(&v, (void *)arg, sizeof(v))) + if (copy_from_user(&v, (void *)arg, sizeof(v))) return -EFAULT; /* if channel < 0, find lowest available one */ @@ -802,7 +802,7 @@ v.channel); } - if(copy_to_user((void *)arg, &v, sizeof(v))) + if (copy_to_user((void *)arg, &v, sizeof(v))) return -EFAULT; return 0; @@ -814,7 +814,7 @@ u64 mask; struct dma_iso_ctx *d; - if(copy_from_user(&channel, (void *)arg, sizeof(int))) + if (copy_from_user(&channel, (void *)arg, sizeof(int))) return -EFAULT; if (channel<0 || channel>(ISO_CHANNELS-1)) { @@ -849,7 +849,7 @@ struct video1394_wait v; struct dma_iso_ctx *d; - if(copy_from_user(&v, (void *)arg, sizeof(v))) + if (copy_from_user(&v, (void *)arg, sizeof(v))) return -EFAULT; d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, v.channel); @@ -911,7 +911,7 @@ struct dma_iso_ctx *d; int i; - if(copy_from_user(&v, (void *)arg, sizeof(v))) + if (copy_from_user(&v, (void *)arg, sizeof(v))) return -EFAULT; d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, v.channel); @@ -939,12 +939,12 @@ } #if 1 - while(d->buffer_status[v.buffer]!= + while (d->buffer_status[v.buffer]!= VIDEO1394_BUFFER_READY) { spin_unlock_irqrestore(&d->lock, flags); interruptible_sleep_on(&d->waitq); spin_lock_irqsave(&d->lock, flags); - if(signal_pending(current)) { + if (signal_pending(current)) { spin_unlock_irqrestore(&d->lock,flags); return -EINTR; } @@ -981,7 +981,7 @@ spin_unlock_irqrestore(&d->lock, flags); v.buffer=i; - if(copy_to_user((void *)arg, &v, sizeof(v))) + if (copy_to_user((void *)arg, &v, sizeof(v))) return -EFAULT; return 0; @@ -994,7 +994,7 @@ qv.packet_sizes = NULL; - if(copy_from_user(&v, (void *)arg, sizeof(v))) + if (copy_from_user(&v, (void *)arg, sizeof(v))) return -EFAULT; d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel); @@ -1097,7 +1097,7 @@ struct video1394_wait v; struct dma_iso_ctx *d; - if(copy_from_user(&v, (void *)arg, sizeof(v))) + if (copy_from_user(&v, (void *)arg, sizeof(v))) return -EFAULT; d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel); @@ -1114,10 +1114,10 @@ return 0; case VIDEO1394_BUFFER_QUEUED: #if 1 - while(d->buffer_status[v.buffer]!= + while (d->buffer_status[v.buffer]!= VIDEO1394_BUFFER_READY) { interruptible_sleep_on(&d->waitq); - if(signal_pending(current)) return -EINTR; + if (signal_pending(current)) return -EINTR; } #else if (wait_event_interruptible(d->waitq, diff -Nru a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c --- a/drivers/media/common/saa7146_core.c Tue Jul 1 18:44:36 2003 +++ b/drivers/media/common/saa7146_core.c Tue Jul 1 18:44:36 2003 @@ -20,10 +20,6 @@ #include -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) - #define KBUILD_MODNAME saa7146 -#endif - /* global variables */ struct list_head saa7146_devices; struct semaphore saa7146_devices_lock; @@ -53,8 +49,7 @@ ****************************************************************************/ /* this is videobuf_vmalloc_to_sg() from video-buf.c */ -static -struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages) +static struct scatterlist* vmalloc_to_sg(unsigned char *virt, int nr_pages) { struct scatterlist *sglist; struct page *pg; @@ -207,7 +202,6 @@ } saa7146_write(dev, ISR, isr); -// DEB_INT(("0x%08x\n",isr)); if( 0 != (dev->ext)) { if( 0 != (dev->ext->irq_mask & isr )) { @@ -260,8 +254,7 @@ /*********************************************************************************/ /* configuration-functions */ -static -int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent) +static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent) { unsigned long adr = 0, len = 0; struct saa7146_dev* dev = kmalloc (sizeof(struct saa7146_dev),GFP_KERNEL); @@ -340,33 +333,33 @@ } /* get memory for various stuff */ - dev->rps0 = (u32*)kmalloc(SAA7146_RPS_MEM, GFP_KERNEL); - if( NULL == dev->rps0 ) { + dev->d_rps0.cpu_addr = pci_alloc_consistent(dev->pci, SAA7146_RPS_MEM, &dev->d_rps0.dma_handle); + if( NULL == dev->d_rps0.cpu_addr ) { err = -ENOMEM; goto kmalloc_error_1; } - memset(dev->rps0, 0x0, SAA7146_RPS_MEM); + memset(dev->d_rps0.cpu_addr, 0x0, SAA7146_RPS_MEM); - dev->rps1 = (u32*)kmalloc(SAA7146_RPS_MEM, GFP_KERNEL); - if( NULL == dev->rps1 ) { + dev->d_rps1.cpu_addr = pci_alloc_consistent(dev->pci, SAA7146_RPS_MEM, &dev->d_rps1.dma_handle); + if( NULL == dev->d_rps1.cpu_addr ) { err = -ENOMEM; goto kmalloc_error_2; } - memset(dev->rps1, 0x0, SAA7146_RPS_MEM); + memset(dev->d_rps1.cpu_addr, 0x0, SAA7146_RPS_MEM); - dev->i2c_mem = (u32*)kmalloc(SAA7146_I2C_MEM, GFP_KERNEL); - if( NULL == dev->i2c_mem ) { + dev->d_i2c.cpu_addr = pci_alloc_consistent(dev->pci, SAA7146_RPS_MEM, &dev->d_i2c.dma_handle); + if( NULL == dev->d_i2c.cpu_addr ) { err = -ENOMEM; goto kmalloc_error_3; } - memset(dev->i2c_mem, 0x00, SAA7146_I2C_MEM); + memset(dev->d_i2c.cpu_addr, 0x0, SAA7146_RPS_MEM); /* the rest + print status message */ /* create a nice device name */ sprintf(&dev->name[0], "saa7146 (%d)",saa7146_num); - INFO(("found saa7146 @ mem 0x%08x (revision %d, irq %d) (0x%04x,0x%04x).\n", (unsigned int)dev->mem, dev->revision,dev->pci->irq,dev->pci->subsystem_vendor,dev->pci->subsystem_device)); + INFO(("found saa7146 @ mem %p (revision %d, irq %d) (0x%04x,0x%04x).\n", dev->mem, dev->revision,dev->pci->irq,dev->pci->subsystem_vendor,dev->pci->subsystem_device)); dev->ext = ext; pci_set_drvdata(pci,dev); @@ -406,11 +399,11 @@ attach_error: probe_error: pci_set_drvdata(pci,NULL); - kfree( dev->i2c_mem ); + pci_free_consistent(dev->pci, SAA7146_RPS_MEM, dev->d_i2c.cpu_addr, dev->d_i2c.dma_handle); kmalloc_error_3: - kfree( dev->rps1 ); + pci_free_consistent(dev->pci, SAA7146_RPS_MEM, dev->d_rps1.cpu_addr, dev->d_rps1.dma_handle); kmalloc_error_2: - kfree( dev->rps0 ); + pci_free_consistent(dev->pci, SAA7146_RPS_MEM, dev->d_rps0.cpu_addr, dev->d_rps0.dma_handle); kmalloc_error_1: free_irq(dev->pci->irq, (void *)dev); irq_error: @@ -423,8 +416,7 @@ return err; } -static -void saa7146_remove_one(struct pci_dev *pdev) +static void saa7146_remove_one(struct pci_dev *pdev) { struct saa7146_dev* dev = (struct saa7146_dev*) pci_get_drvdata(pdev); DEB_EE(("dev:%p\n",dev)); @@ -440,9 +432,9 @@ free_irq(dev->pci->irq, (void *)dev); /* free kernel memory */ - kfree(dev->rps0 ); - kfree(dev->rps1 ); - kfree(dev->i2c_mem); + pci_free_consistent(dev->pci, SAA7146_RPS_MEM, dev->d_i2c.cpu_addr, dev->d_i2c.dma_handle); + pci_free_consistent(dev->pci, SAA7146_RPS_MEM, dev->d_rps1.cpu_addr, dev->d_rps1.dma_handle); + pci_free_consistent(dev->pci, SAA7146_RPS_MEM, dev->d_rps0.cpu_addr, dev->d_rps0.dma_handle); iounmap(dev->mem); release_mem_region(pci_resource_start(dev->pci,0), pci_resource_len(dev->pci,0)); @@ -483,8 +475,7 @@ return 0; } -static -int __init saa7146_init_module(void) +static int __init saa7146_init_module(void) { if( 0 == initialized ) { INIT_LIST_HEAD(&saa7146_devices); @@ -494,8 +485,7 @@ return 0; } -static -void __exit saa7146_cleanup_module(void) +static void __exit saa7146_cleanup_module(void) { } diff -Nru a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c --- a/drivers/media/common/saa7146_fops.c Tue Jul 1 18:44:35 2003 +++ b/drivers/media/common/saa7146_fops.c Tue Jul 1 18:44:35 2003 @@ -1,9 +1,5 @@ #include -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) - #define KBUILD_MODNAME saa7146 -#endif - #define BOARD_CAN_DO_VBI(dev) (dev->revision != 0 && dev->vv_data->vbi_minor != -1) /********************************************************************************/ @@ -111,7 +107,7 @@ saa7146_write(dev, PROT_ADDR1, 0); /* write the address of the rps-program */ - saa7146_write(dev, RPS_ADDR0, virt_to_bus(&dev->rps0[ 0])); + saa7146_write(dev, RPS_ADDR0, dev->d_rps0.dma_handle); /* turn on rps */ saa7146_write(dev, MC1, (MASK_12 | MASK_28)); } @@ -148,8 +144,7 @@ /********************************************************************************/ /* file operations */ -static -int fops_open(struct inode *inode, struct file *file) +static int fops_open(struct inode *inode, struct file *file) { unsigned int minor = minor(inode->i_rdev); struct saa7146_dev *h = NULL, *dev = NULL; @@ -322,11 +317,11 @@ switch (fh->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: { - DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, data:%p, count:%d\n",file, data, count)); + DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, data:%p, count:%lun", file, data, (unsigned long)count)); return saa7146_video_uops.read(file,data,count,ppos); } case V4L2_BUF_TYPE_VBI_CAPTURE: { - DEB_EE(("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, data:%p, count:%d\n",file, data, count)); + DEB_EE(("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, data:%p, count:%lu\n", file, data, (unsigned long)count)); return saa7146_vbi_uops.read(file,data,count,ppos); } break; @@ -393,13 +388,13 @@ vv->video_minor = -1; vv->vbi_minor = -1; - vv->clipping = (u32*)kmalloc(SAA7146_CLIPPING_MEM, GFP_KERNEL); - if( NULL == vv->clipping ) { + vv->d_clipping.cpu_addr = pci_alloc_consistent(dev->pci, SAA7146_CLIPPING_MEM, &vv->d_clipping.dma_handle); + if( NULL == vv->d_clipping.cpu_addr ) { ERR(("out of memory. aborting.\n")); kfree(vv); return -1; } - memset(vv->clipping, 0x0, SAA7146_CLIPPING_MEM); + memset(vv->d_clipping.cpu_addr, 0x0, SAA7146_CLIPPING_MEM); saa7146_video_uops.init(dev,vv); saa7146_vbi_uops.init(dev,vv); @@ -416,6 +411,7 @@ DEB_EE(("dev:%p\n",dev)); + pci_free_consistent(dev->pci, SAA7146_RPS_MEM, vv->d_clipping.cpu_addr, vv->d_clipping.dma_handle); kfree(vv); dev->vv_data = NULL; dev->vv_callback = NULL; @@ -466,15 +462,13 @@ return 0; } -static -int __init saa7146_vv_init_module(void) +static int __init saa7146_vv_init_module(void) { return 0; } -static -void __exit saa7146_vv_cleanup_module(void) +static void __exit saa7146_vv_cleanup_module(void) { } diff -Nru a/drivers/media/common/saa7146_hlp.c b/drivers/media/common/saa7146_hlp.c --- a/drivers/media/common/saa7146_hlp.c Tue Jul 1 18:44:36 2003 +++ b/drivers/media/common/saa7146_hlp.c Tue Jul 1 18:44:36 2003 @@ -1,16 +1,11 @@ #include -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) - #define KBUILD_MODNAME saa7146 -#endif - #define my_min(type,x,y) \ ({ type __x = (x), __y = (y); __x < __y ? __x: __y; }) #define my_max(type,x,y) \ ({ type __x = (x), __y = (y); __x > __y ? __x: __y; }) -static -void calculate_output_format_register(struct saa7146_dev* saa, u32 palette, u32* clip_format) +static void calculate_output_format_register(struct saa7146_dev* saa, u32 palette, u32* clip_format) { /* clear out the necessary bits */ *clip_format &= 0x0000ffff; @@ -18,21 +13,18 @@ *clip_format |= (( ((palette&0xf00)>>8) << 30) | ((palette&0x00f) << 24) | (((palette&0x0f0)>>4) << 16)); } -static -void calculate_bcs_ctrl_register(struct saa7146_dev *dev, int brightness, int contrast, int colour, u32 *bcs_ctrl) +static void calculate_bcs_ctrl_register(struct saa7146_dev *dev, int brightness, int contrast, int colour, u32 *bcs_ctrl) { *bcs_ctrl = ((brightness << 24) | (contrast << 16) | (colour << 0)); } -static -void calculate_hps_source_and_sync(struct saa7146_dev *dev, int source, int sync, u32* hps_ctrl) +static void calculate_hps_source_and_sync(struct saa7146_dev *dev, int source, int sync, u32* hps_ctrl) { *hps_ctrl &= ~(MASK_30 | MASK_31 | MASK_28); *hps_ctrl |= (source << 30) | (sync << 28); } -static -void calculate_hxo_and_hyo(struct saa7146_vv *vv, u32* hps_h_scale, u32* hps_ctrl) +static void calculate_hxo_and_hyo(struct saa7146_vv *vv, u32* hps_h_scale, u32* hps_ctrl) { int hyo = 0, hxo = 0; @@ -77,8 +69,7 @@ u8 h_attenuation[] = { 1, 2, 4, 8, 2, 4, 8, 16, 0}; /* calculate horizontal scale registers */ -static -int calculate_h_scale_registers(struct saa7146_dev *dev, +static int calculate_h_scale_registers(struct saa7146_dev *dev, int in_x, int out_x, int flip_lr, u32* hps_ctrl, u32* hps_v_gain, u32* hps_h_prescale, u32* hps_h_scale) { @@ -225,8 +216,7 @@ u16 v_attenuation[] = { 2, 4, 8, 16, 32, 64, 128, 256, 0}; /* calculate vertical scale registers */ -static -int calculate_v_scale_registers(struct saa7146_dev *dev, enum v4l2_field field, +static int calculate_v_scale_registers(struct saa7146_dev *dev, enum v4l2_field field, int in_y, int out_y, u32* hps_v_scale, u32* hps_v_gain) { int lpi = 0; @@ -322,8 +312,7 @@ } /* simple bubble-sort algorithm with duplicate elimination */ -static -int sort_and_eliminate(u32* values, int* count) +static int sort_and_eliminate(u32* values, int* count) { int low = 0, high = 0, top = 0, temp = 0; int cur = 0, next = 0; @@ -355,12 +344,11 @@ return 0; } -static -void calculate_clipping_registers_rect(struct saa7146_dev *dev, struct saa7146_fh *fh, +static void calculate_clipping_registers_rect(struct saa7146_dev *dev, struct saa7146_fh *fh, struct saa7146_video_dma *vdma2, u32* clip_format, u32* arbtr_ctrl, enum v4l2_field field) { struct saa7146_vv *vv = dev->vv_data; - u32 *clipping = vv->clipping; + u32 *clipping = vv->d_clipping.cpu_addr; int width = fh->ov.win.w.width; int height = fh->ov.win.w.height; @@ -469,9 +457,9 @@ *arbtr_ctrl &= 0xffff00ff; *arbtr_ctrl |= 0x00001c00; - vdma2->base_even = virt_to_bus(clipping); - vdma2->base_odd = virt_to_bus(clipping); - vdma2->prot_addr = virt_to_bus(clipping)+((sizeof(u32))*(numdwords)); + vdma2->base_even = vv->d_clipping.dma_handle; + vdma2->base_odd = vv->d_clipping.dma_handle; + vdma2->prot_addr = vv->d_clipping.dma_handle+((sizeof(u32))*(numdwords)); vdma2->base_page = 0x04; vdma2->pitch = 0x00; vdma2->num_line_byte = (0 << 16 | (sizeof(u32))*(numdwords-1) ); @@ -488,8 +476,7 @@ } /* disable clipping */ -static -void saa7146_disable_clipping(struct saa7146_dev *dev) +static void saa7146_disable_clipping(struct saa7146_dev *dev) { u32 clip_format = saa7146_read(dev, CLIP_FORMAT_CTRL); @@ -504,8 +491,7 @@ saa7146_write(dev, MC1, (MASK_21)); } -static -void saa7146_set_clipping_rect(struct saa7146_dev *dev, struct saa7146_fh *fh) +static void saa7146_set_clipping_rect(struct saa7146_dev *dev, struct saa7146_fh *fh) { enum v4l2_field field = fh->ov.win.field; int clipcount = fh->ov.nclips; @@ -547,8 +533,7 @@ saa7146_write(dev, MC1, (MASK_05 | MASK_21)); } -static -void saa7146_set_window(struct saa7146_dev *dev, int width, int height, enum v4l2_field field) +static void saa7146_set_window(struct saa7146_dev *dev, int width, int height, enum v4l2_field field) { struct saa7146_vv *vv = dev->vv_data; @@ -584,8 +569,7 @@ } /* calculate the new memory offsets for a desired position */ -static -void saa7146_set_position(struct saa7146_dev *dev, int w_x, int w_y, int w_height, enum v4l2_field field) +static void saa7146_set_position(struct saa7146_dev *dev, int w_x, int w_y, int w_height, enum v4l2_field field) { struct saa7146_vv *vv = dev->vv_data; @@ -628,8 +612,7 @@ saa7146_write_out_dma(dev, 1, &vdma1); } -static -void saa7146_set_output_format(struct saa7146_dev *dev, unsigned long palette) +static void saa7146_set_output_format(struct saa7146_dev *dev, unsigned long palette) { u32 clip_format = saa7146_read(dev, CLIP_FORMAT_CTRL); @@ -746,8 +729,7 @@ printk("vdma%d.num_line_byte: 0x%08x\n", which,vdma->num_line_byte); */ } -static -int calculate_video_dma_grab_packed(struct saa7146_dev* dev, struct saa7146_buf *buf) +static int calculate_video_dma_grab_packed(struct saa7146_dev* dev, struct saa7146_buf *buf) { struct saa7146_vv *vv = dev->vv_data; struct saa7146_video_dma vdma1; @@ -795,8 +777,7 @@ return 0; } -static -int calc_planar_422(struct saa7146_vv *vv, struct saa7146_buf *buf, struct saa7146_video_dma *vdma2, struct saa7146_video_dma *vdma3) +static int calc_planar_422(struct saa7146_vv *vv, struct saa7146_buf *buf, struct saa7146_video_dma *vdma2, struct saa7146_video_dma *vdma3) { int height = buf->fmt->height; int width = buf->fmt->width; @@ -826,8 +807,7 @@ return 0; } -static -int calc_planar_420(struct saa7146_vv *vv, struct saa7146_buf *buf, struct saa7146_video_dma *vdma2, struct saa7146_video_dma *vdma3) +static int calc_planar_420(struct saa7146_vv *vv, struct saa7146_buf *buf, struct saa7146_video_dma *vdma2, struct saa7146_video_dma *vdma3) { int height = buf->fmt->height; int width = buf->fmt->width; @@ -857,8 +837,7 @@ } -static -int calculate_video_dma_grab_planar(struct saa7146_dev* dev, struct saa7146_buf *buf) +static int calculate_video_dma_grab_planar(struct saa7146_dev* dev, struct saa7146_buf *buf) { struct saa7146_vv *vv = dev->vv_data; struct saa7146_video_dma vdma1; @@ -953,67 +932,68 @@ return 0; } -static -void program_capture_engine(struct saa7146_dev *dev, int planar) +static void program_capture_engine(struct saa7146_dev *dev, int planar) { struct saa7146_vv *vv = dev->vv_data; - int count = 0; unsigned long e_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_E_FID_A : CMD_E_FID_B; unsigned long o_wait = vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? CMD_O_FID_A : CMD_O_FID_B; - /* write beginning of rps-program */ - count = 0; + if( 0 != (dev->ext->ext_vv_data->flags & SAA7146_EXT_SWAP_ODD_EVEN)) { + unsigned long tmp = e_wait; + e_wait = o_wait; + o_wait = tmp; + } /* wait for o_fid_a/b / e_fid_a/b toggle only if bit 0 is not set*/ - dev->rps0[ count++ ] = CMD_PAUSE | CMD_OAN | CMD_SIG0 | e_wait; - dev->rps0[ count++ ] = CMD_PAUSE | CMD_OAN | CMD_SIG0 | o_wait; + WRITE_RPS0(CMD_PAUSE | CMD_OAN | CMD_SIG0 | e_wait); + WRITE_RPS0(CMD_PAUSE | CMD_OAN | CMD_SIG0 | o_wait); /* set bit 0 */ - dev->rps0[ count++ ] = CMD_WR_REG | (1 << 8) | (MC2/4); - dev->rps0[ count++ ] = MASK_27 | MASK_11; + WRITE_RPS0(CMD_WR_REG | (1 << 8) | (MC2/4)); + WRITE_RPS0(MASK_27 | MASK_11); /* turn on video-dma1 */ - dev->rps0[ count++ ] = CMD_WR_REG_MASK | (MC1/4); - dev->rps0[ count++ ] = MASK_06 | MASK_22; /* => mask */ - dev->rps0[ count++ ] = MASK_06 | MASK_22; /* => values */ + WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4)); + WRITE_RPS0(MASK_06 | MASK_22); /* => mask */ + WRITE_RPS0(MASK_06 | MASK_22); /* => values */ if( 0 != planar ) { /* turn on video-dma2 */ - dev->rps0[ count++ ] = CMD_WR_REG_MASK | (MC1/4); - dev->rps0[ count++ ] = MASK_05 | MASK_21; /* => mask */ - dev->rps0[ count++ ] = MASK_05 | MASK_21; /* => values */ + WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4)); + WRITE_RPS0(MASK_05 | MASK_21); /* => mask */ + WRITE_RPS0(MASK_05 | MASK_21); /* => values */ /* turn on video-dma3 */ - dev->rps0[ count++ ] = CMD_WR_REG_MASK | (MC1/4); - dev->rps0[ count++ ] = MASK_04 | MASK_20; /* => mask */ - dev->rps0[ count++ ] = MASK_04 | MASK_20; /* => values */ + WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4)); + WRITE_RPS0(MASK_04 | MASK_20); /* => mask */ + WRITE_RPS0(MASK_04 | MASK_20); /* => values */ } /* wait for o_fid_a/b / e_fid_a/b toggle */ - dev->rps0[ count++ ] = CMD_PAUSE | e_wait; - dev->rps0[ count++ ] = CMD_PAUSE | o_wait; + WRITE_RPS0(CMD_PAUSE | e_wait); + WRITE_RPS0(CMD_PAUSE | o_wait); /* turn off video-dma1 */ - dev->rps0[ count++ ] = CMD_WR_REG_MASK | (MC1/4); - dev->rps0[ count++ ] = MASK_22 | MASK_06; /* => mask */ - dev->rps0[ count++ ] = MASK_22; /* => values */ + WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4)); + WRITE_RPS0(MASK_22 | MASK_06); /* => mask */ + WRITE_RPS0(MASK_22); /* => values */ if( 0 != planar ) { /* turn off video-dma2 */ - dev->rps0[ count++ ] = CMD_WR_REG_MASK | (MC1/4); - dev->rps0[ count++ ] = MASK_05 | MASK_21; /* => mask */ - dev->rps0[ count++ ] = MASK_21; /* => values */ + WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4)); + WRITE_RPS0(MASK_05 | MASK_21); /* => mask */ + WRITE_RPS0(MASK_21); /* => values */ /* turn off video-dma3 */ - dev->rps0[ count++ ] = CMD_WR_REG_MASK | (MC1/4); - dev->rps0[ count++ ] = MASK_04 | MASK_20; /* => mask */ - dev->rps0[ count++ ] = MASK_20; /* => values */ + WRITE_RPS0(CMD_WR_REG_MASK | (MC1/4)); + WRITE_RPS0(MASK_04 | MASK_20); /* => mask */ + WRITE_RPS0(MASK_20); /* => values */ } /* generate interrupt */ - dev->rps0[ count++ ] = CMD_INTERRUPT; + WRITE_RPS0(CMD_INTERRUPT); /* stop */ - dev->rps0[ count++ ] = CMD_STOP; + WRITE_RPS0(CMD_STOP); } void saa7146_set_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next) @@ -1035,7 +1015,7 @@ } /* write the address of the rps-program */ - saa7146_write(dev, RPS_ADDR0, virt_to_bus(&dev->rps0[ 0])); + saa7146_write(dev, RPS_ADDR0, dev->d_rps0.dma_handle); /* turn on rps */ saa7146_write(dev, MC1, (MASK_12 | MASK_28)); diff -Nru a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146_i2c.c --- a/drivers/media/common/saa7146_i2c.c Tue Jul 1 18:44:38 2003 +++ b/drivers/media/common/saa7146_i2c.c Tue Jul 1 18:44:38 2003 @@ -1,12 +1,7 @@ #include -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) - #define KBUILD_MODNAME saa7146 -#endif - /* helper function */ -static -void my_wait(struct saa7146_dev *dev, long ms) +static void my_wait(struct saa7146_dev *dev, long ms) { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout((((ms+10)/10)*HZ)/1000); @@ -23,8 +18,7 @@ } /* this function returns the status-register of our i2c-device */ -static inline -u32 saa7146_i2c_status(struct saa7146_dev *dev) +static inline u32 saa7146_i2c_status(struct saa7146_dev *dev) { u32 iicsta = saa7146_read(dev, I2C_STATUS); /* @@ -37,8 +31,7 @@ sent through the saa7146. have a look at the specifications p. 122 ff to understand this. it returns the number of u32s to send, or -1 in case of an error. */ -static -int saa7146_i2c_msg_prepare(const struct i2c_msg m[], int num, u32 *op) +static int saa7146_i2c_msg_prepare(const struct i2c_msg m[], int num, u32 *op) { int h1, h2; int i, j, addr; @@ -102,8 +95,7 @@ which bytes were read through the adapter and write them back to the corresponding i2c-message. but instead, we simply write back all bytes. fixme: this could be improved. */ -static -int saa7146_i2c_msg_cleanup(const struct i2c_msg m[], int num, u32 *op) +static int saa7146_i2c_msg_cleanup(const struct i2c_msg m[], int num, u32 *op) { int i, j; int op_count = 0; @@ -125,8 +117,7 @@ } /* this functions resets the i2c-device and returns 0 if everything was fine, otherwise -1 */ -static -int saa7146_i2c_reset(struct saa7146_dev *dev) +static int saa7146_i2c_reset(struct saa7146_dev *dev) { /* get current status */ u32 status = saa7146_i2c_status(dev); @@ -190,8 +181,7 @@ /* this functions writes out the data-byte 'dword' to the i2c-device. it returns 0 if ok, -1 if the transfer failed, -2 if the transfer failed badly (e.g. address error) */ -static -int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword) +static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword) { u32 status = 0, mc2 = 0; int timeout; @@ -284,7 +274,7 @@ int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg msgs[], int num, int retries) { int i = 0, count = 0; - u32* buffer = dev->i2c_mem; + u32* buffer = dev->d_i2c.cpu_addr; int err = 0; int address_err = 0; @@ -377,13 +367,10 @@ } /* utility functions */ -static -int saa7146_i2c_xfer(struct i2c_adapter* adapter, struct i2c_msg msg[], int num) +static int saa7146_i2c_xfer(struct i2c_adapter* adapter, struct i2c_msg msg[], int num) { struct saa7146_dev* dev = i2c_get_adapdata(adapter); - DEB_I2C(("adapter: '%s'.\n", adapter->dev.name)); - /* use helper function to transfer data */ return saa7146_i2c_transfer(dev, msg, num, adapter->retries); } @@ -394,8 +381,7 @@ #include /* exported algorithm data */ -static -struct i2c_algorithm saa7146_algo = { +static struct i2c_algorithm saa7146_algo = { .name = "saa7146 i2c algorithm", .id = I2C_ALGO_SAA7146, .master_xfer = saa7146_i2c_xfer, diff -Nru a/drivers/media/common/saa7146_vbi.c b/drivers/media/common/saa7146_vbi.c --- a/drivers/media/common/saa7146_vbi.c Tue Jul 1 18:44:31 2003 +++ b/drivers/media/common/saa7146_vbi.c Tue Jul 1 18:44:31 2003 @@ -1,20 +1,15 @@ #include -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) - #define KBUILD_MODNAME saa7146 -#endif - static int vbi_pixel_to_capture = 720 * 2; -static -int vbi_workaround(struct saa7146_dev *dev) +static int vbi_workaround(struct saa7146_dev *dev) { struct saa7146_vv *vv = dev->vv_data; u32 *cpu; dma_addr_t dma_addr; - int i, index; + int i; DECLARE_WAITQUEUE(wait, current); @@ -38,54 +33,51 @@ saa7146_write(dev, NUM_LINE_BYTE3, (2<<16)|((vbi_pixel_to_capture)<<0)); saa7146_write(dev, MC2, MASK_04|MASK_20); - - /* we have to do the workaround two times to be sure that - everything is ok */ - for(i = 0; i < 2; i++) { - - /* indicate to the irq handler that we do the workaround */ - saa7146_write(dev, MC2, MASK_31|MASK_15); - - saa7146_write(dev, NUM_LINE_BYTE3, (1<<16)|(2<<0)); - saa7146_write(dev, MC2, MASK_04|MASK_20); - - index = 0; - /* load brs-control register */ - dev->rps1[index++] = CMD_WR_REG | (1 << 8) | (BRS_CTRL/4); + WRITE_RPS1(CMD_WR_REG | (1 << 8) | (BRS_CTRL/4)); /* BXO = 1h, BRS to outbound */ - dev->rps1[index++]=0xc000008c; + WRITE_RPS1(0xc000008c); /* wait for vbi_a */ - dev->rps1[index++] = CMD_PAUSE | MASK_10; + WRITE_RPS1(CMD_PAUSE | MASK_10); /* upload brs */ - dev->rps1[index++] = CMD_UPLOAD | MASK_08; + WRITE_RPS1(CMD_UPLOAD | MASK_08); /* load brs-control register */ - dev->rps1[index++] = CMD_WR_REG | (1 << 8) | (BRS_CTRL/4); + WRITE_RPS1(CMD_WR_REG | (1 << 8) | (BRS_CTRL/4)); /* BYO = 1, BXO = NQBIL (=1728 for PAL, for NTSC this is 858*2) - NumByte3 (=1440) = 288 */ - dev->rps1[index++] = ((1728-(vbi_pixel_to_capture)) << 7) | MASK_19; + WRITE_RPS1(((1728-(vbi_pixel_to_capture)) << 7) | MASK_19); /* wait for brs_done */ - dev->rps1[index++] = CMD_PAUSE | MASK_08; + WRITE_RPS1(CMD_PAUSE | MASK_08); /* upload brs */ - dev->rps1[index++] = CMD_UPLOAD | MASK_08; + WRITE_RPS1(CMD_UPLOAD | MASK_08); /* load video-dma3 NumLines3 and NumBytes3 */ - dev->rps1[index++] = CMD_WR_REG | (1 << 8) | (NUM_LINE_BYTE3/4); + WRITE_RPS1(CMD_WR_REG | (1 << 8) | (NUM_LINE_BYTE3/4)); /* dev->vbi_count*2 lines, 720 pixel (= 1440 Bytes) */ - dev->rps1[index++]= (2 << 16) | (vbi_pixel_to_capture); + WRITE_RPS1((2 << 16) | (vbi_pixel_to_capture)); /* load brs-control register */ - dev->rps1[index++] = CMD_WR_REG | (1 << 8) | (BRS_CTRL/4); + WRITE_RPS1(CMD_WR_REG | (1 << 8) | (BRS_CTRL/4)); /* Set BRS right: note: this is an experimental value for BXO (=> PAL!) */ - dev->rps1[index++] = (540 << 7) | (5 << 19); // 5 == vbi_start + WRITE_RPS1((540 << 7) | (5 << 19)); // 5 == vbi_start /* wait for brs_done */ - dev->rps1[index++] = CMD_PAUSE | MASK_08; + WRITE_RPS1(CMD_PAUSE | MASK_08); /* upload brs and video-dma3*/ - dev->rps1[index++] = CMD_UPLOAD | MASK_08 | MASK_04; + WRITE_RPS1(CMD_UPLOAD | MASK_08 | MASK_04); /* load mc2 register: enable dma3 */ - dev->rps1[index++] = CMD_WR_REG | (1 << 8) | (MC1/4); - dev->rps1[index++] = MASK_20 | MASK_04; + WRITE_RPS1(CMD_WR_REG | (1 << 8) | (MC1/4)); + WRITE_RPS1(MASK_20 | MASK_04); /* generate interrupt */ - dev->rps1[index++] = CMD_INTERRUPT; + WRITE_RPS1(CMD_INTERRUPT); /* stop rps1 */ - dev->rps1[index++] = CMD_STOP; + WRITE_RPS1(CMD_STOP); + + /* we have to do the workaround twice to be sure that + everything is ok */ + for(i = 0; i < 2; i++) { + + /* indicate to the irq handler that we do the workaround */ + saa7146_write(dev, MC2, MASK_31|MASK_15); + + saa7146_write(dev, NUM_LINE_BYTE3, (1<<16)|(2<<0)); + saa7146_write(dev, MC2, MASK_04|MASK_20); /* enable rps1 irqs */ IER_ENABLE(dev,MASK_28); @@ -95,7 +87,7 @@ current->state = TASK_INTERRUPTIBLE; /* start rps1 to enable workaround */ - saa7146_write(dev, RPS_ADDR1, virt_to_bus(&dev->rps1[ 0])); + saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle); saa7146_write(dev, MC1, (MASK_13 | MASK_29)); schedule(); @@ -164,40 +156,39 @@ but by doing this, we can use the whole engine from video-buf.c... */ /* - dev->rps1[ count++ ] = CMD_PAUSE | CMD_OAN | CMD_SIG1 | e_wait; - dev->rps1[ count++ ] = CMD_PAUSE | CMD_OAN | CMD_SIG1 | o_wait; + WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | e_wait); + WRITE_RPS1(CMD_PAUSE | CMD_OAN | CMD_SIG1 | o_wait); */ /* set bit 1 */ - dev->rps1[ count++ ] = CMD_WR_REG | (1 << 8) | (MC2/4); - dev->rps1[ count++ ] = MASK_28 | MASK_12; + WRITE_RPS1(CMD_WR_REG | (1 << 8) | (MC2/4)); + WRITE_RPS1(MASK_28 | MASK_12); /* turn on video-dma3 */ - dev->rps1[ count++ ] = CMD_WR_REG_MASK | (MC1/4); - dev->rps1[ count++ ] = MASK_04 | MASK_20; /* => mask */ - dev->rps1[ count++ ] = MASK_04 | MASK_20; /* => values */ + WRITE_RPS1(CMD_WR_REG_MASK | (MC1/4)); + WRITE_RPS1(MASK_04 | MASK_20); /* => mask */ + WRITE_RPS1(MASK_04 | MASK_20); /* => values */ /* wait for o_fid_a/b / e_fid_a/b toggle */ - dev->rps1[ count++ ] = CMD_PAUSE | o_wait; - dev->rps1[ count++ ] = CMD_PAUSE | e_wait; + WRITE_RPS1(CMD_PAUSE | o_wait); + WRITE_RPS1(CMD_PAUSE | e_wait); /* generate interrupt */ - dev->rps1[ count++ ] = CMD_INTERRUPT; + WRITE_RPS1(CMD_INTERRUPT); /* stop */ - dev->rps1[ count++ ] = CMD_STOP; + WRITE_RPS1(CMD_STOP); /* enable rps1 irqs */ IER_ENABLE(dev, MASK_28); /* write the address of the rps-program */ - saa7146_write(dev, RPS_ADDR1, virt_to_bus(&dev->rps1[ 0])); + saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle); /* turn on rps */ saa7146_write(dev, MC1, (MASK_13 | MASK_29)); } -static -int buffer_activate(struct saa7146_dev *dev, +static int buffer_activate(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next) { @@ -211,8 +202,7 @@ return 0; } -static -int buffer_prepare(struct file *file, struct videobuf_buffer *vb,enum v4l2_field field) +static int buffer_prepare(struct file *file, struct videobuf_buffer *vb,enum v4l2_field field) { struct saa7146_fh *fh = file->private_data; struct saa7146_dev *dev = fh->dev; @@ -261,8 +251,7 @@ return err; } -static int -buffer_setup(struct file *file, unsigned int *count, unsigned int *size) +static int buffer_setup(struct file *file, unsigned int *count, unsigned int *size) { int llength,lines; @@ -277,8 +266,7 @@ return 0; } -static -void buffer_queue(struct file *file, struct videobuf_buffer *vb) +static void buffer_queue(struct file *file, struct videobuf_buffer *vb) { struct saa7146_fh *fh = file->private_data; struct saa7146_dev *dev = fh->dev; @@ -289,8 +277,7 @@ saa7146_buffer_queue(dev,&vv->vbi_q,buf); } -static -void buffer_release(struct file *file, struct videobuf_buffer *vb) +static void buffer_release(struct file *file, struct videobuf_buffer *vb) { struct saa7146_fh *fh = file->private_data; struct saa7146_dev *dev = fh->dev; @@ -300,8 +287,7 @@ saa7146_dma_free(dev,buf); } -static -struct videobuf_queue_ops vbi_qops = { +static struct videobuf_queue_ops vbi_qops = { .buf_setup = buffer_setup, .buf_prepare = buffer_prepare, .buf_queue = buffer_queue, @@ -310,8 +296,7 @@ /* ------------------------------------------------------------------ */ -static -void vbi_stop(struct saa7146_fh *fh) +static void vbi_stop(struct saa7146_fh *fh) { struct saa7146_dev *dev = fh->dev; struct saa7146_vv *vv = dev->vv_data; @@ -333,8 +318,7 @@ spin_unlock_irqrestore(&dev->slock, flags); } -static -void vbi_read_timeout(unsigned long data) +static void vbi_read_timeout(unsigned long data) { struct saa7146_fh *fh = (struct saa7146_fh *)data; struct saa7146_dev *dev = fh->dev; @@ -344,8 +328,7 @@ vbi_stop(fh); } -static -void vbi_init(struct saa7146_dev *dev, struct saa7146_vv *vv) +static void vbi_init(struct saa7146_dev *dev, struct saa7146_vv *vv) { DEB_VBI(("dev:%p\n",dev)); @@ -359,8 +342,7 @@ init_waitqueue_head(&vv->vbi_wq); } -static -void vbi_open(struct saa7146_dev *dev, struct saa7146_fh *fh) +static void vbi_open(struct saa7146_dev *dev, struct saa7146_fh *fh) { DEB_VBI(("dev:%p, fh:%p\n",dev,fh)); @@ -391,8 +373,7 @@ vbi_workaround(dev); } -static -void vbi_close(struct saa7146_dev *dev, struct saa7146_fh *fh, struct file *file) +static void vbi_close(struct saa7146_dev *dev, struct saa7146_fh *fh, struct file *file) { struct saa7146_vv *vv = dev->vv_data; DEB_VBI(("dev:%p, fh:%p\n",dev,fh)); @@ -402,8 +383,7 @@ } } -static -void vbi_irq_done(struct saa7146_dev *dev, unsigned long status) +static void vbi_irq_done(struct saa7146_dev *dev, unsigned long status) { struct saa7146_vv *vv = dev->vv_data; spin_lock(&dev->slock); @@ -422,8 +402,7 @@ spin_unlock(&dev->slock); } -static -ssize_t vbi_read(struct file *file, char *data, size_t count, loff_t *ppos) +static ssize_t vbi_read(struct file *file, char *data, size_t count, loff_t *ppos) { struct saa7146_fh *fh = file->private_data; struct saa7146_dev *dev = fh->dev; diff -Nru a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c --- a/drivers/media/common/saa7146_video.c Tue Jul 1 18:44:36 2003 +++ b/drivers/media/common/saa7146_video.c Tue Jul 1 18:44:36 2003 @@ -1,18 +1,12 @@ #include -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) - #define KBUILD_MODNAME saa7146 -#endif - -static -int memory = 32; +static int memory = 32; MODULE_PARM(memory,"i"); MODULE_PARM_DESC(memory, "maximum memory usage for capture buffers (default: 32Mb)"); /* format descriptions for capture and preview */ -static -struct saa7146_format formats[] = { +static struct saa7146_format formats[] = { { .name = "RGB-8 (3-3-2)", .pixelformat = V4L2_PIX_FMT_RGB332, @@ -67,8 +61,7 @@ due to this, it's impossible to provide additional *packed* formats, which are simply byte swapped (like V4L2_PIX_FMT_YUYV) ... 8-( */ -static -int NUM_FORMATS = sizeof(formats)/sizeof(struct saa7146_format); +static int NUM_FORMATS = sizeof(formats)/sizeof(struct saa7146_format); struct saa7146_format* format_by_fourcc(struct saa7146_dev *dev, int fourcc) { @@ -84,8 +77,7 @@ return NULL; } -static -int g_fmt(struct saa7146_fh *fh, struct v4l2_format *f) +static int g_fmt(struct saa7146_fh *fh, struct v4l2_format *f) { struct saa7146_dev *dev = fh->dev; DEB_EE(("dev:%p, fh:%p\n",dev,fh)); @@ -108,8 +100,7 @@ } } -static -int try_win(struct saa7146_dev *dev, struct v4l2_window *win) +static int try_win(struct saa7146_dev *dev, struct v4l2_window *win) { struct saa7146_vv *vv = dev->vv_data; enum v4l2_field field; @@ -165,8 +156,7 @@ return 0; } -static -int try_fmt(struct saa7146_fh *fh, struct v4l2_format *f) +static int try_fmt(struct saa7146_fh *fh, struct v4l2_format *f) { struct saa7146_dev *dev = fh->dev; struct saa7146_vv *vv = dev->vv_data; @@ -230,8 +220,7 @@ } } -static -int start_preview(struct saa7146_fh *fh) +static int start_preview(struct saa7146_fh *fh) { struct saa7146_dev *dev = fh->dev; struct saa7146_vv *vv = dev->vv_data; @@ -277,8 +266,7 @@ return 0; } -static -int stop_preview(struct saa7146_fh *fh) +static int stop_preview(struct saa7146_fh *fh) { struct saa7146_dev *dev = fh->dev; struct saa7146_vv *vv = dev->vv_data; @@ -302,8 +290,7 @@ return 0; } -static -int s_fmt(struct saa7146_fh *fh, struct v4l2_format *f) +static int s_fmt(struct saa7146_fh *fh, struct v4l2_format *f) { struct saa7146_dev *dev = fh->dev; struct saa7146_vv *vv = dev->vv_data; @@ -362,8 +349,7 @@ /********************************************************************************/ /* device controls */ -static -struct v4l2_queryctrl controls[] = { +static struct v4l2_queryctrl controls[] = { { id: V4L2_CID_BRIGHTNESS, name: "Brightness", @@ -402,13 +388,11 @@ type: V4L2_CTRL_TYPE_BOOLEAN, }, }; -static -int NUM_CONTROLS = sizeof(controls)/sizeof(struct v4l2_queryctrl); +static int NUM_CONTROLS = sizeof(controls)/sizeof(struct v4l2_queryctrl); #define V4L2_CID_PRIVATE_LASTP1 (V4L2_CID_PRIVATE_BASE + 0) -static -struct v4l2_queryctrl* ctrl_by_id(int id) +static struct v4l2_queryctrl* ctrl_by_id(int id) { int i; @@ -418,8 +402,7 @@ return NULL; } -static -int get_control(struct saa7146_fh *fh, struct v4l2_control *c) +static int get_control(struct saa7146_fh *fh, struct v4l2_control *c) { struct saa7146_dev *dev = fh->dev; struct saa7146_vv *vv = dev->vv_data; @@ -434,20 +417,25 @@ case V4L2_CID_BRIGHTNESS: value = saa7146_read(dev, BCS_CTRL); c->value = 0xff & (value >> 24); + DEB_D(("V4L2_CID_BRIGHTNESS: %d\n",c->value)); break; case V4L2_CID_CONTRAST: value = saa7146_read(dev, BCS_CTRL); c->value = 0x7f & (value >> 16); + DEB_D(("V4L2_CID_CONTRAST: %d\n",c->value)); break; case V4L2_CID_SATURATION: value = saa7146_read(dev, BCS_CTRL); c->value = 0x7f & (value >> 0); + DEB_D(("V4L2_CID_SATURATION: %d\n",c->value)); break; case V4L2_CID_VFLIP: c->value = vv->vflip; + DEB_D(("V4L2_CID_VFLIP: %d\n",c->value)); break; case V4L2_CID_HFLIP: c->value = vv->hflip; + DEB_D(("V4L2_CID_HFLIP: %d\n",c->value)); break; default: return -EINVAL; @@ -456,8 +444,7 @@ return 0; } -static -int set_control(struct saa7146_fh *fh, struct v4l2_control *c) +static int set_control(struct saa7146_fh *fh, struct v4l2_control *c) { struct saa7146_dev *dev = fh->dev; struct saa7146_vv *vv = dev->vv_data; @@ -547,8 +534,7 @@ /********************************************************************************/ /* common pagetable functions */ -static -int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *buf) +static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *buf) { struct pci_dev *pci = dev->pci; struct scatterlist *list = buf->vb.dma.sglist; @@ -666,8 +652,7 @@ /********************************************************************************/ /* file operations */ -static -int video_begin(struct saa7146_fh *fh) +static int video_begin(struct saa7146_fh *fh) { struct saa7146_dev *dev = fh->dev; struct saa7146_vv *vv = dev->vv_data; @@ -700,8 +685,7 @@ return 0; } -static -int video_end(struct saa7146_fh *fh) +static int video_end(struct saa7146_fh *fh) { struct saa7146_dev *dev = fh->dev; struct saa7146_vv *vv = dev->vv_data; @@ -876,7 +860,7 @@ return -EINVAL; } - DEB_EE(("VIDIOC_ENUMSTD: type:%d, index:%d\n",f->type,f->index)); + DEB_EE(("VIDIOC_ENUM_FMT: type:%d, index:%d\n",f->type,f->index)); return 0; } case VIDIOC_QUERYCTRL: @@ -974,6 +958,8 @@ struct saa7146_fh *ov_fh = NULL; + DEB_EE(("VIDIOC_S_STD\n")); + if( 0 != vv->streaming ) { return -EBUSY; } @@ -1112,8 +1098,7 @@ /*********************************************************************************/ /* buffer handling functions */ -static -int buffer_activate (struct saa7146_dev *dev, +static int buffer_activate (struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next) { @@ -1126,8 +1111,7 @@ return 0; } -static -int buffer_prepare(struct file *file, struct videobuf_buffer *vb, enum v4l2_field field) +static int buffer_prepare(struct file *file, struct videobuf_buffer *vb, enum v4l2_field field) { struct saa7146_fh *fh = file->private_data; struct saa7146_dev *dev = fh->dev; @@ -1205,8 +1189,7 @@ return err; } -static -int buffer_setup(struct file *file, unsigned int *count, unsigned int *size) +static int buffer_setup(struct file *file, unsigned int *count, unsigned int *size) { struct saa7146_fh *fh = file->private_data; @@ -1225,8 +1208,7 @@ return 0; } -static -void buffer_queue(struct file *file, struct videobuf_buffer *vb) +static void buffer_queue(struct file *file, struct videobuf_buffer *vb) { struct saa7146_fh *fh = file->private_data; struct saa7146_dev *dev = fh->dev; @@ -1238,8 +1220,7 @@ } -static -void buffer_release(struct file *file, struct videobuf_buffer *vb) +static void buffer_release(struct file *file, struct videobuf_buffer *vb) { struct saa7146_fh *fh = file->private_data; struct saa7146_dev *dev = fh->dev; @@ -1249,8 +1230,7 @@ saa7146_dma_free(dev,buf); } -static -struct videobuf_queue_ops video_qops = { +static struct videobuf_queue_ops video_qops = { .buf_setup = buffer_setup, .buf_prepare = buffer_prepare, .buf_queue = buffer_queue, @@ -1260,8 +1240,7 @@ /********************************************************************************/ /* file operations */ -static -void video_init(struct saa7146_dev *dev, struct saa7146_vv *vv) +static void video_init(struct saa7146_dev *dev, struct saa7146_vv *vv) { INIT_LIST_HEAD(&vv->video_q.queue); @@ -1279,8 +1258,7 @@ } -static -void video_open(struct saa7146_dev *dev, struct saa7146_fh *fh) +static void video_open(struct saa7146_dev *dev, struct saa7146_fh *fh) { struct saa7146_format *sfmt; @@ -1301,8 +1279,7 @@ } -static -void video_close(struct saa7146_dev *dev, struct saa7146_fh *fh, struct file *file) +static void video_close(struct saa7146_dev *dev, struct saa7146_fh *fh, struct file *file) { struct saa7146_vv *vv = dev->vv_data; unsigned long flags; @@ -1323,8 +1300,7 @@ } -static -void video_irq_done(struct saa7146_dev *dev, unsigned long st) +static void video_irq_done(struct saa7146_dev *dev, unsigned long st) { struct saa7146_vv *vv = dev->vv_data; struct saa7146_dmaqueue *q = &vv->video_q; @@ -1341,8 +1317,7 @@ spin_unlock(&dev->slock); } -static -ssize_t video_read(struct file *file, char *data, size_t count, loff_t *ppos) +static ssize_t video_read(struct file *file, char *data, size_t count, loff_t *ppos) { struct saa7146_fh *fh = file->private_data; struct saa7146_dev *dev = fh->dev; diff -Nru a/drivers/media/dvb/dvb-core/Makefile b/drivers/media/dvb/dvb-core/Makefile --- a/drivers/media/dvb/dvb-core/Makefile Tue Jul 1 18:44:39 2003 +++ b/drivers/media/dvb/dvb-core/Makefile Tue Jul 1 18:44:39 2003 @@ -3,6 +3,6 @@ # dvb-core-objs = dvbdev.o dmxdev.o dvb_demux.o dvb_filter.o \ - dvb_frontend.o dvb_i2c.o dvb_net.o dvb_ksyms.o dvb_ringbuffer.o + dvb_functions.o dvb_frontend.o dvb_i2c.o dvb_net.o dvb_ksyms.o dvb_ringbuffer.o obj-$(CONFIG_DVB_CORE) += dvb-core.o diff -Nru a/drivers/media/dvb/dvb-core/demux.h b/drivers/media/dvb/dvb-core/demux.h --- a/drivers/media/dvb/dvb-core/demux.h Tue Jul 1 18:44:34 2003 +++ b/drivers/media/dvb/dvb-core/demux.h Tue Jul 1 18:44:34 2003 @@ -25,14 +25,10 @@ #ifndef __DEMUX_H #define __DEMUX_H -#ifndef __KERNEL__ -#define __KERNEL__ -#endif - #include +#include #include #include -#include /*--------------------------------------------------------------------------*/ /* Common definitions */ @@ -47,10 +43,10 @@ #endif /* - * dmx_success_t: Success codes for the Demux Callback API. + * enum dmx_success: Success codes for the Demux Callback API. */ -typedef enum { +enum dmx_success { DMX_OK = 0, /* Received Ok */ DMX_LENGTH_ERROR, /* Incorrect length */ DMX_OVERRUN_ERROR, /* Receiver ring buffer overrun */ @@ -58,7 +54,7 @@ DMX_FRAME_ERROR, /* Frame alignment error */ DMX_FIFO_ERROR, /* Receiver FIFO overrun */ DMX_MISSED_ERROR /* Receiver missed packet */ -} dmx_success_t; +} ; /*--------------------------------------------------------------------------*/ /* TS packet reception */ @@ -74,7 +70,7 @@ /* PES type for filters which write to built-in decoder */ /* these should be kept identical to the types in dmx.h */ -typedef enum +enum dmx_ts_pes { /* also send packets to decoder (if it exists) */ DMX_TS_PES_AUDIO0, DMX_TS_PES_VIDEO0, @@ -101,7 +97,7 @@ DMX_TS_PES_PCR3, DMX_TS_PES_OTHER -} dmx_ts_pes_t; +}; #define DMX_TS_PES_AUDIO DMX_TS_PES_AUDIO0 #define DMX_TS_PES_VIDEO DMX_TS_PES_VIDEO0 @@ -110,39 +106,37 @@ #define DMX_TS_PES_PCR DMX_TS_PES_PCR0 -struct dmx_ts_feed_s { +struct dmx_ts_feed { int is_filtering; /* Set to non-zero when filtering in progress */ - struct dmx_demux_s *parent; /* Back-pointer */ + struct dmx_demux *parent; /* Back-pointer */ void *priv; /* Pointer to private data of the API client */ - int (*set) (struct dmx_ts_feed_s *feed, - uint16_t pid, + int (*set) (struct dmx_ts_feed *feed, + u16 pid, int type, - dmx_ts_pes_t pes_type, + enum dmx_ts_pes pes_type, size_t callback_length, size_t circular_buffer_size, int descramble, struct timespec timeout); - int (*start_filtering) (struct dmx_ts_feed_s* feed); - int (*stop_filtering) (struct dmx_ts_feed_s* feed); + int (*start_filtering) (struct dmx_ts_feed* feed); + int (*stop_filtering) (struct dmx_ts_feed* feed); }; -typedef struct dmx_ts_feed_s dmx_ts_feed_t; - /*--------------------------------------------------------------------------*/ /* Section reception */ /*--------------------------------------------------------------------------*/ -typedef struct { - __u8 filter_value [DMX_MAX_FILTER_SIZE]; - __u8 filter_mask [DMX_MAX_FILTER_SIZE]; - __u8 filter_mode [DMX_MAX_FILTER_SIZE]; - struct dmx_section_feed_s* parent; /* Back-pointer */ +struct dmx_section_filter { + u8 filter_value [DMX_MAX_FILTER_SIZE]; + u8 filter_mask [DMX_MAX_FILTER_SIZE]; + u8 filter_mode [DMX_MAX_FILTER_SIZE]; + struct dmx_section_feed* parent; /* Back-pointer */ void* priv; /* Pointer to private data of the API client */ -} dmx_section_filter_t; +}; -struct dmx_section_feed_s { +struct dmx_section_feed { int is_filtering; /* Set to non-zero when filtering in progress */ - struct dmx_demux_s* parent; /* Back-pointer */ + struct dmx_demux* parent; /* Back-pointer */ void* priv; /* Pointer to private data of the API client */ int check_crc; @@ -152,19 +146,18 @@ int secbufp; int seclen; - int (*set) (struct dmx_section_feed_s* feed, - __u16 pid, + int (*set) (struct dmx_section_feed* feed, + u16 pid, size_t circular_buffer_size, int descramble, int check_crc); - int (*allocate_filter) (struct dmx_section_feed_s* feed, - dmx_section_filter_t** filter); - int (*release_filter) (struct dmx_section_feed_s* feed, - dmx_section_filter_t* filter); - int (*start_filtering) (struct dmx_section_feed_s* feed); - int (*stop_filtering) (struct dmx_section_feed_s* feed); + int (*allocate_filter) (struct dmx_section_feed* feed, + struct dmx_section_filter** filter); + int (*release_filter) (struct dmx_section_feed* feed, + struct dmx_section_filter* filter); + int (*start_filtering) (struct dmx_section_feed* feed); + int (*stop_filtering) (struct dmx_section_feed* feed); }; -typedef struct dmx_section_feed_s dmx_section_feed_t; /*--------------------------------------------------------------------------*/ /* Callback functions */ @@ -174,21 +167,21 @@ size_t buffer1_length, const u8 * buffer2, size_t buffer2_length, - dmx_ts_feed_t* source, - dmx_success_t success); + struct dmx_ts_feed* source, + enum dmx_success success); typedef int (*dmx_section_cb) ( const u8 * buffer1, size_t buffer1_len, const u8 * buffer2, size_t buffer2_len, - dmx_section_filter_t * source, - dmx_success_t success); + struct dmx_section_filter * source, + enum dmx_success success); /*--------------------------------------------------------------------------*/ /* DVB Front-End */ /*--------------------------------------------------------------------------*/ -typedef enum { +enum dmx_frontend_source { DMX_MEMORY_FE, DMX_FRONTEND_0, DMX_FRONTEND_1, @@ -198,26 +191,22 @@ DMX_STREAM_1, DMX_STREAM_2, DMX_STREAM_3 -} dmx_frontend_source_t; +}; -typedef struct { - /* The following char* fields point to NULL terminated strings */ - char* id; /* Unique front-end identifier */ - char* vendor; /* Name of the front-end vendor */ - char* model; /* Name of the front-end model */ +struct dmx_frontend { struct list_head connectivity_list; /* List of front-ends that can be connected to a particular demux */ void* priv; /* Pointer to private data of the API client */ - dmx_frontend_source_t source; -} dmx_frontend_t; + enum dmx_frontend_source source; +}; /*--------------------------------------------------------------------------*/ /* MPEG-2 TS Demux */ /*--------------------------------------------------------------------------*/ /* - * Flags OR'ed in the capabilites field of struct dmx_demux_s. + * Flags OR'ed in the capabilites field of struct dmx_demux. */ #define DMX_TS_FILTERING 1 @@ -236,61 +225,56 @@ /* * DMX_FE_ENTRY(): Casts elements in the list of registered * front-ends from the generic type struct list_head - * to the type * dmx_frontend_t + * to the type * struct dmx_frontend *. */ -#define DMX_FE_ENTRY(list) list_entry(list, dmx_frontend_t, connectivity_list) +#define DMX_FE_ENTRY(list) list_entry(list, struct dmx_frontend, connectivity_list) -struct dmx_demux_s { - /* The following char* fields point to NULL terminated strings */ - char* id; /* Unique demux identifier */ - char* vendor; /* Name of the demux vendor */ - char* model; /* Name of the demux model */ - __u32 capabilities; /* Bitfield of capability flags */ - dmx_frontend_t* frontend; /* Front-end connected to the demux */ +struct dmx_demux { + u32 capabilities; /* Bitfield of capability flags */ + struct dmx_frontend* frontend; /* Front-end connected to the demux */ struct list_head reg_list; /* List of registered demuxes */ void* priv; /* Pointer to private data of the API client */ int users; /* Number of users */ - int (*open) (struct dmx_demux_s* demux); - int (*close) (struct dmx_demux_s* demux); - int (*write) (struct dmx_demux_s* demux, const char* buf, size_t count); - int (*allocate_ts_feed) (struct dmx_demux_s* demux, - dmx_ts_feed_t** feed, + int (*open) (struct dmx_demux* demux); + int (*close) (struct dmx_demux* demux); + int (*write) (struct dmx_demux* demux, const char* buf, size_t count); + int (*allocate_ts_feed) (struct dmx_demux* demux, + struct dmx_ts_feed** feed, dmx_ts_cb callback); - int (*release_ts_feed) (struct dmx_demux_s* demux, - dmx_ts_feed_t* feed); - int (*allocate_section_feed) (struct dmx_demux_s* demux, - dmx_section_feed_t** feed, + int (*release_ts_feed) (struct dmx_demux* demux, + struct dmx_ts_feed* feed); + int (*allocate_section_feed) (struct dmx_demux* demux, + struct dmx_section_feed** feed, dmx_section_cb callback); - int (*release_section_feed) (struct dmx_demux_s* demux, - dmx_section_feed_t* feed); - int (*descramble_mac_address) (struct dmx_demux_s* demux, - __u8* buffer1, + int (*release_section_feed) (struct dmx_demux* demux, + struct dmx_section_feed* feed); + int (*descramble_mac_address) (struct dmx_demux* demux, + u8* buffer1, size_t buffer1_length, - __u8* buffer2, + u8* buffer2, size_t buffer2_length, - __u16 pid); - int (*descramble_section_payload) (struct dmx_demux_s* demux, - __u8* buffer1, + u16 pid); + int (*descramble_section_payload) (struct dmx_demux* demux, + u8* buffer1, size_t buffer1_length, - __u8* buffer2, size_t buffer2_length, - __u16 pid); - int (*add_frontend) (struct dmx_demux_s* demux, - dmx_frontend_t* frontend); - int (*remove_frontend) (struct dmx_demux_s* demux, - dmx_frontend_t* frontend); - struct list_head* (*get_frontends) (struct dmx_demux_s* demux); - int (*connect_frontend) (struct dmx_demux_s* demux, - dmx_frontend_t* frontend); - int (*disconnect_frontend) (struct dmx_demux_s* demux); + u8* buffer2, size_t buffer2_length, + u16 pid); + int (*add_frontend) (struct dmx_demux* demux, + struct dmx_frontend* frontend); + int (*remove_frontend) (struct dmx_demux* demux, + struct dmx_frontend* frontend); + struct list_head* (*get_frontends) (struct dmx_demux* demux); + int (*connect_frontend) (struct dmx_demux* demux, + struct dmx_frontend* frontend); + int (*disconnect_frontend) (struct dmx_demux* demux); - int (*get_pes_pids) (struct dmx_demux_s* demux, __u16 *pids); + int (*get_pes_pids) (struct dmx_demux* demux, u16 *pids); - int (*get_stc) (struct dmx_demux_s* demux, unsigned int num, - uint64_t *stc, unsigned int *base); + int (*get_stc) (struct dmx_demux* demux, unsigned int num, + u64 *stc, unsigned int *base); }; -typedef struct dmx_demux_s dmx_demux_t; /*--------------------------------------------------------------------------*/ /* Demux directory */ @@ -298,14 +282,14 @@ /* * DMX_DIR_ENTRY(): Casts elements in the list of registered - * demuxes from the generic type struct list_head* to the type dmx_demux_t + * demuxes from the generic type struct list_head* to the type struct dmx_demux *. */ -#define DMX_DIR_ENTRY(list) list_entry(list, dmx_demux_t, reg_list) +#define DMX_DIR_ENTRY(list) list_entry(list, struct dmx_demux, reg_list) -int dmx_register_demux (dmx_demux_t* demux); -int dmx_unregister_demux (dmx_demux_t* demux); +int dmx_register_demux (struct dmx_demux* demux); +int dmx_unregister_demux (struct dmx_demux* demux); struct list_head* dmx_get_demuxes (void); #endif /* #ifndef __DEMUX_H */ diff -Nru a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c --- a/drivers/media/dvb/dvb-core/dmxdev.c Tue Jul 1 18:44:36 2003 +++ b/drivers/media/dvb/dvb-core/dmxdev.c Tue Jul 1 18:44:36 2003 @@ -21,41 +21,38 @@ * */ +#include +#include #include #include +#include #include +#include +#include #include +#include #include "dmxdev.h" +#include "dvb_functions.h" -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) - #include "compat.h" -#endif - -//MODULE_DESCRIPTION(""); -//MODULE_AUTHOR("Ralph Metzler, Marcus Metzler"); -//#ifdef MODULE_LICENSE -//MODULE_LICENSE("GPL"); -//#endif MODULE_PARM(debug,"i"); static int debug = 0; #define dprintk if (debug) printk -inline dmxdev_filter_t * +inline struct dmxdev_filter * dvb_dmxdev_file_to_filter(struct file *file) { - return (dmxdev_filter_t *) file->private_data; + return (struct dmxdev_filter *) file->private_data; } -inline dmxdev_dvr_t * -dvb_dmxdev_file_to_dvr(dmxdev_t *dmxdev, struct file *file) +inline struct dmxdev_dvr * +dvb_dmxdev_file_to_dvr(struct dmxdev *dmxdev, struct file *file) { - return (dmxdev_dvr_t *) file->private_data; + return (struct dmxdev_dvr *) file->private_data; } -static inline void -dvb_dmxdev_buffer_init(dmxdev_buffer_t *buffer) +static inline void dvb_dmxdev_buffer_init(struct dmxdev_buffer *buffer) { buffer->data=0; buffer->size=8192; @@ -65,8 +62,7 @@ init_waitqueue_head(&buffer->queue); } -static inline -int dvb_dmxdev_buffer_write(dmxdev_buffer_t *buf, const u8 *src, int len) +static inline int dvb_dmxdev_buffer_write(struct dmxdev_buffer *buf, const u8 *src, int len) { int split; int free; @@ -100,9 +96,8 @@ return len; } -static ssize_t -dvb_dmxdev_buffer_read(dmxdev_buffer_t *src, int non_blocking, - char *buf, size_t count, loff_t *ppos) +static ssize_t dvb_dmxdev_buffer_read(struct dmxdev_buffer *src, + int non_blocking, char *buf, size_t count, loff_t *ppos) { unsigned long todo=count; int split, avail, error; @@ -161,8 +156,7 @@ return count; } -static dmx_frontend_t * -get_fe(dmx_demux_t *demux, int type) +static struct dmx_frontend * get_fe(struct dmx_demux *demux, int type) { struct list_head *head, *pos; @@ -176,8 +170,7 @@ return 0; } -static inline void -dvb_dmxdev_dvr_state_set(dmxdev_dvr_t *dmxdevdvr, int state) +static inline void dvb_dmxdev_dvr_state_set(struct dmxdev_dvr *dmxdevdvr, int state) { spin_lock_irq(&dmxdevdvr->dev->lock); dmxdevdvr->state=state; @@ -187,8 +180,8 @@ static int dvb_dvr_open(struct inode *inode, struct file *file) { struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; - dmxdev_t *dmxdev=(dmxdev_t *) dvbdev->priv; - dmx_frontend_t *front; + struct dmxdev *dmxdev=(struct dmxdev *) dvbdev->priv; + struct dmx_frontend *front; dprintk ("function : %s\n", __FUNCTION__); @@ -236,7 +229,7 @@ static int dvb_dvr_release(struct inode *inode, struct file *file) { struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; - dmxdev_t *dmxdev=(dmxdev_t *) dvbdev->priv; + struct dmxdev *dmxdev=(struct dmxdev *) dvbdev->priv; if (down_interruptible (&dmxdev->mutex)) return -ERESTARTSYS; @@ -260,11 +253,11 @@ return 0; } -static ssize_t -dvb_dvr_write(struct file *file, const char *buf, size_t count, loff_t *ppos) +static ssize_t dvb_dvr_write(struct file *file, const char *buf, + size_t count, loff_t *ppos) { struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; - dmxdev_t *dmxdev=(dmxdev_t *) dvbdev->priv; + struct dmxdev *dmxdev=(struct dmxdev *) dvbdev->priv; int ret; if (!dmxdev->demux->write) @@ -278,11 +271,11 @@ return ret; } -static ssize_t -dvb_dvr_read(struct file *file, char *buf, size_t count, loff_t *ppos) +static ssize_t dvb_dvr_read(struct file *file, char *buf, size_t count, + loff_t *ppos) { struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; - dmxdev_t *dmxdev=(dmxdev_t *) dvbdev->priv; + struct dmxdev *dmxdev=(struct dmxdev *) dvbdev->priv; int ret; //down(&dmxdev->mutex); @@ -293,18 +286,16 @@ return ret; } -static inline void -dvb_dmxdev_filter_state_set(dmxdev_filter_t *dmxdevfilter, int state) +static inline void dvb_dmxdev_filter_state_set(struct dmxdev_filter *dmxdevfilter, int state) { spin_lock_irq(&dmxdevfilter->dev->lock); dmxdevfilter->state=state; spin_unlock_irq(&dmxdevfilter->dev->lock); } -static int -dvb_dmxdev_set_buffer_size(dmxdev_filter_t *dmxdevfilter, unsigned long size) +static int dvb_dmxdev_set_buffer_size(struct dmxdev_filter *dmxdevfilter, unsigned long size) { - dmxdev_buffer_t *buf=&dmxdevfilter->buffer; + struct dmxdev_buffer *buf=&dmxdevfilter->buffer; void *mem; if (buf->size==size) @@ -331,10 +322,9 @@ return 0; } -static void -dvb_dmxdev_filter_timeout(unsigned long data) +static void dvb_dmxdev_filter_timeout(unsigned long data) { - dmxdev_filter_t *dmxdevfilter=(dmxdev_filter_t *)data; + struct dmxdev_filter *dmxdevfilter=(struct dmxdev_filter *)data; dmxdevfilter->buffer.error=-ETIMEDOUT; spin_lock_irq(&dmxdevfilter->dev->lock); @@ -343,8 +333,7 @@ wake_up(&dmxdevfilter->buffer.queue); } -static void -dvb_dmxdev_filter_timer(dmxdev_filter_t *dmxdevfilter) +static void dvb_dmxdev_filter_timer(struct dmxdev_filter *dmxdevfilter) { struct dmx_sct_filter_params *para=&dmxdevfilter->params.sec; @@ -357,12 +346,11 @@ } } -static int -dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, +static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len, const u8 *buffer2, size_t buffer2_len, - dmx_section_filter_t *filter, dmx_success_t success) + struct dmx_section_filter *filter, enum dmx_success success) { - dmxdev_filter_t *dmxdevfilter=(dmxdev_filter_t *) filter->priv; + struct dmxdev_filter *dmxdevfilter=(struct dmxdev_filter *) filter->priv; int ret; if (dmxdevfilter->buffer.error) { @@ -394,13 +382,12 @@ return 0; } -static int -dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, +static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len, const u8 *buffer2, size_t buffer2_len, - dmx_ts_feed_t *feed, dmx_success_t success) + struct dmx_ts_feed *feed, enum dmx_success success) { - dmxdev_filter_t *dmxdevfilter=(dmxdev_filter_t *) feed->priv; - dmxdev_buffer_t *buffer; + struct dmxdev_filter *dmxdevfilter=(struct dmxdev_filter *) feed->priv; + struct dmxdev_buffer *buffer; int ret; spin_lock(&dmxdevfilter->dev->lock); @@ -433,8 +420,7 @@ /* stop feed but only mark the specified filter as stopped (state set) */ -static int -dvb_dmxdev_feed_stop(dmxdev_filter_t *dmxdevfilter) +static int dvb_dmxdev_feed_stop(struct dmxdev_filter *dmxdevfilter) { dvb_dmxdev_filter_state_set(dmxdevfilter, DMXDEV_STATE_SET); @@ -455,8 +441,7 @@ /* start feed associated with the specified filter */ -static -int dvb_dmxdev_feed_start(dmxdev_filter_t *filter) +static int dvb_dmxdev_feed_start(struct dmxdev_filter *filter) { dvb_dmxdev_filter_state_set (filter, DMXDEV_STATE_GO); @@ -478,12 +463,11 @@ /* restart section feed if it has filters left associated with it, otherwise release the feed */ -static -int dvb_dmxdev_feed_restart(dmxdev_filter_t *filter) +static int dvb_dmxdev_feed_restart(struct dmxdev_filter *filter) { int i; - dmxdev_t *dmxdev = filter->dev; - uint16_t pid = filter->params.sec.pid; + struct dmxdev *dmxdev = filter->dev; + u16 pid = filter->params.sec.pid; for (i=0; ifilternum; i++) if (dmxdev->filter[i].state>=DMXDEV_STATE_GO && @@ -498,8 +482,7 @@ return 0; } -static int -dvb_dmxdev_filter_stop(dmxdev_filter_t *dmxdevfilter) +static int dvb_dmxdev_filter_stop(struct dmxdev_filter *dmxdevfilter) { if (dmxdevfilter->statestatedev; + struct dmxdev *dmxdev = filter->dev; void *mem; int ret, i; @@ -574,8 +555,8 @@ case DMXDEV_TYPE_SEC: { struct dmx_sct_filter_params *para=&filter->params.sec; - dmx_section_filter_t **secfilter=&filter->filter.sec; - dmx_section_feed_t **secfeed=&filter->feed.sec; + struct dmx_section_filter **secfilter=&filter->filter.sec; + struct dmx_section_feed **secfeed=&filter->feed.sec; *secfilter=0; *secfeed=0; @@ -656,13 +637,13 @@ dmx_output_t otype; int ret; int ts_type; - dmx_ts_pes_t ts_pes; - dmx_ts_feed_t **tsfeed = &filter->feed.ts; + enum dmx_ts_pes ts_pes; + struct dmx_ts_feed **tsfeed = &filter->feed.ts; filter->feed.ts = 0; otype=para->output; - ts_pes=(dmx_ts_pes_t) para->pes_type; + ts_pes=(enum dmx_ts_pes) para->pes_type; if (ts_pesprivate_data; - dmxdev_t *dmxdev=(dmxdev_t *) dvbdev->priv; + struct dmxdev *dmxdev=(struct dmxdev *) dvbdev->priv; int i; - dmxdev_filter_t *dmxdevfilter; + struct dmxdev_filter *dmxdevfilter; if (!dmxdev->filter) return -EINVAL; @@ -744,8 +725,7 @@ } -static -int dvb_dmxdev_filter_free(dmxdev_t *dmxdev, dmxdev_filter_t *dmxdevfilter) +static int dvb_dmxdev_filter_free(struct dmxdev *dmxdev, struct dmxdev_filter *dmxdevfilter) { if (down_interruptible(&dmxdev->mutex)) return -ERESTARTSYS; @@ -774,8 +754,7 @@ return 0; } -static inline void -invert_mode(dmx_filter_t *filter) +static inline void invert_mode(dmx_filter_t *filter) { int i; @@ -784,9 +763,8 @@ } -static int -dvb_dmxdev_filter_set(dmxdev_t *dmxdev, - dmxdev_filter_t *dmxdevfilter, +static int dvb_dmxdev_filter_set(struct dmxdev *dmxdev, + struct dmxdev_filter *dmxdevfilter, struct dmx_sct_filter_params *params) { dprintk ("function : %s\n", __FUNCTION__); @@ -806,9 +784,8 @@ return 0; } -static int -dvb_dmxdev_pes_filter_set(dmxdev_t *dmxdev, - dmxdev_filter_t *dmxdevfilter, +static int dvb_dmxdev_pes_filter_set(struct dmxdev *dmxdev, + struct dmxdev_filter *dmxdevfilter, struct dmx_pes_filter_params *params) { dvb_dmxdev_filter_stop(dmxdevfilter); @@ -828,9 +805,8 @@ return 0; } -static ssize_t -dvb_dmxdev_read_sec(dmxdev_filter_t *dfil, struct file *file, - char *buf, size_t count, loff_t *ppos) +static ssize_t dvb_dmxdev_read_sec(struct dmxdev_filter *dfil, + struct file *file, char *buf, size_t count, loff_t *ppos) { int result, hcount; int done=0; @@ -871,7 +847,7 @@ ssize_t dvb_demux_read(struct file *file, char *buf, size_t count, loff_t *ppos) { - dmxdev_filter_t *dmxdevfilter=dvb_dmxdev_file_to_filter(file); + struct dmxdev_filter *dmxdevfilter=dvb_dmxdev_file_to_filter(file); int ret=0; if (down_interruptible(&dmxdevfilter->mutex)) @@ -892,8 +868,8 @@ static int dvb_demux_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *parg) { - dmxdev_filter_t *dmxdevfilter=dvb_dmxdev_file_to_filter(file); - dmxdev_t *dmxdev=dmxdevfilter->dev; + struct dmxdev_filter *dmxdevfilter=dvb_dmxdev_file_to_filter(file); + struct dmxdev *dmxdev=dmxdevfilter->dev; unsigned long arg=(unsigned long) parg; int ret=0; @@ -959,7 +935,7 @@ ret=-EINVAL; break; } - dmxdev->demux->get_pes_pids(dmxdev->demux, (uint16_t *)parg); + dmxdev->demux->get_pes_pids(dmxdev->demux, (u16 *)parg); break; case DMX_GET_STC: @@ -987,10 +963,9 @@ } -static -unsigned int dvb_demux_poll (struct file *file, poll_table *wait) +static unsigned int dvb_demux_poll (struct file *file, poll_table *wait) { - dmxdev_filter_t *dmxdevfilter = dvb_dmxdev_file_to_filter(file); + struct dmxdev_filter *dmxdevfilter = dvb_dmxdev_file_to_filter(file); unsigned int mask = 0; if (!dmxdevfilter) @@ -999,7 +974,8 @@ poll_wait(file, &dmxdevfilter->buffer.queue, wait); if (dmxdevfilter->state != DMXDEV_STATE_GO && - dmxdevfilter->state != DMXDEV_STATE_DONE) + dmxdevfilter->state != DMXDEV_STATE_DONE && + dmxdevfilter->state != DMXDEV_STATE_TIMEDOUT) return 0; if (dmxdevfilter->buffer.error) @@ -1012,11 +988,10 @@ } -static -int dvb_demux_release(struct inode *inode, struct file *file) +static int dvb_demux_release(struct inode *inode, struct file *file) { - dmxdev_filter_t *dmxdevfilter = dvb_dmxdev_file_to_filter(file); - dmxdev_t *dmxdev = dmxdevfilter->dev; + struct dmxdev_filter *dmxdevfilter = dvb_dmxdev_file_to_filter(file); + struct dmxdev *dmxdev = dmxdevfilter->dev; return dvb_dmxdev_filter_free(dmxdev, dmxdevfilter); } @@ -1041,7 +1016,7 @@ unsigned int cmd, void *parg) { struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; - dmxdev_t *dmxdev=(dmxdev_t *) dvbdev->priv; + struct dmxdev *dmxdev=(struct dmxdev *) dvbdev->priv; int ret=0; @@ -1068,11 +1043,10 @@ } -static -unsigned int dvb_dvr_poll (struct file *file, poll_table *wait) +static unsigned int dvb_dvr_poll (struct file *file, poll_table *wait) { struct dvb_device *dvbdev = (struct dvb_device *) file->private_data; - dmxdev_t *dmxdev = (dmxdev_t *) dvbdev->priv; + struct dmxdev *dmxdev = (struct dmxdev *) dvbdev->priv; unsigned int mask = 0; dprintk ("function : %s\n", __FUNCTION__); @@ -1092,8 +1066,7 @@ } -static -struct file_operations dvb_dvr_fops = { +static struct file_operations dvb_dvr_fops = { .owner = THIS_MODULE, .read = dvb_dvr_read, .write = dvb_dvr_write, @@ -1111,23 +1084,24 @@ }; int -dvb_dmxdev_init(dmxdev_t *dmxdev, struct dvb_adapter *dvb_adapter) +dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter) { int i; if (dmxdev->demux->open(dmxdev->demux)<0) return -EUSERS; - dmxdev->filter=vmalloc(dmxdev->filternum*sizeof(dmxdev_filter_t)); + dmxdev->filter = vmalloc(dmxdev->filternum*sizeof(struct dmxdev_filter)); if (!dmxdev->filter) return -ENOMEM; - dmxdev->dvr=vmalloc(dmxdev->filternum*sizeof(dmxdev_dvr_t)); + dmxdev->dvr = vmalloc(dmxdev->filternum*sizeof(struct dmxdev_dvr)); if (!dmxdev->dvr) { vfree(dmxdev->filter); - dmxdev->filter=0; + dmxdev->filter = NULL; return -ENOMEM; } + sema_init(&dmxdev->mutex, 1); spin_lock_init(&dmxdev->lock); for (i=0; ifilternum; i++) { @@ -1143,13 +1117,12 @@ dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr, dmxdev, DVB_DEVICE_DVR); dvb_dmxdev_buffer_init(&dmxdev->dvr_buffer); - /* fixme: is this correct? */ - try_module_get(THIS_MODULE); + return 0; } void -dvb_dmxdev_release(dmxdev_t *dmxdev) +dvb_dmxdev_release(struct dmxdev *dmxdev) { dvb_unregister_device(dmxdev->dvbdev); dvb_unregister_device(dmxdev->dvr_dvbdev); @@ -1162,8 +1135,6 @@ dmxdev->dvr=0; } dmxdev->demux->close(dmxdev->demux); - /* fixme: is this correct? */ - module_put(THIS_MODULE); } diff -Nru a/drivers/media/dvb/dvb-core/dmxdev.h b/drivers/media/dvb/dvb-core/dmxdev.h --- a/drivers/media/dvb/dvb-core/dmxdev.h Tue Jul 1 18:44:39 2003 +++ b/drivers/media/dvb/dvb-core/dmxdev.h Tue Jul 1 18:44:39 2003 @@ -24,55 +24,54 @@ #ifndef _DMXDEV_H_ #define _DMXDEV_H_ -#ifndef __KERNEL__ -#define __KERNEL__ -#endif - -#include - -#include -#include #include +#include +#include +#include +#include #include +#include +#include + +#include #include "dvbdev.h" #include "demux.h" -typedef enum { +enum dmxdevype { DMXDEV_TYPE_NONE, DMXDEV_TYPE_SEC, DMXDEV_TYPE_PES, -} dmxdev_type_t; +}; -typedef enum { +enum dmxdev_state { DMXDEV_STATE_FREE, DMXDEV_STATE_ALLOCATED, DMXDEV_STATE_SET, DMXDEV_STATE_GO, DMXDEV_STATE_DONE, DMXDEV_STATE_TIMEDOUT -} dmxdev_state_t; +}; -typedef struct dmxdev_buffer_s { - uint8_t *data; - uint32_t size; - int32_t pread; - int32_t pwrite; +struct dmxdev_buffer { + u8 *data; + int size; + int pread; + int pwrite; wait_queue_head_t queue; int error; -} dmxdev_buffer_t; - +}; -typedef struct dmxdev_filter_s { +struct dmxdev_filter { struct dvb_device *dvbdev; union { - dmx_section_filter_t *sec; + struct dmx_section_filter *sec; } filter; union { - dmx_ts_feed_t *ts; - dmx_section_feed_t *sec; + struct dmx_ts_feed *ts; + struct dmx_section_feed *sec; } feed; union { @@ -81,50 +80,50 @@ } params; int type; - dmxdev_state_t state; - struct dmxdev_s *dev; - dmxdev_buffer_t buffer; + enum dmxdev_state state; + struct dmxdev *dev; + struct dmxdev_buffer buffer; struct semaphore mutex; - // only for sections + /* only for sections */ struct timer_list timer; int todo; - uint8_t secheader[3]; + u8 secheader[3]; u16 pid; -} dmxdev_filter_t; +}; -typedef struct dmxdev_dvr_s { +struct dmxdev_dvr { int state; - struct dmxdev_s *dev; - dmxdev_buffer_t buffer; -} dmxdev_dvr_t; + struct dmxdev *dev; + struct dmxdev_buffer buffer; +}; -typedef struct dmxdev_s { +struct dmxdev { struct dvb_device *dvbdev; struct dvb_device *dvr_dvbdev; - dmxdev_filter_t *filter; - dmxdev_dvr_t *dvr; - dmx_demux_t *demux; + struct dmxdev_filter *filter; + struct dmxdev_dvr *dvr; + struct dmx_demux *demux; int filternum; int capabilities; #define DMXDEV_CAP_DUPLEX 1 - dmx_frontend_t *dvr_orig_fe; + struct dmx_frontend *dvr_orig_fe; - dmxdev_buffer_t dvr_buffer; + struct dmxdev_buffer dvr_buffer; #define DVR_BUFFER_SIZE (10*188*1024) struct semaphore mutex; spinlock_t lock; -} dmxdev_t; +}; -int dvb_dmxdev_init(dmxdev_t *dmxdev, struct dvb_adapter *); -void dvb_dmxdev_release(dmxdev_t *dmxdev); +int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *); +void dvb_dmxdev_release(struct dmxdev *dmxdev); #endif /* _DMXDEV_H_ */ diff -Nru a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c --- a/drivers/media/dvb/dvb-core/dvb_demux.c Tue Jul 1 18:44:32 2003 +++ b/drivers/media/dvb/dvb-core/dvb_demux.c Tue Jul 1 18:44:32 2003 @@ -21,46 +21,31 @@ * */ +#include +#include #include #include #include -#include -#include - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) - #include "compat.h" -#else +#include #include -#endif +#include #include "dvb_demux.h" +#include "dvb_functions.h" #define NOBUFS LIST_HEAD(dmx_muxs); -int dmx_register_demux(dmx_demux_t *demux) +int dmx_register_demux(struct dmx_demux *demux) { - struct list_head *pos; - - if (!(demux->id && demux->vendor && demux->model)) - return -EINVAL; - - list_for_each(pos, &dmx_muxs) { - if (!strcmp(DMX_DIR_ENTRY(pos)->id, demux->id)) - return -EEXIST; - } - demux->users = 0; list_add(&demux->reg_list, &dmx_muxs); - /* fixme: is this correct? */ - try_module_get(THIS_MODULE); - return 0; } -int dmx_unregister_demux(dmx_demux_t* demux) +int dmx_unregister_demux(struct dmx_demux* demux) { struct list_head *pos, *n, *head=&dmx_muxs; @@ -69,8 +54,6 @@ if (demux->users>0) return -EINVAL; list_del(pos); - /* fixme: is this correct? */ - module_put(THIS_MODULE); return 0; } } @@ -92,22 +75,19 @@ ******************************************************************************/ -static inline -u16 section_length(const u8 *buf) +static inline u16 section_length(const u8 *buf) { return 3+((buf[1]&0x0f)<<8)+buf[2]; } -static inline -u16 ts_pid(const u8 *buf) +static inline u16 ts_pid(const u8 *buf) { return ((buf[1]&0x1f)<<8)+buf[2]; } -static inline -int payload(const u8 *tsp) +static inline int payload(const u8 *tsp) { if (!(tsp[3]&0x10)) // no payload? return 0; @@ -134,15 +114,13 @@ } -static -u32 dvb_dmx_crc32 (struct dvb_demux_feed *f, const u8 *src, size_t len) +static u32 dvb_dmx_crc32 (struct dvb_demux_feed *f, const u8 *src, size_t len) { return (f->feed.sec.crc_val = crc32_le (f->feed.sec.crc_val, src, len)); } -static -void dvb_dmx_memcopy (struct dvb_demux_feed *f, u8 *d, const u8 *s, size_t len) +static void dvb_dmx_memcopy (struct dvb_demux_feed *f, u8 *d, const u8 *s, size_t len) { memcpy (d, s, len); } @@ -152,8 +130,7 @@ * Software filter functions ******************************************************************************/ -static inline -int dvb_dmx_swfilter_payload (struct dvb_demux_feed *feed, const u8 *buf) +static inline int dvb_dmx_swfilter_payload (struct dvb_demux_feed *feed, const u8 *buf) { int count = payload(buf); int p; @@ -182,8 +159,7 @@ } -static -int dvb_dmx_swfilter_sectionfilter (struct dvb_demux_feed *feed, +static int dvb_dmx_swfilter_sectionfilter (struct dvb_demux_feed *feed, struct dvb_demux_filter *f) { u8 neq = 0; @@ -206,12 +182,11 @@ } -static inline -int dvb_dmx_swfilter_section_feed (struct dvb_demux_feed *feed) +static inline int dvb_dmx_swfilter_section_feed (struct dvb_demux_feed *feed) { struct dvb_demux *demux = feed->demux; struct dvb_demux_filter *f = feed->filter; - dmx_section_feed_t *sec = &feed->feed.sec; + struct dmx_section_feed *sec = &feed->feed.sec; u8 *buf = sec->secbuf; if (sec->secbufp != sec->seclen) @@ -239,11 +214,10 @@ } -static -int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, const u8 *buf) +static int dvb_dmx_swfilter_section_packet(struct dvb_demux_feed *feed, const u8 *buf) { struct dvb_demux *demux = feed->demux; - dmx_section_feed_t *sec = &feed->feed.sec; + struct dmx_section_feed *sec = &feed->feed.sec; int p, count; int ccok, rest; u8 cc; @@ -366,8 +340,7 @@ } -static inline -void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed, const u8 *buf) +static inline void dvb_dmx_swfilter_packet_type(struct dvb_demux_feed *feed, const u8 *buf) { switch(feed->type) { case DMX_TYPE_TS: @@ -459,8 +432,7 @@ } -static -struct dvb_demux_filter* dvb_dmx_filter_alloc(struct dvb_demux *demux) +static struct dvb_demux_filter * dvb_dmx_filter_alloc(struct dvb_demux *demux) { int i; @@ -476,8 +448,7 @@ return &demux->filter[i]; } -static -struct dvb_demux_feed* dvb_dmx_feed_alloc(struct dvb_demux *demux) +static struct dvb_demux_feed * dvb_dmx_feed_alloc(struct dvb_demux *demux) { int i; @@ -494,8 +465,7 @@ } -static -int dmx_pid_set (u16 pid, struct dvb_demux_feed *feed) +static int dmx_pid_set (u16 pid, struct dvb_demux_feed *feed) { struct dvb_demux *demux = feed->demux; struct list_head *pos, *n, *head=&demux->feed_list; @@ -506,12 +476,14 @@ if (pid == feed->pid) return 0; - if (feed->pid <= DMX_MAX_PID) - list_for_each_safe(pos, n, head) + if (feed->pid <= DMX_MAX_PID) { + list_for_each_safe(pos, n, head) { if (DMX_FEED_ENTRY(pos)->pid == feed->pid) { list_del(pos); break; } + } + } list_add(&feed->list_head, head); feed->pid = pid; @@ -520,9 +492,8 @@ } -static -int dmx_ts_feed_set (struct dmx_ts_feed_s* ts_feed, u16 pid, int ts_type, - dmx_ts_pes_t pes_type, size_t callback_length, +static int dmx_ts_feed_set (struct dmx_ts_feed* ts_feed, u16 pid, int ts_type, + enum dmx_ts_pes pes_type, size_t callback_length, size_t circular_buffer_size, int descramble, struct timespec timeout) { @@ -596,8 +567,7 @@ } -static -int dmx_ts_feed_start_filtering(struct dmx_ts_feed_s* ts_feed) +static int dmx_ts_feed_start_filtering(struct dmx_ts_feed* ts_feed) { struct dvb_demux_feed *feed = (struct dvb_demux_feed *) ts_feed; struct dvb_demux *demux = feed->demux; @@ -630,8 +600,7 @@ return 0; } -static -int dmx_ts_feed_stop_filtering(struct dmx_ts_feed_s* ts_feed) +static int dmx_ts_feed_stop_filtering(struct dmx_ts_feed* ts_feed) { struct dvb_demux_feed *feed = (struct dvb_demux_feed *) ts_feed; struct dvb_demux *demux = feed->demux; @@ -661,8 +630,7 @@ return ret; } -static -int dvbdmx_allocate_ts_feed (dmx_demux_t *dmx, dmx_ts_feed_t **ts_feed, +static int dvbdmx_allocate_ts_feed (struct dmx_demux *dmx, struct dmx_ts_feed **ts_feed, dmx_ts_cb callback) { struct dvb_demux *demux = (struct dvb_demux *) dmx; @@ -684,12 +652,12 @@ feed->buffer = 0; (*ts_feed) = &feed->feed.ts; - (*ts_feed)->is_filtering = 0; (*ts_feed)->parent = dmx; (*ts_feed)->priv = 0; - (*ts_feed)->set = dmx_ts_feed_set; + (*ts_feed)->is_filtering = 0; (*ts_feed)->start_filtering = dmx_ts_feed_start_filtering; (*ts_feed)->stop_filtering = dmx_ts_feed_stop_filtering; + (*ts_feed)->set = dmx_ts_feed_set; if (!(feed->filter = dvb_dmx_filter_alloc(demux))) { @@ -707,8 +675,7 @@ return 0; } -static -int dvbdmx_release_ts_feed(dmx_demux_t *dmx, dmx_ts_feed_t *ts_feed) +static int dvbdmx_release_ts_feed(struct dmx_demux *dmx, struct dmx_ts_feed *ts_feed) { struct dvb_demux *demux = (struct dvb_demux *) dmx; struct dvb_demux_feed *feed = (struct dvb_demux_feed *) ts_feed; @@ -753,9 +720,8 @@ * dmx_section_feed API calls ******************************************************************************/ -static int -dmx_section_feed_allocate_filter(struct dmx_section_feed_s* feed, - dmx_section_filter_t** filter) +static int dmx_section_feed_allocate_filter(struct dmx_section_feed* feed, + struct dmx_section_filter** filter) { struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed; struct dvb_demux *dvbdemux=dvbdmxfeed->demux; @@ -767,8 +733,9 @@ dvbdmxfilter=dvb_dmx_filter_alloc(dvbdemux); if (!dvbdmxfilter) { up(&dvbdemux->mutex); - return -ENOSPC; + return -EBUSY; } + spin_lock_irq(&dvbdemux->lock); *filter=&dvbdmxfilter->filter; (*filter)->parent=feed; @@ -784,8 +751,8 @@ return 0; } -static int -dmx_section_feed_set(struct dmx_section_feed_s* feed, + +static int dmx_section_feed_set(struct dmx_section_feed* feed, u16 pid, size_t circular_buffer_size, int descramble, int check_crc) { @@ -799,16 +766,18 @@ if (down_interruptible (&dvbdmx->mutex)) return -ERESTARTSYS; - if (dvbdmxfeed->pid <= DMX_MAX_PID) - list_for_each_safe(pos, n, head) + if (dvbdmxfeed->pid <= DMX_MAX_PID) { + list_for_each_safe(pos, n, head) { if (DMX_FEED_ENTRY(pos)->pid == dvbdmxfeed->pid) { list_del(pos); break; } + } + } list_add(&dvbdmxfeed->list_head, head); - dvbdmxfeed->pid=pid; + dvbdmxfeed->pid = pid; dvbdmxfeed->buffer_size=circular_buffer_size; dvbdmxfeed->descramble=descramble; if (dvbdmxfeed->descramble) { @@ -834,8 +803,8 @@ static void prepare_secfilters(struct dvb_demux_feed *dvbdmxfeed) { int i; - dmx_section_filter_t *sf; struct dvb_demux_filter *f; + struct dmx_section_filter *sf; u8 mask, mode, doneq; if (!(f=dvbdmxfeed->filter)) @@ -854,8 +823,7 @@ } -static int -dmx_section_feed_start_filtering(dmx_section_feed_t *feed) +static int dmx_section_feed_start_filtering(struct dmx_section_feed *feed) { struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed; struct dvb_demux *dvbdmx=dvbdmxfeed->demux; @@ -895,8 +863,8 @@ return 0; } -static int -dmx_section_feed_stop_filtering(struct dmx_section_feed_s* feed) + +static int dmx_section_feed_stop_filtering(struct dmx_section_feed* feed) { struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed; struct dvb_demux *dvbdmx=dvbdmxfeed->demux; @@ -918,9 +886,9 @@ return ret; } -static int -dmx_section_feed_release_filter(dmx_section_feed_t *feed, - dmx_section_filter_t* filter) + +static int dmx_section_feed_release_filter(struct dmx_section_feed *feed, + struct dmx_section_filter* filter) { struct dvb_demux_filter *dvbdmxfilter=(struct dvb_demux_filter *) filter, *f; struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed; @@ -938,9 +906,10 @@ spin_lock_irq(&dvbdmx->lock); f=dvbdmxfeed->filter; - if (f==dvbdmxfilter) + + if (f == dvbdmxfilter) { dvbdmxfeed->filter=dvbdmxfilter->next; - else { + } else { while(f->next!=dvbdmxfilter) f=f->next; f->next=f->next->next; @@ -951,8 +920,8 @@ return 0; } -static int dvbdmx_allocate_section_feed(dmx_demux_t *demux, - dmx_section_feed_t **feed, +static int dvbdmx_allocate_section_feed(struct dmx_demux *demux, + struct dmx_section_feed **feed, dmx_section_cb callback) { struct dvb_demux *dvbdmx=(struct dvb_demux *) demux; @@ -977,18 +946,19 @@ (*feed)->is_filtering=0; (*feed)->parent=demux; (*feed)->priv=0; + (*feed)->set=dmx_section_feed_set; (*feed)->allocate_filter=dmx_section_feed_allocate_filter; - (*feed)->release_filter=dmx_section_feed_release_filter; (*feed)->start_filtering=dmx_section_feed_start_filtering; (*feed)->stop_filtering=dmx_section_feed_stop_filtering; + (*feed)->release_filter = dmx_section_feed_release_filter; up(&dvbdmx->mutex); return 0; } -static int dvbdmx_release_section_feed(dmx_demux_t *demux, - dmx_section_feed_t *feed) +static int dvbdmx_release_section_feed(struct dmx_demux *demux, + struct dmx_section_feed *feed) { struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) feed; struct dvb_demux *dvbdmx=(struct dvb_demux *) demux; @@ -1010,11 +980,12 @@ dvbdmxfeed->state=DMX_STATE_FREE; if (dvbdmxfeed->pid <= DMX_MAX_PID) { - list_for_each_safe(pos, n, head) + list_for_each_safe(pos, n, head) { if (DMX_FEED_ENTRY(pos)->pid == dvbdmxfeed->pid) { list_del(pos); break; } + } dvbdmxfeed->pid = 0xffff; } @@ -1027,7 +998,7 @@ * dvb_demux kernel data API calls ******************************************************************************/ -static int dvbdmx_open(dmx_demux_t *demux) +static int dvbdmx_open(struct dmx_demux *demux) { struct dvb_demux *dvbdemux=(struct dvb_demux *) demux; @@ -1037,7 +1008,8 @@ return 0; } -static int dvbdmx_close(struct dmx_demux_s *demux) + +static int dvbdmx_close(struct dmx_demux *demux) { struct dvb_demux *dvbdemux=(struct dvb_demux *) demux; @@ -1048,12 +1020,12 @@ return 0; } -static int dvbdmx_write(dmx_demux_t *demux, const char *buf, size_t count) + +static int dvbdmx_write(struct dmx_demux *demux, const char *buf, size_t count) { struct dvb_demux *dvbdemux=(struct dvb_demux *) demux; - if ((!demux->frontend) || - (demux->frontend->source!=DMX_MEMORY_FE)) + if ((!demux->frontend) || (demux->frontend->source != DMX_MEMORY_FE)) return -EINVAL; if (down_interruptible (&dvbdemux->mutex)) @@ -1065,35 +1037,24 @@ } -static int dvbdmx_add_frontend(dmx_demux_t *demux, - dmx_frontend_t *frontend) +static int dvbdmx_add_frontend(struct dmx_demux *demux, struct dmx_frontend *frontend) { struct dvb_demux *dvbdemux=(struct dvb_demux *) demux; - struct list_head *pos, *head=&dvbdemux->frontend_list; - - if (!(frontend->id && frontend->vendor && frontend->model)) - return -EINVAL; - list_for_each(pos, head) - { - if (!strcmp(DMX_FE_ENTRY(pos)->id, frontend->id)) - return -EEXIST; - } + struct list_head *head = &dvbdemux->frontend_list; list_add(&(frontend->connectivity_list), head); + return 0; } -static int -dvbdmx_remove_frontend(dmx_demux_t *demux, - dmx_frontend_t *frontend) + +static int dvbdmx_remove_frontend(struct dmx_demux *demux, struct dmx_frontend *frontend) { struct dvb_demux *dvbdemux=(struct dvb_demux *) demux; struct list_head *pos, *n, *head=&dvbdemux->frontend_list; - list_for_each_safe (pos, n, head) - { - if (DMX_FE_ENTRY(pos)==frontend) - { + list_for_each_safe (pos, n, head) { + if (DMX_FE_ENTRY(pos) == frontend) { list_del(pos); return 0; } @@ -1101,8 +1062,8 @@ return -ENODEV; } -static struct list_head * -dvbdmx_get_frontends(dmx_demux_t *demux) + +static struct list_head * dvbdmx_get_frontends(struct dmx_demux *demux) { struct dvb_demux *dvbdemux=(struct dvb_demux *) demux; @@ -1111,8 +1072,8 @@ return &dvbdemux->frontend_list; } -static int dvbdmx_connect_frontend(dmx_demux_t *demux, - dmx_frontend_t *frontend) + +int dvbdmx_connect_frontend(struct dmx_demux *demux, struct dmx_frontend *frontend) { struct dvb_demux *dvbdemux=(struct dvb_demux *) demux; @@ -1127,7 +1088,8 @@ return 0; } -static int dvbdmx_disconnect_frontend(dmx_demux_t *demux) + +int dvbdmx_disconnect_frontend(struct dmx_demux *demux) { struct dvb_demux *dvbdemux=(struct dvb_demux *) demux; @@ -1139,7 +1101,8 @@ return 0; } -static int dvbdmx_get_pes_pids(dmx_demux_t *demux, u16 *pids) + +static int dvbdmx_get_pes_pids(struct dmx_demux *demux, u16 *pids) { struct dvb_demux *dvbdemux=(struct dvb_demux *) demux; @@ -1150,8 +1113,8 @@ int dvb_dmx_init(struct dvb_demux *dvbdemux) { - int i; - dmx_demux_t *dmx=&dvbdemux->dmx; + int i, err; + struct dmx_demux *dmx = &dvbdemux->dmx; dvbdemux->users=0; dvbdemux->filter=vmalloc(dvbdemux->filternum*sizeof(struct dvb_demux_filter)); @@ -1176,8 +1139,11 @@ dvbdemux->pesfilter[i]=NULL; dvbdemux->pids[i]=0xffff; } - dvbdemux->playing=dvbdemux->recording=0; + INIT_LIST_HEAD(&dvbdemux->feed_list); + + dvbdemux->playing = 0; + dvbdemux->recording = 0; dvbdemux->tsbufp=0; if (!dvbdemux->check_crc32) @@ -1187,9 +1153,8 @@ dvbdemux->memcopy = dvb_dmx_memcopy; dmx->frontend=0; - dmx->reg_list.next=dmx->reg_list.prev=&dmx->reg_list; + dmx->reg_list.prev = dmx->reg_list.next = &dmx->reg_list; dmx->priv=(void *) dvbdemux; - //dmx->users=0; // reset in dmx_register_demux() dmx->open=dvbdmx_open; dmx->close=dvbdmx_close; dmx->write=dvbdmx_write; @@ -1210,8 +1175,8 @@ sema_init(&dvbdemux->mutex, 1); spin_lock_init(&dvbdemux->lock); - if (dmx_register_demux(dmx)<0) - return -1; + if ((err = dmx_register_demux(dmx)) < 0) + return err; return 0; } @@ -1219,7 +1184,7 @@ int dvb_dmx_release(struct dvb_demux *dvbdemux) { - dmx_demux_t *dmx=&dvbdemux->dmx; + struct dmx_demux *dmx = &dvbdemux->dmx; dmx_unregister_demux(dmx); if (dvbdemux->filter) @@ -1228,10 +1193,3 @@ vfree(dvbdemux->feed); return 0; } - -#if 0 -MODULE_DESCRIPTION("Software MPEG Demultiplexer"); -MODULE_AUTHOR("Ralph Metzler, Markus Metzler"); -MODULE_LICENSE("GPL"); -#endif - diff -Nru a/drivers/media/dvb/dvb-core/dvb_demux.h b/drivers/media/dvb/dvb-core/dvb_demux.h --- a/drivers/media/dvb/dvb-core/dvb_demux.h Tue Jul 1 18:44:34 2003 +++ b/drivers/media/dvb/dvb-core/dvb_demux.h Tue Jul 1 18:44:34 2003 @@ -25,8 +25,10 @@ #ifndef _DVB_DEMUX_H_ #define _DVB_DEMUX_H_ -#include +#include #include +#include +#include #include "demux.h" @@ -43,7 +45,7 @@ #define DVB_DEMUX_MASK_MAX 18 struct dvb_demux_filter { - dmx_section_filter_t filter; + struct dmx_section_filter filter; u8 maskandmode [DMX_MAX_FILTER_SIZE]; u8 maskandnotmode [DMX_MAX_FILTER_SIZE]; int doneq; @@ -66,8 +68,8 @@ struct dvb_demux_feed { union { - dmx_ts_feed_t ts; - dmx_section_feed_t sec; + struct dmx_ts_feed ts; + struct dmx_section_feed sec; } feed; union { @@ -89,7 +91,7 @@ int cb_length; int ts_type; - dmx_ts_pes_t pes_type; + enum dmx_ts_pes pes_type; int cc; @@ -99,7 +101,7 @@ }; struct dvb_demux { - dmx_demux_t dmx; + struct dmx_demux dmx; void *priv; int filternum; int feednum; @@ -140,4 +142,8 @@ void dvb_dmx_swfilter_packets(struct dvb_demux *dvbdmx, const u8 *buf, size_t count); void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count); +int dvbdmx_connect_frontend(struct dmx_demux *demux, struct dmx_frontend *frontend); +int dvbdmx_disconnect_frontend(struct dmx_demux *demux); + #endif /* _DVB_DEMUX_H_ */ + diff -Nru a/drivers/media/dvb/dvb-core/dvb_filter.c b/drivers/media/dvb/dvb-core/dvb_filter.c --- a/drivers/media/dvb/dvb-core/dvb_filter.c Tue Jul 1 18:44:39 2003 +++ b/drivers/media/dvb/dvb-core/dvb_filter.c Tue Jul 1 18:44:39 2003 @@ -1,4 +1,6 @@ +#include #include +#include #include "dvb_filter.h" unsigned int bitrates[3][16] = @@ -6,14 +8,14 @@ {0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,0}, {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0}}; -uint32_t freq[4] = {441, 480, 320, 0}; +u32 freq[4] = {441, 480, 320, 0}; unsigned int ac3_bitrates[32] = {32,40,48,56,64,80,96,112,128,160,192,224,256,320,384,448,512,576,640, 0,0,0,0,0,0,0,0,0,0,0,0,0}; -uint32_t ac3_freq[4] = {480, 441, 320, 0}; -uint32_t ac3_frames[3][32] = +u32 ac3_freq[4] = {480, 441, 320, 0}; +u32 ac3_frames[3][32] = {{64,80,96,112,128,160,192,224,256,320,384,448,512,640,768,896,1024, 1152,1280,0,0,0,0,0,0,0,0,0,0,0,0,0}, {69,87,104,121,139,174,208,243,278,348,417,487,557,696,835,975,1114, @@ -24,8 +26,7 @@ #if 0 -static -void setup_ts2pes(ipack *pa, ipack *pv, u16 *pida, u16 *pidv, +static void setup_ts2pes(ipack *pa, ipack *pv, u16 *pida, u16 *pidv, void (*pes_write)(u8 *buf, int count, void *data), void *priv) { @@ -39,8 +40,7 @@ #endif #if 0 -static -void ts_to_pes(ipack *p, u8 *buf) // don't need count (=188) +static void ts_to_pes(ipack *p, u8 *buf) // don't need count (=188) { u8 off = 0; @@ -66,10 +66,9 @@ #if 0 /* needs 5 byte input, returns picture coding type*/ -static -int read_picture_header(uint8_t *headr, mpg_picture *pic, int field, int pr) +static int read_picture_header(u8 *headr, struct mpg_picture *pic, int field, int pr) { - uint8_t pct; + u8 pct; if (pr) printk( "Pic header: "); pic->temporal_reference[field] = (( headr[0] << 2 ) | @@ -113,8 +112,7 @@ #if 0 /* needs 4 byte input */ -static -int read_gop_header(uint8_t *headr, mpg_picture *pic, int pr) +static int read_gop_header(u8 *headr, struct mpg_picture *pic, int pr) { if (pr) printk("GOP header: "); @@ -145,8 +143,7 @@ #if 0 /* needs 8 byte input */ -static -int read_sequence_header(uint8_t *headr, VideoInfo *vi, int pr) +static int read_sequence_header(u8 *headr, struct dvb_video_info *vi, int pr) { int sw; int form = -1; @@ -260,15 +257,14 @@ #if 0 -static -int get_vinfo(uint8_t *mbuf, int count, VideoInfo *vi, int pr) +static int get_vinfo(u8 *mbuf, int count, struct dvb_video_info *vi, int pr) { - uint8_t *headr; + u8 *headr; int found = 0; int c = 0; while (found < 4 && c+4 < count){ - uint8_t *b; + u8 *b; b = mbuf+c; if ( b[0] == 0x00 && b[1] == 0x00 && b[2] == 0x01 @@ -290,16 +286,15 @@ #if 0 -static -int get_ainfo(uint8_t *mbuf, int count, AudioInfo *ai, int pr) +static int get_ainfo(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr) { - uint8_t *headr; + u8 *headr; int found = 0; int c = 0; int fr = 0; while (found < 2 && c < count){ - uint8_t b[2]; + u8 b[2]; memcpy( b, mbuf+c, 2); if ( b[0] == 0xff && (b[1] & 0xf8) == 0xf8) @@ -346,16 +341,16 @@ #endif -int dvb_filter_get_ac3info(uint8_t *mbuf, int count, AudioInfo *ai, int pr) +int dvb_filter_get_ac3info(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr) { - uint8_t *headr; + u8 *headr; int found = 0; int c = 0; - uint8_t frame = 0; + u8 frame = 0; int fr = 0; while ( !found && c < count){ - uint8_t *b = mbuf+c; + u8 *b = mbuf+c; if ( b[0] == 0x0b && b[1] == 0x77 ) found = 1; @@ -378,18 +373,18 @@ ai->bit_rate = ac3_bitrates[frame >> 1]*1000; if (pr) - printk(" BRate: %d kb/s", ai->bit_rate/1000); + printk(" BRate: %d kb/s", (int) ai->bit_rate/1000); ai->frequency = (headr[2] & 0xc0 ) >> 6; fr = (headr[2] & 0xc0 ) >> 6; ai->frequency = freq[fr]*100; - if (pr) printk (" Freq: %d Hz\n", ai->frequency); + if (pr) printk (" Freq: %d Hz\n", (int) ai->frequency); ai->framesize = ac3_frames[fr][frame >> 1]; if ((frame & 1) && (fr == 1)) ai->framesize++; ai->framesize = ai->framesize << 1; - if (pr) printk (" Framesize %d\n", ai->framesize); + if (pr) printk (" Framesize %d\n",(int) ai->framesize); return 0; @@ -397,12 +392,11 @@ #if 0 -static -uint8_t *skip_pes_header(uint8_t **bufp) +static u8 *skip_pes_header(u8 **bufp) { - uint8_t *inbuf = *bufp; - uint8_t *buf = inbuf; - uint8_t *pts = NULL; + u8 *inbuf = *bufp; + u8 *buf = inbuf; + u8 *pts = NULL; int skip = 0; static const int mpeg1_skip_table[16] = { @@ -436,8 +430,7 @@ #endif #if 0 -static -void initialize_quant_matrix( uint32_t *matrix ) +static void initialize_quant_matrix( u32 *matrix ) { int i; @@ -464,8 +457,7 @@ #endif #if 0 -static -void initialize_mpg_picture(mpg_picture *pic) +static void initialize_mpg_picture(struct mpg_picture *pic) { int i; @@ -492,8 +484,7 @@ #endif #if 0 -static -void mpg_set_picture_parameter( int32_t field_type, mpg_picture *pic ) +static void mpg_set_picture_parameter( int32_t field_type, struct mpg_picture *pic ) { int16_t last_h_offset; int16_t last_v_offset; @@ -531,8 +522,7 @@ #endif #if 0 -static -void init_mpg_picture( mpg_picture *pic, int chan, int32_t field_type) +static void init_mpg_picture( struct mpg_picture *pic, int chan, int32_t field_type) { pic->picture_header = 0; pic->sequence_header_data @@ -561,7 +551,7 @@ } #endif -void dvb_filter_pes2ts_init(dvb_filter_pes2ts_t *p2ts, unsigned short pid, +void dvb_filter_pes2ts_init(struct dvb_filter_pes2ts *p2ts, unsigned short pid, dvb_filter_pes2ts_cb_t *cb, void *priv) { unsigned char *buf=p2ts->buf; @@ -574,7 +564,7 @@ p2ts->priv=priv; } -int dvb_filter_pes2ts(dvb_filter_pes2ts_t *p2ts, unsigned char *pes, int len) +int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes, int len) { unsigned char *buf=p2ts->buf; int ret=0, rest; diff -Nru a/drivers/media/dvb/dvb-core/dvb_filter.h b/drivers/media/dvb/dvb-core/dvb_filter.h --- a/drivers/media/dvb/dvb-core/dvb_filter.h Tue Jul 1 18:44:33 2003 +++ b/drivers/media/dvb/dvb-core/dvb_filter.h Tue Jul 1 18:44:33 2003 @@ -2,23 +2,22 @@ #define _DVB_FILTER_H_ #include -#include #include "demux.h" typedef int (dvb_filter_pes2ts_cb_t) (void *, unsigned char *); -typedef struct dvb_filter_pes2ts_s { +struct dvb_filter_pes2ts { unsigned char buf[188]; unsigned char cc; dvb_filter_pes2ts_cb_t *cb; void *priv; -} dvb_filter_pes2ts_t; +}; -void dvb_filter_pes2ts_init(dvb_filter_pes2ts_t *p2ts, unsigned short pid, +void dvb_filter_pes2ts_init(struct dvb_filter_pes2ts *p2ts, unsigned short pid, dvb_filter_pes2ts_cb_t *cb, void *priv); -int dvb_filter_pes2ts(dvb_filter_pes2ts_t *p2ts, unsigned char *pes, int len); +int dvb_filter_pes2ts(struct dvb_filter_pes2ts *p2ts, unsigned char *pes, int len); #define PROG_STREAM_MAP 0xBC @@ -35,14 +34,14 @@ #define ISO13522_STREAM 0xF3 #define PROG_STREAM_DIR 0xFF -#define PICTURE_START 0x00 -#define USER_START 0xb2 -#define SEQUENCE_HEADER 0xb3 -#define SEQUENCE_ERROR 0xb4 -#define EXTENSION_START 0xb5 -#define SEQUENCE_END 0xb7 -#define GOP_START 0xb8 -#define EXCEPT_SLICE 0xb0 +#define DVB_PICTURE_START 0x00 +#define DVB_USER_START 0xb2 +#define DVB_SEQUENCE_HEADER 0xb3 +#define DVB_SEQUENCE_ERROR 0xb4 +#define DVB_EXTENSION_START 0xb5 +#define DVB_SEQUENCE_END 0xb7 +#define DVB_GOP_START 0xb8 +#define DVB_EXCEPT_SLICE 0xb0 #define SEQUENCE_EXTENSION 0x01 #define SEQUENCE_DISPLAY_EXTENSION 0x02 @@ -111,12 +110,12 @@ #define IPACKS 2048 #endif -typedef struct ipack_s { +struct ipack { int size; int found; u8 *buf; u8 cid; - uint32_t plength; + u32 plength; u8 plen[2]; u8 flag1; u8 flag2; @@ -131,34 +130,33 @@ void (*func)(u8 *buf, int size, void *priv); int count; int repack_subids; -} ipack; - -typedef struct video_i{ - uint32_t horizontal_size; - uint32_t vertical_size; - uint32_t aspect_ratio; - uint32_t framerate; - uint32_t video_format; - uint32_t bit_rate; - uint32_t comp_bit_rate; - uint32_t vbv_buffer_size; - int16_t vbv_delay; - uint32_t CSPF; - uint32_t off; -} VideoInfo; +}; +struct dvb_video_info { + u32 horizontal_size; + u32 vertical_size; + u32 aspect_ratio; + u32 framerate; + u32 video_format; + u32 bit_rate; + u32 comp_bit_rate; + u32 vbv_buffer_size; + s16 vbv_delay; + u32 CSPF; + u32 off; +}; #define OFF_SIZE 4 #define FIRST_FIELD 0 #define SECOND_FIELD 1 #define VIDEO_FRAME_PICTURE 0x03 -typedef struct mpg_picture_s{ +struct mpg_picture { int channel; - VideoInfo vinfo; - uint32_t *sequence_gop_header; - uint32_t *picture_header; - int32_t time_code; + struct dvb_video_info vinfo; + u32 *sequence_gop_header; + u32 *picture_header; + s32 time_code; int low_delay; int closed_gop; int broken_link; @@ -166,12 +164,12 @@ int gop_flag; int sequence_end_flag; - uint8_t profile_and_level; - int32_t picture_coding_parameter; - uint32_t matrix[32]; - int8_t matrix_change_flag; + u8 profile_and_level; + s32 picture_coding_parameter; + u32 matrix[32]; + s8 matrix_change_flag; - uint8_t picture_header_parameter; + u8 picture_header_parameter; /* bit 0 - 2: bwd f code bit 3 : fpb vector bit 4 - 6: fwd f code @@ -180,11 +178,11 @@ int mpeg1_flag; int progressive_sequence; int sequence_display_extension_flag; - uint32_t sequence_header_data; - int16_t last_frame_centre_horizontal_offset; - int16_t last_frame_centre_vertical_offset; + u32 sequence_header_data; + s16 last_frame_centre_horizontal_offset; + s16 last_frame_centre_vertical_offset; - uint32_t pts[2]; /* [0] 1st field, [1] 2nd field */ + u32 pts[2]; /* [0] 1st field, [1] 2nd field */ int top_field_first; int repeat_first_field; int progressive_frame; @@ -192,39 +190,36 @@ int forward_bank; int backward_bank; int compress; - int16_t frame_centre_horizontal_offset[OFF_SIZE]; + s16 frame_centre_horizontal_offset[OFF_SIZE]; /* [0-2] 1st field, [3] 2nd field */ - int16_t frame_centre_vertical_offset[OFF_SIZE]; + s16 frame_centre_vertical_offset[OFF_SIZE]; /* [0-2] 1st field, [3] 2nd field */ - int16_t temporal_reference[2]; + s16 temporal_reference[2]; /* [0] 1st field, [1] 2nd field */ - int8_t picture_coding_type[2]; + s8 picture_coding_type[2]; /* [0] 1st field, [1] 2nd field */ - int8_t picture_structure[2]; + s8 picture_structure[2]; /* [0] 1st field, [1] 2nd field */ - int8_t picture_display_extension_flag[2]; + s8 picture_display_extension_flag[2]; /* [0] 1st field, [1] 2nd field */ /* picture_display_extenion() 0:no 1:exit*/ - int8_t pts_flag[2]; + s8 pts_flag[2]; /* [0] 1st field, [1] 2nd field */ -} mpg_picture; - - - +}; -typedef struct audio_i{ +struct dvb_audio_info { int layer ; - uint32_t bit_rate ; - uint32_t frequency ; - uint32_t mode ; - uint32_t mode_extension ; - uint32_t emphasis ; - uint32_t framesize; - uint32_t off; -} AudioInfo; + u32 bit_rate; + u32 frequency; + u32 mode; + u32 mode_extension ; + u32 emphasis; + u32 framesize; + u32 off; +}; -int dvb_filter_get_ac3info(uint8_t *mbuf, int count, AudioInfo *ai, int pr); +int dvb_filter_get_ac3info(u8 *mbuf, int count, struct dvb_audio_info *ai, int pr); #endif diff -Nru a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c --- a/drivers/media/dvb/dvb-core/dvb_frontend.c Tue Jul 1 18:44:33 2003 +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c Tue Jul 1 18:44:33 2003 @@ -22,15 +22,20 @@ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html */ +#include +#include #include -#include +#include #include #include #include #include +#include +#include #include "dvb_frontend.h" #include "dvbdev.h" +#include "dvb_functions.h" static int dvb_frontend_debug = 0; @@ -59,7 +64,7 @@ struct semaphore sem; struct list_head list_head; wait_queue_head_t wait_queue; - struct task_struct *thread; + pid_t thread_pid; unsigned long release_jiffies; unsigned long lost_sync_jiffies; int bending; @@ -97,16 +102,7 @@ static DECLARE_MUTEX(frontend_mutex); -static -inline void ddelay (int ms) -{ - current->state=TASK_INTERRUPTIBLE; - schedule_timeout((HZ*ms)/1000); -} - - -static -int dvb_frontend_internal_ioctl (struct dvb_frontend *frontend, +static int dvb_frontend_internal_ioctl (struct dvb_frontend *frontend, unsigned int cmd, void *arg) { int err = -EOPNOTSUPP; @@ -116,10 +112,10 @@ if (frontend->before_ioctl) err = frontend->before_ioctl (frontend, cmd, arg); - if (err) { + if (err == -EOPNOTSUPP) { err = frontend->ioctl (frontend, cmd, arg); - if (err && frontend->after_ioctl) + if ((err == -EOPNOTSUPP) && frontend->after_ioctl) err = frontend->after_ioctl (frontend, cmd, arg); } @@ -134,8 +130,7 @@ * should make it still possible to receive the requested transponder * on both tuners... */ -static -void dvb_bend_frequency (struct dvb_frontend_data *this_fe, int recursive) +static void dvb_bend_frequency (struct dvb_frontend_data *this_fe, int recursive) { struct list_head *entry; int stepsize = this_fe->info->frequency_stepsize; @@ -188,8 +183,7 @@ } -static -void dvb_call_frontend_notifiers (struct dvb_frontend_data *fe, +static void dvb_call_frontend_notifiers (struct dvb_frontend_data *fe, fe_status_t s) { dprintk ("%s\n", __FUNCTION__); @@ -198,7 +192,7 @@ fe->lost_sync_jiffies = jiffies; if (((s ^ fe->status) & FE_HAS_LOCK) && (s & FE_HAS_LOCK)) - ddelay (fe->info->notifier_delay); + dvb_delay (fe->info->notifier_delay); fe->status = s; @@ -213,8 +207,7 @@ } -static -void dvb_frontend_add_event (struct dvb_frontend_data *fe, fe_status_t status) +static void dvb_frontend_add_event (struct dvb_frontend_data *fe, fe_status_t status) { struct dvb_fe_events *events = &fe->events; struct dvb_frontend_event *e; @@ -252,8 +245,7 @@ } -static -int dvb_frontend_get_event (struct dvb_frontend_data *fe, +static int dvb_frontend_get_event (struct dvb_frontend_data *fe, struct dvb_frontend_event *event, int flags) { struct dvb_fe_events *events = &fe->events; @@ -291,8 +283,7 @@ } -static -int dvb_frontend_set_parameters (struct dvb_frontend_data *fe, +static int dvb_frontend_set_parameters (struct dvb_frontend_data *fe, struct dvb_frontend_parameters *param, int first_trial) { @@ -313,7 +304,7 @@ dvb_bend_frequency (fe, 0); dprintk ("%s: f == %i, drift == %i\n", - __FUNCTION__, param->frequency, fe->lnb_drift); + __FUNCTION__, (int) param->frequency, (int) fe->lnb_drift); param->frequency += fe->lnb_drift + fe->bending; err = dvb_frontend_internal_ioctl (frontend, FE_SET_FRONTEND, param); @@ -324,8 +315,7 @@ return err; } -static -void dvb_frontend_init (struct dvb_frontend_data *fe) +static void dvb_frontend_init (struct dvb_frontend_data *fe) { struct dvb_frontend *frontend = &fe->frontend; @@ -337,8 +327,7 @@ } -static -void update_delay (int *quality, int *delay, int locked) +static void update_delay (int *quality, int *delay, int locked) { int q2; @@ -363,8 +352,7 @@ * here we only come when we have lost the lock bit, * let's try to do something useful... */ -static -void dvb_frontend_recover (struct dvb_frontend_data *fe) +static void dvb_frontend_recover (struct dvb_frontend_data *fe) { dprintk ("%s\n", __FUNCTION__); @@ -391,6 +379,8 @@ if (fe->info->type == FE_QPSK) stepsize = fe->parameters.u.qpsk.symbol_rate / 16000; + else if (fe->info->type == FE_QAM) + stepsize = 0; else stepsize = fe->info->frequency_stepsize * 2; @@ -410,8 +400,7 @@ -static -int dvb_frontend_is_exiting (struct dvb_frontend_data *fe) +static int dvb_frontend_is_exiting (struct dvb_frontend_data *fe) { if (fe->exit) return 1; @@ -424,46 +413,34 @@ } -static -int dvb_frontend_thread (void *data) +static int dvb_frontend_thread (void *data) { struct dvb_frontend_data *fe = (struct dvb_frontend_data *) data; + char name [15]; int quality = 0, delay = 3*HZ; fe_status_t s; dprintk ("%s\n", __FUNCTION__); - lock_kernel (); -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,61)) - daemonize (); -#else - daemonize ("dvb fe"); -#endif -/* not needed anymore in 2.5.x, done in daemonize() */ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) - reparent_to_init (); -#endif - - sigfillset (¤t->blocked); - fe->thread = current; - snprintf (current->comm, sizeof (current->comm), "kdvb-fe-%i:%i", + snprintf (name, sizeof(name), "kdvb-fe-%i:%i", fe->frontend.i2c->adapter->num, fe->frontend.i2c->id); - unlock_kernel (); - dvb_call_frontend_notifiers (fe, 0); - dvb_frontend_init (fe); + dvb_kernel_thread_setup (name); fe->lost_sync_count = -1; + dvb_call_frontend_notifiers (fe, 0); + dvb_frontend_init (fe); + while (!dvb_frontend_is_exiting (fe)) { up (&fe->sem); /* is locked when we enter the thread... */ interruptible_sleep_on_timeout (&fe->wait_queue, delay); + if (signal_pending(current)) + break; - if (down_interruptible (&fe->sem)) { - fe->thread = NULL; - return -ERESTARTSYS; - } + if (down_interruptible (&fe->sem)) + break; if (fe->lost_sync_count == -1) continue; @@ -505,47 +482,79 @@ dvb_frontend_internal_ioctl (&fe->frontend, FE_SLEEP, NULL); up (&fe->sem); - fe->thread = NULL; + + fe->thread_pid = 0; + mb(); + + wake_up_interruptible (&fe->wait_queue); return 0; } -static -void dvb_frontend_stop (struct dvb_frontend_data *fe) +static void dvb_frontend_stop (struct dvb_frontend_data *fe) { dprintk ("%s\n", __FUNCTION__); - while (fe->thread) { fe->exit = 1; + mb(); + + if (!fe->thread_pid) + return; + + /* check if the thread is really alive */ + if (kill_proc(fe->thread_pid, 0, 1) == -ESRCH) { + printk("dvb_frontend_stop: thread PID %d already died\n", + fe->thread_pid); + /* make sure the mutex was not held by the thread */ + init_MUTEX (&fe->sem); + return; + } + wake_up_interruptible (&fe->wait_queue); - current->state = TASK_INTERRUPTIBLE; - schedule_timeout (5); - if (signal_pending(current)) - break; - }; + interruptible_sleep_on(&fe->wait_queue); + + /* paranoia check */ + if (fe->thread_pid) + printk("dvb_frontend_stop: warning: thread PID %d won't exit\n", + fe->thread_pid); } -static -void dvb_frontend_start (struct dvb_frontend_data *fe) +static int dvb_frontend_start (struct dvb_frontend_data *fe) { + int ret; + dprintk ("%s\n", __FUNCTION__); - if (fe->thread) + if (fe->thread_pid) { + if (!fe->exit) + return 0; + else dvb_frontend_stop (fe); + } + if (signal_pending(current)) + return -EINTR; if (down_interruptible (&fe->sem)) - return; + return -EINTR; fe->exit = 0; - fe->thread = (void*) ~0; + fe->thread_pid = 0; + mb(); - kernel_thread (dvb_frontend_thread, fe, 0); + ret = kernel_thread (dvb_frontend_thread, fe, 0); + if (ret < 0) { + printk("dvb_frontend_start: failed to start kernel_thread (%d)\n", ret); + up(&fe->sem); + return ret; + } + fe->thread_pid = ret; + + return 0; } -static -int dvb_frontend_ioctl (struct inode *inode, struct file *file, +static int dvb_frontend_ioctl (struct inode *inode, struct file *file, unsigned int cmd, void *parg) { struct dvb_device *dvbdev = file->private_data; @@ -588,8 +597,7 @@ } -static -unsigned int dvb_frontend_poll (struct file *file, struct poll_table_struct *wait) +static unsigned int dvb_frontend_poll (struct file *file, struct poll_table_struct *wait) { struct dvb_device *dvbdev = file->private_data; struct dvb_frontend_data *fe = dvbdev->priv; @@ -605,8 +613,7 @@ } -static -int dvb_frontend_open (struct inode *inode, struct file *file) +static int dvb_frontend_open (struct inode *inode, struct file *file) { struct dvb_device *dvbdev = file->private_data; struct dvb_frontend_data *fe = dvbdev->priv; @@ -618,18 +625,19 @@ return ret; if ((file->f_flags & O_ACCMODE) != O_RDONLY) { - dvb_frontend_start (fe); + ret = dvb_frontend_start (fe); + if (ret) + dvb_generic_release (inode, file); /* empty event queue */ - fe->events.eventr = fe->events.eventw; + fe->events.eventr = fe->events.eventw = 0; } return ret; } -static -int dvb_frontend_release (struct inode *inode, struct file *file) +static int dvb_frontend_release (struct inode *inode, struct file *file) { struct dvb_device *dvbdev = file->private_data; struct dvb_frontend_data *fe = dvbdev->priv; @@ -830,8 +838,7 @@ } -static -struct file_operations dvb_frontend_fops = { +static struct file_operations dvb_frontend_fops = { .owner = THIS_MODULE, .ioctl = dvb_generic_ioctl, .poll = dvb_frontend_poll, diff -Nru a/drivers/media/dvb/dvb-core/dvb_frontend.h b/drivers/media/dvb/dvb-core/dvb_frontend.h --- a/drivers/media/dvb/dvb-core/dvb_frontend.h Tue Jul 1 18:44:38 2003 +++ b/drivers/media/dvb/dvb-core/dvb_frontend.h Tue Jul 1 18:44:38 2003 @@ -25,15 +25,12 @@ #ifndef _DVB_FRONTEND_H_ #define _DVB_FRONTEND_H_ -#include +#include #include #include #include #include - -#ifndef MODULE_LICENSE -#define MODULE_LICENSE(x) -#endif +#include #include diff -Nru a/drivers/media/dvb/dvb-core/dvb_functions.c b/drivers/media/dvb/dvb-core/dvb_functions.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/media/dvb/dvb-core/dvb_functions.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,86 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void dvb_kernel_thread_setup (const char *thread_name) +{ + lock_kernel (); + + daemonize (thread_name); + + sigfillset (¤t->blocked); + + unlock_kernel (); +} + +/* if the miracle happens and "generic_usercopy()" is included into + the kernel, then this can vanish. please don't make the mistake and + define this as video_usercopy(). this will introduce a dependecy + to the v4l "videodev.o" module, which is unnecessary for some + cards (ie. the budget dvb-cards don't need the v4l module...) */ +int dvb_usercopy(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, + int (*func)(struct inode *inode, struct file *file, + unsigned int cmd, void *arg)) +{ + char sbuf[128]; + void *mbuf = NULL; + void *parg = NULL; + int err = -EINVAL; + + /* Copy arguments into temp kernel buffer */ + switch (_IOC_DIR(cmd)) { + case _IOC_NONE: + parg = (void *)arg; + break; + case _IOC_READ: /* some v4l ioctls are marked wrong ... */ + case _IOC_WRITE: + case (_IOC_WRITE | _IOC_READ): + if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { + parg = sbuf; + } else { + /* too big to allocate from stack */ + mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL); + if (NULL == mbuf) + return -ENOMEM; + parg = mbuf; + } + + err = -EFAULT; + if (copy_from_user(parg, (void *)arg, _IOC_SIZE(cmd))) + goto out; + break; + } + + /* call driver */ + if ((err = func(inode, file, cmd, parg)) == -ENOIOCTLCMD) + err = -EINVAL; + + if (err < 0) + goto out; + + /* Copy results into user buffer */ + switch (_IOC_DIR(cmd)) + { + case _IOC_READ: + case (_IOC_WRITE | _IOC_READ): + if (copy_to_user((void *)arg, parg, _IOC_SIZE(cmd))) + err = -EFAULT; + break; + } + +out: + if (mbuf) + kfree(mbuf); + + return err; +} + +EXPORT_SYMBOL(dvb_usercopy); +EXPORT_SYMBOL(dvb_kernel_thread_setup); diff -Nru a/drivers/media/dvb/dvb-core/dvb_functions.h b/drivers/media/dvb/dvb-core/dvb_functions.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/media/dvb/dvb-core/dvb_functions.h Tue Jul 1 18:44:40 2003 @@ -0,0 +1,27 @@ +#ifndef __DVB_FUNCTIONS_H__ +#define __DVB_FUNCTIONS_H__ + +/** + * a sleeping delay function, waits i ms + * + */ +static inline +void dvb_delay(int i) +{ + current->state=TASK_INTERRUPTIBLE; + schedule_timeout((HZ*i)/1000); +} + +/* we don't mess with video_usercopy() any more, +we simply define out own dvb_usercopy(), which will hopefull become +generic_usercopy() someday... */ + +extern int dvb_usercopy(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, + int (*func)(struct inode *inode, struct file *file, + unsigned int cmd, void *arg)); + +extern void dvb_kernel_thread_setup (const char *thread_name); + +#endif + diff -Nru a/drivers/media/dvb/dvb-core/dvb_i2c.c b/drivers/media/dvb/dvb-core/dvb_i2c.c --- a/drivers/media/dvb/dvb-core/dvb_i2c.c Tue Jul 1 18:44:36 2003 +++ b/drivers/media/dvb/dvb-core/dvb_i2c.c Tue Jul 1 18:44:36 2003 @@ -19,16 +19,15 @@ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html */ +#include #include #include #include -#include - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) - #include "compat.h" -#endif +#include #include "dvb_i2c.h" +#include "dvb_functions.h" + struct dvb_i2c_device { struct list_head list_head; @@ -42,8 +41,7 @@ DECLARE_MUTEX(dvb_i2c_mutex); -static -int register_i2c_client (struct dvb_i2c_bus *i2c, struct dvb_i2c_device *dev) +static int register_i2c_client (struct dvb_i2c_bus *i2c, struct dvb_i2c_device *dev) { struct dvb_i2c_device *client; @@ -61,8 +59,7 @@ } -static -void try_attach_device (struct dvb_i2c_bus *i2c, struct dvb_i2c_device *dev) +static void try_attach_device (struct dvb_i2c_bus *i2c, struct dvb_i2c_device *dev) { if (dev->owner) { if (!try_module_get(dev->owner)) @@ -78,8 +75,7 @@ } -static -void detach_device (struct dvb_i2c_bus *i2c, struct dvb_i2c_device *dev) +static void detach_device (struct dvb_i2c_bus *i2c, struct dvb_i2c_device *dev) { dev->detach (i2c); @@ -88,8 +84,7 @@ } -static -void unregister_i2c_client_from_bus (struct dvb_i2c_device *dev, +static void unregister_i2c_client_from_bus (struct dvb_i2c_device *dev, struct dvb_i2c_bus *i2c) { struct list_head *entry, *n; @@ -107,8 +102,7 @@ } -static -void unregister_i2c_client_from_all_busses (struct dvb_i2c_device *dev) +static void unregister_i2c_client_from_all_busses (struct dvb_i2c_device *dev) { struct list_head *entry, *n; @@ -122,8 +116,7 @@ } -static -void unregister_all_clients_from_bus (struct dvb_i2c_bus *i2c) +static void unregister_all_clients_from_bus (struct dvb_i2c_bus *i2c) { struct list_head *entry, *n; @@ -137,8 +130,7 @@ } -static -void probe_device_on_all_busses (struct dvb_i2c_device *dev) +static void probe_device_on_all_busses (struct dvb_i2c_device *dev) { struct list_head *entry; @@ -152,8 +144,7 @@ } -static -void probe_devices_on_bus (struct dvb_i2c_bus *i2c) +static void probe_devices_on_bus (struct dvb_i2c_bus *i2c) { struct list_head *entry; @@ -167,8 +158,7 @@ } -static -struct dvb_i2c_bus* dvb_find_i2c_bus (int (*xfer) (struct dvb_i2c_bus *i2c, +static struct dvb_i2c_bus* dvb_find_i2c_bus (int (*xfer) (struct dvb_i2c_bus *i2c, const struct i2c_msg msgs[], int num), struct dvb_adapter *adapter, diff -Nru a/drivers/media/dvb/dvb-core/dvb_ksyms.c b/drivers/media/dvb/dvb-core/dvb_ksyms.c --- a/drivers/media/dvb/dvb-core/dvb_ksyms.c Tue Jul 1 18:44:39 2003 +++ b/drivers/media/dvb/dvb-core/dvb_ksyms.c Tue Jul 1 18:44:39 2003 @@ -1,76 +1,15 @@ +#include #include +#include +#include +#include +#include #include "dmxdev.h" -#include "dvb_filter.h" -#include "dvb_frontend.h" -#include "dvb_i2c.h" -#include "dvbdev.h" #include "dvb_demux.h" +#include "dvb_frontend.h" #include "dvb_net.h" - -/* if the miracle happens and "generic_usercopy()" is included into - the kernel, then this can vanish. please don't make the mistake and - define this as video_usercopy(). this will introduce a dependecy - to the v4l "videodev.o" module, which is unnecessary for some - cards (ie. the budget dvb-cards don't need the v4l module...) */ -int dvb_usercopy(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg, - int (*func)(struct inode *inode, struct file *file, - unsigned int cmd, void *arg)) -{ - char sbuf[128]; - void *mbuf = NULL; - void *parg = NULL; - int err = -EINVAL; - - /* Copy arguments into temp kernel buffer */ - switch (_IOC_DIR(cmd)) { - case _IOC_NONE: - parg = (void *)arg; - break; - case _IOC_READ: /* some v4l ioctls are marked wrong ... */ - case _IOC_WRITE: - case (_IOC_WRITE | _IOC_READ): - if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { - parg = sbuf; - } else { - /* too big to allocate from stack */ - mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL); - if (NULL == mbuf) - return -ENOMEM; - parg = mbuf; - } - - err = -EFAULT; - if (copy_from_user(parg, (void *)arg, _IOC_SIZE(cmd))) - goto out; - break; - } - - /* call driver */ - if ((err = func(inode, file, cmd, parg)) == -ENOIOCTLCMD) - err = -EINVAL; - - if (err < 0) - goto out; - - /* Copy results into user buffer */ - switch (_IOC_DIR(cmd)) - { - case _IOC_READ: - case (_IOC_WRITE | _IOC_READ): - if (copy_to_user((void *)arg, parg, _IOC_SIZE(cmd))) - err = -EFAULT; - break; - } - -out: - if (mbuf) - kfree(mbuf); - - return err; -} -EXPORT_SYMBOL(dvb_usercopy); +#include "dvb_filter.h" EXPORT_SYMBOL(dvb_dmxdev_init); EXPORT_SYMBOL(dvb_dmxdev_release); @@ -79,6 +18,8 @@ EXPORT_SYMBOL(dvb_dmx_swfilter_packet); EXPORT_SYMBOL(dvb_dmx_swfilter_packets); EXPORT_SYMBOL(dvb_dmx_swfilter); +EXPORT_SYMBOL(dvbdmx_connect_frontend); +EXPORT_SYMBOL(dvbdmx_disconnect_frontend); EXPORT_SYMBOL(dvb_register_frontend); EXPORT_SYMBOL(dvb_unregister_frontend); diff -Nru a/drivers/media/dvb/dvb-core/dvb_net.c b/drivers/media/dvb/dvb-core/dvb_net.c --- a/drivers/media/dvb/dvb-core/dvb_net.c Tue Jul 1 18:44:32 2003 +++ b/drivers/media/dvb/dvb-core/dvb_net.c Tue Jul 1 18:44:32 2003 @@ -24,15 +24,18 @@ * */ +#include +#include +#include +#include +#include #include #include + #include "dvb_demux.h" #include "dvb_net.h" - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) - #include "compat.h" -#endif +#include "dvb_functions.h" #define DVB_NET_MULTICAST_MAX 10 @@ -40,11 +43,11 @@ struct net_device_stats stats; char name[6]; u16 pid; - struct dmx_demux_s *demux; - dmx_section_feed_t *secfeed; - dmx_section_filter_t *secfilter; + struct dmx_demux *demux; + struct dmx_section_feed *secfeed; + struct dmx_section_filter *secfilter; int multi_num; - dmx_section_filter_t *multi_secfilter[DVB_NET_MULTICAST_MAX]; + struct dmx_section_filter *multi_secfilter[DVB_NET_MULTICAST_MAX]; unsigned char multi_macs[DVB_NET_MULTICAST_MAX][6]; int mode; }; @@ -95,8 +98,7 @@ return htons(ETH_P_802_2); } -static void -dvb_net_sec(struct net_device *dev, const u8 *pkt, int pkt_len) +static void dvb_net_sec(struct net_device *dev, const u8 *pkt, int pkt_len) { u8 *eth; struct sk_buff *skb; @@ -132,11 +134,10 @@ netif_rx(skb); } -static int -dvb_net_callback(const u8 *buffer1, size_t buffer1_len, +static int dvb_net_callback(const u8 *buffer1, size_t buffer1_len, const u8 *buffer2, size_t buffer2_len, - dmx_section_filter_t *filter, - dmx_success_t success) + struct dmx_section_filter *filter, + enum dmx_success success) { struct net_device *dev=(struct net_device *) filter->priv; @@ -146,8 +147,7 @@ return 0; } -static int -dvb_net_tx(struct sk_buff *skb, struct net_device *dev) +static int dvb_net_tx(struct sk_buff *skb, struct net_device *dev) { return 0; } @@ -157,9 +157,8 @@ static u8 mac_allmulti[6]={0x01, 0x00, 0x5e, 0x00, 0x00, 0x00}; static u8 mask_promisc[6]={0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; -static int -dvb_net_filter_set(struct net_device *dev, - dmx_section_filter_t **secfilter, +static int dvb_net_filter_set(struct net_device *dev, + struct dmx_section_filter **secfilter, u8 *mac, u8 *mac_mask) { struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv; @@ -200,12 +199,11 @@ return 0; } -static int -dvb_net_feed_start(struct net_device *dev) +static int dvb_net_feed_start(struct net_device *dev) { int ret, i; struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv; - dmx_demux_t *demux = priv->demux; + struct dmx_demux *demux = priv->demux; unsigned char *mac = (unsigned char *) dev->dev_addr; priv->secfeed=0; @@ -252,8 +250,7 @@ return 0; } -static void -dvb_net_feed_stop(struct net_device *dev) +static void dvb_net_feed_stop(struct net_device *dev) { struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv; int i; @@ -283,8 +280,7 @@ printk("%s: no feed to stop\n", dev->name); } -static int -dvb_add_mc_filter(struct net_device *dev, struct dev_mc_list *mc) +static int dvb_add_mc_filter(struct net_device *dev, struct dev_mc_list *mc) { struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv; int ret; @@ -300,8 +296,7 @@ return ret; } -static void -dvb_net_set_multi(struct net_device *dev) +static void dvb_net_set_multi(struct net_device *dev) { struct dvb_net_priv *priv = (struct dvb_net_priv*) dev->priv; struct dev_mc_list *mc; @@ -343,16 +338,14 @@ } } -static int -dvb_net_set_config(struct net_device *dev, struct ifmap *map) +static int dvb_net_set_config(struct net_device *dev, struct ifmap *map) { if (netif_running(dev)) return -EBUSY; return 0; } -static int -dvb_net_set_mac(struct net_device *dev, void *p) +static int dvb_net_set_mac(struct net_device *dev, void *p) { struct sockaddr *addr=p; int update; @@ -367,29 +360,25 @@ } -static int -dvb_net_open(struct net_device *dev) +static int dvb_net_open(struct net_device *dev) { dvb_net_feed_start(dev); return 0; } -static int -dvb_net_stop(struct net_device *dev) +static int dvb_net_stop(struct net_device *dev) { dvb_net_feed_stop(dev); return 0; } -static struct net_device_stats * -dvb_net_get_stats(struct net_device *dev) +static struct net_device_stats * dvb_net_get_stats(struct net_device *dev) { return &((struct dvb_net_priv*) dev->priv)->stats; } -static int -dvb_net_init_dev(struct net_device *dev) +static int dvb_net_init_dev(struct net_device *dev) { ether_setup(dev); @@ -411,8 +400,7 @@ return 0; } -static int -get_if(struct dvb_net *dvbnet) +static int get_if(struct dvb_net *dvbnet) { int i; @@ -430,7 +418,7 @@ dvb_net_add_if(struct dvb_net *dvbnet, u16 pid) { struct net_device *net; - dmx_demux_t *demux; + struct dmx_demux *demux; struct dvb_net_priv *priv; int result; int if_num; @@ -524,15 +512,14 @@ break; } case NET_REMOVE_IF: - return dvb_net_remove_if(dvbnet, (int) parg); + return dvb_net_remove_if(dvbnet, (long) parg); default: return -EINVAL; } return 0; } -static int -dvb_net_ioctl(struct inode *inode, struct file *file, +static int dvb_net_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { return dvb_usercopy(inode, file, cmd, arg, dvb_net_do_ioctl); @@ -569,7 +556,7 @@ } int -dvb_net_init(struct dvb_adapter *adap, struct dvb_net *dvbnet, dmx_demux_t *dmx) +dvb_net_init(struct dvb_adapter *adap, struct dvb_net *dvbnet, struct dmx_demux *dmx) { int i; diff -Nru a/drivers/media/dvb/dvb-core/dvb_net.h b/drivers/media/dvb/dvb-core/dvb_net.h --- a/drivers/media/dvb/dvb-core/dvb_net.h Tue Jul 1 18:44:32 2003 +++ b/drivers/media/dvb/dvb-core/dvb_net.h Tue Jul 1 18:44:32 2003 @@ -33,18 +33,18 @@ #define DVB_NET_DEVICES_MAX 10 -typedef struct dvb_net { +struct dvb_net { struct dvb_device *dvbdev; int card_num; int dev_num; struct net_device device[DVB_NET_DEVICES_MAX]; int state[DVB_NET_DEVICES_MAX]; - dmx_demux_t *demux; -} dvb_net_t; + struct dmx_demux *demux; +}; void dvb_net_release(struct dvb_net *); -int dvb_net_init(struct dvb_adapter *, struct dvb_net *, dmx_demux_t *); +int dvb_net_init(struct dvb_adapter *, struct dvb_net *, struct dmx_demux *); #endif diff -Nru a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c --- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c Tue Jul 1 18:44:36 2003 +++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c Tue Jul 1 18:44:36 2003 @@ -32,16 +32,18 @@ #define __KERNEL_SYSCALLS__ +#include #include -#include #include +#include +#include #include #include "dvb_ringbuffer.h" -void dvb_ringbuffer_init(dvb_ringbuffer_t *rbuf, void *data, size_t len) +void dvb_ringbuffer_init(struct dvb_ringbuffer *rbuf, void *data, size_t len) { rbuf->pread=rbuf->pwrite=0; rbuf->data=data; @@ -50,19 +52,18 @@ init_waitqueue_head(&rbuf->queue); spin_lock_init(&(rbuf->lock)); - rbuf->lock=SPIN_LOCK_UNLOCKED; } -int dvb_ringbuffer_empty(dvb_ringbuffer_t *rbuf) +int dvb_ringbuffer_empty(struct dvb_ringbuffer *rbuf) { return (rbuf->pread==rbuf->pwrite); } -ssize_t dvb_ringbuffer_free(dvb_ringbuffer_t *rbuf) +ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf) { ssize_t free; @@ -74,7 +75,7 @@ -ssize_t dvb_ringbuffer_avail(dvb_ringbuffer_t *rbuf) +ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf) { ssize_t avail; @@ -86,14 +87,14 @@ -void dvb_ringbuffer_flush(dvb_ringbuffer_t *rbuf) +void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf) { rbuf->pread = rbuf->pwrite; } -void dvb_ringbuffer_flush_spinlock_wakeup(dvb_ringbuffer_t *rbuf) +void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf) { unsigned long flags; @@ -106,7 +107,7 @@ -ssize_t dvb_ringbuffer_read(dvb_ringbuffer_t *rbuf, u8 *buf, size_t len, int usermem) +ssize_t dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len, int usermem) { size_t todo = len; size_t split; @@ -135,7 +136,7 @@ -ssize_t dvb_ringbuffer_write(dvb_ringbuffer_t *rbuf, const u8 *buf, +ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf, size_t len, int usermem) { size_t todo = len; diff -Nru a/drivers/media/dvb/dvb-core/dvb_ringbuffer.h b/drivers/media/dvb/dvb-core/dvb_ringbuffer.h --- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.h Tue Jul 1 18:44:39 2003 +++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.h Tue Jul 1 18:44:39 2003 @@ -32,8 +32,10 @@ #ifndef _DVB_RINGBUFFER_H_ #define _DVB_RINGBUFFER_H_ +#include +#include -typedef struct dvb_ringbuffer { +struct dvb_ringbuffer { u8 *data; ssize_t size; ssize_t pread; @@ -41,7 +43,7 @@ wait_queue_head_t queue; spinlock_t lock; -} dvb_ringbuffer_t; +}; /* @@ -73,25 +75,25 @@ */ /* initialize ring buffer, lock and queue */ -extern void dvb_ringbuffer_init(dvb_ringbuffer_t *rbuf, void *data, size_t len); +extern void dvb_ringbuffer_init(struct dvb_ringbuffer *rbuf, void *data, size_t len); /* test whether buffer is empty */ -extern int dvb_ringbuffer_empty(dvb_ringbuffer_t *rbuf); +extern int dvb_ringbuffer_empty(struct dvb_ringbuffer *rbuf); /* return the number of free bytes in the buffer */ -extern ssize_t dvb_ringbuffer_free(dvb_ringbuffer_t *rbuf); +extern ssize_t dvb_ringbuffer_free(struct dvb_ringbuffer *rbuf); /* return the number of bytes waiting in the buffer */ -extern ssize_t dvb_ringbuffer_avail(dvb_ringbuffer_t *rbuf); +extern ssize_t dvb_ringbuffer_avail(struct dvb_ringbuffer *rbuf); /* read routines & macros */ /* ---------------------- */ /* flush buffer */ -extern void dvb_ringbuffer_flush(dvb_ringbuffer_t *rbuf); +extern void dvb_ringbuffer_flush(struct dvb_ringbuffer *rbuf); /* flush buffer protected by spinlock and wake-up waiting task(s) */ -extern void dvb_ringbuffer_flush_spinlock_wakeup(dvb_ringbuffer_t *rbuf); +extern void dvb_ringbuffer_flush_spinlock_wakeup(struct dvb_ringbuffer *rbuf); /* peek at byte in the buffer */ #define DVB_RINGBUFFER_PEEK(rbuf,offs) \ @@ -106,7 +108,7 @@ ** specifies whether resides in user space ** returns number of bytes transferred or -EFAULT */ -extern ssize_t dvb_ringbuffer_read(dvb_ringbuffer_t *rbuf, u8 *buf, +extern ssize_t dvb_ringbuffer_read(struct dvb_ringbuffer *rbuf, u8 *buf, size_t len, int usermem); @@ -121,7 +123,7 @@ ** specifies whether resides in user space ** returns number of bytes transferred or -EFAULT */ -extern ssize_t dvb_ringbuffer_write(dvb_ringbuffer_t *rbuf, const u8 *buf, +extern ssize_t dvb_ringbuffer_write(struct dvb_ringbuffer *rbuf, const u8 *buf, size_t len, int usermem); #endif /* _DVB_RINGBUFFER_H_ */ diff -Nru a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c --- a/drivers/media/dvb/dvb-core/dvbdev.c Tue Jul 1 18:44:33 2003 +++ b/drivers/media/dvb/dvb-core/dvbdev.c Tue Jul 1 18:44:33 2003 @@ -21,26 +21,19 @@ * */ -#include -#include -#include #include +#include +#include +#include #include #include -#include -#include -#include #include -#include -#include -#include #include +#include +#include #include "dvbdev.h" - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) - #include "compat.h" -#endif +#include "dvb_functions.h" static int dvbdev_debug = 0; #define dprintk if (dvbdev_debug) printk @@ -58,8 +51,7 @@ #define DVB_MAX_IDS 4 #define nums2minor(num,type,id) ((num << 6) | (id << 4) | type) -static -struct dvb_device* dvbdev_find_device (int minor) +static struct dvb_device* dvbdev_find_device (int minor) { struct list_head *entry; @@ -79,8 +71,7 @@ } -static -int dvb_device_open(struct inode *inode, struct file *file) +static int dvb_device_open(struct inode *inode, struct file *file) { struct dvb_device *dvbdev; @@ -164,8 +155,7 @@ } -static -int dvbdev_get_free_id (struct dvb_adapter *adap, int type) +static int dvbdev_get_free_id (struct dvb_adapter *adap, int type) { u32 id = 0; @@ -188,8 +178,8 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, const struct dvb_device *template, void *priv, int type) { - u32 id; struct dvb_device *dvbdev; + int id; if (down_interruptible (&dvbdev_register_lock)) return -ERESTARTSYS; @@ -241,8 +231,7 @@ } -static -int dvbdev_get_free_adapter_num (void) +static int dvbdev_get_free_adapter_num (void) { int num = 0; @@ -284,10 +273,6 @@ memset (adap, 0, sizeof(struct dvb_adapter)); INIT_LIST_HEAD (&adap->device_list); - /* fixme: is this correct? */ - /* No */ - try_module_get(THIS_MODULE); - printk ("DVB: registering new adapter (%s).\n", name); devfs_mk_dir("dvb/adapter%d", num); @@ -310,15 +295,11 @@ list_del (&adap->list_head); up (&dvbdev_register_lock); kfree (adap); - /* fixme: is this correct? */ - /* No. */ - module_put(THIS_MODULE); return 0; } -static -int __init init_dvbdev(void) +static int __init init_dvbdev(void) { devfs_mk_dir("dvb"); @@ -331,8 +312,7 @@ } -static -void __exit exit_dvbdev(void) +static void __exit exit_dvbdev(void) { unregister_chrdev(DVB_MAJOR, "DVB"); devfs_remove("dvb"); diff -Nru a/drivers/media/dvb/dvb-core/dvbdev.h b/drivers/media/dvb/dvb-core/dvbdev.h --- a/drivers/media/dvb/dvb-core/dvbdev.h Tue Jul 1 18:44:34 2003 +++ b/drivers/media/dvb/dvb-core/dvbdev.h Tue Jul 1 18:44:34 2003 @@ -25,8 +25,8 @@ #define _DVBDEV_H_ #include -#include #include +#include #include #include @@ -84,9 +84,5 @@ extern int dvb_generic_release (struct inode *inode, struct file *file); extern int dvb_generic_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); -int dvb_usercopy(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg, - int (*func)(struct inode *inode, struct file *file, - unsigned int cmd, void *arg)); #endif /* #ifndef _DVBDEV_H_ */ diff -Nru a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig --- a/drivers/media/dvb/frontends/Kconfig Tue Jul 1 18:44:32 2003 +++ b/drivers/media/dvb/frontends/Kconfig Tue Jul 1 18:44:32 2003 @@ -5,10 +5,9 @@ tristate "STV0299 based DVB-S frontend (QPSK)" depends on DVB_CORE help - A DVB-S tuner module. - - Say Y when you want to support frontend based on this - demodulator. + The stv0299 by ST is used in many DVB-S tuner modules, + say Y when you want to support frontends based on this + DVB-S demodulator. Some examples are the Alps BSRU6, the Philips SU1278 and the LG TDQB-S00x. @@ -61,6 +60,17 @@ If you don't know what tuner module is soldered on your DVB adapter simply enable all supported frontends, the + right one will get autodetected. + +config DVB_CX24110 + tristate "Frontends with Connexant CX24110 demodulator (QPSK)" + depends on DVB_CORE + help + The CX24110 Demodulator is used in some DVB-S frontends. + Say Y if you want support for this chip in your kernel. + + If you don't know what tuner module is soldered on your + DVB adapter simply enable all supported frontends, the right one will get autodetected. config DVB_GRUNDIG_29504_491 diff -Nru a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile --- a/drivers/media/dvb/frontends/Makefile Tue Jul 1 18:44:31 2003 +++ b/drivers/media/dvb/frontends/Makefile Tue Jul 1 18:44:31 2003 @@ -9,6 +9,7 @@ obj-$(CONFIG_DVB_ALPS_TDLB7) += alps_tdlb7.o obj-$(CONFIG_DVB_ALPS_TDMB7) += alps_tdmb7.o obj-$(CONFIG_DVB_ATMEL_AT76C651) += at76c651.o +obj-$(CONFIG_DVB_CX24110) += cx24110.o obj-$(CONFIG_DVB_GRUNDIG_29504_491) += grundig_29504-491.o obj-$(CONFIG_DVB_GRUNDIG_29504_401) += grundig_29504-401.o obj-$(CONFIG_DVB_VES1820) += ves1820.o diff -Nru a/drivers/media/dvb/frontends/alps_bsrv2.c b/drivers/media/dvb/frontends/alps_bsrv2.c --- a/drivers/media/dvb/frontends/alps_bsrv2.c Tue Jul 1 18:44:32 2003 +++ b/drivers/media/dvb/frontends/alps_bsrv2.c Tue Jul 1 18:44:32 2003 @@ -20,8 +20,11 @@ */ +#include #include #include +#include +#include #include "dvb_frontend.h" @@ -29,19 +32,18 @@ #define dprintk if (debug) printk -static -struct dvb_frontend_info bsrv2_info = { - name: "Alps BSRV2", - type: FE_QPSK, - frequency_min: 950000, - frequency_max: 2150000, - frequency_stepsize: 250, /* kHz for QPSK frontends */ - frequency_tolerance: 29500, - symbol_rate_min: 1000000, - symbol_rate_max: 45000000, -/* symbol_rate_tolerance: ???,*/ - notifier_delay: 50, /* 1/20 s */ - caps: FE_CAN_INVERSION_AUTO | +static struct dvb_frontend_info bsrv2_info = { + .name = "Alps BSRV2", + .type = FE_QPSK, + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_stepsize = 250, /* kHz for QPSK frontends */ + .frequency_tolerance = 29500, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, +/* . symbol_rate_tolerance = ???,*/ + .notifier_delay = 50, /* 1/20 s */ + .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | FE_CAN_QPSK @@ -49,8 +51,7 @@ -static -u8 init_1893_tab [] = { +static u8 init_1893_tab [] = { 0x01, 0xA4, 0x35, 0x81, 0x2A, 0x0d, 0x55, 0xC4, 0x09, 0x69, 0x00, 0x86, 0x4c, 0x28, 0x7F, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -61,8 +62,7 @@ }; -static -u8 init_1893_wtab[] = +static u8 init_1893_wtab[] = { 1,1,1,1,1,1,1,1, 1,1,0,0,1,1,0,0, 0,1,0,0,0,0,0,0, 1,0,1,1,0,0,0,1, @@ -71,11 +71,10 @@ }; -static -int ves1893_writereg (struct dvb_i2c_bus *i2c, u8 reg, u8 data) +static int ves1893_writereg (struct dvb_i2c_bus *i2c, u8 reg, u8 data) { u8 buf [] = { 0x00, reg, data }; - struct i2c_msg msg = { addr: 0x08, flags: 0, buf: buf, len: 3 }; + struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = buf, .len = 3 }; int err; if ((err = i2c->xfer (i2c, &msg, 1)) != 1) { @@ -87,14 +86,13 @@ } -static -u8 ves1893_readreg (struct dvb_i2c_bus *i2c, u8 reg) +static u8 ves1893_readreg (struct dvb_i2c_bus *i2c, u8 reg) { int ret; u8 b0 [] = { 0x00, reg }; u8 b1 [] = { 0 }; - struct i2c_msg msg [] = { { addr: 0x08, flags: 0, buf: b0, len: 2 }, - { addr: 0x08, flags: I2C_M_RD, buf: b1, len: 1 } }; + struct i2c_msg msg [] = { { .addr = 0x08, .flags = 0, .buf = b0, .len = 2 }, + { .addr = 0x08, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; ret = i2c->xfer (i2c, msg, 2); @@ -105,11 +103,10 @@ } -static -int sp5659_write (struct dvb_i2c_bus *i2c, u8 data [4]) +static int sp5659_write (struct dvb_i2c_bus *i2c, u8 data [4]) { int ret; - struct i2c_msg msg = { addr: 0x61, flags: 0, buf: data, len: 4 }; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = 4 }; ret = i2c->xfer (i2c, &msg, 1); @@ -125,8 +122,7 @@ * set up the downconverter frequency divisor for a * reference clock comparision frequency of 125 kHz. */ -static -int sp5659_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq, u8 pwr) +static int sp5659_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq, u8 pwr) { u32 div = (freq + 479500) / 125; u8 buf [4] = { (div >> 8) & 0x7f, div & 0xff, 0x95, (pwr << 5) | 0x30 }; @@ -135,8 +131,7 @@ } -static -int ves1893_init (struct dvb_i2c_bus *i2c) +static int ves1893_init (struct dvb_i2c_bus *i2c) { int i; @@ -150,8 +145,7 @@ } -static -int ves1893_clr_bit (struct dvb_i2c_bus *i2c) +static int ves1893_clr_bit (struct dvb_i2c_bus *i2c) { ves1893_writereg (i2c, 0, init_1893_tab[0] & 0xfe); ves1893_writereg (i2c, 0, init_1893_tab[0]); @@ -160,8 +154,7 @@ } -static -int ves1893_set_inversion (struct dvb_i2c_bus *i2c, fe_spectral_inversion_t inversion) +static int ves1893_set_inversion (struct dvb_i2c_bus *i2c, fe_spectral_inversion_t inversion) { u8 val; @@ -183,8 +176,7 @@ } -static -int ves1893_set_fec (struct dvb_i2c_bus *i2c, fe_code_rate_t fec) +static int ves1893_set_fec (struct dvb_i2c_bus *i2c, fe_code_rate_t fec) { if (fec == FEC_AUTO) return ves1893_writereg (i2c, 0x0d, 0x08); @@ -195,15 +187,13 @@ } -static -fe_code_rate_t ves1893_get_fec (struct dvb_i2c_bus *i2c) +static fe_code_rate_t ves1893_get_fec (struct dvb_i2c_bus *i2c) { return FEC_1_2 + ((ves1893_readreg (i2c, 0x0d) >> 4) & 0x7); } -static -int ves1893_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate) +static int ves1893_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate) { u32 BDR; u32 ratio; @@ -211,7 +201,7 @@ u32 BDRI; u32 tmp; - dprintk("%s: srate == %d\n", __FUNCTION__, srate); + dprintk("%s: srate == %ud\n", __FUNCTION__, (unsigned int) srate); if (srate > 90100000UL/2) srate = 90100000UL/2; @@ -257,9 +247,9 @@ BDRI = ( ((FIN << 8) / ((srate << (FNR >> 1)) >> 2)) + 1) >> 1; dprintk("FNR= %d\n", FNR); - dprintk("ratio= %08x\n", ratio); - dprintk("BDR= %08x\n", BDR); - dprintk("BDRI= %02x\n", BDRI); + dprintk("ratio= %08x\n", (unsigned int) ratio); + dprintk("BDR= %08x\n", (unsigned int) BDR); + dprintk("BDRI= %02x\n", (unsigned int) BDRI); if (BDRI > 0xff) BDRI = 0xff; @@ -286,22 +276,22 @@ } -static -int ves1893_set_voltage (struct dvb_i2c_bus *i2c, fe_sec_voltage_t voltage) +static int ves1893_set_voltage (struct dvb_i2c_bus *i2c, fe_sec_voltage_t voltage) { switch (voltage) { case SEC_VOLTAGE_13: return ves1893_writereg (i2c, 0x1f, 0x20); case SEC_VOLTAGE_18: return ves1893_writereg (i2c, 0x1f, 0x30); + case SEC_VOLTAGE_OFF: + return ves1893_writereg (i2c, 0x1f, 0x00); default: return -EINVAL; } } -static -int bsrv2_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) +static int bsrv2_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) { struct dvb_i2c_bus *i2c = fe->i2c; @@ -387,12 +377,12 @@ case FE_GET_FRONTEND: { struct dvb_frontend_parameters *p = arg; - s32 afc; + int afc; afc = ((int)((char)(ves1893_readreg (i2c, 0x0a) << 1)))/2; - afc = (afc * (int)(p->u.qpsk.symbol_rate/8))/16; + afc = (afc * (int)(p->u.qpsk.symbol_rate/1000/8))/16; - p->frequency += afc; + p->frequency -= afc; p->inversion = (ves1893_readreg (i2c, 0x0f) & 2) ? INVERSION_ON : INVERSION_OFF; p->u.qpsk.fec_inner = ves1893_get_fec (i2c); @@ -425,8 +415,7 @@ } -static -int bsrv2_attach (struct dvb_i2c_bus *i2c) +static int bsrv2_attach (struct dvb_i2c_bus *i2c) { if ((ves1893_readreg (i2c, 0x1e) & 0xf0) != 0xd0) return -ENODEV; @@ -437,22 +426,19 @@ } -static -void bsrv2_detach (struct dvb_i2c_bus *i2c) +static void bsrv2_detach (struct dvb_i2c_bus *i2c) { dvb_unregister_frontend (bsrv2_ioctl, i2c); } -static -int __init init_bsrv2 (void) +static int __init init_bsrv2 (void) { return dvb_register_i2c_device (THIS_MODULE, bsrv2_attach, bsrv2_detach); } -static -void __exit exit_bsrv2 (void) +static void __exit exit_bsrv2 (void) { dvb_unregister_i2c_device (bsrv2_attach); } diff -Nru a/drivers/media/dvb/frontends/alps_tdlb7.c b/drivers/media/dvb/frontends/alps_tdlb7.c --- a/drivers/media/dvb/frontends/alps_tdlb7.c Tue Jul 1 18:44:33 2003 +++ b/drivers/media/dvb/frontends/alps_tdlb7.c Tue Jul 1 18:44:33 2003 @@ -70,31 +70,29 @@ static int errno; -static -struct dvb_frontend_info tdlb7_info = { - name: "Alps TDLB7", - type: FE_OFDM, - frequency_min: 470000000, - frequency_max: 860000000, - frequency_stepsize: 166666, +static struct dvb_frontend_info tdlb7_info = { + .name = "Alps TDLB7", + .type = FE_OFDM, + .frequency_min = 470000000, + .frequency_max = 860000000, + .frequency_stepsize = 166666, #if 0 - frequency_tolerance: ???, - symbol_rate_min: ???, - symbol_rate_max: ???, - symbol_rate_tolerance: ???, - notifier_delay: 0, + .frequency_tolerance = ???, + .symbol_rate_min = ???, + .symbol_rate_max = ???, + .symbol_rate_tolerance = ???, + .notifier_delay = 0, #endif - caps: FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 }; -static -int sp8870_writereg (struct dvb_i2c_bus *i2c, u16 reg, u16 data) +static int sp8870_writereg (struct dvb_i2c_bus *i2c, u16 reg, u16 data) { u8 buf [] = { reg >> 8, reg & 0xff, data >> 8, data & 0xff }; - struct i2c_msg msg = { addr: 0x71, flags: 0, buf: buf, len: 4 }; + struct i2c_msg msg = { .addr = 0x71, .flags = 0, .buf = buf, .len = 4 }; int err; if ((err = i2c->xfer (i2c, &msg, 1)) != 1) { @@ -106,14 +104,13 @@ } -static -u16 sp8870_readreg (struct dvb_i2c_bus *i2c, u16 reg) +static u16 sp8870_readreg (struct dvb_i2c_bus *i2c, u16 reg) { int ret; u8 b0 [] = { reg >> 8 , reg & 0xff }; u8 b1 [] = { 0, 0 }; - struct i2c_msg msg [] = { { addr: 0x71, flags: 0, buf: b0, len: 2 }, - { addr: 0x71, flags: I2C_M_RD, buf: b1, len: 2 } }; + struct i2c_msg msg [] = { { .addr = 0x71, .flags = 0, .buf = b0, .len = 2 }, + { .addr = 0x71, .flags = I2C_M_RD, .buf = b1, .len = 2 } }; ret = i2c->xfer (i2c, msg, 2); @@ -124,11 +121,10 @@ } -static -int sp5659_write (struct dvb_i2c_bus *i2c, u8 data [4]) +static int sp5659_write (struct dvb_i2c_bus *i2c, u8 data [4]) { int ret; - struct i2c_msg msg = { addr: 0x60, flags: 0, buf: data, len: 4 }; + struct i2c_msg msg = { .addr = 0x60, .flags = 0, .buf = data, .len = 4 }; ret = i2c->xfer (i2c, &msg, 1); @@ -139,8 +135,7 @@ } -static -int sp5659_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq) +static int sp5659_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq) { u32 div = (freq + 36200000) / 166666; u8 buf [4]; @@ -160,8 +155,7 @@ } -static -int sp8870_read_code(const char *fn, char **fp) +static int sp8870_read_code(const char *fn, char **fp) { int fd; loff_t l; @@ -197,8 +191,7 @@ } -static -int sp8870_load_code(struct dvb_i2c_bus *i2c) +static int sp8870_load_code(struct dvb_i2c_bus *i2c) { /* this takes a long time. is there a way to do it faster? */ char *lcode; @@ -245,8 +238,7 @@ }; -static -int sp8870_init (struct dvb_i2c_bus *i2c) +static int sp8870_init (struct dvb_i2c_bus *i2c) { dprintk ("%s\n", __FUNCTION__); @@ -285,8 +277,7 @@ } -static -int tdlb7_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) +static int tdlb7_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) { struct dvb_i2c_bus *i2c = fe->i2c; @@ -415,11 +406,10 @@ } -static -int tdlb7_attach (struct dvb_i2c_bus *i2c) +static int tdlb7_attach (struct dvb_i2c_bus *i2c) { - struct i2c_msg msg = { addr: 0x71, flags: 0, buf: NULL, len: 0 }; + struct i2c_msg msg = { .addr = 0x71, .flags = 0, .buf = NULL, .len = 0 }; dprintk ("%s\n", __FUNCTION__); @@ -440,8 +430,7 @@ } -static -void tdlb7_detach (struct dvb_i2c_bus *i2c) +static void tdlb7_detach (struct dvb_i2c_bus *i2c) { dprintk ("%s\n", __FUNCTION__); @@ -449,8 +438,7 @@ } -static -int __init init_tdlb7 (void) +static int __init init_tdlb7 (void) { dprintk ("%s\n", __FUNCTION__); @@ -458,8 +446,7 @@ } -static -void __exit exit_tdlb7 (void) +static void __exit exit_tdlb7 (void) { dprintk ("%s\n", __FUNCTION__); diff -Nru a/drivers/media/dvb/frontends/alps_tdmb7.c b/drivers/media/dvb/frontends/alps_tdmb7.c --- a/drivers/media/dvb/frontends/alps_tdmb7.c Tue Jul 1 18:44:33 2003 +++ b/drivers/media/dvb/frontends/alps_tdmb7.c Tue Jul 1 18:44:33 2003 @@ -20,47 +20,41 @@ */ +#include #include #include +#include +#include #include "dvb_frontend.h" +#include "dvb_functions.h" static int debug = 0; #define dprintk if (debug) printk -static -struct dvb_frontend_info tdmb7_info = { - name: "Alps TDMB7", - type: FE_OFDM, - frequency_min: 470000000, - frequency_max: 860000000, - frequency_stepsize: 166667, +static struct dvb_frontend_info tdmb7_info = { + .name = "Alps TDMB7", + .type = FE_OFDM, + .frequency_min = 470000000, + .frequency_max = 860000000, + .frequency_stepsize = 166667, #if 0 - frequency_tolerance: ???, - symbol_rate_min: ???, - symbol_rate_max: ???, - symbol_rate_tolerance: 500, /* ppm */ - notifier_delay: 0, + .frequency_tolerance = ???, + .symbol_rate_min = ???, + .symbol_rate_max = ???, + .symbol_rate_tolerance = 500, /* ppm */ + .notifier_delay = 0, #endif - caps: FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_CLEAN_SETUP | FE_CAN_RECOVER }; -static -inline void ddelay (int timeout) -{ - current->state=TASK_INTERRUPTIBLE; - schedule_timeout(timeout); -} - - -static -u8 init_tab [] = { +static u8 init_tab [] = { 0x04, 0x10, 0x05, 0x09, 0x06, 0x00, @@ -82,12 +76,11 @@ }; -static -int cx22700_writereg (struct dvb_i2c_bus *i2c, u8 reg, u8 data) +static int cx22700_writereg (struct dvb_i2c_bus *i2c, u8 reg, u8 data) { int ret; u8 buf [] = { reg, data }; - struct i2c_msg msg = { addr: 0x43, flags: 0, buf: buf, len: 2 }; + struct i2c_msg msg = { .addr = 0x43, .flags = 0, .buf = buf, .len = 2 }; dprintk ("%s\n", __FUNCTION__); @@ -101,14 +94,13 @@ } -static -u8 cx22700_readreg (struct dvb_i2c_bus *i2c, u8 reg) +static u8 cx22700_readreg (struct dvb_i2c_bus *i2c, u8 reg) { int ret; u8 b0 [] = { reg }; u8 b1 [] = { 0 }; - struct i2c_msg msg [] = { { addr: 0x43, flags: 0, buf: b0, len: 1 }, - { addr: 0x43, flags: I2C_M_RD, buf: b1, len: 1 } }; + struct i2c_msg msg [] = { { .addr = 0x43, .flags = 0, .buf = b0, .len = 1 }, + { .addr = 0x43, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; dprintk ("%s\n", __FUNCTION__); @@ -121,10 +113,9 @@ } -static -int pll_write (struct dvb_i2c_bus *i2c, u8 data [4]) +static int pll_write (struct dvb_i2c_bus *i2c, u8 data [4]) { - struct i2c_msg msg = { addr: 0x61, flags: 0, buf: data, len: 4 }; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = 4 }; int ret; cx22700_writereg (i2c, 0x0a, 0x00); /* open i2c bus switch */ @@ -142,8 +133,7 @@ * set up the downconverter frequency divisor for a * reference clock comparision frequency of 125 kHz. */ -static -int pll_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq) +static int pll_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq) { u32 div = (freq + 36166667) / 166667; #if 1 //ALPS_SETTINGS @@ -154,14 +144,13 @@ freq < 470000000 ? 0x42 : freq < 862000000 ? 0x41 : 0x81 }; #endif - dprintk ("%s: freq == %i, div == %i\n", __FUNCTION__, freq, div); + dprintk ("%s: freq == %i, div == %i\n", __FUNCTION__, (int) freq, (int) div); return pll_write (i2c, buf); } -static -int cx22700_init (struct dvb_i2c_bus *i2c) +static int cx22700_init (struct dvb_i2c_bus *i2c) { int i; @@ -170,7 +159,7 @@ cx22700_writereg (i2c, 0x00, 0x02); /* soft reset */ cx22700_writereg (i2c, 0x00, 0x00); - ddelay (HZ/100); + dvb_delay (HZ/100); for (i=0; ii2c; @@ -355,7 +340,7 @@ } case FE_READ_BER: - *((uint32_t*) arg) = cx22700_readreg (i2c, 0x0c) & 0x7f; + *((u32*) arg) = cx22700_readreg (i2c, 0x0c) & 0x7f; cx22700_writereg (i2c, 0x0c, 0x00); break; @@ -363,18 +348,18 @@ { u16 rs_ber = (cx22700_readreg (i2c, 0x0d) << 9) | (cx22700_readreg (i2c, 0x0e) << 1); - *((uint16_t*) arg) = ~rs_ber; + *((u16*) arg) = ~rs_ber; break; } case FE_READ_SNR: { u16 rs_ber = (cx22700_readreg (i2c, 0x0d) << 9) | (cx22700_readreg (i2c, 0x0e) << 1); - *((uint16_t*) arg) = ~rs_ber; + *((u16*) arg) = ~rs_ber; break; } case FE_READ_UNCORRECTED_BLOCKS: - *((uint32_t*) arg) = cx22700_readreg (i2c, 0x0f); + *((u32*) arg) = cx22700_readreg (i2c, 0x0f); cx22700_writereg (i2c, 0x0f, 0x00); break; @@ -417,10 +402,9 @@ -static -int tdmb7_attach (struct dvb_i2c_bus *i2c) +static int tdmb7_attach (struct dvb_i2c_bus *i2c) { - struct i2c_msg msg = { addr: 0x43, flags: 0, buf: NULL, len: 0 }; + struct i2c_msg msg = { .addr = 0x43, .flags = 0, .buf = NULL,. len = 0 }; dprintk ("%s\n", __FUNCTION__); @@ -433,8 +417,7 @@ } -static -void tdmb7_detach (struct dvb_i2c_bus *i2c) +static void tdmb7_detach (struct dvb_i2c_bus *i2c) { dprintk ("%s\n", __FUNCTION__); @@ -442,8 +425,7 @@ } -static -int __init init_tdmb7 (void) +static int __init init_tdmb7 (void) { dprintk ("%s\n", __FUNCTION__); @@ -451,8 +433,7 @@ } -static -void __exit exit_tdmb7 (void) +static void __exit exit_tdmb7 (void) { dprintk ("%s\n", __FUNCTION__); diff -Nru a/drivers/media/dvb/frontends/at76c651.c b/drivers/media/dvb/frontends/at76c651.c --- a/drivers/media/dvb/frontends/at76c651.c Tue Jul 1 18:44:37 2003 +++ b/drivers/media/dvb/frontends/at76c651.c Tue Jul 1 18:44:37 2003 @@ -22,11 +22,11 @@ * */ -#include #include -#include +#include +#include +#include #include -#include #if defined(__powerpc__) #include @@ -34,6 +34,7 @@ #include "dvb_frontend.h" #include "dvb_i2c.h" +#include "dvb_functions.h" static int debug = 0; @@ -67,14 +68,13 @@ FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO | FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | FE_CAN_QAM_128 | - FE_CAN_QAM_256, - /* FE_CAN_QAM_512 | FE_CAN_QAM_1024 | */ + FE_CAN_QAM_256 /* | FE_CAN_QAM_512 | FE_CAN_QAM_1024 */ | + FE_CAN_RECOVER | FE_CAN_CLEAN_SETUP | FE_CAN_MUTE_TS }; #if ! defined(__powerpc__) -static __inline__ int -__ilog2(unsigned long x) +static __inline__ int __ilog2(unsigned long x) { int i; @@ -88,13 +88,12 @@ } #endif -static int -at76c651_writereg(struct dvb_i2c_bus *i2c, u8 reg, u8 data) +static int at76c651_writereg(struct dvb_i2c_bus *i2c, u8 reg, u8 data) { int ret; u8 buf[] = { reg, data }; - struct i2c_msg msg = { addr:0x1a >> 1, flags:0, buf:buf, len:2 }; + struct i2c_msg msg = { .addr = 0x1a >> 1, .flags = 0, .buf = buf, .len = 2 }; ret = i2c->xfer(i2c, &msg, 1); @@ -103,21 +102,20 @@ "(reg == 0x%02x, val == 0x%02x, ret == %i)\n", __FUNCTION__, reg, data, ret); - mdelay(10); + dvb_delay(10); return (ret != 1) ? -EREMOTEIO : 0; } -static u8 -at76c651_readreg(struct dvb_i2c_bus *i2c, u8 reg) +static u8 at76c651_readreg(struct dvb_i2c_bus *i2c, u8 reg) { int ret; u8 b0[] = { reg }; u8 b1[] = { 0 }; - struct i2c_msg msg[] = { {addr: 0x1a >> 1, flags: 0, buf: b0, len:1}, - {addr: 0x1a >> 1, flags: I2C_M_RD, buf: b1, len:1} }; + struct i2c_msg msg[] = { {.addr = 0x1a >> 1, .flags = 0, .buf = b0, .len = 1}, + {.addr = 0x1a >> 1, .flags = I2C_M_RD, .buf = b1, .len = 1} }; ret = i2c->xfer(i2c, msg, 2); @@ -128,8 +126,7 @@ } -static int -at76c651_set_auto_config(struct dvb_i2c_bus *i2c) +static int at76c651_set_auto_config(struct dvb_i2c_bus *i2c) { at76c651_writereg(i2c, 0x06, 0x01); @@ -148,8 +145,7 @@ } -static int -at76c651_set_bbfreq(struct dvb_i2c_bus *i2c) +static int at76c651_set_bbfreq(struct dvb_i2c_bus *i2c) { at76c651_writereg(i2c, 0x04, 0x3f); @@ -159,24 +155,21 @@ } -static int -at76c651_reset(struct dvb_i2c_bus *i2c) +static int at76c651_reset(struct dvb_i2c_bus *i2c) { return at76c651_writereg(i2c, 0x07, 0x01); } -static int -at76c651_disable_interrupts(struct dvb_i2c_bus *i2c) +static int at76c651_disable_interrupts(struct dvb_i2c_bus *i2c) { return at76c651_writereg(i2c, 0x0b, 0x00); } -static int -at76c651_switch_tuner_i2c(struct dvb_i2c_bus *i2c, u8 enable) +static int at76c651_switch_tuner_i2c(struct dvb_i2c_bus *i2c, u8 enable) { if (enable) @@ -186,13 +179,12 @@ } -static int -dat7021_write(struct dvb_i2c_bus *i2c, u32 tw) +static int dat7021_write(struct dvb_i2c_bus *i2c, u32 tw) { int ret; struct i2c_msg msg = - { addr:0xc2 >> 1, flags:0, buf:(u8 *) & tw, len:sizeof (tw) }; + { .addr = 0xc2 >> 1, .flags = 0, .buf = (u8 *) & tw, .len = sizeof (tw) }; at76c651_switch_tuner_i2c(i2c, 1); @@ -209,8 +201,7 @@ } -static int -dat7021_set_tv_freq(struct dvb_i2c_bus *i2c, u32 freq) +static int dat7021_set_tv_freq(struct dvb_i2c_bus *i2c, u32 freq) { u32 dw; @@ -238,8 +229,7 @@ } -static int -at76c651_set_symbolrate(struct dvb_i2c_bus *i2c, u32 symbolrate) +static int at76c651_set_symbolrate(struct dvb_i2c_bus *i2c, u32 symbolrate) { u8 exponent; @@ -265,8 +255,7 @@ } -static int -at76c651_set_qam(struct dvb_i2c_bus *i2c, fe_modulation_t qam) +static int at76c651_set_qam(struct dvb_i2c_bus *i2c, fe_modulation_t qam) { u8 qamsel = 0; @@ -308,8 +297,7 @@ } -static int -at76c651_set_inversion(struct dvb_i2c_bus *i2c, +static int at76c651_set_inversion(struct dvb_i2c_bus *i2c, fe_spectral_inversion_t inversion) { @@ -337,8 +325,7 @@ } -static int -at76c651_set_parameters(struct dvb_i2c_bus *i2c, +static int at76c651_set_parameters(struct dvb_i2c_bus *i2c, struct dvb_frontend_parameters *p) { @@ -351,8 +338,7 @@ } -static int -at76c651_set_defaults(struct dvb_i2c_bus *i2c) +static int at76c651_set_defaults(struct dvb_i2c_bus *i2c) { at76c651_set_symbolrate(i2c, 6900000); @@ -365,8 +351,7 @@ } -static int -at76c651_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) +static int at76c651_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg) { switch (cmd) { @@ -462,8 +447,7 @@ } -static int -at76c651_attach(struct dvb_i2c_bus *i2c) +static int at76c651_attach(struct dvb_i2c_bus *i2c) { if (at76c651_readreg(i2c, 0x0e) != 0x65) { @@ -502,8 +486,7 @@ } -static void -at76c651_detach(struct dvb_i2c_bus *i2c) +static void at76c651_detach(struct dvb_i2c_bus *i2c) { dvb_unregister_frontend(at76c651_ioctl, i2c); @@ -512,8 +495,7 @@ } -static int __init -at76c651_init(void) +static int __init at76c651_init(void) { return dvb_register_i2c_device(THIS_MODULE, at76c651_attach, @@ -521,8 +503,7 @@ } -static void __exit -at76c651_exit(void) +static void __exit at76c651_exit(void) { dvb_unregister_i2c_device(at76c651_attach); diff -Nru a/drivers/media/dvb/frontends/cx24110.c b/drivers/media/dvb/frontends/cx24110.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/media/dvb/frontends/cx24110.c Tue Jul 1 18:44:39 2003 @@ -0,0 +1,686 @@ +/* + cx24110 - Single Chip Satellite Channel Receiver driver module + used on the the Pinnacle PCTV Sat cards + + Copyright (C) 2002 Peter Hettkamp based on + work + Copyright (C) 1999 Convergence Integrated Media GmbH + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +/* currently drives the Conexant cx24110 and cx24106 QPSK decoder chips, + connected via i2c to a Conexant Fusion 878 (this uses the standard + linux bttv driver). The tuner chip is supposed to be the Conexant + cx24108 digital satellite tuner, driven through the tuner interface + of the cx24110. SEC is also supplied by the cx24110. + + Oct-2002: Migrate to API V3 (formerly known as NEWSTRUCT) +*/ + +#include +#include +#include +#include + +#include "dvb_frontend.h" +#include "dvb_functions.h" + +static int debug = 0; +#define dprintk if (debug) printk + + +static struct dvb_frontend_info cx24110_info = { + .name = "Conexant CX24110 with CX24108 tuner, aka HM1221/HM1811", + .type = FE_QPSK, + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_stepsize = 1011, /* kHz for QPSK frontends, can be reduced + to 253kHz on the cx24108 tuner */ + .frequency_tolerance = 29500, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, +/* .symbol_rate_tolerance = ???,*/ + .notifier_delay = 50, /* 1/20 s */ + .caps = FE_CAN_INVERSION_AUTO | + FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | + FE_CAN_QPSK | + FE_CAN_CLEAN_SETUP +}; +/* fixme: are these values correct? especially ..._tolerance and caps */ + + +static struct {u8 reg; u8 data;} cx24110_regdata[]= + /* Comments beginning with @ denote this value should + be the default */ + {{0x09,0x01}, /* SoftResetAll */ + {0x09,0x00}, /* release reset */ + {0x01,0xe8}, /* MSB of code rate 27.5MS/s */ + {0x02,0x17}, /* middle byte " */ + {0x03,0x29}, /* LSB " */ + {0x05,0x03}, /* @ DVB mode, standard code rate 3/4 */ + {0x06,0xa5}, /* @ PLL 60MHz */ + {0x07,0x01}, /* @ Fclk, i.e. sampling clock, 60MHz */ + {0x0a,0x00}, /* @ partial chip disables, do not set */ + {0x0b,0x01}, /* set output clock in gapped mode, start signal low + active for first byte */ + {0x0c,0x11}, /* no parity bytes, large hold time, serial data out */ + {0x0d,0x6f}, /* @ RS Sync/Unsync thresholds */ + {0x10,0x40}, /* chip doc is misleading here: write bit 6 as 1 + to avoid starting the BER counter. Reset the + CRC test bit. Finite counting selected */ + {0x15,0xff}, /* @ size of the limited time window for RS BER + estimation. It is *256 RS blocks, this + gives approx. 2.6 sec at 27.5MS/s, rate 3/4 */ + {0x16,0x00}, /* @ enable all RS output ports */ + {0x17,0x04}, /* @ time window allowed for the RS to sync */ + {0x18,0xae}, /* @ allow all standard DVB code rates to be scanned + for automatically */ + /* leave the current code rate and normalization + registers as they are after reset... */ + {0x21,0x10}, /* @ during AutoAcq, search each viterbi setting + only once */ + {0x23,0x18}, /* @ size of the limited time window for Viterbi BER + estimation. It is *65536 channel bits, i.e. + approx. 38ms at 27.5MS/s, rate 3/4 */ + {0x24,0x24}, /* do not trigger Viterbi CRC test. Finite count window */ + /* leave front-end AGC parameters at default values */ + /* leave decimation AGC parameters at default values */ + {0x35,0x40}, /* disable all interrupts. They are not connected anyway */ + {0x36,0xff}, /* clear all interrupt pending flags */ + {0x37,0x00}, /* @ fully enable AutoAcqq state machine */ + {0x38,0x07}, /* @ enable fade recovery, but not autostart AutoAcq */ + /* leave the equalizer parameters on their default values */ + /* leave the final AGC parameters on their default values */ + {0x41,0x00}, /* @ MSB of front-end derotator frequency */ + {0x42,0x00}, /* @ middle bytes " */ + {0x43,0x00}, /* @ LSB " */ + /* leave the carrier tracking loop parameters on default */ + /* leave the bit timing loop parameters at gefault */ + {0x56,0x4d}, /* set the filtune voltage to 2.7V, as recommended by */ + /* the cx24108 data sheet for symbol rates above 15MS/s */ + {0x57,0x00}, /* @ Filter sigma delta enabled, positive */ + {0x61,0x95}, /* GPIO pins 1-4 have special function */ + {0x62,0x05}, /* GPIO pin 5 has special function, pin 6 is GPIO */ + {0x63,0x00}, /* All GPIO pins use CMOS output characteristics */ + {0x64,0x20}, /* GPIO 6 is input, all others are outputs */ + {0x6d,0x30}, /* tuner auto mode clock freq 62kHz */ + {0x70,0x15}, /* use auto mode, tuner word is 21 bits long */ + {0x73,0x00}, /* @ disable several demod bypasses */ + {0x74,0x00}, /* @ " */ + {0x75,0x00} /* @ " */ + /* the remaining registers are for SEC */ + }; + + +static int cx24110_writereg (struct dvb_i2c_bus *i2c, int reg, int data) +{ + u8 buf [] = { reg, data }; + struct i2c_msg msg = { .addr = 0x55, .flags = 0, .buf = buf, .len = 2 }; +/* fixme (medium): HW allows any i2c address. 0x55 is the default, but the + cx24110 might show up at any address */ + int err; + + if ((err = i2c->xfer (i2c, &msg, 1)) != 1) { + dprintk ("%s: writereg error (err == %i, reg == 0x%02x, data == 0x%02x)\n", __FUNCTION__, err, reg, data); + return -EREMOTEIO; + } + + return 0; +} + + +static u8 cx24110_readreg (struct dvb_i2c_bus *i2c, u8 reg) +{ + int ret; + u8 b0 [] = { reg }; + u8 b1 [] = { 0 }; + struct i2c_msg msg [] = { { .addr = 0x55, .flags = 0, .buf = b0, .len = 1 }, + { .addr = 0x55, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; +/* fixme (medium): address might be different from 0x55 */ + ret = i2c->xfer (i2c, msg, 2); + + if (ret != 2) + dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); + + return b1[0]; +} + + +static int cx24108_write (struct dvb_i2c_bus *i2c, u32 data) +{ +/* tuner data is 21 bits long, must be left-aligned in data */ +/* tuner cx24108 is written through a dedicated 3wire interface on the demod chip */ +/* FIXME (low): add error handling, avoid infinite loops if HW fails... */ + +dprintk("cx24110 debug: cx24108_write(%8.8x)\n",data); + + cx24110_writereg(i2c,0x6d,0x30); /* auto mode at 62kHz */ + cx24110_writereg(i2c,0x70,0x15); /* auto mode 21 bits */ + /* if the auto tuner writer is still busy, clear it out */ + while (cx24110_readreg(i2c,0x6d)&0x80) + cx24110_writereg(i2c,0x72,0); + /* write the topmost 8 bits */ + cx24110_writereg(i2c,0x72,(data>>24)&0xff); + /* wait for the send to be completed */ + while ((cx24110_readreg(i2c,0x6d)&0xc0)==0x80) + ; + /* send another 8 bytes */ + cx24110_writereg(i2c,0x72,(data>>16)&0xff); + while ((cx24110_readreg(i2c,0x6d)&0xc0)==0x80) + ; + /* and the topmost 5 bits of this byte */ + cx24110_writereg(i2c,0x72,(data>>8)&0xff); + while ((cx24110_readreg(i2c,0x6d)&0xc0)==0x80) + ; + /* now strobe the enable line once */ + cx24110_writereg(i2c,0x6d,0x32); + cx24110_writereg(i2c,0x6d,0x30); + + return 0; +} + + +static int cx24108_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq) +{ +/* fixme (low): error handling */ + int i, a, n, pump; + u32 band, pll; + + + static const u32 osci[]={ 950000,1019000,1075000,1178000, + 1296000,1432000,1576000,1718000, + 1856000,2036000,2150000}; + static const u32 bandsel[]={0,0x00020000,0x00040000,0x00100800, + 0x00101000,0x00102000,0x00104000, + 0x00108000,0x00110000,0x00120000, + 0x00140000}; + +#define XTAL 1011100 /* Hz, really 1.0111 MHz and a /10 prescaler */ + dprintk("cx24110 debug: cx24108_set_tv_freq, freq=%d\n",freq); + + if (freq<950000) + freq=950000; /* kHz */ + if (freq>2150000) + freq=2150000; /* satellite IF is 950..2150MHz */ + /* decide which VCO to use for the input frequency */ + for (i=1;(iFEC_AUTO) + fec=FEC_AUTO; + + if (fec==FEC_AUTO) { /* (re-)establish AutoAcq behaviour */ + cx24110_writereg(i2c,0x37,cx24110_readreg(i2c,0x37)&0xdf); + /* clear AcqVitDis bit */ + cx24110_writereg(i2c,0x18,0xae); + /* allow all DVB standard code rates */ + cx24110_writereg(i2c,0x05,(cx24110_readreg(i2c,0x05)&0xf0)|0x3); + /* set nominal Viterbi rate 3/4 */ + cx24110_writereg(i2c,0x22,(cx24110_readreg(i2c,0x22)&0xf0)|0x3); + /* set current Viterbi rate 3/4 */ + cx24110_writereg(i2c,0x1a,0x05); cx24110_writereg(i2c,0x1b,0x06); + /* set the puncture registers for code rate 3/4 */ + return 0; + } else { + cx24110_writereg(i2c,0x37,cx24110_readreg(i2c,0x37)|0x20); + /* set AcqVitDis bit */ + if(rate[fec]>0) { + cx24110_writereg(i2c,0x05,(cx24110_readreg(i2c,0x05)&0xf0)|rate[fec]); + /* set nominal Viterbi rate */ + cx24110_writereg(i2c,0x22,(cx24110_readreg(i2c,0x22)&0xf0)|rate[fec]); + /* set current Viterbi rate */ + cx24110_writereg(i2c,0x1a,g1[fec]); + cx24110_writereg(i2c,0x1b,g2[fec]); + /* not sure if this is the right way: I always used AutoAcq mode */ + } else + return -EOPNOTSUPP; +/* fixme (low): which is the correct return code? */ + }; + return 0; +} + + +static fe_code_rate_t cx24110_get_fec (struct dvb_i2c_bus *i2c) +{ + int i; + + i=cx24110_readreg(i2c,0x22)&0x0f; + if(!(i&0x08)) { + return FEC_1_2 + i - 1; + } else { +/* fixme (low): a special code rate has been selected. In theory, we need to + return a denominator value, a numerator value, and a pair of puncture + maps to correctly describe this mode. But this should never happen in + practice, because it cannot be set by cx24110_get_fec. */ + return FEC_NONE; + } +} + + +static int cx24110_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate) +{ +/* fixme (low): add error handling */ + u32 ratio; + u32 tmp, fclk, BDRI; + + static const u32 bands[]={5000000UL,15000000UL,90999000UL/2}; + static const u32 vca[]={0x80f03800,0x81f0f800,0x83f1f800}; + static const u32 vga[]={0x5f8fc000,0x580f0000,0x500c0000}; + static const u8 filtune[]={0xa2,0xcc,0x66}; + int i; + +dprintk("cx24110 debug: entering %s(%d)\n",__FUNCTION__,srate); + if (srate>90999000UL/2) + srate=90999000UL/2; + if (srate<500000) + srate=500000; + + for(i=0;(ibands[i]);i++) + ; + /* first, check which sample rate is appropriate: 45, 60 80 or 90 MHz, + and set the PLL accordingly (R07[1:0] Fclk, R06[7:4] PLLmult, + R06[3:0] PLLphaseDetGain */ + tmp=cx24110_readreg(i2c,0x07)&0xfc; + if(srate<90999000UL/4) { /* sample rate 45MHz*/ + cx24110_writereg(i2c,0x07,tmp); + cx24110_writereg(i2c,0x06,0x78); + fclk=90999000UL/2; + } else if(srate<60666000UL/2) { /* sample rate 60MHz */ + cx24110_writereg(i2c,0x07,tmp|0x1); + cx24110_writereg(i2c,0x06,0xa5); + fclk=60666000UL; + } else if(srate<80888000UL/2) { /* sample rate 80MHz */ + cx24110_writereg(i2c,0x07,tmp|0x2); + cx24110_writereg(i2c,0x06,0x87); + fclk=80888000UL; + } else { /* sample rate 90MHz */ + cx24110_writereg(i2c,0x07,tmp|0x3); + cx24110_writereg(i2c,0x06,0x78); + fclk=90999000UL; + }; + dprintk("cx24110 debug: fclk %d Hz\n",fclk); + /* we need to divide two integers with approx. 27 bits in 32 bit + arithmetic giving a 25 bit result */ + /* the maximum dividend is 90999000/2, 0x02b6446c, this number is + also the most complex divisor. Hence, the dividend has, + assuming 32bit unsigned arithmetic, 6 clear bits on top, the + divisor 2 unused bits at the bottom. Also, the quotient is + always less than 1/2. Borrowed from VES1893.c, of course */ + + tmp=srate<<6; + BDRI=fclk>>2; + ratio=(tmp/BDRI); + + tmp=(tmp%BDRI)<<8; + ratio=(ratio<<8)+(tmp/BDRI); + + tmp=(tmp%BDRI)<<8; + ratio=(ratio<<8)+(tmp/BDRI); + + tmp=(tmp%BDRI)<<1; + ratio=(ratio<<1)+(tmp/BDRI); + + dprintk("srate= %d (range %d, up to %d)\n", srate,i,bands[i]); + dprintk("fclk = %d\n", fclk); + dprintk("ratio= %08x\n", ratio); + + cx24110_writereg(i2c, 0x1, (ratio>>16)&0xff); + cx24110_writereg(i2c, 0x2, (ratio>>8)&0xff); + cx24110_writereg(i2c, 0x3, (ratio)&0xff); + + /* please see the cx24108 data sheet, this controls tuner gain + and bandwidth settings depending on the symbol rate */ + cx24108_write(i2c,vga[i]); + cx24108_write(i2c,vca[i]); /* gain is set on tuner chip */ + cx24110_writereg(i2c,0x56,filtune[i]); /* bw is contolled by filtune voltage */ + + return 0; + +} + + +static int cx24110_set_voltage (struct dvb_i2c_bus *i2c, fe_sec_voltage_t voltage) +{ + switch (voltage) { + case SEC_VOLTAGE_13: + return cx24110_writereg(i2c,0x76,(cx24110_readreg(i2c,0x76)&0x3b)|0xc0); + case SEC_VOLTAGE_18: + return cx24110_writereg(i2c,0x76,(cx24110_readreg(i2c,0x76)&0x3b)|0x40); + default: + return -EINVAL; + }; +} + +static void sendDiSEqCMessage(struct dvb_i2c_bus *i2c, struct dvb_diseqc_master_cmd *pCmd) +{ + int i, rv; + + for (i = 0; i < pCmd->msg_len; i++) + cx24110_writereg(i2c, 0x79 + i, pCmd->msg[i]); + + rv = cx24110_readreg(i2c, 0x76); + + cx24110_writereg(i2c, 0x76, ((rv & 0x90) | 0x40) | ((pCmd->msg_len-3) & 3)); + for (i=500; i-- > 0 && !(cx24110_readreg(i2c,0x76)&0x40);) + ; /* wait for LNB ready */ +} + + +static int cx24110_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) +{ + struct dvb_i2c_bus *i2c = fe->i2c; + static int lastber=0, lastbyer=0,lastbler=0, lastesn0=0, sum_bler=0; + + switch (cmd) { + case FE_GET_INFO: + memcpy (arg, &cx24110_info, sizeof(struct dvb_frontend_info)); + break; + + case FE_READ_STATUS: + { + fe_status_t *status = arg; + int sync = cx24110_readreg (i2c, 0x55); + + *status = 0; + + if (sync & 0x10) + *status |= FE_HAS_SIGNAL; + + if (sync & 0x08) + *status |= FE_HAS_CARRIER; + + sync = cx24110_readreg (i2c, 0x08); + + if (sync & 0x40) + *status |= FE_HAS_VITERBI; + + if (sync & 0x20) + *status |= FE_HAS_SYNC; + + if ((sync & 0x60) == 0x60) + *status |= FE_HAS_LOCK; + + if(cx24110_readreg(i2c,0x10)&0x40) { + /* the RS error counter has finished one counting window */ + cx24110_writereg(i2c,0x10,0x60); /* select the byer reg */ + lastbyer=cx24110_readreg(i2c,0x12)| + (cx24110_readreg(i2c,0x13)<<8)| + (cx24110_readreg(i2c,0x14)<<16); + cx24110_writereg(i2c,0x10,0x70); /* select the bler reg */ + lastbler=cx24110_readreg(i2c,0x12)| + (cx24110_readreg(i2c,0x13)<<8)| + (cx24110_readreg(i2c,0x14)<<16); + cx24110_writereg(i2c,0x10,0x20); /* start new count window */ + sum_bler += lastbler; + } + if(cx24110_readreg(i2c,0x24)&0x10) { + /* the Viterbi error counter has finished one counting window */ + cx24110_writereg(i2c,0x24,0x04); /* select the ber reg */ + lastber=cx24110_readreg(i2c,0x25)| + (cx24110_readreg(i2c,0x26)<<8); + cx24110_writereg(i2c,0x24,0x04); /* start new count window */ + cx24110_writereg(i2c,0x24,0x14); + } + if(cx24110_readreg(i2c,0x6a)&0x80) { + /* the Es/N0 error counter has finished one counting window */ + lastesn0=cx24110_readreg(i2c,0x69)| + (cx24110_readreg(i2c,0x68)<<8); + cx24110_writereg(i2c,0x6a,0x84); /* start new count window */ + } + break; + } + + case FE_READ_BER: + { + u32 *ber = (u32 *) arg; + + *ber = lastber; +/* fixme (maybe): value range is 16 bit. Scale? */ + break; + } + + case FE_READ_SIGNAL_STRENGTH: + { +/* no provision in hardware. Read the frontend AGC accumulator. No idea how to scale this, but I know it is 2s complement */ + u8 signal = cx24110_readreg (i2c, 0x27)+128; + *((u16*) arg) = (signal << 8) | signal; + break; + } + + case FE_READ_SNR: + { +/* no provision in hardware. Can be computed from the Es/N0 estimator, but I don't know how. */ + *(u16*) arg = lastesn0; + break; + } + + case FE_READ_UNCORRECTED_BLOCKS: + { + *(u16*) arg = sum_bler&0xffff; + sum_bler=0; + break; + } + + case FE_SET_FRONTEND: + { + struct dvb_frontend_parameters *p = arg; + + cx24108_set_tv_freq (i2c, p->frequency); + cx24110_set_inversion (i2c, p->inversion); + cx24110_set_fec (i2c, p->u.qpsk.fec_inner); + cx24110_set_symbolrate (i2c, p->u.qpsk.symbol_rate); + cx24110_writereg(i2c,0x04,0x05); /* start aquisition */ + break; + } + + case FE_GET_FRONTEND: + { + struct dvb_frontend_parameters *p = arg; + s32 afc; unsigned sclk; + +/* cannot read back tuner settings (freq). Need to have some private storage */ + + sclk = cx24110_readreg (i2c, 0x07) & 0x03; +/* ok, real AFC (FEDR) freq. is afc/2^24*fsamp, fsamp=45/60/80/90MHz. + * Need 64 bit arithmetic. Is thiss possible in the kernel? */ + if (sclk==0) sclk=90999000L/2L; + else if (sclk==1) sclk=60666000L; + else if (sclk==2) sclk=80888000L; + else sclk=90999000L; + sclk>>=8; + afc = sclk*(cx24110_readreg (i2c, 0x44)&0x1f)+ + ((sclk*cx24110_readreg (i2c, 0x45))>>8)+ + ((sclk*cx24110_readreg (i2c, 0x46))>>16); + + p->frequency += afc; + p->inversion = (cx24110_readreg (i2c, 0x22) & 0x10) ? + INVERSION_ON : INVERSION_OFF; + p->u.qpsk.fec_inner = cx24110_get_fec (i2c); + break; + } + + case FE_SLEEP: +/* cannot do this from the FE end. How to communicate this to the place where it can be done? */ + break; + case FE_INIT: + return cx24110_init (i2c); + + case FE_RESET: +/* no idea what to do for this call */ +/* fixme (medium): fill me in */ + break; + + case FE_SET_TONE: + return cx24110_writereg(i2c,0x76,(cx24110_readreg(i2c,0x76)&~0x10)|((((fe_sec_tone_mode_t) arg)==SEC_TONE_ON)?0x10:0)); + case FE_SET_VOLTAGE: + return cx24110_set_voltage (i2c, (fe_sec_voltage_t) arg); + + case FE_DISEQC_SEND_MASTER_CMD: + sendDiSEqCMessage(i2c, (struct dvb_diseqc_master_cmd*) arg); + return 0; + + default: + return -EOPNOTSUPP; + }; + + return 0; +} + + +static int cx24110_attach (struct dvb_i2c_bus *i2c) +{ + u8 sig; + + sig=cx24110_readreg (i2c, 0x00); + if ( sig != 0x5a && sig != 0x69 ) + return -ENODEV; + + dvb_register_frontend (cx24110_ioctl, i2c, NULL, &cx24110_info); + + return 0; +} + + +static void cx24110_detach (struct dvb_i2c_bus *i2c) +{ + dvb_unregister_frontend (cx24110_ioctl, i2c); +} + + +static int __init init_cx24110 (void) +{ + return dvb_register_i2c_device (THIS_MODULE, cx24110_attach, cx24110_detach); +} + + +static void __exit exit_cx24110 (void) +{ + dvb_unregister_i2c_device (cx24110_attach); +} + + +module_init(init_cx24110); +module_exit(exit_cx24110); + + +MODULE_DESCRIPTION("DVB Frontend driver module for the Conexant cx24108/cx24110 chipset"); +MODULE_AUTHOR("Peter Hettkamp"); +MODULE_LICENSE("GPL"); +MODULE_PARM(debug,"i"); + diff -Nru a/drivers/media/dvb/frontends/dvb_dummy_fe.c b/drivers/media/dvb/frontends/dvb_dummy_fe.c --- a/drivers/media/dvb/frontends/dvb_dummy_fe.c Tue Jul 1 18:44:33 2003 +++ b/drivers/media/dvb/frontends/dvb_dummy_fe.c Tue Jul 1 18:44:33 2003 @@ -30,26 +30,24 @@ /* depending on module parameter sct deliver different infos */ -static -struct dvb_frontend_info dvb_s_dummyfe_info = { - name: "DVB-S dummy frontend", - type: FE_QPSK, - frequency_min: 950000, - frequency_max: 2150000, - frequency_stepsize: 250, /* kHz for QPSK frontends */ - frequency_tolerance: 29500, - symbol_rate_min: 1000000, - symbol_rate_max: 45000000, -/* symbol_rate_tolerance: ???,*/ - notifier_delay: 50, /* 1/20 s */ - caps: FE_CAN_INVERSION_AUTO | +static struct dvb_frontend_info dvb_s_dummyfe_info = { + .name = "DVB-S dummy frontend", + .type = FE_QPSK, + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_stepsize = 250, /* kHz for QPSK frontends */ + .frequency_tolerance = 29500, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, +/* .symbol_rate_tolerance = ???,*/ + .notifier_delay = 50, /* 1/20 s */ + .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | FE_CAN_QPSK }; -static -struct dvb_frontend_info dvb_c_dummyfe_info = { +static struct dvb_frontend_info dvb_c_dummyfe_info = { .name = "DVB-C dummy frontend", .type = FE_QAM, .frequency_stepsize = 62500, @@ -58,9 +56,9 @@ .symbol_rate_min = (57840000/2)/64, /* SACLK/64 == (XIN/2)/64 */ .symbol_rate_max = (57840000/2)/4, /* SACLK/4 */ #if 0 - frequency_tolerance: ???, - symbol_rate_tolerance: ???, /* ppm */ /* == 8% (spec p. 5) */ - notifier_delay: ?, + .frequency_tolerance = ???, + .symbol_rate_tolerance = ???, /* ppm */ /* == 8% (spec p. 5) */ + .notifier_delay = ?, #endif .caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | FE_CAN_QAM_128 | FE_CAN_QAM_256 | @@ -103,8 +101,7 @@ } -static -int dvbdummyfe_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) +static int dvbdummyfe_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) { switch (cmd) { case FE_GET_INFO: @@ -176,23 +173,20 @@ } -static -int dvbdummyfe_attach (struct dvb_i2c_bus *i2c) +static int dvbdummyfe_attach (struct dvb_i2c_bus *i2c) { dvb_register_frontend (dvbdummyfe_ioctl, i2c, NULL, frontend_info()); return 0; } -static -void dvbdummyfe_detach (struct dvb_i2c_bus *i2c) +static void dvbdummyfe_detach (struct dvb_i2c_bus *i2c) { dvb_unregister_frontend (dvbdummyfe_ioctl, i2c); } -static -int __init init_dvbdummyfe (void) +static int __init init_dvbdummyfe (void) { return dvb_register_i2c_device (THIS_MODULE, dvbdummyfe_attach, @@ -201,8 +195,7 @@ } -static -void __exit exit_dvbdummyfe (void) +static void __exit exit_dvbdummyfe (void) { dvb_unregister_i2c_device (dvbdummyfe_attach); return; diff -Nru a/drivers/media/dvb/frontends/grundig_29504-401.c b/drivers/media/dvb/frontends/grundig_29504-401.c --- a/drivers/media/dvb/frontends/grundig_29504-401.c Tue Jul 1 18:44:32 2003 +++ b/drivers/media/dvb/frontends/grundig_29504-401.c Tue Jul 1 18:44:32 2003 @@ -22,10 +22,14 @@ */ -#include #include +#include +#include +#include +#include #include "dvb_frontend.h" +#include "dvb_functions.h" static int debug = 0; @@ -33,27 +37,26 @@ struct dvb_frontend_info grundig_29504_401_info = { - name: "Grundig 29504-401", - type: FE_OFDM, -/* frequency_min: ???,*/ -/* frequency_max: ???,*/ - frequency_stepsize: 166666, -/* frequency_tolerance: ???,*/ -/* symbol_rate_tolerance: ???,*/ - notifier_delay: 0, - caps: FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + .name = "Grundig 29504-401", + .type = FE_OFDM, +/* .frequency_min = ???,*/ +/* .frequency_max = ???,*/ + .frequency_stepsize = 166666, +/* .frequency_tolerance = ???,*/ +/* .symbol_rate_tolerance = ???,*/ + .notifier_delay = 0, + .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_MUTE_TS /*| FE_CAN_CLEAN_SETUP*/ }; -static -int l64781_writereg (struct dvb_i2c_bus *i2c, u8 reg, u8 data) +static int l64781_writereg (struct dvb_i2c_bus *i2c, u8 reg, u8 data) { int ret; u8 buf [] = { reg, data }; - struct i2c_msg msg = { addr: 0x55, flags: 0, buf: buf, len: 2 }; + struct i2c_msg msg = { .addr = 0x55, .flags = 0, .buf = buf, .len = 2 }; if ((ret = i2c->xfer (i2c, &msg, 1)) != 1) dprintk ("%s: write_reg error (reg == %02x) = %02x!\n", @@ -63,14 +66,13 @@ } -static -u8 l64781_readreg (struct dvb_i2c_bus *i2c, u8 reg) +static u8 l64781_readreg (struct dvb_i2c_bus *i2c, u8 reg) { int ret; u8 b0 [] = { reg }; u8 b1 [] = { 0 }; - struct i2c_msg msg [] = { { addr: 0x55, flags: 0, buf: b0, len: 1 }, - { addr: 0x55, flags: I2C_M_RD, buf: b1, len: 1 } }; + struct i2c_msg msg [] = { { .addr = 0x55, .flags = 0, .buf = b0, .len = 1 }, + { .addr = 0x55, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; ret = i2c->xfer (i2c, msg, 2); @@ -81,11 +83,10 @@ } -static -int tsa5060_write (struct dvb_i2c_bus *i2c, u8 data [4]) +static int tsa5060_write (struct dvb_i2c_bus *i2c, u8 data [4]) { int ret; - struct i2c_msg msg = { addr: 0x61, flags: 0, buf: data, len: 4 }; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = 4 }; if ((ret = i2c->xfer (i2c, &msg, 1)) != 1) dprintk ("%s: write_reg error == %02x!\n", __FUNCTION__, ret); @@ -97,29 +98,32 @@ /** * set up the downconverter frequency divisor for a * reference clock comparision frequency of 166666 Hz. - * frequency offset is 36000000 Hz. + * frequency offset is 36125000 Hz. */ -static -int tsa5060_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq) +static int tsa5060_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq) { u32 div; u8 buf [4]; - u8 cfg; + u8 cfg, cpump, band_select; - div = (36000000 + freq) / 166666; + div = (36125000 + freq) / 166666; cfg = 0x88; + cpump = div < 175000000 ? 2 : div < 390000000 ? 1 : + div < 470000000 ? 2 : div < 750000000 ? 1 : 3; + + band_select = div < 175000000 ? 0x0e : div < 470000000 ? 0x05 : 0x03; + buf [0] = (div >> 8) & 0x7f; buf [1] = div & 0xff; buf [2] = ((div >> 10) & 0x60) | cfg; - buf [3] = 0xc0; + buf [3] = cpump | band_select; return tsa5060_write (i2c, buf); } -static -void apply_tps (struct dvb_i2c_bus *i2c) +static void apply_tps (struct dvb_i2c_bus *i2c) { l64781_writereg (i2c, 0x2a, 0x00); l64781_writereg (i2c, 0x2a, 0x01); @@ -133,8 +137,7 @@ } -static -void reset_afc (struct dvb_i2c_bus *i2c) +static void reset_afc (struct dvb_i2c_bus *i2c) { /* Set AFC stall for the AFC_INIT_FRQ setting, TIM_STALL for timing offset */ @@ -152,8 +155,7 @@ } -static -int apply_frontend_param (struct dvb_i2c_bus *i2c, +static int apply_frontend_param (struct dvb_i2c_bus *i2c, struct dvb_frontend_parameters *param) { /* The coderates for FEC_NONE, FEC_4_5 and FEC_FEC_6_7 are arbitrary */ @@ -265,19 +267,17 @@ } -static -void reset_and_configure (struct dvb_i2c_bus *i2c) +static void reset_and_configure (struct dvb_i2c_bus *i2c) { u8 buf [] = { 0x06 }; - struct i2c_msg msg = { addr: 0x00, flags: 0, buf: buf, len: 1 }; + struct i2c_msg msg = { .addr = 0x00, .flags = 0, .buf = buf, .len = 1 }; i2c->xfer (i2c, &msg, 1); } -static -int init (struct dvb_i2c_bus *i2c) +static int init (struct dvb_i2c_bus *i2c) { reset_and_configure (i2c); @@ -415,13 +415,12 @@ } -static -int l64781_attach (struct dvb_i2c_bus *i2c) +static int l64781_attach (struct dvb_i2c_bus *i2c) { u8 b0 [] = { 0x1a }; u8 b1 [] = { 0x00 }; - struct i2c_msg msg [] = { { addr: 0x55, flags: 0, buf: b0, len: 1 }, - { addr: 0x55, flags: I2C_M_RD, buf: b1, len: 1 } }; + struct i2c_msg msg [] = { { .addr = 0x55, .flags = 0, .buf = b0, .len = 1 }, + { .addr = 0x55, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; if (i2c->xfer (i2c, msg, 2) == 2) /* probably an EEPROM... */ return -ENODEV; @@ -440,23 +439,20 @@ } -static -void l64781_detach (struct dvb_i2c_bus *i2c) +static void l64781_detach (struct dvb_i2c_bus *i2c) { dvb_unregister_frontend (grundig_29504_401_ioctl, i2c); } -static -int __init init_grundig_29504_401 (void) +static int __init init_grundig_29504_401 (void) { return dvb_register_i2c_device (THIS_MODULE, l64781_attach, l64781_detach); } -static -void __exit exit_grundig_29504_401 (void) +static void __exit exit_grundig_29504_401 (void) { dvb_unregister_i2c_device (l64781_attach); } diff -Nru a/drivers/media/dvb/frontends/grundig_29504-491.c b/drivers/media/dvb/frontends/grundig_29504-491.c --- a/drivers/media/dvb/frontends/grundig_29504-491.c Tue Jul 1 18:44:37 2003 +++ b/drivers/media/dvb/frontends/grundig_29504-491.c Tue Jul 1 18:44:37 2003 @@ -25,27 +25,30 @@ */ #include +#include #include +#include +#include #include "dvb_frontend.h" +#include "dvb_functions.h" static int debug = 0; #define dprintk if (debug) printk -static -struct dvb_frontend_info grundig_29504_491_info = { - name: "Grundig 29504-491, (TDA8083 based)", - type: FE_QPSK, - frequency_min: 950000, /* FIXME: guessed! */ - frequency_max: 1400000, /* FIXME: guessed! */ - frequency_stepsize: 125, /* kHz for QPSK frontends */ -/* frequency_tolerance: ???,*/ - symbol_rate_min: 1000000, /* FIXME: guessed! */ - symbol_rate_max: 45000000, /* FIXME: guessed! */ -/* symbol_rate_tolerance: ???,*/ - notifier_delay: 0, - caps: FE_CAN_INVERSION_AUTO | +static struct dvb_frontend_info grundig_29504_491_info = { + .name = "Grundig 29504-491, (TDA8083 based)", + .type = FE_QPSK, + .frequency_min = 950000, /* FIXME: guessed! */ + .frequency_max = 1400000, /* FIXME: guessed! */ + .frequency_stepsize = 125, /* kHz for QPSK frontends */ +/* .frequency_tolerance = ???,*/ + .symbol_rate_min = 1000000, /* FIXME: guessed! */ + .symbol_rate_max = 45000000, /* FIXME: guessed! */ +/* .symbol_rate_tolerance = ???,*/ + .notifier_delay = 0, + .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO | @@ -55,8 +58,7 @@ -static -u8 tda8083_init_tab [] = { +static u8 tda8083_init_tab [] = { 0x04, 0x00, 0x4a, 0x79, 0x04, 0x00, 0xff, 0xea, 0x48, 0x42, 0x79, 0x60, 0x70, 0x52, 0x9a, 0x10, 0x0e, 0x10, 0xf2, 0xa7, 0x93, 0x0b, 0x05, 0xc8, @@ -67,12 +69,11 @@ -static -int tda8083_writereg (struct dvb_i2c_bus *i2c, u8 reg, u8 data) +static int tda8083_writereg (struct dvb_i2c_bus *i2c, u8 reg, u8 data) { int ret; u8 buf [] = { reg, data }; - struct i2c_msg msg = { addr: 0x68, flags: 0, buf: buf, len: 2 }; + struct i2c_msg msg = { .addr = 0x68, .flags = 0, .buf = buf, .len = 2 }; ret = i2c->xfer (i2c, &msg, 1); @@ -84,12 +85,11 @@ } -static -int tda8083_readregs (struct dvb_i2c_bus *i2c, u8 reg1, u8 *b, u8 len) +static int tda8083_readregs (struct dvb_i2c_bus *i2c, u8 reg1, u8 *b, u8 len) { int ret; - struct i2c_msg msg [] = { { addr: 0x68, flags: 0, buf: ®1, len: 1 }, - { addr: 0x68, flags: I2C_M_RD, buf: b, len: len } }; + struct i2c_msg msg [] = { { .addr = 0x68, .flags = 0, .buf = ®1, .len = 1 }, + { .addr = 0x68, .flags = I2C_M_RD, .buf = b, .len = len } }; ret = i2c->xfer (i2c, msg, 2); @@ -101,8 +101,7 @@ } -static inline -u8 tda8083_readreg (struct dvb_i2c_bus *i2c, u8 reg) +static inline u8 tda8083_readreg (struct dvb_i2c_bus *i2c, u8 reg) { u8 val; @@ -112,11 +111,10 @@ } -static -int tsa5522_write (struct dvb_i2c_bus *i2c, u8 data [4]) +static int tsa5522_write (struct dvb_i2c_bus *i2c, u8 data [4]) { int ret; - struct i2c_msg msg = { addr: 0x61, flags: 0, buf: data, len: 4 }; + struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = 4 }; ret = i2c->xfer (i2c, &msg, 1); @@ -131,8 +129,7 @@ * set up the downconverter frequency divisor for a * reference clock comparision frequency of 125 kHz. */ -static -int tsa5522_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq) +static int tsa5522_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq) { u32 div = freq / 125; u8 buf [4] = { (div >> 8) & 0x7f, div & 0xff, 0x8e, 0x00 }; @@ -141,8 +138,7 @@ } -static int -tda8083_init (struct dvb_i2c_bus *i2c) +static int tda8083_init (struct dvb_i2c_bus *i2c) { int i; @@ -155,8 +151,7 @@ } -static int -tda8083_set_inversion (struct dvb_i2c_bus *i2c, fe_spectral_inversion_t inversion) +static int tda8083_set_inversion (struct dvb_i2c_bus *i2c, fe_spectral_inversion_t inversion) { /* XXX FIXME: implement other modes than FEC_AUTO */ if (inversion == INVERSION_AUTO) @@ -166,8 +161,7 @@ } -static int -tda8083_set_fec (struct dvb_i2c_bus *i2c, fe_code_rate_t fec) +static int tda8083_set_fec (struct dvb_i2c_bus *i2c, fe_code_rate_t fec) { if (fec == FEC_AUTO) return tda8083_writereg (i2c, 0x07, 0xff); @@ -179,8 +173,7 @@ } -static -fe_code_rate_t tda8083_get_fec (struct dvb_i2c_bus *i2c) +static fe_code_rate_t tda8083_get_fec (struct dvb_i2c_bus *i2c) { u8 index; static fe_code_rate_t fec_tab [] = { FEC_8_9, FEC_1_2, FEC_2_3, FEC_3_4, @@ -195,8 +188,7 @@ } -static -int tda8083_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate) +static int tda8083_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate) { u32 ratio; u32 tmp; @@ -222,7 +214,7 @@ tmp = (tmp % srate) << 8; ratio = (ratio << 8) + tmp / srate; - dprintk("tda8083: ratio == %08x\n", ratio); + dprintk("tda8083: ratio == %08x\n", (unsigned int) ratio); tda8083_writereg (i2c, 0x05, filter); tda8083_writereg (i2c, 0x02, (ratio >> 16) & 0xff); @@ -236,22 +228,19 @@ } -static -void tda8083_wait_diseqc_fifo (struct dvb_i2c_bus *i2c, int timeout) +static void tda8083_wait_diseqc_fifo (struct dvb_i2c_bus *i2c, int timeout) { unsigned long start = jiffies; while (jiffies - start < timeout && !(tda8083_readreg(i2c, 0x02) & 0x80)) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout (5); + dvb_delay(50); }; } -static -int tda8083_send_diseqc_msg (struct dvb_i2c_bus *i2c, +static int tda8083_send_diseqc_msg (struct dvb_i2c_bus *i2c, struct dvb_diseqc_master_cmd *m) { int i; @@ -269,8 +258,7 @@ } -static -int tda8083_send_diseqc_burst (struct dvb_i2c_bus *i2c, fe_sec_mini_cmd_t burst) +static int tda8083_send_diseqc_burst (struct dvb_i2c_bus *i2c, fe_sec_mini_cmd_t burst) { switch (burst) { case SEC_MINI_A: @@ -289,8 +277,7 @@ } -static -int tda8083_set_tone (struct dvb_i2c_bus *i2c, fe_sec_tone_mode_t tone) +static int tda8083_set_tone (struct dvb_i2c_bus *i2c, fe_sec_tone_mode_t tone) { tda8083_writereg (i2c, 0x26, 0xf1); @@ -305,8 +292,7 @@ } -static -int tda8083_set_voltage (struct dvb_i2c_bus *i2c, fe_sec_voltage_t voltage) +static int tda8083_set_voltage (struct dvb_i2c_bus *i2c, fe_sec_voltage_t voltage) { switch (voltage) { case SEC_VOLTAGE_13: @@ -319,8 +305,7 @@ } -static -int grundig_29504_491_ioctl (struct dvb_frontend *fe, unsigned int cmd, +static int grundig_29504_491_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) { struct dvb_i2c_bus *i2c = fe->i2c; @@ -451,8 +436,7 @@ } -static -int tda8083_attach (struct dvb_i2c_bus *i2c) +static int tda8083_attach (struct dvb_i2c_bus *i2c) { if ((tda8083_readreg (i2c, 0x00)) != 0x05) return -ENODEV; @@ -464,23 +448,20 @@ } -static -void tda8083_detach (struct dvb_i2c_bus *i2c) +static void tda8083_detach (struct dvb_i2c_bus *i2c) { dvb_unregister_frontend (grundig_29504_491_ioctl, i2c); } -static -int __init init_tda8083 (void) +static int __init init_tda8083 (void) { return dvb_register_i2c_device (THIS_MODULE, tda8083_attach, tda8083_detach); } -static -void __exit exit_tda8083 (void) +static void __exit exit_tda8083 (void) { dvb_unregister_i2c_device (tda8083_attach); } diff -Nru a/drivers/media/dvb/frontends/nxt6000.c b/drivers/media/dvb/frontends/nxt6000.c --- a/drivers/media/dvb/frontends/nxt6000.c Tue Jul 1 18:44:36 2003 +++ b/drivers/media/dvb/frontends/nxt6000.c Tue Jul 1 18:44:36 2003 @@ -25,13 +25,11 @@ */ -#include #include -#include +#include +#include +#include #include -#include -#include -#include #include "dvb_frontend.h" #include "nxt6000.h" @@ -90,11 +88,11 @@ { u8 buf[] = {reg, data}; - struct i2c_msg msg = {addr: addr >> 1, flags: 0, buf: buf, len: 2}; + struct i2c_msg msg = {.addr = addr >> 1, .flags = 0, .buf = buf, .len = 2}; int ret; if ((ret = i2c->xfer(i2c, &msg, 1)) != 1) - dprintk("nxt6000: nxt6000_write error (addr: 0x%02X, reg: 0x%02X, data: 0x%02X, ret: %d)\n", addr, reg, data, ret); + dprintk("nxt6000: nxt6000_write error (.addr = 0x%02X, reg: 0x%02X, data: 0x%02X, ret: %d)\n", addr, reg, data, ret); return (ret != 1) ? -EFAULT : 0; @@ -115,13 +113,13 @@ int ret; u8 b0[] = {reg}; u8 b1[] = {0}; - struct i2c_msg msgs[] = {{addr: addr >> 1, flags: 0, buf: b0, len: 1}, - {addr: addr >> 1, flags: I2C_M_RD, buf: b1, len: 1}}; + struct i2c_msg msgs[] = {{.addr = addr >> 1, .flags = 0, .buf = b0, .len = 1}, + {.addr = addr >> 1, .flags = I2C_M_RD, .buf = b1, .len = 1}}; ret = i2c->xfer(i2c, msgs, 2); if (ret != 2) - dprintk("nxt6000: nxt6000_read error (addr: 0x%02X, reg: 0x%02X, ret: %d)\n", addr, reg, ret); + dprintk("nxt6000: nxt6000_read error (.addr = 0x%02X, reg: 0x%02X, ret: %d)\n", addr, reg, ret); return b1[0]; @@ -139,7 +137,7 @@ static int pll_write(struct dvb_i2c_bus *i2c, u8 demod_addr, u8 tuner_addr, u8 *buf, u8 len) { - struct i2c_msg msg = {addr: tuner_addr >> 1, flags: 0, buf: buf, len: len}; + struct i2c_msg msg = {.addr = tuner_addr >> 1, .flags = 0, .buf = buf, .len = len}; int ret; nxt6000_write(i2c, demod_addr, ENABLE_TUNER_IIC, 0x01); /* open i2c bus switch */ diff -Nru a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c --- a/drivers/media/dvb/frontends/stv0299.c Tue Jul 1 18:44:39 2003 +++ b/drivers/media/dvb/frontends/stv0299.c Tue Jul 1 18:44:39 2003 @@ -36,35 +36,42 @@ */ #include +#include #include +#include #include "dvb_frontend.h" +#include "dvb_functions.h" + +#if 0 +#define dprintk(x...) printk(x) +#else +#define dprintk(x...) +#endif -static int debug = 0; -#define dprintk if (debug) printk /* frontend types */ #define UNKNOWN_FRONTEND -1 #define PHILIPS_SU1278SH 0 #define ALPS_BSRU6 1 #define LG_TDQF_S001F 2 +#define PHILIPS_SU1278 3 /* Master Clock = 88 MHz */ #define M_CLK (88000000UL) -static -struct dvb_frontend_info uni0299_info = { - name: "STV0299/TSA5059/SL1935 based", - type: FE_QPSK, - frequency_min: 950000, - frequency_max: 2150000, - frequency_stepsize: 125, /* kHz for QPSK frontends */ - frequency_tolerance: M_CLK/2000, - symbol_rate_min: 1000000, - symbol_rate_max: 45000000, - symbol_rate_tolerance: 500, /* ppm */ - notifier_delay: 0, - caps: FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | +static struct dvb_frontend_info uni0299_info = { + .name = "STV0299/TSA5059/SL1935 based", + .type = FE_QPSK, + .frequency_min = 950000, + .frequency_max = 2150000, + .frequency_stepsize = 125, /* kHz for QPSK frontends */ + .frequency_tolerance = M_CLK/2000, + .symbol_rate_min = 1000000, + .symbol_rate_max = 45000000, + .symbol_rate_tolerance = 500, /* ppm */ + .notifier_delay = 0, + .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_QPSK | FE_CAN_FEC_AUTO | FE_CAN_INVERSION_AUTO | @@ -72,13 +79,7 @@ }; -static -u8 init_tab [] = { - /* clock registers */ - 0x01, 0x15, /* K = 0, DIRCLK = 0, M = 0x15 */ - 0x02, 0x30, /* STDBY = 0, VCO = 0 (ON), SERCLK = 0, P = 0 */ - /* f_VCO = 4MHz * 4 * (M+1) / (K+1) = 352 MHz */ - 0x03, 0x00, /* auxiliary clock not used */ +static u8 init_tab [] = { 0x04, 0x7d, /* F22FR = 0x7d */ /* F22 = f_VCO / 128 / 0x7d = 22 kHz */ @@ -90,7 +91,7 @@ 0x07, 0x00, /* DAC LSB */ /* DiSEqC registers */ - 0x08, 0x40, /* DiSEqC off */ + 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */ 0x09, 0x00, /* FIFO */ /* Input/Output configuration register */ @@ -105,34 +106,27 @@ 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ 0x10, 0x3f, // AGC2 0x3d + 0x11, 0x84, 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on - 0x13, 0xb6, // alpha_car b:4 a:0 noise est:256ks derot:on - 0x14, 0x93, // beat carc:0 d:0 e:0xf phase detect algo: 1 + 0x15, 0xc9, // lock detector threshold - 0x16, 0x1d, /* AGC1 integrator value */ + 0x16, 0x00, 0x17, 0x00, - 0x18, 0x14, - 0x19, 0xf2, - - 0x1a, 0x11, + 0x18, 0x00, + 0x19, 0x00, + 0x1a, 0x00, - 0x1b, 0x9c, - 0x1c, 0x00, - 0x1d, 0x00, - 0x1e, 0x0b, 0x1f, 0x50, 0x20, 0x00, 0x21, 0x00, 0x22, 0x00, 0x23, 0x00, - 0x24, 0xff, - 0x25, 0xff, - 0x26, 0xff, 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0 + 0x29, 0x1e, // 1/2 threshold 0x2a, 0x14, // 2/3 threshold 0x2b, 0x0f, // 3/4 threshold @@ -145,70 +139,32 @@ 0x32, 0x19, // viterbi and synchro search 0x33, 0xfc, // rs control 0x34, 0x93, // error control - - 0x0b, 0x00, - 0x27, 0x00, - 0x2f, 0x00, - 0x30, 0x00, - 0x35, 0x00, - 0x36, 0x00, - 0x37, 0x00, - 0x38, 0x00, - 0x39, 0x00, - 0x3a, 0x00, - 0x3b, 0x00, - 0x3c, 0x00, - 0x3d, 0x00, - 0x3e, 0x00, - 0x3f, 0x00, - 0x40, 0x00, - 0x41, 0x00, - 0x42, 0x00, - 0x43, 0x00, - 0x44, 0x00, - 0x45, 0x00, - 0x46, 0x00, - 0x47, 0x00, - 0x48, 0x00, - 0x49, 0x00, - 0x4a, 0x00, - 0x4b, 0x00, - 0x4c, 0x00, - 0x4d, 0x00, - 0x4e, 0x00, - 0x4f, 0x00 }; -static -int stv0299_writereg (struct dvb_i2c_bus *i2c, u8 reg, u8 data) +static int stv0299_writereg (struct dvb_i2c_bus *i2c, u8 reg, u8 data) { int ret; u8 buf [] = { reg, data }; - struct i2c_msg msg = { addr: 0x68, flags: 0, buf: buf, len: 2 }; - - dprintk ("%s\n", __FUNCTION__); + struct i2c_msg msg = { .addr = 0x68, .flags = 0, .buf = buf, .len = 2 }; ret = i2c->xfer (i2c, &msg, 1); if (ret != 1) - dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, ret == %i)\n", - __FUNCTION__, reg, data, ret); + dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, " + "ret == %i)\n", __FUNCTION__, reg, data, ret); return (ret != 1) ? -1 : 0; } -static -u8 stv0299_readreg (struct dvb_i2c_bus *i2c, u8 reg) +static u8 stv0299_readreg (struct dvb_i2c_bus *i2c, u8 reg) { int ret; u8 b0 [] = { reg }; u8 b1 [] = { 0 }; - struct i2c_msg msg [] = { { addr: 0x68, flags: 0, buf: b0, len: 1 }, - { addr: 0x68, flags: I2C_M_RD, buf: b1, len: 1 } }; - - dprintk ("%s\n", __FUNCTION__); + struct i2c_msg msg [] = { { .addr = 0x68, .flags = 0, .buf = b0, .len = 1 }, + { .addr = 0x68, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; ret = i2c->xfer (i2c, msg, 2); @@ -219,53 +175,40 @@ } -static -int stv0299_readregs (struct dvb_i2c_bus *i2c, u8 reg1, u8 *b, u8 len) +static int stv0299_readregs (struct dvb_i2c_bus *i2c, u8 reg1, u8 *b, u8 len) { int ret; - struct i2c_msg msg [] = { { addr: 0x68, flags: 0, buf: ®1, len: 1 }, - { addr: 0x68, flags: I2C_M_RD, buf: b, len: len } }; - - dprintk ("%s\n", __FUNCTION__); + struct i2c_msg msg [] = { { .addr = 0x68, .flags = 0, .buf = ®1, .len = 1 }, + { .addr = 0x68, .flags = I2C_M_RD, .buf = b, .len = len } }; ret = i2c->xfer (i2c, msg, 2); if (ret != 2) dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret); - return ret == 2 ? 0 : -1; + return ret == 2 ? 0 : ret; } -static -int pll_write (struct dvb_i2c_bus *i2c, u8 data [4], int ftype) +static int pll_write (struct dvb_i2c_bus *i2c, u8 addr, u8 *data, int len) { int ret; u8 rpt1 [] = { 0x05, 0xb5 }; /* enable i2c repeater on stv0299 */ - /* TSA5059 i2c-bus address */ - u8 addr = (ftype == PHILIPS_SU1278SH) ? 0x60 : 0x61; - struct i2c_msg msg [] = {{ addr: 0x68, flags: 0, buf: rpt1, len: 2 }, - { addr: addr, flags: 0, buf: data, len: 4 }}; + u8 rpt2 [] = { 0x05, 0x35 }; /* disable i2c repeater on stv0299 */ + struct i2c_msg msg [] = {{ .addr = 0x68, .flags = 0, .buf = rpt1, .len = 2 }, + { addr: addr, .flags = 0, .buf = data, .len = len }, + { .addr = 0x68, .flags = 0, .buf = rpt2, .len = 2 }}; - dprintk ("%s\n", __FUNCTION__); + ret = i2c->xfer (i2c, msg, 3); - if (ftype == LG_TDQF_S001F || ftype == ALPS_BSRU6) { - ret = i2c->xfer (i2c, &msg[0], 1); - ret += i2c->xfer (i2c, &msg[1], 1); - } - else { - ret = i2c->xfer (i2c, msg, 2); - } + if (ret != 3) + printk("%s: i/o error (ret == %i)\n", __FUNCTION__, ret); - if (ret != 2) - dprintk("%s: i/o error (ret == %i)\n", __FUNCTION__, ret); - - return (ret != 2) ? -1 : 0; + return (ret != 3) ? ret : 0; } -static -int sl1935_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq, int ftype) +static int sl1935_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq, int ftype) { u8 buf[4]; u32 div; @@ -288,20 +231,21 @@ else buf[3] = 0x00; - return pll_write (i2c, buf, ftype); + return pll_write (i2c, 0x61, buf, sizeof(buf)); } /** * set up the downconverter frequency divisor for a * reference clock comparision frequency of 125 kHz. */ -static -int tsa5059_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq, int ftype) +static int tsa5059_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq, int ftype) { + u8 addr = (ftype == PHILIPS_SU1278SH) ? 0x60 : 0x61; u32 div = freq / 125; - u8 buf[4] = { (div >> 8) & 0x7f, div & 0xff, 0x84 }; + dprintk ("%s: freq %i, ftype %i\n", __FUNCTION__, freq, ftype); + if (ftype == PHILIPS_SU1278SH) /* activate f_xtal/f_comp signal output */ /* charge pump current C0/C1 = 00 */ @@ -309,30 +253,155 @@ else buf[3] = freq > 1530000 ? 0xc0 : 0xc4; - dprintk ("%s\n", __FUNCTION__); + return pll_write (i2c, addr, buf, sizeof(buf)); +} + + + +#define ABS(x) ((x) < 0 ? -(x) : (x)) +#define MIN2(a,b) ((a) < (b) ? (a) : (b)) +#define MIN3(a,b,c) MIN2(MIN2(a,b),c) + +static int tua6100_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq, + int ftype, int srate) +{ + u8 reg0 [2] = { 0x00, 0x00 }; + u8 reg1 [4] = { 0x01, 0x00, 0x00, 0x00 }; + u8 reg2 [3] = { 0x02, 0x00, 0x00 }; + int _fband; + int first_ZF; + int R, A, N, P, M; + int err; + + first_ZF = (freq) / 1000; + + if (ABS(MIN2(ABS(first_ZF-1190),ABS(first_ZF-1790))) < + ABS(MIN3(ABS(first_ZF-1202),ABS(first_ZF-1542),ABS(first_ZF-1890)))) + _fband = 2; + else + _fband = 3; + + if (_fband == 2) { + if (((first_ZF >= 950) && (first_ZF < 1350)) || + ((first_ZF >= 1430) && (first_ZF < 1950))) + reg0[1] = 0x07; + else if (((first_ZF >= 1350) && (first_ZF < 1430)) || + ((first_ZF >= 1950) && (first_ZF < 2150))) + reg0[1] = 0x0B; + } + + if(_fband == 3) { + if (((first_ZF >= 950) && (first_ZF < 1350)) || + ((first_ZF >= 1455) && (first_ZF < 1950))) + reg0[1] = 0x07; + else if (((first_ZF >= 1350) && (first_ZF < 1420)) || + ((first_ZF >= 1950) && (first_ZF < 2150))) + reg0[1] = 0x0B; + else if ((first_ZF >= 1420) && (first_ZF < 1455)) + reg0[1] = 0x0F; +} + + if (first_ZF > 1525) + reg1[1] |= 0x80; + else + reg1[1] &= 0x7F; + + if (_fband == 2) { + if (first_ZF > 1430) { /* 1430MHZ */ + reg1[1] &= 0xCF; /* N2 */ + reg2[1] &= 0xCF; /* R2 */ + reg2[1] |= 0x10; + } else { + reg1[1] &= 0xCF; /* N2 */ + reg1[1] |= 0x20; + reg2[1] &= 0xCF; /* R2 */ + reg2[1] |= 0x10; + } +} + + if (_fband == 3) { + if ((first_ZF >= 1455) && + (first_ZF < 1630)) { + reg1[1] &= 0xCF; /* N2 */ + reg1[1] |= 0x20; + reg2[1] &= 0xCF; /* R2 */ + } else { + if (first_ZF < 1455) { + reg1[1] &= 0xCF; /* N2 */ + reg1[1] |= 0x20; + reg2[1] &= 0xCF; /* R2 */ + reg2[1] |= 0x10; + } else { + if (first_ZF >= 1630) { + reg1[1] &= 0xCF; /* N2 */ + reg2[1] &= 0xCF; /* R2 */ + reg2[1] |= 0x10; + } + } + } + } + + /* set ports, enable P0 for symbol rates > 4Ms/s */ + if (srate >= 4000000) + reg1[1] |= 0x0c; + else + reg1[1] |= 0x04; - return pll_write (i2c, buf, ftype); + reg2[1] |= 0x0c; + + R = 64; + A = 64; + P = 64; //32 + + M = (freq * R) / 4; /* in Mhz */ + N = (M - A * 1000) / (P * 1000); + + reg1[1] |= (N >> 9) & 0x03; + reg1[2] = (N >> 1) & 0xff; + reg1[3] = (N << 7) & 0x80; + + reg2[1] |= (R >> 8) & 0x03; + reg2[2] = R & 0xFF; /* R */ + + reg1[3] |= A & 0x7f; /* A */ + + if (P == 64) + reg1[1] |= 0x40; /* Prescaler 64/65 */ + + reg0[1] |= 0x03; + + if ((err = pll_write(i2c, 0x60, reg0, sizeof(reg0)))) + return err; + + if ((err = pll_write(i2c, 0x60, reg1, sizeof(reg1)))) + return err; + + if ((err = pll_write(i2c, 0x60, reg2, sizeof(reg2)))) + return err; + + return 0; } -static -int pll_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq, int ftype) + +static int pll_set_tv_freq (struct dvb_i2c_bus *i2c, u32 freq, int ftype, int srate) { if (ftype == LG_TDQF_S001F) return sl1935_set_tv_freq(i2c, freq, ftype); + else if (ftype == PHILIPS_SU1278) + return tua6100_set_tv_freq(i2c, freq, ftype, srate); else return tsa5059_set_tv_freq(i2c, freq, ftype); } #if 0 -static -int tsa5059_read_status (struct dvb_i2c_bus *i2c) +static int tsa5059_read_status (struct dvb_i2c_bus *i2c) { int ret; u8 rpt1 [] = { 0x05, 0xb5 }; u8 stat [] = { 0 }; - struct i2c_msg msg [] = {{ addr: 0x68, flags: 0, buf: rpt1, len: 2 }, - { addr: 0x60, flags: I2C_M_RD, buf: stat, len: 1 }}; + struct i2c_msg msg [] = {{ .addr = 0x68, .flags = 0, .buf = rpt1, .len = 2 }, + { .addr = 0x60, .flags = I2C_M_RD, .buf = stat, .len = 1 }}; dprintk ("%s\n", __FUNCTION__); @@ -346,19 +415,24 @@ #endif -static -int stv0299_init (struct dvb_i2c_bus *i2c, int ftype) +static int stv0299_init (struct dvb_i2c_bus *i2c, int ftype) { int i; dprintk("stv0299: init chip\n"); + stv0299_writereg (i2c, 0x01, 0x15); + stv0299_writereg (i2c, 0x02, ftype == PHILIPS_SU1278 ? 0x00 : 0x30); + stv0299_writereg (i2c, 0x03, 0x00); + for (i=0; istate = TASK_INTERRUPTIBLE; - schedule_timeout (1); + dvb_delay(10); }; return 0; } -static -int stv0299_wait_diseqc_idle (struct dvb_i2c_bus *i2c, int timeout) +static int stv0299_wait_diseqc_idle (struct dvb_i2c_bus *i2c, int timeout) { unsigned long start = jiffies; @@ -455,16 +526,14 @@ dprintk ("%s: timeout!!\n", __FUNCTION__); return -ETIMEDOUT; } - current->state = TASK_INTERRUPTIBLE; - schedule_timeout (1); + dvb_delay(10); }; return 0; } -static -int stv0299_send_diseqc_msg (struct dvb_i2c_bus *i2c, +static int stv0299_send_diseqc_msg (struct dvb_i2c_bus *i2c, struct dvb_diseqc_master_cmd *m) { u8 val; @@ -495,8 +564,7 @@ } -static -int stv0299_send_diseqc_burst (struct dvb_i2c_bus *i2c, fe_sec_mini_cmd_t burst) +static int stv0299_send_diseqc_burst (struct dvb_i2c_bus *i2c, fe_sec_mini_cmd_t burst) { u8 val; @@ -523,12 +591,13 @@ } -static -int stv0299_set_tone (struct dvb_i2c_bus *i2c, fe_sec_tone_mode_t tone) +static int stv0299_set_tone (struct dvb_i2c_bus *i2c, fe_sec_tone_mode_t tone) { u8 val; - dprintk ("%s\n", __FUNCTION__); + dprintk("%s: %s\n", __FUNCTION__, + tone == SEC_TONE_ON ? "SEC_TONE_ON" : + tone == SEC_TONE_OFF ? "SEC_TONE_OFF" : "??"); if (stv0299_wait_diseqc_idle (i2c, 100) < 0) return -ETIMEDOUT; @@ -546,30 +615,43 @@ } -static -int stv0299_set_voltage (struct dvb_i2c_bus *i2c, fe_sec_voltage_t voltage) +static int stv0299_set_voltage (struct dvb_i2c_bus *i2c, fe_sec_voltage_t voltage) { - u8 val; + u8 reg0x08; + u8 reg0x0c; - dprintk ("%s\n", __FUNCTION__); - - val = stv0299_readreg (i2c, 0x0c); - val &= 0x0f; - val |= 0x40; /* LNB power on */ + dprintk("%s: %s\n", __FUNCTION__, + voltage == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" : + voltage == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??"); + + reg0x08 = stv0299_readreg (i2c, 0x08); + reg0x0c = stv0299_readreg (i2c, 0x0c); + + /** + * H/V switching over OP0, OP1 and OP2 are LNB power enable bits + */ + reg0x0c &= 0x0f; + + if (voltage == SEC_VOLTAGE_OFF) { + stv0299_writereg (i2c, 0x08, reg0x08 & ~0x40); + return stv0299_writereg (i2c, 0x0c, reg0x0c & ~0x40); + } else { + stv0299_writereg (i2c, 0x08, reg0x08 | 0x40); + reg0x0c |= 0x40; /* LNB power on */ switch (voltage) { case SEC_VOLTAGE_13: - return stv0299_writereg (i2c, 0x0c, val); + return stv0299_writereg (i2c, 0x0c, reg0x0c); case SEC_VOLTAGE_18: - return stv0299_writereg (i2c, 0x0c, val | 0x10); + return stv0299_writereg (i2c, 0x0c, reg0x0c | 0x10); default: return -EINVAL; }; } +} -static -int stv0299_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate) +static int stv0299_set_symbolrate (struct dvb_i2c_bus *i2c, u32 srate) { u32 ratio; u32 tmp; @@ -607,8 +689,7 @@ } -static -int stv0299_get_symbolrate (struct dvb_i2c_bus *i2c) +static int stv0299_get_symbolrate (struct dvb_i2c_bus *i2c) { u32 Mclk = M_CLK / 4096L; u32 srate; @@ -639,14 +720,11 @@ } -static -int uni0299_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) +static int uni0299_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) { - int tuner_type = (int)fe->data; + int tuner_type = (long) fe->data; struct dvb_i2c_bus *i2c = fe->i2c; - dprintk ("%s\n", __FUNCTION__); - switch (cmd) { case FE_GET_INFO: memcpy (arg, &uni0299_info, sizeof(struct dvb_frontend_info)); @@ -692,7 +770,7 @@ dprintk ("AGC2I: 0x%02x%02x, signal=0x%04x\n", stv0299_readreg (i2c, 0x18), - stv0299_readreg (i2c, 0x19), signal); + stv0299_readreg (i2c, 0x19), (int) signal); signal = signal * 5 / 4; *((u16*) arg) = (signal > 0xffff) ? 0xffff : @@ -716,15 +794,16 @@ { struct dvb_frontend_parameters *p = arg; - pll_set_tv_freq (i2c, p->frequency, tuner_type); + pll_set_tv_freq (i2c, p->frequency, tuner_type, + p->u.qpsk.symbol_rate); + stv0299_set_FEC (i2c, p->u.qpsk.fec_inner); stv0299_set_symbolrate (i2c, p->u.qpsk.symbol_rate); - stv0299_check_inversion (i2c); - /* pll_set_tv_freq (i2c, p->frequency, tuner_type); */ stv0299_writereg (i2c, 0x22, 0x00); stv0299_writereg (i2c, 0x23, 0x00); stv0299_readreg (i2c, 0x23); stv0299_writereg (i2c, 0x12, 0xb9); + stv0299_check_inversion (i2c); /* printk ("%s: tsa5059 status: %x\n", __FUNCTION__, tsa5059_read_status(i2c)); */ break; @@ -752,19 +831,13 @@ case FE_SLEEP: stv0299_writereg (i2c, 0x0c, 0x00); /* LNB power off! */ + stv0299_writereg (i2c, 0x08, 0x00); /* LNB power off! */ stv0299_writereg (i2c, 0x02, 0x80); break; case FE_INIT: return stv0299_init (i2c, tuner_type); - case FE_RESET: - stv0299_writereg (i2c, 0x22, 0x00); - stv0299_writereg (i2c, 0x23, 0x00); - stv0299_readreg (i2c, 0x23); - stv0299_writereg (i2c, 0x12, 0xb9); - break; - case FE_DISEQC_SEND_MASTER_CMD: return stv0299_send_diseqc_msg (i2c, arg); @@ -784,48 +857,65 @@ return 0; } -static -int probe_tuner (struct dvb_i2c_bus *i2c) +static long probe_tuner (struct dvb_i2c_bus *i2c) { - int type; - /* read the status register of TSA5059 */ u8 rpt[] = { 0x05, 0xb5 }; u8 stat [] = { 0 }; - struct i2c_msg msg1 [] = {{ addr: 0x68, flags: 0, buf: rpt, len: 2 }, - { addr: 0x60, flags: I2C_M_RD, buf: stat, len: 1 }}; - struct i2c_msg msg2 [] = {{ addr: 0x68, flags: 0, buf: rpt, len: 2 }, - { addr: 0x61, flags: I2C_M_RD, buf: stat, len: 1 }}; + u8 tda6100_buf [] = { 0, 0 }; + int ret; + struct i2c_msg msg1 [] = {{ .addr = 0x68, .flags = 0, .buf = rpt, len: 2 }, + { .addr = 0x60, .flags = I2C_M_RD, .buf = stat, .len = 1 }}; + struct i2c_msg msg2 [] = {{ .addr = 0x68, .flags = 0, .buf = rpt, len: 2 }, + { .addr = 0x61, .flags = I2C_M_RD, .buf = stat, .len = 1 }}; + struct i2c_msg msg3 [] = {{ .addr = 0x68, .flags = 0, .buf = rpt, len: 2 }, + { .addr = 0x60, .flags = 0, .buf = tda6100_buf, .len = 2 }}; + + stv0299_writereg (i2c, 0x01, 0x15); + stv0299_writereg (i2c, 0x02, 0x30); + stv0299_writereg (i2c, 0x03, 0x00); - if (i2c->xfer(i2c, msg1, 2) == 2) { - type = PHILIPS_SU1278SH; + if ((ret = i2c->xfer(i2c, msg1, 2)) == 2) { printk ("%s: setup for tuner SU1278/SH\n", __FILE__); - } else if (i2c->xfer(i2c, msg2, 2) == 2) { -if (0) { // if ((stat[0] & 0x3f) == 0) { - type = LG_TDQF_S001F; - printk ("%s: setup for tuner TDQF-S001F\n", __FILE__); - } - else { - type = ALPS_BSRU6; - printk ("%s: setup for tuner BSRU6, TDQB-S00x\n", __FILE__); + return PHILIPS_SU1278SH; } + + if ((ret = i2c->xfer(i2c, msg2, 2)) == 2) { + //if ((stat[0] & 0x3f) == 0) { + if (0) { + printk ("%s: setup for tuner TDQF-S001F\n", __FILE__); + return LG_TDQF_S001F; } else { - type = UNKNOWN_FRONTEND; - printk ("%s: unknown PLL synthesizer, " - "please report to !!\n", + printk ("%s: setup for tuner BSRU6, TDQB-S00x\n", __FILE__); + return ALPS_BSRU6; + } + } + + /** + * setup i2c timing for SU1278... + */ + stv0299_writereg (i2c, 0x02, 0x00); + + if ((ret = i2c->xfer(i2c, msg3, 2)) == 2) { + printk ("%s: setup for tuner Philips SU1278\n", __FILE__); + return PHILIPS_SU1278; } - return type; + + printk ("%s: unknown PLL synthesizer (ret == %i), " + "please report to !!\n", + __FILE__, ret); + + return UNKNOWN_FRONTEND; } -static -int uni0299_attach (struct dvb_i2c_bus *i2c) +static int uni0299_attach (struct dvb_i2c_bus *i2c) { - int tuner_type; + long tuner_type; u8 id = stv0299_readreg (i2c, 0x00); - dprintk ("%s\n", __FUNCTION__); + dprintk ("%s: id == 0x%02x\n", __FUNCTION__, id); /* register 0x00 contains 0xa1 for STV0299 and STV0299B */ /* register 0x00 might contain 0x80 when returning from standby */ @@ -842,8 +932,7 @@ } -static -void uni0299_detach (struct dvb_i2c_bus *i2c) +static void uni0299_detach (struct dvb_i2c_bus *i2c) { dprintk ("%s\n", __FUNCTION__); @@ -851,17 +940,14 @@ } -static -int __init init_uni0299 (void) +static int __init init_uni0299 (void) { dprintk ("%s\n", __FUNCTION__); - - return dvb_register_i2c_device (THIS_MODULE, uni0299_attach, uni0299_detach); + return dvb_register_i2c_device (NULL, uni0299_attach, uni0299_detach); } -static -void __exit exit_uni0299 (void) +static void __exit exit_uni0299 (void) { dprintk ("%s\n", __FUNCTION__); @@ -870,9 +956,6 @@ module_init (init_uni0299); module_exit (exit_uni0299); - -MODULE_PARM(debug,"i"); -MODULE_PARM_DESC(debug, "enable verbose debug messages"); MODULE_DESCRIPTION("Universal STV0299/TSA5059/SL1935 DVB Frontend driver"); MODULE_AUTHOR("Ralph Metzler, Holger Waechtler, Peter Schildmann, Felix Domke, Andreas Oberritter"); diff -Nru a/drivers/media/dvb/frontends/ves1820.c b/drivers/media/dvb/frontends/ves1820.c --- a/drivers/media/dvb/frontends/ves1820.c Tue Jul 1 18:44:35 2003 +++ b/drivers/media/dvb/frontends/ves1820.c Tue Jul 1 18:44:35 2003 @@ -19,11 +19,15 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include #include +#include #include -#include +#include +#include #include "dvb_frontend.h" +#include "dvb_functions.h" #if 0 @@ -39,48 +43,43 @@ */ #define SET_PWM(data,pwm) do { \ - (int) data &= ~0xff; \ - (int) data |= pwm; \ + (long) data &= ~0xff; \ + (long) data |= pwm; \ } while (0) #define SET_REG0(data,reg0) do { \ - (int) data &= ~(0xff << 8); \ - (int) data |= reg0 << 8; \ + (long) data &= ~(0xff << 8); \ + (long) data |= reg0 << 8; \ } while (0) #define SET_TUNER(data,type) do { \ - (int) data &= ~(0xff << 16); \ - (int) data |= type << 16; \ + (long) data &= ~(0xff << 16); \ + (long) data |= type << 16; \ } while (0) #define SET_DEMOD_ADDR(data,type) do { \ - (int) data &= ~(0xff << 24); \ - (int) data |= type << 24; \ + (long) data &= ~(0xff << 24); \ + (long) data |= type << 24; \ } while (0) -#define GET_PWM(data) ((u8) ((int) data & 0xff)) -#define GET_REG0(data) ((u8) (((int) data >> 8) & 0xff)) -#define GET_TUNER(data) ((u8) (((int) data >> 16) & 0xff)) -#define GET_DEMOD_ADDR(data) ((u8) (((int) data >> 24) & 0xff)) +#define GET_PWM(data) ((u8) ((long) data & 0xff)) +#define GET_REG0(data) ((u8) (((long) data >> 8) & 0xff)) +#define GET_TUNER(data) ((u8) (((long) data >> 16) & 0xff)) +#define GET_DEMOD_ADDR(data) ((u8) (((long) data >> 24) & 0xff)) +#define XIN 57840000UL +#define FIN (XIN >> 4) -static inline -void ddelay (int ms) -{ - current->state=TASK_INTERRUPTIBLE; - schedule_timeout((HZ*ms)/1000); -} -static -struct dvb_frontend_info ves1820_info = { +static struct dvb_frontend_info ves1820_info = { .name = "VES1820 based DVB-C frontend", .type = FE_QAM, .frequency_stepsize = 62500, .frequency_min = 51000000, .frequency_max = 858000000, - .symbol_rate_min = (57840000/2)/64, /* SACLK/64 == (XIN/2)/64 */ - .symbol_rate_max = (57840000/2)/4, /* SACLK/4 */ + .symbol_rate_min = (XIN/2)/64, /* SACLK/64 == (XIN/2)/64 */ + .symbol_rate_max = (XIN/2)/4, /* SACLK/4 */ #if 0 frequency_tolerance: ???, symbol_rate_tolerance: ???, /* ppm */ /* == 8% (spec p. 5) */ @@ -94,8 +93,7 @@ -static -u8 ves1820_inittab [] = +static u8 ves1820_inittab [] = { 0x69, 0x6A, 0x9B, 0x0A, 0x52, 0x46, 0x26, 0x1A, 0x43, 0x6A, 0xAA, 0xAA, 0x1E, 0x85, 0x43, 0x28, @@ -107,12 +105,11 @@ }; -static -int ves1820_writereg (struct dvb_frontend *fe, u8 reg, u8 data) +static int ves1820_writereg (struct dvb_frontend *fe, u8 reg, u8 data) { u8 addr = GET_DEMOD_ADDR(fe->data); u8 buf[] = { 0x00, reg, data }; - struct i2c_msg msg = { addr: addr, flags: 0, buf: buf, len: 3 }; + struct i2c_msg msg = { addr: addr, .flags = 0, .buf = buf, .len = 3 }; struct dvb_i2c_bus *i2c = fe->i2c; int ret; @@ -123,19 +120,18 @@ "(reg == 0x%02x, val == 0x%02x, ret == %i)\n", __FUNCTION__, reg, data, ret); - mdelay(10); + dvb_delay(10); return (ret != 1) ? -EREMOTEIO : 0; } -static -u8 ves1820_readreg (struct dvb_frontend *fe, u8 reg) +static u8 ves1820_readreg (struct dvb_frontend *fe, u8 reg) { u8 b0 [] = { 0x00, reg }; u8 b1 [] = { 0 }; u8 addr = GET_DEMOD_ADDR(fe->data); - struct i2c_msg msg [] = { { addr: addr, flags: 0, buf: b0, len: 2 }, - { addr: addr, flags: I2C_M_RD, buf: b1, len: 1 } }; + struct i2c_msg msg [] = { { addr: addr, .flags = 0, .buf = b0, .len = 2 }, + { addr: addr, .flags = I2C_M_RD, .buf = b1, .len = 1 } }; struct dvb_i2c_bus *i2c = fe->i2c; int ret; @@ -148,11 +144,10 @@ } -static -int tuner_write (struct dvb_i2c_bus *i2c, u8 addr, u8 data [4]) +static int tuner_write (struct dvb_i2c_bus *i2c, u8 addr, u8 data [4]) { int ret; - struct i2c_msg msg = { addr: addr, flags: 0, buf: data, len: 4 }; + struct i2c_msg msg = { addr: addr, .flags = 0, .buf = data, .len = 4 }; ret = i2c->xfer (i2c, &msg, 1); @@ -167,10 +162,9 @@ * set up the downconverter frequency divisor for a * reference clock comparision frequency of 62.5 kHz. */ -static -int tuner_set_tv_freq (struct dvb_frontend *fe, u32 freq) +static int tuner_set_tv_freq (struct dvb_frontend *fe, u32 freq) { - u32 div; + u32 div, ifreq; static u8 addr [] = { 0x61, 0x62 }; static u8 byte3 [] = { 0x8e, 0x85 }; int tuner_type = GET_TUNER(fe->data); @@ -179,7 +173,13 @@ if (tuner_type == 0xff) /* PLL not reachable over i2c ... */ return 0; - div = (freq + 36125000 + 31250) / 62500; + if (strstr (fe->i2c->adapter->name, "Technotrend")) + ifreq = 35937500; + else + ifreq = 36125000; + + div = (freq + ifreq + 31250) / 62500; + buf[0] = (div >> 8) & 0x7f; buf[1] = div & 0xff; buf[2] = byte3[tuner_type]; @@ -197,19 +197,24 @@ } -static -int ves1820_setup_reg0 (struct dvb_frontend *fe, u8 reg0) +static int ves1820_setup_reg0 (struct dvb_frontend *fe, u8 reg0, + fe_spectral_inversion_t inversion) { reg0 |= GET_REG0(fe->data) & 0x62; + if (INVERSION_ON == inversion) + reg0 &= ~0x20; + else if (INVERSION_OFF == inversion) + reg0 |= 0x20; + ves1820_writereg (fe, 0x00, reg0 & 0xfe); ves1820_writereg (fe, 0x00, reg0 | 0x01); /** * check lock and toggle inversion bit if required... */ - if (!(ves1820_readreg (fe, 0x11) & 0x08)) { - ddelay(1); + if (INVERSION_AUTO == inversion && !(ves1820_readreg (fe, 0x11) & 0x08)) { + dvb_delay(10); if (!(ves1820_readreg (fe, 0x11) & 0x08)) { reg0 ^= 0x20; ves1820_writereg (fe, 0x00, reg0 & 0xfe); @@ -223,8 +228,7 @@ } -static -int ves1820_init (struct dvb_frontend *fe) +static int ves1820_init (struct dvb_frontend *fe) { int i; @@ -241,8 +245,7 @@ } -static -int ves1820_set_symbolrate (struct dvb_frontend *fe, u32 symbolrate) +static int ves1820_set_symbolrate (struct dvb_frontend *fe, u32 symbolrate) { s32 BDR; s32 BDRI; @@ -250,9 +253,6 @@ u16 NDEC = 0; u32 tmp, ratio; -#define XIN 57840000UL -#define FIN (XIN >> 4) - if (symbolrate > XIN/2) symbolrate = XIN/2; @@ -300,12 +300,11 @@ } -static -int ves1820_set_parameters (struct dvb_frontend *fe, +static int ves1820_set_parameters (struct dvb_frontend *fe, struct dvb_frontend_parameters *p) { static const u8 reg0x00 [] = { 0x00, 0x04, 0x08, 0x0c, 0x10 }; - static const u8 reg0x01 [] = { 140, 140, 106, 120, 92 }; + static const u8 reg0x01 [] = { 140, 140, 106, 100, 92 }; static const u8 reg0x05 [] = { 135, 100, 70, 54, 38 }; static const u8 reg0x08 [] = { 162, 116, 67, 52, 35 }; static const u8 reg0x09 [] = { 145, 150, 106, 126, 107 }; @@ -323,15 +322,14 @@ ves1820_writereg (fe, 0x08, reg0x08[real_qam]); ves1820_writereg (fe, 0x09, reg0x09[real_qam]); - ves1820_setup_reg0 (fe, reg0x00[real_qam]); + ves1820_setup_reg0 (fe, reg0x00[real_qam], p->inversion); return 0; } -static -int ves1820_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) +static int ves1820_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) { switch (cmd) { case FE_GET_INFO: @@ -400,15 +398,31 @@ return ves1820_set_parameters (fe, arg); case FE_GET_FRONTEND: - /* XXX FIXME: implement! */ -/* - struct frontend *front = (struct frontend *)arg; + { + struct dvb_frontend_parameters *p = (struct dvb_frontend_parameters *)arg; + u8 reg0 = GET_REG0(fe->data); + int sync; + s8 afc = 0; - front->afc=(int)((char)(readreg(client,0x19))); - front->afc=(front->afc*(int)(front->param.u.qam.SymbolRate/8))/128; -*/ - break; + sync = ves1820_readreg (fe, 0x11); + if (sync & 2) + /* AFC only valid when carrier has been recovered */ + afc = ves1820_readreg(fe, 0x19); + printk ("%s: AFC (%d) %dHz\n", __FILE__, afc, + -((s32)(p->u.qam.symbol_rate >> 3) * afc >> 7)); + + p->inversion = reg0 & 0x20 ? INVERSION_OFF : INVERSION_ON; + p->u.qam.modulation = ((reg0 >> 2) & 7) + QAM_16; + + p->u.qam.fec_inner = FEC_NONE; + + p->frequency = ((p->frequency + 31250) / 62500) * 62500; + // To prevent overflow, shift symbol rate first a + // couple of bits. + p->frequency -= (s32)(p->u.qam.symbol_rate >> 3) * afc >> 7; + break; + } case FE_SLEEP: ves1820_writereg (fe, 0x1b, 0x02); /* pdown ADC */ ves1820_writereg (fe, 0x00, 0x80); /* standby */ @@ -425,13 +439,12 @@ } -static -int probe_tuner (struct dvb_i2c_bus *i2c) +static long probe_tuner (struct dvb_i2c_bus *i2c) { - static const - struct i2c_msg msg1 = { addr: 0x61, flags: 0, buf: NULL, len: 0 }; - static const - struct i2c_msg msg2 = { addr: 0x62, flags: 0, buf: NULL, len: 0 }; + static const struct i2c_msg msg1 = + { .addr = 0x61, .flags = 0, .buf = NULL, .len = 0 }; + static const struct i2c_msg msg2 = + { .addr = 0x62, .flags = 0, .buf = NULL, .len = 0 }; int type; if (i2c->xfer(i2c, &msg1, 1) == 1) { @@ -451,13 +464,12 @@ } -static -u8 read_pwm (struct dvb_i2c_bus *i2c) +static u8 read_pwm (struct dvb_i2c_bus *i2c) { u8 b = 0xff; u8 pwm; - struct i2c_msg msg [] = { { addr: 0x50, flags: 0, buf: &b, len: 1 }, - { addr: 0x50, flags: I2C_M_RD, buf: &pwm, len: 1 } }; + struct i2c_msg msg [] = { { .addr = 0x50, .flags = 0, .buf = &b, .len = 1 }, + { .addr = 0x50, .flags = I2C_M_RD, .buf = &pwm, .len = 1 } }; i2c->xfer (i2c, msg, 2); @@ -470,13 +482,12 @@ } -static -int probe_demod_addr (struct dvb_i2c_bus *i2c) +static long probe_demod_addr (struct dvb_i2c_bus *i2c) { u8 b [] = { 0x00, 0x1a }; u8 id; - struct i2c_msg msg [] = { { addr: 0x08, flags: 0, buf: b, len: 2 }, - { addr: 0x08, flags: I2C_M_RD, buf: &id, len: 1 } }; + struct i2c_msg msg [] = { { .addr = 0x08, .flags = 0, .buf = b, .len = 2 }, + { .addr = 0x08, .flags = I2C_M_RD, .buf = &id, .len = 1 } }; if (i2c->xfer(i2c, msg, 2) == 2 && (id & 0xf0) == 0x70) return msg[0].addr; @@ -490,12 +501,11 @@ } -static -int ves1820_attach (struct dvb_i2c_bus *i2c) +static int ves1820_attach (struct dvb_i2c_bus *i2c) { void *data = NULL; - int demod_addr; - int tuner_type; + long demod_addr; + long tuner_type; if ((demod_addr = probe_demod_addr(i2c)) < 0) return -ENODEV; @@ -514,23 +524,20 @@ } -static -void ves1820_detach (struct dvb_i2c_bus *i2c) +static void ves1820_detach (struct dvb_i2c_bus *i2c) { dvb_unregister_frontend (ves1820_ioctl, i2c); } -static -int __init init_ves1820 (void) +static int __init init_ves1820 (void) { return dvb_register_i2c_device (THIS_MODULE, ves1820_attach, ves1820_detach); } -static -void __exit exit_ves1820 (void) +static void __exit exit_ves1820 (void) { dvb_unregister_i2c_device (ves1820_attach); } diff -Nru a/drivers/media/dvb/ttpci/av7110.c b/drivers/media/dvb/ttpci/av7110.c --- a/drivers/media/dvb/ttpci/av7110.c Tue Jul 1 18:44:36 2003 +++ b/drivers/media/dvb/ttpci/av7110.c Tue Jul 1 18:44:36 2003 @@ -58,23 +58,25 @@ #include #include #include -#include -#include -#include -#include -#include #include #include - #include #include #include #include +#include +#include +#include +#include +#include + #include #include "dvb_i2c.h" #include "dvb_frontend.h" +#include "dvb_functions.h" + #if 1 #define DEBUG_VARIABLE av7110_debug @@ -87,15 +89,16 @@ #include "av7110.h" #include "av7110_ipack.h" -static int AV_StartPlay(av7110_t *av7110, int av); -static void restart_feeds(av7110_t *av7110); -static int bootarm(av7110_t *av7110); -static inline int i2c_writereg(av7110_t *av7110, u8 id, u8 reg, u8 val); -static inline u8 i2c_readreg(av7110_t *av7110, u8 id, u8 reg); -static int outcom(av7110_t *av7110, int type, int com, int num, ...); -static void SetMode(av7110_t *av7110, int mode); +static int AV_StartPlay(struct av7110 *av7110, int av); +static void restart_feeds(struct av7110 *av7110); +static int bootarm(struct av7110 *av7110); +static inline int i2c_writereg(struct av7110 *av7110, u8 id, u8 reg, u8 val); +static inline u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg); +static int outcom(struct av7110 *av7110, int type, int com, int num, ...); +static void SetMode(struct av7110 *av7110, int mode); +static void dvb_video_add_event (struct av7110 *av7110, struct video_event *event); -void pes_to_ts(u8 const *buf, long int length, u16 pid, p2t_t *p); +void pes_to_ts(u8 const *buf, long int length, u16 pid, struct av7110_p2t *p); void p_to_t(u8 const *buf, long int length, u16 pid, u8 *counter, struct dvb_demux_feed *feed); static int av7110_debug = 0; @@ -107,20 +110,7 @@ int av7110_num = 0; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) - #define KBUILD_MODNAME av7110 -#endif - -/**************************************************************************** - * General helper functions - ****************************************************************************/ - -static inline void ddelay(int i) -{ - current->state=TASK_INTERRUPTIBLE; - schedule_timeout((HZ*i)/100); -} - +#define FW_CI_LL_SUPPORT(arm_app) (((arm_app) >> 16) & 0x8000) /**************************************************************************** * DEBI functions @@ -129,8 +119,7 @@ /* This DEBI code is based on the Stradis driver by Nathan Laredo */ -static -int wait_for_debi_done(av7110_t *av7110) +static int wait_for_debi_done(struct av7110 *av7110) { struct saa7146_dev *dev = av7110->dev; int start; @@ -163,7 +152,7 @@ return 0; } -static int debiwrite(av7110_t *av7110, u32 config, +static int debiwrite(struct av7110 *av7110, u32 config, int addr, u32 val, int count) { struct saa7146_dev *dev = av7110->dev; @@ -183,7 +172,7 @@ return 0; } -static u32 debiread(av7110_t *av7110, u32 config, int addr, int count) +static u32 debiread(struct av7110 *av7110, u32 config, int addr, int count) { struct saa7146_dev *dev = av7110->dev; u32 result = 0; @@ -207,16 +196,16 @@ /* DEBI during interrupt */ -static inline void -iwdebi(av7110_t *av7110, u32 config, int addr, u32 val, int count) +/* fixme: val can be a pointer to a memory or an u32 value -- this + won't work on 64bit platforms! */ +static inline void iwdebi(struct av7110 *av7110, u32 config, int addr, u32 val, int count) { if (count>4 && val) memcpy(av7110->debi_virt, (char *) val, count); debiwrite(av7110, config, addr, val, count); } -static inline u32 -irdebi(av7110_t *av7110, u32 config, int addr, u32 val, int count) +static inline u32 irdebi(struct av7110 *av7110, u32 config, int addr, u32 val, int count) { u32 res; @@ -228,8 +217,7 @@ /* DEBI outside interrupts, only for count<=4! */ -static inline void -wdebi(av7110_t *av7110, u32 config, int addr, u32 val, int count) +static inline void wdebi(struct av7110 *av7110, u32 config, int addr, u32 val, int count) { unsigned long flags; @@ -238,8 +226,7 @@ spin_unlock_irqrestore(&av7110->debilock, flags); } -static inline u32 -rdebi(av7110_t *av7110, u32 config, int addr, u32 val, int count) +static inline u32 rdebi(struct av7110 *av7110, u32 config, int addr, u32 val, int count) { unsigned long flags; u32 res; @@ -251,8 +238,7 @@ } -static inline char -chtrans(char c) +static inline char chtrans(char c) { if (c<32 || c>126) c=0x20; @@ -262,8 +248,7 @@ /* handle mailbox registers of the dual ported RAM */ -static inline void -ARM_ResetMailBox(av7110_t *av7110) +static inline void ARM_ResetMailBox(struct av7110 *av7110) { unsigned long flags; @@ -276,20 +261,17 @@ spin_unlock_irqrestore(&av7110->debilock, flags); } -static inline void -ARM_ClearMailBox(av7110_t *av7110) +static inline void ARM_ClearMailBox(struct av7110 *av7110) { iwdebi(av7110, DEBINOSWAP, IRQ_RX, 0, 2); } -static inline void -ARM_ClearIrq(av7110_t *av7110) +static inline void ARM_ClearIrq(struct av7110 *av7110) { irdebi(av7110, DEBINOSWAP, IRQ_RX, 0, 2); } -static void -reset_arm(av7110_t *av7110) +static void reset_arm(struct av7110 *av7110) { saa7146_setgpio(av7110->dev, RESET_LINE, SAA7146_GPIO_OUTLO); @@ -315,8 +297,7 @@ printk("av7110: ARM RESET\n"); } -static void -recover_arm(av7110_t *av7110) +static void recover_arm(struct av7110 *av7110) { DEB_EE(("av7110: %p\n",av7110)); @@ -326,12 +307,13 @@ printk("OOPS, no current->files\n"); reset_arm(av7110); } - ddelay(10); + + dvb_delay(100); restart_feeds(av7110); + outcom(av7110, COMTYPE_PIDFILTER, SetIR, 1, av7110->ir_config); } -static void -arm_error(av7110_t *av7110) +static void arm_error(struct av7110 *av7110) { DEB_EE(("av7110: %p\n",av7110)); @@ -342,25 +324,13 @@ static int arm_thread(void *data) { - av7110_t *av7110 = data; + struct av7110 *av7110 = data; u16 newloops = 0; DEB_EE(("av7110: %p\n",av7110)); - lock_kernel(); -#if 0 - daemonize(); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) - reparent_to_init (); -#endif -#else - exit_mm(current); - current->session=current->pgrp=1; -#endif - sigfillset(¤t->blocked); - strcpy(current->comm, "arm_mon"); + dvb_kernel_thread_setup ("arm_mon"); av7110->arm_thread = current; - unlock_kernel(); while (!av7110->arm_rmmod && !signal_pending(current)) { interruptible_sleep_on_timeout(&av7110->arm_wait, 5*HZ); @@ -394,12 +364,11 @@ } -static int -record_cb(dvb_filter_pes2ts_t *p2t, u8 *buf, size_t len) +static int record_cb(struct dvb_filter_pes2ts *p2t, u8 *buf, size_t len) { struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) p2t->priv; - DEB_EE(("dvb_filter_pes2ts_t:%p\n",p2t)); + DEB_EE(("struct dvb_filter_pes2ts:%p\n",p2t)); if (!(dvbdmxfeed->ts_type & TS_PACKET)) return 0; @@ -412,8 +381,7 @@ return dvb_filter_pes2ts(p2t, buf, len); } -static int -dvb_filter_pes2ts_cb(void *priv, unsigned char *data) +static int dvb_filter_pes2ts_cb(void *priv, unsigned char *data) { struct dvb_demux_feed *dvbdmxfeed=(struct dvb_demux_feed *) priv; @@ -425,8 +393,7 @@ return 0; } -static int -AV_StartRecord(av7110_t *av7110, int av, +static int AV_StartRecord(struct av7110 *av7110, int av, struct dvb_demux_feed *dvbdmxfeed) { struct dvb_demux *dvbdmx=dvbdmxfeed->demux; @@ -471,8 +438,7 @@ return 0; } -static int -AV_StartPlay(av7110_t *av7110, int av) +static int AV_StartPlay(struct av7110 *av7110, int av) { DEB_EE(("av7110: %p\n",av7110)); @@ -505,8 +471,7 @@ return av7110->playing; } -static void -AV_Stop(av7110_t *av7110, int av) +static void AV_Stop(struct av7110 *av7110, int av) { DEB_EE(("av7110: %p\n",av7110)); @@ -548,9 +513,9 @@ * * If we want to support multiple controls we would have to do much more... */ -void av7110_setup_irc_config (av7110_t *av7110, u32 ir_config) +void av7110_setup_irc_config (struct av7110 *av7110, u32 ir_config) { - static av7110_t *last; + static struct av7110 *last; DEB_EE(("av7110: %p\n",av7110)); @@ -559,8 +524,10 @@ else last = av7110; - if (av7110) + if (av7110) { outcom(av7110, COMTYPE_PIDFILTER, SetIR, 1, ir_config); + av7110->ir_config = ir_config; + } } static void (*irc_handler)(u32); @@ -585,7 +552,7 @@ DECLARE_TASKLET(irtask,run_handlers,0); -void IR_handle(av7110_t *av7110, u32 ircom) +void IR_handle(struct av7110 *av7110, u32 ircom) { DEB_S(("av7110: ircommand = %08x\n", ircom)); irtask.data = (unsigned long) ircom; @@ -596,7 +563,7 @@ * IRQ handling ****************************************************************************/ -void CI_handle(av7110_t *av7110, u8 *data, u16 len) +void CI_handle(struct av7110 *av7110, u8 *data, u16 len) { //CI_out(av7110, data, len); @@ -629,12 +596,11 @@ } -static inline int -DvbDmxFilterCallback(u8 * buffer1, size_t buffer1_len, +static inline int DvbDmxFilterCallback(u8 * buffer1, size_t buffer1_len, u8 * buffer2, size_t buffer2_len, struct dvb_demux_filter *dvbdmxfilter, - dmx_success_t success, - av7110_t *av7110) + enum dmx_success success, + struct av7110 *av7110) { DEB_EE(("av7110: %p\n",av7110)); @@ -648,7 +614,7 @@ if ((((buffer1[1]<<8)|buffer1[2])&0xfff)+3!=buffer1_len) return 0; if (dvbdmxfilter->doneq) { - dmx_section_filter_t *filter=&dvbdmxfilter->filter; + struct dmx_section_filter *filter=&dvbdmxfilter->filter; int i; u8 xor, neq=0; @@ -691,8 +657,7 @@ //#define DEBUG_TIMING -inline static void -print_time(char *s) +static inline void print_time(char *s) { #ifdef DEBUG_TIMING struct timeval tv; @@ -701,8 +666,7 @@ #endif } -static void -ci_get_data(dvb_ringbuffer_t *cibuf, u8 *data, int len) +static void ci_get_data(struct dvb_ringbuffer *cibuf, u8 *data, int len) { if (dvb_ringbuffer_free(cibuf) < len+2) return; @@ -715,10 +679,9 @@ wake_up_interruptible(&cibuf->queue); } -static -void debiirq (unsigned long data) +static void debiirq (unsigned long data) { - struct av7110_s *av7110 = (struct av7110_s*) data; + struct av7110 *av7110 = (struct av7110*) data; int type=av7110->debitype; int handle=(type>>8)&0x1f; @@ -731,8 +694,10 @@ if (type==-1) { printk("DEBI irq oops @ %ld, psr:0x%08x, ssr:0x%08x\n",jiffies,saa7146_read(av7110->dev,PSR),saa7146_read(av7110->dev,SSR)); + spin_lock(&av7110->debilock); ARM_ClearMailBox(av7110); ARM_ClearIrq(av7110); + spin_unlock(&av7110->debilock); return; } av7110->debitype=-1; @@ -844,8 +809,7 @@ spin_unlock(&av7110->debilock); } -static int -pes_play(void *dest, dvb_ringbuffer_t *buf, int dlen) +static int pes_play(void *dest, struct dvb_ringbuffer *buf, int dlen) { int len; u32 sync; @@ -876,23 +840,22 @@ blen|=DVB_RINGBUFFER_PEEK(buf,5); blen+=6; if (lendlen) { - printk("buffer empty - avail %d blen %u dlen %d\n",len,blen,dlen); + //printk("buffer empty - avail %d blen %u dlen %d\n",len,blen,dlen); wake_up(&buf->queue); return -1; } (void)dvb_ringbuffer_read(buf,dest,(size_t)blen,0); - DEB_S(("pread=%08x, pwrite=%08x\n",buf->pread, buf->pwrite)); + DEB_S(("pread=0x%08lx, pwrite=0x%08lx\n",(unsigned long)buf->pread, (unsigned long)buf->pwrite)); wake_up(&buf->queue); return blen; } -static -void gpioirq (unsigned long data) +static void gpioirq (unsigned long data) { - struct av7110_s *av7110 = (struct av7110_s*) data; + struct av7110 *av7110 = (struct av7110*) data; u32 rxbuf, txbuf; int len; @@ -926,10 +889,51 @@ case DATA_PES_PLAY: break; + case DATA_MPEG_VIDEO_EVENT: + { + u32 h_ar; + struct video_event event; + + av7110->video_size.w = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_WIDTH, 0, 2); + h_ar = irdebi(av7110, DEBINOSWAP, STATUS_MPEG_HEIGHT_AR, 0, 2); + + iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2); + iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2); + + av7110->video_size.h = h_ar & 0xfff; + DEB_D(("GPIO0 irq: DATA_MPEG_VIDEO_EVENT: w/h/ar = %u/%u/%u\n", + av7110->video_size.w, + av7110->video_size.h, + av7110->video_size.aspect_ratio)); + + event.type = VIDEO_EVENT_SIZE_CHANGED; + event.u.size.w = av7110->video_size.w; + event.u.size.h = av7110->video_size.h; + switch ((h_ar >> 12) & 0xf) + { + case 3: + av7110->video_size.aspect_ratio = VIDEO_FORMAT_16_9; + event.u.size.aspect_ratio = VIDEO_FORMAT_16_9; + av7110->videostate.video_format = VIDEO_FORMAT_16_9; + break; + case 4: + av7110->video_size.aspect_ratio = VIDEO_FORMAT_221_1; + event.u.size.aspect_ratio = VIDEO_FORMAT_221_1; + av7110->videostate.video_format = VIDEO_FORMAT_221_1; + break; + default: + av7110->video_size.aspect_ratio = VIDEO_FORMAT_4_3; + event.u.size.aspect_ratio = VIDEO_FORMAT_4_3; + av7110->videostate.video_format = VIDEO_FORMAT_4_3; + } + dvb_video_add_event(av7110, &event); + break; + } + case DATA_CI_PUT: { int avail; - dvb_ringbuffer_t *cibuf=&av7110->ci_wbuffer; + struct dvb_ringbuffer *cibuf=&av7110->ci_wbuffer; avail=dvb_ringbuffer_avail(cibuf); if (avail<=2) { @@ -1077,7 +1081,7 @@ ****************************************************************************/ -static int OutCommand(av7110_t *av7110, u16* buf, int length) +static int OutCommand(struct av7110 *av7110, u16* buf, int length) { int i; u32 start; @@ -1095,7 +1099,7 @@ start = jiffies; while ( rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2 ) ) { - ddelay(1); + dvb_delay(1); if ((jiffies - start) > ARM_WAIT_FREE) { printk(KERN_ERR "%s: timeout waiting for COMMAND idle\n", __FUNCTION__); return -1; @@ -1106,7 +1110,7 @@ start = jiffies; while ( rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2 ) ) { - ddelay(1); + dvb_delay(1); if ((jiffies - start) > ARM_WAIT_SHAKE) { printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__); return -1; @@ -1117,7 +1121,7 @@ start = jiffies; while ( rdebi(av7110, DEBINOSWAP, MSGSTATE, 0, 2) & OSDQFull ) { - ddelay(1); + dvb_delay(1); if ((jiffies - start) > ARM_WAIT_OSD) { printk(KERN_ERR "%s: timeout waiting for !OSDQFull\n", __FUNCTION__); return -1; @@ -1137,7 +1141,7 @@ start = jiffies; while ( rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2 ) ) { - ddelay(1); + dvb_delay(1); if ((jiffies - start) > ARM_WAIT_FREE) { printk(KERN_ERR "%s: timeout waiting for COMMAND to complete\n", __FUNCTION__); return -1; @@ -1158,8 +1162,7 @@ return 0; } -inline static int -SOutCommand(av7110_t *av7110, u16* buf, int length) +static inline int SOutCommand(struct av7110 *av7110, u16* buf, int length) { int ret; @@ -1181,7 +1184,7 @@ } -static int outcom(av7110_t *av7110, int type, int com, int num, ...) +static int outcom(struct av7110 *av7110, int type, int com, int num, ...) { va_list args; u16 buf[num+2]; @@ -1205,7 +1208,7 @@ return ret; } -int SendCICommand(av7110_t *av7110, u8 subcom, u8 *Params, u8 ParamLen) +int SendCICommand(struct av7110 *av7110, u8 subcom, u8 *Params, u8 ParamLen) { int i, ret; u16 CommandBuffer[18] = { ((COMTYPE_COMMON_IF << 8) + subcom), @@ -1228,7 +1231,7 @@ } -static int CommandRequest(av7110_t *av7110, u16 *Buff, int length, u16 *buf, int n) +static int CommandRequest(struct av7110 *av7110, u16 *Buff, int length, u16 *buf, int n) { int err; s16 i; @@ -1257,7 +1260,7 @@ while ( rdebi(av7110, DEBINOSWAP, COMMAND, 0, 2) ) { #ifdef _NOHANDSHAKE - ddelay(1); + dvb_delay(1); #endif if ((jiffies - start) > ARM_WAIT_FREE) { printk("%s: timeout waiting for COMMAND to complete\n", __FUNCTION__); @@ -1269,7 +1272,7 @@ #ifndef _NOHANDSHAKE start = jiffies; while ( rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2 ) ) { - ddelay(1); + dvb_delay(1); if ((jiffies - start) > ARM_WAIT_SHAKE) { printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__); up(&av7110->dcomlock); @@ -1300,8 +1303,7 @@ } -static inline int -RequestParameter(av7110_t *av7110, u16 tag, u16* Buff, s16 length) +static inline int RequestParameter(struct av7110 *av7110, u16 tag, u16* Buff, s16 length) { int ret; ret = CommandRequest(av7110, &tag, 0, Buff, length); @@ -1315,19 +1317,29 @@ * Firmware commands ****************************************************************************/ +static inline int msp_writereg(struct av7110 *av7110, u8 dev, u16 reg, u16 val) +{ + u8 msg[5]={ dev, reg>>8, reg&0xff, val>>8 , val&0xff }; + struct dvb_i2c_bus *i2c = av7110->i2c_bus; + struct i2c_msg msgs; + + msgs.flags=0; + msgs.addr=0x40; + msgs.len=5; + msgs.buf=msg; + return i2c->xfer(i2c, &msgs, 1); +} -inline static int -SendDAC(av7110_t *av7110, u8 addr, u8 data) +static inline int SendDAC(struct av7110 *av7110, u8 addr, u8 data) { DEB_EE(("av7110: %p\n",av7110)); return outcom(av7110, COMTYPE_AUDIODAC, AudioDAC, 2, addr, data); } -static int -SetVolume(av7110_t *av7110, int volleft, int volright) +static int SetVolume(struct av7110 *av7110, int volleft, int volright) { - int err; + int err, vol, val, balance = 0; DEB_EE(("av7110: %p\n",av7110)); @@ -1349,54 +1361,65 @@ i2c_writereg(av7110, 0x20, 0x03, volleft); i2c_writereg(av7110, 0x20, 0x04, volright); return 0; + + case DVB_ADAC_MSP: + vol = (volleft > volright) ? volleft : volright; + val = (vol * 0x73 / 255) << 8; + if (vol > 0) { + balance = ((volright-volleft) * 127) / vol; + } + msp_writereg(av7110, 0x12, 0x0001, balance << 8); + msp_writereg(av7110, 0x12, 0x0000, val); /* loudspeaker */ + msp_writereg(av7110, 0x12, 0x0006, val); /* headphonesr */ + return 0; } return 0; } #ifdef CONFIG_DVB_AV7110_OSD -inline static int ResetBlend(av7110_t *av7110, u8 windownr) +static inline int ResetBlend(struct av7110 *av7110, u8 windownr) { return outcom(av7110, COMTYPE_OSD, SetNonBlend, 1, windownr); } -inline static int SetColorBlend(av7110_t *av7110, u8 windownr) +static inline int SetColorBlend(struct av7110 *av7110, u8 windownr) { return outcom(av7110, COMTYPE_OSD, SetCBlend, 1, windownr); } -inline static int SetWindowBlend(av7110_t *av7110, u8 windownr, u8 blending) +static inline int SetWindowBlend(struct av7110 *av7110, u8 windownr, u8 blending) { return outcom(av7110, COMTYPE_OSD, SetWBlend, 2, windownr, blending); } -inline static int SetBlend_(av7110_t *av7110, u8 windownr, - OSDPALTYPE colordepth, u16 index, u8 blending) +static inline int SetBlend_(struct av7110 *av7110, u8 windownr, + enum av7110_osd_palette_type colordepth, u16 index, u8 blending) { return outcom(av7110, COMTYPE_OSD, SetBlend, 4, windownr, colordepth, index, blending); } -inline static int SetColor_(av7110_t *av7110, u8 windownr, - OSDPALTYPE colordepth, u16 index, u16 colorhi, u16 colorlo) +static inline int SetColor_(struct av7110 *av7110, u8 windownr, + enum av7110_osd_palette_type colordepth, u16 index, u16 colorhi, u16 colorlo) { return outcom(av7110, COMTYPE_OSD, SetColor, 5, windownr, colordepth, index, colorhi, colorlo); } -inline static int BringToTop(av7110_t *av7110, u8 windownr) +static inline int BringToTop(struct av7110 *av7110, u8 windownr) { return outcom(av7110, COMTYPE_OSD, WTop, 1, windownr); } -inline static int SetFont(av7110_t *av7110, u8 windownr, u8 fontsize, +static inline int SetFont(struct av7110 *av7110, u8 windownr, u8 fontsize, u16 colorfg, u16 colorbg) { return outcom(av7110, COMTYPE_OSD, Set_Font, 4, windownr, fontsize, colorfg, colorbg); } -static int FlushText(av7110_t *av7110) +static int FlushText(struct av7110 *av7110) { u32 start; @@ -1404,7 +1427,7 @@ return -ERESTARTSYS; start = jiffies; while ( rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2 ) ) { - ddelay(1); + dvb_delay(1); if ((jiffies - start) > ARM_WAIT_OSD) { printk(KERN_ERR "%s: timeout waiting for BUFF1_BASE == 0\n", __FUNCTION__); up(&av7110->dcomlock); @@ -1415,7 +1438,7 @@ return 0; } -static int WriteText(av7110_t *av7110, u8 win, u16 x, u16 y, u8* buf) +static int WriteText(struct av7110 *av7110, u8 win, u16 x, u16 y, u8* buf) { int i, ret; u32 start; @@ -1427,7 +1450,7 @@ start = jiffies; while ( rdebi(av7110, DEBINOSWAP, BUFF1_BASE, 0, 2 ) ) { - ddelay(1); + dvb_delay(1); if ((jiffies - start) > ARM_WAIT_OSD) { printk(KERN_ERR "%s: timeout waiting for BUFF1_BASE == 0\n", __FUNCTION__); up(&av7110->dcomlock); @@ -1437,7 +1460,7 @@ #ifndef _NOHANDSHAKE start = jiffies; while ( rdebi(av7110, DEBINOSWAP, HANDSHAKE_REG, 0, 2 ) ) { - ddelay(1); + dvb_delay(1); if ((jiffies - start) > ARM_WAIT_SHAKE) { printk(KERN_ERR "%s: timeout waiting for HANDSHAKE_REG\n", __FUNCTION__); up(&av7110->dcomlock); @@ -1457,42 +1480,42 @@ return ret; } -inline static int DrawLine(av7110_t *av7110, u8 windownr, +static inline int DrawLine(struct av7110 *av7110, u8 windownr, u16 x, u16 y, u16 dx, u16 dy, u16 color) { return outcom(av7110, COMTYPE_OSD, DLine, 6, windownr, x, y, dx, dy, color); } -inline static int DrawBlock(av7110_t *av7110, u8 windownr, +static inline int DrawBlock(struct av7110 *av7110, u8 windownr, u16 x, u16 y, u16 dx, u16 dy, u16 color) { return outcom(av7110, COMTYPE_OSD, DBox, 6, windownr, x, y, dx, dy, color); } -inline static int HideWindow(av7110_t *av7110, u8 windownr) +static inline int HideWindow(struct av7110 *av7110, u8 windownr) { return outcom(av7110, COMTYPE_OSD, WHide, 1, windownr); } -inline static int MoveWindowRel(av7110_t *av7110, u8 windownr, u16 x, u16 y) +static inline int MoveWindowRel(struct av7110 *av7110, u8 windownr, u16 x, u16 y) { return outcom(av7110, COMTYPE_OSD, WMoveD, 3, windownr, x, y); } -inline static int MoveWindowAbs(av7110_t *av7110, u8 windownr, u16 x, u16 y) +static inline int MoveWindowAbs(struct av7110 *av7110, u8 windownr, u16 x, u16 y) { return outcom(av7110, COMTYPE_OSD, WMoveA, 3, windownr, x, y); } -inline static int DestroyOSDWindow(av7110_t *av7110, u8 windownr) +static inline int DestroyOSDWindow(struct av7110 *av7110, u8 windownr) { return outcom(av7110, COMTYPE_OSD, WDestroy, 1, windownr); } #if 0 -static void DestroyOSDWindows(av7110_t *av7110) +static void DestroyOSDWindows(struct av7110 *av7110) { int i; @@ -1501,20 +1524,18 @@ } #endif -static inline int -CreateOSDWindow(av7110_t *av7110, u8 windownr, - DISPTYPE disptype, u16 width, u16 height) +static inline int CreateOSDWindow(struct av7110 *av7110, u8 windownr, + enum av7110_window_display_type disptype, u16 width, u16 height) { return outcom(av7110, COMTYPE_OSD, WCreate, 4, windownr, disptype, width, height); } -static OSDPALTYPE bpp2pal[8]={Pal1Bit, Pal2Bit, 0, Pal4Bit, 0, 0, 0, Pal8Bit}; -static DISPTYPE bpp2bit[8]={BITMAP1, BITMAP2, 0, BITMAP4, 0, 0, 0, BITMAP8}; +static enum av7110_osd_palette_type bpp2pal[8]={Pal1Bit, Pal2Bit, 0, Pal4Bit, 0, 0, 0, Pal8Bit}; +static enum av7110_window_display_type bpp2bit[8]={BITMAP1, BITMAP2, 0, BITMAP4, 0, 0, 0, BITMAP8}; -static inline int -LoadBitmap(av7110_t *av7110, u16 format, u16 dx, u16 dy, int inc, u8* data) +static inline int LoadBitmap(struct av7110 *av7110, u16 format, u16 dx, u16 dy, int inc, u8* data) { int bpp; int i; @@ -1533,7 +1554,7 @@ break; schedule(); } - current->state=TASK_RUNNING; + set_current_state(TASK_RUNNING); remove_wait_queue(&av7110->bmpq, &wait); } if (av7110->bmp_state==BMP_LOADING) @@ -1573,8 +1594,7 @@ return outcom(av7110, COMTYPE_OSD, LoadBmp, 3, format, dx, dy); } -static int -BlitBitmap(av7110_t *av7110, u16 win, u16 x, u16 y, u16 trans) +static int BlitBitmap(struct av7110 *av7110, u16 win, u16 x, u16 y, u16 trans) { DECLARE_WAITQUEUE(wait, current); @@ -1591,7 +1611,7 @@ break; schedule(); } - current->state=TASK_RUNNING; + set_current_state(TASK_RUNNING); remove_wait_queue(&av7110->bmpq, &wait); } if (av7110->bmp_state==BMP_LOADED) @@ -1599,8 +1619,7 @@ return -1; } -static inline int -ReleaseBitmap(av7110_t *av7110) +static inline int ReleaseBitmap(struct av7110 *av7110) { DEB_EE(("av7110: %p\n",av7110)); @@ -1626,8 +1645,7 @@ return Cr|(Cb<<16)|(Y<<8); } -static void -OSDSetColor(av7110_t *av7110, u8 color, u8 r, u8 g, u8 b, u8 blend) +static void OSDSetColor(struct av7110 *av7110, u8 color, u8 r, u8 g, u8 b, u8 blend) { u16 ch, cl; u32 yuv; @@ -1641,8 +1659,7 @@ color, ((blend>>4)&0x0f)); } -static int -OSDSetBlock(av7110_t *av7110, int x0, int y0, int x1, int y1, int inc, u8 *data) +static int OSDSetBlock(struct av7110 *av7110, int x0, int y0, int x1, int y1, int inc, u8 *data) { uint w, h, bpp, bpl, size, lpb, bnum, brest; int i; @@ -1672,8 +1689,7 @@ return 0; } -static int -OSD_DrawCommand(av7110_t *av7110, osd_cmd_t *dc) +static int OSD_DrawCommand(struct av7110 *av7110, osd_cmd_t *dc) { switch (dc->cmd) { case OSD_Close: @@ -1779,12 +1795,11 @@ } -static int -dvb_osd_ioctl(struct inode *inode, struct file *file, +static int dvb_osd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *parg) { struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; - av7110_t *av7110=(av7110_t *) dvbdev->priv; + struct av7110 *av7110=(struct av7110 *) dvbdev->priv; DEB_EE(("av7110: %p\n",av7110)); @@ -1815,8 +1830,7 @@ /* get version of the firmware ROM, RTSL, video ucode and ARM application */ -static void -firmversion(av7110_t *av7110) +static void firmversion(struct av7110 *av7110) { u16 buf[20]; @@ -1837,7 +1851,7 @@ av7110->arm_rtsl, av7110->arm_vid, av7110->arm_app); /* print firmware capabilities */ - if ((av7110->arm_app >> 16) & 0x8000) + if (FW_CI_LL_SUPPORT(av7110->arm_app)) printk ("DVB: AV711%d(%d) - firmware supports CI link layer interface\n", av7110->avtype, av7110->dvb_adapter->num); else @@ -1847,8 +1861,7 @@ return; } -static int -waitdebi(av7110_t *av7110, int adr, int state) +static int waitdebi(struct av7110 *av7110, int adr, int state) { int k; @@ -1862,8 +1875,7 @@ } -static int -load_dram(av7110_t *av7110, u32 *data, int len) +static int load_dram(struct av7110 *av7110, u32 *data, int len) { int i; int blocks, rest; @@ -1911,8 +1923,7 @@ } -static u8 -bootcode[] = { +static u8 bootcode[] = { 0xea, 0x00, 0x00, 0x0e, 0xe1, 0xb0, 0xf0, 0x0e, /* 0x0000 */ 0xe2, 0x5e, 0xf0, 0x04, 0xe2, 0x5e, 0xf0, 0x04, 0xe2, 0x5e, 0xf0, 0x08, 0xe2, 0x5e, 0xf0, 0x04, @@ -1938,8 +1949,7 @@ #include "av7110_firm.h" -static int -bootarm(av7110_t *av7110) +static int bootarm(struct av7110 *av7110) { struct saa7146_dev *dev= av7110->dev; u32 ret; @@ -1986,7 +1996,7 @@ wait_for_debi_done(av7110); saa7146_setgpio(dev, RESET_LINE, SAA7146_GPIO_OUTHI); - current->state=TASK_INTERRUPTIBLE; + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ); DEB_D(("bootarm: load dram code\n")); @@ -2018,22 +2028,25 @@ return 0; } -static inline int -SetPIDs(av7110_t *av7110, u16 vpid, u16 apid, u16 ttpid, +static inline int SetPIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid, u16 subpid, u16 pcrpid) { DEB_EE(("av7110: %p\n",av7110)); if (vpid == 0x1fff || apid == 0x1fff || - ttpid == 0x1fff || subpid == 0x1fff || pcrpid == 0x1fff) + ttpid == 0x1fff || subpid == 0x1fff || pcrpid == 0x1fff) { vpid = apid = ttpid = subpid = pcrpid = 0; + av7110->pids[DMX_PES_VIDEO] = 0; + av7110->pids[DMX_PES_AUDIO] = 0; + av7110->pids[DMX_PES_TELETEXT] = 0; + av7110->pids[DMX_PES_PCR] = 0; + } return outcom(av7110, COMTYPE_PIDFILTER, MultiPID, 5, pcrpid, vpid, apid, ttpid, subpid); } -static void -ChangePIDs(av7110_t *av7110, u16 vpid, u16 apid, u16 ttpid, +static void ChangePIDs(struct av7110 *av7110, u16 vpid, u16 apid, u16 ttpid, u16 subpid, u16 pcrpid) { DEB_EE(("av7110: %p\n",av7110)); @@ -2048,15 +2061,16 @@ av7110->pids[DMX_PES_SUBTITLE]=0; - if (av7110->fe_synced) + if (av7110->fe_synced) { + pcrpid = av7110->pids[DMX_PES_PCR]; SetPIDs(av7110, vpid, apid, ttpid, subpid, pcrpid); + } up(&av7110->pid_mutex); } -static void -SetMode(av7110_t *av7110, int mode) +static void SetMode(struct av7110 *av7110, int mode) { DEB_EE(("av7110: %p\n",av7110)); @@ -2071,23 +2085,20 @@ } } -inline static void -TestMode(av7110_t *av7110, int mode) +static inline void TestMode(struct av7110 *av7110, int mode) { DEB_EE(("av7110: %p\n",av7110)); outcom(av7110, COMTYPE_ENCODER, SetTestMode, 1, mode); } -inline static void -VidMode(av7110_t *av7110, int mode) +static inline void VidMode(struct av7110 *av7110, int mode) { DEB_EE(("av7110: %p\n",av7110)); outcom(av7110, COMTYPE_ENCODER, SetVidMode, 1, mode); } -static int inline -vidcom(av7110_t *av7110, u32 com, u32 arg) +static inline int vidcom(struct av7110 *av7110, u32 com, u32 arg) { DEB_EE(("av7110: %p\n",av7110)); return outcom(av7110, 0x80, 0x02, 4, @@ -2095,24 +2106,21 @@ (arg>>16), (arg&0xffff)); } -static int inline -audcom(av7110_t *av7110, u32 com) +static inline int audcom(struct av7110 *av7110, u32 com) { DEB_EE(("av7110: %p\n",av7110)); return outcom(av7110, 0x80, 0x03, 4, (com>>16), (com&0xffff)); } -inline static void -Set22K(av7110_t *av7110, int state) +static inline void Set22K(struct av7110 *av7110, int state) { DEB_EE(("av7110: %p\n",av7110)); outcom(av7110, COMTYPE_AUDIODAC, (state ? ON22K : OFF22K), 0); } -static -int SendDiSEqCMsg(av7110_t *av7110, int len, u8 *msg, int burst) +static int SendDiSEqCMsg(struct av7110 *av7110, int len, u8 *msg, unsigned long burst) { int i; u16 buf[18] = { ((COMTYPE_AUDIODAC << 8) + SendDiSEqC), @@ -2144,8 +2152,7 @@ * I2C client commands ****************************************************************************/ -static inline int -i2c_writereg(av7110_t *av7110, u8 id, u8 reg, u8 val) +static inline int i2c_writereg(struct av7110 *av7110, u8 id, u8 reg, u8 val) { u8 msg[2]={ reg, val }; struct dvb_i2c_bus *i2c = av7110->i2c_bus; @@ -2158,22 +2165,7 @@ return i2c->xfer (i2c, &msgs, 1); } -static inline int -msp_writereg(av7110_t *av7110, u8 dev, u16 reg, u16 val) -{ - u8 msg[5]={ dev, reg>>8, reg&0xff, val>>8 , val&0xff }; - struct dvb_i2c_bus *i2c = av7110->i2c_bus; - struct i2c_msg msgs; - - msgs.flags=0; - msgs.addr=0x40; - msgs.len=5; - msgs.buf=msg; - return i2c->xfer(i2c, &msgs, 1); -} - -static inline u8 -i2c_readreg(av7110_t *av7110, u8 id, u8 reg) +static inline u8 i2c_readreg(struct av7110 *av7110, u8 id, u8 reg) { struct dvb_i2c_bus *i2c = av7110->i2c_bus; u8 mm1[] = {0x00}; @@ -2203,8 +2195,7 @@ VIDEO_MODE_PAL, VIDEO_MODE_PAL, VIDEO_MODE_PAL, VIDEO_MODE_PAL, }; -static void -get_video_format(av7110_t *av7110, u8 *buf, int count) +static void get_video_format(struct av7110 *av7110, u8 *buf, int count) { int i; int hsize,vsize; @@ -2230,8 +2221,7 @@ } } -static inline long -aux_ring_buffer_write(dvb_ringbuffer_t *rbuf, const char *buf, unsigned long count) +static inline long aux_ring_buffer_write(struct dvb_ringbuffer *rbuf, const char *buf, unsigned long count) { unsigned long todo = count; int free; @@ -2253,10 +2243,9 @@ return count-todo; } -static void -play_video_cb(u8 *buf, int count, void *priv) +static void play_video_cb(u8 *buf, int count, void *priv) { - av7110_t *av7110=(av7110_t *) priv; + struct av7110 *av7110=(struct av7110 *) priv; DEB_EE(("av7110: %p\n",av7110)); if ((buf[3]&0xe0)==0xe0) { @@ -2266,10 +2255,9 @@ aux_ring_buffer_write(&av7110->aout, buf, count); } -static void -play_audio_cb(u8 *buf, int count, void *priv) +static void play_audio_cb(u8 *buf, int count, void *priv) { - av7110_t *av7110=(av7110_t *) priv; + struct av7110 *av7110=(struct av7110 *) priv; DEB_EE(("av7110: %p\n",av7110)); aux_ring_buffer_write(&av7110->aout, buf, count); @@ -2277,8 +2265,7 @@ #define FREE_COND (dvb_ringbuffer_free(&av7110->avout)>=20*1024 && dvb_ringbuffer_free(&av7110->aout)>=20*1024) -static ssize_t -dvb_play(av7110_t *av7110, const u8 *buf, +static ssize_t dvb_play(struct av7110 *av7110, const u8 *buf, unsigned long count, int nonblock, int type, int umem) { unsigned long todo = count, n; @@ -2316,8 +2303,7 @@ return count-todo; } -static ssize_t -dvb_aplay(av7110_t *av7110, const u8 *buf, +static ssize_t dvb_aplay(struct av7110 *av7110, const u8 *buf, unsigned long count, int nonblock, int type) { unsigned long todo = count, n; @@ -2351,7 +2337,7 @@ return count-todo; } -void init_p2t(p2t_t *p, struct dvb_demux_feed *feed) +void init_p2t(struct av7110_p2t *p, struct dvb_demux_feed *feed) { memset(p->pes,0,TS_SIZE); p->counter = 0; @@ -2360,7 +2346,7 @@ if (feed) p->feed = feed; } -void clear_p2t(p2t_t *p) +void clear_p2t(struct av7110_p2t *p) { memset(p->pes,0,TS_SIZE); // p->counter = 0; @@ -2414,7 +2400,7 @@ return c; } -void pes_to_ts( u8 const *buf, long int length, u16 pid, p2t_t *p) +void pes_to_ts( u8 const *buf, long int length, u16 pid, struct av7110_p2t *p) { int c,c2,l,add; int check,rest; @@ -2634,11 +2620,10 @@ return 0; } -static -unsigned int dvb_audio_poll(struct file *file, poll_table *wait) +static unsigned int dvb_audio_poll(struct file *file, poll_table *wait) { struct dvb_device *dvbdev = (struct dvb_device *) file->private_data; - av7110_t *av7110 = (av7110_t *) dvbdev->priv; + struct av7110 *av7110 = (struct av7110 *) dvbdev->priv; unsigned int mask = 0; DEB_EE(("av7110: %p\n",av7110)); @@ -2669,11 +2654,10 @@ * hardware filter functions ******************************************************************************/ -static int -StartHWFilter(struct dvb_demux_filter *dvbdmxfilter) +static int StartHWFilter(struct dvb_demux_filter *dvbdmxfilter) { struct dvb_demux_feed *dvbdmxfeed=dvbdmxfilter->feed; - av7110_t *av7110=(av7110_t *) dvbdmxfeed->demux->priv; + struct av7110 *av7110=(struct av7110 *) dvbdmxfeed->demux->priv; u16 buf[20]; int ret, i; u16 handle; @@ -2713,10 +2697,9 @@ return ret; } -static int -StopHWFilter(struct dvb_demux_filter *dvbdmxfilter) +static int StopHWFilter(struct dvb_demux_filter *dvbdmxfilter) { - av7110_t *av7110=(av7110_t *) dvbdmxfilter->feed->demux->priv; + struct av7110 *av7110=(struct av7110 *) dvbdmxfilter->feed->demux->priv; u16 buf[3]; u16 answ[2]; int ret; @@ -2749,12 +2732,11 @@ } -static int -av7110_write_to_decoder(struct dvb_demux_feed *feed, const u8 *buf, size_t len) +static int av7110_write_to_decoder(struct dvb_demux_feed *feed, const u8 *buf, size_t len) { struct dvb_demux *demux = feed->demux; - av7110_t *av7110 = (av7110_t *) demux->priv; - ipack *ipack = &av7110->ipack[feed->pes_type]; + struct av7110 *av7110 = (struct av7110 *) demux->priv; + struct ipack *ipack = &av7110->ipack[feed->pes_type]; DEB_EE(("av7110: %p\n",av7110)); @@ -2789,11 +2771,10 @@ } -static void -dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed) +static void dvb_feed_start_pid(struct dvb_demux_feed *dvbdmxfeed) { struct dvb_demux *dvbdmx=dvbdmxfeed->demux; - av7110_t *av7110=(av7110_t *) dvbdmx->priv; + struct av7110 *av7110=(struct av7110 *) dvbdmx->priv; u16 *pid=dvbdmx->pids, npids[5]; int i; @@ -2809,7 +2790,7 @@ StartHWFilter(dvbdmxfeed->filter); return; } - if (dvbdmxfeed->pes_type<=2) + if (dvbdmxfeed->pes_type<=2 || dvbdmxfeed->pes_type==4) ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]); if (dvbdmxfeed->pes_type<2 && npids[0]) @@ -2828,11 +2809,10 @@ } } -static void -dvb_feed_stop_pid(struct dvb_demux_feed *dvbdmxfeed) +static void dvb_feed_stop_pid(struct dvb_demux_feed *dvbdmxfeed) { struct dvb_demux *dvbdmx=dvbdmxfeed->demux; - av7110_t *av7110=(av7110_t *) dvbdmx->priv; + struct av7110 *av7110=(struct av7110 *) dvbdmx->priv; u16 *pid=dvbdmx->pids, npids[5]; int i; @@ -2866,11 +2846,10 @@ ChangePIDs(av7110, npids[1], npids[0], npids[2], npids[3], npids[4]); } -static int -av7110_start_feed(struct dvb_demux_feed *feed) +static int av7110_start_feed(struct dvb_demux_feed *feed) { struct dvb_demux *demux = feed->demux; - av7110_t *av7110 = (av7110_t *) demux->priv; + struct av7110 *av7110 = (struct av7110 *) demux->priv; DEB_EE(("av7110: %p\n",av7110)); @@ -2925,11 +2904,10 @@ } -static int -av7110_stop_feed(struct dvb_demux_feed *feed) +static int av7110_stop_feed(struct dvb_demux_feed *feed) { struct dvb_demux *demux = feed->demux; - av7110_t *av7110 = (av7110_t *) demux->priv; + struct av7110 *av7110 = (struct av7110 *) demux->priv; DEB_EE(("av7110: %p\n",av7110)); @@ -2966,8 +2944,7 @@ } -static void -restart_feeds(av7110_t *av7110) +static void restart_feeds(struct av7110 *av7110) { struct dvb_demux *dvbdmx=&av7110->demux; struct dvb_demux_feed *feed; @@ -2990,14 +2967,53 @@ AV_StartPlay(av7110, mode); } +static int dvb_get_stc(struct dmx_demux *demux, unsigned int num, + uint64_t *stc, unsigned int *base) +{ + int ret; + u16 fwstc[4]; + u16 tag = ((COMTYPE_REQUEST << 8) + ReqSTC); + struct dvb_demux *dvbdemux; + struct av7110 *av7110; + + /* pointer casting paranoia... */ + if (!demux) + BUG(); + dvbdemux = (struct dvb_demux *) demux->priv; + if (!dvbdemux) + BUG(); + av7110 = (struct av7110 *) dvbdemux->priv; + + DEB_EE(("av7110: %p\n",av7110)); + + if (num != 0) + return -EINVAL; + + ret = CommandRequest(av7110, &tag, 0, fwstc, 4); + if (ret) { + printk(KERN_ERR "%s: CommandRequest error\n", __FUNCTION__); + return -EIO; + } + DEB_EE(("av7110: fwstc = %04hx %04hx %04hx %04hx\n", + fwstc[0], fwstc[1], fwstc[2], fwstc[3])); + + *stc = (((uint64_t)fwstc[2] & 1) << 32) | + (((uint64_t)fwstc[1]) << 16) | ((uint64_t)fwstc[0]); + *base = 1; + + DEB_EE(("av7110: stc = %lu\n", (unsigned long)*stc)); + + return 0; +} + + /****************************************************************************** * SEC device file operations ******************************************************************************/ -static -int av7110_diseqc_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) +static int av7110_diseqc_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg) { - av7110_t *av7110 = fe->before_after_data; + struct av7110 *av7110 = fe->before_after_data; DEB_EE(("av7110: %p\n",av7110)); @@ -3018,13 +3034,12 @@ case FE_DISEQC_SEND_MASTER_CMD: { struct dvb_diseqc_master_cmd *cmd = arg; - - SendDiSEqCMsg (av7110, cmd->msg_len, cmd->msg, 0); + SendDiSEqCMsg (av7110, cmd->msg_len, cmd->msg, -1); break; } case FE_DISEQC_SEND_BURST: - SendDiSEqCMsg (av7110, 0, NULL, (int) arg); + SendDiSEqCMsg (av7110, 0, NULL, (unsigned long)arg); break; default: @@ -3038,20 +3053,20 @@ * CI link layer file ops (FIXME: move this to separate module later) ******************************************************************************/ -int ci_ll_init(dvb_ringbuffer_t *cirbuf, dvb_ringbuffer_t *ciwbuf, int size) +int ci_ll_init(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf, int size) { dvb_ringbuffer_init(cirbuf, vmalloc(size), size); dvb_ringbuffer_init(ciwbuf, vmalloc(size), size); return 0; } -void ci_ll_flush(dvb_ringbuffer_t *cirbuf, dvb_ringbuffer_t *ciwbuf) +void ci_ll_flush(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf) { dvb_ringbuffer_flush_spinlock_wakeup(cirbuf); dvb_ringbuffer_flush_spinlock_wakeup(ciwbuf); } -void ci_ll_release(dvb_ringbuffer_t *cirbuf, dvb_ringbuffer_t *ciwbuf) +void ci_ll_release(struct dvb_ringbuffer *cirbuf, struct dvb_ringbuffer *ciwbuf) { vfree(cirbuf->data); cirbuf->data=0; @@ -3060,7 +3075,7 @@ } -int ci_ll_reset(dvb_ringbuffer_t *cibuf, struct file *file, +int ci_ll_reset(struct dvb_ringbuffer *cibuf, struct file *file, int slots, ca_slot_info_t *slot) { int i; @@ -3086,8 +3101,7 @@ return 0; } -static ssize_t -ci_ll_write(dvb_ringbuffer_t *cibuf, struct file *file, const char *buf, size_t count, loff_t *ppos) +static ssize_t ci_ll_write(struct dvb_ringbuffer *cibuf, struct file *file, const char *buf, size_t count, loff_t *ppos) { int free; int non_blocking=file->f_flags&O_NONBLOCK; @@ -3109,8 +3123,7 @@ return dvb_ringbuffer_write(cibuf,buf,count,1); } -static ssize_t -ci_ll_read(dvb_ringbuffer_t *cibuf, struct file *file, char *buf, size_t count, loff_t *ppos) +static ssize_t ci_ll_read(struct dvb_ringbuffer *cibuf, struct file *file, char *buf, size_t count, loff_t *ppos) { int avail; int non_blocking=file->f_flags&O_NONBLOCK; @@ -3135,11 +3148,10 @@ return dvb_ringbuffer_read(cibuf,buf,len,1); } -static int -dvb_ca_open(struct inode *inode, struct file *file) +static int dvb_ca_open(struct inode *inode, struct file *file) { struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; - av7110_t *av7110=(av7110_t *) dvbdev->priv; + struct av7110 *av7110=(struct av7110 *) dvbdev->priv; int err=dvb_generic_open(inode, file); DEB_EE(("av7110: %p\n",av7110)); @@ -3150,13 +3162,12 @@ return 0; } -static -unsigned int dvb_ca_poll (struct file *file, poll_table *wait) +static unsigned int dvb_ca_poll (struct file *file, poll_table *wait) { struct dvb_device *dvbdev = (struct dvb_device *) file->private_data; - av7110_t *av7110 = (av7110_t *) dvbdev->priv; - dvb_ringbuffer_t *rbuf = &av7110->ci_rbuffer; - dvb_ringbuffer_t *wbuf = &av7110->ci_wbuffer; + struct av7110 *av7110 = (struct av7110 *) dvbdev->priv; + struct dvb_ringbuffer *rbuf = &av7110->ci_rbuffer; + struct dvb_ringbuffer *wbuf = &av7110->ci_wbuffer; unsigned int mask = 0; DEB_EE(("av7110: %p\n",av7110)); @@ -3172,12 +3183,11 @@ return mask; } -static -int dvb_ca_ioctl(struct inode *inode, struct file *file, +static int dvb_ca_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *parg) { struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; - av7110_t *av7110=(av7110_t *) dvbdev->priv; + struct av7110 *av7110=(struct av7110 *) dvbdev->priv; unsigned long arg=(unsigned long) parg; DEB_EE(("av7110: %p\n",av7110)); @@ -3196,7 +3206,7 @@ cap.slot_num=2; #ifdef NEW_CI - cap.slot_type=CA_CI_LINK|CA_DESCR; + cap.slot_type=(FW_CI_LL_SUPPORT(av7110->arm_app) ? CA_CI_LINK : CA_CI) | CA_DESCR; #else cap.slot_type=CA_CI|CA_DESCR; #endif @@ -3214,7 +3224,7 @@ return -EINVAL; av7110->ci_slot[info->num].num = info->num; #ifdef NEW_CI - av7110->ci_slot[info->num].type = CA_CI_LINK; + av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ? CA_CI_LINK : CA_CI; #else av7110->ci_slot[info->num].type = CA_CI; #endif @@ -3261,22 +3271,20 @@ return 0; } -static ssize_t -dvb_ca_write(struct file *file, const char *buf, +static ssize_t dvb_ca_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; - av7110_t *av7110=(av7110_t *) dvbdev->priv; + struct av7110 *av7110=(struct av7110 *) dvbdev->priv; DEB_EE(("av7110: %p\n",av7110)); return ci_ll_write(&av7110->ci_wbuffer, file, buf, count, ppos); } -static ssize_t -dvb_ca_read(struct file *file, char *buf, size_t count, loff_t *ppos) +static ssize_t dvb_ca_read(struct file *file, char *buf, size_t count, loff_t *ppos) { struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; - av7110_t *av7110=(av7110_t *) dvbdev->priv; + struct av7110 *av7110=(struct av7110 *) dvbdev->priv; DEB_EE(("av7110: %p\n",av7110)); return ci_ll_read(&av7110->ci_rbuffer, file, buf, count, ppos); @@ -3285,35 +3293,103 @@ /****************************************************************************** + * Video MPEG decoder events + ******************************************************************************/ +static void dvb_video_add_event (struct av7110 *av7110, struct video_event *event) +{ + struct dvb_video_events *events = &av7110->video_events; + int wp; + + DEB_D(("\n")); + + spin_lock_bh(&events->lock); + + wp = (events->eventw + 1) % MAX_VIDEO_EVENT; + + if (wp == events->eventr) { + events->overflow = 1; + events->eventr = (events->eventr + 1) % MAX_VIDEO_EVENT; + } + + //FIXME: timestamp? + memcpy(&events->events[events->eventw], event, sizeof(struct video_event)); + + events->eventw = wp; + + spin_unlock_bh(&events->lock); + + wake_up_interruptible (&events->wait_queue); +} + + +static int dvb_video_get_event (struct av7110 *av7110, struct video_event *event, int flags) +{ + struct dvb_video_events *events = &av7110->video_events; + + DEB_D(("\n")); + + if (events->overflow) { + events->overflow = 0; + return -EOVERFLOW; + } + + if (events->eventw == events->eventr) { + int ret; + + if (flags & O_NONBLOCK) + return -EWOULDBLOCK; + + ret = wait_event_interruptible (events->wait_queue, + events->eventw != events->eventr); + if (ret < 0) + return ret; + } + + spin_lock_bh(&events->lock); + + memcpy (event, &events->events[events->eventr], + sizeof(struct video_event)); + + events->eventr = (events->eventr + 1) % MAX_VIDEO_EVENT; + + spin_unlock_bh(&events->lock); + + return 0; +} + + +/****************************************************************************** * DVB device file operations ******************************************************************************/ -static -unsigned int dvb_video_poll(struct file *file, poll_table *wait) +static unsigned int dvb_video_poll(struct file *file, poll_table *wait) { struct dvb_device *dvbdev = (struct dvb_device *) file->private_data; - av7110_t *av7110 = (av7110_t *) dvbdev->priv; + struct av7110 *av7110 = (struct av7110 *) dvbdev->priv; unsigned int mask = 0; DEB_EE(("av7110: %p\n",av7110)); poll_wait(file, &av7110->avout.queue, wait); + poll_wait(file, &av7110->video_events.wait_queue, wait); + + if (av7110->video_events.eventw != av7110->video_events.eventr) + mask = POLLPRI; if (av7110->playing) { if (FREE_COND) mask |= (POLLOUT | POLLWRNORM); } else /* if not playing: may play if asked for */ - mask = (POLLOUT | POLLWRNORM); + mask |= (POLLOUT | POLLWRNORM); return mask; } -static ssize_t -dvb_video_write(struct file *file, const char *buf, +static ssize_t dvb_video_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; - av7110_t *av7110=(av7110_t *) dvbdev->priv; + struct av7110 *av7110=(struct av7110 *) dvbdev->priv; DEB_EE(("av7110: %p\n",av7110)); @@ -3323,12 +3399,11 @@ return dvb_play(av7110, buf, count, file->f_flags&O_NONBLOCK, 1, 1); } -static ssize_t -dvb_audio_write(struct file *file, const char *buf, +static ssize_t dvb_audio_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; - av7110_t *av7110=(av7110_t *) dvbdev->priv; + struct av7110 *av7110=(struct av7110 *) dvbdev->priv; DEB_EE(("av7110: %p\n",av7110)); @@ -3343,33 +3418,34 @@ #define MIN_IFRAME 400000 -static void -play_iframe(av7110_t *av7110, u8 *buf, unsigned int len, int nonblock) +static int play_iframe(struct av7110 *av7110, u8 *buf, unsigned int len, int nonblock) { int i, n=1; DEB_EE(("av7110: %p\n",av7110)); if (!(av7110->playing&RP_VIDEO)) { - AV_StartPlay(av7110, RP_VIDEO); + if (AV_StartPlay(av7110, RP_VIDEO) < 0) + return -EBUSY; n=MIN_IFRAME/len+1; } + /* FIXME: nonblock? */ dvb_play(av7110, iframe_header, sizeof(iframe_header), 0, 1, 0); for (i=0; iipack[1]); + return 0; } -static int -dvb_video_ioctl(struct inode *inode, struct file *file, +static int dvb_video_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *parg) { struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; - av7110_t *av7110=(av7110_t *) dvbdev->priv; + struct av7110 *av7110=(struct av7110 *) dvbdev->priv; unsigned long arg=(unsigned long) parg; int ret=0; @@ -3441,8 +3517,12 @@ break; case VIDEO_GET_EVENT: - //FIXME: write firmware support for this - ret=-EOPNOTSUPP; + ret=dvb_video_get_event(av7110, parg, file->f_flags); + break; + + case VIDEO_GET_SIZE: + memcpy(parg, &av7110->video_size, sizeof(video_size_t)); + break; case VIDEO_SET_DISPLAY_FORMAT: { @@ -3488,8 +3568,9 @@ { struct video_still_picture *pic= (struct video_still_picture *) parg; + av7110->videostate.stream_source = VIDEO_SOURCE_MEMORY; dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout); - play_iframe(av7110, pic->iFrame, pic->size, + ret = play_iframe(av7110, pic->iFrame, pic->size, file->f_flags&O_NONBLOCK); break; } @@ -3555,12 +3636,11 @@ return ret; } -static int -dvb_audio_ioctl(struct inode *inode, struct file *file, +static int dvb_audio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *parg) { struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; - av7110_t *av7110=(av7110_t *) dvbdev->priv; + struct av7110 *av7110=(struct av7110 *) dvbdev->priv; unsigned long arg=(unsigned long) parg; int ret=0; @@ -3680,7 +3760,7 @@ static int dvb_video_open(struct inode *inode, struct file *file) { struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; - av7110_t *av7110=(av7110_t *) dvbdev->priv; + struct av7110 *av7110=(struct av7110 *) dvbdev->priv; int err; DEB_EE(("av7110: %p\n",av7110)); @@ -3692,13 +3772,18 @@ av7110->video_blank=1; av7110->audiostate.AV_sync_state=1; av7110->videostate.stream_source=VIDEO_SOURCE_DEMUX; + + if ((file->f_flags & O_ACCMODE) != O_RDONLY) + /* empty event queue */ + av7110->video_events.eventr = av7110->video_events.eventw = 0; + return 0; } static int dvb_video_release(struct inode *inode, struct file *file) { struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; - av7110_t *av7110=(av7110_t *) dvbdev->priv; + struct av7110 *av7110=(struct av7110 *) dvbdev->priv; DEB_EE(("av7110: %p\n",av7110)); @@ -3709,7 +3794,7 @@ static int dvb_audio_open(struct inode *inode, struct file *file) { struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; - av7110_t *av7110=(av7110_t *) dvbdev->priv; + struct av7110 *av7110=(struct av7110 *) dvbdev->priv; int err=dvb_generic_open(inode, file); DEB_EE(("av7110: %p\n",av7110)); @@ -3724,7 +3809,7 @@ static int dvb_audio_release(struct inode *inode, struct file *file) { struct dvb_device *dvbdev=(struct dvb_device *) file->private_data; - av7110_t *av7110=(av7110_t *) dvbdev->priv; + struct av7110 *av7110=(struct av7110 *) dvbdev->priv; DEB_EE(("av7110: %p\n",av7110)); @@ -3791,10 +3876,9 @@ }; -static -void av7110_before_after_tune (fe_status_t s, void *data) +static void av7110_before_after_tune (fe_status_t s, void *data) { - struct av7110_s *av7110 = data; + struct av7110 *av7110 = data; DEB_EE(("av7110: %p\n",av7110)); @@ -3819,11 +3903,9 @@ } -static -int av7110_register(av7110_t *av7110) +static int av7110_register(struct av7110 *av7110) { int ret, i; - dmx_frontend_t *dvbfront=&av7110->hw_frontend; struct dvb_demux *dvbdemux=&av7110->demux; DEB_EE(("av7110: %p\n",av7110)); @@ -3856,8 +3938,6 @@ av7110->videostate.display_format=VIDEO_CENTER_CUT_OUT; av7110->display_ar=VIDEO_FORMAT_4_3; - memcpy(av7110->demux_id, "demux0_0", 9); - av7110->demux_id[5] = av7110->dvb_adapter->num + '0'; dvbdemux->priv = (void *) av7110; for (i=0; i<32; i++) @@ -3868,18 +3948,11 @@ dvbdemux->start_feed = av7110_start_feed; dvbdemux->stop_feed = av7110_stop_feed; dvbdemux->write_to_decoder = av7110_write_to_decoder; - dvbdemux->dmx.vendor = "TI"; - dvbdemux->dmx.model = "AV7110"; - dvbdemux->dmx.id = av7110->demux_id; dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING); dvb_dmx_init(&av7110->demux); - - dvbfront->id = "hw_frontend"; - dvbfront->vendor = "VLSI"; - dvbfront->model = "DVB Frontend"; - dvbfront->source = DMX_FRONTEND_0; + av7110->demux.dmx.get_stc = dvb_get_stc; av7110->dmxdev.filternum = 32; av7110->dmxdev.demux = &dvbdemux->dmx; @@ -3887,14 +3960,13 @@ dvb_dmxdev_init(&av7110->dmxdev, av7110->dvb_adapter); - ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, - &av7110->hw_frontend); + av7110->hw_frontend.source = DMX_FRONTEND_0; + + ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->hw_frontend); + if (ret < 0) return ret; - av7110->mem_frontend.id = "mem_frontend"; - av7110->mem_frontend.vendor = "memory"; - av7110->mem_frontend.model = "sw"; av7110->mem_frontend.source = DMX_MEMORY_FE; ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &av7110->mem_frontend); @@ -3907,6 +3979,12 @@ if (ret < 0) return ret; + init_waitqueue_head(&av7110->video_events.wait_queue); + spin_lock_init(&av7110->video_events.lock); + av7110->video_events.eventw = av7110->video_events.eventr = 0; + av7110->video_events.overflow = 0; + memset(&av7110->video_size, 0, sizeof (video_size_t)); + dvb_register_device(av7110->dvb_adapter, &av7110->video_dev, &dvbdev_video, av7110, DVB_DEVICE_VIDEO); @@ -3935,8 +4013,7 @@ } -static void -dvb_unregister(av7110_t *av7110) +static void dvb_unregister(struct av7110 *av7110) { struct dvb_demux *dvbdemux=&av7110->demux; @@ -3970,8 +4047,7 @@ // } } -static -int master_xfer (struct dvb_i2c_bus *i2c, const struct i2c_msg msgs[], int num) +static int master_xfer (struct dvb_i2c_bus *i2c, const struct i2c_msg msgs[], int num) { struct saa7146_dev *dev = i2c->data; return saa7146_i2c_transfer(dev, msgs, num, 6); @@ -3988,21 +4064,20 @@ { 0, 0 } }; -static -int av7110_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *pci_ext) +static int av7110_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *pci_ext) { - av7110_t *av7110 = NULL; + struct av7110 *av7110 = NULL; int ret = 0; - if (!(av7110 = kmalloc (sizeof (struct av7110_s), GFP_KERNEL))) { + if (!(av7110 = kmalloc (sizeof (struct av7110), GFP_KERNEL))) { printk ("%s: out of memory!\n", __FUNCTION__); return -ENOMEM; } - memset(av7110, 0, sizeof(av7110_t)); + memset(av7110, 0, sizeof(struct av7110)); av7110->card_name = (char*)pci_ext->ext_priv; - (av7110_t*)dev->ext_priv = av7110; + (struct av7110*)dev->ext_priv = av7110; DEB_EE(("dev: %p, av7110: %p\n",dev,av7110)); @@ -4062,9 +4137,6 @@ av7110->debilock=SPIN_LOCK_UNLOCKED; av7110->debitype=-1; - /* default ADAC type */ - av7110->adac_type = adac; - /* default OSD window */ av7110->osdwin=1; @@ -4120,30 +4192,32 @@ kernel_thread(arm_thread, (void *) av7110, 0); + /* set internal volume control to maximum */ + av7110->adac_type = DVB_ADAC_TI; SetVolume(av7110, 0xff, 0xff); + VidMode(av7110, vidmode); /* remaining inits according to card and frontend type */ if (i2c_writereg(av7110, 0x20, 0x00, 0x00)==1) { - printk ("av7110%d: Crystal audio DAC detected\n", + printk ("av7110(%d): Crystal audio DAC detected\n", av7110->dvb_adapter->num); av7110->adac_type = DVB_ADAC_CRYSTAL; i2c_writereg(av7110, 0x20, 0x01, 0xd2); i2c_writereg(av7110, 0x20, 0x02, 0x49); i2c_writereg(av7110, 0x20, 0x03, 0x00); i2c_writereg(av7110, 0x20, 0x04, 0x00); - } - /** - * some special handling for the Siemens DVB-C card... + * some special handling for the Siemens DVB-C cards... */ - if (dev->pci->subsystem_vendor == 0x110a) { - if (i2c_writereg(av7110, 0x80, 0x0, 0x80)==1) { + } else if (i2c_writereg(av7110, 0x80, 0x0, 0x80)==1) { i2c_writereg(av7110, 0x80, 0x0, 0); - printk ("av7110: DVB-C analog module detected, " - "initializing MSP3400\n"); - ddelay(10); + printk ("av7110(%d): DVB-C analog module detected, " + "initializing MSP3400\n", + av7110->dvb_adapter->num); + av7110->adac_type = DVB_ADAC_MSP; + dvb_delay(100); msp_writereg(av7110, 0x12, 0x0013, 0x0c00); msp_writereg(av7110, 0x12, 0x0000, 0x7f00); // loudspeaker + headphone msp_writereg(av7110, 0x12, 0x0008, 0x0220); // loudspeaker source @@ -4151,17 +4225,26 @@ msp_writereg(av7110, 0x12, 0x000a, 0x0220); // SCART 1 source msp_writereg(av7110, 0x12, 0x0007, 0x7f00); // SCART 1 volume msp_writereg(av7110, 0x12, 0x000d, 0x4800); // prescale SCART + } else if (dev->pci->subsystem_vendor == 0x110a) { + printk("av7110(%d): DVB-C w/o analog module detected\n", + av7110->dvb_adapter->num); + av7110->adac_type = DVB_ADAC_NONE; + } else { + av7110->adac_type = adac; + printk("av7110(%d): adac type set to %d\n", + av7110->dvb_adapter->num, av7110->adac_type); } - + if (av7110->adac_type == DVB_ADAC_NONE || av7110->adac_type == DVB_ADAC_MSP) { // switch DVB SCART on outcom(av7110, COMTYPE_AUDIODAC, MainSwitch, 1, 0); outcom(av7110, COMTYPE_AUDIODAC, ADSwitch, 1, 1); //saa7146_setgpio(dev, 1, SAA7146_GPIO_OUTHI); // RGB on, SCART pin 16 //saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // SCARTpin 8 - av7110->adac_type = DVB_ADAC_NONE; } + SetVolume(av7110, 0xff, 0xff); + av7110_setup_irc_config (av7110, 0); av7110_register(av7110); @@ -4185,10 +4268,9 @@ return ret; } -static -int av7110_detach (struct saa7146_dev* saa) +static int av7110_detach (struct saa7146_dev* saa) { - av7110_t *av7110 = (av7110_t*)saa->ext_priv; + struct av7110 *av7110 = (struct av7110*)saa->ext_priv; DEB_EE(("av7110: %p\n",av7110)); saa7146_unregister_device(&av7110->vd, saa); @@ -4197,7 +4279,7 @@ wake_up_interruptible(&av7110->arm_wait); while (av7110->arm_thread) - ddelay(1); + dvb_delay(1); dvb_unregister(av7110); @@ -4226,10 +4308,9 @@ } -static -void av7110_irq(struct saa7146_dev* dev, u32 *isr) +static void av7110_irq(struct saa7146_dev* dev, u32 *isr) { - av7110_t *av7110 = (av7110_t*)dev->ext_priv; + struct av7110 *av7110 = (struct av7110*)dev->ext_priv; DEB_EE(("dev: %p, av7110: %p\n",dev,av7110)); @@ -4243,15 +4324,13 @@ /* FIXME: these values are experimental values that look better than the values from the latest "official" driver -- at least for me... (MiHu) */ -static -struct saa7146_standard standard[] = { +static struct saa7146_standard standard[] = { { "PAL", V4L2_STD_PAL, 0x15, 288, 576, 0x4a, 708, 709, 576, 768 }, // { "PAL", V4L2_STD_PAL, 0x15, 288, 576, 0x3a, 720, 721, 576, 768 }, { "NTSC", V4L2_STD_NTSC, 0x10, 244, 480, 0x40, 708, 709, 480, 640 }, }; -static -struct saa7146_extension av7110_extension; +static struct saa7146_extension av7110_extension; #define MAKE_AV7110_INFO(x_var,x_name) \ static struct saa7146_pci_extension_data x_var = { \ @@ -4268,8 +4347,7 @@ MAKE_AV7110_INFO(unkwn2, "Technotrend/Hauppauge PCI rev?(unknown2)?"); MAKE_AV7110_INFO(nexus, "Technotrend/Hauppauge Nexus PCI DVB-S"); -static -struct pci_device_id pci_tbl[] = { +static struct pci_device_id pci_tbl[] = { MAKE_EXTENSION_PCI(fs_1_5, 0x110a, 0xffff), MAKE_EXTENSION_PCI(fs_1_5, 0x110a, 0x0000), MAKE_EXTENSION_PCI(fs_1_3, 0x13c2, 0x0000), @@ -4280,6 +4358,7 @@ MAKE_EXTENSION_PCI(tt_2_1, 0x13c2, 0x0004), MAKE_EXTENSION_PCI(tt_1_6, 0x13c2, 0x0006), MAKE_EXTENSION_PCI(tt_t, 0x13c2, 0x0008), + MAKE_EXTENSION_PCI(tt_2_1, 0x13c2, 0x1102), MAKE_EXTENSION_PCI(unkwn1, 0xffc2, 0x0000), MAKE_EXTENSION_PCI(unkwn2, 0x00a1, 0x00a1), MAKE_EXTENSION_PCI(nexus, 0x00a1, 0xa1a0), @@ -4288,9 +4367,11 @@ } }; +MODULE_DEVICE_TABLE(pci, pci_tbl); + static int std_callback(struct saa7146_dev* dev, struct saa7146_standard *std) { - av7110_t *av7110 = (av7110_t*)dev->ext_priv; + struct av7110 *av7110 = (struct av7110*)dev->ext_priv; if (std->id == V4L2_STD_PAL) { av7110->vidmode = VIDEO_MODE_PAL; SetMode(av7110, av7110->vidmode); @@ -4306,8 +4387,7 @@ } -static -struct saa7146_ext_vv av7110_vv_data = { +static struct saa7146_ext_vv av7110_vv_data = { .inputs = 1, .audios = 1, .capabilities = 0, @@ -4321,8 +4401,7 @@ .ioctl = av7110_ioctl, }; -static -struct saa7146_extension av7110_extension = { +static struct saa7146_extension av7110_extension = { .name = "dvb\0", .ext_vv_data = &av7110_vv_data, @@ -4336,8 +4415,7 @@ }; -static -int __init av7110_init(void) +static int __init av7110_init(void) { if (saa7146_register_extension(&av7110_extension)) return -ENODEV; @@ -4348,8 +4426,7 @@ } -static -void __exit av7110_exit(void) +static void __exit av7110_exit(void) { av7110_ir_exit(); saa7146_unregister_extension(&av7110_extension); diff -Nru a/drivers/media/dvb/ttpci/av7110.h b/drivers/media/dvb/ttpci/av7110.h --- a/drivers/media/dvb/ttpci/av7110.h Tue Jul 1 18:44:31 2003 +++ b/drivers/media/dvb/ttpci/av7110.h Tue Jul 1 18:44:31 2003 @@ -40,39 +40,32 @@ #include "dvb_net.h" #include "dvb_ringbuffer.h" -typedef enum BOOTSTATES +enum av7110_bootstate { BOOTSTATE_BUFFER_EMPTY = 0, BOOTSTATE_BUFFER_FULL = 1, BOOTSTATE_BOOT_COMPLETE = 2 -} BOOTSTATES; +}; -typedef enum +enum av7110_type_rec_play_format { RP_None, AudioPES, AudioMp2, AudioPCM, VideoPES, AV_PES -} TYPE_REC_PLAY_FORMAT; - -typedef struct PARAMSTRUCT -{ - unsigned int wCommand; - int error; - unsigned long pdwData[100]; -} PARAMSTRUCT, *PPARAMSTRUCT; +}; -typedef enum OSDPALTYPE +enum av7110_osd_palette_type { NoPalet = 0, /* No palette */ Pal1Bit = 2, /* 2 colors for 1 Bit Palette */ Pal2Bit = 4, /* 4 colors for 2 bit palette */ Pal4Bit = 16, /* 16 colors for 4 bit palette */ Pal8Bit = 256 /* 256 colors for 16 bit palette */ -} OSDPALTYPE, *POSDPALTYPE; +}; -typedef enum { +enum av7110_window_display_type { BITMAP1, /* 1 bit bitmap */ BITMAP2, /* 2 bit bitmap */ BITMAP4, /* 4 bit bitmap */ @@ -93,9 +86,9 @@ VIDEOTDSIZE, /* True Size MPEG Video Display Double Resolution */ VIDEONSIZE, /* Full Size MPEG Video Display */ CURSOR /* Cursor */ -} DISPTYPE; /* Window display type */ +}; -// switch defines +/* switch defines */ #define SB_GPIO 3 #define SB_OFF SAA7146_GPIO_OUTLO //SlowBlank aus (TV-Mode) #define SB_ON SAA7146_GPIO_INPUT //SlowBlank an (AV-Mode) @@ -106,14 +99,13 @@ #define FB_ON SAA7146_GPIO_OUTHI //FastBlank an (RGB-Mode) #define FB_LOOP SAA7146_GPIO_INPUT //FastBlank der PC-Grafik durchschleifen -typedef enum VIDEOOUTPUTMODE +enum av7110_video_output_mode { NO_OUT = 0, //disable analog Output CVBS_RGB_OUT = 1, CVBS_YC_OUT = 2, YC_OUT = 3 -} VIDEOOUTPUTMODE, *PVIDEOOUTPUTMODE; - +}; #define GPMQFull 0x0001 //Main Message Queue Full #define GPMQOver 0x0002 //Main Message Queue Overflow @@ -127,9 +119,9 @@ #define SECTION_CYCLE 0x02 #define SECTION_CONTINUOS 0x04 #define SECTION_MODE 0x06 -#define SECTION_IPMPE 0x0C // bis zu 4k gro_ -#define SECTION_HIGH_SPEED 0x1C // vergrv_erter Puffer f|r High Speed Filter -#define DATA_PIPING_FLAG 0x20 // f|r Data Piping Filter +#define SECTION_IPMPE 0x0C // bis zu 4k groß +#define SECTION_HIGH_SPEED 0x1C // vergrößerter Puffer für High Speed Filter +#define DATA_PIPING_FLAG 0x20 // für Data Piping Filter #define PBUFSIZE_NONE 0x0000 #define PBUFSIZE_1P 0x0100 @@ -141,7 +133,7 @@ #define PBUFSIZE_16K 0x0700 #define PBUFSIZE_32K 0x0800 -typedef enum { +enum av7110_osd_command { WCreate, WDestroy, WMoveD, @@ -162,9 +154,9 @@ ReleaseBmp, SetWTrans, SetWNoTrans -} OSDCOM; +}; -typedef enum { +enum av7110_pid_command { MultiPID, VideoPID, AudioPID, @@ -177,13 +169,13 @@ Scan, SetDescr, SetIR -} PIDCOM; +}; -typedef enum { +enum av7110_mpeg_command { SelAudChannels -} MPEGCOM; +}; -typedef enum { +enum av7110_audio_command { AudioDAC, CabADAC, ON22K, @@ -192,9 +184,9 @@ ADSwitch, SendDiSEqC, SetRegister -} AUDCOM; +}; -typedef enum { +enum av7110_request_command { AudioState, AudioBuffState, VideoState1, @@ -203,19 +195,21 @@ CrashCounter, ReqVersion, ReqVCXO, - ReqRegister -} REQCOM; + ReqRegister, + ReqSecFilterError, + ReqSTC +}; -typedef enum { +enum av7110_encoder_command { SetVidMode, SetTestMode, LoadVidCode, SetMonitorType, SetPanScanType, SetFreezeMode -} ENC; +}; -typedef enum { +enum av7110_rec_play_state { __Record, __Stop, __Play, @@ -224,9 +218,9 @@ __FF_IP, __Scan_I, __Continue -} REC_PLAY; +}; -typedef enum { +enum av7110_command_type { COMTYPE_NOCOM, COMTYPE_PIDFILTER, COMTYPE_MPEGDECODER, @@ -244,17 +238,7 @@ COMTYPE_VIDEO, COMTYPE_AUDIO, COMTYPE_CI_LL, -} COMTYPE; - -typedef enum { - AV7110_VIDEO_FREEZE, - AV7110_VIDEO_CONTINUE -} VIDEOCOM; - -typedef enum { - DVB_AUDIO_PAUSE, -} AUDIOCOM; - +}; #define VID_NONE_PREF 0x00 /* No aspect ration processing preferred */ #define VID_PAN_SCAN_PREF 0x01 /* Pan and Scan Display preferred */ @@ -275,6 +259,7 @@ #define DATA_STREAMING 0x0a #define DATA_CI_GET 0x0b #define DATA_CI_PUT 0x0c +#define DATA_MPEG_VIDEO_EVENT 0x0d #define DATA_PES_RECORD 0x10 #define DATA_PES_PLAY 0x11 @@ -364,14 +349,6 @@ #define MAX_PLENGTH 0xFFFF #define MAX_VID_PES 0x1FFF -typedef struct section_s { - int id; - int length; - int found; - u8 payload[4096+3]; -} section_t; - - #define MY_STATE_PES_START 1 #define MY_STATE_PES_STARTED 2 #define MY_STATE_FULL 4 @@ -393,64 +370,34 @@ enum {AV_PES_STREAM, PS_STREAM, TS_STREAM, PES_STREAM}; -typedef struct ps_packet_s{ - u8 scr[6]; - u8 mux_rate[3]; - u8 stuff_length; - u8 data[20]; - u8 sheader_llength[2]; - int sheader_length; - u8 rate_bound[3]; - u8 audio_bound; - u8 video_bound; - u8 reserved; - int npes; - int mpeg; -} ps_packet_t; - -typedef struct a2p_s{ - int type; - int found; - int length; - int headr; - u8 cid; - u8 flags; - u8 abuf[MAX_PLENGTH]; - int alength; - u8 vbuf[MAX_PLENGTH]; - int vlength; - int plength; - u8 last_av_pts[4]; - u8 av_pts[4]; - u8 scr[4]; - u16 count0; - u16 count1; - u16 pidv; - u16 pida; - u16 countv; - u16 counta; - void *dataA; - void *dataV; - void (*write_cb)(u8 const *buf, long int count, - void *data); -} a2p_t; - - -typedef struct p2t_s { +struct av7110_p2t { u8 pes[TS_SIZE]; u8 counter; long int pos; int frags; struct dvb_demux_feed *feed; -} p2t_t; +}; + +/* video MPEG decoder events: */ +/* (code copied from dvb_frontend.c, should maybe be factored out...) */ +#define MAX_VIDEO_EVENT 8 +struct dvb_video_events { + struct video_event events[MAX_VIDEO_EVENT]; + int eventw; + int eventr; + int overflow; + wait_queue_head_t wait_queue; + spinlock_t lock; +}; + /* place to store all the necessary device information */ -typedef struct av7110_s { +struct av7110 { /* devices */ struct dvb_device dvb_dev; - dvb_net_t dvb_net; + struct dvb_net dvb_net; struct video_device vd; struct saa7146_dev *dev; @@ -464,15 +411,16 @@ int adac_type; /* audio DAC type */ #define DVB_ADAC_TI 0 #define DVB_ADAC_CRYSTAL 1 +#define DVB_ADAC_MSP 2 #define DVB_ADAC_NONE -1 /* buffers */ void *iobuf; /* memory for all buffers */ - dvb_ringbuffer_t avout; /* buffer for video or A/V mux */ + struct dvb_ringbuffer avout; /* buffer for video or A/V mux */ #define AVOUTLEN (128*1024) - dvb_ringbuffer_t aout; /* buffer for audio */ + struct dvb_ringbuffer aout; /* buffer for audio */ #define AOUTLEN (64*1024) void *bmpbuf; #define BMPLEN (8*32768+1024) @@ -522,12 +470,11 @@ ca_slot_info_t ci_slot[2]; int vidmode; - dmxdev_t dmxdev; + struct dmxdev dmxdev; struct dvb_demux demux; - char demux_id[16]; - dmx_frontend_t hw_frontend; - dmx_frontend_t mem_frontend; + struct dmx_frontend hw_frontend; + struct dmx_frontend mem_frontend; int fe_synced; struct semaphore pid_mutex; @@ -543,9 +490,9 @@ struct audio_status audiostate; struct dvb_demux_filter *handle2filter[32]; - p2t_t p2t_filter[MAXFILT]; - dvb_filter_pes2ts_t p2t[2]; - struct ipack_s ipack[2]; + struct av7110_p2t p2t_filter[MAXFILT]; + struct dvb_filter_pes2ts p2t[2]; + struct ipack ipack[2]; u8 *kbuf[2]; int sinfo; @@ -573,8 +520,8 @@ u16 pids[DMX_PES_OTHER]; - dvb_ringbuffer_t ci_rbuffer; - dvb_ringbuffer_t ci_wbuffer; + struct dvb_ringbuffer ci_rbuffer; + struct dvb_ringbuffer ci_wbuffer; struct dvb_adapter *dvb_adapter; @@ -583,8 +530,13 @@ struct dvb_device *ca_dev; struct dvb_device *osd_dev; + struct dvb_video_events video_events; + video_size_t video_size; + int dsp_dev; -} av7110_t; + + u32 ir_config; +}; #define DPRAM_BASE 0x4000 @@ -623,26 +575,15 @@ #define Reserved (DPRAM_BASE + 0x1E00) #define Reserved_SIZE 0x1C0 -#define DEBUG_WINDOW (DPRAM_BASE + 0x1FC0) -#define DBG_LOOP_CNT (DEBUG_WINDOW + 0x00) -#define DBG_SEC_CNT (DEBUG_WINDOW + 0x02) -#define DBG_AVRP_BUFF (DEBUG_WINDOW + 0x04) -#define DBG_AVRP_PEAK (DEBUG_WINDOW + 0x06) -#define DBG_MSG_CNT (DEBUG_WINDOW + 0x08) -#define DBG_CODE_REG (DEBUG_WINDOW + 0x0a) -#define DBG_TTX_Q (DEBUG_WINDOW + 0x0c) -#define DBG_AUD_EN (DEBUG_WINDOW + 0x0e) -#define DBG_WRONG_COM (DEBUG_WINDOW + 0x10) -#define DBG_ARR_OVFL (DEBUG_WINDOW + 0x12) -#define DBG_BUFF_OVFL (DEBUG_WINDOW + 0x14) -#define DBG_OVFL_CNT (DEBUG_WINDOW + 0x16) -#define DBG_SEC_OVFL (DEBUG_WINDOW + 0x18) - #define STATUS_BASE (DPRAM_BASE + 0x1FC0) #define STATUS_SCR (STATUS_BASE + 0x00) #define STATUS_MODES (STATUS_BASE + 0x04) #define STATUS_LOOPS (STATUS_BASE + 0x08) +#define STATUS_MPEG_WIDTH (STATUS_BASE + 0x0C) +/* ((aspect_ratio & 0xf) << 12) | (height & 0xfff) */ +#define STATUS_MPEG_HEIGHT_AR (STATUS_BASE + 0x0E) + #define RX_TYPE (DPRAM_BASE + 0x1FE8) #define RX_LEN (DPRAM_BASE + 0x1FEA) #define TX_TYPE (DPRAM_BASE + 0x1FEC) @@ -673,7 +614,7 @@ extern void av7110_register_irc_handler(void (*func)(u32)); extern void av7110_unregister_irc_handler(void (*func)(u32)); -extern void av7110_setup_irc_config (av7110_t *av7110, u32 ir_config); +extern void av7110_setup_irc_config (struct av7110 *av7110, u32 ir_config); extern int av7110_ir_init (void); extern void av7110_ir_exit (void); diff -Nru a/drivers/media/dvb/ttpci/av7110_firm.h b/drivers/media/dvb/ttpci/av7110_firm.h --- a/drivers/media/dvb/ttpci/av7110_firm.h Tue Jul 1 18:44:31 2003 +++ b/drivers/media/dvb/ttpci/av7110_firm.h Tue Jul 1 18:44:31 2003 @@ -1,5 +1,5 @@ -#include +#include u8 Dpram [] __initdata = { 0xe5, 0x9f, 0xf0, 0x1c, 0xe1, 0xb0, 0xf0, 0x0e, diff -Nru a/drivers/media/dvb/ttpci/av7110_ipack.c b/drivers/media/dvb/ttpci/av7110_ipack.c --- a/drivers/media/dvb/ttpci/av7110_ipack.c Tue Jul 1 18:44:34 2003 +++ b/drivers/media/dvb/ttpci/av7110_ipack.c Tue Jul 1 18:44:34 2003 @@ -1,9 +1,10 @@ #include "dvb_filter.h" #include "av7110_ipack.h" #include /* for memcpy() */ +#include -void av7110_ipack_reset(ipack *p) +void av7110_ipack_reset(struct ipack *p) { p->found = 0; p->cid = 0; @@ -19,7 +20,7 @@ } -void av7110_ipack_init(ipack *p, int size, +void av7110_ipack_init(struct ipack *p, int size, void (*func)(u8 *buf, int size, void *priv)) { if ( !(p->buf = vmalloc(size*sizeof(u8))) ){ @@ -32,17 +33,17 @@ } -void av7110_ipack_free(ipack * p) +void av7110_ipack_free(struct ipack * p) { - if (p->buf) vfree(p->buf); + if (p->buf) + vfree(p->buf); } -static -void send_ipack(ipack *p) +static void send_ipack(struct ipack *p) { int off; - AudioInfo ai; + struct dvb_audio_info ai; int ac3_off = 0; int streamid=0; int nframes= 0; @@ -109,7 +110,7 @@ } -void av7110_ipack_flush(ipack *p) +void av7110_ipack_flush(struct ipack *p) { if (p->plength != MMAX_PLENGTH-6 || p->found<=6) return; @@ -120,8 +121,7 @@ } -static -void write_ipack(ipack *p, const u8 *data, int count) +static void write_ipack(struct ipack *p, const u8 *data, int count) { u8 headr[3] = { 0x00, 0x00, 0x01} ; @@ -144,7 +144,7 @@ } -int av7110_ipack_instant_repack (const u8 *buf, int count, ipack *p) +int av7110_ipack_instant_repack (const u8 *buf, int count, struct ipack *p) { int l; int c=0; diff -Nru a/drivers/media/dvb/ttpci/av7110_ipack.h b/drivers/media/dvb/ttpci/av7110_ipack.h --- a/drivers/media/dvb/ttpci/av7110_ipack.h Tue Jul 1 18:44:31 2003 +++ b/drivers/media/dvb/ttpci/av7110_ipack.h Tue Jul 1 18:44:31 2003 @@ -1,13 +1,13 @@ #ifndef _AV7110_IPACK_H_ #define _AV7110_IPACK_H_ -extern void av7110_ipack_init(ipack *p, int size, +extern void av7110_ipack_init(struct ipack *p, int size, void (*func)(u8 *buf, int size, void *priv)); -extern void av7110_ipack_reset(ipack *p); -extern int av7110_ipack_instant_repack(const u8 *buf, int count, ipack *p); -extern void av7110_ipack_free(ipack * p); -extern void av7110_ipack_flush(ipack *p); +extern void av7110_ipack_reset(struct ipack *p); +extern int av7110_ipack_instant_repack(const u8 *buf, int count, struct ipack *p); +extern void av7110_ipack_free(struct ipack * p); +extern void av7110_ipack_flush(struct ipack *p); #endif diff -Nru a/drivers/media/dvb/ttpci/av7110_ir.c b/drivers/media/dvb/ttpci/av7110_ir.c --- a/drivers/media/dvb/ttpci/av7110_ir.c Tue Jul 1 18:44:33 2003 +++ b/drivers/media/dvb/ttpci/av7110_ir.c Tue Jul 1 18:44:33 2003 @@ -1,18 +1,13 @@ -#include -#include +#include #include #include #include #include +#include #include "av7110.h" -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) -#include "input_fake.h" -#endif - - -#define UP_TIMEOUT (HZ/2) +#define UP_TIMEOUT (HZ/4) static int av7110_ir_debug = 0; @@ -21,11 +16,11 @@ static struct input_dev input_dev; +static u32 ir_config; -static -u16 key_map [256] = { +static u16 key_map [256] = { KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, - KEY_8, KEY_9, KEY_MHP, 0, KEY_POWER, KEY_MUTE, 0, KEY_INFO, + KEY_8, KEY_9, KEY_BACK, 0, KEY_POWER, KEY_MUTE, 0, KEY_INFO, KEY_VOLUMEUP, KEY_VOLUMEDOWN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_CHANNELUP, KEY_CHANNELDOWN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -47,8 +42,7 @@ }; -static -void av7110_emit_keyup (unsigned long data) +static void av7110_emit_keyup (unsigned long data) { if (!data || !test_bit (data, input_dev.key)) return; @@ -57,43 +51,69 @@ } -static -struct timer_list keyup_timer = { function: av7110_emit_keyup }; +static struct timer_list keyup_timer = { function: av7110_emit_keyup }; -static -void av7110_emit_key (u32 ircom) +static void av7110_emit_key (u32 ircom) { - int down = ircom & (0x80000000); - u16 keycode = key_map[ircom & 0xff]; + u8 data; + u8 addr; + static u16 old_toggle = 0; + u16 new_toggle; + u16 keycode; + + /* extract device address and data */ + if (ir_config & 0x0001) { + /* TODO RCMM: ? bits device address, 8 bits data */ + data = ircom & 0xff; + addr = (ircom >> 8) & 0xff; + } else { + /* RC5: 5 bits device address, 6 bits data */ + data = ircom & 0x3f; + addr = (ircom >> 6) & 0x1f; + } - dprintk ("#########%08x######### key %02x %s (keycode %i)\n", - ircom, ircom & 0xff, down ? "pressed" : "released", keycode); + keycode = key_map[data]; + + dprintk ("#########%08x######### addr %i data 0x%02x (keycode %i)\n", + ircom, addr, data, keycode); + + /* check device address (if selected) */ + if (ir_config & 0x4000) + if (addr != ((ir_config >> 16) & 0xff)) + return; if (!keycode) { printk ("%s: unknown key 0x%02x!!\n", - __FUNCTION__, ircom & 0xff); + __FUNCTION__, data); return; } + if (ir_config & 0x0001) + new_toggle = 0; /* RCMM */ + else + new_toggle = (ircom & 0x800); /* RC5 */ + if (timer_pending (&keyup_timer)) { del_timer (&keyup_timer); - if (keyup_timer.data != keycode) + if (keyup_timer.data != keycode || new_toggle != old_toggle) { input_event (&input_dev, EV_KEY, keyup_timer.data, !!0); - } - - clear_bit (keycode, input_dev.key); + input_event (&input_dev, EV_KEY, keycode, !0); + } else + input_event (&input_dev, EV_KEY, keycode, 2); + } else input_event (&input_dev, EV_KEY, keycode, !0); keyup_timer.expires = jiffies + UP_TIMEOUT; keyup_timer.data = keycode; add_timer (&keyup_timer); + + old_toggle = new_toggle; } -static -void input_register_keys (void) +static void input_register_keys (void) { int i; @@ -108,17 +128,35 @@ } -static -int av7110_ir_write_proc (struct file *file, const char *buffer, +static void input_repeat_key(unsigned long data) +{ + /* dummy routine to disable autorepeat in the input driver */ +} + + +static int av7110_ir_write_proc (struct file *file, const char *buffer, unsigned long count, void *data) { - u32 ir_config; + char *page; + int size = 4 + 256 * sizeof(u16); - if (count < 4 + 256 * sizeof(u16)) + if (count < size) return -EINVAL; - memcpy (&ir_config, buffer, 4); - memcpy (&key_map, buffer + 4, 256 * sizeof(u16)); + page = (char *)vmalloc(size); + if( NULL == page ) { + return -ENOMEM; + } + + if (copy_from_user(page, buffer, size)) { + vfree(page); + return -EFAULT; + } + + memcpy (&ir_config, page, 4); + memcpy (&key_map, page + 4, 256 * sizeof(u16)); + + vfree(page); av7110_setup_irc_config (NULL, ir_config); @@ -141,10 +179,12 @@ * enable keys */ set_bit (EV_KEY, input_dev.evbit); + set_bit (EV_REP, input_dev.evbit); input_register_keys (); input_register_device(&input_dev); + input_dev.timer.function = input_repeat_key; av7110_setup_irc_config (NULL, 0x0001); av7110_register_irc_handler (av7110_emit_key); diff -Nru a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c --- a/drivers/media/dvb/ttpci/budget-av.c Tue Jul 1 18:44:37 2003 +++ b/drivers/media/dvb/ttpci/budget-av.c Tue Jul 1 18:44:37 2003 @@ -30,13 +30,10 @@ * the project's page is at http://www.linuxtv.org/dvb/ */ -#include "budget.h" #include -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) - #define KBUILD_MODNAME budget_av -#endif - +#include "budget.h" +#include "dvb_functions.h" struct budget_av { struct budget budget; @@ -48,16 +45,8 @@ * INITIALIZATION ****************************************************************************/ -static inline -void ddelay(int i) -{ - current->state=TASK_INTERRUPTIBLE; - schedule_timeout((HZ*i)/100); -} - -static -u8 i2c_readreg (struct dvb_i2c_bus *i2c, u8 id, u8 reg) +static u8 i2c_readreg (struct dvb_i2c_bus *i2c, u8 id, u8 reg) { u8 mm1[] = {0x00}; u8 mm2[] = {0x00}; @@ -76,8 +65,7 @@ } -static -int i2c_writereg (struct dvb_i2c_bus *i2c, u8 id, u8 reg, u8 val) +static int i2c_writereg (struct dvb_i2c_bus *i2c, u8 id, u8 reg, u8 val) { u8 msg[2]={ reg, val }; struct i2c_msg msgs; @@ -90,8 +78,7 @@ } -static const -u8 saa7113_tab[] = { +static const u8 saa7113_tab[] = { 0x01, 0x08, 0x02, 0xc0, 0x03, 0x33, @@ -121,8 +108,7 @@ }; -static -int saa7113_init (struct budget_av *budget_av) +static int saa7113_init (struct budget_av *budget_av) { struct budget *budget = &budget_av->budget; const u8 *data = saa7113_tab; @@ -146,8 +132,7 @@ } -static -int saa7113_setinput (struct budget_av *budget_av, int input) +static int saa7113_setinput (struct budget_av *budget_av, int input) { struct budget *budget = &budget_av->budget; @@ -165,8 +150,7 @@ } -static -int budget_av_detach (struct saa7146_dev *dev) +static int budget_av_detach (struct saa7146_dev *dev) { struct budget_av *budget_av = (struct budget_av*) dev->ext_priv; int err; @@ -175,7 +159,7 @@ saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO); - ddelay(20); + dvb_delay(200); saa7146_unregister_device (&budget_av->vd, dev); @@ -187,8 +171,7 @@ } -static -int budget_av_attach (struct saa7146_dev* dev, +static int budget_av_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info) { struct budget_av *budget_av; @@ -221,7 +204,7 @@ //test_knc_ci(av7110); saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTHI); - ddelay(50); + dvb_delay(500); if ((err = saa7113_init (budget_av))) { budget_av_detach(dev); @@ -245,9 +228,11 @@ /* what is this? since we don't support open()/close() notifications, we simply put this into the release handler... */ -// saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO); - ddelay(20); - +/* + saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout (20); +*/ /* fixme: find some sane values here... */ saa7146_write(dev, PCI_BT_V1, 0x1c00101f); @@ -263,8 +248,7 @@ }; -static -struct saa7146_extension_ioctls ioctls[] = { +static struct saa7146_extension_ioctls ioctls[] = { { VIDIOC_ENUMINPUT, SAA7146_EXCLUSIVE }, { VIDIOC_G_INPUT, SAA7146_EXCLUSIVE }, { VIDIOC_S_INPUT, SAA7146_EXCLUSIVE }, @@ -272,8 +256,7 @@ }; -static -int av_ioctl(struct saa7146_dev *dev, unsigned int cmd, void *arg) +static int av_ioctl(struct saa7146_dev *dev, unsigned int cmd, void *arg) { struct budget_av *budget_av = (struct budget_av*) dev->ext_priv; /* @@ -315,15 +298,13 @@ return 0; } -static -struct saa7146_standard standard[] = { +static struct saa7146_standard standard[] = { { "PAL", V4L2_STD_PAL, SAA7146_PAL_VALUES }, { "NTSC", V4L2_STD_NTSC, SAA7146_NTSC_VALUES }, }; -static -struct saa7146_ext_vv vv_data = { +static struct saa7146_ext_vv vv_data = { .inputs = 2, .capabilities = 0, // perhaps later: V4L2_CAP_VBI_CAPTURE, but that need tweaking with the saa7113 .flags = 0, @@ -340,18 +321,16 @@ MAKE_BUDGET_INFO(knc1, "KNC1 DVB-S", BUDGET_KNC1); -static -struct pci_device_id pci_tbl [] = { +static struct pci_device_id pci_tbl [] = { MAKE_EXTENSION_PCI(knc1, 0x1131, 0x4f56), { .vendor = 0, } }; +MODULE_DEVICE_TABLE(pci, pci_tbl); - -static -struct saa7146_extension budget_extension = { +static struct saa7146_extension budget_extension = { .name = "budget dvb /w video in\0", .pci_tbl = pci_tbl, @@ -366,8 +345,7 @@ }; -static -int __init budget_av_init(void) +static int __init budget_av_init(void) { DEB_EE((".\n")); @@ -378,8 +356,7 @@ } -static -void __exit budget_av_exit(void) +static void __exit budget_av_exit(void) { DEB_EE((".\n")); saa7146_unregister_extension(&budget_extension); diff -Nru a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c --- a/drivers/media/dvb/ttpci/budget-ci.c Tue Jul 1 18:44:32 2003 +++ b/drivers/media/dvb/ttpci/budget-ci.c Tue Jul 1 18:44:32 2003 @@ -28,10 +28,6 @@ */ #include "budget.h" -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) - #define KBUILD_MODNAME budget -#endif - #include #include @@ -39,12 +35,6 @@ #include #include -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) -#include "input_fake.h" -#endif - - - struct budget_ci { struct budget budget; struct input_dev input_dev; @@ -78,8 +68,7 @@ -static -int wait_for_debi_done(struct saa7146_dev *saa) +static int wait_for_debi_done(struct saa7146_dev *saa) { int start = jiffies; @@ -113,8 +102,7 @@ } -static -u32 debiread (struct saa7146_dev *saa, u32 config, int addr, int count) +static u32 debiread (struct saa7146_dev *saa, u32 config, int addr, int count) { u32 result = 0; @@ -141,8 +129,7 @@ /* DEBI during interrupt */ -static inline -u32 irdebi(struct saa7146_dev *saa, u32 config, int addr, u32 val, int count) +static inline u32 irdebi(struct saa7146_dev *saa, u32 config, int addr, u32 val, int count) { u32 res; res = debiread(saa, config, addr, count); @@ -158,8 +145,7 @@ Hauppauge (from NOVA-CI-s box product) i've taken a "middle of the road" approach and note the differences */ -static - u16 key_map[64] = { +static u16 key_map[64] = { /* 0x0X */ KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7, KEY_8, KEY_9, @@ -209,8 +195,7 @@ }; -static -void msp430_ir_debounce (unsigned long data) +static void msp430_ir_debounce (unsigned long data) { struct input_dev *dev = (struct input_dev *) data; @@ -227,8 +212,7 @@ -static -void msp430_ir_interrupt (unsigned long data) +static void msp430_ir_interrupt (unsigned long data) { struct budget_ci *budget_ci = (struct budget_ci*) data; struct saa7146_dev *saa = budget_ci->budget.dev; @@ -266,8 +250,7 @@ } -static -int msp430_ir_init (struct budget_ci *budget_ci) +static int msp430_ir_init (struct budget_ci *budget_ci) { struct saa7146_dev *saa = budget_ci->budget.dev; int i; @@ -294,8 +277,7 @@ } -static -void msp430_ir_deinit (struct budget_ci *budget_ci) +static void msp430_ir_deinit (struct budget_ci *budget_ci) { struct saa7146_dev *saa = budget_ci->budget.dev; struct input_dev *dev = &budget_ci->input_dev; @@ -311,8 +293,7 @@ } -static -void budget_ci_irq (struct saa7146_dev *dev, u32 *isr) +static void budget_ci_irq (struct saa7146_dev *dev, u32 *isr) { struct budget_ci *budget_ci = (struct budget_ci*) dev->ext_priv; @@ -327,8 +308,7 @@ -static -int budget_ci_attach (struct saa7146_dev* dev, +static int budget_ci_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info) { struct budget_ci *budget_ci; @@ -356,8 +336,7 @@ -static -int budget_ci_detach (struct saa7146_dev* dev) +static int budget_ci_detach (struct saa7146_dev* dev) { struct budget_ci *budget_ci = (struct budget_ci*) dev->ext_priv; int err; @@ -379,8 +358,7 @@ MAKE_BUDGET_INFO(ttbci, "TT-Budget/WinTV-NOVA-CI PCI", BUDGET_TT_HW_DISEQC); -static -struct pci_device_id pci_tbl[] = { +static struct pci_device_id pci_tbl[] = { MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100c), MAKE_EXTENSION_PCI(ttbci, 0x13c2, 0x100f), { @@ -388,10 +366,9 @@ } }; +MODULE_DEVICE_TABLE(pci, pci_tbl); - -static -struct saa7146_extension budget_extension = { +static struct saa7146_extension budget_extension = { .name = "budget_ci dvb\0", .flags = 0, .ext_vv_data = NULL, @@ -406,8 +383,7 @@ }; -static -int __init budget_ci_init(void) +static int __init budget_ci_init(void) { if (saa7146_register_extension(&budget_extension)) return -ENODEV; @@ -416,8 +392,7 @@ } -static -void __exit budget_ci_exit(void) +static void __exit budget_ci_exit(void) { DEB_EE((".\n")); saa7146_unregister_extension(&budget_extension); diff -Nru a/drivers/media/dvb/ttpci/budget-core.c b/drivers/media/dvb/ttpci/budget-core.c --- a/drivers/media/dvb/ttpci/budget-core.c Tue Jul 1 18:44:34 2003 +++ b/drivers/media/dvb/ttpci/budget-core.c Tue Jul 1 18:44:34 2003 @@ -1,26 +1,12 @@ #include "budget.h" -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) - #define KBUILD_MODNAME budget -#endif int budget_debug = 0; /**************************************************************************** - * General helper functions - ****************************************************************************/ - -static inline void ddelay(int i) -{ - current->state=TASK_INTERRUPTIBLE; - schedule_timeout((HZ*i)/100); -} - -/**************************************************************************** * TT budget / WinTV Nova ****************************************************************************/ -static -int stop_ts_capture(struct budget *budget) +static int stop_ts_capture(struct budget *budget) { DEB_EE(("budget: %p\n",budget)); @@ -33,8 +19,7 @@ } -static -int start_ts_capture (struct budget *budget) +static int start_ts_capture (struct budget *budget) { struct saa7146_dev *dev=budget->dev; @@ -75,8 +60,7 @@ } -static -void vpeirq (unsigned long data) +static void vpeirq (unsigned long data) { struct budget *budget = (struct budget*) data; u8 *mem = (u8 *)(budget->grabbing); @@ -113,8 +97,7 @@ * DVB API SECTION ****************************************************************************/ -static -int budget_start_feed(struct dvb_demux_feed *feed) +static int budget_start_feed(struct dvb_demux_feed *feed) { struct dvb_demux *demux = feed->demux; struct budget *budget = (struct budget*) demux->priv; @@ -127,8 +110,7 @@ return start_ts_capture (budget); } -static -int budget_stop_feed(struct dvb_demux_feed *feed) +static int budget_stop_feed(struct dvb_demux_feed *feed) { struct dvb_demux *demux = feed->demux; struct budget *budget = (struct budget *) demux->priv; @@ -139,17 +121,13 @@ } -static -int budget_register(struct budget *budget) +static int budget_register(struct budget *budget) { - int ret; - dmx_frontend_t *dvbfront=&budget->hw_frontend; struct dvb_demux *dvbdemux=&budget->demux; + int ret; DEB_EE(("budget: %p\n",budget)); - memcpy(budget->demux_id, "demux0_0", 9); - budget->demux_id[5] = budget->dvb_adapter->num + '0'; dvbdemux->priv = (void *) budget; dvbdemux->filternum = 256; @@ -158,33 +136,24 @@ dvbdemux->stop_feed = budget_stop_feed; dvbdemux->write_to_decoder = NULL; - dvbdemux->dmx.vendor = "CIM"; - dvbdemux->dmx.model = "sw"; - dvbdemux->dmx.id = budget->demux_id; dvbdemux->dmx.capabilities = (DMX_TS_FILTERING | DMX_SECTION_FILTERING | DMX_MEMORY_BASED_FILTERING); dvb_dmx_init(&budget->demux); - dvbfront->id = "hw_frontend"; - dvbfront->vendor = "VLSI"; - dvbfront->model = "DVB Frontend"; - dvbfront->source = DMX_FRONTEND_0; - budget->dmxdev.filternum = 256; budget->dmxdev.demux = &dvbdemux->dmx; budget->dmxdev.capabilities = 0; dvb_dmxdev_init(&budget->dmxdev, budget->dvb_adapter); - ret=dvbdemux->dmx.add_frontend (&dvbdemux->dmx, - &budget->hw_frontend); + budget->hw_frontend.source = DMX_FRONTEND_0; + + ret = dvbdemux->dmx.add_frontend(&dvbdemux->dmx, &budget->hw_frontend); + if (ret < 0) return ret; - budget->mem_frontend.id = "mem_frontend"; - budget->mem_frontend.vendor = "memory"; - budget->mem_frontend.model = "sw"; budget->mem_frontend.source = DMX_MEMORY_FE; ret=dvbdemux->dmx.add_frontend (&dvbdemux->dmx, &budget->mem_frontend); @@ -203,8 +172,7 @@ } -static -void budget_unregister(struct budget *budget) +static void budget_unregister(struct budget *budget) { struct dvb_demux *dvbdemux=&budget->demux; @@ -221,8 +189,7 @@ } -static -int master_xfer (struct dvb_i2c_bus *i2c, const struct i2c_msg msgs[], int num) +static int master_xfer (struct dvb_i2c_bus *i2c, const struct i2c_msg msgs[], int num) { struct saa7146_dev *dev = i2c->data; return saa7146_i2c_transfer(dev, msgs, num, 6); @@ -278,9 +245,9 @@ saa7146_setgpio(dev, 2, SAA7146_GPIO_OUTHI); /* frontend power on */ - if (budget_register(budget) == 0) + if (budget_register(budget) == 0) { return 0; - + } err: if (budget->grabbing) vfree(budget->grabbing); @@ -312,7 +279,6 @@ saa7146_pgtable_free (dev->pci, &budget->pt); vfree (budget->grabbing); - kfree (budget); return 0; } diff -Nru a/drivers/media/dvb/ttpci/budget-patch.c b/drivers/media/dvb/ttpci/budget-patch.c --- a/drivers/media/dvb/ttpci/budget-patch.c Tue Jul 1 18:44:32 2003 +++ b/drivers/media/dvb/ttpci/budget-patch.c Tue Jul 1 18:44:32 2003 @@ -31,9 +31,7 @@ */ #include "budget.h" -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) - #define KBUILD_MODNAME budget_patch -#endif +#include "av7110.h" #define budget_patch budget @@ -41,55 +39,14 @@ MAKE_BUDGET_INFO(fs_1_3,"Siemens/Technotrend/Hauppauge PCI rev1.3+Budget_Patch", BUDGET_PATCH); -static -struct pci_device_id pci_tbl[] = { +static struct pci_device_id pci_tbl[] = { MAKE_EXTENSION_PCI(fs_1_3,0x13c2, 0x0000), { .vendor = 0, } }; - -#define COMMAND (DPRAM_BASE + 0x0FC) -#define DPRAM_BASE 0x4000 -#define DEBINOSWAP 0x000e0000 - - -typedef enum { - AudioDAC, - CabADAC, - ON22K, - OFF22K, - MainSwitch, - ADSwitch, - SendDiSEqC, - SetRegister -} AUDCOM; - - -typedef enum { - COMTYPE_NOCOM, - COMTYPE_PIDFILTER, - COMTYPE_MPEGDECODER, - COMTYPE_OSD, - COMTYPE_BMP, - COMTYPE_ENCODER, - COMTYPE_AUDIODAC, - COMTYPE_REQUEST, - COMTYPE_SYSTEM, - COMTYPE_REC_PLAY, - COMTYPE_COMMON_IF, - COMTYPE_PID_FILTER, - COMTYPE_PES, - COMTYPE_TS, - COMTYPE_VIDEO, - COMTYPE_AUDIO, - COMTYPE_CI_LL, -} COMTYPE; - - -static -int wdebi(struct budget_patch *budget, u32 config, int addr, u32 val, int count) +static int wdebi(struct budget_patch *budget, u32 config, int addr, u32 val, int count) { struct saa7146_dev *dev=budget->dev; @@ -109,8 +66,7 @@ } -static -int SOutCommand(struct budget_patch *budget, u16* buf, int length) +static int SOutCommand(struct budget_patch *budget, u16* buf, int length) { int i; @@ -129,8 +85,7 @@ } -static -void av7110_set22k(struct budget_patch *budget, int state) +static void av7110_set22k(struct budget_patch *budget, int state) { u16 buf[2] = {( COMTYPE_AUDIODAC << 8) | (state ? ON22K : OFF22K), 0}; @@ -139,8 +94,7 @@ } -static int -av7110_send_diseqc_msg(struct budget_patch *budget, int len, u8 *msg, int burst) +static int av7110_send_diseqc_msg(struct budget_patch *budget, int len, u8 *msg, int burst) { int i; u16 buf[18] = { ((COMTYPE_AUDIODAC << 8) | SendDiSEqC), @@ -207,12 +161,10 @@ } -static -int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info) +static int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info) { struct budget_patch *budget; int err; - int cnt; if (!(budget = kmalloc (sizeof(struct budget_patch), GFP_KERNEL))) return -ENOMEM; @@ -235,31 +187,33 @@ ** (74HCT4040, LVC74) for the generation of this VSYNC signal, ** which seems that can be done perfectly without this :-)). */ - cnt = 0; // Setup RPS1 "program" (p35) + + // Setup RPS1 "program" (p35) + // Wait reset Source Line Counter Threshold (p36) - dev->rps1[cnt++]=cpu_to_le32(CMD_PAUSE | RPS_INV | EVT_HS); + WRITE_RPS1(cpu_to_le32(CMD_PAUSE | RPS_INV | EVT_HS)); // Wait Source Line Counter Threshold (p36) - dev->rps1[cnt++]=cpu_to_le32(CMD_PAUSE | EVT_HS); + WRITE_RPS1(cpu_to_le32(CMD_PAUSE | EVT_HS)); // Set GPIO3=1 (p42) - dev->rps1[cnt++]=cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)); - dev->rps1[cnt++]=cpu_to_le32(GPIO3_MSK); - dev->rps1[cnt++]=cpu_to_le32(SAA7146_GPIO_OUTHI<<24); + WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2))); + WRITE_RPS1(cpu_to_le32(GPIO3_MSK)); + WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTHI<<24)); // Wait reset Source Line Counter Threshold (p36) - dev->rps1[cnt++]=cpu_to_le32(CMD_PAUSE | RPS_INV | EVT_HS); + WRITE_RPS1(cpu_to_le32(CMD_PAUSE | RPS_INV | EVT_HS)); // Wait Source Line Counter Threshold - dev->rps1[cnt++]=cpu_to_le32(CMD_PAUSE | EVT_HS); + WRITE_RPS1(cpu_to_le32(CMD_PAUSE | EVT_HS)); // Set GPIO3=0 (p42) - dev->rps1[cnt++]=cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2)); - dev->rps1[cnt++]=cpu_to_le32(GPIO3_MSK); - dev->rps1[cnt++]=cpu_to_le32(SAA7146_GPIO_OUTLO<<24); + WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2))); + WRITE_RPS1(cpu_to_le32(GPIO3_MSK)); + WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTLO<<24)); // Jump to begin of RPS program (p37) - dev->rps1[cnt++]=cpu_to_le32(CMD_JUMP); - dev->rps1[cnt++]=cpu_to_le32(virt_to_bus(&dev->rps1[0])); + WRITE_RPS1(cpu_to_le32(CMD_JUMP)); + WRITE_RPS1(cpu_to_le32(dev->d_rps1.dma_handle)); // Fix VSYNC level saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); // Set RPS1 Address register to point to RPS code (r108 p42) - saa7146_write(dev, RPS_ADDR1, virt_to_bus(&dev->rps1[0])); + saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle); // Set Source Line Counter Threshold, using BRS (rCC p43) saa7146_write(dev, RPS_THRESH1, ((TS_HEIGHT/2) | MASK_12)); // Enable RPS1 (rFC p33) @@ -274,8 +228,7 @@ } -static -int budget_patch_detach (struct saa7146_dev* dev) +static int budget_patch_detach (struct saa7146_dev* dev) { struct budget_patch *budget = (struct budget_patch*) dev->ext_priv; int err; @@ -291,8 +244,7 @@ } -static -int __init budget_patch_init(void) +static int __init budget_patch_init(void) { if (saa7146_register_extension(&budget_extension)) return -ENODEV; @@ -301,16 +253,14 @@ } -static -void __exit budget_patch_exit(void) +static void __exit budget_patch_exit(void) { DEB_EE((".\n")); saa7146_unregister_extension(&budget_extension); } -static -struct saa7146_extension budget_extension = { +static struct saa7146_extension budget_extension = { .name = "budget_patch dvb\0", .flags = 0, .ext_vv_data = NULL, diff -Nru a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c --- a/drivers/media/dvb/ttpci/budget.c Tue Jul 1 18:44:35 2003 +++ b/drivers/media/dvb/ttpci/budget.c Tue Jul 1 18:44:35 2003 @@ -30,21 +30,9 @@ */ #include "budget.h" -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) - #define KBUILD_MODNAME budget -#endif +#include "dvb_functions.h" - - -static inline void ddelay(int i) -{ - current->state=TASK_INTERRUPTIBLE; - schedule_timeout((HZ*i)/100); -} - - -static -void Set22K (struct budget *budget, int state) +static void Set22K (struct budget *budget, int state) { struct saa7146_dev *dev=budget->dev; DEB_EE(("budget: %p\n",budget)); @@ -56,8 +44,7 @@ /* taken from the Skyvision DVB driver by Ralph Metzler */ -static -void DiseqcSendBit (struct budget *budget, int data) +static void DiseqcSendBit (struct budget *budget, int data) { struct saa7146_dev *dev=budget->dev; DEB_EE(("budget: %p\n",budget)); @@ -69,8 +56,7 @@ } -static -void DiseqcSendByte (struct budget *budget, int data) +static void DiseqcSendByte (struct budget *budget, int data) { int i, par=1, d; @@ -86,8 +72,7 @@ } -static -int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, int burst) +static int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long burst) { struct saa7146_dev *dev=budget->dev; int i; @@ -110,7 +95,7 @@ udelay(12500); saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); } - ddelay(2); + dvb_delay(20); } return 0; @@ -146,7 +131,7 @@ } case FE_DISEQC_SEND_BURST: - SendDiSEqCMsg (budget, 0, NULL, (int) arg); + SendDiSEqCMsg (budget, 0, NULL, (unsigned long)arg); break; default: @@ -157,18 +142,20 @@ } -static -int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info) +static int budget_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info) { - struct budget *budget; + struct budget *budget = NULL; int err; - if (!(budget = kmalloc (sizeof(struct budget), GFP_KERNEL))) + budget = kmalloc(sizeof(struct budget), GFP_KERNEL); + if( NULL == budget ) { return -ENOMEM; + } - DEB_EE(("budget: %p\n",budget)); + DEB_EE(("dev:%p, info:%p, budget:%p\n",dev,info,budget)); if ((err = ttpci_budget_init (budget, dev, info))) { + printk("==> failed\n"); kfree (budget); return err; } @@ -182,8 +169,7 @@ } -static -int budget_detach (struct saa7146_dev* dev) +static int budget_detach (struct saa7146_dev* dev) { struct budget *budget = (struct budget*) dev->ext_priv; int err; @@ -194,6 +180,7 @@ err = ttpci_budget_deinit (budget); kfree (budget); + dev->ext_priv = NULL; return err; } @@ -209,8 +196,7 @@ /* Uncomment for Budget Patch */ /*MAKE_BUDGET_INFO(fs_1_3,"Siemens/Technotrend/Hauppauge PCI rev1.3+Budget_Patch", BUDGET_PATCH);*/ -static -struct pci_device_id pci_tbl[] = { +static struct pci_device_id pci_tbl[] = { /* Uncomment for Budget Patch */ /*MAKE_EXTENSION_PCI(fs_1_3,0x13c2, 0x0000),*/ MAKE_EXTENSION_PCI(ttbs, 0x13c2, 0x1003), @@ -222,10 +208,9 @@ } }; +MODULE_DEVICE_TABLE(pci, pci_tbl); - -static -struct saa7146_extension budget_extension = { +static struct saa7146_extension budget_extension = { .name = "budget dvb\0", .flags = 0, .ext_vv_data = NULL, @@ -240,8 +225,7 @@ }; -static -int __init budget_init(void) +static int __init budget_init(void) { if (saa7146_register_extension(&budget_extension)) return -ENODEV; @@ -250,8 +234,7 @@ } -static -void __exit budget_exit(void) +static void __exit budget_exit(void) { DEB_EE((".\n")); saa7146_unregister_extension(&budget_extension); diff -Nru a/drivers/media/dvb/ttpci/budget.h b/drivers/media/dvb/ttpci/budget.h --- a/drivers/media/dvb/ttpci/budget.h Tue Jul 1 18:44:36 2003 +++ b/drivers/media/dvb/ttpci/budget.h Tue Jul 1 18:44:36 2003 @@ -1,6 +1,8 @@ #ifndef __BUDGET_DVB__ #define __BUDGET_DVB__ +#include + #include "dvb_i2c.h" #include "dvb_frontend.h" #include "dvbdev.h" @@ -10,8 +12,6 @@ #include "dvb_filter.h" #include "dvb_net.h" -#include - extern int budget_debug; struct budget_info { @@ -24,7 +24,7 @@ /* devices */ struct dvb_device dvb_dev; - dvb_net_t dvb_net; + struct dvb_net dvb_net; struct saa7146_dev *dev; @@ -37,12 +37,11 @@ struct tasklet_struct fidb_tasklet; struct tasklet_struct vpe_tasklet; - dmxdev_t dmxdev; + struct dmxdev dmxdev; struct dvb_demux demux; - char demux_id[16]; - dmx_frontend_t hw_frontend; - dmx_frontend_t mem_frontend; + struct dmx_frontend hw_frontend; + struct dmx_frontend mem_frontend; int fe_synced; struct semaphore pid_mutex; diff -Nru a/drivers/media/video/dpc7146.c b/drivers/media/video/dpc7146.c --- a/drivers/media/video/dpc7146.c Tue Jul 1 18:44:34 2003 +++ b/drivers/media/video/dpc7146.c Tue Jul 1 18:44:34 2003 @@ -23,10 +23,6 @@ #include #include /* for saa7111a */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) - #define KBUILD_MODNAME dpc7146 -#endif - #define I2C_SAA7111A 0x24 /* All unused bytes are reserverd. */ @@ -338,6 +334,8 @@ .vendor = 0, } }; + +MODULE_DEVICE_TABLE(pci, pci_tbl); static struct saa7146_ext_vv vv_data = { diff -Nru a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c --- a/drivers/media/video/mxb.c Tue Jul 1 18:44:31 2003 +++ b/drivers/media/video/mxb.c Tue Jul 1 18:44:31 2003 @@ -26,10 +26,6 @@ #include #include /* for saa7111a */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,51) - #define KBUILD_MODNAME mxb -#endif - #include "mxb.h" #include "tea6415c.h" #include "tea6420.h" diff -Nru a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c --- a/drivers/media/video/saa7111.c Tue Jul 1 18:44:34 2003 +++ b/drivers/media/video/saa7111.c Tue Jul 1 18:44:34 2003 @@ -57,7 +57,7 @@ int sat; }; -static unsigned short normal_i2c[] = { 34>>1, I2C_CLIENT_END }; +static unsigned short normal_i2c[] = { 0x24, 0x25, I2C_CLIENT_END }; static unsigned short normal_i2c_range[] = { I2C_CLIENT_END }; I2C_CLIENT_INSMOD; diff -Nru a/drivers/mtd/afs.c b/drivers/mtd/afs.c --- a/drivers/mtd/afs.c Tue Jul 1 18:44:38 2003 +++ b/drivers/mtd/afs.c Tue Jul 1 18:44:38 2003 @@ -21,7 +21,7 @@ This is access code for flashes using ARM's flash partitioning standards. - $Id: afs.c,v 1.11 2003/05/16 17:08:24 dwmw2 Exp $ + $Id: afs.c,v 1.12 2003/06/13 15:31:06 rmk Exp $ ======================================================================*/ @@ -76,17 +76,19 @@ return ret; } + ret = 1; + /* * Does it contain the magic number? */ if (fs.signature != 0xa0ffff9f) - ret = 1; + ret = 0; /* * Don't touch the SIB. */ if (fs.type == 2) - ret = 1; + ret = 0; *iis_start = fs.image_info_base & mask; *img_start = fs.image_start & mask; @@ -96,14 +98,14 @@ * be located after the footer structure. */ if (*iis_start >= ptr) - ret = 1; + ret = 0; /* * Check the start of this image. The image * data can not be located after this block. */ if (*img_start > off) - ret = 1; + ret = 0; return ret; } @@ -152,7 +154,7 @@ ret = afs_read_footer(mtd, &img_ptr, &iis_ptr, off, mask); if (ret < 0) break; - if (ret == 1) + if (ret == 0) continue; ret = afs_read_iis(mtd, &iis, iis_ptr); @@ -185,7 +187,7 @@ ret = afs_read_footer(mtd, &img_ptr, &iis_ptr, off, mask); if (ret < 0) break; - if (ret == 1) + if (ret == 0) continue; /* Read the image info block */ diff -Nru a/drivers/mtd/chips/amd_flash.c b/drivers/mtd/chips/amd_flash.c --- a/drivers/mtd/chips/amd_flash.c Tue Jul 1 18:44:33 2003 +++ b/drivers/mtd/chips/amd_flash.c Tue Jul 1 18:44:33 2003 @@ -3,7 +3,7 @@ * * Author: Jonas Holmberg * - * $Id: amd_flash.c,v 1.22 2003/05/28 13:47:19 dwmw2 Exp $ + * $Id: amd_flash.c,v 1.23 2003/06/12 09:24:13 dwmw2 Exp $ * * Copyright (c) 2001 Axis Communications AB * @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include diff -Nru a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c --- a/drivers/mtd/chips/cfi_cmdset_0001.c Tue Jul 1 18:44:33 2003 +++ b/drivers/mtd/chips/cfi_cmdset_0001.c Tue Jul 1 18:44:33 2003 @@ -4,7 +4,7 @@ * * (C) 2000 Red Hat. GPL'd * - * $Id: cfi_cmdset_0001.c,v 1.123 2003/05/28 12:51:48 dwmw2 Exp $ + * $Id: cfi_cmdset_0001.c,v 1.126 2003/06/23 07:45:48 dwmw2 Exp $ * * * 10/10/2000 Nicolas Pitre @@ -936,7 +936,7 @@ struct cfi_private *cfi = map->fldrv_priv; cfi_word status, status_OK; unsigned long cmd_adr, timeo; - int wbufsize, z, ret=0; + int wbufsize, z, ret=0, bytes, words; wbufsize = CFIDEV_INTERLEAVE << cfi->cfiq->MaxBufWriteSize; adr += chip->start; @@ -995,10 +995,13 @@ } /* Write length of data to come */ - cfi_write(map, CMD(len/CFIDEV_BUSWIDTH-1), cmd_adr ); + bytes = len & (CFIDEV_BUSWIDTH-1); + words = len / CFIDEV_BUSWIDTH; + cfi_write(map, CMD(words - !bytes), cmd_adr ); /* Write data */ - for (z = 0; z < len; z += CFIDEV_BUSWIDTH) { + z = 0; + while(z < words * CFIDEV_BUSWIDTH) { if (cfi_buswidth_is_1()) { map_write8 (map, *((__u8*)buf)++, adr+z); } else if (cfi_buswidth_is_2()) { @@ -1011,6 +1014,26 @@ ret = -EINVAL; goto out; } + z += CFIDEV_BUSWIDTH; + } + if (bytes) { + int i = 0, n = 0; + u_char tmp_buf[8], *tmp_p = tmp_buf; + + while (bytes--) + tmp_buf[i++] = buf[n++]; + while (i < CFIDEV_BUSWIDTH) + tmp_buf[i++] = 0xff; + if (cfi_buswidth_is_2()) { + map_write16 (map, *((__u16*)tmp_p)++, adr+z); + } else if (cfi_buswidth_is_4()) { + map_write32 (map, *((__u32*)tmp_p)++, adr+z); + } else if (cfi_buswidth_is_8()) { + map_write64 (map, *((__u64*)tmp_p)++, adr+z); + } else { + ret = -EINVAL; + goto out; + } } /* GO GO GO */ cfi_write(map, CMD(0xd0), cmd_adr); @@ -1119,12 +1142,12 @@ } /* Write buffer is worth it only if more than one word to write... */ - while(len > CFIDEV_BUSWIDTH) { + while(len) { /* We must not cross write block boundaries */ int size = wbufsize - (ofs & (wbufsize-1)); if (size > len) - size = len & ~(CFIDEV_BUSWIDTH-1); + size = len; ret = do_write_buffer(map, &cfi->chips[chipnum], ofs, buf, size); if (ret) @@ -1142,17 +1165,6 @@ return 0; } } - - /* ... and write the remaining bytes */ - if (len > 0) { - size_t local_retlen; - ret = cfi_intelext_write_words(mtd, ofs + (chipnum << cfi->chipshift), - len, &local_retlen, buf); - if (ret) - return ret; - (*retlen) += local_retlen; - } - return 0; } @@ -1423,6 +1435,7 @@ * with the chip now anyway. */ } + spin_unlock(chip->mutex); } /* Unlock the chips again */ diff -Nru a/drivers/mtd/chips/gen_probe.c b/drivers/mtd/chips/gen_probe.c --- a/drivers/mtd/chips/gen_probe.c Tue Jul 1 18:44:37 2003 +++ b/drivers/mtd/chips/gen_probe.c Tue Jul 1 18:44:37 2003 @@ -1,8 +1,8 @@ /* * Routines common to all CFI-type probes. - * (C) 2001, 2001 Red Hat, Inc. + * (C) 2001-2003 Red Hat, Inc. * GPL'd - * $Id: gen_probe.c,v 1.11 2003/05/21 15:15:05 dwmw2 Exp $ + * $Id: gen_probe.c,v 1.13 2003/06/25 11:50:37 dwmw2 Exp $ */ #include @@ -281,6 +281,7 @@ extern cfi_cmdset_fn_t cfi_cmdset_0001; extern cfi_cmdset_fn_t cfi_cmdset_0002; +extern cfi_cmdset_fn_t cfi_cmdset_0020; static inline struct mtd_info *cfi_cmdset_unknown(struct map_info *map, int primary) diff -Nru a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c --- a/drivers/mtd/devices/doc2000.c Tue Jul 1 18:44:31 2003 +++ b/drivers/mtd/devices/doc2000.c Tue Jul 1 18:44:31 2003 @@ -4,7 +4,7 @@ * (c) 1999 Machine Vision Holdings, Inc. * (c) 1999, 2000 David Woodhouse * - * $Id: doc2000.c,v 1.52 2003/05/20 21:03:07 dwmw2 Exp $ + * $Id: doc2000.c,v 1.53 2003/06/11 09:45:19 dwmw2 Exp $ */ #include @@ -553,6 +553,7 @@ mtd->type = MTD_NANDFLASH; mtd->flags = MTD_CAP_NANDFLASH; + mtd->ecctype = MTD_ECC_RS_DiskOnChip; mtd->size = 0; mtd->erasesize = 0; mtd->oobblock = 512; diff -Nru a/drivers/mtd/devices/doc2001.c b/drivers/mtd/devices/doc2001.c --- a/drivers/mtd/devices/doc2001.c Tue Jul 1 18:44:34 2003 +++ b/drivers/mtd/devices/doc2001.c Tue Jul 1 18:44:34 2003 @@ -4,7 +4,7 @@ * (c) 1999 Machine Vision Holdings, Inc. * (c) 1999, 2000 David Woodhouse * - * $Id: doc2001.c,v 1.40 2003/05/20 21:03:07 dwmw2 Exp $ + * $Id: doc2001.c,v 1.41 2003/06/11 09:45:19 dwmw2 Exp $ */ #include @@ -359,9 +359,10 @@ mtd->type = MTD_NANDFLASH; mtd->flags = MTD_CAP_NANDFLASH; + mtd->ecctype = MTD_ECC_RS_DiskOnChip; mtd->size = 0; - /* FIXME: erase size is not always 8kB */ + /* FIXME: erase size is not always 8KiB */ mtd->erasesize = 0x2000; mtd->oobblock = 512; diff -Nru a/drivers/mtd/devices/doc2001plus.c b/drivers/mtd/devices/doc2001plus.c --- a/drivers/mtd/devices/doc2001plus.c Tue Jul 1 18:44:31 2003 +++ b/drivers/mtd/devices/doc2001plus.c Tue Jul 1 18:44:31 2003 @@ -6,7 +6,7 @@ * (c) 1999 Machine Vision Holdings, Inc. * (c) 1999, 2000 David Woodhouse * - * $Id: doc2001plus.c,v 1.4 2003/05/23 11:28:46 dwmw2 Exp $ + * $Id: doc2001plus.c,v 1.5 2003/06/11 09:45:19 dwmw2 Exp $ */ #include @@ -458,6 +458,7 @@ mtd->type = MTD_NANDFLASH; mtd->flags = MTD_CAP_NANDFLASH; + mtd->ecctype = MTD_ECC_RS_DiskOnChip; mtd->size = 0; mtd->erasesize = 0; diff -Nru a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c --- a/drivers/mtd/ftl.c Tue Jul 1 18:44:37 2003 +++ b/drivers/mtd/ftl.c Tue Jul 1 18:44:37 2003 @@ -1,5 +1,5 @@ /* This version ported to the Linux-MTD system by dwmw2@infradead.org - * $Id: ftl.c,v 1.50 2003/05/21 10:49:47 dwmw2 Exp $ + * $Id: ftl.c,v 1.51 2003/06/23 12:00:08 dwmw2 Exp $ * * Fixes: Arnaldo Carvalho de Melo * - fixes some leaks on failure in build_maps and ftl_notify_add, cleanups @@ -984,37 +984,20 @@ return 0; } /* ftl_write */ -/*====================================================================== - - IOCTL calls for getting device parameters. - -======================================================================*/ - -static int ftl_ioctl(struct mtd_blktrans_dev *dev, struct inode *inode, - struct file *file, u_int cmd, u_long arg) +static int ftl_getgeo(struct mtd_blktrans_dev *dev, struct hd_geometry *geo) { - struct hd_geometry *geo = (struct hd_geometry *)arg; - partition_t *part = (void *)dev; - u_long sect; - - switch (cmd) { - case HDIO_GETGEO: - /* Sort of arbitrary: round size down to 4K boundary */ - sect = le32_to_cpu(part->header.FormattedSize)/SECTOR_SIZE; - if (put_user(1, (char *)&geo->heads) || - put_user(8, (char *)&geo->sectors) || - put_user((sect>>3), (short *)&geo->cylinders) || - put_user(0, (u_long *)&geo->start)) - return -EFAULT; + partition_t *part = (void *)dev; + u_long sect; - case BLKFLSBUF: - return 0; - } - return -ENOTTY; -} /* ftl_ioctl */ + /* Sort of arbitrary: round size down to 4KiB boundary */ + sect = le32_to_cpu(part->header.FormattedSize)/SECTOR_SIZE; + geo->heads = 1; + geo->sectors = 8; + geo->cylinders = sect >> 3; -/*======================================================================*/ + return 0; +} static int ftl_readsect(struct mtd_blktrans_dev *dev, unsigned long block, char *buf) @@ -1102,7 +1085,7 @@ .part_bits = PART_BITS, .readsect = ftl_readsect, .writesect = ftl_writesect, - .ioctl = ftl_ioctl, + .getgeo = ftl_getgeo, .add_mtd = ftl_add_mtd, .remove_dev = ftl_remove_dev, .owner = THIS_MODULE, @@ -1110,7 +1093,7 @@ int init_ftl(void) { - DEBUG(0, "$Id: ftl.c,v 1.50 2003/05/21 10:49:47 dwmw2 Exp $\n"); + DEBUG(0, "$Id: ftl.c,v 1.51 2003/06/23 12:00:08 dwmw2 Exp $\n"); return register_mtd_blktrans(&ftl_tr); } diff -Nru a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c --- a/drivers/mtd/inftlcore.c Tue Jul 1 18:44:32 2003 +++ b/drivers/mtd/inftlcore.c Tue Jul 1 18:44:32 2003 @@ -7,7 +7,7 @@ * (c) 1999 Machine Vision Holdings, Inc. * Author: David Woodhouse * - * $Id: inftlcore.c,v 1.9 2003/05/23 11:41:47 dwmw2 Exp $ + * $Id: inftlcore.c,v 1.14 2003/06/26 08:28:26 dwmw2 Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -113,7 +113,7 @@ (long)inftl->sectors ); } - if (add_mtd_blktrans_dev) { + if (add_mtd_blktrans_dev(&inftl->mbd)) { if (inftl->PUtable) kfree(inftl->PUtable); if (inftl->VUtable) @@ -573,7 +573,7 @@ { unsigned char BlockUsed[MAX_SECTORS_PER_UNIT]; unsigned char BlockDeleted[MAX_SECTORS_PER_UNIT]; - unsigned int thisEUN, prevEUN, status; + unsigned int thisEUN, status; int block, silly; struct inftl_bci bci; size_t retlen; @@ -645,26 +645,45 @@ DEBUG(MTD_DEBUG_LEVEL1, "INFTL: deleting empty VUC %d\n", thisVUC); for (;;) { + u16 *prevEUN = &inftl->VUtable[thisVUC]; + thisEUN = *prevEUN; + + /* If the chain is all gone already, we're done */ + if (thisEUN == BLOCK_NIL) { + DEBUG(MTD_DEBUG_LEVEL2, "INFTL: Empty VUC %d for deletion was already absent\n", thisEUN); + return; + } + /* Find oldest unit in chain. */ - thisEUN = inftl->VUtable[thisVUC]; - prevEUN = BLOCK_NIL; while (inftl->PUtable[thisEUN] != BLOCK_NIL) { - prevEUN = thisEUN; - thisEUN = inftl->PUtable[thisEUN]; + BUG_ON(thisEUN >= inftl->nb_blocks); + + prevEUN = &inftl->PUtable[thisEUN]; + thisEUN = *prevEUN; } + DEBUG(MTD_DEBUG_LEVEL3, "Deleting EUN %d from VUC %d\n", + thisEUN, thisVUC); + if (INFTL_formatblock(inftl, thisEUN) < 0) { /* * Could not erase : mark block as reserved. - * FixMe: Update Bad Unit Table on disk. + * FixMe: Update Bad Unit Table on medium. */ inftl->PUtable[thisEUN] = BLOCK_RESERVED; } else { /* Correctly erased : mark it as free */ inftl->PUtable[thisEUN] = BLOCK_FREE; - inftl->PUtable[prevEUN] = BLOCK_NIL; inftl->numfreeEUNs++; - } + } + + /* Now sort out whatever was pointing to it... */ + *prevEUN = BLOCK_NIL; + + /* Ideally we'd actually be responsive to new + requests while we're doing this -- if there's + free space why should others be made to wait? */ + cond_resched(); } inftl->VUtable[thisVUC] = BLOCK_NIL; @@ -835,35 +854,22 @@ return 0; } - -static int inftl_ioctl(struct mtd_blktrans_dev *dev, - struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static int inftl_getgeo(struct mtd_blktrans_dev *dev, struct hd_geometry *geo) { - struct NFTLrecord *nftl = (void *)dev; - - switch (cmd) { - case HDIO_GETGEO: { - struct hd_geometry g; + struct INFTLrecord *inftl = (void *)dev; - g.heads = nftl->heads; - g.sectors = nftl->sectors; - g.cylinders = nftl->cylinders; - g.start = 0; - return copy_to_user((void *)arg, &g, sizeof g) ? -EFAULT : 0; - } + geo->heads = inftl->heads; + geo->sectors = inftl->sectors; + geo->cylinders = inftl->cylinders; - default: - return -ENOTTY; - } + return 0; } - struct mtd_blktrans_ops inftl_tr = { .name = "inftl", .major = INFTL_MAJOR, .part_bits = INFTL_PARTN_BITS, - .ioctl = inftl_ioctl, + .getgeo = inftl_getgeo, .readsect = inftl_readblock, .writesect = inftl_writeblock, .add_mtd = inftl_add_mtd, @@ -875,7 +881,7 @@ int __init init_inftl(void) { - printk(KERN_INFO "INFTL: inftlcore.c $Revision: 1.9 $, " + printk(KERN_INFO "INFTL: inftlcore.c $Revision: 1.14 $, " "inftlmount.c %s\n", inftlmountrev); return register_mtd_blktrans(&inftl_tr); diff -Nru a/drivers/mtd/inftlmount.c b/drivers/mtd/inftlmount.c --- a/drivers/mtd/inftlmount.c Tue Jul 1 18:44:31 2003 +++ b/drivers/mtd/inftlmount.c Tue Jul 1 18:44:31 2003 @@ -8,7 +8,7 @@ * Author: Fabrice Bellard (fabrice.bellard@netgem.com) * Copyright (C) 2000 Netgem S.A. * - * $Id: inftlmount.c,v 1.9 2003/05/23 11:35:07 dwmw2 Exp $ + * $Id: inftlmount.c,v 1.11 2003/06/23 07:39:21 dwmw2 Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,7 +25,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define __NO_VERSION__ #include #include #include @@ -42,7 +41,7 @@ #include #include -char inftlmountrev[]="$Revision: 1.9 $"; +char inftlmountrev[]="$Revision: 1.11 $"; /* * find_boot_record: Find the INFTL Media Header and its Spare copy which @@ -242,7 +241,7 @@ } if ((ip->lastUnit - ip->firstUnit + 1) < ip->virtualUnits) { printk(KERN_WARNING "INFTL: Media Header " - "Parition %d sanity check failed\n" + "Partition %d sanity check failed\n" " firstUnit %d : lastUnit %d > " "virtualUnits %d\n", i, ip->lastUnit, ip->firstUnit, ip->Reserved0); @@ -250,7 +249,7 @@ } if (ip->Reserved1 != 0) { printk(KERN_WARNING "INFTL: Media Header " - "Parition %d sanity check failed: " + "Partition %d sanity check failed: " "Reserved1 %d != 0\n", i, ip->Reserved1); return -1; @@ -261,7 +260,7 @@ } if (i >= 4) { - printk(KERN_WARNING "INFTL: Media Header Parition " + printk(KERN_WARNING "INFTL: Media Header Partition " "sanity check failed:\n No partition " "marked as Disk Partition\n"); return -1; @@ -630,7 +629,7 @@ if (prev_block < s->nb_blocks) prev_block += s->firstEUN; - /* Already explored paritial chain? */ + /* Already explored partial chain? */ if (s->PUtable[block] != BLOCK_NOTEXPLORED) { /* Check if chain for this logical */ if (logical_block == first_logical_block) { diff -Nru a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig --- a/drivers/mtd/maps/Kconfig Tue Jul 1 18:44:39 2003 +++ b/drivers/mtd/maps/Kconfig Tue Jul 1 18:44:39 2003 @@ -1,5 +1,5 @@ # drivers/mtd/maps/Kconfig -# $Id: Kconfig,v 1.11 2003/05/28 15:16:56 dwmw2 Exp $ +# $Id: Kconfig,v 1.12 2003/06/23 07:38:11 dwmw2 Exp $ menu "Mapping drivers for chip access" depends on MTD!=n @@ -476,7 +476,7 @@ config MTD_UCLINUX tristate "Generic uClinux RAM/ROM filesystem support" - depends on MTD_PARTITIONS + depends on MTD_PARTITIONS && !MMU help Map driver to support image based filesystems for uClinux. diff -Nru a/drivers/mtd/maps/arctic-mtd.c b/drivers/mtd/maps/arctic-mtd.c --- a/drivers/mtd/maps/arctic-mtd.c Tue Jul 1 18:44:34 2003 +++ b/drivers/mtd/maps/arctic-mtd.c Tue Jul 1 18:44:34 2003 @@ -1,5 +1,5 @@ /* - * $Id: arctic-mtd.c,v 1.8 2003/05/21 12:45:17 dwmw2 Exp $ + * $Id: arctic-mtd.c,v 1.10 2003/06/02 16:37:59 trini Exp $ * * drivers/mtd/maps/arctic-mtd.c MTD mappings and partition tables for * IBM 405LP Arctic boards. @@ -45,18 +45,23 @@ #include /* - * fe000000 -- ff9fffff Arctic FFS (26MB) - * ffa00000 -- fff5ffff kernel (5.504MB) - * fff60000 -- ffffffff firmware (640KB) + * 0 : 0xFE00 0000 - 0xFEFF FFFF : Filesystem 1 (16MiB) + * 1 : 0xFF00 0000 - 0xFF4F FFFF : kernel (5.12MiB) + * 2 : 0xFF50 0000 - 0xFFF5 FFFF : Filesystem 2 (10.624MiB) (if non-XIP) + * 3 : 0xFFF6 0000 - 0xFFFF FFFF : PIBS Firmware (640KiB) */ -#define ARCTIC_FFS_SIZE 0x01a00000 /* 26 M */ -#define ARCTIC_FIRMWARE_SIZE 0x000a0000 /* 640K */ +#define FFS1_SIZE 0x01000000 /* 16MiB */ +#define KERNEL_SIZE 0x00500000 /* 5.12MiB */ +#define FFS2_SIZE 0x00a60000 /* 10.624MiB */ +#define FIRMWARE_SIZE 0x000a0000 /* 640KiB */ -#define NAME "Arctic Linux Flash" -#define PADDR SUBZERO_BOOTFLASH_PADDR -#define SIZE SUBZERO_BOOTFLASH_SIZE -#define BUSWIDTH 2 + +#define NAME "Arctic Linux Flash" +#define PADDR SUBZERO_BOOTFLASH_PADDR +#define BUSWIDTH 2 +#define SIZE SUBZERO_BOOTFLASH_SIZE +#define PARTITIONS 4 /* Flash memories on these boards are memory resources, accessed big-endian. */ @@ -73,17 +78,19 @@ static struct mtd_info *arctic_mtd; -static struct mtd_partition arctic_partitions[3] = { - { .name = "Arctic FFS", - .size = ARCTIC_FFS_SIZE, +static struct mtd_partition arctic_partitions[PARTITIONS] = { + { .name = "Filesystem", + .size = FFS1_SIZE, .offset = 0,}, - { .name = "Kernel", - .size = SUBZERO_BOOTFLASH_SIZE - ARCTIC_FFS_SIZE - - ARCTIC_FIRMWARE_SIZE, - .offset = ARCTIC_FFS_SIZE,}, + { .name = "Kernel", + .size = KERNEL_SIZE, + .offset = FFS1_SIZE,}, + { .name = "Filesystem", + .size = FFS2_SIZE, + .offset = FFS1_SIZE + KERNEL_SIZE,}, { .name = "Firmware", - .size = ARCTIC_FIRMWARE_SIZE, - .offset = SUBZERO_BOOTFLASH_SIZE - ARCTIC_FIRMWARE_SIZE,}, + .size = FIRMWARE_SIZE, + .offset = SUBZERO_BOOTFLASH_SIZE - FIRMWARE_SIZE,}, }; static int __init @@ -107,7 +114,7 @@ arctic_mtd->owner = THIS_MODULE; - return add_mtd_partitions(arctic_mtd, arctic_partitions, 3); + return add_mtd_partitions(arctic_mtd, arctic_partitions, PARTITIONS); } static void __exit diff -Nru a/drivers/mtd/maps/ebony.c b/drivers/mtd/maps/ebony.c --- a/drivers/mtd/maps/ebony.c Tue Jul 1 18:44:37 2003 +++ b/drivers/mtd/maps/ebony.c Tue Jul 1 18:44:37 2003 @@ -1,5 +1,5 @@ /* - * $Id: ebony.c,v 1.7 2003/05/21 12:45:18 dwmw2 Exp $ + * $Id: ebony.c,v 1.8 2003/06/23 11:48:18 dwmw2 Exp $ * * Mapping for Ebony user flash * @@ -60,8 +60,6 @@ } }; -#define NB_OF(x) (sizeof(x)/sizeof(x[0])) - int __init init_ebony(void) { u8 fpga0_reg; @@ -109,7 +107,7 @@ if (flash) { flash->owner = THIS_MODULE; add_mtd_partitions(flash, ebony_small_partitions, - NB_OF(ebony_small_partitions)); + ARRAY_SIZE(ebony_small_partitions)); } else { printk("map probe failed for flash\n"); return -ENXIO; @@ -131,7 +129,7 @@ if (flash) { flash->owner = THIS_MODULE; add_mtd_partitions(flash, ebony_large_partitions, - NB_OF(ebony_large_partitions)); + ARRAY_SIZE(ebony_large_partitions)); } else { printk("map probe failed for flash\n"); return -ENXIO; diff -Nru a/drivers/mtd/maps/edb7312.c b/drivers/mtd/maps/edb7312.c --- a/drivers/mtd/maps/edb7312.c Tue Jul 1 18:44:39 2003 +++ b/drivers/mtd/maps/edb7312.c Tue Jul 1 18:44:39 2003 @@ -1,5 +1,5 @@ /* - * $Id: edb7312.c,v 1.8 2003/05/21 12:45:18 dwmw2 Exp $ + * $Id: edb7312.c,v 1.9 2003/06/23 11:48:18 dwmw2 Exp $ * * Handle mapping of the NOR flash on Cogent EDB7312 boards * @@ -67,7 +67,6 @@ }, }; -#define NB_OF(x) (sizeof (x) / sizeof (x[0])) static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; #endif @@ -109,7 +108,7 @@ if (mtd_parts_nb == 0) { mtd_parts = static_partitions; - mtd_parts_nb = NB_OF(static_partitions); + mtd_parts_nb = ARRAY_SIZE(static_partitions); part_type = "static"; } #endif diff -Nru a/drivers/mtd/maps/elan-104nc.c b/drivers/mtd/maps/elan-104nc.c --- a/drivers/mtd/maps/elan-104nc.c Tue Jul 1 18:44:35 2003 +++ b/drivers/mtd/maps/elan-104nc.c Tue Jul 1 18:44:35 2003 @@ -16,7 +16,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - $Id: elan-104nc.c,v 1.17 2003/05/21 15:15:07 dwmw2 Exp $ + $Id: elan-104nc.c,v 1.18 2003/06/23 07:37:02 dwmw2 Exp $ The ELAN-104NC has up to 8 Mibyte of Intel StrataFlash (28F320/28F640) in x16 mode. This drivers uses the CFI probe and Intel Extended Command Set drivers. @@ -223,30 +223,19 @@ } iounmap((void *)iomapadr); - release_region(PAGE_IO,PAGE_IO_SIZE); } int __init init_elan_104nc(void) { - /* Urg! We use I/O port 0x22 without request_region()ing it */ - /* - if (check_region(PAGE_IO,PAGE_IO_SIZE) != 0) { - printk( KERN_ERR"%s: IO ports 0x%x-0x%x in use\n", - elan_104nc_map.name, - PAGE_IO, PAGE_IO+PAGE_IO_SIZE-1 ); - return -EAGAIN; - } - */ + /* Urg! We use I/O port 0x22 without request_region()ing it, + because it's already allocated to the PIC. */ + iomapadr = (unsigned long)ioremap(WINDOW_START, WINDOW_LENGTH); if (!iomapadr) { printk( KERN_ERR"%s: failed to ioremap memory region\n", elan_104nc_map.name ); return -EIO; } - - /* - request_region( PAGE_IO, PAGE_IO_SIZE, "ELAN-104NC flash" ); - */ printk( KERN_INFO"%s: IO:0x%x-0x%x MEM:0x%x-0x%x\n", elan_104nc_map.name, diff -Nru a/drivers/mtd/maps/impa7.c b/drivers/mtd/maps/impa7.c --- a/drivers/mtd/maps/impa7.c Tue Jul 1 18:44:32 2003 +++ b/drivers/mtd/maps/impa7.c Tue Jul 1 18:44:32 2003 @@ -1,5 +1,5 @@ /* - * $Id: impa7.c,v 1.8 2003/05/21 12:45:18 dwmw2 Exp $ + * $Id: impa7.c,v 1.9 2003/06/23 11:47:43 dwmw2 Exp $ * * Handle mapping of the NOR flash on implementa A7 boards * @@ -66,12 +66,11 @@ }, }; -#define NB_OF(x) (sizeof (x) / sizeof (x[0])) +static int mtd_parts_nb[NUM_FLASHBANKS]; +static struct mtd_partition *mtd_parts[NUM_FLASHBANKS]; #endif -static int mtd_parts_nb = 0; -static struct mtd_partition *mtd_parts = 0; static const char *probes[] = { "cmdlinepart", NULL }; int __init init_impa7(void) @@ -84,7 +83,6 @@ { WINDOW_ADDR0, WINDOW_SIZE0 }, { WINDOW_ADDR1, WINDOW_SIZE1 }, }; - char mtdid[10]; int devicesfound = 0; for(i=0; iowner = THIS_MODULE; - add_mtd_device(impa7_mtd[i]); devicesfound++; #ifdef CONFIG_MTD_PARTITIONS - mtd_parts_nb = parse_mtd_partitions(impa7_mtd[i], - probes, - &mtd_parts, - 0); - if (mtd_parts_nb > 0) - part_type = "command line"; -#endif - if (mtd_parts_nb <= 0) - { - mtd_parts = static_partitions; - mtd_parts_nb = NB_OF(static_partitions); + mtd_parts_nb[i] = parse_mtd_partitions(impa7_mtd[i], + probes, + &mtd_parts[i], + 0); + if (mtd_parts_nb[i] > 0) { + part_type = "command line"; + } else { + mtd_parts[i] = static_partitions; + mtd_parts_nb[i] = ARRAY_SIZE(static_partitions); part_type = "static"; } - if (mtd_parts_nb <= 0) - { - printk(KERN_NOTICE MSG_PREFIX - "no partition info available\n"); - } - else - { - printk(KERN_NOTICE MSG_PREFIX - "using %s partition definition\n", - part_type); - add_mtd_partitions(impa7_mtd[i], - mtd_parts, mtd_parts_nb); - } + + printk(KERN_NOTICE MSG_PREFIX + "using %s partition definition\n", + part_type); + add_mtd_partitions(impa7_mtd[i], + mtd_parts[i], mtd_parts_nb[i]); +#else + add_mtd_device(impa7_mtd[i]); + #endif } else - iounmap((void *)impa7_map[i].virt); + iounmap((void *)impa7_map[i].virt); } return devicesfound == 0 ? -ENXIO : 0; } @@ -150,15 +140,14 @@ static void __exit cleanup_impa7(void) { int i; - for (i=0; i * - * $Id: pb1xxx-flash.c,v 1.8 2003/05/21 12:45:19 dwmw2 Exp $ + * $Id: pb1xxx-flash.c,v 1.9 2003/06/23 11:48:18 dwmw2 Exp $ */ #include @@ -131,9 +131,6 @@ #error Unsupported board #endif - -#define NB_OF(x) (sizeof(x)/sizeof(x[0])) - static struct mtd_partition *parsed_parts; static struct mtd_info *mymtd; @@ -151,7 +148,7 @@ */ part_type = "static"; parts = pb1xxx_partitions; - nb_parts = NB_OF(pb1xxx_partitions); + nb_parts = ARRAY_SIZE(pb1xxx_partitions); pb1xxx_map.size = flash_size; /* diff -Nru a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c --- a/drivers/mtd/maps/pcmciamtd.c Tue Jul 1 18:44:32 2003 +++ b/drivers/mtd/maps/pcmciamtd.c Tue Jul 1 18:44:32 2003 @@ -1,5 +1,5 @@ /* - * $Id: pcmciamtd.c,v 1.47 2003/05/28 13:36:14 dwmw2 Exp $ + * $Id: pcmciamtd.c,v 1.48 2003/06/24 07:14:38 spse Exp $ * * pcmciamtd.c - MTD driver for PCMCIA flash memory cards * @@ -43,33 +43,32 @@ static const int debug = 0; #endif -#define err(format, arg...) printk(KERN_ERR __FILE__ ": " format "\n" , ## arg) -#define info(format, arg...) printk(KERN_INFO __FILE__ ": " format "\n" , ## arg) -#define warn(format, arg...) printk(KERN_WARNING __FILE__ ": " format "\n" , ## arg) +#define err(format, arg...) printk(KERN_ERR "pcmciamtd: " format "\n" , ## arg) +#define info(format, arg...) printk(KERN_INFO "pcmciamtd: " format "\n" , ## arg) +#define warn(format, arg...) printk(KERN_WARNING "pcmciamtd: " format "\n" , ## arg) #define DRIVER_DESC "PCMCIA Flash memory card driver" -#define DRIVER_VERSION "$Revision: 1.47 $" +#define DRIVER_VERSION "$Revision: 1.48 $" /* Size of the PCMCIA address space: 26 bits = 64 MB */ #define MAX_PCMCIA_ADDR 0x4000000 struct pcmciamtd_dev { - struct list_head list; dev_link_t link; /* PCMCIA link */ + dev_node_t node; /* device node */ caddr_t win_base; /* ioremapped address of PCMCIA window */ unsigned int win_size; /* size of window */ - unsigned int cardsize; /* size of whole card */ unsigned int offset; /* offset into card the window currently points at */ struct map_info pcmcia_map; struct mtd_info *mtd_info; - u8 vpp; + int vpp; char mtd_name[sizeof(struct cistpl_vers_1_t)]; }; static dev_info_t dev_info = "pcmciamtd"; -static LIST_HEAD(dev_list); +static dev_link_t *dev_list; /* Module parameters */ @@ -99,7 +98,7 @@ MODULE_PARM(mem_speed, "i"); MODULE_PARM_DESC(mem_speed, "Set memory access speed in ns"); MODULE_PARM(force_size, "i"); -MODULE_PARM_DESC(force_size, "Force size of card in MB (1-64)"); +MODULE_PARM_DESC(force_size, "Force size of card in MiB (1-64)"); MODULE_PARM(setvpp, "i"); MODULE_PARM_DESC(setvpp, "Set Vpp (0=Never, 1=On writes, 2=Always on, default=0)"); MODULE_PARM(vpp, "i"); @@ -116,6 +115,11 @@ memreq_t mrq; int ret; + if(!(dev->link.state & DEV_PRESENT)) { + DEBUG(1, "device removed state = 0x%4.4X", dev->link.state); + return 0; + } + mrq.CardOffset = to & ~(dev->win_size-1); if(mrq.CardOffset != dev->offset) { DEBUG(2, "Remapping window from 0x%8.8x to 0x%8.8x", @@ -238,11 +242,16 @@ /* read/write{8,16} copy_{from,to} routines with direct access */ +#define DEV_REMOVED(x) (!(*(u_int *)x->map_priv_1 & DEV_PRESENT)) + static u8 pcmcia_read8(struct map_info *map, unsigned long ofs) { caddr_t win_base = (caddr_t)map->map_priv_2; u8 d; + if(DEV_REMOVED(map)) + return 0; + d = readb(win_base + ofs); DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%02x", ofs, win_base + ofs, d); return d; @@ -254,6 +263,9 @@ caddr_t win_base = (caddr_t)map->map_priv_2; u16 d; + if(DEV_REMOVED(map)) + return 0; + d = readw(win_base + ofs); DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%04x", ofs, win_base + ofs, d); return d; @@ -264,6 +276,9 @@ { caddr_t win_base = (caddr_t)map->map_priv_2; + if(DEV_REMOVED(map)) + return; + DEBUG(3, "to = %p from = %lu len = %u", to, from, len); memcpy_fromio(to, win_base + from, len); } @@ -273,6 +288,9 @@ { caddr_t win_base = (caddr_t)map->map_priv_2; + if(DEV_REMOVED(map)) + return; + DEBUG(3, "adr = 0x%08lx (%p) data = 0x%02x", adr, win_base + adr, d); writeb(d, win_base + adr); } @@ -282,6 +300,9 @@ { caddr_t win_base = (caddr_t)map->map_priv_2; + if(DEV_REMOVED(map)) + return; + DEBUG(3, "adr = 0x%08lx (%p) data = 0x%04x", adr, win_base + adr, d); writew(d, win_base + adr); } @@ -291,6 +312,9 @@ { caddr_t win_base = (caddr_t)map->map_priv_2; + if(DEV_REMOVED(map)) + return; + DEBUG(3, "to = %lu from = %p len = %u", to, from, len); memcpy_toio(win_base + to, from, len); } @@ -323,40 +347,18 @@ static void pcmciamtd_release(u_long arg) { dev_link_t *link = (dev_link_t *)arg; - struct pcmciamtd_dev *dev = NULL; - int ret; - struct list_head *temp1, *temp2; + struct pcmciamtd_dev *dev = link->priv; DEBUG(3, "link = 0x%p", link); - /* Find device in list */ - list_for_each_safe(temp1, temp2, &dev_list) { - dev = list_entry(temp1, struct pcmciamtd_dev, list); - if(link == &dev->link) - break; - } - if(link != &dev->link) { - DEBUG(1, "Cant find %p in dev_list", link); - return; - } - if(dev) { - if(dev->mtd_info) { - del_mtd_device(dev->mtd_info); - dev->mtd_info = NULL; - MOD_DEC_USE_COUNT; - } - if (link->win) { - if(dev->win_base) { - iounmap(dev->win_base); - dev->win_base = NULL; - } - CardServices(ReleaseWindow, link->win); + if (link->win) { + if(dev->win_base) { + iounmap(dev->win_base); + dev->win_base = NULL; } - ret = CardServices(ReleaseConfiguration, link->handle); - if(ret != CS_SUCCESS) - cs_error(link->handle, ReleaseConfiguration, ret); - + CardServices(ReleaseWindow, link->win); } + CardServices(ReleaseConfiguration, link->handle); link->state &= ~DEV_CONFIG; } @@ -465,7 +467,6 @@ if(force_size) { dev->pcmcia_map.size = force_size << 20; DEBUG(2, "size forced to %dM", force_size); - } if(buswidth) { @@ -580,9 +581,8 @@ } DEBUG(1, "mapped window dev = %p req.base = 0x%lx base = %p size = 0x%x", dev, req.Base, dev->win_base, req.Size); - dev->cardsize = 0; - dev->offset = 0; + dev->offset = 0; dev->pcmcia_map.map_priv_1 = (unsigned long)dev; dev->pcmcia_map.map_priv_2 = (unsigned long)link->win; @@ -614,9 +614,6 @@ cs_error(link->handle, RequestConfiguration, ret); } - link->dev = NULL; - link->state &= ~DEV_CONFIG_PENDING; - if(mem_type == 1) { mtd = do_map_probe("map_ram", &dev->pcmcia_map); } else if(mem_type == 2) { @@ -640,7 +637,6 @@ dev->mtd_info = mtd; mtd->owner = THIS_MODULE; - dev->cardsize = mtd->size; if(new_name) { int size = 0; @@ -649,19 +645,19 @@ size */ if(mtd->size < 1048576) { /* <1MiB in size, show size in KiB */ size = mtd->size >> 10; - unit = 'K'; + unit = 'K'; } else { size = mtd->size >> 20; unit = 'M'; } - sprintf(mtd->name, "%d%ciB %s", size, unit, "PCMCIA Memory card"); + snprintf(dev->mtd_name, sizeof(dev->mtd_name), "%d%ciB %s", size, unit, "PCMCIA Memory card"); } /* If the memory found is fits completely into the mapped PCMCIA window, use the faster non-remapping read/write functions */ - if(dev->cardsize <= dev->win_size) { + if(mtd->size <= dev->win_size) { DEBUG(1, "Using non remapping memory functions"); - + dev->pcmcia_map.map_priv_1 = (unsigned long)&(dev->link.state); dev->pcmcia_map.map_priv_2 = (unsigned long)dev->win_base; dev->pcmcia_map.read8 = pcmcia_read8; dev->pcmcia_map.read16 = pcmcia_read16; @@ -671,16 +667,17 @@ dev->pcmcia_map.copy_to = pcmcia_copy_to; } - MOD_INC_USE_COUNT; if(add_mtd_device(mtd)) { + map_destroy(mtd); dev->mtd_info = NULL; - MOD_DEC_USE_COUNT; err("Couldnt register MTD device"); pcmciamtd_release((u_long)link); return; } - DEBUG(1, "mtd added @ %p mtd->priv = %p", mtd, mtd->priv); - + snprintf(dev->node.dev_name, sizeof(dev->node.dev_name), "mtd%d", mtd->index); + info("mtd%d: %s", mtd->index, mtd->name); + link->state &= ~DEV_CONFIG_PENDING; + link->dev = &dev->node; return; cs_failed: @@ -707,8 +704,14 @@ case CS_EVENT_CARD_REMOVAL: DEBUG(2, "EVENT_CARD_REMOVAL"); link->state &= ~DEV_PRESENT; - if (link->state & DEV_CONFIG) + if (link->state & DEV_CONFIG) { + struct pcmciamtd_dev *dev = link->priv; + if(dev->mtd_info) { + del_mtd_device(dev->mtd_info); + info("mtd%d: Removed", dev->mtd_info->index); + } mod_timer(&link->release, jiffies + HZ/20); + } break; case CS_EVENT_CARD_INSERTION: DEBUG(2, "EVENT_CARD_INSERTION"); @@ -746,47 +749,23 @@ static void pcmciamtd_detach(dev_link_t *link) { - int ret; - struct pcmciamtd_dev *dev = NULL; - struct list_head *temp1, *temp2; - DEBUG(3, "link=0x%p", link); - /* Find device in list */ - list_for_each_safe(temp1, temp2, &dev_list) { - dev = list_entry(temp1, struct pcmciamtd_dev, list); - if(link == &dev->link) - break; - } - if(link != &dev->link) { - DEBUG(1, "Cant find %p in dev_list", link); - return; - } - del_timer(&link->release); - if(!dev) { - DEBUG(3, "dev is NULL"); - return; - } - - if (link->state & DEV_CONFIG) { - //pcmciamtd_release((u_long)link); - DEBUG(3, "DEV_CONFIG set"); - link->state |= DEV_STALE_LINK; - return; + if(link->state & DEV_CONFIG) { + pcmciamtd_release((u_long)link); } if (link->handle) { + int ret; DEBUG(2, "Deregistering with card services"); ret = CardServices(DeregisterClient, link->handle); if (ret != CS_SUCCESS) cs_error(link->handle, DeregisterClient, ret); } - DEBUG(3, "Freeing dev (%p)", dev); - list_del(&dev->list); - link->priv = NULL; - kfree(dev); + + link->state |= DEV_STALE_LINK; } @@ -808,15 +787,18 @@ DEBUG(1, "dev=0x%p", dev); memset(dev, 0, sizeof(*dev)); - link = &dev->link; link->priv = dev; + link = &dev->link; + link->priv = dev; + init_timer(&link->release); link->release.function = &pcmciamtd_release; link->release.data = (u_long)link; link->conf.Attributes = 0; link->conf.IntType = INT_MEMORY; - list_add(&dev->list, &dev_list); + link->next = dev_list; + dev_list = link; /* Register with Card Services */ client_reg.dev_info = &dev_info; @@ -835,19 +817,21 @@ pcmciamtd_detach(link); return NULL; } - + DEBUG(2, "link = %p", link); return link; } + static struct pcmcia_driver pcmciamtd_driver = { - .owner = THIS_MODULE, .drv = { - .name = "pcmciamtd", + .name = "pcmciamtd" }, .attach = pcmciamtd_attach, .detach = pcmciamtd_detach, + .owner = THIS_MODULE }; + static int __init init_pcmciamtd(void) { info(DRIVER_DESC " " DRIVER_VERSION); @@ -864,25 +848,41 @@ info("bad mem_type (%d), using default", mem_type); mem_type = 0; } - return pcmcia_register_driver(&pcmciamtd_driver); } static void __exit exit_pcmciamtd(void) { - struct list_head *temp1, *temp2; - DEBUG(1, DRIVER_DESC " unloading"); - pcmcia_unregister_driver(&pcmciamtd_driver); - /* XXX: this really needs to move into generic code.. */ - list_for_each_safe(temp1, temp2, &dev_list) { - dev_link_t *link = &list_entry(temp1, struct pcmciamtd_dev, list)->link; - if (link && (link->state & DEV_CONFIG)) { - pcmciamtd_release((u_long)link); - pcmciamtd_detach(link); + while(dev_list) { + dev_link_t *link = dev_list; + + dev_list = link->next; + if (link) { + struct pcmciamtd_dev *dev = link->priv; + + if(dev) { + if(link->state & DEV_PRESENT) { + if (!(link->state & DEV_STALE_LINK)) { + pcmciamtd_detach(link); + } + link->state &= ~DEV_PRESENT; + if(dev->mtd_info) { + del_mtd_device(dev->mtd_info); + info("mtd%d: Removed", + dev->mtd_info->index); + } + } + if(dev->mtd_info) { + DEBUG(2, "Destroying map for mtd%d", + dev->mtd_info->index); + map_destroy(dev->mtd_info); + } + kfree(dev); + } } } } diff -Nru a/drivers/mtd/maps/tqm8xxl.c b/drivers/mtd/maps/tqm8xxl.c --- a/drivers/mtd/maps/tqm8xxl.c Tue Jul 1 18:44:32 2003 +++ b/drivers/mtd/maps/tqm8xxl.c Tue Jul 1 18:44:32 2003 @@ -2,7 +2,7 @@ * Handle mapping of the flash memory access routines * on TQM8xxL based devices. * - * $Id: tqm8xxl.c,v 1.8 2003/05/21 12:45:20 dwmw2 Exp $ + * $Id: tqm8xxl.c,v 1.9 2003/06/23 11:48:18 dwmw2 Exp $ * * based on rpxlite.c * @@ -110,8 +110,6 @@ }; #endif -#define NB_OF(x) (sizeof(x)/sizeof(x[0])) - int __init init_tqm_mtd(void) { int idx = 0, ret = 0; @@ -198,11 +196,11 @@ */ part_banks[0].mtd_part = tqm8xxl_partitions; part_banks[0].type = "Static image"; - part_banks[0].nums = NB_OF(tqm8xxl_partitions); + part_banks[0].nums = ARRAY_SIZE(tqm8xxl_partitions); part_banks[1].mtd_part = tqm8xxl_fs_partitions; part_banks[1].type = "Static file system"; - part_banks[1].nums = NB_OF(tqm8xxl_fs_partitions); + part_banks[1].nums = ARRAY_SIZE(tqm8xxl_fs_partitions); for(idx = 0; idx < num_banks ; idx++) { if (part_banks[idx].nums == 0) { diff -Nru a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c --- a/drivers/mtd/mtd_blkdevs.c Tue Jul 1 18:44:31 2003 +++ b/drivers/mtd/mtd_blkdevs.c Tue Jul 1 18:44:31 2003 @@ -1,5 +1,5 @@ /* - * $Id: mtd_blkdevs.c,v 1.12 2003/05/21 01:00:59 dwmw2 Exp $ + * $Id: mtd_blkdevs.c,v 1.16 2003/06/23 13:34:43 dwmw2 Exp $ * * (C) 2003 David Woodhouse * @@ -18,8 +18,10 @@ #include #include #include +#include #include #include +#include #include static LIST_HEAD(blktrans_majors); @@ -46,7 +48,7 @@ nsect = req->current_nr_sectors; buf = req->buffer; - if (!req->flags & REQ_CMD) + if (!(req->flags & REQ_CMD)) return 0; if (block + nsect > get_capacity(req->rq_disk)) @@ -93,14 +95,14 @@ recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); + spin_lock_irq(rq->queue_lock); + while (!tr->blkcore_priv->exiting) { struct request *req; struct mtd_blktrans_dev *dev; int res = 0; DECLARE_WAITQUEUE(wait, current); - spin_lock_irq(rq->queue_lock); - req = elv_next_request(rq); if (!req) { @@ -112,6 +114,8 @@ schedule(); remove_wait_queue(&tr->blkcore_priv->thread_wq, &wait); + spin_lock_irq(rq->queue_lock); + continue; } @@ -159,7 +163,7 @@ dev->mtd->usecount++; ret = 0; - if (tr->open && (ret = tr->open(dev, i, f))) { + if (tr->open && (ret = tr->open(dev))) { dev->mtd->usecount--; module_put(dev->mtd->owner); out_tr: @@ -179,7 +183,7 @@ tr = dev->tr; if (tr->release) - ret = tr->release(dev, i, f); + ret = tr->release(dev); if (!ret) { dev->mtd->usecount--; @@ -194,21 +198,33 @@ static int blktrans_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - struct mtd_blktrans_dev *dev; - struct mtd_blktrans_ops *tr; - int ret = -ENOTTY; - - dev = inode->i_bdev->bd_disk->private_data; - tr = dev->tr; + struct mtd_blktrans_dev *dev = inode->i_bdev->bd_disk->private_data; + struct mtd_blktrans_ops *tr = dev->tr; - if (tr->ioctl) - ret = tr->ioctl(dev, inode, file, cmd, arg); - - if (ret == -ENOTTY && (cmd == BLKROSET || cmd == BLKFLSBUF)) { + switch (cmd) { + case BLKFLSBUF: + if (tr->flush) + return tr->flush(dev); /* The core code did the work, we had nothing to do. */ - ret = 0; + return 0; + + case HDIO_GETGEO: + if (tr->getgeo) { + struct hd_geometry g; + + memset(&g, 0, sizeof(g)); + int ret = tr->getgeo(dev, &g); + if (ret) + return ret; + + g.start = get_start_sect(inode->i_bdev); + if (copy_to_user((void *)arg, &g, sizeof(g))) + return -EFAULT; + return 0; + } /* else */ + default: + return -ENOTTY; } - return ret; } struct block_device_operations mtd_blktrans_ops = { @@ -328,8 +344,6 @@ if (mtd->type == MTD_ABSENT) return; - printk("%s:%s %d: count %d\n", __FILE__, __func__, __LINE__, atomic_read(&mtd_table_mutex.count)); - list_for_each(this, &blktrans_majors) { struct mtd_blktrans_ops *tr = list_entry(this, struct mtd_blktrans_ops, list); @@ -391,8 +405,6 @@ INIT_LIST_HEAD(&tr->devs); list_add(&tr->list, &blktrans_majors); - - printk("%s:%s %d: count %d\n", __FILE__, __func__, __LINE__, atomic_read(&mtd_table_mutex.count)); for (i=0; itype != MTD_ABSENT) diff -Nru a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c --- a/drivers/mtd/mtdblock.c Tue Jul 1 18:44:34 2003 +++ b/drivers/mtd/mtdblock.c Tue Jul 1 18:44:34 2003 @@ -1,7 +1,7 @@ /* * Direct MTD block device access * - * $Id: mtdblock.c,v 1.61 2003/05/21 10:49:38 dwmw2 Exp $ + * $Id: mtdblock.c,v 1.63 2003/06/23 12:00:08 dwmw2 Exp $ * * (C) 2000-2003 Nicolas Pitre * (C) 1999-2003 David Woodhouse @@ -248,11 +248,19 @@ unsigned long block, char *buf) { struct mtdblk_dev *mtdblk = mtdblks[dev->devnum]; + if (unlikely(!mtdblk->cache_data)) { + mtdblk->cache_data = vmalloc(mtdblk->mtd->erasesize); + if (!mtdblk->cache_data) + return -EINTR; + /* -EINTR is not really correct, but it is the best match + * documented in man 2 write for all cases. We could also + * return -EAGAIN sometimes, but why bother? + */ + } return do_cached_write(mtdblk, block<<9, 512, buf); } -static int mtdblock_open(struct mtd_blktrans_dev *mbd, - struct inode *inode, struct file *file) +static int mtdblock_open(struct mtd_blktrans_dev *mbd) { struct mtdblk_dev *mtdblk; struct mtd_info *mtd = mbd->mtd; @@ -279,11 +287,7 @@ if ((mtdblk->mtd->flags & MTD_CAP_RAM) != MTD_CAP_RAM && mtdblk->mtd->erasesize) { mtdblk->cache_size = mtdblk->mtd->erasesize; - mtdblk->cache_data = vmalloc(mtdblk->mtd->erasesize); - if (!mtdblk->cache_data) { - kfree(mtdblk); - return -ENOMEM; - } + mtdblk->cache_data = NULL; } mtdblks[dev] = mtdblk; @@ -293,17 +297,13 @@ return 0; } -static int mtdblock_release(struct mtd_blktrans_dev *mbd, - struct inode *inode, struct file *file) +static int mtdblock_release(struct mtd_blktrans_dev *mbd) { - int dev; - struct mtdblk_dev *mtdblk; + int dev = mbd->devnum; + struct mtdblk_dev *mtdblk = mtdblks[dev]; DEBUG(MTD_DEBUG_LEVEL1, "mtdblock_release\n"); - dev = minor(inode->i_rdev); - mtdblk = mtdblks[dev]; - down(&mtdblk->cache_sem); write_cached_data(mtdblk); up(&mtdblk->cache_sem); @@ -321,27 +321,17 @@ return 0; } - -static int mtdblock_ioctl(struct mtd_blktrans_dev *dev, - struct inode * inode, struct file * file, - unsigned int cmd, unsigned long arg) +static int mtdblock_flush(struct mtd_blktrans_dev *dev) { - struct mtdblk_dev *mtdblk; - - mtdblk = mtdblks[minor(inode->i_rdev)]; + struct mtdblk_dev *mtdblk = mtdblks[dev->devnum]; - switch (cmd) { - case BLKFLSBUF: - down(&mtdblk->cache_sem); - write_cached_data(mtdblk); - up(&mtdblk->cache_sem); - if (mtdblk->mtd->sync) - mtdblk->mtd->sync(mtdblk->mtd); - return 0; + down(&mtdblk->cache_sem); + write_cached_data(mtdblk); + up(&mtdblk->cache_sem); - default: - return -ENOTTY; - } + if (mtdblk->mtd->sync) + mtdblk->mtd->sync(mtdblk->mtd); + return 0; } static void mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) @@ -376,7 +366,7 @@ .major = 31, .part_bits = 0, .open = mtdblock_open, - .ioctl = mtdblock_ioctl, + .flush = mtdblock_flush, .release = mtdblock_release, .readsect = mtdblock_readsect, .writesect = mtdblock_writesect, diff -Nru a/drivers/mtd/mtdblock_ro.c b/drivers/mtd/mtdblock_ro.c --- a/drivers/mtd/mtdblock_ro.c Tue Jul 1 18:44:35 2003 +++ b/drivers/mtd/mtdblock_ro.c Tue Jul 1 18:44:35 2003 @@ -1,11 +1,12 @@ /* - * $Id: mtdblock_ro.c,v 1.17 2003/05/18 19:27:27 dwmw2 Exp $ + * $Id: mtdblock_ro.c,v 1.18 2003/06/23 12:00:08 dwmw2 Exp $ * * (C) 2003 David Woodhouse * * Simple read-only (writable only for RAM) mtdblock driver */ +#include #include #include #include diff -Nru a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c --- a/drivers/mtd/mtdpart.c Tue Jul 1 18:44:36 2003 +++ b/drivers/mtd/mtdpart.c Tue Jul 1 18:44:36 2003 @@ -5,7 +5,7 @@ * * This code is GPL * - * $Id: mtdpart.c,v 1.39 2003/05/21 15:15:03 dwmw2 Exp $ + * $Id: mtdpart.c,v 1.41 2003/06/18 14:53:02 dwmw2 Exp $ * * 02-21-2002 Thomas Gleixner * added support for read_oob, write_oob @@ -120,7 +120,7 @@ size_t *retlen, u_char *buf) { struct mtd_part *part = PART(mtd); - return part->master->read_user_prot_reg (part->master, from, + return part->master->read_fact_prot_reg (part->master, from, len, retlen, buf); } diff -Nru a/drivers/mtd/nand/autcpu12.c b/drivers/mtd/nand/autcpu12.c --- a/drivers/mtd/nand/autcpu12.c Tue Jul 1 18:44:32 2003 +++ b/drivers/mtd/nand/autcpu12.c Tue Jul 1 18:44:32 2003 @@ -6,7 +6,7 @@ * Derived from drivers/mtd/spia.c * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) * - * $Id: autcpu12.c,v 1.10 2003/04/20 07:24:40 gleixner Exp $ + * $Id: autcpu12.c,v 1.11 2003/06/04 17:04:09 gleixner Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -28,6 +28,7 @@ */ #include +#include #include #include #include diff -Nru a/drivers/mtd/nand/nand.c b/drivers/mtd/nand/nand.c --- a/drivers/mtd/nand/nand.c Tue Jul 1 18:44:39 2003 +++ b/drivers/mtd/nand/nand.c Tue Jul 1 18:44:39 2003 @@ -124,9 +124,15 @@ + a structure, which will be supplied by a filesystem driver * If NULL is given, then the defaults (none or defaults * supplied by ioctl (MEMSETOOBSEL) are used. - * For partitions the partition defaults are used (mtdpart.c) + * For partitions the partition defaults are used (mtdpart.c) + * + * 06-04-2003 tglx: fix compile errors and fix write verify problem for + * some chips, which need either a delay between the readback + * and the next write command or have the CE removed. The + * CE disable/enable is much faster than a 20us delay and + * it should work on all available chips. * - * $Id: nand.c,v 1.45 2003/05/20 21:01:30 dwmw2 Exp $ + * $Id: nand.c,v 1.46 2003/06/04 17:10:36 gleixner Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -141,6 +147,7 @@ #include #include #include +#include #include #include @@ -510,6 +517,13 @@ } } } + /* + * Terminate the read command. This is faster than sending a reset command or + * applying a 20us delay before issuing the next programm sequence. + * This is not a problem for all chips, but I have found a bunch of them. + */ + nand_deselect(); + nand_select(); #endif return 0; } diff -Nru a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c --- a/drivers/mtd/nftlcore.c Tue Jul 1 18:44:31 2003 +++ b/drivers/mtd/nftlcore.c Tue Jul 1 18:44:31 2003 @@ -1,7 +1,7 @@ /* Linux driver for NAND Flash Translation Layer */ /* (c) 1999 Machine Vision Holdings, Inc. */ /* Author: David Woodhouse */ -/* $Id: nftlcore.c,v 1.92 2003/05/23 11:41:47 dwmw2 Exp $ */ +/* $Id: nftlcore.c,v 1.94 2003/06/23 12:00:08 dwmw2 Exp $ */ /* The contents of this file are distributed under the GNU General @@ -101,7 +101,7 @@ (long)nftl->sectors ); } - if (add_mtd_blktrans_dev) { + if (add_mtd_blktrans_dev(&nftl->mbd)) { if (nftl->ReplUnitTable) kfree(nftl->ReplUnitTable); if (nftl->EUNtable) @@ -699,29 +699,17 @@ return 0; } -static int nftl_ioctl(struct mtd_blktrans_dev *dev, - struct inode * inode, struct file * file, - unsigned int cmd, unsigned long arg) +static int nftl_getgeo(struct mtd_blktrans_dev *dev, struct hd_geometry *geo) { struct NFTLrecord *nftl = (void *)dev; - switch (cmd) { - case HDIO_GETGEO: { - struct hd_geometry g; - - g.heads = nftl->heads; - g.sectors = nftl->sectors; - g.cylinders = nftl->cylinders; - g.start = 0; - return copy_to_user((void *)arg, &g, sizeof g) ? -EFAULT : 0; - } + geo->heads = nftl->heads; + geo->sectors = nftl->sectors; + geo->cylinders = nftl->cylinders; - default: - return -ENOTTY; - } + return 0; } - /**************************************************************************** * * Module stuff @@ -733,7 +721,7 @@ .name = "nftl", .major = NFTL_MAJOR, .part_bits = NFTL_PARTN_BITS, - .ioctl = nftl_ioctl, + .getgeo = nftl_getgeo, .readsect = nftl_readblock, #ifdef CONFIG_NFTL_RW .writesect = nftl_writeblock, @@ -747,7 +735,7 @@ int __init init_nftl(void) { - printk(KERN_INFO "NFTL driver: nftlcore.c $Revision: 1.92 $, nftlmount.c %s\n", nftlmountrev); + printk(KERN_INFO "NFTL driver: nftlcore.c $Revision: 1.94 $, nftlmount.c %s\n", nftlmountrev); return register_mtd_blktrans(&nftl_tr); } diff -Nru a/drivers/net/Kconfig b/drivers/net/Kconfig --- a/drivers/net/Kconfig Tue Jul 1 18:44:37 2003 +++ b/drivers/net/Kconfig Tue Jul 1 18:44:37 2003 @@ -492,16 +492,16 @@ help Say Y here to support the Ethernet subsystem on your GT96100 card. -config MIPS_AU1000_ENET +config MIPS_AU1X00_ENET bool "MIPS AU1000 Ethernet support" - depends on NET_ETHERNET && MIPS_AU1000 + depends on NET_ETHERNET && SOC_AU1X00 help - If you have an Alchemy Semi AU1000 ethernet controller - on an SGI MIPS system, say Y. Otherwise, say N. + If you have an Alchemy Semi AU1X00 based system + say Y. Otherwise, say N. config NET_SB1250_MAC tristate "SB1250 Ethernet support" - depends on NET_ETHERNET && SIBYTE_SB1250 + depends on NET_ETHERNET && SIBYTE_SB1xxx_SOC config SGI_IOC3_ETH bool "SGI IOC3 Ethernet" @@ -511,6 +511,10 @@ the Ethernet-HOWTO, available from . +config SGI_O2MACE_ETH + tristate "SGI O2 MACE Fast Ethernet support" + depends on NET_ETHERNET && SGI_IP32=y + config STNIC tristate "National DP83902AV support" depends on NET_ETHERNET && SUPERH @@ -1391,6 +1395,10 @@ . The module will be called cs89x. +config TC35815 + tristate "TOSHIBA TC35815 Ethernet support" + depends on NET_PCI && PCI + config DGRS tristate "Digi Intl. RightSwitch SE-X support" depends on NET_PCI && (PCI || EISA) @@ -1839,14 +1847,14 @@ The module will be called de620. config SGISEEQ - bool "SGI Seeq ethernet controller support" + tristate "SGI Seeq ethernet controller support" depends on NET_ETHERNET && SGI_IP22 help Say Y here if you have an Seeq based Ethernet network card. This is used in many Silicon Graphics machines. config DECLANCE - bool "DEC LANCE ethernet controller support" + tristate "DEC LANCE ethernet controller support" depends on NET_ETHERNET && DECSTATION help This driver is for the series of Ethernet controllers produced by diff -Nru a/drivers/net/Makefile b/drivers/net/Makefile --- a/drivers/net/Makefile Tue Jul 1 18:44:33 2003 +++ b/drivers/net/Makefile Tue Jul 1 18:44:33 2003 @@ -117,6 +117,7 @@ obj-$(CONFIG_SUN3LANCE) += sun3lance.o obj-$(CONFIG_DEFXX) += defxx.o obj-$(CONFIG_SGISEEQ) += sgiseeq.o +obj-$(CONFIG_SGI_O2MACE_ETH) += meth.o obj-$(CONFIG_AT1700) += at1700.o obj-$(CONFIG_FMV18X) += fmv18x.o obj-$(CONFIG_EL1) += 3c501.o @@ -156,7 +157,7 @@ obj-$(CONFIG_EQUALIZER) += eql.o obj-$(CONFIG_MIPS_JAZZ_SONIC) += jazzsonic.o obj-$(CONFIG_MIPS_GT96100ETH) += gt96100eth.o -obj-$(CONFIG_MIPS_AU1000_ENET) += au1000_eth.o +obj-$(CONFIG_MIPS_AU1X00_ENET) += au1000_eth.o obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o obj-$(CONFIG_BAGETLANCE) += bagetlance.o obj-$(CONFIG_DECLANCE) += declance.o diff -Nru a/drivers/net/Makefile.lib b/drivers/net/Makefile.lib --- a/drivers/net/Makefile.lib Tue Jul 1 18:44:37 2003 +++ b/drivers/net/Makefile.lib Tue Jul 1 18:44:37 2003 @@ -24,6 +24,7 @@ obj-$(CONFIG_PCMCIA_SMC91C92) += crc32.o obj-$(CONFIG_PCMCIA_XIRTULIP) += crc32.o obj-$(CONFIG_PCNET32) += crc32.o +obj-$(CONFIG_SGI_IOC3_ETH) += crc32.o obj-$(CONFIG_SIS900) += crc32.o obj-$(CONFIG_SMC9194) += crc32.o obj-$(CONFIG_ADAPTEC_STARFIRE) += crc32.o diff -Nru a/drivers/net/Space.c b/drivers/net/Space.c --- a/drivers/net/Space.c Tue Jul 1 18:44:32 2003 +++ b/drivers/net/Space.c Tue Jul 1 18:44:32 2003 @@ -82,7 +82,6 @@ extern int SK_init(struct net_device *); extern int seeq8005_probe(struct net_device *); extern int smc_init( struct net_device * ); -extern int sgiseeq_probe(struct net_device *); extern int atarilance_probe(struct net_device *); extern int sun3lance_probe(struct net_device *); extern int sun3_82586_probe(struct net_device *); @@ -343,14 +342,6 @@ {NULL, 0}, }; - -static struct devprobe sgi_probes[] __initdata = { -#ifdef CONFIG_SGISEEQ - {sgiseeq_probe, 0}, -#endif - {NULL, 0}, -}; - static struct devprobe mips_probes[] __initdata = { #ifdef CONFIG_MIPS_JAZZ_SONIC {sonic_probe, 0}, @@ -384,8 +375,6 @@ if (probe_list(dev, m68k_probes) == 0) return 0; if (probe_list(dev, mips_probes) == 0) - return 0; - if (probe_list(dev, sgi_probes) == 0) return 0; if (probe_list(dev, eisa_probes) == 0) return 0; diff -Nru a/drivers/net/acenic.c b/drivers/net/acenic.c --- a/drivers/net/acenic.c Tue Jul 1 18:44:34 2003 +++ b/drivers/net/acenic.c Tue Jul 1 18:44:34 2003 @@ -3026,9 +3026,6 @@ return 0; case ETHTOOL_SSET: - if(!capable(CAP_NET_ADMIN)) - return -EPERM; - link = readl(®s->GigLnkState); if (link & LNK_1000MB) speed = SPEED_1000; diff -Nru a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c --- a/drivers/net/arcnet/arc-rimi.c Tue Jul 1 18:44:31 2003 +++ b/drivers/net/arcnet/arc-rimi.c Tue Jul 1 18:44:31 2003 @@ -86,6 +86,8 @@ */ static int __init arcrimi_probe(struct net_device *dev) { + int retval; + BUGLVL(D_NORMAL) printk(VERSION); BUGLVL(D_NORMAL) printk("E-mail me if you actually test the RIM I driver, please!\n"); @@ -97,16 +99,27 @@ "must specify the shmem and irq!\n"); return -ENODEV; } - if (check_mem_region(dev->mem_start, BUFFER_SIZE)) { + /* + * Grab the memory region at mem_start for BUFFER_SIZE bytes. + * Later in arcrimi_found() the real size will be determined + * and this reserve will be released and the correct size + * will be taken. + */ + if (!request_mem_region(dev->mem_start, BUFFER_SIZE, "arcnet (90xx)")) { BUGMSG(D_NORMAL, "Card memory already allocated\n"); return -ENODEV; } if (dev->dev_addr[0] == 0) { + release_mem_region(dev->mem_start, BUFFER_SIZE); BUGMSG(D_NORMAL, "You need to specify your card's station " "ID!\n"); return -ENODEV; } - return arcrimi_found(dev); + retval = arcrimi_found(dev); + if (retval < 0) { + release_mem_region(dev->mem_start, BUFFER_SIZE); + } + return retval; } @@ -182,8 +195,19 @@ /* get and check the station ID from offset 1 in shmem */ dev->dev_addr[0] = readb(lp->mem_start + 1); - /* reserve the memory region - guaranteed to work by check_region */ - request_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1, "arcnet (90xx)"); + /* + * re-reserve the memory region - arcrimi_probe() alloced this reqion + * but didn't know the real size. Free that region and then re-get + * with the correct size. There is a VERY slim chance this could + * fail. + */ + release_mem_region(dev->mem_start, BUFFER_SIZE); + if (!request_mem_region(dev->mem_start, + dev->mem_end - dev->mem_start + 1, + "arcnet (90xx)")) { + BUGMSG(D_NORMAL, "Card memory already allocated\n"); + goto err_free_dev_priv; + } BUGMSG(D_NORMAL, "ARCnet RIM I: station %02Xh found at IRQ %d, " "ShMem %lXh (%ld*%d bytes).\n", diff -Nru a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c --- a/drivers/net/au1000_eth.c Tue Jul 1 18:44:35 2003 +++ b/drivers/net/au1000_eth.c Tue Jul 1 18:44:35 2003 @@ -1,13 +1,10 @@ /* - * * Alchemy Semi Au1000 ethernet driver * * Copyright 2001 MontaVista Software Inc. * Author: MontaVista Software, Inc. * ppopov@mvista.com or source@mvista.com * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -20,16 +17,8 @@ * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - * - * */ - -#ifndef __mips__ -#error This driver only works with MIPS architectures! -#endif - +#include #include #include @@ -125,7 +114,7 @@ }, au1100_iflist[NUM_INTERFACES] = { {AU1000_ETH0_BASE, AU1000_ETH0_IRQ}, - {NULL, NULL} + {0, 0} }; static char version[] __devinitdata = @@ -152,13 +141,6 @@ * code. */ -static char *phy_link[] = - {"unknown", - "10Base2", "10BaseT", - "AUI", - "100BaseT", "100BaseTX", "100BaseFX" - }; - int bcm_5201_init(struct net_device *dev, int phy_addr) { s16 data; @@ -184,6 +166,11 @@ data &= ~MII_FDX_LED; mdio_write(dev, phy_addr, MII_INT, data); + /* Enable TX LED instead of FDX */ + data = mdio_read(dev, phy_addr, MII_INT); + data &= ~MII_FDX_LED; + mdio_write(dev, phy_addr, MII_INT, data); + if (au1000_debug > 4) dump_mii(dev, phy_addr); return 0; } @@ -640,7 +627,7 @@ int prid; int base_addr, irq; - prid = read_32bit_cp0_register(CP0_PRID); + prid = read_c0_prid(); for (i=0; iname, ioaddr, irq); + dev->name, ioaddr, irq); aup = dev->priv; @@ -816,7 +804,7 @@ return 0; free_region: - release_region(ioaddr, MAC_IOSIZE); + release_region(PHYSADDR(ioaddr), MAC_IOSIZE); unregister_netdev(dev); if (aup->vaddr) dma_free((void *)aup->vaddr, @@ -1047,8 +1035,9 @@ ptxd = aup->tx_dma_ring[aup->tx_tail]; while (ptxd->buff_stat & TX_T_DONE) { - update_tx_stats(dev, ptxd->status, ptxd->len & 0x3ff); + update_tx_stats(dev, ptxd->status, aup->tx_len[aup->tx_tail] & 0x3ff); ptxd->buff_stat &= ~TX_T_DONE; + aup->tx_len[aup->tx_tail] = 0; ptxd->len = 0; au_sync(); @@ -1088,7 +1077,8 @@ return 1; } else if (buff_stat & TX_T_DONE) { - update_tx_stats(dev, ptxd->status, ptxd->len & 0x3ff); + update_tx_stats(dev, ptxd->status, aup->tx_len[aup->tx_head] & 0x3ff); + aup->tx_len[aup->tx_head] = 0; ptxd->len = 0; } @@ -1103,11 +1093,13 @@ for (i=skb->len; ivaddr)[i] = 0; } + aup->tx_len[aup->tx_head] = MAC_MIN_PKT_SIZE; ptxd->len = MAC_MIN_PKT_SIZE; } - else + else { + aup->tx_len[aup->tx_head] = skb->len; ptxd->len = skb->len; - + } ptxd->buff_stat = pDB->dma_addr | TX_DMA_ENABLE; au_sync(); dev_kfree_skb(skb); @@ -1244,6 +1236,8 @@ printk(KERN_ERR "%s: au1000_tx_timeout: dev=%p\n", dev->name, dev); reset_mac(dev); au1000_init(dev); + dev->trans_start = jiffies; + netif_wake_queue(dev); } static void set_rx_mode(struct net_device *dev) @@ -1269,7 +1263,8 @@ mc_filter[1] = mc_filter[0] = 0; for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; i++, mclist = mclist->next) { - set_bit(ether_crc(ETH_ALEN, mclist->dmi_addr)>>26, mc_filter); + set_bit(ether_crc_le(ETH_ALEN, mclist->dmi_addr)>>26, + mc_filter); } aup->mac->multi_hash_high = mc_filter[1]; aup->mac->multi_hash_low = mc_filter[0]; @@ -1285,18 +1280,21 @@ /* fixme */ switch(cmd) { - case SIOCGMIIPHY: /* Get the address of the PHY in use. */ + case SIOCGMIIPHY: /* Get the address of the PHY in use. */ data[0] = PHY_ADDRESS; + return 0; - case SIOCGMIIREG: /* Read the specified MII register. */ + case SIOCGMIIREG: /* Read the specified MII register. */ //data[3] = mdio_read(ioaddr, data[0], data[1]); return 0; - case SIOCSMIIREG: /* Write the specified MII register */ + case SIOCSMIIREG: /* Write the specified MII register */ if (!capable(CAP_NET_ADMIN)) return -EPERM; + //mdio_write(ioaddr, data[0], data[1], data[2]); return 0; + default: return -EOPNOTSUPP; } diff -Nru a/drivers/net/au1000_eth.h b/drivers/net/au1000_eth.h --- a/drivers/net/au1000_eth.h Tue Jul 1 18:44:34 2003 +++ b/drivers/net/au1000_eth.h Tue Jul 1 18:44:34 2003 @@ -1,13 +1,10 @@ /* - * * Alchemy Semi Au1000 ethernet driver include file * * Author: Pete Popov * * Copyright 2001 MontaVista Software Inc. * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -20,11 +17,8 @@ * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. - * - * ######################################################################## - * - * */ +#include #define NUM_INTERFACES 2 @@ -137,7 +131,7 @@ #define MII_AUX_100 0x0002 #define MII_AUX_F100 0x0004 #define MII_AUX_ANEG 0x0008 -#define MII_FDX_LED 0x8000 +#define MII_FDX_LED 0x8000 typedef struct mii_phy { struct mii_phy * next; @@ -203,6 +197,7 @@ db_dest_t db[NUM_RX_BUFFS+NUM_TX_BUFFS]; volatile rx_dma_t *rx_dma_ring[NUM_RX_DMA]; volatile tx_dma_t *tx_dma_ring[NUM_TX_DMA]; + int tx_len[NUM_TX_DMA]; db_dest_t *rx_db_inuse[NUM_RX_DMA]; db_dest_t *tx_db_inuse[NUM_TX_DMA]; u32 rx_head; diff -Nru a/drivers/net/declance.c b/drivers/net/declance.c --- a/drivers/net/declance.c Tue Jul 1 18:44:35 2003 +++ b/drivers/net/declance.c Tue Jul 1 18:44:35 2003 @@ -5,6 +5,8 @@ * * adopted from sunlance.c by Richard van den Berg * + * Copyright (C) 2002, 2003 Maciej W. Rozycki + * * additional sources: * - PMAD-AA TURBOchannel Ethernet Module Functional Specification, * Revision 1.2 @@ -16,76 +18,71 @@ * v0.002: Removed most sparc stuff, left only some module and dma stuff. * * v0.003: Enhanced base address calculation from proposals by - * Harald Koerfgen and Thomas Riemer. + * Harald Koerfgen and Thomas Riemer. * * v0.004: lance-regs is pointing at the right addresses, added prom - * check. First start of address mapping and DMA. + * check. First start of address mapping and DMA. * - * v0.005: started to play around with LANCE-DMA. This driver will not work - * for non IOASIC lances. HK + * v0.005: started to play around with LANCE-DMA. This driver will not + * work for non IOASIC lances. HK * - * v0.006: added pointer arrays to lance_private and setup routine for them - * in dec_lance_init. HK + * v0.006: added pointer arrays to lance_private and setup routine for + * them in dec_lance_init. HK * - * v0.007: Big shit. The LANCE seems to use a different DMA mechanism to access - * the init block. This looks like one (short) word at a time, but the smallest - * amount the IOASIC can transfer is a (long) word. So we have a 2-2 padding here. - * Changed lance_init_block accordingly. The 16-16 padding for the buffers - * seems to be correct. HK + * v0.007: Big shit. The LANCE seems to use a different DMA mechanism to + * access the init block. This looks like one (short) word at a + * time, but the smallest amount the IOASIC can transfer is a + * (long) word. So we have a 2-2 padding here. Changed + * lance_init_block accordingly. The 16-16 padding for the buffers + * seems to be correct. HK * - * v0.008 - mods to make PMAX_LANCE work. 01/09/1999 triemer - */ - -#undef DEBUG_DRIVER - -static char *version = -"declance.c: v0.008 by Linux Mips DECstation task force\n"; - -static char *lancestr = "LANCE"; - -/* - * card types + * v0.008: mods to make PMAX_LANCE work. 01/09/1999 triemer + * + * v0.009: Module support fixes, multiple interfaces support, various + * bits. macro */ -#define ASIC_LANCE 1 -#define PMAD_LANCE 2 -#define PMAX_LANCE 3 +#include +#include +#include +#include +#include #include #include +#include #include +#include +#include +#include +#include +#include #include -#include +#include #include +#include #include #include -#include -#include -#include +#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +static char version[] __devinitdata = +"declance.c: v0.009 by Linux MIPS DECstation task force\n"; + +MODULE_AUTHOR("Linux MIPS DECstation task force"); +MODULE_DESCRIPTION("DEC LANCE (DECstation onboard, PMAD-xx) driver"); +MODULE_LICENSE("GPL"); + +/* + * card types + */ +#define ASIC_LANCE 1 +#define PMAD_LANCE 2 +#define PMAX_LANCE 3 #ifndef CONFIG_TC unsigned long system_base; unsigned long dmaptr; #endif -static int type; #define LE_CSR0 0 #define LE_CSR1 1 @@ -160,8 +157,6 @@ #define TX_BUFF_SIZE PKT_BUF_SZ #undef TEST_HITS -#define DEBUG_DRIVER 1 - #define ZERO 0 /* The DS2000/3000 have a linear 64 KB buffer. @@ -179,26 +174,26 @@ */ struct lance_rx_desc { - unsigned short rmd0; /* low address of packet */ + unsigned short rmd0; /* low address of packet */ short gap0; unsigned char rmd1_hadr; /* high address of packet */ unsigned char rmd1_bits; /* descriptor bits */ short gap1; - short length; /* This length is 2s complement (negative)! - * Buffer length - */ + short length; /* 2s complement (negative!) + of buffer length */ short gap2; - unsigned short mblength; /* This is the actual number of bytes received */ + unsigned short mblength; /* actual number of bytes received */ short gap3; }; struct lance_tx_desc { - unsigned short tmd0; /* low address of packet */ + unsigned short tmd0; /* low address of packet */ short gap0; unsigned char tmd1_hadr; /* high address of packet */ unsigned char tmd1_bits; /* descriptor bits */ short gap1; - short length; /* Length is 2s complement (negative)! */ + short length; /* 2s complement (negative!) + of buffer length */ short gap2; unsigned short misc; short gap3; @@ -207,28 +202,26 @@ /* First part of the LANCE initialization block, described in databook. */ struct lance_init_block { - unsigned short mode; /* Pre-set mode (reg. 15) */ + unsigned short mode; /* pre-set mode (reg. 15) */ short gap0; - unsigned char phys_addr[12]; /* Physical ethernet address - * only 0, 1, 4, 5, 8, 9 are valid - * 2, 3, 6, 7, 10, 11 are gaps - */ - unsigned short filter[8]; /* Multicast filter. - * only 0, 2, 4, 6 are valid - * 1, 3, 5, 7 are gaps - */ + unsigned char phys_addr[12]; /* physical ethernet address + only 0, 1, 4, 5, 8, 9 are valid + 2, 3, 6, 7, 10, 11 are gaps */ + unsigned short filter[8]; /* multicast filter + only 0, 2, 4, 6 are valid + 1, 3, 5, 7 are gaps */ /* Receive and transmit ring base, along with extra bits. */ - unsigned short rx_ptr; /* receive descriptor addr */ + unsigned short rx_ptr; /* receive descriptor addr */ short gap1; - unsigned short rx_len; /* receive len and high addr */ + unsigned short rx_len; /* receive len and high addr */ short gap2; - unsigned short tx_ptr; /* transmit descriptor addr */ + unsigned short tx_ptr; /* transmit descriptor addr */ short gap3; - unsigned short tx_len; /* transmit len and high addr */ + unsigned short tx_len; /* transmit len and high addr */ short gap4; - char gap5[16]; + short gap5[8]; /* The buffer descriptors */ struct lance_rx_desc brx_ring[RX_RING_SIZE]; @@ -247,10 +240,12 @@ #define LANCE_ADDR(x) (PHYSADDR(x) >> 1) struct lance_private { - char *name; + struct net_device *next; + int type; + int slot; + int dma_irq; volatile struct lance_regs *ll; volatile struct lance_init_block *init_block; - volatile unsigned long *dma_ptr_reg; spinlock_t lock; @@ -261,8 +256,6 @@ unsigned short busmaster_regval; - struct net_device *dev; /* Backpointer */ - struct lance_private *next_module; struct timer_list multicast_timer; /* Pointers to the ring buffers as seen from the CPU */ @@ -292,16 +285,12 @@ int dec_lance_debug = 2; -/* - #ifdef MODULE - static struct lance_private *root_lance_dev = NULL; - #endif - */ +static struct net_device *root_lance_dev; static inline void writereg(volatile unsigned short *regptr, short value) { *regptr = value; - wbflush(); + iob(); } /* Load the CSR registers */ @@ -330,7 +319,7 @@ * Our specialized copy routines * */ -void cp_to_buf(void *to, const void *from, __kernel_size_t len) +void cp_to_buf(const int type, void *to, const void *from, int len) { unsigned short *tp, *fp, clen; unsigned char *rtp, *rfp; @@ -381,10 +370,10 @@ } } - wbflush(); + iob(); } -void cp_from_buf(void *to, unsigned char *from, int len) +void cp_from_buf(const int type, void *to, const void *from, int len) { unsigned short *tp, *fp, clen; unsigned char *rtp, *rfp; @@ -509,7 +498,7 @@ if (i < 3 && ZERO) printk("%d: 0x%8.8x(0x%8.8x)\n", i, leptr, (int) lp->rx_buf_ptr_cpu[i]); } - wbflush(); + iob(); } static int init_restart_lance(struct lance_private *lp) @@ -551,22 +540,21 @@ #ifdef TEST_HITS { - int i; + int i; - printk("["); - for (i = 0; i < RX_RING_SIZE; i++) { - if (i == lp->rx_new) - printk("%s", - ib->brx_ring[i].rmd1_bits & LE_R1_OWN ? "_" : "X"); - else - printk("%s", - ib->brx_ring[i].rmd1_bits & LE_R1_OWN ? "." : "1"); - } - printk("]"); + printk("["); + for (i = 0; i < RX_RING_SIZE; i++) { + if (i == lp->rx_new) + printk("%s", ib->brx_ring[i].rmd1_bits & + LE_R1_OWN ? "_" : "X"); + else + printk("%s", ib->brx_ring[i].rmd1_bits & + LE_R1_OWN ? "." : "1"); + } + printk("]"); } #endif - for (rd = &ib->brx_ring[lp->rx_new]; !((bits = rd->rmd1_bits) & LE_R1_OWN); rd = &ib->brx_ring[lp->rx_new]) { @@ -608,8 +596,8 @@ skb_reserve(skb, 2); /* 16 byte align */ skb_put(skb, len); /* make room */ - cp_from_buf(skb->data, - (char *) lp->rx_buf_ptr_cpu[lp->rx_new], + cp_from_buf(lp->type, skb->data, + (char *)lp->rx_buf_ptr_cpu[lp->rx_new], len); skb->protocol = eth_type_trans(skb, dev); @@ -709,6 +697,14 @@ spin_unlock(&lp->lock); } +static void lance_dma_merr_int(const int irq, void *dev_id, + struct pt_regs *regs) +{ + struct net_device *dev = (struct net_device *) dev_id; + + printk("%s: DMA error\n", dev->name); +} + static irqreturn_t lance_interrupt(const int irq, void *dev_id, struct pt_regs *regs) { @@ -741,19 +737,8 @@ lp->stats.rx_errors++; if (csr0 & LE_C0_MERR) { - volatile unsigned long int_stat = *(unsigned long *) (system_base + IOCTL + SIR); - printk("%s: Memory error, status %04x\n", dev->name, csr0); - if (int_stat & LANCE_DMA_MEMRDERR) { - printk("%s: DMA error\n", dev->name); - int_stat |= LANCE_DMA_MEMRDERR; - /* - * re-enable LANCE DMA - */ - *(unsigned long *) (system_base + IOCTL + SSR) |= (1 << 16); - wbflush(); - } writereg(&ll->rdp, LE_C0_STOP); lance_init_ring(dev); @@ -800,10 +785,30 @@ netif_start_queue(dev); /* Associate IRQ with lance_interrupt */ - if (request_irq(dev->irq, &lance_interrupt, 0, lp->name, dev)) { - printk("Lance: Can't get irq %d\n", dev->irq); + if (request_irq(dev->irq, &lance_interrupt, 0, "lance", dev)) { + printk("lance: Can't get IRQ %d\n", dev->irq); return -EAGAIN; } + if (lp->dma_irq >= 0) { + unsigned long flags; + + if (request_irq(lp->dma_irq, &lance_dma_merr_int, 0, + "lance error", dev)) { + free_irq(dev->irq, dev); + printk("lance: Can't get DMA IRQ %d\n", lp->dma_irq); + return -EAGAIN; + } + + spin_lock_irqsave(&ioasic_ssr_lock, flags); + + fast_mb(); + /* Enable I/O ASIC LANCE DMA. */ + ioasic_write(IO_REG_SSR, + ioasic_read(IO_REG_SSR) | IO_SSR_LANCE_DMA_EN); + + fast_mb(); + spin_unlock_irqrestore(&ioasic_ssr_lock, flags); + } status = init_restart_lance(lp); @@ -827,7 +832,22 @@ writereg(&ll->rap, LE_CSR0); writereg(&ll->rdp, LE_C0_STOP); - free_irq(dev->irq, (void *) dev); + if (lp->dma_irq >= 0) { + unsigned long flags; + + spin_lock_irqsave(&ioasic_ssr_lock, flags); + + fast_mb(); + /* Disable I/O ASIC LANCE DMA. */ + ioasic_write(IO_REG_SSR, + ioasic_read(IO_REG_SSR) & ~IO_SSR_LANCE_DMA_EN); + + fast_iob(); + spin_unlock_irqrestore(&ioasic_ssr_lock, flags); + + free_irq(lp->dma_irq, dev); + } + free_irq(dev->irq, dev); /* MOD_DEC_USE_COUNT; */ @@ -886,7 +906,8 @@ ib->btx_ring[entry].length = (-len); ib->btx_ring[entry].misc = 0; - cp_to_buf((char *) lp->tx_buf_ptr_cpu[entry], skb->data, skblen); + cp_to_buf(lp->type, (char *)lp->tx_buf_ptr_cpu[entry], skb->data, + skblen); /* Clear the slack of the packet, do I need this? */ /* For a firewall it's a good idea - AC */ @@ -926,7 +947,7 @@ volatile u16 *mcast_table = (u16 *) & ib->filter; struct dev_mc_list *dmi = dev->mc_list; char *addrs; - int i, j, bit, byte; + int i; u32 crc; /* set all multicast bits */ @@ -952,7 +973,7 @@ if (!(*addrs & 1)) continue; - crc = ether_crc_le(6, addrs); + crc = ether_crc_le(ETH_ALEN, addrs); crc = crc >> 26; mcast_table[2 * (crc >> 4)] |= 1 << (crc & 0xf); } @@ -1001,7 +1022,7 @@ lance_set_multicast(dev); } -static int __init dec_lance_init(struct net_device *dev, const int type) +static int __init dec_lance_init(const int type, const int slot) { static unsigned version_printed; struct net_device *dev; @@ -1013,25 +1034,29 @@ #ifndef CONFIG_TC system_base = KN01_LANCE_BASE; -#else - int slot; #endif if (dec_lance_debug && version_printed++ == 0) printk(version); - dev = init_etherdev(0, sizeof(struct lance_private)); + dev = init_etherdev(NULL, sizeof(struct lance_private)); if (!dev) return -ENOMEM; + SET_MODULE_OWNER(dev); - /* init_etherdev ensures the data structures used by the LANCE are aligned. */ + /* + * init_etherdev ensures the data structures used by the LANCE + * are aligned. + */ lp = (struct lance_private *) dev->priv; spin_lock_init(&lp->lock); + lp->type = type; + lp->slot = slot; switch (type) { #ifdef CONFIG_TC case ASIC_LANCE: - dev->base_addr = system_base + LANCE; + dev->base_addr = system_base + IOASIC_LANCE; /* buffer space for the on-board LANCE shared memory */ /* @@ -1039,78 +1064,101 @@ */ dev->mem_start = KSEG1ADDR(0x00020000); dev->mem_end = dev->mem_start + 0x00020000; - dev->irq = ETHER; - esar_base = system_base + ESAR; - + dev->irq = dec_interrupt[DEC_IRQ_LANCE]; + esar_base = system_base + IOASIC_ESAR; + /* Workaround crash with booting KN04 2.1k from Disk */ - memset(dev->mem_start, 0, dev->mem_end - dev->mem_start); + memset((void *)dev->mem_start, 0, + dev->mem_end - dev->mem_start); /* * setup the pointer arrays, this sucks [tm] :-( */ for (i = 0; i < RX_RING_SIZE; i++) { - lp->rx_buf_ptr_cpu[i] = (char *) (dev->mem_start + BUF_OFFSET_CPU - + 2 * i * RX_BUFF_SIZE); - lp->rx_buf_ptr_lnc[i] = (char *) (BUF_OFFSET_LNC - + i * RX_BUFF_SIZE); + lp->rx_buf_ptr_cpu[i] = + (char *)(dev->mem_start + BUF_OFFSET_CPU + + 2 * i * RX_BUFF_SIZE); + lp->rx_buf_ptr_lnc[i] = + (char *)(BUF_OFFSET_LNC + i * RX_BUFF_SIZE); } for (i = 0; i < TX_RING_SIZE; i++) { - lp->tx_buf_ptr_cpu[i] = (char *) (dev->mem_start + BUF_OFFSET_CPU - + 2 * RX_RING_SIZE * RX_BUFF_SIZE - + 2 * i * TX_BUFF_SIZE); - lp->tx_buf_ptr_lnc[i] = (char *) (BUF_OFFSET_LNC - + RX_RING_SIZE * RX_BUFF_SIZE - + i * TX_BUFF_SIZE); + lp->tx_buf_ptr_cpu[i] = + (char *)(dev->mem_start + BUF_OFFSET_CPU + + 2 * RX_RING_SIZE * RX_BUFF_SIZE + + 2 * i * TX_BUFF_SIZE); + lp->tx_buf_ptr_lnc[i] = + (char *)(BUF_OFFSET_LNC + + RX_RING_SIZE * RX_BUFF_SIZE + + i * TX_BUFF_SIZE); } - /* - * setup and enable IOASIC LANCE DMA - */ - lp->dma_ptr_reg = (unsigned long *) (system_base + IOCTL + LANCE_DMA_P); - *(lp->dma_ptr_reg) = PHYSADDR(dev->mem_start) << 3; - *(unsigned long *) (system_base + IOCTL + SSR) |= (1 << 16); - wbflush(); + /* Setup I/O ASIC LANCE DMA. */ + lp->dma_irq = dec_interrupt[DEC_IRQ_LANCE_MERR]; + ioasic_write(IO_REG_LANCE_DMA_P, + PHYSADDR(dev->mem_start) << 3); break; + case PMAD_LANCE: - slot = search_tc_card("PMAD-AA"); claim_tc_card(slot); dev->mem_start = get_tc_base_addr(slot); dev->base_addr = dev->mem_start + 0x100000; dev->irq = get_tc_irq_nr(slot); esar_base = dev->mem_start + 0x1c0002; + lp->dma_irq = -1; + + for (i = 0; i < RX_RING_SIZE; i++) { + lp->rx_buf_ptr_cpu[i] = + (char *)(dev->mem_start + BUF_OFFSET_CPU + + i * RX_BUFF_SIZE); + lp->rx_buf_ptr_lnc[i] = + (char *)(BUF_OFFSET_LNC + i * RX_BUFF_SIZE); + } + for (i = 0; i < TX_RING_SIZE; i++) { + lp->tx_buf_ptr_cpu[i] = + (char *)(dev->mem_start + BUF_OFFSET_CPU + + RX_RING_SIZE * RX_BUFF_SIZE + + i * TX_BUFF_SIZE); + lp->tx_buf_ptr_lnc[i] = + (char *)(BUF_OFFSET_LNC + + RX_RING_SIZE * RX_BUFF_SIZE + + i * TX_BUFF_SIZE); + } + break; #endif + case PMAX_LANCE: - dev->irq = ETHER; + dev->irq = dec_interrupt[DEC_IRQ_LANCE]; dev->base_addr = KN01_LANCE_BASE; dev->mem_start = KN01_LANCE_BASE + 0x01000000; esar_base = KN01_RTC_BASE + 1; + lp->dma_irq = -1; + /* * setup the pointer arrays, this sucks [tm] :-( */ for (i = 0; i < RX_RING_SIZE; i++) { lp->rx_buf_ptr_cpu[i] = - (char *) (dev->mem_start + BUF_OFFSET_CPU - + 2 * i * RX_BUFF_SIZE); - + (char *)(dev->mem_start + BUF_OFFSET_CPU + + 2 * i * RX_BUFF_SIZE); lp->rx_buf_ptr_lnc[i] = - (char *) (BUF_OFFSET_LNC - + i * RX_BUFF_SIZE); - + (char *)(BUF_OFFSET_LNC + i * RX_BUFF_SIZE); } for (i = 0; i < TX_RING_SIZE; i++) { lp->tx_buf_ptr_cpu[i] = - (char *) (dev->mem_start + BUF_OFFSET_CPU - + 2 * RX_RING_SIZE * RX_BUFF_SIZE - + 2 * i * TX_BUFF_SIZE); - lp->tx_buf_ptr_lnc[i] = (char *) (BUF_OFFSET_LNC - + RX_RING_SIZE * RX_BUFF_SIZE - + i * TX_BUFF_SIZE); - + (char *)(dev->mem_start + BUF_OFFSET_CPU + + 2 * RX_RING_SIZE * RX_BUFF_SIZE + + 2 * i * TX_BUFF_SIZE); + lp->tx_buf_ptr_lnc[i] = + (char *)(BUF_OFFSET_LNC + + RX_RING_SIZE * RX_BUFF_SIZE + + i * TX_BUFF_SIZE); } + break; + default: printk("declance_init called with unknown type\n"); ret = -ENODEV; @@ -1140,6 +1188,9 @@ } } + lp->next = root_lance_dev; + root_lance_dev = dev; + /* Copy the ethernet address to the device structure, later to the * lance initialization block so the lance gets it every time it's * (re)initialized. @@ -1162,7 +1213,6 @@ printk(" irq = %d\n", dev->irq); - lp->dev = dev; dev->open = &lance_open; dev->stop = &lance_close; dev->hard_start_xmit = &lance_start_xmit; @@ -1174,8 +1224,6 @@ /* lp->ll is the location of the registers for lance card */ lp->ll = ll; - lp->name = lancestr; - /* busmaster_regval (CSR3) should be zero according to the PMAD-AA * specification. */ @@ -1183,8 +1231,6 @@ dev->dma = 0; - ether_setup(dev); - /* We cannot sleep if the chip is busy during a * multicast list update event, because such events * can occur from interrupts (ex. IPv6). So we @@ -1194,11 +1240,6 @@ lp->multicast_timer.data = (unsigned long) dev; lp->multicast_timer.function = &lance_set_multicast_retry; -#ifdef MODULE - dev->ifindex = dev_new_index(); - lp->next_module = root_lance_dev; - root_lance_dev = lp; -#endif return 0; err_out: @@ -1211,61 +1252,51 @@ /* Find all the lance cards on the system and initialize them */ static int __init dec_lance_probe(void) { - struct net_device *dev = NULL; - static int called; - -#ifdef MODULE - root_lance_dev = NULL; -#endif - + int count = 0; + /* Scan slots for PMAD-AA cards first. */ #ifdef CONFIG_TC - int slot = -1; - if (TURBOCHANNEL) { - if (IOASIC && !called) { - called = 1; - type = ASIC_LANCE; - } else { - if ((slot = search_tc_card("PMAD-AA")) >= 0) { - type = PMAD_LANCE; - } else { - return -ENODEV; - } - } - } else { - if (!called) { - called = 1; - type = PMAX_LANCE; - } else { - return -ENODEV; + int slot; + + while ((slot = search_tc_card("PMAD-AA")) >= 0) { + if (dec_lance_init(PMAD_LANCE, slot) < 0) + break; + count++; } } -#else - if (!called && !TURBOCHANNEL) { - called = 1; - type = PMAX_LANCE; - } else { - return -ENODEV; - } #endif - return dec_lance_init(dev, type); + /* Then handle onboard devices. */ + if (dec_interrupt[DEC_IRQ_LANCE] >= 0) { + if (dec_interrupt[DEC_IRQ_LANCE_MERR] >= 0) { +#ifdef CONFIG_TC + if (dec_lance_init(ASIC_LANCE, -1) >= 0) + count++; +#endif + } else if (!TURBOCHANNEL) { + if (dec_lance_init(PMAX_LANCE, -1) >= 0) + count++; + } + } + + return (count > 0) ? 0 : -ENODEV; } static void __exit dec_lance_cleanup(void) { -#ifdef MODULE - struct lance_private *lp; - - while (root_lance_dev) { - lp = root_lance_dev->next_module; + while (root_lance_dev) { + struct net_device *dev = root_lance_dev; + struct lance_private *lp = (struct lance_private *)dev->priv; - unregister_netdev(root_lance_dev->dev); - kfree(root_lance_dev->dev); - root_lance_dev = lp; - } -#endif /* MODULE */ +#ifdef CONFIG_TC + if (lp->slot >= 0) + release_tc_card(lp->slot); +#endif + root_lance_dev = lp->next; + unregister_netdev(dev); + kfree(dev); + } } module_init(dec_lance_probe); diff -Nru a/drivers/net/e100/e100_main.c b/drivers/net/e100/e100_main.c --- a/drivers/net/e100/e100_main.c Tue Jul 1 18:44:35 2003 +++ b/drivers/net/e100/e100_main.c Tue Jul 1 18:44:35 2003 @@ -2068,13 +2068,14 @@ skb->ip_summed = CHECKSUM_NONE; } + bdp->drv_stats.net_stats.rx_bytes += skb->len; + if(bdp->vlgrp && (rfd_status & CB_STATUS_VLAN)) { vlan_hwaccel_rx(skb, bdp->vlgrp, be16_to_cpu(rfd->vlanid)); } else { netif_rx(skb); } dev->last_rx = jiffies; - bdp->drv_stats.net_stats.rx_bytes += skb->len; rfd_cnt++; } /* end of rfd loop */ @@ -3424,10 +3425,6 @@ int ethtool_new_speed_duplex; struct ethtool_cmd ecmd; - if (!capable(CAP_NET_ADMIN)) { - return -EPERM; - } - bdp = dev->priv; if (copy_from_user(&ecmd, ifr->ifr_data, sizeof (ecmd))) { return -EFAULT; @@ -3545,8 +3542,6 @@ void *addr = ifr->ifr_data; u16 mdi_reg; - if (!capable(CAP_NET_ADMIN)) - return -EPERM; bdp = dev->priv; if(copy_from_user(®s, addr, sizeof(regs))) @@ -3574,9 +3569,6 @@ { struct e100_private *bdp; - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - bdp = dev->priv; if ((bdp->speed_duplex_caps & SUPPORTED_Autoneg) && @@ -3632,9 +3624,6 @@ void *ptr; u8 *eeprom_data_bytes = (u8 *)eeprom_data; - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - bdp = dev->priv; if (copy_from_user(&ecmd, ifr->ifr_data, sizeof (ecmd))) @@ -3911,9 +3900,6 @@ struct e100_private *bdp; struct ethtool_wolinfo wolinfo; int res = 0; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; bdp = dev->priv; diff -Nru a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c --- a/drivers/net/e1000/e1000_ethtool.c Tue Jul 1 18:44:34 2003 +++ b/drivers/net/e1000/e1000_ethtool.c Tue Jul 1 18:44:34 2003 @@ -1289,8 +1289,6 @@ } case ETHTOOL_SSET: { struct ethtool_cmd ecmd; - if(!capable(CAP_NET_ADMIN)) - return -EPERM; if(copy_from_user(&ecmd, addr, sizeof(ecmd))) return -EFAULT; return e1000_ethtool_sset(adapter, &ecmd); @@ -1363,8 +1361,6 @@ return 0; } case ETHTOOL_NWAY_RST: { - if(!capable(CAP_NET_ADMIN)) - return -EPERM; if(netif_running(netdev)) { e1000_down(adapter); e1000_up(adapter); @@ -1393,8 +1389,6 @@ } case ETHTOOL_SWOL: { struct ethtool_wolinfo wol; - if(!capable(CAP_NET_ADMIN)) - return -EPERM; if(copy_from_user(&wol, addr, sizeof(wol)) != 0) return -EFAULT; return e1000_ethtool_swol(adapter, &wol); @@ -1436,9 +1430,6 @@ case ETHTOOL_SEEPROM: { struct ethtool_eeprom eeprom; - if(!capable(CAP_NET_ADMIN)) - return -EPERM; - if(copy_from_user(&eeprom, addr, sizeof(eeprom))) return -EFAULT; @@ -1469,9 +1460,6 @@ uint64_t data[E1000_TEST_LEN]; } test = { {ETHTOOL_TEST} }; int err; - - if(!capable(CAP_NET_ADMIN)) - return -EPERM; if(copy_from_user(&test.eth_test, addr, sizeof(test.eth_test))) return -EFAULT; diff -Nru a/drivers/net/eepro100.c b/drivers/net/eepro100.c --- a/drivers/net/eepro100.c Tue Jul 1 18:44:36 2003 +++ b/drivers/net/eepro100.c Tue Jul 1 18:44:36 2003 @@ -116,6 +116,7 @@ #include #include +#include #include #include #include @@ -670,7 +671,7 @@ if (tx_ring_space == NULL) return -1; - dev = init_etherdev(NULL, sizeof(struct speedo_private)); + dev = alloc_etherdev(sizeof(struct speedo_private)); if (dev == NULL) { printk(KERN_ERR "eepro100: Could not allocate ethernet device.\n"); pci_free_consistent(pdev, size, tx_ring_space, tx_ring_dma); @@ -687,6 +688,10 @@ else option = 0; + rtnl_lock(); + if (dev_alloc_name(dev, dev->name) < 0) + goto err_free_unlock; + /* Read the station address EEPROM before doing the reset. Nominally his should even be done before accepting the device, but then we wouldn't have a device name with which to report the error. @@ -881,7 +886,16 @@ dev->set_multicast_list = &set_rx_mode; dev->do_ioctl = &speedo_ioctl; + if (register_netdevice(dev)) + goto err_free_unlock; + rtnl_unlock(); + return 0; + + err_free_unlock: + rtnl_unlock(); + kfree(dev); + return -1; } static void do_slow_command(struct net_device *dev, int cmd) diff -Nru a/drivers/net/gt96100eth.c b/drivers/net/gt96100eth.c --- a/drivers/net/gt96100eth.c Tue Jul 1 18:44:36 2003 +++ b/drivers/net/gt96100eth.c Tue Jul 1 18:44:37 2003 @@ -3,8 +3,6 @@ * Author: MontaVista Software, Inc. * stevel@mvista.com or source@mvista.com * - * ######################################################################## - * * This program is free software; you can distribute it and/or modify it * under the terms of the GNU General Public License (Version 2) as * published by the Free Software Foundation. @@ -18,8 +16,6 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. * - * ######################################################################## - * * Ethernet driver for the MIPS GT96100 Advanced Communication Controller. * * Revision history @@ -32,18 +28,7 @@ * gt96100_cleanup_module(), and other general code cleanups * . */ - -#ifndef __OPTIMIZE__ -#error You must compile this file with the correct options! -#error See the last lines of the source file. -#error You must compile this driver with "-O". -#endif - -#ifndef __mips__ -#error This driver only works with MIPS architectures! -#endif - - +#include #include #include #include diff -Nru a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c --- a/drivers/net/ioc3-eth.c Tue Jul 1 18:44:31 2003 +++ b/drivers/net/ioc3-eth.c Tue Jul 1 18:44:31 2003 @@ -5,7 +5,7 @@ * * Driver for SGI's IOC3 based Ethernet cards as found in the PCI card. * - * Copyright (C) 1999, 2000, 2001 Ralf Baechle + * Copyright (C) 1999, 2000, 2001, 2003 Ralf Baechle * Copyright (C) 1995, 1999, 2000, 2001 by Silicon Graphics, Inc. * * References: @@ -36,7 +36,7 @@ #include #include -#ifdef CONFIG_SERIAL +#ifdef CONFIG_SERIAL_8250 #include #include #define IOC3_BAUD (22000000 / (3*16)) @@ -377,82 +377,6 @@ ip->dev->dev_addr[i - 2] = nic[i]; } -#if defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_SGI_SN2) -/* - * Get the ether-address on SN1 nodes - */ -static void ioc3_get_eaddr_sn(struct ioc3_private *ip) -{ - int ibrick_mac_addr_get(nasid_t, char *); - struct ioc3 *ioc3 = ip->regs; - nasid_t nasid_of_ioc3; - char io7eaddr[20]; - long mac; - int err_val; - - /* - * err_val = ibrick_mac_addr_get(get_nasid(), io7eaddr ); - * - * BAD!! The above call uses get_nasid() and assumes that - * the ioc3 pointed to by struct ioc3 is hooked up to the - * cbrick that we're running on. The proper way to make this call - * is to figure out which nasid the ioc3 is connected to - * and use that to call ibrick_mac_addr_get. Below is - * a hack to do just that. - */ - - /* - * Get the nasid of the ioc3 from the ioc3's base addr. - * FIXME: the 8 at the end assumes we're in memory mode, - * not node mode (for that, we'd change it to a 9). - * Is there a call to extract this info from a physical - * addr somewhere in an sn header file already? If so, - * we should probably use that, or restructure this routine - * to use pci_dev and generic numa nodeid getting stuff. - */ - nasid_of_ioc3 = (((unsigned long)ioc3 >> 33) & ~(-1 << 8)); - err_val = ibrick_mac_addr_get(nasid_of_ioc3, io7eaddr ); - - - if (err_val) { - /* Couldn't read the eeprom; try OSLoadOptions. */ - printk("WARNING: ibrick_mac_addr_get failed: %d\n", err_val); - - /* this is where we hardwire the mac address - * 1st ibrick had 08:00:69:11:34:75 - * 2nd ibrick had 08:00:69:11:35:35 - * - * Eagan Machines: - * mankato1 08:00:69:11:BE:95 - * warroad 08:00:69:11:bd:60 - * duron 08:00:69:11:34:60 - * - * an easy way to get the mac address is to hook - * up an ip35, then from L1 do 'cti serial' - * and then look for MAC line XXX THIS DOESN"T QUITE WORK!! - */ - printk("ioc3_get_eaddr: setting ethernet address to:\n -----> "); - ip->dev->dev_addr[0] = 0x8; - ip->dev->dev_addr[1] = 0x0; - ip->dev->dev_addr[2] = 0x69; - ip->dev->dev_addr[3] = 0x11; - ip->dev->dev_addr[4] = 0x34; - ip->dev->dev_addr[5] = 0x60; - } - else { - long simple_strtol(const char *,char **,unsigned int); - - mac = simple_strtol(io7eaddr, (char **)0, 16); - ip->dev->dev_addr[0] = (mac >> 40) & 0xff; - ip->dev->dev_addr[1] = (mac >> 32) & 0xff; - ip->dev->dev_addr[2] = (mac >> 24) & 0xff; - ip->dev->dev_addr[3] = (mac >> 16) & 0xff; - ip->dev->dev_addr[4] = (mac >> 8) & 0xff; - ip->dev->dev_addr[5] = mac & 0xff; - } -} -#endif - /* * Ok, this is hosed by design. It's necessary to know what machine the * NIC is in in order to know how to read the NIC address. We also have @@ -460,30 +384,15 @@ */ static void ioc3_get_eaddr(struct ioc3_private *ip) { - void (*do_get_eaddr)(struct ioc3_private *ip) = NULL; int i; - /* - * We should also use this code for PCI cards, no matter what host - * machine but how to know that we're a PCI card? - */ -#ifdef CONFIG_SGI_IP27 - do_get_eaddr = ioc3_get_eaddr_nic; -#endif -#if defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_SGI_SN2) - do_get_eaddr = ioc3_get_eaddr_sn; -#endif - if (!do_get_eaddr) { - printk(KERN_ERR "Don't know how to read MAC address of this " - "IOC3 NIC\n"); - return; - } + ioc3_get_eaddr_nic(ip); printk("Ethernet address is "); for (i = 0; i < 6; i++) { printk("%02x", ip->dev->dev_addr[i]); - if (i < 7) + if (i < 5) printk(":"); } printk(".\n"); @@ -588,7 +497,7 @@ ip->stats.rx_frame_errors++; next: ip->rx_skbs[n_entry] = new_skb; - rxr[n_entry] = cpu_to_be32((0xa5UL << 56) | + rxr[n_entry] = cpu_to_be64((0xa5UL << 56) | ((unsigned long) rxb & TO_PHYS_MASK)); rxb->w0 = 0; /* Clear valid flag */ n_entry = (n_entry + 1) & 511; /* Update erpir */ @@ -1550,7 +1459,7 @@ } ip->regs = ioc3; -#ifdef CONFIG_SERIAL +#ifdef CONFIG_SERIAL_8250 ioc3_serial_probe(pdev, ioc3); #endif @@ -1613,6 +1522,7 @@ struct ioc3_private *ip = dev->priv; struct ioc3 *ioc3 = ip->regs; + unregister_netdev(dev); iounmap(ioc3); pci_release_regions(pdev); kfree(dev); @@ -1844,9 +1754,6 @@ return -EFAULT; return 0; } else if (ecmd.cmd == ETHTOOL_SSET) { - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - /* Verify the settings we care about. */ if (ecmd.autoneg != AUTONEG_ENABLE && ecmd.autoneg != AUTONEG_DISABLE) diff -Nru a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig --- a/drivers/net/irda/Kconfig Tue Jul 1 18:44:36 2003 +++ b/drivers/net/irda/Kconfig Tue Jul 1 18:44:36 2003 @@ -289,6 +289,10 @@ . The module will be called donauboe. +config AU1000_FIR + tristate "Alchemy Au1000 SIR/FIR" + depends on MIPS_AU1000 && IRDA + config SMC_IRCC_OLD tristate "SMC IrCC (old driver) (EXPERIMENTAL)" depends on EXPERIMENTAL && IRDA diff -Nru a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile --- a/drivers/net/irda/Makefile Tue Jul 1 18:44:34 2003 +++ b/drivers/net/irda/Makefile Tue Jul 1 18:44:34 2003 @@ -28,6 +28,7 @@ obj-$(CONFIG_OLD_BELKIN_DONGLE) += old_belkin.o obj-$(CONFIG_EP7211_IR) += ep7211_ir.o obj-$(CONFIG_MCP2120_DONGLE) += mcp2120.o +obj-$(CONFIG_AU1000_FIR) += au1k_ir.o obj-$(CONFIG_ACT200L_DONGLE) += act200l.o obj-$(CONFIG_MA600_DONGLE) += ma600.o # New SIR drivers diff -Nru a/drivers/net/irda/au1k_ir.c b/drivers/net/irda/au1k_ir.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/net/irda/au1k_ir.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,868 @@ +/* + * + * Alchemy Semi Au1000 IrDA driver + * + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * ######################################################################## + * + * + */ + +#ifndef __mips__ +#error This driver only works with MIPS architectures! +#endif + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "net/irda/au1000_ircc.h" + +static int au1k_irda_net_init(struct net_device *); +static int au1k_irda_start(struct net_device *); +static int au1k_irda_stop(struct net_device *dev); +static int au1k_irda_hard_xmit(struct sk_buff *, struct net_device *); +static int au1k_irda_rx(struct net_device *); +static void au1k_irda_interrupt(int, void *, struct pt_regs *); +static void au1k_tx_timeout(struct net_device *); +static struct net_device_stats *au1k_irda_stats(struct net_device *); +static int au1k_irda_ioctl(struct net_device *, struct ifreq *, int); +static int au1k_irda_set_speed(struct net_device *dev, int speed); + +static void *dma_alloc(size_t, dma_addr_t *); +static void dma_free(void *, size_t); + +static int qos_mtt_bits = 0x07; /* 1 ms or more */ +static struct net_device *ir_devs[NUM_IR_IFF]; +static char version[] __devinitdata = + "au1k_ircc:1.0 ppopov@mvista.com\n"; + +#define RUN_AT(x) (jiffies + (x)) + +static spinlock_t ir_lock = SPIN_LOCK_UNLOCKED; + +/* + * IrDA peripheral bug. You have to read the register + * twice to get the right value. + */ +u32 read_ir_reg(u32 addr) +{ + readl(addr); + return readl(addr); +} + + +/* + * Buffer allocation/deallocation routines. The buffer descriptor returned + * has the virtual and dma address of a buffer suitable for + * both, receive and transmit operations. + */ +static db_dest_t *GetFreeDB(struct au1k_private *aup) +{ + db_dest_t *pDB; + pDB = aup->pDBfree; + + if (pDB) { + aup->pDBfree = pDB->pnext; + } + return pDB; +} + +static void ReleaseDB(struct au1k_private *aup, db_dest_t *pDB) +{ + db_dest_t *pDBfree = aup->pDBfree; + if (pDBfree) + pDBfree->pnext = pDB; + aup->pDBfree = pDB; +} + + +/* + DMA memory allocation, derived from pci_alloc_consistent. + However, the Au1000 data cache is coherent (when programmed + so), therefore we return KSEG0 address, not KSEG1. +*/ +static void *dma_alloc(size_t size, dma_addr_t * dma_handle) +{ + void *ret; + int gfp = GFP_ATOMIC | GFP_DMA; + + ret = (void *) __get_free_pages(gfp, get_order(size)); + + if (ret != NULL) { + memset(ret, 0, size); + *dma_handle = virt_to_bus(ret); + ret = KSEG0ADDR(ret); + } + return ret; +} + + +static void dma_free(void *vaddr, size_t size) +{ + vaddr = KSEG0ADDR(vaddr); + free_pages((unsigned long) vaddr, get_order(size)); +} + + +static void +setup_hw_rings(struct au1k_private *aup, u32 rx_base, u32 tx_base) +{ + int i; + for (i=0; irx_ring[i] = (volatile ring_dest_t *) + (rx_base + sizeof(ring_dest_t)*i); + } + for (i=0; itx_ring[i] = (volatile ring_dest_t *) + (tx_base + sizeof(ring_dest_t)*i); + } +} + + +/* + * Device has already been stopped at this point. + */ +static void au1k_irda_net_uninit(struct net_device *dev) +{ + dev->hard_start_xmit = NULL; + dev->open = NULL; + dev->stop = NULL; + dev->do_ioctl = NULL; + dev->get_stats = NULL; + dev->priv = NULL; +} + + +static int au1k_irda_init(void) +{ + static unsigned version_printed = 0; + struct net_device *dev; + int err; + + if (version_printed++ == 0) printk(version); + + rtnl_lock(); + dev = dev_alloc("irda%d", &err); + if (dev) { + dev->irq = AU1000_IRDA_RX_INT; /* TX has its own interrupt */ + dev->init = au1k_irda_net_init; + dev->uninit = au1k_irda_net_uninit; + err = register_netdevice(dev); + + if (err) + kfree(dev); + else + ir_devs[0] = dev; + printk(KERN_INFO "IrDA: Registered device %s\n", dev->name); + } + rtnl_unlock(); + return err; +} + +static int au1k_irda_init_iobuf(iobuff_t *io, int size) +{ + io->head = kmalloc(size, GFP_KERNEL); + if (io->head != NULL) { + io->truesize = size; + io->in_frame = FALSE; + io->state = OUTSIDE_FRAME; + io->data = io->head; + } + return io->head ? 0 : -ENOMEM; +} + +static int au1k_irda_net_init(struct net_device *dev) +{ + struct au1k_private *aup = NULL; + int i, retval = 0, err; + db_dest_t *pDB, *pDBfree; + unsigned long temp; + + dev->priv = kmalloc(sizeof(struct au1k_private), GFP_KERNEL); + if (dev->priv == NULL) { + retval = -ENOMEM; + goto out; + } + memset(dev->priv, 0, sizeof(struct au1k_private)); + aup = dev->priv; + + err = au1k_irda_init_iobuf(&aup->rx_buff, 14384); + if (err) + goto out; + + dev->open = au1k_irda_start; + dev->hard_start_xmit = au1k_irda_hard_xmit; + dev->stop = au1k_irda_stop; + dev->get_stats = au1k_irda_stats; + dev->do_ioctl = au1k_irda_ioctl; + dev->tx_timeout = au1k_tx_timeout; + + irda_device_setup(dev); + irda_init_max_qos_capabilies(&aup->qos); + + /* The only value we must override it the baudrate */ + aup->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600| + IR_115200|IR_576000 |(IR_4000000 << 8); + + aup->qos.min_turn_time.bits = qos_mtt_bits; + irda_qos_bits_to_value(&aup->qos); + + + /* Tx ring follows rx ring + 512 bytes */ + /* we need a 1k aligned buffer */ + aup->rx_ring[0] = (ring_dest_t *) + dma_alloc(2*MAX_NUM_IR_DESC*(sizeof(ring_dest_t)), &temp); + + /* allocate the data buffers */ + aup->db[0].vaddr = + (void *)dma_alloc(MAX_BUF_SIZE * 2*NUM_IR_DESC, &temp); + if (!aup->db[0].vaddr || !aup->rx_ring[0]) { + retval = -ENOMEM; + goto out; + } + + setup_hw_rings(aup, (u32)aup->rx_ring[0], (u32)aup->rx_ring[0] + 512); + + pDBfree = NULL; + pDB = aup->db; + for (i=0; i<(2*NUM_IR_DESC); i++) { + pDB->pnext = pDBfree; + pDBfree = pDB; + pDB->vaddr = + (u32 *)((unsigned)aup->db[0].vaddr + MAX_BUF_SIZE*i); + pDB->dma_addr = (dma_addr_t)virt_to_bus(pDB->vaddr); + pDB++; + } + aup->pDBfree = pDBfree; + + /* attach a data buffer to each descriptor */ + for (i=0; irx_ring[i]->addr_0 = (u8)(pDB->dma_addr & 0xff); + aup->rx_ring[i]->addr_1 = (u8)((pDB->dma_addr>>8) & 0xff); + aup->rx_ring[i]->addr_2 = (u8)((pDB->dma_addr>>16) & 0xff); + aup->rx_ring[i]->addr_3 = (u8)((pDB->dma_addr>>24) & 0xff); + aup->rx_db_inuse[i] = pDB; + } + for (i=0; itx_ring[i]->addr_0 = (u8)(pDB->dma_addr & 0xff); + aup->tx_ring[i]->addr_1 = (u8)((pDB->dma_addr>>8) & 0xff); + aup->tx_ring[i]->addr_2 = (u8)((pDB->dma_addr>>16) & 0xff); + aup->tx_ring[i]->addr_3 = (u8)((pDB->dma_addr>>24) & 0xff); + aup->tx_ring[i]->count_0 = 0; + aup->tx_ring[i]->count_1 = 0; + aup->tx_ring[i]->flags = 0; + aup->tx_db_inuse[i] = pDB; + } + return 0; + +out: + if (aup->db[0].vaddr) + dma_free((void *)aup->db[0].vaddr, + MAX_BUF_SIZE * 2*NUM_IR_DESC); + if (aup->rx_ring[0]) + kfree((void *)aup->rx_ring[0]); + if (aup->rx_buff.head) + kfree(aup->rx_buff.head); + if (dev->priv != NULL) + kfree(dev->priv); + unregister_netdevice(dev); + printk(KERN_ERR "%s: au1k_init_module failed. Returns %d\n", + dev->name, retval); + return retval; +} + + +static int au1k_init(struct net_device *dev) +{ + struct au1k_private *aup = (struct au1k_private *) dev->priv; + int i; + u32 control; + u32 ring_address; + + /* bring the device out of reset */ + control = 0xe; /* coherent, clock enable, one half system clock */ + +#ifndef CONFIG_CPU_LITTLE_ENDIAN + control |= 1; +#endif + aup->tx_head = 0; + aup->tx_tail = 0; + aup->rx_head = 0; + + for (i=0; irx_ring[i]->flags = AU_OWN; + } + + writel(control, IR_INTERFACE_CONFIG); + au_sync_delay(10); + + writel(read_ir_reg(IR_ENABLE) & ~0x8000, IR_ENABLE); /* disable PHY */ + au_sync_delay(1); + + writel(MAX_BUF_SIZE, IR_MAX_PKT_LEN); + + ring_address = (u32)virt_to_phys((void *)aup->rx_ring[0]); + writel(ring_address >> 26, IR_RING_BASE_ADDR_H); + writel((ring_address >> 10) & 0xffff, IR_RING_BASE_ADDR_L); + + writel(RING_SIZE_64<<8 | RING_SIZE_64<<12, IR_RING_SIZE); + + writel(1<<2 | IR_ONE_PIN, IR_CONFIG_2); /* 48MHz */ + writel(0, IR_RING_ADDR_CMPR); + + au1k_irda_set_speed(dev, 9600); + return 0; +} + +static int au1k_irda_start(struct net_device *dev) +{ + int retval; + char hwname[32]; + struct au1k_private *aup = (struct au1k_private *) dev->priv; + + MOD_INC_USE_COUNT; + + if ((retval = au1k_init(dev))) { + printk(KERN_ERR "%s: error in au1k_init\n", dev->name); + MOD_DEC_USE_COUNT; + return retval; + } + + if ((retval = request_irq(AU1000_IRDA_TX_INT, &au1k_irda_interrupt, + 0, dev->name, dev))) { + printk(KERN_ERR "%s: unable to get IRQ %d\n", + dev->name, dev->irq); + MOD_DEC_USE_COUNT; + return retval; + } + if ((retval = request_irq(AU1000_IRDA_RX_INT, &au1k_irda_interrupt, + 0, dev->name, dev))) { + free_irq(AU1000_IRDA_TX_INT, dev); + printk(KERN_ERR "%s: unable to get IRQ %d\n", + dev->name, dev->irq); + MOD_DEC_USE_COUNT; + return retval; + } + + /* Give self a hardware name */ + sprintf(hwname, "Au1000 SIR/FIR"); + aup->irlap = irlap_open(dev, &aup->qos, hwname); + netif_start_queue(dev); + + writel(read_ir_reg(IR_CONFIG_2) | 1<<8, IR_CONFIG_2); /* int enable */ + + aup->timer.expires = RUN_AT((3*HZ)); + aup->timer.data = (unsigned long)dev; + return 0; +} + +static int au1k_irda_stop(struct net_device *dev) +{ + struct au1k_private *aup = (struct au1k_private *) dev->priv; + + /* disable interrupts */ + writel(read_ir_reg(IR_CONFIG_2) & ~(1<<8), IR_CONFIG_2); + writel(0, IR_CONFIG_1); + writel(0, IR_INTERFACE_CONFIG); /* disable clock */ + au_sync(); + + if (aup->irlap) { + irlap_close(aup->irlap); + aup->irlap = NULL; + } + + netif_stop_queue(dev); + del_timer(&aup->timer); + + /* disable the interrupt */ + free_irq(AU1000_IRDA_TX_INT, dev); + free_irq(AU1000_IRDA_RX_INT, dev); + MOD_DEC_USE_COUNT; + return 0; +} + +static void __exit au1k_irda_exit(void) +{ + struct net_device *dev = ir_devs[0]; + struct au1k_private *aup = (struct au1k_private *) dev->priv; + + if (!dev) { + printk(KERN_ERR "au1k_ircc no dev found\n"); + return; + } + if (aup->db[0].vaddr) { + dma_free((void *)aup->db[0].vaddr, + MAX_BUF_SIZE * 2*NUM_IR_DESC); + aup->db[0].vaddr = 0; + } + if (aup->rx_ring[0]) { + dma_free((void *)aup->rx_ring[0], + 2*MAX_NUM_IR_DESC*(sizeof(ring_dest_t))); + aup->rx_ring[0] = 0; + } + rtnl_lock(); + unregister_netdevice(dev); + rtnl_unlock(); + ir_devs[0] = 0; +} + + +static inline void +update_tx_stats(struct net_device *dev, u32 status, u32 pkt_len) +{ + struct au1k_private *aup = (struct au1k_private *) dev->priv; + struct net_device_stats *ps = &aup->stats; + + ps->tx_packets++; + ps->tx_bytes += pkt_len; + + if (status & IR_TX_ERROR) { + ps->tx_errors++; + ps->tx_aborted_errors++; + } +} + + +static void au1k_tx_ack(struct net_device *dev) +{ + struct au1k_private *aup = (struct au1k_private *) dev->priv; + volatile ring_dest_t *ptxd; + + ptxd = aup->tx_ring[aup->tx_tail]; + while (!(ptxd->flags & AU_OWN) && (aup->tx_tail != aup->tx_head)) { + update_tx_stats(dev, ptxd->flags, + ptxd->count_1<<8 | ptxd->count_0); + ptxd->count_0 = 0; + ptxd->count_1 = 0; + au_sync(); + + aup->tx_tail = (aup->tx_tail + 1) & (NUM_IR_DESC - 1); + ptxd = aup->tx_ring[aup->tx_tail]; + + if (aup->tx_full) { + aup->tx_full = 0; + netif_wake_queue(dev); + } + } + + if (aup->tx_tail == aup->tx_head) { + if (aup->newspeed) { + au1k_irda_set_speed(dev, aup->newspeed); + aup->newspeed = 0; + } + else { + writel(read_ir_reg(IR_CONFIG_1) & ~IR_TX_ENABLE, + IR_CONFIG_1); + au_sync(); + writel(read_ir_reg(IR_CONFIG_1) | IR_RX_ENABLE, + IR_CONFIG_1); + writel(0, IR_RING_PROMPT); + au_sync(); + } + } +} + + +/* + * Au1000 transmit routine. + */ +static int au1k_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct au1k_private *aup = (struct au1k_private *) dev->priv; + int speed = irda_get_next_speed(skb); + volatile ring_dest_t *ptxd; + u32 len; + + u32 flags; + db_dest_t *pDB; + + if (speed != aup->speed && speed != -1) { + aup->newspeed = speed; + } + + if ((skb->len == 0) && (aup->newspeed)) { + if (aup->tx_tail == aup->tx_head) { + au1k_irda_set_speed(dev, speed); + aup->newspeed = 0; + } + dev_kfree_skb(skb); + return 0; + } + + ptxd = aup->tx_ring[aup->tx_head]; + flags = ptxd->flags; + + if (flags & AU_OWN) { + printk(KERN_INFO "%s: tx_full\n", dev->name); + netif_stop_queue(dev); + aup->tx_full = 1; + return 1; + } + else if (((aup->tx_head + 1) & (NUM_IR_DESC - 1)) == aup->tx_tail) { + printk(KERN_INFO "%s: tx_full\n", dev->name); + netif_stop_queue(dev); + aup->tx_full = 1; + return 1; + } + + pDB = aup->tx_db_inuse[aup->tx_head]; + +#if 0 + if (read_ir_reg(IR_RX_BYTE_CNT) != 0) { + printk("tx warning: rx byte cnt %x\n", + read_ir_reg(IR_RX_BYTE_CNT)); + } +#endif + + if (aup->speed == 4000000) { + /* FIR */ + memcpy((void *)pDB->vaddr, skb->data, skb->len); + ptxd->count_0 = skb->len & 0xff; + ptxd->count_1 = (skb->len >> 8) & 0xff; + } + else { + /* SIR */ + len = async_wrap_skb(skb, (u8 *)pDB->vaddr, MAX_BUF_SIZE); + ptxd->count_0 = len & 0xff; + ptxd->count_1 = (len >> 8) & 0xff; + ptxd->flags |= IR_DIS_CRC; + } + ptxd->flags |= AU_OWN; + au_sync(); + + writel(read_ir_reg(IR_CONFIG_1) | IR_TX_ENABLE, IR_CONFIG_1); + writel(0, IR_RING_PROMPT); + au_sync(); + + dev_kfree_skb(skb); + aup->tx_head = (aup->tx_head + 1) & (NUM_IR_DESC - 1); + dev->trans_start = jiffies; + return 0; +} + + +static inline void +update_rx_stats(struct net_device *dev, u32 status, u32 count) +{ + struct au1k_private *aup = (struct au1k_private *) dev->priv; + struct net_device_stats *ps = &aup->stats; + + ps->rx_packets++; + + if (status & IR_RX_ERROR) { + ps->rx_errors++; + if (status & (IR_PHY_ERROR|IR_FIFO_OVER)) + ps->rx_missed_errors++; + if (status & IR_MAX_LEN) + ps->rx_length_errors++; + if (status & IR_CRC_ERROR) + ps->rx_crc_errors++; + } + else + ps->rx_bytes += count; +} + +/* + * Au1000 receive routine. + */ +static int au1k_irda_rx(struct net_device *dev) +{ + struct au1k_private *aup = (struct au1k_private *) dev->priv; + struct sk_buff *skb; + volatile ring_dest_t *prxd; + u32 flags, count; + db_dest_t *pDB; + + prxd = aup->rx_ring[aup->rx_head]; + flags = prxd->flags; + + while (!(flags & AU_OWN)) { + pDB = aup->rx_db_inuse[aup->rx_head]; + count = prxd->count_1<<8 | prxd->count_0; + if (!(flags & IR_RX_ERROR)) { + /* good frame */ + update_rx_stats(dev, flags, count); + skb=alloc_skb(count+1,GFP_ATOMIC); + if (skb == NULL) { + aup->stats.rx_dropped++; + continue; + } + skb_reserve(skb, 1); + if (aup->speed == 4000000) + skb_put(skb, count); + else + skb_put(skb, count-2); + memcpy(skb->data, (void *)pDB->vaddr, count-2); + skb->dev = dev; + skb->mac.raw = skb->data; + skb->protocol = htons(ETH_P_IRDA); + netif_rx(skb); + prxd->count_0 = 0; + prxd->count_1 = 0; + } + prxd->flags |= AU_OWN; + aup->rx_head = (aup->rx_head + 1) & (NUM_IR_DESC - 1); + writel(0, IR_RING_PROMPT); + au_sync(); + + /* next descriptor */ + prxd = aup->rx_ring[aup->rx_head]; + flags = prxd->flags; + dev->last_rx = jiffies; + + } + return 0; +} + + +void au1k_irda_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct net_device *dev = (struct net_device *) dev_id; + + if (dev == NULL) { + printk(KERN_ERR "%s: isr: null dev ptr\n", dev->name); + return; + } + + writel(0, IR_INT_CLEAR); /* ack irda interrupts */ + + au1k_irda_rx(dev); + au1k_tx_ack(dev); +} + + +/* + * The Tx ring has been full longer than the watchdog timeout + * value. The transmitter must be hung? + */ +static void au1k_tx_timeout(struct net_device *dev) +{ + u32 speed; + struct au1k_private *aup = (struct au1k_private *) dev->priv; + + printk(KERN_ERR "%s: tx timeout\n", dev->name); + speed = aup->speed; + aup->speed = 0; + au1k_irda_set_speed(dev, speed); + aup->tx_full = 0; + netif_wake_queue(dev); +} + + +/* + * Set the IrDA communications speed. + */ +static int +au1k_irda_set_speed(struct net_device *dev, int speed) +{ + unsigned long flags; + struct au1k_private *aup = (struct au1k_private *) dev->priv; + u32 control; + int ret = 0, timeout = 10, i; + volatile ring_dest_t *ptxd; + + if (speed == aup->speed) + return ret; + + spin_lock_irqsave(&ir_lock, flags); + + /* disable PHY first */ + writel(read_ir_reg(IR_ENABLE) & ~0x8000, IR_ENABLE); + + /* disable RX/TX */ + writel(read_ir_reg(IR_CONFIG_1) & ~(IR_RX_ENABLE|IR_TX_ENABLE), + IR_CONFIG_1); + au_sync_delay(1); + while (read_ir_reg(IR_ENABLE) & (IR_RX_STATUS | IR_TX_STATUS)) { + mdelay(1); + if (!timeout--) { + printk(KERN_ERR "%s: rx/tx disable timeout\n", + dev->name); + break; + } + } + + /* disable DMA */ + writel(read_ir_reg(IR_CONFIG_1) & ~IR_DMA_ENABLE, IR_CONFIG_1); + au_sync_delay(1); + + /* + * After we disable tx/rx. the index pointers + * go back to zero. + */ + aup->tx_head = aup->tx_tail = aup->rx_head = 0; + for (i=0; itx_ring[i]; + ptxd->flags = 0; + ptxd->count_0 = 0; + ptxd->count_1 = 0; + } + + for (i=0; irx_ring[i]; + ptxd->count_0 = 0; + ptxd->count_1 = 0; + ptxd->flags = AU_OWN; + } + + if (speed == 4000000) + writel(1<<13, CPLD_AUX1); + else + writel(readl(CPLD_AUX1) & ~(1<<13), CPLD_AUX1); + + switch (speed) { + case 9600: + writel(11<<10 | 12<<5, IR_WRITE_PHY_CONFIG); + writel(IR_SIR_MODE, IR_CONFIG_1); + break; + case 19200: + writel(5<<10 | 12<<5, IR_WRITE_PHY_CONFIG); + writel(IR_SIR_MODE, IR_CONFIG_1); + break; + case 38400: + writel(2<<10 | 12<<5, IR_WRITE_PHY_CONFIG); + writel(IR_SIR_MODE, IR_CONFIG_1); + break; + case 57600: + writel(1<<10 | 12<<5, IR_WRITE_PHY_CONFIG); + writel(IR_SIR_MODE, IR_CONFIG_1); + break; + case 115200: + writel(12<<5, IR_WRITE_PHY_CONFIG); + writel(IR_SIR_MODE, IR_CONFIG_1); + break; + case 4000000: + writel(0xF, IR_WRITE_PHY_CONFIG); + writel(IR_FIR|IR_DMA_ENABLE|IR_RX_ENABLE, IR_CONFIG_1); + break; + default: + printk(KERN_ERR "%s unsupported speed %x\n", dev->name, speed); + ret = -EINVAL; + break; + } + + aup->speed = speed; + writel(read_ir_reg(IR_ENABLE) | 0x8000, IR_ENABLE); + au_sync(); + + control = read_ir_reg(IR_ENABLE); + writel(0, IR_RING_PROMPT); + au_sync(); + + if (control & (1<<14)) { + printk(KERN_ERR "%s: configuration error\n", dev->name); + } + else { + if (control & (1<<11)) + printk(KERN_INFO "%s Valid SIR config\n", dev->name); + if (control & (1<<12)) + printk(KERN_INFO "%s Valid MIR config\n", dev->name); + if (control & (1<<13)) + printk(KERN_INFO "%s Valid FIR config\n", dev->name); + if (control & (1<<10)) + printk(KERN_INFO "%s TX enabled\n", dev->name); + if (control & (1<<9)) + printk(KERN_INFO "%s RX enabled\n", dev->name); + } + + spin_unlock_irqrestore(&ir_lock, flags); + return ret; +} + +static int +au1k_irda_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd) +{ + struct if_irda_req *rq = (struct if_irda_req *)ifreq; + struct au1k_private *aup = dev->priv; + int ret = -EOPNOTSUPP; + + switch (cmd) { + case SIOCSBANDWIDTH: + if (capable(CAP_NET_ADMIN)) { + /* + * We are unable to set the speed if the + * device is not running. + */ + if (aup->open) + ret = au1k_irda_set_speed(dev, + rq->ifr_baudrate); + else { + printk(KERN_ERR "%s ioctl: !netif_running\n", + dev->name); + ret = 0; + } + } + break; + + case SIOCSMEDIABUSY: + ret = -EPERM; + if (capable(CAP_NET_ADMIN)) { + irda_device_set_media_busy(dev, TRUE); + ret = 0; + } + break; + + case SIOCGRECEIVING: + rq->ifr_receiving = 0; + break; + default: + break; + } + return ret; +} + + +static struct net_device_stats *au1k_irda_stats(struct net_device *dev) +{ + struct au1k_private *aup = (struct au1k_private *) dev->priv; + return &aup->stats; +} + +#ifdef MODULE +MODULE_AUTHOR("Pete Popov "); +MODULE_DESCRIPTION("Au1000 IrDA Device Driver"); + +module_init(au1k_irda_init); +module_exit(au1k_irda_exit); +#endif /* MODULE */ diff -Nru a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c --- a/drivers/net/irda/vlsi_ir.c Tue Jul 1 18:44:31 2003 +++ b/drivers/net/irda/vlsi_ir.c Tue Jul 1 18:44:31 2003 @@ -2,7 +2,7 @@ * * vlsi_ir.c: VLSI82C147 PCI IrDA controller driver for Linux * - * Copyright (c) 2001-2002 Martin Diehl + * Copyright (c) 2001-2003 Martin Diehl * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -28,7 +28,7 @@ MODULE_LICENSE("GPL"); #define DRIVER_NAME "vlsi_ir" -#define DRIVER_VERSION "v0.4" +#define DRIVER_VERSION "v0.4a" /********************************************************/ @@ -149,6 +149,9 @@ /********************************************************/ +/* needed regardless of CONFIG_PROC_FS */ +static struct proc_dir_entry *vlsi_proc_root = NULL; + #ifdef CONFIG_PROC_FS static int vlsi_proc_pdev(struct pci_dev *pdev, char *buf, int len) @@ -394,8 +397,6 @@ return out - buf; } -static struct proc_dir_entry *vlsi_proc_root = NULL; - struct vlsi_proc_data { int size; char *data; @@ -494,11 +495,18 @@ } static struct file_operations vlsi_proc_fops = { + /* protect individual procdir file entry against rmmod */ + .owner = THIS_MODULE, .open = vlsi_proc_open, .llseek = vlsi_proc_lseek, .read = vlsi_proc_read, .release = vlsi_proc_release, }; + +#define VLSI_PROC_FOPS (&vlsi_proc_fops) + +#else /* CONFIG_PROC_FS */ +#define VLSI_PROC_FOPS NULL #endif /********************************************************/ @@ -1800,8 +1808,7 @@ goto out_freedev; } -#ifdef CONFIG_PROC_FS - { + if (vlsi_proc_root != NULL) { struct proc_dir_entry *ent; ent = create_proc_entry(ndev->name, S_IFREG|S_IRUGO, vlsi_proc_root); @@ -1810,11 +1817,11 @@ goto out_unregister; } ent->data = ndev; - ent->proc_fops = &vlsi_proc_fops; + ent->proc_fops = VLSI_PROC_FOPS; ent->size = 0; idev->proc_entry = ent; - } -#endif + } else + idev->proc_entry = NULL; printk(KERN_INFO "%s: registered device %s\n", drivername, ndev->name); @@ -1851,12 +1858,10 @@ down(&idev->sem); pci_set_drvdata(pdev, NULL); pci_disable_device(pdev); -#ifdef CONFIG_PROC_FS if (idev->proc_entry) { remove_proc_entry(ndev->name, vlsi_proc_root); idev->proc_entry = NULL; } -#endif up(&idev->sem); unregister_netdev(ndev); @@ -1993,9 +1998,7 @@ #endif }; -#ifdef CONFIG_PROC_FS #define PROC_DIR ("driver/" DRIVER_NAME) -#endif static int __init vlsi_mod_init(void) { @@ -2025,18 +2028,23 @@ sirpulse = !!sirpulse; -#ifdef CONFIG_PROC_FS + /* create_proc_entry returns NULL if !CONFIG_PROC_FS. + * Failure to create the procfs entry is handled like running + * without procfs - it's not required for the driver to work. + */ vlsi_proc_root = create_proc_entry(PROC_DIR, S_IFDIR, 0); - if (!vlsi_proc_root) - return -ENOMEM; -#endif + if (vlsi_proc_root) { + /* protect registered procdir against module removal. + * Because we are in the module init path there's no race + * window after create_proc_entry (and no barrier needed). + */ + vlsi_proc_root->owner = THIS_MODULE; + } ret = pci_module_init(&vlsi_irda_driver); -#ifdef CONFIG_PROC_FS - if (ret) + if (ret && vlsi_proc_root) remove_proc_entry(PROC_DIR, 0); -#endif return ret; } @@ -2044,7 +2052,8 @@ static void __exit vlsi_mod_exit(void) { pci_unregister_driver(&vlsi_irda_driver); - remove_proc_entry(PROC_DIR, 0); + if (vlsi_proc_root) + remove_proc_entry(PROC_DIR, 0); } module_init(vlsi_mod_init); diff -Nru a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c --- a/drivers/net/ixgb/ixgb_ethtool.c Tue Jul 1 18:44:37 2003 +++ b/drivers/net/ixgb/ixgb_ethtool.c Tue Jul 1 18:44:37 2003 @@ -448,8 +448,6 @@ case ETHTOOL_SSET:{ struct ethtool_cmd ecmd; - if (!capable(CAP_NET_ADMIN)) - return -EPERM; if (copy_from_user(&ecmd, addr, sizeof (ecmd))) return -EFAULT; return ixgb_ethtool_sset(adapter, &ecmd); @@ -482,9 +480,6 @@ #endif /* ETHTOOL_GREGS */ case ETHTOOL_NWAY_RST:{ IXGB_DBG("ETHTOOL_NWAY_RST\n"); - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - ixgb_down(adapter); ixgb_up(adapter); @@ -539,9 +534,6 @@ struct ethtool_eeprom eeprom; IXGB_DBG("ETHTOOL_SEEPROM\n"); - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - if (copy_from_user(&eeprom, addr, sizeof (eeprom))) return -EFAULT; diff -Nru a/drivers/net/meth.c b/drivers/net/meth.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/net/meth.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,862 @@ +/* + * meth.c -- O2 Builtin 10/100 Ethernet driver + * + * Copyright (C) 2001 Ilya Volynets + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include +#include + +#include +#include /* printk() */ +#include +#include +#include /* error codes */ +#include /* size_t */ +#include /* mark_bh */ +#include + +#include +#include /* struct device, and other headers */ +#include /* eth_type_trans */ +#include /* struct iphdr */ +#include /* struct tcphdr */ +#include +#include /*MII definitions */ + +#include +#include +#include + +#include "meth.h" + +#include +#include + +#ifndef MFE_DEBUG +#define MFE_DEBUG 0 +#endif + +#if MFE_DEBUG>=1 +#define DPRINTK(str,args...) printk (KERN_DEBUG "meth(%ld): %s: " str, jiffies, __FUNCTION__ , ## args) +#define MFE_RX_DEBUG 2 +#else +#define DPRINTK(str,args...) +#define MFE_RX_DEBUG 0 +#endif + + +static const char *version="meth.c: Ilya Volynets (ilya@theIlya.com)"; +static const char *meth_str="SGI O2 Fast Ethernet"; +MODULE_AUTHOR("Ilya Volynets"); +MODULE_DESCRIPTION("SGI O2 Builtin Fast Ethernet driver"); + +/* This is a load-time options */ +/*static int eth = 0; +MODULE_PARM(eth, "i");*/ + +#define HAVE_TX_TIMEOUT +/* The maximum time waited (in jiffies) before assuming a Tx failed. (400ms) */ +#define TX_TIMEOUT (400*HZ/1000) + +#ifdef HAVE_TX_TIMEOUT +static int timeout = TX_TIMEOUT; +MODULE_PARM(timeout, "i"); +#endif + +int meth_eth; + +/* + * This structure is private to each device. It is used to pass + * packets in and out, so there is place for a packet + */ + +typedef struct meth_private { + struct net_device_stats stats; + volatile struct meth_regs *regs; + u64 mode; /* in-memory copy of MAC control register */ + int phy_addr; /* address of phy, used by mdio_* functions, initialized in mdio_probe*/ + tx_packet *tx_ring; + dma_addr_t tx_ring_dma; + int free_space; + struct sk_buff *tx_skbs[TX_RING_ENTRIES]; + dma_addr_t tx_skb_dmas[TX_RING_ENTRIES]; + int tx_read,tx_write; + int tx_count; + + rx_packet *rx_ring[RX_RING_ENTRIES]; + dma_addr_t rx_ring_dmas[RX_RING_ENTRIES]; + int rx_write; + + spinlock_t meth_lock; +} meth_private; + +extern struct net_device meth_devs[]; +void meth_tx_timeout (struct net_device *dev); +void meth_interrupt(int irq, void *dev_id, struct pt_regs *pregs); + +/* global, initialized in ip32-setup.c */ +char o2meth_eaddr[8]={0,0,0,0,0,0,0,0}; + +static inline void load_eaddr(struct net_device *dev, + volatile struct meth_regs *regs) +{ + int i; + DPRINTK("Loading MAC Address: %02x:%02x:%02x:%02x:%02x:%02x\n", + (int)o2meth_eaddr[0]&0xFF,(int)o2meth_eaddr[1]&0xFF,(int)o2meth_eaddr[2]&0xFF, + (int)o2meth_eaddr[3]&0xFF,(int)o2meth_eaddr[4]&0xFF,(int)o2meth_eaddr[5]&0xFF); + //memcpy(dev->dev_addr,o2meth_eaddr+2,6); + for (i=0; i<6; i++) + dev->dev_addr[i]=o2meth_eaddr[i]; + regs->mac_addr= //dev->dev_addr[0]|(dev->dev_addr[1]<<8)| + //dev->dev_addr[2]<<16|(dev->dev_addr[3]<<24)| + //dev->dev_addr[4]<<32|(dev->dev_addr[5]<<40); + (*(u64*)o2meth_eaddr)>>16; + DPRINTK("MAC, finally is %0lx\n",regs->mac_addr); +} + +/* + *Waits for BUSY status of mdio bus to clear + */ +#define WAIT_FOR_PHY(___regs, ___rval) \ + while((___rval=___regs->phy_data)&MDIO_BUSY){ \ + udelay(25); \ + } +/*read phy register, return value read */ +static int mdio_read(meth_private *priv,int phyreg) +{ + volatile meth_regs* regs=priv->regs; + volatile u32 rval; + WAIT_FOR_PHY(regs,rval) + regs->phy_registers=(priv->phy_addr<<5)|(phyreg&0x1f); + udelay(25); + regs->phy_trans_go=1; + udelay(25); + WAIT_FOR_PHY(regs,rval) + return rval&MDIO_DATA_MASK; +} + +/*write phy register */ +static void mdio_write(meth_private* priv,int pfyreg,int val) +{ + volatile meth_regs* regs=priv->regs; + int rval; +/// DPRINTK("Trying to write value %i to reguster %i\n",val, pfyreg); + spin_lock_irq(&priv->meth_lock); + WAIT_FOR_PHY(regs,rval) + regs->phy_registers=(priv->phy_addr<<5)|(pfyreg&0x1f); + regs->phy_data=val; + udelay(25); + WAIT_FOR_PHY(regs,rval) + spin_unlock_irq(&priv->meth_lock); +} + +/* Modify phy register using given mask and value */ +static void mdio_update(meth_private* priv,int phyreg, int val, int mask) +{ + int rval; + DPRINTK("RMW value %i to PHY register %i with mask %i\n",val,phyreg,mask); + rval=mdio_read(priv,phyreg); + rval=(rval&~mask)|(val&mask); + mdio_write(priv,phyreg,rval); +} + +/* handle errata data on MDIO bus */ +//static void mdio_errata(meth_private *priv) +//{ + /* Hmmm... what the hell is phyerrata? does it come from sys init parameters in IRIX */ +//} +static int mdio_probe(meth_private *priv) +{ + int i, p2, p3; + DPRINTK("Detecting PHY kind\n"); + /* check if phy is detected already */ + if(priv->phy_addr>=0&&priv->phy_addr<32) + return 0; + spin_lock_irq(&priv->meth_lock); + for (i=0;i<32;++i){ + priv->phy_addr=(char)i; + p2=mdio_read(priv,2); +#ifdef MFE_DEBUG + p3=mdio_read(priv,3); + switch ((p2<<12)|(p3>>4)){ + case PHY_QS6612X: + DPRINTK("PHY is QS6612X\n"); + break; + case PHY_ICS1889: + DPRINTK("PHY is ICS1889\n"); + break; + case PHY_ICS1890: + DPRINTK("PHY is ICS1890\n"); + break; + case PHY_DP83840: + DPRINTK("PHY is DP83840\n"); + break; + } +#endif + if(p2!=0xffff&&p2!=0x0000){ + DPRINTK("PHY code: %x\n",(p2<<12)|(p3>>4)); + break; + } + } + spin_unlock_irq(&priv->meth_lock); + if(priv->phy_addr<32) { + return 0; + } + DPRINTK("Oopsie! PHY is not known!\n"); + priv->phy_addr=-1; + return -ENODEV; +} + +static void meth_check_link(struct net_device *dev) +{ + struct meth_private *priv = (struct meth_private *) dev->priv; + int mii_partner = mdio_read(priv, 5); + int mii_advertising = mdio_read(priv, 4); + int negotiated = mii_advertising & mii_partner; + int duplex, speed; + + if (mii_partner == 0xffff) + return; + + duplex = ((negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040)?METH_PHY_FDX:0; + speed = (negotiated & 0x0380)?METH_100MBIT:0; + + if ((priv->mode & METH_PHY_FDX) ^ duplex) + { + DPRINTK("Setting %s-duplex\n", duplex ? "full" : "half"); + if (duplex) + priv->mode |= METH_PHY_FDX; + else + priv->mode &= ~METH_PHY_FDX; + priv->regs->mac_ctrl = priv->mode; + } + + if ((priv->mode & METH_100MBIT) ^ speed) + { + DPRINTK("Setting %dMbs mode\n", speed ? 100 : 10); + if (duplex) + priv->mode |= METH_100MBIT; + else + priv->mode &= ~METH_100MBIT; + priv->regs->mac_ctrl = priv->mode; + } +} + + +static int meth_init_tx_ring(meth_private *priv) +{ + /* Init TX ring */ + DPRINTK("Initializing TX ring\n"); + priv->tx_ring = (tx_packet *) pci_alloc_consistent(NULL,TX_RING_BUFFER_SIZE,&(priv->tx_ring_dma)); + if(!priv->tx_ring) + return -ENOMEM; + memset(priv->tx_ring, 0, TX_RING_BUFFER_SIZE); + priv->tx_count = priv->tx_read = priv->tx_write = 0; + priv->regs->tx_ring_base = priv->tx_ring_dma; + priv->free_space = TX_RING_ENTRIES; + /* Now init skb save area */ + memset(priv->tx_skbs,0,sizeof(priv->tx_skbs)); + memset(priv->tx_skb_dmas,0,sizeof(priv->tx_skb_dmas)); + DPRINTK("Done with TX ring init\n"); + return 0; +} + +static int meth_init_rx_ring(meth_private *priv) +{ + int i; + DPRINTK("Initializing RX ring\n"); + for(i=0;irx_ring[i]=get_free_page(GFP_KERNEL))) + return -ENOMEM; + DPRINTK("\t2:\t%i\n",i);*/ + priv->rx_ring[i]=(rx_packet*)pci_alloc_consistent(NULL,METH_RX_BUFF_SIZE,&(priv->rx_ring_dmas[i])); + /* I'll need to re-sync it after each RX */ + DPRINTK("\t%p\n",priv->rx_ring[i]); + priv->regs->rx_fifo=priv->rx_ring_dmas[i]; + } + priv->rx_write = 0; + DPRINTK("Done with RX ring\n"); + return 0; +} +static void meth_free_tx_ring(meth_private *priv) +{ + int i; + + /* Remove any pending skb */ + for (i = 0; i < TX_RING_ENTRIES; i++) { + if (priv->tx_skbs[i]) + dev_kfree_skb(priv->tx_skbs[i]); + priv->tx_skbs[i] = NULL; + } + pci_free_consistent(NULL, + TX_RING_BUFFER_SIZE, + priv->tx_ring, + priv->tx_ring_dma); +} +static void meth_free_rx_ring(meth_private *priv) +{ + int i; + + for(i=0;irx_ring[i], + priv->rx_ring_dmas[i]); +} + +int meth_reset(struct net_device *dev) +{ + struct meth_private *priv = (struct meth_private *) dev->priv; + + /* Reset card */ + priv->regs->mac_ctrl = SGI_MAC_RESET; + priv->regs->mac_ctrl = 0; + udelay(25); + DPRINTK("MAC control after reset: %016lx\n", priv->regs->mac_ctrl); + + /* Load ethernet address */ + load_eaddr(dev, priv->regs); + /* Should load some "errata", but later */ + + /* Check for device */ + if(mdio_probe(priv) < 0) { + DPRINTK("Unable to find PHY\n"); + return -ENODEV; + } + + /* Initial mode -- 10|Half-duplex|Accept normal packets */ + priv->mode=METH_ACCEPT_MCAST|METH_DEFAULT_IPG; + if(dev->flags | IFF_PROMISC) + priv->mode |= METH_PROMISC; + priv->regs->mac_ctrl = priv->mode; + + /* Autonegociate speed and duplex mode */ + meth_check_link(dev); + + /* Now set dma control, but don't enable DMA, yet */ + priv->regs->dma_ctrl= (4 << METH_RX_OFFSET_SHIFT) | + (RX_RING_ENTRIES << METH_RX_DEPTH_SHIFT); + + return(0); +} + +/*============End Helper Routines=====================*/ + +/* + * Open and close + */ + +int meth_open(struct net_device *dev) +{ + meth_private *priv=dev->priv; + volatile meth_regs *regs=priv->regs; + + MOD_INC_USE_COUNT; + + /* Start DMA */ + regs->dma_ctrl|= + METH_DMA_TX_EN|/*METH_DMA_TX_INT_EN|*/ + METH_DMA_RX_EN|METH_DMA_RX_INT_EN; + + if(request_irq(dev->irq,meth_interrupt,SA_SHIRQ,meth_str,dev)){ + printk(KERN_ERR "%s: Can't get irq %d\n", dev->name, dev->irq); + return -EAGAIN; + } + netif_start_queue(dev); + DPRINTK("Opened... DMA control=0x%08lx\n", regs->dma_ctrl); + return 0; +} + +int meth_release(struct net_device *dev) +{ + netif_stop_queue(dev); /* can't transmit any more */ + /* shut down dma */ + ((meth_private*)(dev->priv))->regs->dma_ctrl&= + ~(METH_DMA_TX_EN|METH_DMA_TX_INT_EN| + METH_DMA_RX_EN|METH_DMA_RX_INT_EN); + free_irq(dev->irq, dev); + MOD_DEC_USE_COUNT; + return 0; +} + +/* + * Configuration changes (passed on by ifconfig) + */ +int meth_config(struct net_device *dev, struct ifmap *map) +{ + if (dev->flags & IFF_UP) /* can't act on a running interface */ + return -EBUSY; + + /* Don't allow changing the I/O address */ + if (map->base_addr != dev->base_addr) { + printk(KERN_WARNING "meth: Can't change I/O address\n"); + return -EOPNOTSUPP; + } + + /* Allow changing the IRQ */ + if (map->irq != dev->irq) { + printk(KERN_WARNING "meth: Can't change IRQ\n"); + return -EOPNOTSUPP; + } + DPRINTK("Configured\n"); + + /* ignore other fields */ + return 0; +} + +/* + * Receive a packet: retrieve, encapsulate and pass over to upper levels + */ +void meth_rx(struct net_device* dev) +{ + struct sk_buff *skb; + struct meth_private *priv = (struct meth_private *) dev->priv; + rx_packet *rxb; + DPRINTK("RX...\n"); + // TEMP while((rxb=priv->rx_ring[priv->rx_write])->status.raw&0x8000000000000000){ + while((rxb=priv->rx_ring[priv->rx_write])->status.raw&0x8000000000000000){ + int len=rxb->status.parsed.rx_len - 4; /* omit CRC */ + DPRINTK("(%i)\n",priv->rx_write); + /* length sanity check */ + if(len < 60 || len > 1518) { + printk(KERN_DEBUG "%s: bogus packet size: %d, status=%#2x.\n", + dev->name, priv->rx_write, rxb->status.raw); + priv->stats.rx_errors++; + priv->stats.rx_length_errors++; + } + if(!(rxb->status.raw&METH_RX_STATUS_ERRORS)){ + skb=alloc_skb(len+2,GFP_ATOMIC);/* Should be atomic -- we are in interrupt */ + if(!skb){ + /* Ouch! No memory! Drop packet on the floor */ + DPRINTK("!!!>>>Ouch! Not enough Memory for RX buffer!\n"); + priv->stats.rx_dropped++; + } else { + skb_reserve(skb, 2); /* align IP on 16B boundary */ + memcpy(skb_put(skb, len), rxb->buf, len); + /* Write metadata, and then pass to the receive level */ + skb->dev = dev; + skb->protocol = eth_type_trans(skb, dev); + //skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it */ + + DPRINTK("passing packet\n"); + DPRINTK("len = %d rxb->status = %x\n", + len, rxb->status.raw); + netif_rx(skb); + dev->last_rx = jiffies; + priv->stats.rx_packets++; + priv->stats.rx_bytes+=len; + DPRINTK("There we go... Whew...\n"); + } + } + priv->regs->rx_fifo=priv->rx_ring_dmas[priv->rx_write]; + rxb->status.raw=0; + priv->rx_write=(priv->rx_write+1)&(RX_RING_ENTRIES-1); + } +} + +static int meth_tx_full(struct net_device *dev) +{ + struct meth_private *priv = (struct meth_private *) dev->priv; + + return(priv->tx_count >= TX_RING_ENTRIES-1); +} + +void meth_tx_cleanup(struct net_device* dev, int rptr) +{ + meth_private *priv=dev->priv; + tx_packet* status; + struct sk_buff *skb; + + spin_lock(&priv->meth_lock); + + /* Stop DMA */ + priv->regs->dma_ctrl &= ~(METH_DMA_TX_INT_EN); + + while(priv->tx_read != rptr){ + skb = priv->tx_skbs[priv->tx_read]; + status = &priv->tx_ring[priv->tx_read]; + if(!status->header.res.sent) + break; + if(status->header.raw & METH_TX_STATUS_DONE) { + priv->stats.tx_packets++; + priv->stats.tx_bytes += skb->len; + } + dev_kfree_skb_irq(skb); + priv->tx_skbs[priv->tx_read] = NULL; + status->header.raw = 0; + priv->tx_read = (priv->tx_read+1)&(TX_RING_ENTRIES-1); + priv->tx_count --; + } + + /* wake up queue if it was stopped */ + if (netif_queue_stopped(dev) && ! meth_tx_full(dev)) { + netif_wake_queue(dev); + } + + spin_unlock(priv->meth_lock); +} + +/* + * The typical interrupt entry point + */ +void meth_interrupt(int irq, void *dev_id, struct pt_regs *pregs) +{ + struct meth_private *priv; + union { + u32 reg; /*Whole status register */ + struct { + u32 : 2, + rx_seq : 5, + tx_read : 9, + + rx_read : 8, + int_mask: 8; + } parsed; + } status; + /* + * As usual, check the "device" pointer for shared handlers. + * Then assign "struct device *dev" + */ + struct net_device *dev = (struct net_device *)dev_id; + /* ... and check with hw if it's really ours */ + + if (!dev /*paranoid*/ ) return; + + /* Lock the device */ + priv = (struct meth_private *) dev->priv; + + status.reg = priv->regs->int_flags; + + DPRINTK("Interrupt, status %08x...\n",status.reg); + if (status.parsed.int_mask & METH_INT_RX_THRESHOLD) { + /* send it to meth_rx for handling */ + meth_rx(dev); + } + + if (status.parsed.int_mask & (METH_INT_TX_EMPTY|METH_INT_TX_PKT)) { + /* a transmission is over: free the skb */ + meth_tx_cleanup(dev, status.parsed.tx_read); + } + /* check for errors too... */ + if (status.parsed.int_mask & (METH_INT_TX_LINK_FAIL)) + printk(KERN_WARNING "meth: link failure\n"); + if (status.parsed.int_mask & (METH_INT_MEM_ERROR)) + printk(KERN_WARNING "meth: memory error\n"); + if (status.parsed.int_mask & (METH_INT_TX_ABORT)) + printk(KERN_WARNING "meth: aborted\n"); + DPRINTK("Interrupt handling done...\n"); + + priv->regs->int_flags=status.reg&0xff; /* clear interrupts */ +} + +/* + * Transmits packets that fit into TX descriptor (are <=120B) + */ +static void meth_tx_short_prepare(meth_private* priv, struct sk_buff* skb) +{ + tx_packet *desc=&priv->tx_ring[priv->tx_write]; + int len = (skb->lenlen; + + DPRINTK("preparing short packet\n"); + /* maybe I should set whole thing to 0 first... */ + memcpy(desc->data.dt+(120-len),skb->data,skb->len); + if(skb->len < len) + memset(desc->data.dt+120-len+skb->len,0,len-skb->len); + desc->header.raw=METH_TX_CMD_INT_EN|(len-1)|((128-len)<<16); + DPRINTK("desc=%016lx\n",desc->header.raw); +} +#define TX_CATBUF1 BIT(25) +static void meth_tx_1page_prepare(meth_private* priv, struct sk_buff* skb) +{ + tx_packet *desc=&priv->tx_ring[priv->tx_write]; + void *buffer_data = (void *)(((u64)skb->data + 7ULL) & (~7ULL)); + int unaligned_len = (int)((u64)buffer_data - (u64)skb->data); + int buffer_len = skb->len - unaligned_len; + dma_addr_t catbuf; + + DPRINTK("preparing 1 page...\n"); + DPRINTK("length=%d data=%p\n", skb->len, skb->data); + DPRINTK("unaligned_len=%d\n", unaligned_len); + DPRINTK("buffer_data=%p buffer_len=%d\n", + buffer_data, + buffer_len); + + desc->header.raw=METH_TX_CMD_INT_EN|TX_CATBUF1|(skb->len-1); + + /* unaligned part */ + if(unaligned_len){ + memcpy(desc->data.dt+(120-unaligned_len), + skb->data, unaligned_len); + desc->header.raw |= (128-unaligned_len) << 16; + } + + /* first page */ + catbuf = pci_map_single(NULL, + buffer_data, + buffer_len, + PCI_DMA_TODEVICE); + DPRINTK("catbuf=%x\n", catbuf); + desc->data.cat_buf[0].form.start_addr = catbuf >> 3; + desc->data.cat_buf[0].form.len = buffer_len-1; + DPRINTK("desc=%016lx\n",desc->header.raw); + DPRINTK("cat_buf[0].raw=%016lx\n",desc->data.cat_buf[0].raw); +} +#define TX_CATBUF2 BIT(26) +static void meth_tx_2page_prepare(meth_private* priv, struct sk_buff* skb) +{ + tx_packet *desc=&priv->tx_ring[priv->tx_write]; + void *buffer1_data = (void *)(((u64)skb->data + 7ULL) & (~7ULL)); + void *buffer2_data = (void *)PAGE_ALIGN((u64)skb->data); + int unaligned_len = (int)((u64)buffer1_data - (u64)skb->data); + int buffer1_len = (int)((u64)buffer2_data - (u64)buffer1_data); + int buffer2_len = skb->len - buffer1_len - unaligned_len; + dma_addr_t catbuf1, catbuf2; + + DPRINTK("preparing 2 pages... \n"); + DPRINTK("length=%d data=%p\n", skb->len, skb->data); + DPRINTK("unaligned_len=%d\n", unaligned_len); + DPRINTK("buffer1_data=%p buffer1_len=%d\n", + buffer1_data, + buffer1_len); + DPRINTK("buffer2_data=%p buffer2_len=%d\n", + buffer2_data, + buffer2_len); + + desc->header.raw=METH_TX_CMD_INT_EN|TX_CATBUF1|TX_CATBUF2|(skb->len-1); + /* unaligned part */ + if(unaligned_len){ + memcpy(desc->data.dt+(120-unaligned_len), + skb->data, unaligned_len); + desc->header.raw |= (128-unaligned_len) << 16; + } + + /* first page */ + catbuf1 = pci_map_single(NULL, + buffer1_data, + buffer1_len, + PCI_DMA_TODEVICE); + DPRINTK("catbuf1=%x\n", catbuf1); + desc->data.cat_buf[0].form.start_addr = catbuf1 >> 3; + desc->data.cat_buf[0].form.len = buffer1_len-1; + /* second page */ + catbuf2 = pci_map_single(NULL, + buffer2_data, + buffer2_len, + PCI_DMA_TODEVICE); + DPRINTK("catbuf2=%x\n", catbuf2); + desc->data.cat_buf[1].form.start_addr = catbuf2 >> 3; + desc->data.cat_buf[1].form.len = buffer2_len-1; + DPRINTK("desc=%016lx\n",desc->header.raw); + DPRINTK("cat_buf[0].raw=%016lx\n",desc->data.cat_buf[0].raw); + DPRINTK("cat_buf[1].raw=%016lx\n",desc->data.cat_buf[1].raw); +} + + +void meth_add_to_tx_ring(meth_private *priv, struct sk_buff* skb) +{ + DPRINTK("Transmitting data...\n"); + if(skb->len <= 120) { + /* Whole packet fits into descriptor */ + meth_tx_short_prepare(priv,skb); + } else if(PAGE_ALIGN((u64)skb->data) != + PAGE_ALIGN((u64)skb->data+skb->len-1)) { + /* Packet crosses page boundary */ + meth_tx_2page_prepare(priv,skb); + } else { + /* Packet is in one page */ + meth_tx_1page_prepare(priv,skb); + } + + /* Remember the skb, so we can free it at interrupt time */ + priv->tx_skbs[priv->tx_write] = skb; + priv->tx_write = (priv->tx_write+1) & (TX_RING_ENTRIES-1); + priv->regs->tx_info.wptr = priv->tx_write; + priv->tx_count ++; + /* Enable DMA transfer */ + priv->regs->dma_ctrl |= METH_DMA_TX_INT_EN; +} + +/* + * Transmit a packet (called by the kernel) + */ +int meth_tx(struct sk_buff *skb, struct net_device *dev) +{ + struct meth_private *priv = (struct meth_private *) dev->priv; + + spin_lock_irq(&priv->meth_lock); + + meth_add_to_tx_ring(priv, skb); + dev->trans_start = jiffies; /* save the timestamp */ + + /* If TX ring is full, tell the upper layer to stop sending packets */ + if (meth_tx_full(dev)) { + DPRINTK("TX full: stopping\n"); + netif_stop_queue(dev); + } + + spin_unlock_irq(&priv->meth_lock); + + return 0; +} + +/* + * Deal with a transmit timeout. + */ + +void meth_tx_timeout (struct net_device *dev) +{ + struct meth_private *priv = (struct meth_private *) dev->priv; + + printk(KERN_WARNING "%s: transmit timed out\n", dev->name); + + /* Protect against concurrent rx interrupts */ + spin_lock_irq(&priv->meth_lock); + + /* Try to reset the adaptor. */ + meth_reset(dev); + + priv->stats.tx_errors++; + + /* Clear all rings */ + meth_free_tx_ring(priv); + meth_free_rx_ring(priv); + meth_init_tx_ring(priv); + meth_init_rx_ring(priv); + + /* Restart dma */ + priv->regs->dma_ctrl|=METH_DMA_TX_EN|METH_DMA_RX_EN|METH_DMA_RX_INT_EN; + + /* Enable interrupt */ + spin_unlock_irq(&priv->meth_lock); + + dev->trans_start = jiffies; + netif_wake_queue(dev); + + return; +} + +/* + * Ioctl commands + */ +int meth_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + + DPRINTK("ioctl\n"); + return 0; +} + +/* + * Return statistics to the caller + */ +struct net_device_stats *meth_stats(struct net_device *dev) +{ + struct meth_private *priv = (struct meth_private *) dev->priv; + return &priv->stats; +} + +/* + * The init function (sometimes called probe). + * It is invoked by register_netdev() + */ +int meth_init(struct net_device *dev) +{ + meth_private *priv; + int ret; + /* + * Then, assign other fields in dev, using ether_setup() and some + * hand assignments + */ + ether_setup(dev); /* assign some of the fields */ + + dev->open = meth_open; + dev->stop = meth_release; + dev->set_config = meth_config; + dev->hard_start_xmit = meth_tx; + dev->do_ioctl = meth_ioctl; + dev->get_stats = meth_stats; +#ifdef HAVE_TX_TIMEOUT + dev->tx_timeout = meth_tx_timeout; + dev->watchdog_timeo = timeout; +#endif + dev->irq = MACE_ETHERNET_IRQ; + SET_MODULE_OWNER(dev); + + /* + * Then, allocate the priv field. This encloses the statistics + * and a few private fields. + */ + priv = kmalloc(sizeof(struct meth_private), GFP_KERNEL); + if (priv == NULL) + return -ENOMEM; + dev->priv=priv; + memset(priv, 0, sizeof(struct meth_private)); + spin_lock_init(&((struct meth_private *) dev->priv)->meth_lock); + /* + * Make the usual checks: check_region(), probe irq, ... -ENODEV + * should be returned if no device found. No resource should be + * grabbed: this is done on open(). + */ + priv->regs=(meth_regs*)SGI_MFE; + dev->base_addr=SGI_MFE; + priv->phy_addr = -1; /* No phy is known yet... */ + + /* Initialize the hardware */ + if((ret=meth_reset(dev)) < 0) + return ret; + + /* Allocate the ring buffers */ + if((ret=meth_init_tx_ring(priv))<0||(ret=meth_init_rx_ring(priv))<0){ + meth_free_tx_ring(priv); + meth_free_rx_ring(priv); + return ret; + } + + printk("SGI O2 Fast Ethernet rev. %ld\n", priv->regs->mac_ctrl >> 29); + + return 0; +} + +/* + * The devices + */ + +struct net_device meth_devs[1] = { + { init: meth_init, } /* init, nothing more */ +}; + +/* + * Finally, the module stuff + */ + +int meth_init_module(void) +{ + int result, device_present = 0; + + strcpy(meth_devs[0].name, "eth%d"); + + if ( (result = register_netdev(meth_devs)) ) + printk("meth: error %i registering device \"%s\"\n", + result, meth_devs->name); + else device_present++; +#ifndef METH_DEBUG + EXPORT_NO_SYMBOLS; +#endif + + return device_present ? 0 : -ENODEV; +} + +void meth_cleanup(void) +{ + kfree(meth_devs->priv); + unregister_netdev(meth_devs); + return; +} + +module_init(meth_init_module); +module_exit(meth_cleanup); diff -Nru a/drivers/net/meth.h b/drivers/net/meth.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/net/meth.h Tue Jul 1 18:44:40 2003 @@ -0,0 +1,273 @@ + +/* + * snull.h -- definitions for the network module + * + * Copyright (C) 2001 Alessandro Rubini and Jonathan Corbet + * Copyright (C) 2001 O'Reilly & Associates + * + * The source code in this file can be freely used, adapted, + * and redistributed in source or binary form, so long as an + * acknowledgment appears in derived source files. The citation + * should list that the code comes from the book "Linux Device + * Drivers" by Alessandro Rubini and Jonathan Corbet, published + * by O'Reilly & Associates. No warranty is attached; + * we cannot take responsibility for errors or fitness for use. + */ + +/* version dependencies have been confined to a separate file */ + +#define SGI_MFE (MACE_BASE+MACE_ENET) +/* (0xBF280000)*/ + +/* Tunable parameters */ +#define TX_RING_ENTRIES 64 /* 64-512?*/ + +#define RX_RING_ENTRIES 16 /* Do not change */ +/* Internal constants */ +#define TX_RING_BUFFER_SIZE (TX_RING_ENTRIES*sizeof(tx_packet)) +#define RX_BUFFER_SIZE 1546 /* ethenet packet size */ +#define METH_RX_BUFF_SIZE 4096 +#define RX_BUFFER_OFFSET (sizeof(rx_status_vector)+2) /* staus vector + 2 bytes of padding */ +#define RX_BUCKET_SIZE 256 + + + +/* For more detailed explanations of what each field menas, + see Nick's great comments to #defines below (or docs, if + you are lucky enough toget hold of them :)*/ + +/* tx status vector is written over tx command header upon + dma completion. */ + +typedef struct tx_status_vector { + u64 sent:1; /* always set to 1...*/ + u64 pad0:34;/* always set to 0 */ + u64 flags:9; /*I'm too lazy to specify each one separately at the moment*/ + u64 col_retry_cnt:4; /*collision retry count*/ + u64 len:16; /*Transmit length in bytes*/ +} tx_status_vector; + +/* + * Each packet is 128 bytes long. + * It consists of header, 0-3 concatination + * buffer pointers and up to 120 data bytes. + */ +typedef struct tx_packet_hdr { + u64 pad1:36; /*should be filled with 0 */ + u64 cat_ptr3_valid:1, /*Concatination pointer valid flags*/ + cat_ptr2_valid:1, + cat_ptr1_valid:1; + u64 tx_int_flag:1; /*Generate TX intrrupt when packet has been sent*/ + u64 term_dma_flag:1; /*Terminate transmit DMA on transmit abort conditions*/ + u64 data_offset:7; /*Starting byte offset in ring data block*/ + u64 data_len:16; /*Length of valid data in bytes-1*/ +} tx_packet_hdr; +typedef union tx_cat_ptr { + struct { + u64 pad2:16; /* should be 0 */ + u64 len:16; /*length of buffer data - 1*/ + u64 start_addr:29; /*Physical starting address*/ + u64 pad1:3; /* should be zero */ + } form; + u64 raw; +} tx_cat_ptr; + +typedef struct tx_packet { + union { + tx_packet_hdr header; + tx_status_vector res; + u64 raw; + }header; + union { + tx_cat_ptr cat_buf[3]; + char dt[120]; + } data; +} tx_packet; + +typedef union rx_status_vector { + struct { + u64 pad1:1;/*fill it with ones*/ + u64 pad2:15;/*fill with 0*/ + u64 ip_chk_sum:16; + u64 seq_num:5; + u64 mac_addr_match:1; + u64 mcast_addr_match:1; + u64 carrier_event_seen:1; + u64 bad_packet:1; + u64 long_event_seen:1; + u64 invalid_preamble:1; + u64 broadcast:1; + u64 multicast:1; + u64 crc_error:1; + u64 huh:1;/*???*/ + u64 rx_code_violation:1; + u64 rx_len:16; + } parsed; + u64 raw; +} rx_status_vector; + +typedef struct rx_packet { + rx_status_vector status; + u64 pad[3]; /* For whatever reason, there needs to be 4 double-word offset */ + u16 pad2; + char buf[METH_RX_BUFF_SIZE-sizeof(rx_status_vector)-3*sizeof(u64)-sizeof(u16)];/* data */ +} rx_packet; + +typedef struct meth_regs { + u64 mac_ctrl; /*0x00,rw,31:0*/ + u64 int_flags; /*0x08,rw,30:0*/ + u64 dma_ctrl; /*0x10,rw,15:0*/ + u64 timer; /*0x18,rw,5:0*/ + u64 int_tx; /*0x20,wo,0:0*/ + u64 int_rx; /*0x28,wo,9:4*/ + struct { + u32 tx_info_pad; + u32 rptr:16,wptr:16; + } tx_info; /*0x30,rw,31:0*/ + u64 tx_info_al; /*0x38,rw,31:0*/ + struct { + u32 rx_buff_pad1; + u32 rx_buff_pad2:8, + wptr:8, + rptr:8, + depth:8; + } rx_buff; /*0x40,ro,23:0*/ + u64 rx_buff_al1; /*0x48,ro,23:0*/ + u64 rx_buff_al2; /*0x50,ro,23:0*/ + u64 int_update; /*0x58,wo,31:0*/ + u32 phy_data_pad; + u32 phy_data; /*0x60,rw,16:0*/ + u32 phy_reg_pad; + u32 phy_registers; /*0x68,rw,9:0*/ + u64 phy_trans_go; /*0x70,wo,0:0*/ + u64 backoff_seed; /*0x78,wo,10:0*/ + u64 imq_reserved[4];/*0x80,ro,64:0(x4)*/ + /*===================================*/ + u64 mac_addr; /*0xA0,rw,47:0, I think it's MAC address, but I'm not sure*/ + u64 mcast_addr; /*0xA8,rw,47:0, This seems like secondary MAC address*/ + u64 mcast_filter; /*0xB0,rw,63:0*/ + u64 tx_ring_base; /*0xB8,rw,31:13*/ + /* Following are read-only debugging info register */ + u64 tx_pkt1_hdr; /*0xC0,ro,63:0*/ + u64 tx_pkt1_ptr[3]; /*0xC8,ro,63:0(x3)*/ + u64 tx_pkt2_hdr; /*0xE0,ro,63:0*/ + u64 tx_pkt2_ptr[3]; /*0xE8,ro,63:0(x3)*/ + /*===================================*/ + u32 rx_pad; + u32 rx_fifo; + u64 reserved[31]; +}meth_regs; + + /* Bits in METH_MAC */ + +#define SGI_MAC_RESET BIT(0) /* 0: MAC110 active in run mode, 1: Global reset signal to MAC110 core is active */ +#define METH_PHY_FDX BIT(1) /* 0: Disable full duplex, 1: Enable full duplex */ +#define METH_PHY_LOOP BIT(2) /* 0: Normal operation, follows 10/100mbit and M10T/MII select, 1: loops internal MII bus */ + /* selects ignored */ +#define METH_100MBIT BIT(3) /* 0: 10meg mode, 1: 100meg mode */ +#define METH_PHY_MII BIT(4) /* 0: MII selected, 1: SIA selected */ + /* Note: when loopback is set this bit becomes collision control. Setting this bit will */ + /* cause a collision to be reported. */ + + /* Bits 5 and 6 are used to determine the the Destination address filter mode */ +#define METH_ACCEPT_MY 0 /* 00: Accept PHY address only */ +#define METH_ACCEPT_MCAST 0x20 /* 01: Accept physical, broadcast, and multicast filter matches only */ +#define METH_ACCEPT_AMCAST 0x40 /* 10: Accept physical, broadcast, and all multicast packets */ +#define METH_PROMISC 0x60 /* 11: Promiscious mode */ + +#define METH_PHY_LINK_FAIL BIT(7) /* 0: Link failure detection disabled, 1: Hardware scans for link failure in PHY */ + +#define METH_MAC_IPG 0x1ffff00 + +#define METH_DEFAULT_IPG ((17<<15) | (11<<22) | (21<<8)) + /* 0x172e5c00 */ /* 23, 23, 23 */ /*0x54A9500 *//*21,21,21*/ + /* Bits 8 through 14 are used to determine Inter-Packet Gap between "Back to Back" packets */ + /* The gap depends on the clock speed of the link, 80ns per increment for 100baseT, 800ns */ + /* per increment for 10BaseT */ + + /* Bits 15 through 21 are used to determine IPGR1 */ + + /* Bits 22 through 28 are used to determine IPGR2 */ + +#define METH_REV_SHIFT 29 /* Bits 29 through 31 are used to determine the revision */ + /* 000: Inital revision */ + /* 001: First revision, Improved TX concatenation */ + + +/* DMA control bits */ +#define METH_RX_OFFSET_SHIFT 12 /* Bits 12:14 of DMA control register indicate starting offset of packet data for RX operation */ +#define METH_RX_DEPTH_SHIFT 4 /* Bits 8:4 define RX fifo depth -- when # of RX fifo entries != depth, interrupt is generted */ + +#define METH_DMA_TX_EN BIT(1) /* enable TX DMA */ +#define METH_DMA_TX_INT_EN BIT(0) /* enable TX Buffer Empty interrupt */ +#define METH_DMA_RX_EN BIT(15) /* Enable RX */ +#define METH_DMA_RX_INT_EN BIT(9) /* Enable interrupt on RX packet */ + + +/* RX status bits */ + +#define METH_RX_ST_RCV_CODE_VIOLATION BIT(16) +#define METH_RX_ST_DRBL_NBL BIT(17) +#define METH_RX_ST_CRC_ERR BIT(18) +#define METH_RX_ST_MCAST_PKT BIT(19) +#define METH_RX_ST_BCAST_PKT BIT(20) +#define METH_RX_ST_INV_PREAMBLE_CTX BIT(21) +#define METH_RX_ST_LONG_EVT_SEEN BIT(22) +#define METH_RX_ST_BAD_PACKET BIT(23) +#define METH_RX_ST_CARRIER_EVT_SEEN BIT(24) +#define METH_RX_ST_MCAST_FILTER_MATCH BIT(25) +#define METH_RX_ST_PHYS_ADDR_MATCH BIT(26) + +#define METH_RX_STATUS_ERRORS \ + ( \ + METH_RX_ST_RCV_CODE_VIOLATION| \ + METH_RX_ST_CRC_ERR| \ + METH_RX_ST_INV_PREAMBLE_CTX| \ + METH_RX_ST_LONG_EVT_SEEN| \ + METH_RX_ST_BAD_PACKET| \ + METH_RX_ST_CARRIER_EVT_SEEN \ + ) + /* Bits in METH_INT */ + /* Write _1_ to corresponding bit to clear */ +#define METH_INT_TX_EMPTY BIT(0) /* 0: No interrupt pending, 1: The TX ring buffer is empty */ +#define METH_INT_TX_PKT BIT(1) /* 0: No interrupt pending */ + /* 1: A TX message had the INT request bit set, the packet has been sent. */ +#define METH_INT_TX_LINK_FAIL BIT(2) /* 0: No interrupt pending, 1: PHY has reported a link failure */ +#define METH_INT_MEM_ERROR BIT(3) /* 0: No interrupt pending */ + /* 1: A memory error occurred durring DMA, DMA stopped, Fatal */ +#define METH_INT_TX_ABORT BIT(4) /* 0: No interrupt pending, 1: The TX aborted operation, DMA stopped, FATAL */ +#define METH_INT_RX_THRESHOLD BIT(5) /* 0: No interrupt pending, 1: Selected receive threshold condition Valid */ +#define METH_INT_RX_UNDERFLOW BIT(6) /* 0: No interrupt pending, 1: FIFO was empty, packet could not be queued */ +#define METH_INT_RX_OVERFLOW BIT(7) /* 0: No interrupt pending, 1: DMA FIFO Overflow, DMA stopped, FATAL */ + +#define METH_INT_RX_RPTR_MASK 0x0001F00 /* Bits 8 through 12 alias of RX read-pointer */ + + /* Bits 13 through 15 are always 0. */ + +#define METH_INT_TX_RPTR_MASK 0x1FF0000 /* Bits 16 through 24 alias of TX read-pointer */ + +#define METH_INT_SEQ_MASK 0x2E000000 /* Bits 25 through 29 are the starting seq number for the message at the */ + /* top of the queue */ + +#define METH_ERRORS ( \ + METH_INT_RX_OVERFLOW| \ + METH_INT_RX_UNDERFLOW| \ + METH_INT_MEM_ERROR| \ + METH_INT_TX_ABORT) + +#define METH_INT_MCAST_HASH BIT(30) /* If RX DMA is enabled the hash select logic output is latched here */ + +/* TX status bits */ +#define METH_TX_STATUS_DONE BIT(23) /* Packet was transmitted successfully */ + +/* Tx command header bits */ +#define METH_TX_CMD_INT_EN BIT(24) /* Generate TX interrupt when packet is sent */ + +/* Phy MDIO interface busy flag */ +#define MDIO_BUSY BIT(16) +#define MDIO_DATA_MASK 0xFFFF +/* PHY defines */ +#define PHY_QS6612X 0x0181441 /* Quality TX */ +#define PHY_ICS1889 0x0015F41 /* ICS FX */ +#define PHY_ICS1890 0x0015F42 /* ICS TX */ +#define PHY_DP83840 0x20005C0 /* National TX */ diff -Nru a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c --- a/drivers/net/pcmcia/3c574_cs.c Tue Jul 1 18:44:33 2003 +++ b/drivers/net/pcmcia/3c574_cs.c Tue Jul 1 18:44:33 2003 @@ -211,7 +211,6 @@ struct el3_private { dev_link_t link; - struct net_device dev; dev_node_t node; struct net_device_stats stats; u16 advertising, partner; /* NWay media advertisement */ @@ -291,13 +290,12 @@ flush_stale_links(); /* Create the PC card device object. */ - lp = kmalloc(sizeof(*lp), GFP_KERNEL); - if (!lp) + dev = alloc_etherdev(sizeof(struct el3_private)); + if (!dev) return NULL; - - memset(lp, 0, sizeof(*lp)); - link = &lp->link; dev = &lp->dev; - link->priv = dev->priv = link->irq.Instance = lp; + lp = dev->priv; + link = &lp->link; + link->priv = dev; init_timer(&link->release); link->release.function = &tc574_release; @@ -312,6 +310,7 @@ for (i = 0; i < 4; i++) link->irq.IRQInfo2 |= 1 << irq_list[i]; link->irq.Handler = &el3_interrupt; + link->irq.Instance = dev; link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; @@ -323,7 +322,6 @@ dev->get_stats = &el3_get_stats; dev->do_ioctl = &el3_ioctl; dev->set_multicast_list = &set_rx_mode; - ether_setup(dev); dev->open = &el3_open; dev->stop = &el3_close; #ifdef HAVE_TX_TIMEOUT @@ -364,7 +362,7 @@ static void tc574_detach(dev_link_t *link) { - struct el3_private *lp = link->priv; + struct net_device *dev = link->priv; dev_link_t **linkp; DEBUG(0, "3c574_detach(0x%p)\n", link); @@ -390,8 +388,8 @@ /* Unlink device structure, free bits */ *linkp = link->next; if (link->dev) - unregister_netdev(&lp->dev); - kfree(lp); + unregister_netdev(dev); + kfree(dev); } /* tc574_detach */ @@ -407,8 +405,8 @@ static void tc574_config(dev_link_t *link) { client_handle_t handle = link->handle; - struct el3_private *lp = link->priv; - struct net_device *dev = &lp->dev; + struct net_device *dev = link->priv; + struct el3_private *lp = dev->priv; tuple_t tuple; cisparse_t parse; unsigned short buf[32]; @@ -599,8 +597,7 @@ event_callback_args_t *args) { dev_link_t *link = args->client_data; - struct el3_private *lp = link->priv; - struct net_device *dev = &lp->dev; + struct net_device *dev = link->priv; DEBUG(1, "3c574_event(0x%06x)\n", event); @@ -856,7 +853,7 @@ tc574_reset(dev); lp->media.function = &media_check; - lp->media.data = (unsigned long)lp; + lp->media.data = (unsigned long) dev; lp->media.expires = jiffies + HZ; add_timer(&lp->media); @@ -939,8 +936,8 @@ /* The EL3 interrupt handler. */ static irqreturn_t el3_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - struct el3_private *lp = dev_id; - struct net_device *dev = &lp->dev; + struct net_device *dev = (struct net_device *) dev_id; + struct el3_private *lp = dev->priv; ioaddr_t ioaddr, status; int work_budget = max_interrupt_work; int handled = 0; @@ -1032,8 +1029,8 @@ */ static void media_check(unsigned long arg) { - struct el3_private *lp = (struct el3_private *)arg; - struct net_device *dev = &lp->dev; + struct net_device *dev = (struct net_device *) arg; + struct el3_private *lp = dev->priv; ioaddr_t ioaddr = dev->base_addr; unsigned long flags; unsigned short /* cable, */ media, partner; diff -Nru a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c --- a/drivers/net/pcmcia/3c589_cs.c Tue Jul 1 18:44:38 2003 +++ b/drivers/net/pcmcia/3c589_cs.c Tue Jul 1 18:44:38 2003 @@ -106,7 +106,6 @@ struct el3_private { dev_link_t link; - struct net_device dev; dev_node_t node; struct net_device_stats stats; /* For transceiver monitoring */ @@ -213,14 +212,14 @@ flush_stale_links(); /* Create new ethernet device */ - lp = kmalloc(sizeof(*lp), GFP_KERNEL); - if (!lp) return NULL; - memset(lp, 0, sizeof(*lp)); + dev = alloc_etherdev(sizeof(struct el3_private)); + if (!dev) + return NULL; + lp = dev->priv; + link = &lp->link; + link->priv = dev; + spin_lock_init(&lp->lock); - - link = &lp->link; dev = &lp->dev; - link->priv = dev->priv = link->irq.Instance = lp; - init_timer(&link->release); link->release.function = &tc589_release; link->release.data = (unsigned long)link; @@ -234,6 +233,7 @@ for (i = 0; i < 4; i++) link->irq.IRQInfo2 |= 1 << irq_list[i]; link->irq.Handler = &el3_interrupt; + link->irq.Instance = dev; link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; @@ -246,7 +246,6 @@ dev->set_config = &el3_config; dev->get_stats = &el3_get_stats; dev->set_multicast_list = &set_multicast_list; - ether_setup(dev); dev->open = &el3_open; dev->stop = &el3_close; #ifdef HAVE_TX_TIMEOUT @@ -288,7 +287,7 @@ static void tc589_detach(dev_link_t *link) { - struct el3_private *lp = link->priv; + struct net_device *dev = link->priv; dev_link_t **linkp; DEBUG(0, "3c589_detach(0x%p)\n", link); @@ -314,8 +313,8 @@ /* Unlink device structure, free bits */ *linkp = link->next; if (link->dev) - unregister_netdev(&lp->dev); - kfree(lp); + unregister_netdev(dev); + kfree(dev); } /* tc589_detach */ @@ -333,8 +332,8 @@ static void tc589_config(dev_link_t *link) { client_handle_t handle = link->handle; - struct el3_private *lp = link->priv; - struct net_device *dev = &lp->dev; + struct net_device *dev = link->priv; + struct el3_private *lp = dev->priv; tuple_t tuple; cisparse_t parse; u16 buf[32], *phys_addr; @@ -487,8 +486,7 @@ event_callback_args_t *args) { dev_link_t *link = args->client_data; - struct el3_private *lp = link->priv; - struct net_device *dev = &lp->dev; + struct net_device *dev = link->priv; DEBUG(1, "3c589_event(0x%06x)\n", event); @@ -738,7 +736,7 @@ tc589_reset(dev); init_timer(&lp->media); lp->media.function = &media_check; - lp->media.data = (unsigned long)lp; + lp->media.data = (unsigned long) dev; lp->media.expires = jiffies + HZ; add_timer(&lp->media); @@ -818,8 +816,8 @@ /* The EL3 interrupt handler. */ static irqreturn_t el3_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - struct el3_private *lp = dev_id; - struct net_device *dev = &lp->dev; + struct net_device *dev = (struct net_device *) dev_id; + struct el3_private *lp = dev->priv; ioaddr_t ioaddr, status; int i = 0, handled = 1; @@ -903,8 +901,8 @@ static void media_check(unsigned long arg) { - struct el3_private *lp = (struct el3_private *)(arg); - struct net_device *dev = &lp->dev; + struct net_device *dev = (struct net_device *)(arg); + struct el3_private *lp = dev->priv; ioaddr_t ioaddr = dev->base_addr; u16 media, errs; unsigned long flags; diff -Nru a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c --- a/drivers/net/pcmcia/fmvj18x_cs.c Tue Jul 1 18:44:36 2003 +++ b/drivers/net/pcmcia/fmvj18x_cs.c Tue Jul 1 18:44:36 2003 @@ -130,7 +130,6 @@ */ typedef struct local_info_t { dev_link_t link; - struct net_device dev; dev_node_t node; struct net_device_stats stats; long open_time; @@ -273,11 +272,12 @@ flush_stale_links(); /* Make up a FMVJ18x specific data structure */ - lp = kmalloc(sizeof(*lp), GFP_KERNEL); - if (!lp) return NULL; - memset(lp, 0, sizeof(*lp)); - link = &lp->link; dev = &lp->dev; - link->priv = dev->priv = link->irq.Instance = lp; + dev = alloc_etherdev(sizeof(local_info_t)); + if (!dev) + return NULL; + lp = dev->priv; + link = &lp->link; + link->priv = dev; init_timer(&link->release); link->release.function = &fmvj18x_release; @@ -297,6 +297,7 @@ for (i = 0; i < 4; i++) link->irq.IRQInfo2 |= 1 << irq_list[i]; link->irq.Handler = &fjn_interrupt; + link->irq.Instance = dev; /* General socket configuration */ link->conf.Attributes = CONF_ENABLE_IRQ; @@ -309,7 +310,6 @@ dev->set_config = &fjn_config; dev->get_stats = &fjn_get_stats; dev->set_multicast_list = &set_rx_mode; - ether_setup(dev); dev->open = &fjn_open; dev->stop = &fjn_close; #ifdef HAVE_TX_TIMEOUT @@ -344,7 +344,7 @@ static void fmvj18x_detach(dev_link_t *link) { - local_info_t *lp = link->priv; + struct net_device *dev = link->priv; dev_link_t **linkp; DEBUG(0, "fmvj18x_detach(0x%p)\n", link); @@ -371,8 +371,8 @@ /* Unlink device structure, free pieces */ *linkp = link->next; if (link->dev) - unregister_netdev(&lp->dev); - kfree(lp); + unregister_netdev(dev); + kfree(dev); } /* fmvj18x_detach */ @@ -423,8 +423,8 @@ static void fmvj18x_config(dev_link_t *link) { client_handle_t handle = link->handle; - local_info_t *lp = link->priv; - struct net_device *dev = &lp->dev; + struct net_device *dev = link->priv; + local_info_t *lp = dev->priv; tuple_t tuple; cisparse_t parse; u_short buf[32]; @@ -704,8 +704,7 @@ memreq_t mem; u_char *base; int i, j; - local_info_t *lp = link->priv; - struct net_device *dev = &lp->dev; + struct net_device *dev = link->priv; ioaddr_t ioaddr; /* Allocate a small memory window */ @@ -776,8 +775,7 @@ event_callback_args_t *args) { dev_link_t *link = args->client_data; - local_info_t *lp = link->priv; - struct net_device *dev = &lp->dev; + struct net_device *dev = link->priv; DEBUG(1, "fmvj18x_event(0x%06x)\n", event); @@ -847,8 +845,8 @@ static irqreturn_t fjn_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - local_info_t *lp = dev_id; - struct net_device *dev = &lp->dev; + struct net_device *dev = dev_id; + local_info_t *lp = dev->priv; ioaddr_t ioaddr; unsigned short tx_stat, rx_stat; diff -Nru a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c --- a/drivers/net/pcmcia/nmclan_cs.c Tue Jul 1 18:44:32 2003 +++ b/drivers/net/pcmcia/nmclan_cs.c Tue Jul 1 18:44:32 2003 @@ -359,7 +359,6 @@ typedef struct _mace_private { dev_link_t link; - struct net_device dev; dev_node_t node; struct net_device_stats linux_stats; /* Linux statistics counters */ mace_statistics mace_stats; /* MACE chip statistics counters */ @@ -476,12 +475,13 @@ flush_stale_links(); /* Create new ethernet device */ - lp = kmalloc(sizeof(*lp), GFP_KERNEL); - if (!lp) return NULL; - memset(lp, 0, sizeof(*lp)); - link = &lp->link; dev = &lp->dev; - link->priv = dev->priv = link->irq.Instance = lp; - + dev = alloc_etherdev(sizeof(mace_private)); + if (!dev) + return NULL; + lp = dev->priv; + link = &lp->link; + link->priv = dev; + init_timer(&link->release); link->release.function = &nmclan_release; link->release.data = (u_long)link; @@ -496,6 +496,7 @@ for (i = 0; i < 4; i++) link->irq.IRQInfo2 |= 1 << irq_list[i]; link->irq.Handler = &mace_interrupt; + link->irq.Instance = dev; link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; @@ -510,7 +511,6 @@ dev->get_stats = &mace_get_stats; dev->set_multicast_list = &set_multicast_list; dev->do_ioctl = &mace_ioctl; - ether_setup(dev); dev->open = &mace_open; dev->stop = &mace_close; #ifdef HAVE_TX_TIMEOUT @@ -550,7 +550,7 @@ static void nmclan_detach(dev_link_t *link) { - mace_private *lp = link->priv; + struct net_device *dev = link->priv; dev_link_t **linkp; DEBUG(0, "nmclan_detach(0x%p)\n", link); @@ -576,8 +576,8 @@ /* Unlink device structure, free bits */ *linkp = link->next; if (link->dev) - unregister_netdev(&lp->dev); - kfree(lp); + unregister_netdev(dev); + kfree(dev); } /* nmclan_detach */ @@ -710,8 +710,8 @@ static void nmclan_config(dev_link_t *link) { client_handle_t handle = link->handle; - mace_private *lp = link->priv; - struct net_device *dev = &lp->dev; + struct net_device *dev = link->priv; + mace_private *lp = dev->priv; tuple_t tuple; cisparse_t parse; u_char buf[64]; @@ -836,8 +836,7 @@ event_callback_args_t *args) { dev_link_t *link = args->client_data; - mace_private *lp = link->priv; - struct net_device *dev = &lp->dev; + struct net_device *dev = link->priv; DEBUG(1, "nmclan_event(0x%06x)\n", event); @@ -1145,8 +1144,8 @@ ---------------------------------------------------------------------------- */ static irqreturn_t mace_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - mace_private *lp = (mace_private *)dev_id; - struct net_device *dev = &lp->dev; + struct net_device *dev = (struct net_device *) dev_id; + mace_private *lp = dev->priv; ioaddr_t ioaddr = dev->base_addr; int status; int IntrCnt = MACE_MAX_IR_ITERATIONS; diff -Nru a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c --- a/drivers/net/pcmcia/smc91c92_cs.c Tue Jul 1 18:44:36 2003 +++ b/drivers/net/pcmcia/smc91c92_cs.c Tue Jul 1 18:44:36 2003 @@ -113,7 +113,6 @@ struct smc_private { dev_link_t link; - struct net_device dev; spinlock_t lock; u_short manfid; u_short cardid; @@ -344,10 +343,13 @@ flush_stale_links(); /* Create new ethernet device */ - smc = kmalloc(sizeof(struct smc_private), GFP_KERNEL); - if (!smc) return NULL; - memset(smc, 0, sizeof(struct smc_private)); - link = &smc->link; dev = &smc->dev; + dev = alloc_etherdev(sizeof(struct smc_private)); + if (!dev) + return NULL; + smc = dev->priv; + link = &smc->link; + link->priv = dev; + spin_lock_init(&smc->lock); init_timer(&link->release); link->release.function = &smc91c92_release; @@ -363,6 +365,7 @@ for (i = 0; i < 4; i++) link->irq.IRQInfo2 |= 1 << irq_list[i]; link->irq.Handler = &smc_interrupt; + link->irq.Instance = dev; link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; @@ -373,7 +376,6 @@ dev->get_stats = &smc_get_stats; dev->set_config = &s9k_config; dev->set_multicast_list = &set_rx_mode; - ether_setup(dev); dev->open = &smc_open; dev->stop = &smc_close; dev->do_ioctl = &smc_ioctl; @@ -381,7 +383,6 @@ dev->tx_timeout = smc_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; #endif - dev->priv = link->priv = link->irq.Instance = smc; smc->mii_if.dev = dev; smc->mii_if.mdio_read = mdio_read; @@ -421,7 +422,7 @@ static void smc91c92_detach(dev_link_t *link) { - struct smc_private *smc = link->priv; + struct net_device *dev = link->priv; dev_link_t **linkp; DEBUG(0, "smc91c92_detach(0x%p)\n", link); @@ -447,8 +448,8 @@ /* Unlink device structure, free bits */ *linkp = link->next; if (link->dev) - unregister_netdev(&smc->dev); - kfree(smc); + unregister_netdev(dev); + kfree(dev); } /* smc91c92_detach */ @@ -502,7 +503,8 @@ static int mhz_3288_power(dev_link_t *link) { - struct smc_private *smc = link->priv; + struct net_device *dev = link->priv; + struct smc_private *smc = dev->priv; u_char tmp; /* Read the ISR twice... */ @@ -523,8 +525,8 @@ static int mhz_mfc_config(dev_link_t *link) { - struct smc_private *smc = link->priv; - struct net_device *dev = &smc->dev; + struct net_device *dev = link->priv; + struct smc_private *smc = dev->priv; tuple_t tuple; cisparse_t parse; u_char buf[255]; @@ -590,8 +592,7 @@ static int mhz_setup(dev_link_t *link) { client_handle_t handle = link->handle; - struct smc_private *smc = link->priv; - struct net_device *dev = &smc->dev; + struct net_device *dev = link->priv; tuple_t tuple; cisparse_t parse; u_char buf[255], *station_addr; @@ -638,8 +639,8 @@ static void mot_config(dev_link_t *link) { - struct smc_private *smc = link->priv; - struct net_device *dev = &smc->dev; + struct net_device *dev = link->priv; + struct smc_private *smc = dev->priv; ioaddr_t ioaddr = dev->base_addr; ioaddr_t iouart = link->io.BasePort2; @@ -659,8 +660,7 @@ static int mot_setup(dev_link_t *link) { - struct smc_private *smc = link->priv; - struct net_device *dev = &smc->dev; + struct net_device *dev = link->priv; ioaddr_t ioaddr = dev->base_addr; int i, wait, loop; u_int addr; @@ -694,8 +694,7 @@ static int smc_config(dev_link_t *link) { - struct smc_private *smc = link->priv; - struct net_device *dev = &smc->dev; + struct net_device *dev = link->priv; tuple_t tuple; cisparse_t parse; u_char buf[255]; @@ -727,8 +726,7 @@ static int smc_setup(dev_link_t *link) { client_handle_t handle = link->handle; - struct smc_private *smc = link->priv; - struct net_device *dev = &smc->dev; + struct net_device *dev = link->priv; tuple_t tuple; cisparse_t parse; cistpl_lan_node_id_t *node_id; @@ -755,7 +753,6 @@ return 0; } } - /* Try the third string in the Version 1 Version/ID tuple. */ tuple.DesiredTuple = CISTPL_VERS_1; if (first_tuple(handle, &tuple, &parse) != CS_SUCCESS) @@ -771,8 +768,7 @@ static int osi_config(dev_link_t *link) { - struct smc_private *smc = link->priv; - struct net_device *dev = &smc->dev; + struct net_device *dev = link->priv; static ioaddr_t com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 }; int i, j; @@ -806,8 +802,7 @@ static int osi_setup(dev_link_t *link, u_short manfid, u_short cardid) { client_handle_t handle = link->handle; - struct smc_private *smc = link->priv; - struct net_device *dev = &smc->dev; + struct net_device *dev = link->priv; tuple_t tuple; u_char buf[255]; int i; @@ -862,8 +857,7 @@ static int check_sig(dev_link_t *link) { - struct smc_private *smc = link->priv; - struct net_device *dev = &smc->dev; + struct net_device *dev = link->priv; ioaddr_t ioaddr = dev->base_addr; int width; u_short s; @@ -921,8 +915,8 @@ static void smc91c92_config(dev_link_t *link) { client_handle_t handle = link->handle; - struct smc_private *smc = link->priv; - struct net_device *dev = &smc->dev; + struct net_device *dev = link->priv; + struct smc_private *smc = dev->priv; tuple_t tuple; cisparse_t parse; u_short buf[32]; @@ -1090,7 +1084,6 @@ static void smc91c92_release(u_long arg) { dev_link_t *link = (dev_link_t *)arg; - struct smc_private *smc = link->priv; DEBUG(0, "smc91c92_release(0x%p)\n", link); @@ -1105,6 +1098,8 @@ CardServices(ReleaseIO, link->handle, &link->io); CardServices(ReleaseIRQ, link->handle, &link->irq); if (link->win) { + struct net_device *dev = link->priv; + struct smc_private *smc = dev->priv; iounmap(smc->base); CardServices(ReleaseWindow, link->win); } @@ -1126,8 +1121,8 @@ event_callback_args_t *args) { dev_link_t *link = args->client_data; - struct smc_private *smc = link->priv; - struct net_device *dev = &smc->dev; + struct net_device *dev = link->priv; + struct smc_private *smc = dev->priv; int i; DEBUG(1, "smc91c92_event(0x%06x)\n", event); @@ -1302,7 +1297,7 @@ smc_reset(dev); init_timer(&smc->media); smc->media.function = &media_check; - smc->media.data = (u_long)smc; + smc->media.data = (u_long) dev; smc->media.expires = jiffies + HZ; add_timer(&smc->media); @@ -1576,8 +1571,8 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - struct smc_private *smc = dev_id; - struct net_device *dev = &smc->dev; + struct net_device *dev = dev_id; + struct smc_private *smc = dev->priv; ioaddr_t ioaddr; u_short saved_bank, saved_pointer, mask, status; unsigned int handled = 1; @@ -1967,8 +1962,8 @@ static void media_check(u_long arg) { - struct smc_private *smc = (struct smc_private *)(arg); - struct net_device *dev = &smc->dev; + struct net_device *dev = (struct net_device *) arg; + struct smc_private *smc = dev->priv; ioaddr_t ioaddr = dev->base_addr; u_short i, media, saved_bank; u_short link; diff -Nru a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c --- a/drivers/net/ppp_generic.c Tue Jul 1 18:44:38 2003 +++ b/drivers/net/ppp_generic.c Tue Jul 1 18:44:38 2003 @@ -1352,7 +1352,7 @@ kfree_skb(skb); return; } - + proto = PPP_PROTO(skb); read_lock_bh(&pch->upl); if (pch->ppp == 0 || proto >= 0xc000 || proto == PPP_CCPFRAG) { @@ -1446,6 +1446,7 @@ /* decompress VJ compressed packets */ if (ppp->vj == 0 || (ppp->flags & SC_REJ_COMP_TCP)) goto err; + if (skb_tailroom(skb) < 124) { /* copy to a new sk_buff with more tailroom */ ns = dev_alloc_skb(skb->len + 128); @@ -1458,6 +1459,9 @@ kfree_skb(skb); skb = ns; } + else if (!pskb_may_pull(skb, skb->len)) + goto err; + len = slhc_uncompress(ppp->vj, skb->data + 2, skb->len - 2); if (len <= 0) { printk(KERN_DEBUG "PPP: VJ decompression error\n"); @@ -1474,6 +1478,13 @@ case PPP_VJC_UNCOMP: if (ppp->vj == 0 || (ppp->flags & SC_REJ_COMP_TCP)) goto err; + + /* Until we fix the decompressor need to make sure + * data portion is linear. + */ + if (!pskb_may_pull(skb, skb->len)) + goto err; + if (slhc_remember(ppp->vj, skb->data + 2, skb->len - 2) <= 0) { printk(KERN_ERR "PPP: VJ uncompressed error\n"); goto err; @@ -1551,6 +1562,12 @@ struct sk_buff *ns; int len; + /* Until we fix all the decompressor's need to make sure + * data portion is linear. + */ + if (!pskb_may_pull(skb, skb->len)) + goto err; + if (proto == PPP_COMP) { ns = dev_alloc_skb(ppp->mru + PPP_HDRLEN); if (ns == 0) { @@ -1603,7 +1620,7 @@ struct list_head *l; int mphdrlen = (ppp->flags & SC_MP_SHORTSEQ)? MPHDRLEN_SSN: MPHDRLEN; - if (skb->len < mphdrlen + 1 || ppp->mrru == 0) + if (!pskb_may_pull(skb, mphdrlen + 1) || ppp->mrru == 0) goto err; /* no good, throw it away */ /* Decode sequence number and begin/end bits */ @@ -2018,12 +2035,12 @@ static void ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound) { - unsigned char *dp = skb->data + 2; + unsigned char *dp; int len; - if (skb->len < CCP_HDRLEN + 2 - || skb->len < (len = CCP_LENGTH(dp)) + 2) - return; /* too short */ + if (!pskb_may_pull(skb, CCP_HDRLEN + 2)) + return; /* no header */ + dp = skb->data + 2; switch (CCP_CODE(dp)) { case CCP_CONFREQ: @@ -2056,6 +2073,8 @@ case CCP_CONFACK: if ((ppp->flags & (SC_CCP_OPEN | SC_CCP_UP)) != SC_CCP_OPEN) break; + if (!pskb_may_pull(skb, len = CCP_LENGTH(dp)) + 2) + return; /* too short */ dp += CCP_HDRLEN; len -= CCP_HDRLEN; if (len < CCP_OPT_MINLEN || len < CCP_OPT_LENGTH(dp)) diff -Nru a/drivers/net/pppoe.c b/drivers/net/pppoe.c --- a/drivers/net/pppoe.c Tue Jul 1 18:44:36 2003 +++ b/drivers/net/pppoe.c Tue Jul 1 18:44:36 2003 @@ -77,27 +77,14 @@ #include -static int __attribute__((unused)) pppoe_debug = 7; #define PPPOE_HASH_BITS 4 #define PPPOE_HASH_SIZE (1<sk_state & PPPOX_BOUND) { + struct pppoe_hdr *ph = (struct pppoe_hdr *) skb->nh.raw; + int len = ntohs(ph->length); skb_pull(skb, sizeof(struct pppoe_hdr)); + skb_trim(skb, len); + ppp_input(&po->chan, skb); } else if (sk->sk_state & PPPOX_RELAY) { relay_po = get_item_by_addr(&po->pppoe_relay); @@ -361,7 +349,7 @@ goto abort_put; skb_pull(skb, sizeof(struct pppoe_hdr)); - if (!__pppoe_xmit( relay_po->sk , skb)) + if (!__pppoe_xmit( relay_po->sk, skb)) goto abort_put; } else { sock_queue_rcv_skb(sk, skb); @@ -387,17 +375,22 @@ struct packet_type *pt) { - struct pppoe_hdr *ph = (struct pppoe_hdr *) skb->nh.raw; + struct pppoe_hdr *ph; struct pppox_opt *po; - struct sock *sk ; + struct sock *sk; int ret; - po = get_item((unsigned long) ph->sid, skb->mac.ethernet->h_source); + if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr))) + goto drop; - if (!po) { - kfree_skb(skb); - return NET_RX_DROP; - } + if (!(skb = skb_share_check(skb, GFP_ATOMIC))) + goto out; + + ph = (struct pppoe_hdr *) skb->nh.raw; + + po = get_item((unsigned long) ph->sid, skb->mac.ethernet->h_source); + if (!po) + goto drop; sk = po->sk; bh_lock_sock(sk); @@ -414,6 +407,10 @@ sock_put(sk); return ret; +drop: + kfree_skb(skb); +out: + return NET_RX_DROP; } /************************************************************************ @@ -427,9 +424,16 @@ struct packet_type *pt) { - struct pppoe_hdr *ph = (struct pppoe_hdr *) skb->nh.raw; + struct pppoe_hdr *ph; struct pppox_opt *po; + if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr))) + goto abort; + + if (!(skb = skb_share_check(skb, GFP_ATOMIC))) + goto out; + + ph = (struct pppoe_hdr *) skb->nh.raw; if (ph->code != PADT_CODE) goto abort; @@ -457,17 +461,20 @@ abort: kfree_skb(skb); +out: return NET_RX_SUCCESS; /* Lies... :-) */ } -struct packet_type pppoes_ptype = { +static struct packet_type pppoes_ptype = { .type = __constant_htons(ETH_P_PPP_SES), .func = pppoe_rcv, + .data = (void *)1, }; -struct packet_type pppoed_ptype = { +static struct packet_type pppoed_ptype = { .type = __constant_htons(ETH_P_PPP_DISC), .func = pppoe_disc_rcv, + .data = (void *)1, }; /*********************************************************************** @@ -522,7 +529,7 @@ goto out; } -int pppoe_release(struct socket *sock) +static int pppoe_release(struct socket *sock) { struct sock *sk = sock->sk; struct pppox_opt *po; @@ -559,7 +566,7 @@ } -int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr, +static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr, int sockaddr_len, int flags) { struct sock *sk = sock->sk; @@ -648,7 +655,7 @@ } -int pppoe_getname(struct socket *sock, struct sockaddr *uaddr, +static int pppoe_getname(struct socket *sock, struct sockaddr *uaddr, int *usockaddr_len, int peer) { int len = sizeof(struct sockaddr_pppox); @@ -667,7 +674,7 @@ } -int pppoe_ioctl(struct socket *sock, unsigned int cmd, +static int pppoe_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) { struct sock *sk = sock->sk; @@ -769,7 +776,7 @@ } -int pppoe_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, +static int pppoe_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, int total_len) { struct sk_buff *skb = NULL; @@ -847,7 +854,7 @@ * xmit function for internal use. * ***********************************************************************/ -int __pppoe_xmit(struct sock *sk, struct sk_buff *skb) +static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb) { struct pppox_opt *po = pppox_sk(sk); struct net_device *dev = po->pppoe_dev; @@ -921,16 +928,18 @@ * sends PPP frame over PPPoE socket * ***********************************************************************/ -int pppoe_xmit(struct ppp_channel *chan, struct sk_buff *skb) +static int pppoe_xmit(struct ppp_channel *chan, struct sk_buff *skb) { struct sock *sk = (struct sock *) chan->private; return __pppoe_xmit(sk, skb); } -struct ppp_channel_ops pppoe_chan_ops = { pppoe_xmit , NULL }; +static struct ppp_channel_ops pppoe_chan_ops = { + .start_xmit = pppoe_xmit, +}; -int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock, +static int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *m, int total_len, int flags) { struct sock *sk = sock->sk; @@ -1029,8 +1038,9 @@ goto out; } po = v; - po = po->next; - if (!po) { + if (po->next) + po = po->next; + else { int hash = hash_item(po->pppoe_pa.sid, po->pppoe_pa.remote); while (++hash < PPPOE_HASH_SIZE) { @@ -1071,7 +1081,7 @@ /* ->ioctl are set at pppox_create */ -struct proto_ops pppoe_ops = { +static struct proto_ops pppoe_ops = { .family = AF_PPPOX, .owner = THIS_MODULE, .release = pppoe_release, @@ -1090,14 +1100,14 @@ .mmap = sock_no_mmap }; -struct pppox_proto pppoe_proto = { +static struct pppox_proto pppoe_proto = { .create = pppoe_create, .ioctl = pppoe_ioctl, .owner = THIS_MODULE, }; -int __init pppoe_init(void) +static int __init pppoe_init(void) { int err = register_pppox_proto(PX_PROTO_OE, &pppoe_proto); @@ -1125,7 +1135,7 @@ goto out; } -void __exit pppoe_exit(void) +static void __exit pppoe_exit(void) { unregister_pppox_proto(PX_PROTO_OE); dev_remove_pack(&pppoes_ptype); diff -Nru a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c --- a/drivers/net/sb1250-mac.c Tue Jul 1 18:44:38 2003 +++ b/drivers/net/sb1250-mac.c Tue Jul 1 18:44:38 2003 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001 Broadcom Corporation + * Copyright (C) 2001,2002,2003 Broadcom Corporation * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -17,17 +17,21 @@ */ /* - This driver is designed for the Broadcom BCM12500 SOC chip's built-in + This driver is designed for the Broadcom SiByte SOC built-in Ethernet controllers. - The author may be reached as mpl@broadcom.com + Written by Mitch Lichtenberg at Broadcom Corp. */ + +#define CONFIG_SBMAC_COALESCE + /* A few user-configurable values. These may be modified when a driver module is loaded. */ static int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */ +static int noisy_mii = 1; /* mii status msgs */ /* Used to pass the media type, etc. Both 'options[]' and 'full_duplex[]' should exist for driver @@ -41,6 +45,10 @@ static int full_duplex[MAX_UNITS] = {-1, -1, -1}; #endif +#ifdef CONFIG_SBMAC_COALESCE +static int int_pktcnt = 0; +static int int_timeout = 0; +#endif /* Operational parameters that usually are not changed. */ @@ -59,22 +67,21 @@ #include #include #include +#include #include #include #include #include -#include #include #include #include /* Processor type for cache alignment. */ #include #include -#include -#include +#include /* This is only here until the firmware is ready. In that case, the firmware leaves the ethernet address in the register for us. */ -#ifdef CONFIG_SWARM_STANDALONE +#ifdef CONFIG_SIBYTE_STANDALONE #define SBMAC_ETH0_HWADDR "40:00:00:00:01:00" #define SBMAC_ETH1_HWADDR "40:00:00:00:01:01" #define SBMAC_ETH2_HWADDR "40:00:00:00:01:02" @@ -84,23 +91,29 @@ /* These identify the driver base version and may not be removed. */ #if 0 static char version1[] __devinitdata = -"sb1250-mac.c:1.00 1/11/2001 Written by Mitch Lichtenberg (mpl@broadcom.com)\n"; +"sb1250-mac.c:1.00 1/11/2001 Written by Mitch Lichtenberg\n"; #endif -MODULE_AUTHOR("Mitch Lichtenberg (mpl@broadcom.com)"); -MODULE_DESCRIPTION("Broadcom BCM12500 SOC GB Ethernet driver"); +MODULE_AUTHOR("Mitch Lichtenberg (Broadcom Corp.)"); +MODULE_DESCRIPTION("Broadcom SiByte SOC GB Ethernet driver"); MODULE_PARM(debug, "i"); +MODULE_PARM(noisy_mii, "i"); MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); +MODULE_PARM(int_pktcnt, "i"); +MODULE_PARM(int_timeout, "i"); +#include #include #include #include #include #include +#include +#include /********************************************************************** @@ -109,8 +122,6 @@ typedef unsigned long sbmac_port_t; -typedef uint64_t sbmac_physaddr_t; -typedef uint64_t sbmac_enetaddr_t; typedef enum { sbmac_speed_auto, sbmac_speed_10, sbmac_speed_100, sbmac_speed_1000 } sbmac_speed_t; @@ -134,24 +145,19 @@ (d)->sbdma_dscrtable : (d)->f+1) -#define CACHELINESIZE 32 -#define NUMCACHEBLKS(x) (((x)+CACHELINESIZE-1)/CACHELINESIZE) -#define KMALLOC(x) kmalloc((x),GFP_KERNEL) -#define KFREE(x) kfree(x) -#define KVTOPHYS(x) virt_to_bus((void *)(x)) +#define NUMCACHEBLKS(x) (((x)+SMP_CACHE_BYTES-1)/SMP_CACHE_BYTES) +#define SBMAC_READCSR(t) in64((unsigned long)t) +#define SBMAC_WRITECSR(t,v) out64(v, (unsigned long)t) -#define SBMAC_READCSR(t) (in64((unsigned long)(t))) -#define SBMAC_WRITECSR(t,v) (out64(v, (unsigned long)(t))) - -#define PKSEG1(x) ((sbmac_port_t) KSEG1ADDR(x)) #define SBMAC_MAX_TXDESCR 32 #define SBMAC_MAX_RXDESCR 32 #define ETHER_ALIGN 2 #define ETHER_ADDR_LEN 6 -#define ENET_PACKET_SIZE 1518 +#define ENET_PACKET_SIZE 1518 +/*#define ENET_PACKET_SIZE 9216 */ /********************************************************************** * DMA Descriptor structure @@ -163,7 +169,6 @@ } sbdmadscr_t; typedef unsigned long paddr_t; -typedef unsigned long vaddr_t; /********************************************************************** * DMA Controller structure @@ -178,8 +183,13 @@ struct sbmac_softc *sbdma_eth; /* back pointer to associated MAC */ int sbdma_channel; /* channel number */ - int sbdma_txdir; /* direction (1=transmit) */ - int sbdma_maxdescr; /* total # of descriptors in ring */ + int sbdma_txdir; /* direction (1=transmit) */ + int sbdma_maxdescr; /* total # of descriptors in ring */ +#ifdef CONFIG_SBMAC_COALESCE + int sbdma_int_pktcnt; /* # descriptors rx/tx before interrupt*/ + int sbdma_int_timeout; /* # usec rx/tx interrupt */ +#endif + sbmac_port_t sbdma_config0; /* DMA config register 0 */ sbmac_port_t sbdma_config1; /* DMA config register 1 */ sbmac_port_t sbdma_dscrbase; /* Descriptor base address */ @@ -198,7 +208,6 @@ paddr_t sbdma_dscrtable_phys; /* and also the phys addr */ sbdmadscr_t *sbdma_addptr; /* next dscr for sw to add */ sbdmadscr_t *sbdma_remptr; /* next dscr for sw to remove */ - } sbmacdma_t; @@ -218,10 +227,10 @@ struct net_device_stats sbm_stats; int sbm_devflags; /* current device flags */ - int sbm_phy_oldbmsr; - int sbm_phy_oldanlpar; - int sbm_phy_oldk1stsr; - int sbm_phy_oldlinkstat; + int sbm_phy_oldbmsr; + int sbm_phy_oldanlpar; + int sbm_phy_oldk1stsr; + int sbm_phy_oldlinkstat; int sbm_buffersize; unsigned char sbm_phys[2]; @@ -230,7 +239,7 @@ * Controller-specific things */ - sbmac_port_t sbm_base; /* MAC's base address */ + unsigned long sbm_base; /* MAC's base address */ sbmac_state_t sbm_state; /* current state */ sbmac_port_t sbm_macenable; /* MAC Enable Register */ @@ -246,11 +255,12 @@ sbmac_duplex_t sbm_duplex; /* current duplex */ sbmac_fc_t sbm_fc; /* current flow control setting */ - u_char sbm_hwaddr[ETHER_ADDR_LEN]; + unsigned char sbm_hwaddr[ETHER_ADDR_LEN]; sbmacdma_t sbm_txdma; /* for now, only use channel 0 */ sbmacdma_t sbm_rxdma; - + int rx_hw_checksum; + int sbe_idx; }; @@ -267,7 +277,7 @@ int chan, int txrx, int maxdescr); -static void sbdma_channel_start(sbmacdma_t *d); +static void sbdma_channel_start(sbmacdma_t *d, int rxtx); static int sbdma_add_rcvbuffer(sbmacdma_t *d,struct sk_buff *m); static int sbdma_add_txbuffer(sbmacdma_t *d,struct sk_buff *m); static void sbdma_emptyring(sbmacdma_t *d); @@ -279,12 +289,11 @@ static void sbmac_channel_stop(struct sbmac_softc *s); static sbmac_state_t sbmac_set_channel_state(struct sbmac_softc *,sbmac_state_t); static void sbmac_promiscuous_mode(struct sbmac_softc *sc,int onoff); -/*static void sbmac_init_and_start(struct sbmac_softc *sc);*/ static uint64_t sbmac_addr2reg(unsigned char *ptr); static irqreturn_t sbmac_intr(int irq,void *dev_instance,struct pt_regs *rgs); static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev); static void sbmac_setmulti(struct sbmac_softc *sc); -static int sbmac_init(struct net_device *dev); +static int sbmac_init(struct net_device *dev, int idx); static int sbmac_set_speed(struct sbmac_softc *s,sbmac_speed_t speed); static int sbmac_set_duplex(struct sbmac_softc *s,sbmac_duplex_t duplex,sbmac_fc_t fc); @@ -308,6 +317,8 @@ * Globals ********************************************************************* */ +static uint64_t sbmac_orig_hwaddr[MAX_UNITS]; + /********************************************************************** * MDIO constants @@ -328,8 +339,8 @@ #define BMCR_DUPLEX 0x0100 #define BMCR_COLTEST 0x0080 #define BMCR_SPEED1 0x0040 -#define BMCR_SPEED1000 (BMCR_SPEED1|BMCR_SPEED0) -#define BMCR_SPEED100 (BMCR_SPEED0) +#define BMCR_SPEED1000 BMCR_SPEED1 +#define BMCR_SPEED100 BMCR_SPEED0 #define BMCR_SPEED10 0 #define BMSR_100BT4 0x8000 @@ -437,6 +448,8 @@ #define M_MAC_MDIO_DIR_OUTPUT 0 /* for clarity */ +#define ENABLE 1 +#define DISABLE 0 /********************************************************************** * SBMAC_MII_SYNC(s) @@ -490,7 +503,8 @@ curmask = 1 << (bitcnt - 1); for (i = 0; i < bitcnt; i++) { - if (data & curmask) bits |= M_MAC_MDIO_OUT; + if (data & curmask) + bits |= M_MAC_MDIO_OUT; else bits &= ~M_MAC_MDIO_OUT; SBMAC_WRITECSR(s->sbm_mdio,bits); SBMAC_WRITECSR(s->sbm_mdio,bits | M_MAC_MDC); @@ -571,7 +585,8 @@ regval <<= 1; if (error == 0) { - if (SBMAC_READCSR(s->sbm_mdio) & M_MAC_MDIO_IN) regval |= 1; + if (SBMAC_READCSR(s->sbm_mdio) & M_MAC_MDIO_IN) + regval |= 1; } SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_INPUT | M_MAC_MDC); @@ -581,7 +596,8 @@ /* Switch back to output */ SBMAC_WRITECSR(s->sbm_mdio,M_MAC_MDIO_DIR_OUTPUT); - if (error == 0) return regval; + if (error == 0) + return regval; return 0; } @@ -651,20 +667,68 @@ d->sbdma_channel = chan; d->sbdma_txdir = txrx; +#if 0 + /* RMON clearing */ + s->sbe_idx =(s->sbm_base - A_MAC_BASE_0)/MAC_SPACING; +#endif + + SBMAC_WRITECSR(KSEG1ADDR( + A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_BYTES)), 0); + SBMAC_WRITECSR(KSEG1ADDR( + A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_COLLISIONS)), 0); + SBMAC_WRITECSR(KSEG1ADDR( + A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_LATE_COL)), 0); + SBMAC_WRITECSR(KSEG1ADDR( + A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_EX_COL)), 0); + SBMAC_WRITECSR(KSEG1ADDR( + A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_FCS_ERROR)), 0); + SBMAC_WRITECSR(KSEG1ADDR( + A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_ABORT)), 0); + SBMAC_WRITECSR(KSEG1ADDR( + A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_BAD)), 0); + SBMAC_WRITECSR(KSEG1ADDR( + A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_GOOD)), 0); + SBMAC_WRITECSR(KSEG1ADDR( + A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_RUNT)), 0); + SBMAC_WRITECSR(KSEG1ADDR( + A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_TX_OVERSIZE)), 0); + SBMAC_WRITECSR(KSEG1ADDR( + A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BYTES)), 0); + SBMAC_WRITECSR(KSEG1ADDR( + A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_MCAST)), 0); + SBMAC_WRITECSR(KSEG1ADDR( + A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BCAST)), 0); + SBMAC_WRITECSR(KSEG1ADDR( + A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_BAD)), 0); + SBMAC_WRITECSR(KSEG1ADDR( + A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_GOOD)), 0); + SBMAC_WRITECSR(KSEG1ADDR( + A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_RUNT)), 0); + SBMAC_WRITECSR(KSEG1ADDR( + A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_OVERSIZE)), 0); + SBMAC_WRITECSR(KSEG1ADDR( + A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_FCS_ERROR)), 0); + SBMAC_WRITECSR(KSEG1ADDR( + A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_LENGTH_ERROR)), 0); + SBMAC_WRITECSR(KSEG1ADDR( + A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_CODE_ERROR)), 0); + SBMAC_WRITECSR(KSEG1ADDR( + A_MAC_REGISTER(s->sbe_idx, R_MAC_RMON_RX_ALIGN_ERROR)), 0); + /* * initialize register pointers */ d->sbdma_config0 = - PKSEG1(s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG0)); + s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG0); d->sbdma_config1 = - PKSEG1(s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG0)); + s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG1); d->sbdma_dscrbase = - PKSEG1(s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_BASE)); + s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_BASE); d->sbdma_dscrcnt = - PKSEG1(s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_CNT)); + s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_CNT); d->sbdma_curdscr = - PKSEG1(s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CUR_DSCRADDR)); + s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CUR_DSCRADDR); /* * Allocate memory for the ring @@ -673,23 +737,41 @@ d->sbdma_maxdescr = maxdescr; d->sbdma_dscrtable = (sbdmadscr_t *) - KMALLOC(d->sbdma_maxdescr*sizeof(sbdmadscr_t)); + kmalloc(d->sbdma_maxdescr*sizeof(sbdmadscr_t), GFP_KERNEL); memset(d->sbdma_dscrtable,0,d->sbdma_maxdescr*sizeof(sbdmadscr_t)); d->sbdma_dscrtable_end = d->sbdma_dscrtable + d->sbdma_maxdescr; - d->sbdma_dscrtable_phys = KVTOPHYS(d->sbdma_dscrtable); + d->sbdma_dscrtable_phys = virt_to_phys(d->sbdma_dscrtable); /* * And context table */ d->sbdma_ctxtable = (struct sk_buff **) - KMALLOC(d->sbdma_maxdescr*sizeof(struct sk_buff *)); + kmalloc(d->sbdma_maxdescr*sizeof(struct sk_buff *), GFP_KERNEL); memset(d->sbdma_ctxtable,0,d->sbdma_maxdescr*sizeof(struct sk_buff *)); +#ifdef CONFIG_SBMAC_COALESCE + /* + * Setup Rx/Tx DMA coalescing defaults + */ + + if ( int_pktcnt ) { + d->sbdma_int_pktcnt = int_pktcnt; + } else { + d->sbdma_int_pktcnt = 1; + } + + if ( int_timeout ) { + d->sbdma_int_timeout = int_timeout; + } else { + d->sbdma_int_timeout = 0; + } +#endif + } /********************************************************************** @@ -699,33 +781,75 @@ * * Input parameters: * d - DMA channel to init (context must be previously init'd + * rxtx - DMA_RX or DMA_TX depending on what type of channel * * Return value: * nothing ********************************************************************* */ -static void sbdma_channel_start(sbmacdma_t *d) +static void sbdma_channel_start(sbmacdma_t *d, int rxtx ) { /* * Turn on the DMA channel */ +#ifdef CONFIG_SBMAC_COALESCE + SBMAC_WRITECSR(d->sbdma_config1, + V_DMA_INT_TIMEOUT(d->sbdma_int_timeout) | + 0); + SBMAC_WRITECSR(d->sbdma_config0, + M_DMA_EOP_INT_EN | + V_DMA_RINGSZ(d->sbdma_maxdescr) | + V_DMA_INT_PKTCNT(d->sbdma_int_pktcnt) | + 0); +#else SBMAC_WRITECSR(d->sbdma_config1,0); - - SBMAC_WRITECSR(d->sbdma_dscrbase,d->sbdma_dscrtable_phys); - SBMAC_WRITECSR(d->sbdma_config0, V_DMA_RINGSZ(d->sbdma_maxdescr) | 0); - +#endif + + SBMAC_WRITECSR(d->sbdma_dscrbase,d->sbdma_dscrtable_phys); + /* * Initialize ring pointers */ - + d->sbdma_addptr = d->sbdma_dscrtable; d->sbdma_remptr = d->sbdma_dscrtable; } +/********************************************************************** + * SBDMA_CHANNEL_STOP(d) + * + * Initialize the hardware registers for a DMA channel. + * + * Input parameters: + * d - DMA channel to init (context must be previously init'd + * + * Return value: + * nothing + ********************************************************************* */ + +static void sbdma_channel_stop(sbmacdma_t *d) +{ + /* + * Turn off the DMA channel + */ + + SBMAC_WRITECSR(d->sbdma_config1,0); + + SBMAC_WRITECSR(d->sbdma_dscrbase,0); + + SBMAC_WRITECSR(d->sbdma_config0,0); + + /* + * Zero ring pointers + */ + + d->sbdma_addptr = 0; + d->sbdma_remptr = 0; +} static void sbdma_align_skb(struct sk_buff *skb,int power2,int offset) { @@ -777,7 +901,7 @@ if (nextdsc == d->sbdma_remptr) { return -ENOSPC; } - + /* * Allocate a sk_buff if we don't already have one. * If we do have an sk_buff, reset it so that it's empty. @@ -788,25 +912,25 @@ * * 1. the data does not start in the middle of a cache line. * 2. The data does not end in the middle of a cache line - * 3. The buffer can be aligned such that the IP addresses are + * 3. The buffer can be aligned such that the IP addresses are * naturally aligned. * - * Remember, the SB1250's MAC writes whole cache lines at a time, + * Remember, the SOCs MAC writes whole cache lines at a time, * without reading the old contents first. So, if the sk_buff's - * data portion starts in the middle of a cache line, the SB1250 + * data portion starts in the middle of a cache line, the SOC * DMA will trash the beginning (and ending) portions. */ if (sb == NULL) { - sb_new = dev_alloc_skb(ENET_PACKET_SIZE + CACHELINESIZE*2 + ETHER_ALIGN); + sb_new = dev_alloc_skb(ENET_PACKET_SIZE + SMP_CACHE_BYTES * 2 + ETHER_ALIGN); if (sb_new == NULL) { printk(KERN_INFO "%s: sk_buff allocation failed\n", d->sbdma_eth->sbm_dev->name); return -ENOBUFS; } - - sbdma_align_skb(sb_new,CACHELINESIZE,ETHER_ALIGN); - + + sbdma_align_skb(sb_new, SMP_CACHE_BYTES, ETHER_ALIGN); + /* mark skbuff owned by our device */ sb_new->dev = d->sbdma_eth->sbm_dev; } @@ -814,7 +938,7 @@ sb_new = sb; /* * nothing special to reinit buffer, it's already aligned - * and sb->tail already points to a good place. + * and sb->data already points to a good place. */ } @@ -822,10 +946,19 @@ * fill in the descriptor */ - dsc->dscr_a = KVTOPHYS(sb_new->tail) | +#ifdef CONFIG_SBMAC_COALESCE + /* + * Do not interrupt per DMA transfer. + */ + dsc->dscr_a = virt_to_phys(sb_new->tail) | + V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize+ETHER_ALIGN)) | + 0; +#else + dsc->dscr_a = virt_to_phys(sb_new->tail) | V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize+ETHER_ALIGN)) | M_DMA_DSCRA_INTERRUPT; - +#endif + /* receiving: no options */ dsc->dscr_b = 0; @@ -904,12 +1037,14 @@ * while doing the calculation. */ - phys = KVTOPHYS(sb->data); - ncb = NUMCACHEBLKS(length+(phys & (CACHELINESIZE-1))); - + phys = virt_to_phys(sb->data); + ncb = NUMCACHEBLKS(length+(phys & (SMP_CACHE_BYTES - 1))); + dsc->dscr_a = phys | V_DMA_DSCRA_A_SIZE(ncb) | +#ifndef CONFIG_SBMAC_COALESCE M_DMA_DSCRA_INTERRUPT | +#endif M_DMA_ETHTX_SOP; /* transmitting: set outbound options and length */ @@ -986,7 +1121,8 @@ int idx; for (idx = 0; idx < SBMAC_MAX_RXDESCR-1; idx++) { - if (sbdma_add_rcvbuffer(d,NULL) != 0) break; + if (sbdma_add_rcvbuffer(d,NULL) != 0) + break; } } @@ -1037,7 +1173,8 @@ * the hardware is working on right now. */ - if (curidx == hwidx) break; + if (curidx == hwidx) + break; /* * Otherwise, get the packet's sk_buff ptr back @@ -1058,35 +1195,51 @@ if (!(dsc->dscr_a & M_DMA_ETHRX_BAD)) { /* - * Set length into the packet - */ - skb_put(sb,len); - - /* * Add a new buffer to replace the old one. If we fail * to allocate a buffer, we're going to drop this * packet and put it right back on the receive ring. */ if (sbdma_add_rcvbuffer(d,NULL) == -ENOBUFS) { - sbdma_add_rcvbuffer(d,sb); /* re-add old buffer */ - } - else { - /* - * Buffer has been replaced on the receive ring. - * Pass the buffer to the kernel - */ - sc->sbm_stats.rx_bytes += len; - sc->sbm_stats.rx_packets++; - sb->protocol = eth_type_trans(sb,d->sbdma_eth->sbm_dev); - netif_rx(sb); - } - } - else { + sc->sbm_stats.rx_dropped++; + sbdma_add_rcvbuffer(d,sb); /* re-add old buffer */ + } else { + /* + * Set length into the packet + */ + skb_put(sb,len); + + /* + * Buffer has been replaced on the + * receive ring. Pass the buffer to + * the kernel */ + sc->sbm_stats.rx_bytes += len; + sc->sbm_stats.rx_packets++; + sb->protocol = eth_type_trans(sb,d->sbdma_eth->sbm_dev); + if (sc->rx_hw_checksum == ENABLE) { + /* if the ip checksum is good + indicate in skb. else set + CHECKSUM_NONE as device + failed to checksum the + packet */ + + if (((dsc->dscr_b) |M_DMA_ETHRX_BADTCPCS) || + ((dsc->dscr_a)| M_DMA_ETHRX_BADIP4CS)) { + sb->ip_summed = CHECKSUM_NONE; + } else { + printk(KERN_DEBUG "hw checksum fail .\n"); + sb->ip_summed = CHECKSUM_UNNECESSARY; + } + } /* rx_hw_checksum */ + + netif_rx(sb); + } + } else { /* * Packet was mangled somehow. Just drop it and * put it back on the receive ring. */ + sc->sbm_stats.rx_errors++; sbdma_add_rcvbuffer(d,sb); } @@ -1143,21 +1296,27 @@ curidx = d->sbdma_remptr - d->sbdma_dscrtable; { - /* XXX This is gross, ugly, and only here because justin hacked it - in to fix a problem without really understanding it. - - It seems that, for whatever reason, this routine is invoked immediately upon the enabling of interrupts. - So then the Read below returns zero, making hwidx a negative number, and anti-hilarity - ensues. - - I'm guessing there's a proper fix involving clearing out interrupt state from old packets - before enabling interrupts, but I'm not sure. - - Anyways, this hack seems to work, and is Good Enough for 11 PM. :) - - -Justin - */ - + /* XXX This is gross, ugly, and only here + * because justin hacked it in to fix a + * problem without really understanding it. + * + * It seems that, for whatever reason, this + * routine is invoked immediately upon the + * enabling of interrupts. So then the Read + * below returns zero, making hwidx a negative + * number, and anti-hilarity ensues. + * + * I'm guessing there's a proper fix involving + * clearing out interrupt state from old + * packets before enabling interrupts, but I'm + * not sure. + * + * Anyways, this hack seems to work, and is + * Good Enough for 11 PM. :) + * + * -Justin + */ + uint64_t tmp = SBMAC_READCSR(d->sbdma_curdscr); if (!tmp) { break; @@ -1171,7 +1330,8 @@ * the hardware is working on right now. */ - if (curidx == hwidx) break; + if (curidx == hwidx) + break; /* * Otherwise, get the packet's sk_buff ptr back @@ -1238,14 +1398,14 @@ * figure out the addresses of some ports */ - s->sbm_macenable = PKSEG1(s->sbm_base + R_MAC_ENABLE); - s->sbm_maccfg = PKSEG1(s->sbm_base + R_MAC_CFG); - s->sbm_fifocfg = PKSEG1(s->sbm_base + R_MAC_THRSH_CFG); - s->sbm_framecfg = PKSEG1(s->sbm_base + R_MAC_FRAMECFG); - s->sbm_rxfilter = PKSEG1(s->sbm_base + R_MAC_ADFILTER_CFG); - s->sbm_isr = PKSEG1(s->sbm_base + R_MAC_STATUS); - s->sbm_imr = PKSEG1(s->sbm_base + R_MAC_INT_MASK); - s->sbm_mdio = PKSEG1(s->sbm_base + R_MAC_MDIO); + s->sbm_macenable = s->sbm_base + R_MAC_ENABLE; + s->sbm_maccfg = s->sbm_base + R_MAC_CFG; + s->sbm_fifocfg = s->sbm_base + R_MAC_THRSH_CFG; + s->sbm_framecfg = s->sbm_base + R_MAC_FRAMECFG; + s->sbm_rxfilter = s->sbm_base + R_MAC_ADFILTER_CFG; + s->sbm_isr = s->sbm_base + R_MAC_STATUS; + s->sbm_imr = s->sbm_base + R_MAC_INT_MASK; + s->sbm_mdio = s->sbm_base + R_MAC_MDIO; s->sbm_phys[0] = 1; s->sbm_phys[1] = 0; @@ -1284,12 +1444,12 @@ static void sbdma_uninitctx(struct sbmacdma_s *d) { if (d->sbdma_dscrtable) { - KFREE(d->sbdma_dscrtable); + kfree(d->sbdma_dscrtable); d->sbdma_dscrtable = NULL; } if (d->sbdma_ctxtable) { - KFREE(d->sbdma_ctxtable); + kfree(d->sbdma_ctxtable); d->sbdma_ctxtable = NULL; } } @@ -1319,13 +1479,14 @@ uint64_t reg; sbmac_port_t port; uint64_t cfg,fifo,framecfg; - int idx; + int idx, th_value; /* * Don't do this if running */ - if (s->sbm_state == sbmac_state_on) return; + if (s->sbm_state == sbmac_state_on) + return; /* * Bring the controller out of reset, but leave it off. @@ -1351,26 +1512,36 @@ M_MAC_SS_EN | 0; + /* + * Be sure that RD_THRSH+WR_THRSH <= 32 for pass1 pars + * and make sure that RD_THRSH + WR_THRSH <=128 for pass2 and above + * Use a larger RD_THRSH for gigabit + */ + if (periph_rev >= 2) + th_value = 64; + else + th_value = 28; + fifo = V_MAC_TX_WR_THRSH(4) | /* Must be '4' or '8' */ - V_MAC_TX_RD_THRSH(4) | + ((s->sbm_speed == sbmac_speed_1000) + ? V_MAC_TX_RD_THRSH(th_value) : V_MAC_TX_RD_THRSH(4)) | V_MAC_TX_RL_THRSH(4) | V_MAC_RX_PL_THRSH(4) | V_MAC_RX_RD_THRSH(4) | /* Must be '4' */ V_MAC_RX_PL_THRSH(4) | V_MAC_RX_RL_THRSH(8) | 0; - + framecfg = V_MAC_MIN_FRAMESZ_DEFAULT | V_MAC_MAX_FRAMESZ_DEFAULT | V_MAC_BACKOFF_SEL(1); - - + /* * Clear out the hash address map */ - port = PKSEG1(s->sbm_base + R_MAC_HASH_BASE); - for (idx = 0; idx < MAC_HASH_COUNT; idx++) { + port = s->sbm_base + R_MAC_HASH_BASE; + for (idx = 0; idx < MAC_HASH_COUNT; idx++) { SBMAC_WRITECSR(port,0); port += sizeof(uint64_t); } @@ -1379,7 +1550,7 @@ * Clear out the exact-match table */ - port = PKSEG1(s->sbm_base + R_MAC_ADDR_BASE); + port = s->sbm_base + R_MAC_ADDR_BASE; for (idx = 0; idx < MAC_ADDR_COUNT; idx++) { SBMAC_WRITECSR(port,0); port += sizeof(uint64_t); @@ -1389,14 +1560,14 @@ * Clear out the DMA Channel mapping table registers */ - port = PKSEG1(s->sbm_base + R_MAC_CHUP0_BASE); + port = s->sbm_base + R_MAC_CHUP0_BASE; for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) { SBMAC_WRITECSR(port,0); port += sizeof(uint64_t); } - port = PKSEG1(s->sbm_base + R_MAC_CHLO0_BASE); + port = s->sbm_base + R_MAC_CHLO0_BASE; for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) { SBMAC_WRITECSR(port,0); port += sizeof(uint64_t); @@ -1409,13 +1580,13 @@ reg = sbmac_addr2reg(s->sbm_hwaddr); - port = PKSEG1(s->sbm_base + R_MAC_ADDR_BASE); + port = s->sbm_base + R_MAC_ADDR_BASE; SBMAC_WRITECSR(port,reg); - port = PKSEG1(s->sbm_base + R_MAC_ETHERNET_ADDR); + port = s->sbm_base + R_MAC_ETHERNET_ADDR; #ifdef CONFIG_SB1_PASS_1_WORKAROUNDS /* - * Pass1 SB1250s do not receive packets addressed to the + * Pass1 SOCs do not receive packets addressed to the * destination address in the R_MAC_ETHERNET_ADDR register. * Set the value to zero. */ @@ -1439,8 +1610,8 @@ * Initialize DMA channels (rings should be ok now) */ - sbdma_channel_start(&(s->sbm_rxdma)); - sbdma_channel_start(&(s->sbm_txdma)); + sbdma_channel_start(&(s->sbm_rxdma), DMA_RX); + sbdma_channel_start(&(s->sbm_txdma), DMA_TX); /* * Configure the speed, duplex, and flow control @@ -1467,12 +1638,22 @@ + +#ifdef CONFIG_SBMAC_COALESCE + /* + * Accept any TX interrupt and EOP count/timer RX interrupts on ch 0 + */ + SBMAC_WRITECSR(s->sbm_imr, + ((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) | + ((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_RX_CH0)); +#else /* * Accept any kind of interrupt on TX and RX DMA channel 0 */ SBMAC_WRITECSR(s->sbm_imr, (M_MAC_INT_CHANNEL << S_MAC_TX_CH0) | (M_MAC_INT_CHANNEL << S_MAC_RX_CH0)); +#endif /* * Enable receiving unicasts and broadcasts @@ -1517,11 +1698,10 @@ static void sbmac_channel_stop(struct sbmac_softc *s) { - uint64_t ctl; - /* don't do this if already stopped */ - if (s->sbm_state == sbmac_state_off) return; + if (s->sbm_state == sbmac_state_off) + return; /* don't accept any packets, disable all interrupts */ @@ -1534,14 +1714,18 @@ /* turn off receiver and transmitter */ - ctl = SBMAC_READCSR(s->sbm_macenable); - ctl &= ~(M_MAC_RXDMA_EN0 | M_MAC_TXDMA_EN0); - SBMAC_WRITECSR(s->sbm_macenable,ctl); + SBMAC_WRITECSR(s->sbm_macenable,0); /* We're stopped now. */ s->sbm_state = sbmac_state_off; + /* + * Stop DMA channels (rings should be ok now) + */ + + sbdma_channel_stop(&(s->sbm_rxdma)); + sbdma_channel_stop(&(s->sbm_txdma)); /* Empty the receive and transmit rings */ @@ -1610,7 +1794,8 @@ { uint64_t reg; - if (sc->sbm_state != sbmac_state_on) return; + if (sc->sbm_state != sbmac_state_on) + return; if (onoff) { reg = SBMAC_READCSR(sc->sbm_rxfilter); @@ -1624,31 +1809,36 @@ } } - - -#if 0 /********************************************************************** - * SBMAC_INIT_AND_START(sc) + * SBMAC_SETIPHDR_OFFSET(sc,onoff) * - * Stop the channel and restart it. This is generally used - * when we have to do something to the channel that requires - * a swift kick. + * Set the iphdr offset as 15 assuming ethernet encapsulation * * Input parameters: * sc - softc + * + * Return value: + * nothing ********************************************************************* */ -static void sbmac_init_and_start(struct sbmac_softc *sc) +static void sbmac_set_iphdr_offset(struct sbmac_softc *sc) { - unsigned long flags; - - spin_lock_irqsave(&(sc->sbm_lock),flags); + uint64_t reg; - sbmac_set_channel_state(sc,sbmac_state_on); + /* Hard code the off set to 15 for now */ + reg = SBMAC_READCSR(sc->sbm_rxfilter); + reg &= ~M_MAC_IPHDR_OFFSET | V_MAC_IPHDR_OFFSET(15); + SBMAC_WRITECSR(sc->sbm_rxfilter,reg); - spin_unlock_irqrestore(&(sc->sbm_lock),flags); + /* read system identification to determine revision */ + if (periph_rev >= 2) { + printk(KERN_INFO "%s: enabling TCP rcv checksum\n", + sc->sbm_dev->name); + sc->rx_hw_checksum = ENABLE; + } else { + sc->rx_hw_checksum = DISABLE; + } } -#endif /********************************************************************** @@ -1712,7 +1902,8 @@ s->sbm_speed = speed; - if (s->sbm_state == sbmac_state_on) return 0; /* save for next restart */ + if (s->sbm_state == sbmac_state_on) + return 0; /* save for next restart */ /* * Read current register values @@ -1772,7 +1963,6 @@ SBMAC_WRITECSR(s->sbm_maccfg,cfg); return 1; - } /********************************************************************** @@ -1802,7 +1992,8 @@ s->sbm_duplex = duplex; s->sbm_fc = fc; - if (s->sbm_state == sbmac_state_on) return 0; /* save for next restart */ + if (s->sbm_state == sbmac_state_on) + return 0; /* save for next restart */ /* * Read current register values @@ -1886,7 +2077,7 @@ * Return value: * nothing ********************************************************************* */ -static void sbmac_intr(int irq,void *dev_instance,struct pt_regs *rgs) +static irqreturn_t sbmac_intr(int irq,void *dev_instance,struct pt_regs *rgs) { struct net_device *dev = (struct net_device *) dev_instance; struct sbmac_softc *sc = (struct sbmac_softc *) (dev->priv); @@ -1896,14 +2087,17 @@ for (;;) { /* - * Read the ISR (this clears the bits in the real register) + * Read the ISR (this clears the bits in the real + * register, except for counter addr) */ - isr = SBMAC_READCSR(sc->sbm_isr); + isr = SBMAC_READCSR(sc->sbm_isr) & ~M_MAC_COUNTER_ADDR; if (isr == 0) break; + handled = 1; + /* * Transmits on channel 0 */ @@ -1915,6 +2109,23 @@ /* * Receives on channel 0 */ + + /* + * It's important to test all the bits (or at least the + * EOP_SEEN bit) when deciding to do the RX process + * particularly when coalescing, to make sure we + * take care of the following: + * + * If you have some packets waiting (have been received + * but no interrupt) and get a TX interrupt before + * the RX timer or counter expires, reading the ISR + * above will clear the timer and counter, and you + * won't get another interrupt until a packet shows + * up to start the timer again. Testing + * EOP_SEEN here takes care of this case. + * (EOP_SEEN is part of M_MAC_INT_CHANNEL << S_MAC_RX_CH0) + */ + if (isr & (M_MAC_INT_CHANNEL << S_MAC_RX_CH0)) { sbdma_rx_process(sc,&(sc->sbm_rxdma)); @@ -1952,6 +2163,9 @@ if (sbdma_add_txbuffer(&(sc->sbm_txdma),skb)) { /* XXX save skb that we could not send */ netif_stop_queue(dev); + spin_unlock_irq(&sc->sbm_lock); + + return 1; } dev->trans_start = jiffies; @@ -1990,12 +2204,12 @@ */ for (idx = 1; idx < MAC_ADDR_COUNT; idx++) { - port = PKSEG1(sc->sbm_base + R_MAC_ADDR_BASE+(idx*sizeof(uint64_t))); + port = sc->sbm_base + R_MAC_ADDR_BASE+(idx*sizeof(uint64_t)); SBMAC_WRITECSR(port,0); } for (idx = 0; idx < MAC_HASH_COUNT; idx++) { - port = PKSEG1(sc->sbm_base + R_MAC_HASH_BASE+(idx*sizeof(uint64_t))); + port = sc->sbm_base + R_MAC_HASH_BASE+(idx*sizeof(uint64_t)); SBMAC_WRITECSR(port,0); } @@ -2032,8 +2246,7 @@ mclist = dev->mc_list; while (mclist && (idx < MAC_ADDR_COUNT)) { reg = sbmac_addr2reg(mclist->dmi_addr); - port = PKSEG1(sc->sbm_base + - R_MAC_ADDR_BASE+(idx*sizeof(uint64_t))); + port = sc->sbm_base + R_MAC_ADDR_BASE+(idx * sizeof(uint64_t)); SBMAC_WRITECSR(port,reg); idx++; mclist = mclist->next; @@ -2070,10 +2283,14 @@ { int digit; - if ((str >= '0') && (str <= '9')) digit = str - '0'; - else if ((str >= 'a') && (str <= 'f')) digit = str - 'a' + 10; - else if ((str >= 'A') && (str <= 'F')) digit = str - 'A' + 10; - else return -1; + if ((str >= '0') && (str <= '9')) + digit = str - '0'; + else if ((str >= 'a') && (str <= 'f')) + digit = str - 'a' + 10; + else if ((str >= 'A') && (str <= 'F')) + digit = str - 'A' + 10; + else + return -1; return digit; } @@ -2092,16 +2309,18 @@ * 0 if ok, else -1 ********************************************************************* */ -static int sbmac_parse_hwaddr(char *str,u_char *hwaddr) +static int sbmac_parse_hwaddr(char *str, unsigned char *hwaddr) { int digit1,digit2; int idx = 6; while (*str && (idx > 0)) { digit1 = sbmac_parse_xdigit(*str); - if (digit1 < 0) return -1; + if (digit1 < 0) + return -1; str++; - if (!*str) return -1; + if (!*str) + return -1; if ((*str == ':') || (*str == '-')) { digit2 = digit1; @@ -2109,20 +2328,32 @@ } else { digit2 = sbmac_parse_xdigit(*str); - if (digit2 < 0) return -1; + if (digit2 < 0) + return -1; str++; } *hwaddr++ = (digit1 << 4) | digit2; idx--; - if (*str == '-') str++; - if (*str == ':') str++; + if (*str == '-') + str++; + if (*str == ':') + str++; } return 0; } #endif +static int sb1250_change_mtu(struct net_device *_dev, int new_mtu) +{ + if (new_mtu > ENET_PACKET_SIZE) + return -EINVAL; + _dev->mtu = new_mtu; + printk(KERN_INFO "changing the mtu to %d\n", new_mtu); + return 0; +} + /********************************************************************** * SBMAC_INIT(dev) * @@ -2135,19 +2366,20 @@ * status ********************************************************************* */ -static int sbmac_init(struct net_device *dev) +static int sbmac_init(struct net_device *dev, int idx) { struct sbmac_softc *sc; - u_char *eaddr; + unsigned char *eaddr; uint64_t ea_reg; - int idx; + int i; sc = (struct sbmac_softc *)dev->priv; /* Determine controller base address */ - sc->sbm_base = (sbmac_port_t) dev->base_addr; + sc->sbm_base = KSEG1ADDR(dev->base_addr); sc->sbm_dev = dev; + sc->sbe_idx = idx; eaddr = sc->sbm_hwaddr; @@ -2156,16 +2388,15 @@ * for us in the ethernet address register for each mac. */ - ea_reg = SBMAC_READCSR(PKSEG1(sc->sbm_base + R_MAC_ETHERNET_ADDR)); - SBMAC_WRITECSR(PKSEG1(sc->sbm_base + R_MAC_ETHERNET_ADDR), 0); - for (idx = 0; idx < 6; idx++) { - eaddr[idx] = (uint8_t) (ea_reg & 0xFF); + ea_reg = SBMAC_READCSR(sc->sbm_base + R_MAC_ETHERNET_ADDR); + SBMAC_WRITECSR(sc->sbm_base + R_MAC_ETHERNET_ADDR, 0); + for (i = 0; i < 6; i++) { + eaddr[i] = (uint8_t) (ea_reg & 0xFF); ea_reg >>= 8; } - - for (idx = 0; idx < 6; idx++) { - dev->dev_addr[idx] = eaddr[idx]; + for (i = 0; i < 6; i++) { + dev->dev_addr[i] = eaddr[i]; } @@ -2173,8 +2404,8 @@ * Init packet size */ - sc->sbm_buffersize = ENET_PACKET_SIZE + CACHELINESIZE*2 + ETHER_ALIGN; - + sc->sbm_buffersize = ENET_PACKET_SIZE + SMP_CACHE_BYTES * 2 + ETHER_ALIGN; + /* * Initialize context (get pointers to registers and stuff), then * allocate the memory for the descriptor tables. @@ -2184,13 +2415,13 @@ /* - * Display Ethernet address (this is called during the config process - * so we need to finish off the config message that was being displayed) + * Display Ethernet address (this is called during the config + * process so we need to finish off the config message that + * was being displayed) */ printk(KERN_INFO - "%s: SB1250 Ethernet at 0x%08lX, address: %02X-%02X-%02X-%02X-%02X-%02X\n", - dev->name, - (unsigned long) sc->sbm_base, + "%s: SiByte Ethernet at 0x%08lX, address: %02X-%02X-%02X-%02X-%02X-%02X\n", + dev->name, dev->base_addr, eaddr[0],eaddr[1],eaddr[2],eaddr[3],eaddr[4],eaddr[5]); /* @@ -2208,9 +2439,13 @@ dev->do_ioctl = sbmac_mii_ioctl; dev->tx_timeout = sbmac_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; + + dev->change_mtu = sb1250_change_mtu; + + /* This is needed for PASS2 for Rx H/W checksum feature */ + sbmac_set_iphdr_offset(sc); return 0; - } @@ -2237,7 +2472,7 @@ * Configure default speed */ - sbmac_mii_poll(sc,1); + sbmac_mii_poll(sc,noisy_mii); /* * Turn on the channel @@ -2319,7 +2554,8 @@ chg = 1; } - if (chg == 0) return 0; + if (chg == 0) + return 0; p += sprintf(p,"Link speed: "); @@ -2371,8 +2607,6 @@ } - - static void sbmac_timer(unsigned long data) { struct net_device *dev = (struct net_device *)data; @@ -2399,19 +2633,19 @@ * Poll the PHY to see what speed we should be running at */ - if (sbmac_mii_poll(sc,1)) { - if (sc->sbm_state != sbmac_state_off) { - /* - * something changed, restart the channel - */ - if (debug > 1) { - printk("%s: restarting channel because speed changed\n", - sc->sbm_dev->name); - } - sbmac_channel_stop(sc); - sbmac_channel_start(sc); + if (sbmac_mii_poll(sc,noisy_mii)) { + if (sc->sbm_state != sbmac_state_off) { + /* + * something changed, restart the channel + */ + if (debug > 1) { + printk("%s: restarting channel because speed changed\n", + sc->sbm_dev->name); + } + sbmac_channel_stop(sc); + sbmac_channel_start(sc); } - } + } spin_unlock_irq (&sc->sbm_lock); @@ -2479,7 +2713,8 @@ spin_unlock_irqrestore(&sc->sbm_lock, flags); if (msg_flag) { - printk(KERN_NOTICE "%s: Promiscuous mode %sabled.\n", dev->name,(msg_flag==1)?"en":"dis"); + printk(KERN_NOTICE "%s: Promiscuous mode %sabled.\n", + dev->name,(msg_flag==1)?"en":"dis"); } /* @@ -2530,31 +2765,31 @@ { struct sbmac_softc *sc = (struct sbmac_softc *)dev->priv; unsigned long flags; - + int irq; + sbmac_set_channel_state(sc,sbmac_state_off); - + del_timer_sync(&sc->sbm_timer); - + spin_lock_irqsave(&sc->sbm_lock, flags); - + netif_stop_queue(dev); - + if (debug > 1) { printk(KERN_DEBUG "%s: Shutting down ethercard\n",dev->name); } - + spin_unlock_irqrestore(&sc->sbm_lock, flags); - - /* Make sure there is no irq-handler running on a different CPU. */ - synchronize_irq(dev->irq); - - free_irq(dev->irq, dev); - + + irq = dev->irq; + synchronize_irq(irq); + free_irq(irq, dev); + sbdma_emptyring(&(sc->sbm_txdma)); sbdma_emptyring(&(sc->sbm_rxdma)); MOD_DEC_USE_COUNT; - + return 0; } @@ -2571,8 +2806,8 @@ port = A_MAC_CHANNEL_BASE(chan); sbmac_parse_hwaddr(addr,eaddr); val = sbmac_addr2reg(eaddr); - SBMAC_WRITECSR(PKSEG1(port+R_MAC_ETHERNET_ADDR),val); - val = SBMAC_READCSR(PKSEG1(port+R_MAC_ETHERNET_ADDR)); + SBMAC_WRITECSR(KSEG1ADDR(port+R_MAC_ETHERNET_ADDR),val); + val = SBMAC_READCSR(KSEG1ADDR(port+R_MAC_ETHERNET_ADDR)); } #endif @@ -2585,6 +2820,7 @@ int macidx = 0; struct net_device *dev; sbmac_port_t port; + int chip_max_units; /* * For bringup when not using the firmware, we can pre-fill @@ -2605,8 +2841,25 @@ * Walk through the Ethernet controllers and find * those who have their MAC addresses set. */ - - for (idx = 0; idx < MAX_UNITS; idx++) { + switch (soc_type) { + case K_SYS_SOC_TYPE_BCM1250: + case K_SYS_SOC_TYPE_BCM1250_ALT: + chip_max_units = 3; + break; + case K_SYS_SOC_TYPE_BCM1120: + case K_SYS_SOC_TYPE_BCM1125: + case K_SYS_SOC_TYPE_BCM1125H: + case K_SYS_SOC_TYPE_BCM1250_ALT2: /* Hybrid */ + chip_max_units = 2; + break; + default: + chip_max_units = 0; + break; + } + if (chip_max_units > MAX_UNITS) + chip_max_units = MAX_UNITS; + + for (idx = 0; idx < chip_max_units; idx++) { /* * This is the base address of the MAC. @@ -2620,25 +2873,31 @@ * If we find a zero, skip this MAC. */ - if (SBMAC_READCSR(PKSEG1(port+R_MAC_ETHERNET_ADDR)) == 0) { + sbmac_orig_hwaddr[idx] = SBMAC_READCSR(KSEG1ADDR(port+R_MAC_ETHERNET_ADDR)); + if (sbmac_orig_hwaddr[idx] == 0) { + printk(KERN_DEBUG "sbmac: not configuring MAC at " + "%lx\n", port); continue; - } + } /* * Okay, cool. Initialize this MAC. */ dev = init_etherdev(NULL,sizeof(struct sbmac_softc)); - if (!dev) break; /* problems, get out now. */ + if (!dev) + return -ENOMEM; /* return ENOMEM */ + + printk(KERN_DEBUG "sbmac: configuring MAC at %lx\n", port); + dev->irq = K_INT_MAC_0 + idx; dev->base_addr = port; dev->mem_end = 0; /*dev->init = sbmac_init;*/ - sbmac_init(dev); + sbmac_init(dev, macidx); dev_sbmac[macidx] = dev; macidx++; - } /* @@ -2654,9 +2913,11 @@ { int idx; struct net_device *dev; + sbmac_port_t port; for (idx = 0; idx < MAX_UNITS; idx++) { dev = dev_sbmac[idx]; - if (dev == NULL) continue; + if (dev == NULL) + continue; if (dev->priv != NULL) { struct sbmac_softc *sc = (struct sbmac_softc *) dev->priv; @@ -2664,9 +2925,11 @@ sbmac_uninitctx(sc); - KFREE(sc); } - KFREE(dev); + + port = A_MAC_CHANNEL_BASE(idx); + SBMAC_WRITECSR(KSEG1ADDR(port+R_MAC_ETHERNET_ADDR), sbmac_orig_hwaddr[idx] ); + kfree(dev); dev_sbmac[idx] = NULL; } } diff -Nru a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c --- a/drivers/net/sgiseeq.c Tue Jul 1 18:44:38 2003 +++ b/drivers/net/sgiseeq.c Tue Jul 1 18:44:38 2003 @@ -5,6 +5,7 @@ */ #include #include +#include #include #include #include @@ -25,8 +26,8 @@ #include #include #include -#include -#include +#include +#include #include #include "sgiseeq.h" @@ -90,8 +91,8 @@ struct sgiseeq_private { volatile struct sgiseeq_init_block srings; char *name; - volatile struct hpc3_ethregs *hregs; - volatile struct sgiseeq_regs *sregs; + struct hpc3_ethregs *hregs; + struct sgiseeq_regs *sregs; /* Ring entry counters. */ unsigned int rx_new, tx_new; @@ -102,17 +103,22 @@ unsigned char mode; struct net_device_stats stats; + + struct net_device *next_module; }; -static inline void hpc3_eth_reset(volatile struct hpc3_ethregs *hregs) +/* A list of all installed seeq devices, for removing the driver module. */ +static struct net_device *root_sgiseeq_dev; + +static inline void hpc3_eth_reset(struct hpc3_ethregs *hregs) { hregs->rx_reset = (HPC3_ERXRST_CRESET | HPC3_ERXRST_CLRIRQ); udelay(20); hregs->rx_reset = 0; } -static inline void reset_hpc3_and_seeq(volatile struct hpc3_ethregs *hregs, - volatile struct sgiseeq_regs *sregs) +static inline void reset_hpc3_and_seeq(struct hpc3_ethregs *hregs, + struct sgiseeq_regs *sregs) { hregs->rx_ctrl = hregs->tx_ctrl = 0; hpc3_eth_reset(hregs); @@ -122,15 +128,15 @@ SEEQ_RCMD_IDRIB | SEEQ_RCMD_ICRC) static inline void seeq_go(struct sgiseeq_private *sp, - volatile struct hpc3_ethregs *hregs, - volatile struct sgiseeq_regs *sregs) + struct hpc3_ethregs *hregs, + struct sgiseeq_regs *sregs) { sregs->rstat = sp->mode | RSTAT_GO_BITS; hregs->rx_ctrl = HPC3_ERXCTRL_ACTIVE; } static inline void seeq_load_eaddr(struct net_device *dev, - volatile struct sgiseeq_regs *sregs) + struct sgiseeq_regs *sregs) { int i; @@ -171,7 +177,6 @@ return -ENOMEM; ib->tx_desc[i].buf_vaddr = KSEG1ADDR(buffer); ib->tx_desc[i].tdma.pbuf = PHYSADDR(buffer); -// flush_cache_all(); } ib->tx_desc[i].tdma.cntinfo = (TCNTINFO_INIT); } @@ -186,7 +191,6 @@ return -ENOMEM; ib->rx_desc[i].buf_vaddr = KSEG1ADDR(buffer); ib->rx_desc[i].rdma.pbuf = PHYSADDR(buffer); -// flush_cache_all(); } ib->rx_desc[i].rdma.cntinfo = (RCNTINFO_INIT); } @@ -203,7 +207,7 @@ static int once; struct sgiseeq_rx_desc *r = gpriv->srings.rx_desc; struct sgiseeq_tx_desc *t = gpriv->srings.tx_desc; - volatile struct hpc3_ethregs *hregs = gpriv->hregs; + struct hpc3_ethregs *hregs = gpriv->hregs; int i; if(once) @@ -242,9 +246,9 @@ #define RDMACFG_INIT (HPC3_ERXDCFG_FRXDC | HPC3_ERXDCFG_FEOP | HPC3_ERXDCFG_FIRQ) static int init_seeq(struct net_device *dev, struct sgiseeq_private *sp, - volatile struct sgiseeq_regs *sregs) + struct sgiseeq_regs *sregs) { - volatile struct hpc3_ethregs *hregs = sp->hregs; + struct hpc3_ethregs *hregs = sp->hregs; int err; reset_hpc3_and_seeq(hregs, sregs); @@ -285,8 +289,8 @@ } static inline void rx_maybe_restart(struct sgiseeq_private *sp, - volatile struct hpc3_ethregs *hregs, - volatile struct sgiseeq_regs *sregs) + struct hpc3_ethregs *hregs, + struct sgiseeq_regs *sregs) { if (!(hregs->rx_ctrl & HPC3_ERXCTRL_ACTIVE)) { hregs->rx_ndptr = PHYSADDR(&sp->srings.rx_desc[sp->rx_new]); @@ -299,8 +303,8 @@ (rd) = &(sp)->srings.rx_desc[(sp)->rx_new]) static inline void sgiseeq_rx(struct net_device *dev, struct sgiseeq_private *sp, - volatile struct hpc3_ethregs *hregs, - volatile struct sgiseeq_regs *sregs) + struct hpc3_ethregs *hregs, + struct sgiseeq_regs *sregs) { struct sgiseeq_rx_desc *rd; struct sk_buff *skb = 0; @@ -332,7 +336,7 @@ sp->stats.rx_packets++; sp->stats.rx_bytes += len; } else { - printk ("%s: Memory squeeze, deferring packet.\n", + printk (KERN_NOTICE "%s: Memory squeeze, deferring packet.\n", dev->name); sp->stats.rx_dropped++; } @@ -350,7 +354,7 @@ } static inline void tx_maybe_reset_collisions(struct sgiseeq_private *sp, - volatile struct sgiseeq_regs *sregs) + struct sgiseeq_regs *sregs) { if (sp->is_edlc) { sregs->rw.wregs.control = sp->control & ~(SEEQ_CTRL_XCNT); @@ -359,7 +363,7 @@ } static inline void kick_tx(struct sgiseeq_tx_desc *td, - volatile struct hpc3_ethregs *hregs) + struct hpc3_ethregs *hregs) { /* If the HPC aint doin nothin, and there are more packets * with ETXD cleared and XIU set we must make very certain @@ -377,8 +381,8 @@ } static inline void sgiseeq_tx(struct net_device *dev, struct sgiseeq_private *sp, - volatile struct hpc3_ethregs *hregs, - volatile struct sgiseeq_regs *sregs) + struct hpc3_ethregs *hregs, + struct sgiseeq_regs *sregs) { struct sgiseeq_tx_desc *td; unsigned long status = hregs->tx_ctrl; @@ -420,8 +424,8 @@ { struct net_device *dev = (struct net_device *) dev_id; struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv; - volatile struct hpc3_ethregs *hregs = sp->hregs; - volatile struct sgiseeq_regs *sregs = sp->sregs; + struct hpc3_ethregs *hregs = sp->hregs; + struct sgiseeq_regs *sregs = sp->sregs; /* Ack the IRQ and set software state. */ hregs->rx_reset = HPC3_ERXRST_CLRIRQ; @@ -429,7 +433,7 @@ /* Always check for received packets. */ sgiseeq_rx(dev, sp, hregs, sregs); - /* Only check for tx acks iff we have something queued. */ + /* Only check for tx acks if we have something queued. */ if (sp->tx_old != sp->tx_new) sgiseeq_tx(dev, sp, hregs, sregs); @@ -442,47 +446,34 @@ static int sgiseeq_open(struct net_device *dev) { struct sgiseeq_private *sp = (struct sgiseeq_private *)dev->priv; - volatile struct sgiseeq_regs *sregs = sp->sregs; - unsigned long flags; - int err; - - local_irq_save(flags); + struct sgiseeq_regs *sregs = sp->sregs; - err = -EAGAIN; - if (request_irq(dev->irq, sgiseeq_interrupt, 0, sgiseeqstr, dev)) { - printk("Seeq8003: Can't get irq %d\n", dev->irq); - goto out; - } - err = init_seeq(dev, sp, sregs); + int err = init_seeq(dev, sp, sregs); if (err) - goto out; + return err; netif_start_queue(dev); -out: - local_irq_restore(flags); - return err; + return 0; } static int sgiseeq_close(struct net_device *dev) { struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv; - volatile struct sgiseeq_regs *sregs = sp->sregs; + struct sgiseeq_regs *sregs = sp->sregs; netif_stop_queue(dev); /* Shutdown the Seeq. */ reset_hpc3_and_seeq(sp->hregs, sregs); - free_irq(dev->irq, dev); - return 0; } static inline int sgiseeq_reset(struct net_device *dev) { struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv; - volatile struct sgiseeq_regs *sregs = sp->sregs; + struct sgiseeq_regs *sregs = sp->sregs; int err; err = init_seeq(dev, sp, sregs); @@ -504,12 +495,12 @@ static int sgiseeq_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv; - volatile struct hpc3_ethregs *hregs = sp->hregs; + struct hpc3_ethregs *hregs = sp->hregs; unsigned long flags; struct sgiseeq_tx_desc *td; int skblen, len, entry; - save_and_cli(flags); + local_irq_save(flags); /* Setup... */ skblen = skb->len; @@ -553,14 +544,14 @@ if (!TX_BUFFS_AVAIL(sp)) netif_stop_queue(dev); - restore_flags(flags); + local_irq_restore(flags); return 0; } static void timeout(struct net_device *dev) { - printk("%s: transmit timed out, resetting\n", dev->name); + printk(KERN_NOTICE "%s: transmit timed out, resetting\n", dev->name); sgiseeq_reset(dev); dev->trans_start = jiffies; @@ -603,41 +594,56 @@ buf[i].rdma.pnext = PHYSADDR(&buf[0]); } -static char onboard_eth_addr[6]; - #define ALIGNED(x) ((((unsigned long)(x)) + 0xf) & ~(0xf)) -int sgiseeq_init(struct net_device *dev, struct sgiseeq_regs *sregs, - struct hpc3_ethregs *hregs, int irq) +int sgiseeq_init(struct hpc3_regs* regs, int irq) { - static unsigned version_printed; - int i; + struct net_device *dev; struct sgiseeq_private *sp; - - dev->priv = (struct sgiseeq_private *) get_zeroed_page(GFP_KERNEL); - if (dev->priv == NULL) + int i; + + sp = (struct sgiseeq_private *) get_zeroed_page(GFP_KERNEL); + if (!sp) { + printk (KERN_ERR + "Seeq8003: Could not allocate private data.\n"); return -ENOMEM; + } - if (!version_printed++) - printk(version); - - printk("%s: SGI Seeq8003 ", dev->name); - - for (i = 0; i < 6; i++) - printk("%2.2x%c", - dev->dev_addr[i] = onboard_eth_addr[i], - i == 5 ? ' ': ':'); + dev = init_etherdev(NULL, 0); + if (!dev) { + printk (KERN_ERR + "Seeq8003: Could not allocate memory for device.\n"); + free_page((unsigned long) sp); + return -ENOMEM; + } + if (request_irq(irq, sgiseeq_interrupt, 0, sgiseeqstr, dev)) { + printk(KERN_ERR "Seeq8003: Can't get irq %d\n", dev->irq); + free_page((unsigned long) sp); + unregister_netdev(dev); + return -EAGAIN; + } + + printk(KERN_INFO "%s: SGI Seeq8003 ", dev->name); + +#define EADDR_NVOFS 250 + for (i = 0; i < 3; i++) { + unsigned short tmp = ip22_nvram_read(EADDR_NVOFS / 2 + i); + + printk("%2.2x:%2.2x%c", + dev->dev_addr[2 * i] = tmp >> 8, + dev->dev_addr[2 * i + 1] = tmp & 0xff, + i == 2 ? ' ' : ':'); + } printk("\n"); - sp = (struct sgiseeq_private *) dev->priv; + dev->priv = sp; #ifdef DEBUG gpriv = sp; gdev = dev; #endif - memset((char *)dev->priv, 0, sizeof(struct sgiseeq_private)); - sp->sregs = sregs; - sp->hregs = hregs; + sp->sregs = (struct sgiseeq_regs *) &hpc3c0->eth_ext[0]; + sp->hregs = &hpc3c0->ethregs; sp->name = sgiseeqstr; sp->srings.rx_desc = (struct sgiseeq_rx_desc *) @@ -654,14 +660,13 @@ setup_tx_ring(sp->srings.tx_desc, SEEQ_TX_BUFFERS); /* Reset the chip. */ - hpc3_eth_reset((volatile struct hpc3_ethregs *) hregs); + hpc3_eth_reset(sp->hregs); - sp->is_edlc = !(sregs->rw.rregs.collision_tx[0] & 0xff); - if (sp->is_edlc) { + sp->is_edlc = !(sp->sregs->rw.rregs.collision_tx[0] & 0xff); + if (sp->is_edlc) sp->control = (SEEQ_CTRL_XCNT | SEEQ_CTRL_ACCNT | SEEQ_CTRL_SFLAG | SEEQ_CTRL_ESHORT | SEEQ_CTRL_ENCARR); - } dev->open = sgiseeq_open; dev->stop = sgiseeq_close; @@ -674,51 +679,37 @@ dev->dma = 0; ether_setup(dev); + sp->next_module = root_sgiseeq_dev; + root_sgiseeq_dev = dev; + return 0; } -static inline unsigned char str2hexnum(unsigned char c) +static int __init sgiseeq_probe(void) { - if (c >= '0' && c <= '9') - return c - '0'; - if (c >= 'a' && c <= 'f') - return c - 'a' + 10; - return 0; /* foo */ + printk(version); + + /* On board adapter on 1st HPC is always present */ + return sgiseeq_init(hpc3c0, SGI_ENET_IRQ); } -static inline void str2eaddr(unsigned char *ea, unsigned char *str) +static void __exit sgiseeq_exit(void) { - int i; - - for (i = 0; i < 6; i++) { - unsigned char num; + struct sgiseeq_private *sp; + struct net_device *next, *dev = root_sgiseeq_dev; - if(*str == ':') - str++; - num = str2hexnum(*str++) << 4; - num |= (str2hexnum(*str++)); - ea[i] = num; + while (dev) { + sp = (struct sgiseeq_private *) dev->priv; + next = sp->next_module; + free_irq(dev->irq, dev); + free_page((unsigned long) sp); + unregister_netdev(dev); + kfree(dev); + dev = next; } } -int sgiseeq_probe(struct net_device *dev) -{ - static int initialized; - char *ep; - - if (initialized) /* Already initialized? */ - return 1; - initialized++; - - /* First get the ethernet address of the onboard interface from ARCS. - * This is fragile; PROM doesn't like running from cache. - * On MIPS64 it crashes for some other, yet unknown reason ... - */ - ep = ArcGetEnvironmentVariable("eaddr"); - str2eaddr(onboard_eth_addr, ep); - return sgiseeq_init(dev, - (struct sgiseeq_regs *) (KSEG1ADDR(0x1fbd4000)), - &hpc3c0->ethregs, SGI_ENET_IRQ); -} +module_init(sgiseeq_probe); +module_exit(sgiseeq_exit); MODULE_LICENSE("GPL"); diff -Nru a/drivers/net/sgiseeq.h b/drivers/net/sgiseeq.h --- a/drivers/net/sgiseeq.h Tue Jul 1 18:44:34 2003 +++ b/drivers/net/sgiseeq.h Tue Jul 1 18:44:34 2003 @@ -1,4 +1,4 @@ -/* $Id: sgiseeq.h,v 1.4 1999/10/09 00:01:24 ralf Exp $ +/* * sgiseeq.h: Defines for the Seeq8003 ethernet controller. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) diff -Nru a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c --- a/drivers/net/sk98lin/skge.c Tue Jul 1 18:44:32 2003 +++ b/drivers/net/sk98lin/skge.c Tue Jul 1 18:44:32 2003 @@ -48,6 +48,9 @@ * History: * * $Log: skge.c,v $ + * Revision x.xx.x.x 2003/06/07 02:31:17 romieu@fr.zoreil.com + * pci api style init. + * * Revision 1.29.2.6 2001/05/21 07:59:29 mlindner * fix: MTU init problems * @@ -275,6 +278,10 @@ #include "h/skdrv2nd.h" /* defines ******************************************************************/ + +#define DRV_MODULE_NAME "sk98lin" +#define PFX DRV_MODULE_NAME ": " + /* for debuging on x86 only */ /* #define BREAKPOINT() asm(" int $3"); */ @@ -361,9 +368,7 @@ /* global variables *********************************************************/ -static const char *BootString = BOOT_STRING; -struct net_device *sk98lin_root_dev = NULL; -static int probed __initdata = 0; +static int boards_found; struct inode_operations SkInodeOps; //static struct file_operations SkFileOps; /* with open/relase */ @@ -371,236 +376,219 @@ static uintptr_t TxQueueAddr[SK_MAX_MACS][2] = {{0x680, 0x600},{0x780, 0x700}}; static uintptr_t RxQueueAddr[SK_MAX_MACS] = {0x400, 0x480}; +spinlock_t sk_devs_lock = SPIN_LOCK_UNLOCKED; + +static int SkGeDevInit(struct net_device *dev) +{ + DEV_NET *pNet = dev->priv; + int ret = 0; + + dev->open = &SkGeOpen; + dev->stop = &SkGeClose; + dev->hard_start_xmit = &SkGeXmit; + dev->get_stats = &SkGeStats; + dev->set_multicast_list = &SkGeSetRxMode; + dev->set_mac_address = &SkGeSetMacAddr; + dev->do_ioctl = &SkGeIoctl; + dev->change_mtu = &SkGeChangeMtu; + + if (register_netdev(dev) != 0) { + printk(KERN_ERR "Unable to register etherdev\n"); + ret = -ENOMEM; + goto out; + } + pNet->proc = create_proc_entry(dev->name, S_IFREG | 0444, pSkRootDir); + if (pNet->proc) { + pNet->proc->data = dev; + pNet->proc->owner = THIS_MODULE; + pNet->proc->proc_fops = &sk_proc_fops; + } +out: + return ret; +} + +static void SkGeDevCleanUp(struct net_device *dev) +{ + DEV_NET *pNet = dev->priv; + + if (pNet->proc) { + spin_lock(&sk_devs_lock); + pNet->proc->data = NULL; + spin_unlock(&sk_devs_lock); + remove_proc_entry(dev->name, pSkRootDir); + } + unregister_netdev(dev); +} /***************************************************************************** * - * skge_probe - find all SK-98xx adapters + * skge_init_one - init a single instance of a SK-98xx adapter * * Description: - * This function scans the PCI bus for SK-98xx adapters. Resources for - * each adapter are allocated and the adapter is brought into Init 1 - * state. + * This function allocates resources for an SK-98xx adapter and brings + * it into Init 1 state. * * Returns: * 0, if everything is ok - * !=0, on error + * <0, on error */ -static int __init skge_probe (void) +static int __devinit skge_init_one(struct pci_dev *pdev, + const struct pci_device_id *ent) { - int proc_root_initialized = 0; - int boards_found = 0; - int version_disp = 0; SK_AC *pAC; - DEV_NET *pNet = NULL; - struct pci_dev *pdev = NULL; - unsigned long base_address; - struct net_device *dev = NULL; - - if (probed) - return -ENODEV; - probed++; - - /* display driver info */ - if (!version_disp) - { - /* set display flag to TRUE so that */ - /* we only display this string ONCE */ - version_disp = 1; - printk("%s\n", BootString); - } + DEV_NET *pNet; + unsigned long base_address; + struct net_device *dev; + int ret; - while((pdev = pci_find_device(PCI_VENDOR_ID_SYSKONNECT, - PCI_DEVICE_ID_SYSKONNECT_GE, pdev)) != NULL) { - - pNet = NULL; +#ifndef MODULE + static int version_disp = 0; - if (pci_enable_device(pdev)) - continue; +if (!version_disp++) + printk(KERN_INFO "%s\n", BOOT_STRING); +#endif + ret = pci_enable_device(pdev); + if (ret) + goto out; - /* Configure DMA attributes. */ - if (pci_set_dma_mask(pdev, (u64) 0xffffffffffffffffULL) && - pci_set_dma_mask(pdev, (u64) 0xffffffff)) - continue; - - dev = alloc_etherdev(sizeof(DEV_NET)); - if (!dev) { - printk(KERN_ERR "Unable to allocate etherdev " - "structure!\n"); - break; + /* Configure DMA attributes. */ + if (pci_set_dma_mask(pdev, (u64) 0xffffffffffffffff)) { + ret = pci_set_dma_mask(pdev, (u64) 0xffffffff); + if (ret) { + printk(KERN_ERR PFX "No usable DMA configuration\n"); + goto out_disable; } + } - pNet = dev->priv; - pNet->pAC = kmalloc(sizeof(SK_AC), GFP_KERNEL); - if (pNet->pAC == NULL){ - kfree(dev); - printk(KERN_ERR "Unable to allocate adapter " - "structure!\n"); - break; - } + ret = -ENOMEM; - memset(pNet->pAC, 0, sizeof(SK_AC)); - pAC = pNet->pAC; - pAC->PciDev = *pdev; - pAC->PciDevId = pdev->device; - pAC->dev[0] = dev; - pAC->dev[1] = dev; - sprintf(pAC->Name, "SysKonnect SK-98xx"); - pAC->CheckQueue = SK_FALSE; + dev = alloc_etherdev(sizeof(DEV_NET)); + if (!dev) { + printk(KERN_ERR "Unable to allocate etherdev structure!\n"); + goto out_disable; + } + + pNet = dev->priv; + + pAC = kmalloc(sizeof(*pAC), GFP_KERNEL); + if (pAC == NULL){ + printk(KERN_ERR "Unable to allocate adapter structure!\n"); + goto out_free_dev; + } + + memset(pAC, 0, sizeof(SK_AC)); + pNet->pAC = pAC; + pAC->PciDev = *pdev; + pAC->PciDevId = pdev->device; + pAC->dev[0] = dev; + pAC->dev[1] = dev; + sprintf(pAC->Name, "SysKonnect SK-98xx"); + pAC->CheckQueue = SK_FALSE; - pNet->Mtu = 1500; - pNet->Up = 0; - dev->irq = pdev->irq; + pNet->Mtu = 1500; + pNet->Up = 0; + dev->irq = pdev->irq; - SET_MODULE_OWNER(dev); - SET_NETDEV_DEV(dev, &pdev->dev); - dev->open = &SkGeOpen; - dev->stop = &SkGeClose; - dev->hard_start_xmit = &SkGeXmit; - dev->get_stats = &SkGeStats; - dev->set_multicast_list = &SkGeSetRxMode; - dev->set_mac_address = &SkGeSetMacAddr; - dev->do_ioctl = &SkGeIoctl; - dev->change_mtu = &SkGeChangeMtu; - - if(!proc_root_initialized) { - pSkRootDir = create_proc_entry(SK_Root_Dir_entry, - S_IFDIR | S_IWUSR | S_IRUGO | S_IXUGO, proc_net); - pSkRootDir->owner = THIS_MODULE; - proc_root_initialized = 1; - } + SET_MODULE_OWNER(dev); + SET_NETDEV_DEV(dev, &pdev->dev); + ret = SkGeDevInit(dev); + if (ret < 0) + goto out_free_priv; - /* - * Dummy value. - */ - dev->base_addr = 42; - pci_set_master(pdev); - base_address = pci_resource_start (pdev, 0); + /* + * Dummy value. + */ + dev->base_addr = 42; + pci_set_master(pdev); + base_address = pci_resource_start(pdev, 0); #ifdef SK_BIG_ENDIAN - /* - * On big endian machines, we use the adapter's aibility of - * reading the descriptors as big endian. - */ - { + /* + * On big endian machines, we use the adapter's ability of + * reading the descriptors as big endian. + */ + { SK_U32 our2; - SkPciReadCfgDWord(pAC, PCI_OUR_REG_2, &our2); - our2 |= PCI_REV_DESC; - SkPciWriteCfgDWord(pAC, PCI_OUR_REG_2, our2); - } + SkPciReadCfgDWord(pAC, PCI_OUR_REG_2, &our2); + our2 |= PCI_REV_DESC; + SkPciWriteCfgDWord(pAC, PCI_OUR_REG_2, our2); + } #endif /* BIG ENDIAN */ - /* - * Remap the regs into kernel space. - */ + /* + * Remap the regs into kernel space. + */ - pAC->IoBase = (char*)ioremap(base_address, 0x4000); - if (!pAC->IoBase){ - printk(KERN_ERR "%s: Unable to map I/O register, " - "SK 98xx No. %i will be disabled.\n", - dev->name, boards_found); - kfree(dev); - break; - } - pAC->Index = boards_found; + pAC->IoBase = (char*)ioremap(base_address, 0x4000); + if (!pAC->IoBase) { + printk(KERN_ERR PFX "unable to map I/O register. " + "SK 98xx device disabled.\n"); + ret = -EIO; + goto out_dev_uninit; + } + pAC->Index = boards_found++; + + ret = SkGeBoardInit(dev, pAC); + if (ret < 0) + goto out_free_resources; + + memcpy((caddr_t) &dev->dev_addr, + (caddr_t) &pAC->Addr.Net[0].CurrentMacAddress, 6); + + pNet->PortNr = 0; + pNet->NetNr = 0; + + /* More then one port found */ + if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) { + struct net_device *sec_dev; + + sec_dev = alloc_etherdev(sizeof(DEV_NET)); + if (!sec_dev) { + printk(KERN_ERR PFX + "Unable to allocate etherdev structure!\n"); + ret = -ENOMEM; + goto out_free_resources; + } + + pAC->dev[1] = sec_dev; + pNet = sec_dev->priv; + pNet->PortNr = 1; + pNet->NetNr = 1; + pNet->pAC = pAC; + pNet->Mtu = 1500; + pNet->Up = 0; - if (SkGeBoardInit(dev, pAC)) { - FreeResources(dev); - kfree(dev); - continue; - } + ret = SkGeDevInit(sec_dev); + if (ret < 0) + goto out_free_secondary_dev; - memcpy((caddr_t) &dev->dev_addr, + memcpy((caddr_t) &sec_dev->dev_addr, (caddr_t) &pAC->Addr.Net[0].CurrentMacAddress, 6); - pNet->PortNr = 0; - pNet->NetNr = 0; - - if (register_netdev(dev) != 0) { - printk(KERN_ERR "Unable to register etherdev\n"); - sk98lin_root_dev = pAC->Next; - remove_proc_entry(dev->name, pSkRootDir); - FreeResources(dev); - kfree(dev); - continue; - } - - pNet->proc = create_proc_entry(dev->name, - S_IFREG | 0444, pSkRootDir); - if (pNet->proc) { - pNet->proc->data = dev; - pNet->proc->owner = THIS_MODULE; - pNet->proc->proc_fops = &sk_proc_fops; - } - - boards_found++; - - /* More then one port found */ - if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) { - dev = alloc_etherdev(sizeof(DEV_NET)); - if (!dev) { - printk(KERN_ERR "Unable to allocate etherdev " - "structure!\n"); - break; - } - - pAC->dev[1] = dev; - pNet = dev->priv; - pNet->PortNr = 1; - pNet->NetNr = 1; - pNet->pAC = pAC; - pNet->Mtu = 1500; - pNet->Up = 0; - - dev->open = &SkGeOpen; - dev->stop = &SkGeClose; - dev->hard_start_xmit = &SkGeXmit; - dev->get_stats = &SkGeStats; - dev->set_multicast_list = &SkGeSetRxMode; - dev->set_mac_address = &SkGeSetMacAddr; - dev->do_ioctl = &SkGeIoctl; - dev->change_mtu = &SkGeChangeMtu; - - memcpy((caddr_t) &dev->dev_addr, - (caddr_t) &pAC->Addr.Net[1].CurrentMacAddress, 6); - - printk("%s: %s\n", dev->name, pAC->DeviceStr); - printk(" PrefPort:B RlmtMode:Dual Check Link State\n"); - - if (register_netdev(dev) != 0) { - printk(KERN_ERR "Unable to register etherdev\n"); - kfree(dev); - break; - } - - pNet->proc = create_proc_entry(dev->name, - S_IFREG | 0444, pSkRootDir); - if (pNet->proc) { - pNet->proc->data = dev; - pNet->proc->owner = THIS_MODULE; - pNet->proc->proc_fops = &sk_proc_fops; - } - - } - - - /* - * This is bollocks, but we need to tell the net-init - * code that it shall go for the next device. - */ -#ifndef MODULE - dev->base_addr = 0; -#endif + printk("%s: %s\n", sec_dev->name, pAC->DeviceStr); + printk(" PrefPort:B RlmtMode:Dual Check Link State\n"); } + pci_set_drvdata(pdev, dev); - /* - * If we're at this point we're going through skge_probe() for - * the first time. Return success (0) if we've initialized 1 - * or more boards. Otherwise, return failure (-ENODEV). - */ - - return boards_found; -} /* skge_probe */ + ret = 0; +out: + return ret; + +out_free_secondary_dev: + kfree(pAC->dev[1]); +out_free_resources: + FreeResources(dev); +out_dev_uninit: + SkGeDevCleanUp(dev); +out_free_priv: + kfree(pAC); +out_free_dev: + kfree(dev); +out_disable: + pci_disable_device(pdev); + goto out; +} /* skge_init_one */ /***************************************************************************** * @@ -718,39 +706,9 @@ static int debug = 0; /* not used */ static int options[SK_MAX_CARD_PARAM] = {0, }; /* not used */ - -/***************************************************************************** - * - * skge_init_module - module initialization function - * - * Description: - * Very simple, only call skge_probe and return approriate result. - * - * Returns: - * 0, if everything is ok - * !=0, on error - */ -static int __init skge_init_module(void) -{ - int cards; - sk98lin_root_dev = NULL; - - /* just to avoid warnings ... */ - debug = 0; - options[0] = 0; - - cards = skge_probe(); - if (cards == 0) { - printk("No adapter found\n"); - } - return cards ? 0 : -ENODEV; -} /* skge_init_module */ - -spinlock_t sk_devs_lock = SPIN_LOCK_UNLOCKED; - /***************************************************************************** * - * skge_cleanup_module - module unload function + * skge_remove_one - remove a single instance of a SK-98xx adapter * * Description: * Disable adapter if it is still running, free resources, @@ -758,82 +716,65 @@ * * Returns: N/A */ -static void __exit skge_cleanup_module(void) +static void __devexit skge_remove_one(struct pci_dev *pdev) { -DEV_NET *pNet; -SK_AC *pAC; -struct net_device *next; -unsigned long Flags; -SK_EVPARA EvPara; + struct net_device *dev = pci_get_drvdata(pdev); + DEV_NET *pNet = dev->priv; + SK_AC *pAC = pNet->pAC; + unsigned long Flags; + SK_EVPARA EvPara; - while (sk98lin_root_dev) { - pNet = (DEV_NET*) sk98lin_root_dev->priv; - pAC = pNet->pAC; - next = pAC->Next; - netif_stop_queue(sk98lin_root_dev); - SkGeYellowLED(pAC, pAC->IoBase, 0); - if (pNet->proc) { - spin_lock(&sk_devs_lock); - pNet->proc->data = NULL; - spin_unlock(&sk_devs_lock); - } - - if(pAC->BoardLevel == 2) { - /* board is still alive */ - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - EvPara.Para32[0] = 0; - EvPara.Para32[1] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); - EvPara.Para32[0] = 1; - EvPara.Para32[1] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); - SkEventDispatcher(pAC, pAC->IoBase); - /* disable interrupts */ - SK_OUT32(pAC->IoBase, B0_IMSK, 0); - SkGeDeInit(pAC, pAC->IoBase); - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - pAC->BoardLevel = 0; - /* We do NOT check here, if IRQ was pending, of course*/ - } - - if(pAC->BoardLevel == 1) { - /* board is still alive */ - SkGeDeInit(pAC, pAC->IoBase); - pAC->BoardLevel = 0; - } - - if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 2){ - pNet = (DEV_NET*) pAC->dev[1]->priv; - if (pNet->proc) { - spin_lock(&sk_devs_lock); - pNet->proc->data = NULL; - spin_unlock(&sk_devs_lock); - } - unregister_netdev(pAC->dev[1]); - kfree(pAC->dev[1]); - } + netif_stop_queue(dev); + SkGeYellowLED(pAC, pAC->IoBase, 0); + if (pNet->proc) { + spin_lock(&sk_devs_lock); + pNet->proc->data = NULL; + spin_unlock(&sk_devs_lock); + remove_proc_entry(dev->name, pSkRootDir); + } - FreeResources(sk98lin_root_dev); + if (pAC->BoardLevel == 2) { + /* board is still alive */ + spin_lock_irqsave(&pAC->SlowPathLock, Flags); + EvPara.Para32[0] = 0; + EvPara.Para32[1] = -1; + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); + EvPara.Para32[0] = 1; + EvPara.Para32[1] = -1; + SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); + SkEventDispatcher(pAC, pAC->IoBase); + /* disable interrupts */ + SK_OUT32(pAC->IoBase, B0_IMSK, 0); + SkGeDeInit(pAC, pAC->IoBase); + spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); + pAC->BoardLevel = 0; + /* We do NOT check here, if IRQ was pending, of course*/ + } - sk98lin_root_dev->get_stats = NULL; - /* - * otherwise unregister_netdev calls get_stats with - * invalid IO ... :-( - */ - unregister_netdev(sk98lin_root_dev); - kfree(sk98lin_root_dev); - kfree(pAC); - sk98lin_root_dev = next; + if (pAC->BoardLevel == 1) { + /* board is still alive */ + SkGeDeInit(pAC, pAC->IoBase); + pAC->BoardLevel = 0; } - /* clear proc-dir */ - remove_proc_entry(pSkRootDir->name, proc_net); + if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 2) { + SkGeDevCleanUp(pAC->dev[1]); + kfree(pAC->dev[1]); + } -} /* skge_cleanup_module */ + FreeResources(dev); -module_init(skge_init_module); -module_exit(skge_cleanup_module); + dev->get_stats = NULL; + /* + * otherwise unregister_netdev calls get_stats with + * invalid IO ... :-( + */ + unregister_netdev(dev); + kfree(dev); + kfree(pAC); + boards_found--; +} /* skge_remove_one */ /***************************************************************************** * @@ -968,12 +909,6 @@ SkGeYellowLED(pAC, pAC->IoBase, 1); - /* - * Register the device here - */ - pAC->Next = sk98lin_root_dev; - sk98lin_root_dev = dev; - return (0); } /* SkGeBoardInit */ @@ -4097,9 +4032,62 @@ #endif /* DEBUG */ +static struct pci_device_id skge_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_GE, + PCI_ANY_ID, PCI_ANY_ID, }, + { 0,} +}; +MODULE_DEVICE_TABLE(pci, skge_pci_tbl); + +static struct pci_driver skge_driver = { + .name = DRV_MODULE_NAME, + .id_table = skge_pci_tbl, + .probe = skge_init_one, + .remove = __devexit_p(skge_remove_one), +}; + +/***************************************************************************** + * + * skge_init - module initialization function + * + * Description: + * root /proc directory allocation and pci driver invocation. + * + * Returns: + * 0, if everything is ok + * !=0, on error + */ +static int __init skge_init(void) +{ + int ret = -ENOMEM; + + /* just to avoid warnings ... */ + debug = 0; + options[0] = 0; + + pSkRootDir = create_proc_entry(DRV_MODULE_NAME, + S_IFDIR | S_IWUSR | S_IRUGO | S_IXUGO, proc_net); + if (pSkRootDir) { + pSkRootDir->owner = THIS_MODULE; + ret = pci_module_init(&skge_driver); + if (ret) + remove_proc_entry(pSkRootDir->name, proc_net); + } + return ret; +} /* skge_init */ + + +static void __exit skge_cleanup(void) +{ + remove_proc_entry(pSkRootDir->name, proc_net); + pci_unregister_driver(&skge_driver); +} + +module_init(skge_init); +module_exit(skge_cleanup); + /* * Local variables: * compile-command: "make" * End: */ - diff -Nru a/drivers/net/sungem.c b/drivers/net/sungem.c --- a/drivers/net/sungem.c Tue Jul 1 18:44:38 2003 +++ b/drivers/net/sungem.c Tue Jul 1 18:44:38 2003 @@ -2384,9 +2384,6 @@ return 0; case ETHTOOL_SSET: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - /* Verify the settings we care about. */ if (ecmd.autoneg != AUTONEG_ENABLE && ecmd.autoneg != AUTONEG_DISABLE) diff -Nru a/drivers/net/sunhme.c b/drivers/net/sunhme.c --- a/drivers/net/sunhme.c Tue Jul 1 18:44:34 2003 +++ b/drivers/net/sunhme.c Tue Jul 1 18:44:34 2003 @@ -2481,9 +2481,6 @@ return -EFAULT; return 0; } else if (ecmd.cmd == ETHTOOL_SSET) { - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - /* Verify the settings we care about. */ if (ecmd.autoneg != AUTONEG_ENABLE && ecmd.autoneg != AUTONEG_DISABLE) diff -Nru a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c --- a/drivers/net/tulip/de2104x.c Tue Jul 1 18:44:37 2003 +++ b/drivers/net/tulip/de2104x.c Tue Jul 1 18:44:37 2003 @@ -77,7 +77,6 @@ #define DE_DEF_MSG_ENABLE (NETIF_MSG_DRV | \ NETIF_MSG_PROBE | \ NETIF_MSG_LINK | \ - NETIF_MSG_TIMER | \ NETIF_MSG_IFDOWN | \ NETIF_MSG_IFUP | \ NETIF_MSG_RX_ERR | \ diff -Nru a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c --- a/drivers/net/tulip/tulip_core.c Tue Jul 1 18:44:35 2003 +++ b/drivers/net/tulip/tulip_core.c Tue Jul 1 18:44:35 2003 @@ -94,6 +94,8 @@ static int csr0 = 0x01A00000 | 0x9000; #elif defined(__arm__) || defined(__sh__) static int csr0 = 0x01A00000 | 0x4800; +#elif defined(__mips__) +static int csr0 = 0x00200000 | 0x4000; #else #warning Processor architecture undefined! static int csr0 = 0x00A00000 | 0x4800; @@ -1486,6 +1488,16 @@ #ifdef CONFIG_DDB5477 if ((pdev->bus->number == 0) && (PCI_SLOT(pdev->devfn) == 4)) { /* DDB5477 MAC address in first EEPROM locations. */ + sa_offset = 0; + /* No media table either */ + tp->flags &= ~HAS_MEDIA_TABLE; + } +#endif +#ifdef CONFIG_MIPS_COBALT + if ((pdev->bus->number == 0) && + ((PCI_SLOT(pdev->devfn) == 7) || + (PCI_SLOT(pdev->devfn) == 12))) { + /* Cobalt MAC address in first EEPROM locations. */ sa_offset = 0; /* No media table either */ tp->flags &= ~HAS_MEDIA_TABLE; diff -Nru a/drivers/net/typhoon.c b/drivers/net/typhoon.c --- a/drivers/net/typhoon.c Tue Jul 1 18:44:36 2003 +++ b/drivers/net/typhoon.c Tue Jul 1 18:44:36 2003 @@ -40,7 +40,7 @@ /* Set the copy breakpoint for the copy-only-tiny-frames scheme. * Setting to > 1518 effectively disables this feature. */ -static int rx_copybreak = 0; +static int rx_copybreak = 200; /* end user-configurable values */ @@ -85,8 +85,8 @@ #define PKT_BUF_SZ 1536 #define DRV_MODULE_NAME "typhoon" -#define DRV_MODULE_VERSION "1.0" -#define DRV_MODULE_RELDATE "03/02/14" +#define DRV_MODULE_VERSION "1.5.1" +#define DRV_MODULE_RELDATE "03/06/26" #define PFX DRV_MODULE_NAME ": " #define ERR_PFX KERN_ERR PFX @@ -150,7 +150,7 @@ #define TYPHOON_CRYPTO_DES 1 #define TYPHOON_CRYPTO_3DES 2 #define TYPHOON_CRYPTO_VARIABLE 4 -#define TYPHOON_FIBER 5 +#define TYPHOON_FIBER 8 enum typhoon_cards { TYPHOON_TX = 0, TYPHOON_TX95, TYPHOON_TX97, TYPHOON_SVR, @@ -1798,7 +1798,7 @@ u32 intr_status; intr_status = readl(ioaddr + TYPHOON_REG_INTR_STATUS); - if(!intr_status) + if(!(intr_status & TYPHOON_INTR_HOST_INT)) return IRQ_NONE; writel(intr_status, ioaddr + TYPHOON_REG_INTR_STATUS); diff -Nru a/drivers/net/wan/sdla_chdlc.c b/drivers/net/wan/sdla_chdlc.c --- a/drivers/net/wan/sdla_chdlc.c Tue Jul 1 18:44:35 2003 +++ b/drivers/net/wan/sdla_chdlc.c Tue Jul 1 18:44:35 2003 @@ -996,13 +996,11 @@ set_bit(0,&chdlc_priv_area->config_chdlc); chdlc_priv_area->config_chdlc_timeout=jiffies; - del_timer(&chdlc_priv_area->poll_delay_timer); /* Start the CHDLC configuration after 1sec delay. * This will give the interface initilization time * to finish its configuration */ - chdlc_priv_area->poll_delay_timer.expires=jiffies+HZ; - add_timer(&chdlc_priv_area->poll_delay_timer); + mod_timer(&chdlc_priv_area->poll_delay_timer, jiffies + HZ); return err; } diff -Nru a/drivers/net/wan/sdla_fr.c b/drivers/net/wan/sdla_fr.c --- a/drivers/net/wan/sdla_fr.c Tue Jul 1 18:44:39 2003 +++ b/drivers/net/wan/sdla_fr.c Tue Jul 1 18:44:39 2003 @@ -4163,9 +4163,7 @@ { fr_channel_t* chan = dev->priv; - del_timer(&chan->fr_arp_timer); - chan->fr_arp_timer.expires = jiffies + (chan->inarp_interval * HZ); - add_timer(&chan->fr_arp_timer); + mod_timer(&chan->fr_arp_timer, jiffies + chan->inarp_interval * HZ); return; } diff -Nru a/drivers/net/wan/sdla_ppp.c b/drivers/net/wan/sdla_ppp.c --- a/drivers/net/wan/sdla_ppp.c Tue Jul 1 18:44:33 2003 +++ b/drivers/net/wan/sdla_ppp.c Tue Jul 1 18:44:33 2003 @@ -762,9 +762,7 @@ /* Start the PPP configuration after 1sec delay. * This will give the interface initilization time * to finish its configuration */ - del_timer(&ppp_priv_area->poll_delay_timer); - ppp_priv_area->poll_delay_timer.expires = jiffies+HZ; - add_timer(&ppp_priv_area->poll_delay_timer); + mod_timer(&ppp_priv_area->poll_delay_timer, jiffies + HZ); return 0; } diff -Nru a/drivers/net/wan/sdla_x25.c b/drivers/net/wan/sdla_x25.c --- a/drivers/net/wan/sdla_x25.c Tue Jul 1 18:44:36 2003 +++ b/drivers/net/wan/sdla_x25.c Tue Jul 1 18:44:36 2003 @@ -1235,9 +1235,7 @@ connect(card); S508_S514_unlock(card, &smp_flags); - del_timer(&card->u.x.x25_timer); - card->u.x.x25_timer.expires=jiffies+HZ; - add_timer(&card->u.x.x25_timer); + mod_timer(&card->u.x.x25_timer, jiffies + HZ); } } /* Device is not up until the we are in connected state */ diff -Nru a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c --- a/drivers/net/wireless/airo.c Tue Jul 1 18:44:32 2003 +++ b/drivers/net/wireless/airo.c Tue Jul 1 18:44:32 2003 @@ -2901,6 +2901,7 @@ airo_entry); apriv->proc_entry->uid = proc_uid; apriv->proc_entry->gid = proc_gid; + apriv->proc_entry->owner = THIS_MODULE; /* Setup the StatsDelta */ entry = create_proc_entry("StatsDelta", @@ -2909,6 +2910,7 @@ entry->uid = proc_uid; entry->gid = proc_gid; entry->data = dev; + entry->owner = THIS_MODULE; SETPROC_OPS(entry, proc_statsdelta_ops); /* Setup the Stats */ @@ -2918,6 +2920,7 @@ entry->uid = proc_uid; entry->gid = proc_gid; entry->data = dev; + entry->owner = THIS_MODULE; SETPROC_OPS(entry, proc_stats_ops); /* Setup the Status */ @@ -2927,6 +2930,7 @@ entry->uid = proc_uid; entry->gid = proc_gid; entry->data = dev; + entry->owner = THIS_MODULE; SETPROC_OPS(entry, proc_status_ops); /* Setup the Config */ @@ -2936,6 +2940,7 @@ entry->uid = proc_uid; entry->gid = proc_gid; entry->data = dev; + entry->owner = THIS_MODULE; SETPROC_OPS(entry, proc_config_ops); /* Setup the SSID */ @@ -2945,6 +2950,7 @@ entry->uid = proc_uid; entry->gid = proc_gid; entry->data = dev; + entry->owner = THIS_MODULE; SETPROC_OPS(entry, proc_SSID_ops); /* Setup the APList */ @@ -2954,6 +2960,7 @@ entry->uid = proc_uid; entry->gid = proc_gid; entry->data = dev; + entry->owner = THIS_MODULE; SETPROC_OPS(entry, proc_APList_ops); /* Setup the BSSList */ @@ -2963,6 +2970,7 @@ entry->uid = proc_uid; entry->gid = proc_gid; entry->data = dev; + entry->owner = THIS_MODULE; SETPROC_OPS(entry, proc_BSSList_ops); /* Setup the WepKey */ @@ -2972,6 +2980,7 @@ entry->uid = proc_uid; entry->gid = proc_gid; entry->data = dev; + entry->owner = THIS_MODULE; SETPROC_OPS(entry, proc_wepkey_ops); return 0; @@ -3062,8 +3071,6 @@ StatusRid status_rid; int i; - MOD_INC_USE_COUNT; - if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; memset(file->private_data, 0, sizeof(struct proc_data)); @@ -3143,8 +3150,6 @@ StatsRid stats; int i, j; int *vals = stats.vals; - MOD_INC_USE_COUNT; - if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; @@ -3421,8 +3426,6 @@ struct airo_info *ai = dev->priv; int i; - MOD_INC_USE_COUNT; - if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; memset(file->private_data, 0, sizeof(struct proc_data)); @@ -3692,8 +3695,6 @@ int j=0; int rc; - MOD_INC_USE_COUNT; - if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; memset(file->private_data, 0, sizeof(struct proc_data)); @@ -3742,8 +3743,6 @@ char *ptr; SsidRid SSID_rid; - MOD_INC_USE_COUNT; - if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; memset(file->private_data, 0, sizeof(struct proc_data)); @@ -3788,8 +3787,6 @@ char *ptr; APListRid APList_rid; - MOD_INC_USE_COUNT; - if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; memset(file->private_data, 0, sizeof(struct proc_data)); @@ -3840,8 +3837,6 @@ /* If doLoseSync is not 1, we won't do a Lose Sync */ int doLoseSync = -1; - MOD_INC_USE_COUNT; - if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) return -ENOMEM; memset(file->private_data, 0, sizeof(struct proc_data)); @@ -3904,7 +3899,6 @@ { struct proc_data *data = (struct proc_data *)file->private_data; if ( data->on_close != NULL ) data->on_close( inode, file ); - MOD_DEC_USE_COUNT; if ( data->rbuffer ) kfree( data->rbuffer ); if ( data->wbuffer ) kfree( data->wbuffer ); kfree( data ); diff -Nru a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c --- a/drivers/net/wireless/netwave_cs.c Tue Jul 1 18:44:39 2003 +++ b/drivers/net/wireless/netwave_cs.c Tue Jul 1 18:44:39 2003 @@ -321,7 +321,6 @@ typedef struct netwave_private { dev_link_t link; - struct net_device dev; spinlock_t spinlock; /* Serialize access to the hardware (SMP) */ dev_node_t node; u_char *ramBase; @@ -449,11 +448,13 @@ netwave_flush_stale_links(); /* Initialize the dev_link_t structure */ - priv = kmalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) return NULL; - memset(priv, 0, sizeof(*priv)); - link = &priv->link; dev = &priv->dev; - link->priv = dev->priv = priv; + dev = alloc_etherdev(sizeof(netwave_private)); + if (!dev) + return NULL; + priv = dev->priv; + link = &priv->link; + link->priv = dev; + init_timer(&link->release); link->release.function = &netwave_release; link->release.data = (u_long)link; @@ -504,7 +505,6 @@ dev->tx_timeout = &netwave_watchdog; dev->watchdog_timeo = TX_TIMEOUT; - ether_setup(dev); dev->open = &netwave_open; dev->stop = &netwave_close; link->irq.Instance = dev; @@ -541,7 +541,7 @@ */ static void netwave_detach(dev_link_t *link) { - netwave_private *priv = link->priv; + struct net_device *dev = link->priv; dev_link_t **linkp; DEBUG(0, "netwave_detach(0x%p)\n", link); @@ -580,8 +580,8 @@ /* Unlink device structure, free pieces */ *linkp = link->next; if (link->dev) - unregister_netdev(&priv->dev); - kfree(priv); + unregister_netdev(dev); + kfree(dev); } /* netwave_detach */ @@ -1038,8 +1038,8 @@ static void netwave_pcmcia_config(dev_link_t *link) { client_handle_t handle = link->handle; - netwave_private *priv = link->priv; - struct net_device *dev = &priv->dev; + struct net_device *dev = link->priv; + netwave_private *priv = dev->priv; tuple_t tuple; cisparse_t parse; int i, j, last_ret, last_fn; @@ -1099,7 +1099,7 @@ * Allocate a 32K memory window. Note that the dev_link_t * structure provides space for one window handle -- if your * device needs several windows, you'll need to keep track of - * the handles in your private data structure, link->priv. + * the handles in your private data structure, dev->priv. */ DEBUG(1, "Setting mem speed of %d\n", mem_speed); @@ -1161,7 +1161,8 @@ */ static void netwave_release(u_long arg) { dev_link_t *link = (dev_link_t *)arg; - netwave_private *priv = link->priv; + struct net_device *dev = link->priv; + netwave_private *priv = dev->priv; DEBUG(0, "netwave_release(0x%p)\n", link); @@ -1206,8 +1207,7 @@ static int netwave_event(event_t event, int priority, event_callback_args_t *args) { dev_link_t *link = args->client_data; - netwave_private *priv = link->priv; - struct net_device *dev = &priv->dev; + struct net_device *dev = link->priv; DEBUG(1, "netwave_event(0x%06x)\n", event); diff -Nru a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c --- a/drivers/net/wireless/strip.c Tue Jul 1 18:44:36 2003 +++ b/drivers/net/wireless/strip.c Tue Jul 1 18:44:36 2003 @@ -284,7 +284,7 @@ */ struct tty_struct *tty; /* ptr to TTY structure */ - struct net_device dev; /* Our device structure */ + struct net_device *dev; /* Our device structure */ /* * Neighbour radio records @@ -509,7 +509,7 @@ *p++ = '\"'; *p++ = 0; - printk(KERN_INFO "%s: %-13s%s\n", strip_info->dev.name, msg, pkt_text); + printk(KERN_INFO "%s: %-13s%s\n", strip_info->dev->name, msg, pkt_text); } @@ -846,7 +846,7 @@ static int allocate_buffers(struct strip *strip_info) { - struct net_device *dev = &strip_info->dev; + struct net_device *dev = strip_info->dev; int sx_size = MAX(STRIP_ENCAP_SIZE(MAX_RECV_MTU), 4096); int tx_size = STRIP_ENCAP_SIZE(dev->mtu) + MaxCommandStringLength; __u8 *r = kmalloc(MAX_RECV_MTU, GFP_ATOMIC); @@ -881,7 +881,7 @@ static void strip_changedmtu(struct strip *strip_info) { int old_mtu = strip_info->mtu; - struct net_device *dev = &strip_info->dev; + struct net_device *dev = strip_info->dev; unsigned char *orbuff = strip_info->rx_buff; unsigned char *osbuff = strip_info->sx_buff; unsigned char *otbuff = strip_info->tx_buff; @@ -889,14 +889,14 @@ if (dev->mtu > MAX_SEND_MTU) { printk(KERN_ERR "%s: MTU exceeds maximum allowable (%d), MTU change cancelled.\n", - strip_info->dev.name, MAX_SEND_MTU); + strip_info->dev->name, MAX_SEND_MTU); dev->mtu = old_mtu; return; } if (!allocate_buffers(strip_info)) { printk(KERN_ERR "%s: unable to grow strip buffers, MTU change cancelled.\n", - strip_info->dev.name); + strip_info->dev->name); dev->mtu = old_mtu; return; } @@ -923,7 +923,7 @@ strip_info->tx_head = strip_info->tx_buff; printk(KERN_NOTICE "%s: strip MTU changed fom %d to %d.\n", - strip_info->dev.name, old_mtu, strip_info->mtu); + strip_info->dev->name, old_mtu, strip_info->mtu); if (orbuff) kfree(orbuff); @@ -940,7 +940,7 @@ */ strip_info->idle_timer.expires = jiffies + 1 * HZ; add_timer(&strip_info->idle_timer); - netif_wake_queue(&strip_info->dev); + netif_wake_queue(strip_info->dev); } @@ -1087,10 +1087,10 @@ FirmwareVersion firmware_version = strip_info->firmware_version; SerialNumber serial_number = strip_info->serial_number; BatteryVoltage battery_voltage = strip_info->battery_voltage; - char *if_name = strip_info->dev.name; + char *if_name = strip_info->dev->name; MetricomAddress true_dev_addr = strip_info->true_dev_addr; MetricomAddress dev_dev_addr = - *(MetricomAddress *) strip_info->dev.dev_addr; + *(MetricomAddress *) strip_info->dev->dev_addr; int manual_dev_addr = strip_info->manual_dev_addr; #ifdef EXT_COUNTERS unsigned long rx_bytes = strip_info->rx_bytes; @@ -1133,7 +1133,7 @@ p += sprintf(p, " Next gratuitous ARP:\t"); if (!memcmp - (strip_info->dev.dev_addr, zero_address.c, + (strip_info->dev->dev_addr, zero_address.c, sizeof(zero_address))) p += sprintf(p, "Disabled\n"); else { @@ -1210,7 +1210,7 @@ */ if (strip_info->working) { printk(KERN_INFO "%s: No response: Resetting radio.\n", - strip_info->dev.name); + strip_info->dev->name); strip_info->firmware_version.c[0] = '\0'; strip_info->serial_number.c[0] = '\0'; strip_info->battery_voltage.c[0] = '\0'; @@ -1231,7 +1231,7 @@ /* Mark radio address as unknown */ *(MetricomAddress *) & strip_info->true_dev_addr = zero_address; if (!strip_info->manual_dev_addr) - *(MetricomAddress *) strip_info->dev.dev_addr = + *(MetricomAddress *) strip_info->dev->dev_addr = zero_address; strip_info->working = FALSE; strip_info->firmware_level = NoStructure; @@ -1285,7 +1285,7 @@ /* First make sure we're connected. */ if (!strip_info || strip_info->magic != STRIP_MAGIC || - !netif_running(&strip_info->dev)) + !netif_running(strip_info->dev)) return; if (strip_info->tx_left > 0) { @@ -1340,14 +1340,14 @@ else { printk(KERN_ERR "%s: strip_make_packet: Unknown packet type 0x%04X\n", - strip_info->dev.name, ntohs(header->protocol)); + strip_info->dev->name, ntohs(header->protocol)); return (NULL); } if (len > strip_info->mtu) { printk(KERN_ERR "%s: Dropping oversized transmit packet: %d bytes\n", - strip_info->dev.name, len); + strip_info->dev->name, len); return (NULL); } @@ -1357,7 +1357,7 @@ */ if (!memcmp(haddr.c, strip_info->true_dev_addr.c, sizeof(haddr))) { printk(KERN_ERR "%s: Dropping packet addressed to self\n", - strip_info->dev.name); + strip_info->dev->name); return (NULL); } @@ -1367,7 +1367,7 @@ */ if (haddr.c[0] == 0xFF) { u32 brd = 0; - struct in_device *in_dev = in_dev_get(&strip_info->dev); + struct in_device *in_dev = in_dev_get(strip_info->dev); if (in_dev == NULL) return NULL; read_lock(&in_dev->lock); @@ -1377,10 +1377,10 @@ in_dev_put(in_dev); /* arp_query returns 1 if it succeeds in looking up the address, 0 if it fails */ - if (!arp_query(haddr.c, brd, &strip_info->dev)) { + if (!arp_query(haddr.c, brd, strip_info->dev)) { printk(KERN_ERR "%s: Unable to send packet (no broadcast hub configured)\n", - strip_info->dev.name); + strip_info->dev->name); return (NULL); } /* @@ -1491,7 +1491,7 @@ #endif strip_info->watchdog_doprobe = jiffies + 10 * HZ; strip_info->watchdog_doreset = jiffies + 1 * HZ; - /*printk(KERN_INFO "%s: Routine radio test.\n", strip_info->dev.name); */ + /*printk(KERN_INFO "%s: Routine radio test.\n", strip_info->dev->name); */ } /* @@ -1506,7 +1506,7 @@ */ if (strip_info->tx_size - strip_info->tx_left < 20) printk(KERN_ERR "%s: Sending%5d bytes;%5d bytes free.\n", - strip_info->dev.name, strip_info->tx_left, + strip_info->dev->name, strip_info->tx_left, strip_info->tx_size - strip_info->tx_left); /* @@ -1519,7 +1519,7 @@ } if (1) { - struct in_device *in_dev = in_dev_get(&strip_info->dev); + struct in_device *in_dev = in_dev_get(strip_info->dev); brd = addr = 0; if (in_dev) { read_lock(&in_dev->lock); @@ -1549,11 +1549,11 @@ */ if (strip_info->working && (long) jiffies - strip_info->gratuitous_arp >= 0 - && memcmp(strip_info->dev.dev_addr, zero_address.c, + && memcmp(strip_info->dev->dev_addr, zero_address.c, sizeof(zero_address)) - && arp_query(haddr.c, brd, &strip_info->dev)) { + && arp_query(haddr.c, brd, strip_info->dev)) { /*printk(KERN_INFO "%s: Sending gratuitous ARP with interval %ld\n", - strip_info->dev.name, strip_info->arp_interval / HZ); */ + strip_info->dev->name, strip_info->arp_interval / HZ); */ strip_info->gratuitous_arp = jiffies + strip_info->arp_interval; strip_info->arp_interval *= 2; @@ -1561,11 +1561,11 @@ strip_info->arp_interval = MaxARPInterval; if (addr) arp_send(ARPOP_REPLY, ETH_P_ARP, addr, /* Target address of ARP packet is our address */ - &strip_info->dev, /* Device to send packet on */ + strip_info->dev, /* Device to send packet on */ addr, /* Source IP address this ARP packet comes from */ NULL, /* Destination HW address is NULL (broadcast it) */ - strip_info->dev.dev_addr, /* Source HW address is our HW address */ - strip_info->dev.dev_addr); /* Target HW address is our HW address (redundant) */ + strip_info->dev->dev_addr, /* Source HW address is our HW address */ + strip_info->dev->dev_addr); /* Target HW address is our HW address (redundant) */ } /* @@ -1608,18 +1608,18 @@ if (rx_pps_count / 8 >= 10) printk(KERN_INFO "%s: WARNING: Receiving %ld packets per second.\n", - strip_info->dev.name, rx_pps_count / 8); + strip_info->dev->name, rx_pps_count / 8); if (tx_pps_count / 8 >= 10) printk(KERN_INFO "%s: WARNING: Tx %ld packets per second.\n", - strip_info->dev.name, tx_pps_count / 8); + strip_info->dev->name, tx_pps_count / 8); if (sx_pps_count / 8 >= 10) printk(KERN_INFO "%s: WARNING: Sending %ld packets per second.\n", - strip_info->dev.name, sx_pps_count / 8); + strip_info->dev->name, sx_pps_count / 8); } spin_lock_irqsave(&strip_lock, flags); /* See if someone has been ifconfigging */ - if (strip_info->mtu != strip_info->dev.mtu) + if (strip_info->mtu != strip_info->dev->mtu) strip_changedmtu(strip_info); strip_send(strip_info, skb); @@ -1735,7 +1735,7 @@ len = MIN(len, sizeof(FirmwareVersion) - 1); if (strip_info->firmware_version.c[0] == 0) printk(KERN_INFO "%s: Radio Firmware: %.*s\n", - strip_info->dev.name, len, value_begin); + strip_info->dev->name, len, value_begin); sprintf(strip_info->firmware_version.c, "%.*s", len, value_begin); /* Look for the first colon */ @@ -1806,10 +1806,10 @@ MetricomAddressString addr_string; radio_address_to_string(&addr, &addr_string); printk(KERN_INFO "%s: Radio address = %s\n", - strip_info->dev.name, addr_string.c); + strip_info->dev->name, addr_string.c); strip_info->true_dev_addr = addr; if (!strip_info->manual_dev_addr) - *(MetricomAddress *) strip_info->dev.dev_addr = + *(MetricomAddress *) strip_info->dev->dev_addr = addr; /* Give the radio a few seconds to get its head straight, then send an arp */ strip_info->gratuitous_arp = jiffies + 15 * HZ; @@ -1830,7 +1830,7 @@ if (sum == 0 && strip_info->firmware_level == StructuredMessages) { strip_info->firmware_level = ChecksummedMessages; printk(KERN_INFO "%s: Radio provides message checksums\n", - strip_info->dev.name); + strip_info->dev->name); } return (sum == 0); } @@ -1849,7 +1849,7 @@ if (has_prefix(msg, len, "001")) { /* Not in StarMode! */ RecvErr("Error Msg:", strip_info); printk(KERN_INFO "%s: Radio %s is not in StarMode\n", - strip_info->dev.name, sendername); + strip_info->dev->name, sendername); } else if (has_prefix(msg, len, "002")) { /* Remap handle */ @@ -1859,7 +1859,7 @@ else if (has_prefix(msg, len, "003")) { /* Can't resolve name */ RecvErr("Error Msg:", strip_info); printk(KERN_INFO "%s: Destination radio name is unknown\n", - strip_info->dev.name); + strip_info->dev->name); } else if (has_prefix(msg, len, "004")) { /* Name too small or missing */ @@ -1876,7 +1876,7 @@ if (!strip_info->working) { strip_info->working = TRUE; printk(KERN_INFO "%s: Radio now in starmode\n", - strip_info->dev.name); + strip_info->dev->name); /* * If the radio has just entered a working state, we should do our first * probe ASAP, so that we find out our radio address etc. without delay. @@ -1888,7 +1888,7 @@ strip_info->next_command = 0; /* Try to enable checksums ASAP */ printk(KERN_INFO "%s: Radio provides structured messages\n", - strip_info->dev.name); + strip_info->dev->name); } if (strip_info->firmware_level >= StructuredMessages) { /* @@ -1916,14 +1916,14 @@ RecvErr("Error Msg:", strip_info); printk(KERN_ERR "%s: Error! Packet size too big for radio.\n", - strip_info->dev.name); + strip_info->dev->name); } else if (has_prefix(msg, len, "008")) { /* Bad character in name */ RecvErr("Error Msg:", strip_info); printk(KERN_ERR "%s: Radio name contains illegal character\n", - strip_info->dev.name); + strip_info->dev->name); } else if (has_prefix(msg, len, "009")) /* No count or line terminator */ @@ -1994,7 +1994,7 @@ /* real radio hardware address, try to find another strip device that has been */ /* manually set to that address that we can 'transfer ownership' of this packet to */ if (strip_info->manual_dev_addr && - !memcmp(strip_info->dev.dev_addr, zero_address.c, + !memcmp(strip_info->dev->dev_addr, zero_address.c, sizeof(zero_address)) && memcmp(&strip_info->true_dev_addr, zero_address.c, sizeof(zero_address))) { @@ -2002,13 +2002,13 @@ read_lock_bh(&dev_base_lock); dev = dev_base; while (dev) { - if (dev->type == strip_info->dev.type && + if (dev->type == strip_info->dev->type && !memcmp(dev->dev_addr, &strip_info->true_dev_addr, sizeof(MetricomAddress))) { printk(KERN_INFO "%s: Transferred packet ownership to %s.\n", - strip_info->dev.name, dev->name); + strip_info->dev->name, dev->name); read_unlock_bh(&dev_base_lock); return (dev); } @@ -2016,7 +2016,7 @@ } read_unlock_bh(&dev_base_lock); } - return (&strip_info->dev); + return (strip_info->dev); } /* @@ -2029,7 +2029,7 @@ struct sk_buff *skb = dev_alloc_skb(sizeof(STRIP_Header) + packetlen); if (!skb) { printk(KERN_ERR "%s: memory squeeze, dropping packet.\n", - strip_info->dev.name); + strip_info->dev->name); strip_info->rx_dropped++; } else { memcpy(skb_put(skb, sizeof(STRIP_Header)), header, @@ -2073,12 +2073,12 @@ if (packetlen > MAX_RECV_MTU) { printk(KERN_INFO "%s: Dropping oversized received IP packet: %d bytes\n", - strip_info->dev.name, packetlen); + strip_info->dev->name, packetlen); strip_info->rx_dropped++; return; } - /*printk(KERN_INFO "%s: Got %d byte IP packet\n", strip_info->dev.name, packetlen); */ + /*printk(KERN_INFO "%s: Got %d byte IP packet\n", strip_info->dev->name, packetlen); */ /* Decode remainder of the IP packet */ ptr = @@ -2117,13 +2117,13 @@ if (packetlen > MAX_RECV_MTU) { printk(KERN_INFO "%s: Dropping oversized received ARP packet: %d bytes\n", - strip_info->dev.name, packetlen); + strip_info->dev->name, packetlen); strip_info->rx_dropped++; return; } /*printk(KERN_INFO "%s: Got %d byte ARP %s\n", - strip_info->dev.name, packetlen, + strip_info->dev->name, packetlen, ntohs(arphdr->ar_op) == ARPOP_REQUEST ? "request" : "reply"); */ /* Decode remainder of the ARP packet */ @@ -2251,7 +2251,7 @@ } } - /*printk(KERN_INFO "%s: Got packet from \"%s\".\n", strip_info->dev.name, sendername); */ + /*printk(KERN_INFO "%s: Got packet from \"%s\".\n", strip_info->dev->name, sendername); */ /* * Fill in (pseudo) source and destination addresses in the packet. @@ -2320,13 +2320,13 @@ unsigned long flags; if (!strip_info || strip_info->magic != STRIP_MAGIC - || !netif_running(&strip_info->dev)) + || !netif_running(strip_info->dev)) return; spin_lock_irqsave(&strip_lock, flags); /* Argh! mtu change time! - costs us the packet part received at the change */ - if (strip_info->mtu != strip_info->dev.mtu) + if (strip_info->mtu != strip_info->dev->mtu) strip_changedmtu(strip_info); #if 0 @@ -2347,7 +2347,7 @@ while (cp < end) { if (fp && *fp) printk(KERN_INFO "%s: %s on serial port\n", - strip_info->dev.name, TTYERROR(*fp)); + strip_info->dev->name, TTYERROR(*fp)); if (fp && *fp++ && !strip_info->discard) { /* If there's a serial error, record it */ /* If we have some characters in the buffer, discard them */ strip_info->discard = strip_info->sx_count; @@ -2360,7 +2360,7 @@ if (strip_info->sx_count > 3000) printk(KERN_INFO "%s: Cut a %d byte packet (%d bytes remaining)%s\n", - strip_info->dev.name, + strip_info->dev->name, strip_info->sx_count, end - cp - 1, strip_info-> @@ -2371,12 +2371,12 @@ strip_info->rx_over_errors++; printk(KERN_INFO "%s: sx_buff overflow (%d bytes total)\n", - strip_info->dev.name, + strip_info->dev->name, strip_info->sx_count); } else if (strip_info->discard) printk(KERN_INFO "%s: Discarding bad packet (%d/%d)\n", - strip_info->dev.name, + strip_info->dev->name, strip_info->discard, strip_info->sx_count); else @@ -2415,9 +2415,9 @@ memcmp(addr->c, broadcast_address.c, sizeof(broadcast_address)); if (strip_info->manual_dev_addr) - *(MetricomAddress *) strip_info->dev.dev_addr = *addr; + *(MetricomAddress *) strip_info->dev->dev_addr = *addr; else - *(MetricomAddress *) strip_info->dev.dev_addr = + *(MetricomAddress *) strip_info->dev->dev_addr = strip_info->true_dev_addr; return 0; } @@ -2496,7 +2496,7 @@ strip_info->user_baud = get_baud(strip_info->tty); printk(KERN_INFO "%s: Initializing Radio.\n", - strip_info->dev.name); + strip_info->dev->name); ResetRadio(strip_info); strip_info->idle_timer.expires = jiffies + 1 * HZ; add_timer(&strip_info->idle_timer); @@ -2589,6 +2589,8 @@ if (strip_info->next) strip_info->next->referrer = strip_info->referrer; strip_info->magic = 0; + if (strip_info->dev) + kfree(strip_info->dev); kfree(strip_info); } @@ -2600,6 +2602,7 @@ { int channel_id = 0; struct strip **s = &struct_strip_list; + struct net_device *dev; struct strip *strip_info = (struct strip *) kmalloc(sizeof(struct strip), GFP_KERNEL); @@ -2612,13 +2615,22 @@ memset(strip_info, 0, sizeof(struct strip)); + /* allocate the net_device */ + dev = kmalloc(sizeof(struct net_device), GFP_KERNEL); + if (!dev) { + kfree(strip_info); + return NULL; + } + strip_info->dev = dev; + SET_MODULE_OWNER(dev); + /* * Search the list to find where to put our new entry * (and in the process decide what channel number it is * going to be) */ - while (*s && (*s)->dev.base_addr == channel_id) { + while (*s && (*s)->dev->base_addr == channel_id) { channel_id++; s = &(*s)->next; } @@ -2639,15 +2651,15 @@ strip_info->gratuitous_arp = jiffies + LongTime; strip_info->arp_interval = 0; init_timer(&strip_info->idle_timer); - strip_info->idle_timer.data = (long) &strip_info->dev; + strip_info->idle_timer.data = (long) dev; strip_info->idle_timer.function = strip_IdleTask; /* Note: strip_info->if_name is currently 8 characters long */ - sprintf(strip_info->dev.name, "st%d", channel_id); - strip_info->dev.base_addr = channel_id; - strip_info->dev.priv = (void *) strip_info; - strip_info->dev.next = NULL; - strip_info->dev.init = strip_dev_init; + sprintf(dev->name, "st%d", channel_id); + dev->base_addr = channel_id; + dev->priv = (void *) strip_info; + dev->next = NULL; + dev->init = strip_dev_init; return strip_info; } @@ -2682,7 +2694,7 @@ * strip_dev_init() will be called as a side-effect */ - if (register_netdev(&strip_info->dev) != 0) { + if (register_netdev(strip_info->dev) != 0) { printk(KERN_ERR "strip: register_netdev() failed.\n"); strip_free(strip_info); return -ENFILE; @@ -2699,7 +2711,7 @@ * Restore default settings */ - strip_info->dev.type = ARPHRD_METRICOM; /* dtang */ + strip_info->dev->type = ARPHRD_METRICOM; /* dtang */ /* * Set tty options @@ -2709,15 +2721,13 @@ tty->termios->c_cflag |= CLOCAL; /* Ignore modem control signals. */ tty->termios->c_cflag &= ~HUPCL; /* Don't close on hup */ - MOD_INC_USE_COUNT; - printk(KERN_INFO "STRIP: device \"%s\" activated\n", - strip_info->dev.name); + strip_info->dev->name); /* * Done. We have linked the TTY line to a channel. */ - return (strip_info->dev.base_addr); + return (strip_info->dev->base_addr); } /* @@ -2738,15 +2748,14 @@ if (!strip_info || strip_info->magic != STRIP_MAGIC) return; - unregister_netdev(&strip_info->dev); + unregister_netdev(strip_info->dev); tty->disc_data = 0; strip_info->tty = NULL; printk(KERN_INFO "STRIP: device \"%s\" closed down\n", - strip_info->dev.name); + strip_info->dev->name); strip_free(strip_info); tty->disc_data = NULL; - MOD_DEC_USE_COUNT; } @@ -2767,13 +2776,13 @@ switch (cmd) { case SIOCGIFNAME: - if(copy_to_user((void *) arg, strip_info->dev.name, strlen(strip_info->dev.name) + 1)) + if(copy_to_user((void *) arg, strip_info->dev->name, strlen(strip_info->dev->name) + 1)) return -EFAULT; break; case SIOCSIFHWADDR: { MetricomAddress addr; - //printk(KERN_INFO "%s: SIOCSIFHWADDR\n", strip_info->dev.name); + //printk(KERN_INFO "%s: SIOCSIFHWADDR\n", strip_info->dev->name); if(copy_from_user(&addr, (void *) arg, sizeof(MetricomAddress))) return -EFAULT; return set_mac_address(strip_info, &addr); diff -Nru a/drivers/pci/Makefile b/drivers/pci/Makefile --- a/drivers/pci/Makefile Tue Jul 1 18:44:37 2003 +++ b/drivers/pci/Makefile Tue Jul 1 18:44:37 2003 @@ -3,15 +3,16 @@ # obj-y += access.o bus.o probe.o pci.o pool.o quirks.o \ - names.o pci-driver.o search.o hotplug.o \ - pci-sysfs.o + names.o pci-driver.o search.o pci-sysfs.o obj-$(CONFIG_PM) += power.o obj-$(CONFIG_PROC_FS) += proc.o ifndef CONFIG_SPARC64 -obj-$(CONFIG_PCI) += setup-res.o +obj-y += setup-res.o endif +obj-$(CONFIG_HOTPLUG) += hotplug.o + # Build the PCI Hotplug drivers if we were asked to obj-$(CONFIG_HOTPLUG_PCI) += hotplug/ @@ -24,16 +25,11 @@ obj-$(CONFIG_SUPERH) += setup-bus.o setup-irq.o obj-$(CONFIG_PPC32) += setup-irq.o obj-$(CONFIG_PPC64) += setup-bus.o -obj-$(CONFIG_DDB5476) += setup-bus.o obj-$(CONFIG_SGI_IP27) += setup-irq.o +obj-$(CONFIG_SGI_IP32) += setup-irq.o obj-$(CONFIG_X86_VISWS) += setup-irq.o -# CompactPCI hotplug requires the pbus_* functions -ifdef CONFIG_HOTPLUG_PCI_CPCI -obj-y += setup-bus.o -endif - -# Hotplug (eg, cardbus) now requires setup-bus +# Cardbus & CompactPCI use setup-bus obj-$(CONFIG_HOTPLUG) += setup-bus.o ifndef CONFIG_X86 diff -Nru a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig --- a/drivers/pci/hotplug/Kconfig Tue Jul 1 18:44:34 2003 +++ b/drivers/pci/hotplug/Kconfig Tue Jul 1 18:44:34 2003 @@ -21,6 +21,31 @@ When in doubt, say N. +config HOTPLUG_PCI_FAKE + tristate "Fake PCI Hotplug driver" + depends on HOTPLUG_PCI + help + Say Y here if you want to use the fake PCI hotplug driver. It can + be used to simulate PCI hotplug events if even if your system is + not PCI hotplug capable. + + This driver will "emulate" removing PCI devices from the system. + If the "power" file is written to with "0" then the specified PCI + device will be completely removed from the kernel. + + WARNING, this does NOT turn off the power to the PCI device. + This is a "logical" removal, not a physical or electrical + removal. + + Use this module at your own risk. You have been warned! + + This code is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called fakephp. If you want to compile it + as a module, say M here and read . + + When in doubt, say N. + config HOTPLUG_PCI_COMPAQ tristate "Compaq PCI Hotplug driver" depends on HOTPLUG_PCI && X86 diff -Nru a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile --- a/drivers/pci/hotplug/Makefile Tue Jul 1 18:44:36 2003 +++ b/drivers/pci/hotplug/Makefile Tue Jul 1 18:44:36 2003 @@ -3,6 +3,7 @@ # obj-$(CONFIG_HOTPLUG_PCI) += pci_hotplug.o +obj-$(CONFIG_HOTPLUG_PCI_FAKE) += fakephp.o obj-$(CONFIG_HOTPLUG_PCI_COMPAQ) += cpqphp.o obj-$(CONFIG_HOTPLUG_PCI_IBM) += ibmphp.o obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o diff -Nru a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c --- a/drivers/pci/hotplug/acpiphp_core.c Tue Jul 1 18:44:36 2003 +++ b/drivers/pci/hotplug/acpiphp_core.c Tue Jul 1 18:44:36 2003 @@ -380,6 +380,25 @@ } /** + * release_slot - free up the memory used by a slot + * @hotplug_slot: slot to free + */ +static void release_slot(struct hotplug_slot *hotplug_slot) +{ + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); + + if (slot == NULL) + return; + + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + kfree(slot->hotplug_slot->info); + kfree(slot->hotplug_slot->name); + kfree(slot->hotplug_slot); + kfree(slot); +} + +/** * init_slots - initialize 'struct slot' structures for each slot * */ @@ -422,6 +441,7 @@ slot->number = i; slot->hotplug_slot->private = slot; + slot->hotplug_slot->release = &release_slot; slot->hotplug_slot->ops = &acpi_hotplug_slot_ops; slot->acpi_slot = get_slot_from_id(i); @@ -435,10 +455,7 @@ retval = pci_hp_register(slot->hotplug_slot); if (retval) { err("pci_hp_register failed with error %d\n", retval); - kfree(slot->hotplug_slot->info); - kfree(slot->hotplug_slot->name); - kfree(slot->hotplug_slot); - kfree(slot); + release_slot(slot->hotplug_slot); return retval; } @@ -457,13 +474,10 @@ struct slot *slot; list_for_each_safe (tmp, n, &slot_list) { + /* memory will be freed in release_slot callback */ slot = list_entry(tmp, struct slot, slot_list); list_del(&slot->slot_list); pci_hp_deregister(slot->hotplug_slot); - kfree(slot->hotplug_slot->info); - kfree(slot->hotplug_slot->name); - kfree(slot->hotplug_slot); - kfree(slot); } return; diff -Nru a/drivers/pci/hotplug/cpci_hotplug_core.c b/drivers/pci/hotplug/cpci_hotplug_core.c --- a/drivers/pci/hotplug/cpci_hotplug_core.c Tue Jul 1 18:44:34 2003 +++ b/drivers/pci/hotplug/cpci_hotplug_core.c Tue Jul 1 18:44:34 2003 @@ -278,6 +278,19 @@ return 0; } +static void release_slot(struct hotplug_slot *hotplug_slot) +{ + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); + + if(slot == NULL) + return; + + kfree(slot->hotplug_slot->info); + kfree(slot->hotplug_slot->name); + kfree(slot->hotplug_slot); + kfree(slot); +} + #define SLOT_NAME_SIZE 6 static void make_slot_name(struct slot *slot) @@ -346,6 +359,7 @@ slot->devfn = PCI_DEVFN(i, 0); hotplug_slot->private = slot; + hotplug_slot->release = &release_slot; make_slot_name(slot); hotplug_slot->ops = &cpci_hotplug_slot_ops; @@ -382,6 +396,7 @@ { struct slot *slot; struct list_head *tmp; + struct list_head *next; int status; if(!bus) { @@ -393,7 +408,7 @@ spin_unlock(&list_lock); return -1; } - list_for_each(tmp, &slot_list) { + list_for_each_safe(tmp, next, &slot_list) { slot = list_entry(tmp, struct slot, slot_list); if(slot->bus == bus) { dbg("deregistering slot %s", slot->hotplug_slot->name); @@ -405,11 +420,6 @@ } list_del(&slot->slot_list); - kfree(slot->hotplug_slot->info); - kfree(slot->hotplug_slot->name); - kfree(slot->hotplug_slot); - kfree(slot); - slots--; } } diff -Nru a/drivers/pci/hotplug/cpqphp_core.c b/drivers/pci/hotplug/cpqphp_core.c --- a/drivers/pci/hotplug/cpqphp_core.c Tue Jul 1 18:44:31 2003 +++ b/drivers/pci/hotplug/cpqphp_core.c Tue Jul 1 18:44:31 2003 @@ -312,6 +312,20 @@ return previous; } +static void release_slot(struct hotplug_slot *hotplug_slot) +{ + struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); + + if (slot == NULL) + return; + + dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); + + kfree(slot->hotplug_slot->info); + kfree(slot->hotplug_slot->name); + kfree(slot->hotplug_slot); + kfree(slot); +} static int ctrl_slot_setup (struct controller * ctrl, void *smbios_start, void *smbios_table) { @@ -401,6 +415,7 @@ new_slot->capabilities |= ((read_slot_enable(ctrl) << 2) >> ctrl_slot) & 0x04; /* register this slot with the hotplug pci core */ + new_slot->hotplug_slot->release = &release_slot; new_slot->hotplug_slot->private = new_slot; make_slot_name (new_slot->hotplug_slot->name, SLOT_NAME_SIZE, new_slot); new_slot->hotplug_slot->ops = &cpqphp_hotplug_slot_ops; @@ -415,10 +430,7 @@ result = pci_hp_register (new_slot->hotplug_slot); if (result) { err ("pci_hp_register failed with error %d\n", result); - kfree (new_slot->hotplug_slot->info); - kfree (new_slot->hotplug_slot->name); - kfree (new_slot->hotplug_slot); - kfree (new_slot); + release_slot(new_slot->hotplug_slot); return result; } @@ -430,10 +442,9 @@ slot_number++; } - return(0); + return 0; } - static int ctrl_slot_cleanup (struct controller * ctrl) { struct slot *old_slot, *next_slot; @@ -442,12 +453,9 @@ ctrl->slot = NULL; while (old_slot) { + /* memory will be freed by the release_slot callback */ next_slot = old_slot->next; pci_hp_deregister (old_slot->hotplug_slot); - kfree(old_slot->hotplug_slot->info); - kfree(old_slot->hotplug_slot->name); - kfree(old_slot->hotplug_slot); - kfree(old_slot); old_slot = next_slot; } @@ -498,7 +506,7 @@ sizeof(struct irq_routing_table)) / sizeof(struct irq_info); // Make sure I got at least one entry if (len == 0) { - if (PCIIRQRoutingInfoLength != NULL) kfree(PCIIRQRoutingInfoLength ); + kfree(PCIIRQRoutingInfoLength); return -1; } @@ -509,9 +517,7 @@ if ((tbus == bus_num) && (tdevice == dev_num)) { *slot = tslot; - - if (PCIIRQRoutingInfoLength != NULL) - kfree(PCIIRQRoutingInfoLength); + kfree(PCIIRQRoutingInfoLength); return 0; } else { // Didn't get a match on the target PCI device. Check if the @@ -540,10 +546,10 @@ // slot number for the bridge. if (bridgeSlot != 0xFF) { *slot = bridgeSlot; - if (PCIIRQRoutingInfoLength != NULL) kfree(PCIIRQRoutingInfoLength ); + kfree(PCIIRQRoutingInfoLength); return 0; } - if (PCIIRQRoutingInfoLength != NULL) kfree(PCIIRQRoutingInfoLength ); + kfree(PCIIRQRoutingInfoLength); // Couldn't find an entry in the routing table for this PCI device return -1; } diff -Nru a/drivers/pci/hotplug/cpqphp_pci.c b/drivers/pci/hotplug/cpqphp_pci.c --- a/drivers/pci/hotplug/cpqphp_pci.c Tue Jul 1 18:44:38 2003 +++ b/drivers/pci/hotplug/cpqphp_pci.c Tue Jul 1 18:44:38 2003 @@ -198,7 +198,7 @@ ctrl->pci_bus->number = bus_num; - for (tdevice = 0; tdevice < 0x100; tdevice++) { + for (tdevice = 0; tdevice < 0xFF; tdevice++) { //Scan for access first if (PCI_RefinedAccessConfig(ctrl->pci_bus, tdevice, 0x08, &work) == -1) continue; @@ -210,7 +210,7 @@ return 0; } } - for (tdevice = 0; tdevice < 0x100; tdevice++) { + for (tdevice = 0; tdevice < 0xFF; tdevice++) { //Scan for access first if (PCI_RefinedAccessConfig(ctrl->pci_bus, tdevice, 0x08, &work) == -1) continue; diff -Nru a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/pci/hotplug/fakephp.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,232 @@ +/* + * Fake PCI Hot Plug Controller Driver + * + * Copyright (c) 2003 Greg Kroah-Hartman + * Copyright (c) 2003 IBM Corp. + * Copyright (c) 2003 Rolf Eike Beer + * + * Based on ideas and code from: + * Vladimir Kondratiev + * Rolf Eike Beer + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 2 of the License. + * + * Send feedback to + */ + +/* + * + * This driver will "emulate" removing PCI devices from the system. If + * the "power" file is written to with "0" then the specified PCI device + * will be completely removed from the kernel. + * + * WARNING, this does NOT turn off the power to the PCI device. This is + * a "logical" removal, not a physical or electrical removal. + * + * Use this module at your own risk, you have been warned! + * + * Enabling PCI devices is left as an exercise for the reader... + * + */ +#include +#include +#include +#include +#include +#include "pci_hotplug.h" +#include "../pci.h" + +#if !defined(CONFIG_HOTPLUG_PCI_FAKE_MODULE) + #define MY_NAME "fakephp" +#else + #define MY_NAME THIS_MODULE->name +#endif + +#define dbg(format, arg...) \ + do { \ + if (debug) \ + printk(KERN_DEBUG "%s: " format, \ + MY_NAME , ## arg); \ + } while (0) +#define err(format, arg...) printk(KERN_ERR "%s: " format, MY_NAME , ## arg) +#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg) + +#define DRIVER_AUTHOR "Greg Kroah-Hartman " +#define DRIVER_DESC "Fake PCI Hot Plug Controller Driver" + +struct dummy_slot { + struct list_head node; + struct hotplug_slot *slot; + struct pci_dev *dev; +}; + +static int debug; +static LIST_HEAD(slot_list); + +static int enable_slot (struct hotplug_slot *slot); +static int disable_slot (struct hotplug_slot *slot); + +static struct hotplug_slot_ops dummy_hotplug_slot_ops = { + .owner = THIS_MODULE, + .enable_slot = enable_slot, + .disable_slot = disable_slot, +}; + +static void dummy_release(struct hotplug_slot *slot) +{ + struct dummy_slot *dslot = slot->private; + + list_del(&dslot->node); + kfree(dslot->slot->info); + kfree(dslot->slot); + pci_dev_put(dslot->dev); + kfree(dslot); +} + +static int add_slot(struct pci_dev *dev) +{ + struct dummy_slot *dslot; + struct hotplug_slot *slot; + int retval = -ENOMEM; + + slot = kmalloc(sizeof(struct hotplug_slot), GFP_KERNEL); + if (!slot) + goto error; + memset(slot, 0, sizeof(*slot)); + + slot->info = kmalloc(sizeof(struct hotplug_slot_info), GFP_KERNEL); + if (!slot->info) + goto error_slot; + memset(slot->info, 0, sizeof(struct hotplug_slot_info)); + + slot->info->power_status = 1; + slot->info->max_bus_speed = PCI_SPEED_UNKNOWN; + slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN; + + slot->name = &dev->dev.bus_id[0]; + dbg("slot->name = %s\n", slot->name); + + dslot = kmalloc(sizeof(struct dummy_slot), GFP_KERNEL); + if (!dslot) + goto error_info; + + slot->ops = &dummy_hotplug_slot_ops; + slot->release = &dummy_release; + slot->private = dslot; + + retval = pci_hp_register(slot); + if (retval) { + err("pci_hp_register failed with error %d\n", retval); + goto error_dslot; + } + + dslot->slot = slot; + dslot->dev = pci_dev_get(dev); + list_add (&dslot->node, &slot_list); + return retval; + +error_dslot: + kfree(dslot); +error_info: + kfree(slot->info); +error_slot: + kfree(slot); +error: + return retval; +} + +static int __init pci_scan_buses(void) +{ + struct pci_dev *dev = NULL; + int retval = 0; + + while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + retval = add_slot(dev); + if (retval) { + pci_dev_put(dev); + break; + } + } + + return retval; +} + +static void remove_slot(struct dummy_slot *dslot) +{ + int retval; + + dbg("removing slot %s\n", dslot->slot->name); + retval = pci_hp_deregister(dslot->slot); + if (retval) + err("Problem unregistering a slot %s\n", dslot->slot->name); +} + +static int enable_slot(struct hotplug_slot *hotplug_slot) +{ + return -ENODEV; +} + +static int disable_slot(struct hotplug_slot *slot) +{ + struct dummy_slot *dslot; + + if (!slot) + return -ENODEV; + dslot = slot->private; + + dbg("%s - physical_slot = %s\n", __FUNCTION__, slot->name); + + /* don't disable bridged devices just yet, we can't handle them easily... */ + if (dslot->dev->subordinate) { + err("Can't remove PCI devices with other PCI devices behind it yet.\n"); + return -ENODEV; + } + + /* remove the device from the pci core */ + pci_remove_bus_device(dslot->dev); + + /* blow away this sysfs entry and other parts. */ + remove_slot(dslot); + + return 0; +} + +static void cleanup_slots (void) +{ + struct list_head *tmp; + struct list_head *next; + struct dummy_slot *dslot; + + list_for_each_safe (tmp, next, &slot_list) { + dslot = list_entry (tmp, struct dummy_slot, node); + remove_slot(dslot); + } + +} + +static int __init dummyphp_init(void) +{ + info(DRIVER_DESC "\n"); + + return pci_scan_buses(); +} + + +static void __exit dummyphp_exit(void) +{ + cleanup_slots(); +} + +module_init(dummyphp_init); +module_exit(dummyphp_exit); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); +MODULE_PARM(debug, "i"); +MODULE_PARM_DESC(debug, "Debugging mode enabled or not"); + diff -Nru a/drivers/pci/hotplug/ibmphp.h b/drivers/pci/hotplug/ibmphp.h --- a/drivers/pci/hotplug/ibmphp.h Tue Jul 1 18:44:32 2003 +++ b/drivers/pci/hotplug/ibmphp.h Tue Jul 1 18:44:32 2003 @@ -7,7 +7,7 @@ * Written By: Jyoti Shah, Tong Yu, Irene Zubarev, IBM Corporation * * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (c) 2001,2002 IBM Corp. + * Copyright (c) 2001-2003 IBM Corp. * * All rights reserved. * @@ -398,7 +398,6 @@ extern int ibmphp_hpc_writeslot (struct slot *, u8); extern void ibmphp_lock_operations (void); extern void ibmphp_unlock_operations (void); -extern int ibmphp_hpc_fillhpslotinfo (struct hotplug_slot *); extern int ibmphp_hpc_start_poll_thread (void); extern void ibmphp_hpc_stop_poll_thread (void); diff -Nru a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c --- a/drivers/pci/hotplug/ibmphp_core.c Tue Jul 1 18:44:39 2003 +++ b/drivers/pci/hotplug/ibmphp_core.c Tue Jul 1 18:44:39 2003 @@ -3,8 +3,8 @@ * * Written By: Chuck Cole, Jyoti Shah, Tong Yu, Irene Zubarev, IBM Corporation * - * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (c) 2001,2002 IBM Corp. + * Copyright (c) 2001,2003 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (c) 2001-2003 IBM Corp. * * All rights reserved. * @@ -739,26 +739,8 @@ debug ("%s -- enter\n", __FUNCTION__); list_for_each_safe (tmp, next, &ibmphp_slot_head) { - slot_cur = list_entry (tmp, struct slot, ibm_slot_list); - pci_hp_deregister (slot_cur->hotplug_slot); - - if (slot_cur->hotplug_slot) { - kfree (slot_cur->hotplug_slot); - slot_cur->hotplug_slot = NULL; - } - - if (slot_cur->ctrl) - slot_cur->ctrl = NULL; - - if (slot_cur->bus_on) - slot_cur->bus_on = NULL; - - ibmphp_unconfigure_card (&slot_cur, -1); /* we don't want to actually remove the resources, since free_resources will do just that */ - - kfree (slot_cur); - slot_cur = NULL; } debug ("%s -- exit\n", __FUNCTION__); } @@ -1221,7 +1203,6 @@ { int rc; u8 flag; - int parm = 0; debug ("DISABLING SLOT... \n"); @@ -1270,7 +1251,7 @@ return 0; } - rc = ibmphp_unconfigure_card (&slot_cur, parm); + rc = ibmphp_unconfigure_card (&slot_cur, 0); slot_cur->func = NULL; debug ("in disable_slot. after unconfigure_card\n"); if (rc) { diff -Nru a/drivers/pci/hotplug/ibmphp_ebda.c b/drivers/pci/hotplug/ibmphp_ebda.c --- a/drivers/pci/hotplug/ibmphp_ebda.c Tue Jul 1 18:44:32 2003 +++ b/drivers/pci/hotplug/ibmphp_ebda.c Tue Jul 1 18:44:32 2003 @@ -3,8 +3,8 @@ * * Written By: Tong Yu, IBM Corporation * - * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (c) 2001,2002 IBM Corp. + * Copyright (c) 2001,2003 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (c) 2001-2003 IBM Corp. * * All rights reserved. * @@ -727,6 +727,64 @@ return str; } +static int fillslotinfo(struct hotplug_slot *hotplug_slot) +{ + struct slot *slot; + int rc = 0; + + if (!hotplug_slot || !hotplug_slot->private) + return -EINVAL; + + slot = hotplug_slot->private; + rc = ibmphp_hpc_readslot(slot, READ_ALLSTAT, NULL); + if (rc) + return rc; + + // power - enabled:1 not:0 + hotplug_slot->info->power_status = SLOT_POWER(slot->status); + + // attention - off:0, on:1, blinking:2 + hotplug_slot->info->attention_status = SLOT_ATTN(slot->status, slot->ext_status); + + // latch - open:1 closed:0 + hotplug_slot->info->latch_status = SLOT_LATCH(slot->status); + + // pci board - present:1 not:0 + if (SLOT_PRESENT (slot->status)) + hotplug_slot->info->adapter_status = 1; + else + hotplug_slot->info->adapter_status = 0; +/* + if (slot->bus_on->supported_bus_mode + && (slot->bus_on->supported_speed == BUS_SPEED_66)) + hotplug_slot->info->max_bus_speed_status = BUS_SPEED_66PCIX; + else + hotplug_slot->info->max_bus_speed_status = slot->bus_on->supported_speed; +*/ + + return rc; +} + +static void release_slot(struct hotplug_slot *hotplug_slot) +{ + struct slot *slot; + + if (!hotplug_slot || !hotplug_slot->private) + return; + + slot = hotplug_slot->private; + kfree(slot->hotplug_slot->info); + kfree(slot->hotplug_slot->name); + kfree(slot->hotplug_slot); + slot->ctrl = NULL; + slot->bus_on = NULL; + + /* we don't want to actually remove the resources, since free_resources will do just that */ + ibmphp_unconfigure_card(&slot, -1); + + kfree (slot); +} + static struct pci_driver ibmphp_driver; /* @@ -900,32 +958,32 @@ // register slots with hpc core as well as create linked list of ibm slot for (index = 0; index < hpc_ptr->slot_count; index++) { - hp_slot_ptr = (struct hotplug_slot *) kmalloc (sizeof (struct hotplug_slot), GFP_KERNEL); + hp_slot_ptr = kmalloc(sizeof(*hp_slot_ptr), GFP_KERNEL); if (!hp_slot_ptr) { rc = -ENOMEM; goto error_no_hp_slot; } - memset (hp_slot_ptr, 0, sizeof (struct hotplug_slot)); + memset(hp_slot_ptr, 0, sizeof(*hp_slot_ptr)); - hp_slot_ptr->info = (struct hotplug_slot_info *) kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL); + hp_slot_ptr->info = kmalloc (sizeof(struct hotplug_slot_info), GFP_KERNEL); if (!hp_slot_ptr->info) { rc = -ENOMEM; goto error_no_hp_info; } - memset (hp_slot_ptr->info, 0, sizeof (struct hotplug_slot_info)); + memset(hp_slot_ptr->info, 0, sizeof(struct hotplug_slot_info)); - hp_slot_ptr->name = (char *) kmalloc (30, GFP_KERNEL); + hp_slot_ptr->name = kmalloc(30, GFP_KERNEL); if (!hp_slot_ptr->name) { rc = -ENOMEM; goto error_no_hp_name; } - tmp_slot = kmalloc (sizeof (struct slot), GFP_KERNEL); + tmp_slot = kmalloc(sizeof(*tmp_slot), GFP_KERNEL); if (!tmp_slot) { rc = -ENOMEM; goto error_no_slot; } - memset (tmp_slot, 0, sizeof (*tmp_slot)); + memset(tmp_slot, 0, sizeof(*tmp_slot)); tmp_slot->flag = TRUE; @@ -959,8 +1017,9 @@ tmp_slot->hotplug_slot = hp_slot_ptr; hp_slot_ptr->private = tmp_slot; + hp_slot_ptr->release = release_slot; - rc = ibmphp_hpc_fillhpslotinfo (hp_slot_ptr); + rc = fillslotinfo(hp_slot_ptr); if (rc) goto error; diff -Nru a/drivers/pci/hotplug/ibmphp_hpc.c b/drivers/pci/hotplug/ibmphp_hpc.c --- a/drivers/pci/hotplug/ibmphp_hpc.c Tue Jul 1 18:44:33 2003 +++ b/drivers/pci/hotplug/ibmphp_hpc.c Tue Jul 1 18:44:33 2003 @@ -3,7 +3,7 @@ * * Written By: Jyoti Shah, IBM Corporation * - * Copyright (c) 2001-2002 IBM Corp. + * Copyright (c) 2001-2003 IBM Corp. * * All rights reserved. * @@ -114,7 +114,6 @@ static void get_hpc_access (void); static void free_hpc_access (void); static void poll_hpc (void); -static int update_slot (struct slot *, u8); static int process_changeinstatus (struct slot *, struct slot *); static int process_changeinlatch (u8, u8, struct controller *); static int hpc_poll_thread (void *); @@ -152,11 +151,11 @@ u8 status; int i; void *wpg_addr; // base addr + offset - ulong wpg_data, // data to/from WPG LOHI format - ultemp, data; // actual data HILO format + unsigned long wpg_data; // data to/from WPG LOHI format + unsigned long ultemp; + unsigned long data; // actual data HILO format - - debug_polling ("%s - Entry WPGBbar[%lx] index[%x] \n", __FUNCTION__, (ulong) WPGBbar, index); + debug_polling ("%s - Entry WPGBbar[%p] index[%x] \n", __FUNCTION__, WPGBbar, index); //-------------------------------------------------------------------- // READ - step 1 @@ -165,17 +164,17 @@ if (ctlr_ptr->ctlr_type == 0x02) { data = WPG_READATADDR_MASK; // fill in I2C address - ultemp = (ulong) ctlr_ptr->u.wpeg_ctlr.i2c_addr; + ultemp = (unsigned long)ctlr_ptr->u.wpeg_ctlr.i2c_addr; ultemp = ultemp >> 1; data |= (ultemp << 8); // fill in index - data |= (ulong) index; + data |= (unsigned long)index; } else if (ctlr_ptr->ctlr_type == 0x04) { data = WPG_READDIRECT_MASK; // fill in index - ultemp = (ulong) index; + ultemp = (unsigned long)index; ultemp = ultemp << 8; data |= ultemp; } else { @@ -184,14 +183,14 @@ } wpg_data = swab32 (data); // swap data before writing - (ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMOSUP_OFFSET; + wpg_addr = WPGBbar + WPG_I2CMOSUP_OFFSET; writel (wpg_data, wpg_addr); //-------------------------------------------------------------------- // READ - step 2 : clear the message buffer data = 0x00000000; wpg_data = swab32 (data); - (ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMBUFL_OFFSET; + wpg_addr = WPGBbar + WPG_I2CMBUFL_OFFSET; writel (wpg_data, wpg_addr); //-------------------------------------------------------------------- @@ -199,7 +198,7 @@ // 2020 : [20] OR operation at [20] offset 0x20 data = WPG_I2CMCNTL_STARTOP_MASK; wpg_data = swab32 (data); - (ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMCNTL_OFFSET + (ulong) WPG_I2C_OR; + wpg_addr = WPGBbar + WPG_I2CMCNTL_OFFSET + WPG_I2C_OR; writel (wpg_data, wpg_addr); //-------------------------------------------------------------------- @@ -207,7 +206,7 @@ i = CMD_COMPLETE_TOUT_SEC; while (i) { long_delay (1 * HZ / 100); - (ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMCNTL_OFFSET; + wpg_addr = WPGBbar + WPG_I2CMCNTL_OFFSET; wpg_data = readl (wpg_addr); data = swab32 (wpg_data); if (!(data & WPG_I2CMCNTL_STARTOP_MASK)) @@ -223,7 +222,7 @@ i = CMD_COMPLETE_TOUT_SEC; while (i) { long_delay (1 * HZ / 100); - (ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CSTAT_OFFSET; + wpg_addr = WPGBbar + WPG_I2CSTAT_OFFSET; wpg_data = readl (wpg_addr); data = swab32 (wpg_data); if (HPC_I2CSTATUS_CHECK (data)) @@ -237,7 +236,7 @@ //-------------------------------------------------------------------- // READ - step 6 : get DATA - (ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMBUFL_OFFSET; + wpg_addr = WPGBbar + WPG_I2CMBUFL_OFFSET; wpg_data = readl (wpg_addr); data = swab32 (wpg_data); @@ -259,12 +258,12 @@ { u8 rc; void *wpg_addr; // base addr + offset - ulong wpg_data, // data to/from WPG LOHI format - ultemp, data; // actual data HILO format + unsigned long wpg_data; // data to/from WPG LOHI format + unsigned long ultemp; + unsigned long data; // actual data HILO format int i; - - debug_polling ("%s - Entry WPGBbar[%lx] index[%x] cmd[%x]\n", __FUNCTION__, (ulong) WPGBbar, index, cmd); + debug_polling ("%s - Entry WPGBbar[%p] index[%x] cmd[%x]\n", __FUNCTION__, WPGBbar, index, cmd); rc = 0; //-------------------------------------------------------------------- @@ -276,17 +275,17 @@ if (ctlr_ptr->ctlr_type == 0x02) { data = WPG_WRITEATADDR_MASK; // fill in I2C address - ultemp = (ulong) ctlr_ptr->u.wpeg_ctlr.i2c_addr; + ultemp = (unsigned long)ctlr_ptr->u.wpeg_ctlr.i2c_addr; ultemp = ultemp >> 1; data |= (ultemp << 8); // fill in index - data |= (ulong) index; + data |= (unsigned long)index; } else if (ctlr_ptr->ctlr_type == 0x04) { data = WPG_WRITEDIRECT_MASK; // fill in index - ultemp = (ulong) index; + ultemp = (unsigned long)index; ultemp = ultemp << 8; data |= ultemp; } else { @@ -295,14 +294,14 @@ } wpg_data = swab32 (data); // swap data before writing - (ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMOSUP_OFFSET; + wpg_addr = WPGBbar + WPG_I2CMOSUP_OFFSET; writel (wpg_data, wpg_addr); //-------------------------------------------------------------------- // WRITE - step 2 : clear the message buffer - data = 0x00000000 | (ulong) cmd; + data = 0x00000000 | (unsigned long)cmd; wpg_data = swab32 (data); - (ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMBUFL_OFFSET; + wpg_addr = WPGBbar + WPG_I2CMBUFL_OFFSET; writel (wpg_data, wpg_addr); //-------------------------------------------------------------------- @@ -310,7 +309,7 @@ // 2020 : [20] OR operation at [20] offset 0x20 data = WPG_I2CMCNTL_STARTOP_MASK; wpg_data = swab32 (data); - (ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMCNTL_OFFSET + (ulong) WPG_I2C_OR; + wpg_addr = WPGBbar + WPG_I2CMCNTL_OFFSET + WPG_I2C_OR; writel (wpg_data, wpg_addr); //-------------------------------------------------------------------- @@ -318,7 +317,7 @@ i = CMD_COMPLETE_TOUT_SEC; while (i) { long_delay (1 * HZ / 100); - (ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMCNTL_OFFSET; + wpg_addr = WPGBbar + WPG_I2CMCNTL_OFFSET; wpg_data = readl (wpg_addr); data = swab32 (wpg_data); if (!(data & WPG_I2CMCNTL_STARTOP_MASK)) @@ -335,7 +334,7 @@ i = CMD_COMPLETE_TOUT_SEC; while (i) { long_delay (1 * HZ / 100); - (ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CSTAT_OFFSET; + wpg_addr = WPGBbar + WPG_I2CSTAT_OFFSET; wpg_data = readl (wpg_addr); data = swab32 (wpg_data); if (HPC_I2CSTATUS_CHECK (data)) @@ -543,7 +542,7 @@ int rc = 0; int busindex; - debug_polling ("%s - Entry pslot[%lx] cmd[%x] pstatus[%lx]\n", __FUNCTION__, (ulong) pslot, cmd, (ulong) pstatus); + debug_polling ("%s - Entry pslot[%p] cmd[%x] pstatus[%p]\n", __FUNCTION__, pslot, cmd, pstatus); if ((pslot == NULL) || ((pstatus == NULL) && (cmd != READ_ALLSTAT) && (cmd != READ_BUSSTATUS))) { @@ -683,7 +682,7 @@ int rc = 0; int timeout; - debug_polling ("%s - Entry pslot[%lx] cmd[%x]\n", __FUNCTION__, (ulong) pslot, cmd); + debug_polling ("%s - Entry pslot[%p] cmd[%x]\n", __FUNCTION__, pslot, cmd); if (pslot == NULL) { rc = -EINVAL; err ("%s - Error Exit rc[%d]\n", __FUNCTION__, rc); @@ -917,71 +916,6 @@ } -/* ---------------------------------------------------------------------- - * Name: ibmphp_hpc_fillhpslotinfo(hotplug_slot * phpslot) - * - * Action: fill out the hotplug_slot info - * - * Input: pointer to hotplug_slot - * - * Return - * Value: 0 or error codes - *-----------------------------------------------------------------------*/ -int ibmphp_hpc_fillhpslotinfo (struct hotplug_slot *phpslot) -{ - int rc = 0; - struct slot *pslot; - - if (phpslot && phpslot->private) { - pslot = (struct slot *) phpslot->private; - rc = update_slot (pslot, (u8) TRUE); - if (!rc) { - - // power - enabled:1 not:0 - phpslot->info->power_status = SLOT_POWER (pslot->status); - - // attention - off:0, on:1, blinking:2 - phpslot->info->attention_status = SLOT_ATTN (pslot->status, pslot->ext_status); - - // latch - open:1 closed:0 - phpslot->info->latch_status = SLOT_LATCH (pslot->status); - - // pci board - present:1 not:0 - if (SLOT_PRESENT (pslot->status)) - phpslot->info->adapter_status = 1; - else - phpslot->info->adapter_status = 0; -/* - if (pslot->bus_on->supported_bus_mode - && (pslot->bus_on->supported_speed == BUS_SPEED_66)) - phpslot->info->max_bus_speed_status = BUS_SPEED_66PCIX; - else - phpslot->info->max_bus_speed_status = pslot->bus_on->supported_speed; -*/ } else - rc = -EINVAL; - } else - rc = -EINVAL; - - return rc; -} - -/*---------------------------------------------------------------------- -* Name: update_slot -* -* Action: fill out slot status and extended status, controller status -* -* Input: pointer to slot struct -*---------------------------------------------------------------------*/ -static int update_slot (struct slot *pslot, u8 update) -{ - int rc = 0; - - debug ("%s - Entry pslot[%lx]\n", __FUNCTION__, (ulong) pslot); - rc = ibmphp_hpc_readslot (pslot, READ_ALLSTAT, NULL); - debug ("%s - Exit rc[%d]\n", __FUNCTION__, rc); - return rc; -} - /*---------------------------------------------------------------------- * Name: process_changeinstatus * @@ -1004,8 +938,7 @@ u8 disable = FALSE; u8 update = FALSE; - debug ("process_changeinstatus - Entry pslot[%lx], poldslot[%lx]\n", (ulong) pslot, - (ulong) poldslot); + debug ("process_changeinstatus - Entry pslot[%p], poldslot[%p]\n", pslot, poldslot); // bit 0 - HPC_SLOT_POWER if ((pslot->status & 0x01) != (poldslot->status & 0x01)) diff -Nru a/drivers/pci/hotplug/ibmphp_res.c b/drivers/pci/hotplug/ibmphp_res.c --- a/drivers/pci/hotplug/ibmphp_res.c Tue Jul 1 18:44:37 2003 +++ b/drivers/pci/hotplug/ibmphp_res.c Tue Jul 1 18:44:37 2003 @@ -42,7 +42,7 @@ static int update_bridge_ranges (struct bus_node **); static int add_range (int type, struct range_node *, struct bus_node *); static void fix_resources (struct bus_node *); -static inline struct bus_node *find_bus_wprev (u8, struct bus_node **, u8); +static struct bus_node *find_bus_wprev (u8, struct bus_node **, u8); static LIST_HEAD(gbuses); LIST_HEAD(ibmphp_res_head); @@ -1757,7 +1757,7 @@ return find_bus_wprev (bus_number, NULL, 0); } -static inline struct bus_node *find_bus_wprev (u8 bus_number, struct bus_node **prev, u8 flag) +static struct bus_node *find_bus_wprev (u8 bus_number, struct bus_node **prev, u8 flag) { struct bus_node *bus_cur; struct list_head *tmp; diff -Nru a/drivers/pci/hotplug/pci_hotplug.h b/drivers/pci/hotplug/pci_hotplug.h --- a/drivers/pci/hotplug/pci_hotplug.h Tue Jul 1 18:44:34 2003 +++ b/drivers/pci/hotplug/pci_hotplug.h Tue Jul 1 18:44:34 2003 @@ -51,6 +51,8 @@ ssize_t (*show)(struct hotplug_slot *, char *); ssize_t (*store)(struct hotplug_slot *, const char *, size_t); }; +#define to_hotplug_attr(n) container_of(n, struct hotplug_slot_attribute, attr); + /** * struct hotplug_slot_ops -the callbacks that the hotplug pci core can use * @owner: The module owner of this structure @@ -130,12 +132,14 @@ char *name; struct hotplug_slot_ops *ops; struct hotplug_slot_info *info; + void (*release) (struct hotplug_slot *slot); void *private; /* Variables below this are for use only by the hotplug pci core. */ struct list_head slot_list; struct kobject kobj; }; +#define to_hotplug_slot(n) container_of(n, struct hotplug_slot, kobj) extern int pci_hp_register (struct hotplug_slot *slot); extern int pci_hp_deregister (struct hotplug_slot *slot); diff -Nru a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c --- a/drivers/pci/hotplug/pci_hotplug_core.c Tue Jul 1 18:44:37 2003 +++ b/drivers/pci/hotplug/pci_hotplug_core.c Tue Jul 1 18:44:37 2003 @@ -74,20 +74,16 @@ static ssize_t hotplug_slot_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) { - struct hotplug_slot *slot=container_of(kobj, - struct hotplug_slot,kobj); - struct hotplug_slot_attribute *attribute = - container_of(attr, struct hotplug_slot_attribute, attr); + struct hotplug_slot *slot = to_hotplug_slot(kobj); + struct hotplug_slot_attribute *attribute = to_hotplug_attr(attr); return attribute->show ? attribute->show(slot, buf) : 0; } static ssize_t hotplug_slot_attr_store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t len) { - struct hotplug_slot *slot=container_of(kobj, - struct hotplug_slot,kobj); - struct hotplug_slot_attribute *attribute = - container_of(attr, struct hotplug_slot_attribute, attr); + struct hotplug_slot *slot = to_hotplug_slot(kobj); + struct hotplug_slot_attribute *attribute = to_hotplug_attr(attr); return attribute->store ? attribute->store(slot, buf, len) : 0; } @@ -96,8 +92,16 @@ .store = hotplug_slot_attr_store, }; +static void hotplug_slot_release(struct kobject *kobj) +{ + struct hotplug_slot *slot = to_hotplug_slot(kobj); + if (slot->release) + slot->release(slot); +} + static struct kobj_type hotplug_slot_ktype = { - .sysfs_ops = &hotplug_slot_sysfs_ops + .sysfs_ops = &hotplug_slot_sysfs_ops, + .release = &hotplug_slot_release, }; static decl_subsys(hotplug_slots, &hotplug_slot_ktype, NULL); diff -Nru a/drivers/pci/hotplug/pcihp_skeleton.c b/drivers/pci/hotplug/pcihp_skeleton.c --- a/drivers/pci/hotplug/pcihp_skeleton.c Tue Jul 1 18:44:35 2003 +++ b/drivers/pci/hotplug/pcihp_skeleton.c Tue Jul 1 18:44:35 2003 @@ -1,8 +1,8 @@ /* - * PCI Hot Plug Controller Skeleton Driver - 0.1 + * PCI Hot Plug Controller Skeleton Driver - 0.2 * - * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com) - * Copyright (c) 2001 IBM Corp. + * Copyright (c) 2001,2003 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (c) 2001,2003 IBM Corp. * * All rights reserved. * @@ -69,7 +69,7 @@ static int debug; static int num_slots; -#define DRIVER_VERSION "0.1" +#define DRIVER_VERSION "0.2" #define DRIVER_AUTHOR "Greg Kroah-Hartman " #define DRIVER_DESC "Hot Plug PCI Controller Skeleton Driver" @@ -288,6 +288,21 @@ return retval; } +static void release_slots(struct hotplug_slot *hotplug_slot) +{ + struct slot *slot = get_slot(hotplug_slot, __FUNCTION__); + int retval = 0; + + if (slot == NULL) + return -ENODEV; + + dbg(__FUNCTION__" - physical_slot = %s\n", hotplug_slot->name); + kfree(slot->hotplug_slot->info); + kfree(slot->hotplug_slot->name); + kfree(slot->hotplug_slot); + kfree(slot); +} + #define SLOT_NAME_SIZE 10 static void make_slot_name (struct slot *slot) { @@ -347,6 +362,7 @@ slot->number = i; hotplug_slot->private = slot; + hotplug_slot->release = &release_slot; make_slot_name (slot); hotplug_slot->ops = &skel_hotplug_slot_ops; @@ -376,27 +392,23 @@ return retval; } - -static void cleanup_slots (void) + +static void cleanup_slots(void) { struct list_head *tmp; + struct list_head *next; struct slot *slot; /* - * Unregister all of our slots with the pci_hotplug subsystem, - * and free up all memory that we had allocated. + * Unregister all of our slots with the pci_hotplug subsystem. + * Memory will be freed in release_slot() callback after slot's + * lifespan is finished. */ - list_for_each (tmp, &slot_list) { + list_for_each_safe (tmp, next, &slot_list) { slot = list_entry (tmp, struct slot, slot_list); list_del (&slot->slot_list); pci_hp_deregister (slot->hotplug_slot); - kfree (slot->hotplug_slot->info); - kfree (slot->hotplug_slot->name); - kfree (slot->hotplug_slot); - kfree (slot); } - - return; } static int __init pcihp_skel_init(void) diff -Nru a/drivers/pci/hotplug.c b/drivers/pci/hotplug.c --- a/drivers/pci/hotplug.c Tue Jul 1 18:44:38 2003 +++ b/drivers/pci/hotplug.c Tue Jul 1 18:44:38 2003 @@ -12,7 +12,6 @@ static void pci_free_resources(struct pci_dev *dev); -#ifdef CONFIG_HOTPLUG int pci_hotplug (struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size) { @@ -209,16 +208,6 @@ } EXPORT_SYMBOL(pci_remove_device_safe); -#else /* CONFIG_HOTPLUG */ - -int pci_hotplug (struct device *dev, char **envp, int num_envp, - char *buffer, int buffer_size) -{ - return -ENODEV; -} - -#endif /* CONFIG_HOTPLUG */ - static void pci_free_resources(struct pci_dev *dev) { @@ -283,7 +272,5 @@ } } -#ifdef CONFIG_HOTPLUG EXPORT_SYMBOL(pci_remove_bus_device); EXPORT_SYMBOL(pci_remove_behind_bridge); -#endif diff -Nru a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c --- a/drivers/pci/pci-driver.c Tue Jul 1 18:44:36 2003 +++ b/drivers/pci/pci-driver.c Tue Jul 1 18:44:36 2003 @@ -486,6 +486,14 @@ put_device(&dev->dev); } +#ifndef CONFIG_HOTPLUG +int pci_hotplug (struct device *dev, char **envp, int num_envp, + char *buffer, int buffer_size) +{ + return -ENODEV; +} +#endif + struct bus_type pci_bus_type = { .name = "pci", .match = pci_bus_match, diff -Nru a/drivers/pci/pci.c b/drivers/pci/pci.c --- a/drivers/pci/pci.c Tue Jul 1 18:44:33 2003 +++ b/drivers/pci/pci.c Tue Jul 1 18:44:33 2003 @@ -747,6 +747,7 @@ EXPORT_SYMBOL(isa_bridge); #endif +EXPORT_SYMBOL(pci_enable_device_bars); EXPORT_SYMBOL(pci_enable_device); EXPORT_SYMBOL(pci_disable_device); EXPORT_SYMBOL(pci_max_busnr); diff -Nru a/drivers/pci/probe.c b/drivers/pci/probe.c --- a/drivers/pci/probe.c Tue Jul 1 18:44:36 2003 +++ b/drivers/pci/probe.c Tue Jul 1 18:44:36 2003 @@ -18,7 +18,10 @@ #define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */ #define CARDBUS_RESERVE_BUSNR 3 +/* Ugh. Need to stop exporting this to modules. */ LIST_HEAD(pci_root_buses); +EXPORT_SYMBOL(pci_root_buses); + LIST_HEAD(pci_devices); /* @@ -106,7 +109,7 @@ (((unsigned long) ~sz) << 32); #else if (l) { - printk(KERN_ERR "PCI: Unable to handle 64-bit address for device %s\n", dev->slot_name); + printk(KERN_ERR "PCI: Unable to handle 64-bit address for device %s\n", pci_name(dev)); res->start = 0; res->flags = 0; continue; @@ -301,7 +304,7 @@ pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses); DBG("Scanning behind PCI bridge %s, config %06x, pass %d\n", - dev->slot_name, buses & 0xffffff, pass); + pci_name(dev), buses & 0xffffff, pass); if ((buses & 0xffff00) && !pcibios_assign_all_busses() && !is_cardbus) { unsigned int cmax; @@ -400,8 +403,9 @@ { u32 class; - sprintf(dev->slot_name, "%02x:%02x.%d", dev->bus->number, - PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); + dev->slot_name = dev->dev.bus_id; + sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(dev->bus), + dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); sprintf(dev->dev.name, "PCI device %04x:%04x", dev->vendor, dev->device); @@ -449,12 +453,12 @@ default: /* unknown header */ printk(KERN_ERR "PCI: device %s has unknown header type %02x, ignoring.\n", - dev->slot_name, dev->hdr_type); + pci_name(dev), dev->hdr_type); return -1; bad: printk(KERN_ERR "PCI: %s: class %x doesn't match header type %02x. Ignoring class.\n", - dev->slot_name, class, dev->hdr_type); + pci_name(dev), class, dev->hdr_type); dev->class = PCI_CLASS_NOT_DEFINED; } @@ -528,9 +532,6 @@ pci_name_device(dev); - /* now put in global tree */ - sprintf(dev->dev.bus_id, "%04x:%s", pci_domain_nr(bus), - dev->slot_name); dev->dev.dma_mask = &dev->dma_mask; return dev; @@ -643,7 +644,7 @@ return 0; } -static struct pci_bus * __devinit pci_alloc_primary_bus_parented(struct device *parent, int bus) +struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus, struct pci_ops *ops, void *sysdata) { struct pci_bus *b; @@ -656,46 +657,39 @@ b = pci_alloc_bus(); if (!b) return NULL; - + b->dev = kmalloc(sizeof(*(b->dev)),GFP_KERNEL); if (!b->dev){ kfree(b); return NULL; } - + + b->sysdata = sysdata; + b->ops = ops; + list_add_tail(&b->node, &pci_root_buses); memset(b->dev,0,sizeof(*(b->dev))); - sprintf(b->dev->bus_id,"pci%d",bus); - strcpy(b->dev->name,"Host/PCI Bridge"); b->dev->parent = parent; + sprintf(b->dev->bus_id,"pci%04x:%02x", pci_domain_nr(b), bus); + strcpy(b->dev->name,"Host/PCI Bridge"); device_register(b->dev); b->number = b->secondary = bus; b->resource[0] = &ioport_resource; b->resource[1] = &iomem_resource; - return b; -} -struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, int bus, struct pci_ops *ops, void *sysdata) -{ - struct pci_bus *b = pci_alloc_primary_bus_parented(parent, bus); - if (b) { - b->sysdata = sysdata; - b->ops = ops; - b->subordinate = pci_scan_child_bus(b); - pci_bus_add_devices(b); - } + b->subordinate = pci_scan_child_bus(b); + + pci_bus_add_devices(b); + return b; } EXPORT_SYMBOL(pci_scan_bus_parented); -EXPORT_SYMBOL(pci_root_buses); - #ifdef CONFIG_HOTPLUG EXPORT_SYMBOL(pci_add_new_bus); EXPORT_SYMBOL(pci_do_scan_bus); EXPORT_SYMBOL(pci_scan_slot); -EXPORT_SYMBOL(pci_scan_bus); EXPORT_SYMBOL(pci_scan_bridge); #endif diff -Nru a/drivers/pcmcia/au1000_generic.c b/drivers/pcmcia/au1000_generic.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/pcmcia/au1000_generic.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,702 @@ +/* + * + * Alchemy Semi Au1000 pcmcia driver + * + * Copyright 2001 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * ######################################################################## + * + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include "cs_internal.h" + +#include +#include +#include + +#include +#include + +#ifdef PCMCIA_DEBUG +static int pc_debug; +#endif + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Pete Popov, MontaVista Software "); +MODULE_DESCRIPTION("Linux PCMCIA Card Services: Au1x00 Socket Controller"); + +#define MAP_SIZE 0x1000000 + +/* This structure maintains housekeeping state for each socket, such + * as the last known values of the card detect pins, or the Card Services + * callback value associated with the socket: + */ +static struct au1000_pcmcia_socket *pcmcia_socket; +static int socket_count; + + +/* Returned by the low-level PCMCIA interface: */ +static struct pcmcia_low_level *pcmcia_low_level; + +/* Event poll timer structure */ +static struct timer_list poll_timer; + + +/* Prototypes for routines which are used internally: */ + +static int au1000_pcmcia_driver_init(void); +static void au1000_pcmcia_driver_shutdown(void); +static void au1000_pcmcia_task_handler(void *data); +static void au1000_pcmcia_poll_event(unsigned long data); +static void au1000_pcmcia_interrupt(int irq, void *dev, struct pt_regs *regs); +static struct tq_struct au1000_pcmcia_task; + +#ifdef CONFIG_PROC_FS +static int au1000_pcmcia_proc_status(char *buf, char **start, + off_t pos, int count, int *eof, void *data); +#endif + + +/* Prototypes for operations which are exported to the + * new-and-impr^H^H^H^H^H^H^H^H^H^H in-kernel PCMCIA core: + */ + +static int au1000_pcmcia_init(u32 sock); +static int au1000_pcmcia_suspend(u32 sock); +static int au1000_pcmcia_register_callback(u32 sock, + void (*handler)(void *, u32), void *info); +static int au1000_pcmcia_inquire_socket(u32 sock, socket_cap_t *cap); +static int au1000_pcmcia_get_status(u32 sock, u_int *value); +static int au1000_pcmcia_get_socket(u32 sock, socket_state_t *state); +static int au1000_pcmcia_set_socket(u32 sock, socket_state_t *state); +static int au1000_pcmcia_get_io_map(u32 sock, struct pccard_io_map *io); +static int au1000_pcmcia_set_io_map(u32 sock, struct pccard_io_map *io); +static int au1000_pcmcia_get_mem_map(u32 sock, struct pccard_mem_map *mem); +static int au1000_pcmcia_set_mem_map(u32 sock, struct pccard_mem_map *mem); +#ifdef CONFIG_PROC_FS +static void au1000_pcmcia_proc_setup(u32 sock, struct proc_dir_entry *base); +#endif + +static struct pccard_operations au1000_pcmcia_operations = { + au1000_pcmcia_init, + au1000_pcmcia_suspend, + au1000_pcmcia_register_callback, + au1000_pcmcia_inquire_socket, + au1000_pcmcia_get_status, + au1000_pcmcia_get_socket, + au1000_pcmcia_set_socket, + au1000_pcmcia_get_io_map, + au1000_pcmcia_set_io_map, + au1000_pcmcia_get_mem_map, + au1000_pcmcia_set_mem_map, +#ifdef CONFIG_PROC_FS + au1000_pcmcia_proc_setup +#endif +}; + +static spinlock_t pcmcia_lock = SPIN_LOCK_UNLOCKED; + +static int __init au1000_pcmcia_driver_init(void) +{ + servinfo_t info; + struct pcmcia_init pcmcia_init; + struct pcmcia_state state; + unsigned int i; + + printk("\nAu1x00 PCMCIA (CS release %s)\n", CS_RELEASE); + +#ifndef CONFIG_64BIT_PHYS_ADDR + printk(KERN_ERR "Au1x00 PCMCIA 36 bit IO support not enabled\n"); + return -1; +#endif + + CardServices(GetCardServicesInfo, &info); + + if(info.Revision!=CS_RELEASE_CODE){ + printk(KERN_ERR "Card Services release codes do not match\n"); + return -1; + } + +#if defined(CONFIG_MIPS_PB1000) || defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_PB1500) + pcmcia_low_level=&pb1x00_pcmcia_ops; +#else +#error Unsupported AU1000 board. +#endif + + pcmcia_init.handler=au1000_pcmcia_interrupt; + if((socket_count=pcmcia_low_level->init(&pcmcia_init))<0) { + printk(KERN_ERR "Unable to initialize PCMCIA service.\n"); + return -EIO; + } + + /* NOTE: the chip select must already be setup */ + + pcmcia_socket = + kmalloc(sizeof(struct au1000_pcmcia_socket) * socket_count, + GFP_KERNEL); + if (!pcmcia_socket) { + printk(KERN_ERR "Card Services can't get memory \n"); + return -1; + } + memset(pcmcia_socket, 0, + sizeof(struct au1000_pcmcia_socket) * socket_count); + + /* + * Assuming max of 2 sockets, which the Au1000 supports. + * WARNING: the Pb1000 has two sockets, and both work, but you + * can't use them both at the same time due to glue logic conflicts. + */ + for(i=0; i < socket_count; i++) { + + if(pcmcia_low_level->socket_state(i, &state)<0){ + printk(KERN_ERR "Unable to get PCMCIA status\n"); + return -EIO; + } + pcmcia_socket[i].k_state=state; + pcmcia_socket[i].cs_state.csc_mask=SS_DETECT; + + if (i == 0) { + pcmcia_socket[i].virt_io = + (u32)ioremap((ioaddr_t)0xF00000000, 0x1000); + pcmcia_socket[i].phys_attr = (memaddr_t)0xF40000000; + pcmcia_socket[i].phys_mem = (memaddr_t)0xF80000000; + } + else { + pcmcia_socket[i].virt_io = + (u32)ioremap((ioaddr_t)0xF08000000, 0x1000); + pcmcia_socket[i].phys_attr = (memaddr_t)0xF48000000; + pcmcia_socket[i].phys_mem = (memaddr_t)0xF88000000; + } + } + + /* Only advertise as many sockets as we can detect: */ + if(register_ss_entry(socket_count, &au1000_pcmcia_operations)<0){ + printk(KERN_ERR "Unable to register socket service routine\n"); + return -ENXIO; + } + + /* Start the event poll timer. + * It will reschedule by itself afterwards. + */ + au1000_pcmcia_poll_event(0); + + DEBUG(1, "au1000: initialization complete\n"); + return 0; + +} /* au1000_pcmcia_driver_init() */ + +module_init(au1000_pcmcia_driver_init); + +static void __exit au1000_pcmcia_driver_shutdown(void) +{ + int i; + + del_timer_sync(&poll_timer); + unregister_ss_entry(&au1000_pcmcia_operations); + pcmcia_low_level->shutdown(); + flush_scheduled_tasks(); + for(i=0; i < socket_count; i++) { + if (pcmcia_socket[i].virt_io) + iounmap((void *)pcmcia_socket[i].virt_io); + } + DEBUG(1, "au1000: shutdown complete\n"); +} + +module_exit(au1000_pcmcia_driver_shutdown); + +static int au1000_pcmcia_init(unsigned int sock) { return 0; } + +static int au1000_pcmcia_suspend(unsigned int sock) +{ + return 0; +} + + +static inline unsigned +au1000_pcmcia_events(struct pcmcia_state *state, + struct pcmcia_state *prev_state, + unsigned int mask, unsigned int flags) +{ + unsigned int events=0; + + if(state->detect!=prev_state->detect){ + DEBUG(2, "%s(): card detect value %u\n", + __FUNCTION__, state->detect); + events |= mask&SS_DETECT; + } + + + if(state->ready!=prev_state->ready){ + DEBUG(2, "%s(): card ready value %u\n", + __FUNCTION__, state->ready); + events |= mask&((flags&SS_IOCARD)?0:SS_READY); + } + + *prev_state=*state; + return events; + +} /* au1000_pcmcia_events() */ + + +/* + * Au1000_pcmcia_task_handler() + * Processes socket events. + */ +static void au1000_pcmcia_task_handler(void *data) +{ + struct pcmcia_state state; + int i, events, irq_status; + + for(i=0; isocket_state(i, &state))<0) + printk(KERN_ERR "low-level PCMCIA error\n"); + + events = au1000_pcmcia_events(&state, + &pcmcia_socket[i].k_state, + pcmcia_socket[i].cs_state.csc_mask, + pcmcia_socket[i].cs_state.flags); + if(pcmcia_socket[i].handler!=NULL) { + pcmcia_socket[i].handler(pcmcia_socket[i].handler_info, + events); + } + } + +} /* au1000_pcmcia_task_handler() */ + +static struct tq_struct au1000_pcmcia_task = { + routine: au1000_pcmcia_task_handler +}; + + +static void au1000_pcmcia_poll_event(unsigned long dummy) +{ + poll_timer.function = au1000_pcmcia_poll_event; + poll_timer.expires = jiffies + AU1000_PCMCIA_POLL_PERIOD; + add_timer(&poll_timer); + schedule_task(&au1000_pcmcia_task); +} + + +/* + * au1000_pcmcia_interrupt() + * The actual interrupt work is performed by au1000_pcmcia_task(), + * because the Card Services event handling code performs scheduling + * operations which cannot be executed from within an interrupt context. + */ +static void +au1000_pcmcia_interrupt(int irq, void *dev, struct pt_regs *regs) +{ + schedule_task(&au1000_pcmcia_task); +} + + +static int +au1000_pcmcia_register_callback(unsigned int sock, + void (*handler)(void *, unsigned int), void *info) +{ + if(handler==NULL){ + pcmcia_socket[sock].handler=NULL; + MOD_DEC_USE_COUNT; + } else { + MOD_INC_USE_COUNT; + pcmcia_socket[sock].handler=handler; + pcmcia_socket[sock].handler_info=info; + } + return 0; +} + + +/* au1000_pcmcia_inquire_socket() + * + * From the sa1100 socket driver : + * + * Implements the inquire_socket() operation for the in-kernel PCMCIA + * service (formerly SS_InquireSocket in Card Services). We set + * SS_CAP_STATIC_MAP, which disables the memory resource database check. + * (Mapped memory is set up within the socket driver itself.) + * + * In conjunction with the STATIC_MAP capability is a new field, + * `io_offset', recommended by David Hinds. Rather than go through + * the SetIOMap interface (which is not quite suited for communicating + * window locations up from the socket driver), we just pass up + * an offset which is applied to client-requested base I/O addresses + * in alloc_io_space(). + * + * Returns: 0 on success, -1 if no pin has been configured for `sock' + */ +static int au1000_pcmcia_inquire_socket(unsigned int sock, socket_cap_t *cap) +{ + struct pcmcia_irq_info irq_info; + + if(sock > socket_count){ + printk(KERN_ERR "au1000: socket %u not configured\n", sock); + return -1; + } + + /* from the sa1100_generic driver: */ + + /* SS_CAP_PAGE_REGS: used by setup_cis_mem() in cistpl.c to set the + * force_low argument to validate_mem() in rsrc_mgr.c -- since in + * general, the mapped * addresses of the PCMCIA memory regions + * will not be within 0xffff, setting force_low would be + * undesirable. + * + * SS_CAP_STATIC_MAP: don't bother with the (user-configured) memory + * resource database; we instead pass up physical address ranges + * and allow other parts of Card Services to deal with remapping. + * + * SS_CAP_PCCARD: we can deal with 16-bit PCMCIA & CF cards, but + * not 32-bit CardBus devices. + */ + cap->features=(SS_CAP_PAGE_REGS | SS_CAP_STATIC_MAP | SS_CAP_PCCARD); + + irq_info.sock=sock; + irq_info.irq=-1; + + if(pcmcia_low_level->get_irq_info(&irq_info)<0){ + printk(KERN_ERR "Error obtaining IRQ info socket %u\n", sock); + return -1; + } + + cap->irq_mask=0; + cap->map_size=MAP_SIZE; + cap->pci_irq=irq_info.irq; + cap->io_offset=pcmcia_socket[sock].virt_io; + + return 0; + +} /* au1000_pcmcia_inquire_socket() */ + + +static int +au1000_pcmcia_get_status(unsigned int sock, unsigned int *status) +{ + struct pcmcia_state state; + + + if((pcmcia_low_level->socket_state(sock, &state))<0){ + printk(KERN_ERR "Unable to get PCMCIA status from kernel.\n"); + return -1; + } + + pcmcia_socket[sock].k_state = state; + + *status = state.detect?SS_DETECT:0; + + *status |= state.ready?SS_READY:0; + + *status |= pcmcia_socket[sock].cs_state.Vcc?SS_POWERON:0; + + if(pcmcia_socket[sock].cs_state.flags&SS_IOCARD) + *status |= state.bvd1?SS_STSCHG:0; + else { + if(state.bvd1==0) + *status |= SS_BATDEAD; + else if(state.bvd2 == 0) + *status |= SS_BATWARN; + } + + *status|=state.vs_3v?SS_3VCARD:0; + + *status|=state.vs_Xv?SS_XVCARD:0; + + DEBUG(2, "\tstatus: %s%s%s%s%s%s%s%s\n", + (*status&SS_DETECT)?"DETECT ":"", + (*status&SS_READY)?"READY ":"", + (*status&SS_BATDEAD)?"BATDEAD ":"", + (*status&SS_BATWARN)?"BATWARN ":"", + (*status&SS_POWERON)?"POWERON ":"", + (*status&SS_STSCHG)?"STSCHG ":"", + (*status&SS_3VCARD)?"3VCARD ":"", + (*status&SS_XVCARD)?"XVCARD ":""); + + return 0; + +} /* au1000_pcmcia_get_status() */ + + +static int +au1000_pcmcia_get_socket(unsigned int sock, socket_state_t *state) +{ + *state = pcmcia_socket[sock].cs_state; + return 0; +} + + +static int +au1000_pcmcia_set_socket(unsigned int sock, socket_state_t *state) +{ + struct pcmcia_configure configure; + + DEBUG(2, "\tmask: %s%s%s%s%s%s\n\tflags: %s%s%s%s%s%s\n" + "\tVcc %d Vpp %d irq %d\n", + (state->csc_mask==0)?"":"", + (state->csc_mask&SS_DETECT)?"DETECT ":"", + (state->csc_mask&SS_READY)?"READY ":"", + (state->csc_mask&SS_BATDEAD)?"BATDEAD ":"", + (state->csc_mask&SS_BATWARN)?"BATWARN ":"", + (state->csc_mask&SS_STSCHG)?"STSCHG ":"", + (state->flags==0)?"":"", + (state->flags&SS_PWR_AUTO)?"PWR_AUTO ":"", + (state->flags&SS_IOCARD)?"IOCARD ":"", + (state->flags&SS_RESET)?"RESET ":"", + (state->flags&SS_SPKR_ENA)?"SPKR_ENA ":"", + (state->flags&SS_OUTPUT_ENA)?"OUTPUT_ENA ":"", + state->Vcc, state->Vpp, state->io_irq); + + configure.sock=sock; + configure.vcc=state->Vcc; + configure.vpp=state->Vpp; + configure.output=(state->flags&SS_OUTPUT_ENA)?1:0; + configure.speaker=(state->flags&SS_SPKR_ENA)?1:0; + configure.reset=(state->flags&SS_RESET)?1:0; + + if(pcmcia_low_level->configure_socket(&configure)<0){ + printk(KERN_ERR "Unable to configure socket %u\n", sock); + return -1; + } + + pcmcia_socket[sock].cs_state = *state; + return 0; + +} /* au1000_pcmcia_set_socket() */ + + +static int +au1000_pcmcia_get_io_map(unsigned int sock, struct pccard_io_map *map) +{ + DEBUG(1, "au1000_pcmcia_get_io_map: sock %d\n", sock); + if(map->map>=MAX_IO_WIN){ + printk(KERN_ERR "%s(): map (%d) out of range\n", + __FUNCTION__, map->map); + return -1; + } + *map=pcmcia_socket[sock].io_map[map->map]; + return 0; +} + + +int +au1000_pcmcia_set_io_map(unsigned int sock, struct pccard_io_map *map) +{ + unsigned int speed; + unsigned long start; + + if(map->map>=MAX_IO_WIN){ + printk(KERN_ERR "%s(): map (%d) out of range\n", + __FUNCTION__, map->map); + return -1; + } + + if(map->flags&MAP_ACTIVE){ + speed=(map->speed>0)?map->speed:AU1000_PCMCIA_IO_SPEED; + pcmcia_socket[sock].speed_io=speed; + } + + start=map->start; + + if(map->stop==1) { + map->stop=PAGE_SIZE-1; + } + + map->start=pcmcia_socket[sock].virt_io; + map->stop=map->start+(map->stop-start); + pcmcia_socket[sock].io_map[map->map]=*map; + DEBUG(3, "set_io_map %d start %x stop %x\n", + map->map, map->start, map->stop); + return 0; + +} /* au1000_pcmcia_set_io_map() */ + + +static int +au1000_pcmcia_get_mem_map(unsigned int sock, struct pccard_mem_map *map) +{ + + if(map->map>=MAX_WIN) { + printk(KERN_ERR "%s(): map (%d) out of range\n", + __FUNCTION__, map->map); + return -1; + } + *map=pcmcia_socket[sock].mem_map[map->map]; + return 0; +} + + +static int +au1000_pcmcia_set_mem_map(unsigned int sock, struct pccard_mem_map *map) +{ + unsigned int speed; + unsigned long start; + u_long flags; + + if(map->map>=MAX_WIN){ + printk(KERN_ERR "%s(): map (%d) out of range\n", + __FUNCTION__, map->map); + return -1; + } + + if(map->flags&MAP_ACTIVE){ + speed=(map->speed>0)?map->speed:AU1000_PCMCIA_MEM_SPEED; + + /* TBD */ + if(map->flags&MAP_ATTRIB){ + pcmcia_socket[sock].speed_attr=speed; + } + else { + pcmcia_socket[sock].speed_mem=speed; + } + } + + spin_lock_irqsave(&pcmcia_lock, flags); + start=map->sys_start; + + if(map->sys_stop==0) + map->sys_stop=MAP_SIZE-1; + + if (map->flags & MAP_ATTRIB) { + map->sys_start = pcmcia_socket[sock].phys_attr + + map->card_start; + } + else { + map->sys_start = pcmcia_socket[sock].phys_mem + + map->card_start; + } + + map->sys_stop=map->sys_start+(map->sys_stop-start); + pcmcia_socket[sock].mem_map[map->map]=*map; + spin_unlock_irqrestore(&pcmcia_lock, flags); + DEBUG(3, "set_mem_map %d start %x stop %x card_start %x\n", + map->map, map->sys_start, map->sys_stop, + map->card_start); + return 0; + +} /* au1000_pcmcia_set_mem_map() */ + + +#if defined(CONFIG_PROC_FS) + +static void +au1000_pcmcia_proc_setup(unsigned int sock, struct proc_dir_entry *base) +{ + struct proc_dir_entry *entry; + + if((entry=create_proc_entry("status", 0, base))==NULL){ + printk(KERN_ERR "Unable to install \"status\" procfs entry\n"); + return; + } + + entry->read_proc=au1000_pcmcia_proc_status; + entry->data=(void *)sock; +} + + +/* au1000_pcmcia_proc_status() + * Implements the /proc/bus/pccard/??/status file. + * + * Returns: the number of characters added to the buffer + */ +static int +au1000_pcmcia_proc_status(char *buf, char **start, off_t pos, + int count, int *eof, void *data) +{ + char *p=buf; + unsigned int sock=(unsigned int)data; + + p+=sprintf(p, "k_flags : %s%s%s%s%s%s%s\n", + pcmcia_socket[sock].k_state.detect?"detect ":"", + pcmcia_socket[sock].k_state.ready?"ready ":"", + pcmcia_socket[sock].k_state.bvd1?"bvd1 ":"", + pcmcia_socket[sock].k_state.bvd2?"bvd2 ":"", + pcmcia_socket[sock].k_state.wrprot?"wrprot ":"", + pcmcia_socket[sock].k_state.vs_3v?"vs_3v ":"", + pcmcia_socket[sock].k_state.vs_Xv?"vs_Xv ":""); + + p+=sprintf(p, "status : %s%s%s%s%s%s%s%s%s\n", + pcmcia_socket[sock].k_state.detect?"SS_DETECT ":"", + pcmcia_socket[sock].k_state.ready?"SS_READY ":"", + pcmcia_socket[sock].cs_state.Vcc?"SS_POWERON ":"", + pcmcia_socket[sock].cs_state.flags&SS_IOCARD?\ + "SS_IOCARD ":"", + (pcmcia_socket[sock].cs_state.flags&SS_IOCARD && + pcmcia_socket[sock].k_state.bvd1)?"SS_STSCHG ":"", + ((pcmcia_socket[sock].cs_state.flags&SS_IOCARD)==0 && + (pcmcia_socket[sock].k_state.bvd1==0))?"SS_BATDEAD ":"", + ((pcmcia_socket[sock].cs_state.flags&SS_IOCARD)==0 && + (pcmcia_socket[sock].k_state.bvd2==0))?"SS_BATWARN ":"", + pcmcia_socket[sock].k_state.vs_3v?"SS_3VCARD ":"", + pcmcia_socket[sock].k_state.vs_Xv?"SS_XVCARD ":""); + + p+=sprintf(p, "mask : %s%s%s%s%s\n", + pcmcia_socket[sock].cs_state.csc_mask&SS_DETECT?\ + "SS_DETECT ":"", + pcmcia_socket[sock].cs_state.csc_mask&SS_READY?\ + "SS_READY ":"", + pcmcia_socket[sock].cs_state.csc_mask&SS_BATDEAD?\ + "SS_BATDEAD ":"", + pcmcia_socket[sock].cs_state.csc_mask&SS_BATWARN?\ + "SS_BATWARN ":"", + pcmcia_socket[sock].cs_state.csc_mask&SS_STSCHG?\ + "SS_STSCHG ":""); + + p+=sprintf(p, "cs_flags : %s%s%s%s%s\n", + pcmcia_socket[sock].cs_state.flags&SS_PWR_AUTO?\ + "SS_PWR_AUTO ":"", + pcmcia_socket[sock].cs_state.flags&SS_IOCARD?\ + "SS_IOCARD ":"", + pcmcia_socket[sock].cs_state.flags&SS_RESET?\ + "SS_RESET ":"", + pcmcia_socket[sock].cs_state.flags&SS_SPKR_ENA?\ + "SS_SPKR_ENA ":"", + pcmcia_socket[sock].cs_state.flags&SS_OUTPUT_ENA?\ + "SS_OUTPUT_ENA ":""); + + p+=sprintf(p, "Vcc : %d\n", pcmcia_socket[sock].cs_state.Vcc); + p+=sprintf(p, "Vpp : %d\n", pcmcia_socket[sock].cs_state.Vpp); + p+=sprintf(p, "irq : %d\n", pcmcia_socket[sock].cs_state.io_irq); + p+=sprintf(p, "I/O : %u\n", pcmcia_socket[sock].speed_io); + p+=sprintf(p, "attribute: %u\n", pcmcia_socket[sock].speed_attr); + p+=sprintf(p, "common : %u\n", pcmcia_socket[sock].speed_mem); + return p-buf; +} + + +#endif /* defined(CONFIG_PROC_FS) */ diff -Nru a/drivers/pcmcia/au1000_pb1x00.c b/drivers/pcmcia/au1000_pb1x00.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/pcmcia/au1000_pb1x00.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,411 @@ +/* + * + * Alchemy Semi Pb1x00 boards specific pcmcia routines. + * + * Copyright 2002 MontaVista Software Inc. + * Author: MontaVista Software, Inc. + * ppopov@mvista.com or source@mvista.com + * + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include "cs_internal.h" + +#include +#include +#include + +#include +#include + +#ifdef CONFIG_MIPS_PB1000 +#include +#define PCMCIA_IRQ AU1000_GPIO_15 +#elif defined (CONFIG_MIPS_PB1500) +#include +#define PCMCIA_IRQ AU1000_GPIO_11 /* fixme */ +#elif defined (CONFIG_MIPS_PB1100) +#include +#define PCMCIA_IRQ AU1000_GPIO_11 +#endif + +static int pb1x00_pcmcia_init(struct pcmcia_init *init) +{ +#ifdef CONFIG_MIPS_PB1000 + u16 pcr; + pcr = PCR_SLOT_0_RST | PCR_SLOT_1_RST; + + au_writel(0x8000, PB1000_MDR); /* clear pcmcia interrupt */ + au_sync_delay(100); + au_writel(0x4000, PB1000_MDR); /* enable pcmcia interrupt */ + au_sync(); + + pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,0); + pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,1); + au_writel(pcr, PB1000_PCR); + au_sync_delay(20); + + return PCMCIA_NUM_SOCKS; + +#else /* fixme -- take care of the Pb1500 at some point */ + + u16 pcr; + pcr = au_readw(PB1100_MEM_PCMCIA) & ~0xf; /* turn off power */ + pcr &= ~(PB1100_PC_DEASSERT_RST | PB1100_PC_DRV_EN); + au_writew(pcr, PB1100_MEM_PCMCIA); + au_sync_delay(500); + return PCMCIA_NUM_SOCKS; +#endif +} + +static int pb1x00_pcmcia_shutdown(void) +{ +#ifdef CONFIG_MIPS_PB1000 + u16 pcr; + pcr = PCR_SLOT_0_RST | PCR_SLOT_1_RST; + pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,0); + pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,1); + au_writel(pcr, PB1000_PCR); + au_sync_delay(20); + return 0; +#else + u16 pcr; + pcr = au_readw(PB1100_MEM_PCMCIA) & ~0xf; /* turn off power */ + pcr &= ~(PB1100_PC_DEASSERT_RST | PB1100_PC_DRV_EN); + au_writew(pcr, PB1100_MEM_PCMCIA); + au_sync_delay(2); + return 0; +#endif +} + +static int +pb1x00_pcmcia_socket_state(unsigned sock, struct pcmcia_state *state) +{ + u32 inserted0, inserted1; + u16 vs0, vs1; + +#ifdef CONFIG_MIPS_PB1000 + vs0 = vs1 = (u16)au_readl(PB1000_ACR1); + inserted0 = !(vs0 & (ACR1_SLOT_0_CD1 | ACR1_SLOT_0_CD2)); + inserted1 = !(vs1 & (ACR1_SLOT_1_CD1 | ACR1_SLOT_1_CD2)); + vs0 = (vs0 >> 4) & 0x3; + vs1 = (vs1 >> 12) & 0x3; +#else + vs0 = (au_readw(PB1100_BOARD_STATUS) >> 4) & 0x3; + inserted0 = !((au_readl(SYS_PINSTATERD) >> 9) & 0x1); /* gpio 9 */ +#endif + + state->ready = 0; + state->vs_Xv = 0; + state->vs_3v = 0; + state->detect = 0; + + if (sock == 0) { + if (inserted0) { + switch (vs0) { + case 0: + case 2: + state->vs_3v=1; + break; + case 3: /* 5V */ + break; + default: + /* return without setting 'detect' */ + printk(KERN_ERR "pb1x00 bad VS (%d)\n", + vs0); + return; + } + state->detect = 1; + } + } + else { + if (inserted1) { + switch (vs1) { + case 0: + case 2: + state->vs_3v=1; + break; + case 3: /* 5V */ + break; + default: + /* return without setting 'detect' */ + printk(KERN_ERR "pb1x00 bad VS (%d)\n", + vs1); + return; + } + state->detect = 1; + } + } + + if (state->detect) { + state->ready = 1; + } + + state->bvd1=1; + state->bvd2=1; + state->wrprot=0; + return 1; +} + + +static int pb1x00_pcmcia_get_irq_info(struct pcmcia_irq_info *info) +{ + + if(info->sock > PCMCIA_MAX_SOCK) return -1; + + /* + * Even in the case of the Pb1000, both sockets are connected + * to the same irq line. + */ + info->irq = PCMCIA_IRQ; + + return 0; +} + + +static int +pb1x00_pcmcia_configure_socket(const struct pcmcia_configure *configure) +{ + u16 pcr; + + if(configure->sock > PCMCIA_MAX_SOCK) return -1; + +#ifdef CONFIG_MIPS_PB1000 + pcr = au_readl(PB1000_PCR); + + if (configure->sock == 0) { + pcr &= ~(PCR_SLOT_0_VCC0 | PCR_SLOT_0_VCC1 | + PCR_SLOT_0_VPP0 | PCR_SLOT_0_VPP1); + } + else { + pcr &= ~(PCR_SLOT_1_VCC0 | PCR_SLOT_1_VCC1 | + PCR_SLOT_1_VPP0 | PCR_SLOT_1_VPP1); + } + + pcr &= ~PCR_SLOT_0_RST; + DEBUG(KERN_INFO "Vcc %dV Vpp %dV, pcr %x\n", + configure->vcc, configure->vpp, pcr); + switch(configure->vcc){ + case 0: /* Vcc 0 */ + switch(configure->vpp) { + case 0: + pcr |= SET_VCC_VPP(VCC_HIZ,VPP_GND, + configure->sock); + break; + case 12: + pcr |= SET_VCC_VPP(VCC_HIZ,VPP_12V, + configure->sock); + break; + case 50: + pcr |= SET_VCC_VPP(VCC_HIZ,VPP_5V, + configure->sock); + break; + case 33: + pcr |= SET_VCC_VPP(VCC_HIZ,VPP_3V, + configure->sock); + break; + default: + pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ, + configure->sock); + printk("%s: bad Vcc/Vpp (%d:%d)\n", + __FUNCTION__, + configure->vcc, + configure->vpp); + break; + } + break; + case 50: /* Vcc 5V */ + switch(configure->vpp) { + case 0: + pcr |= SET_VCC_VPP(VCC_5V,VPP_GND, + configure->sock); + break; + case 50: + pcr |= SET_VCC_VPP(VCC_5V,VPP_5V, + configure->sock); + break; + case 12: + pcr |= SET_VCC_VPP(VCC_5V,VPP_12V, + configure->sock); + break; + case 33: + pcr |= SET_VCC_VPP(VCC_5V,VPP_3V, + configure->sock); + break; + default: + pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ, + configure->sock); + printk("%s: bad Vcc/Vpp (%d:%d)\n", + __FUNCTION__, + configure->vcc, + configure->vpp); + break; + } + break; + case 33: /* Vcc 3.3V */ + switch(configure->vpp) { + case 0: + pcr |= SET_VCC_VPP(VCC_3V,VPP_GND, + configure->sock); + break; + case 50: + pcr |= SET_VCC_VPP(VCC_3V,VPP_5V, + configure->sock); + break; + case 12: + pcr |= SET_VCC_VPP(VCC_3V,VPP_12V, + configure->sock); + break; + case 33: + pcr |= SET_VCC_VPP(VCC_3V,VPP_3V, + configure->sock); + break; + default: + pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ, + configure->sock); + printk("%s: bad Vcc/Vpp (%d:%d)\n", + __FUNCTION__, + configure->vcc, + configure->vpp); + break; + } + break; + default: /* what's this ? */ + pcr |= SET_VCC_VPP(VCC_HIZ,VPP_HIZ,configure->sock); + printk(KERN_ERR "%s: bad Vcc %d\n", + __FUNCTION__, configure->vcc); + break; + } + + if (configure->sock == 0) { + pcr &= ~(PCR_SLOT_0_RST); + if (configure->reset) + pcr |= PCR_SLOT_0_RST; + } + else { + pcr &= ~(PCR_SLOT_1_RST); + if (configure->reset) + pcr |= PCR_SLOT_1_RST; + } + au_writel(pcr, PB1000_PCR); + au_sync_delay(300); + +#else + + pcr = au_readw(PB1100_MEM_PCMCIA) & ~0xf; + + DEBUG(KERN_INFO "Vcc %dV Vpp %dV, pcr %x, reset %d\n", + configure->vcc, configure->vpp, pcr, configure->reset); + + + switch(configure->vcc){ + case 0: /* Vcc 0 */ + pcr |= SET_VCC_VPP(0,0); + break; + case 50: /* Vcc 5V */ + switch(configure->vpp) { + case 0: + pcr |= SET_VCC_VPP(2,0); + break; + case 50: + pcr |= SET_VCC_VPP(2,1); + break; + case 12: + pcr |= SET_VCC_VPP(2,2); + break; + case 33: + default: + pcr |= SET_VCC_VPP(0,0); + printk("%s: bad Vcc/Vpp (%d:%d)\n", + __FUNCTION__, + configure->vcc, + configure->vpp); + break; + } + break; + case 33: /* Vcc 3.3V */ + switch(configure->vpp) { + case 0: + pcr |= SET_VCC_VPP(1,0); + break; + case 12: + pcr |= SET_VCC_VPP(1,2); + break; + case 33: + pcr |= SET_VCC_VPP(1,1); + break; + case 50: + default: + pcr |= SET_VCC_VPP(0,0); + printk("%s: bad Vcc/Vpp (%d:%d)\n", + __FUNCTION__, + configure->vcc, + configure->vpp); + break; + } + break; + default: /* what's this ? */ + pcr |= SET_VCC_VPP(0,0); + printk(KERN_ERR "%s: bad Vcc %d\n", + __FUNCTION__, configure->vcc); + break; + } + + au_writew(pcr, PB1100_MEM_PCMCIA); + au_sync_delay(300); + + if (!configure->reset) { + pcr |= PB1100_PC_DRV_EN; + au_writew(pcr, PB1100_MEM_PCMCIA); + au_sync_delay(100); + pcr |= PB1100_PC_DEASSERT_RST; + au_writew(pcr, PB1100_MEM_PCMCIA); + au_sync_delay(100); + } + else { + pcr &= ~(PB1100_PC_DEASSERT_RST | PB1100_PC_DRV_EN); + au_writew(pcr, PB1100_MEM_PCMCIA); + au_sync_delay(100); + } +#endif + return 0; +} + +struct pcmcia_low_level pb1x00_pcmcia_ops = { + pb1x00_pcmcia_init, + pb1x00_pcmcia_shutdown, + pb1x00_pcmcia_socket_state, + pb1x00_pcmcia_get_irq_info, + pb1x00_pcmcia_configure_socket +}; diff -Nru a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c --- a/drivers/pcmcia/cs.c Tue Jul 1 18:44:33 2003 +++ b/drivers/pcmcia/cs.c Tue Jul 1 18:44:33 2003 @@ -231,18 +231,6 @@ ======================================================================*/ -static int register_callback(struct pcmcia_socket *s, void (*handler)(void *, unsigned int), void * info) -{ - int error; - - if (handler && !try_module_get(s->ss_entry->owner)) - return -ENODEV; - error = s->ss_entry->register_callback(s, handler, info); - if (!handler) - module_put(s->ss_entry->owner); - return error; -} - static int get_socket_status(struct pcmcia_socket *s, int *val) { return s->ss_entry->get_status(s, val); @@ -363,6 +351,7 @@ wait_for_completion(&socket->thread_done); BUG_ON(!socket->thread); + pcmcia_parse_events(socket, SS_DETECT); return 0; } @@ -723,6 +712,9 @@ { int ret; + if (!try_module_get(skt->owner)) + return CS_NO_CARD; + ret = socket_setup(skt, setup_delay); if (ret == CS_SUCCESS) { #ifdef CONFIG_CARDBUS @@ -733,8 +725,10 @@ #endif send_event(skt, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW); skt->socket.flags &= ~SS_DEBOUNCED; - } else + } else { socket_shutdown(skt); + module_put(skt->owner); + } return ret; } @@ -778,14 +772,55 @@ send_event(skt, CS_EVENT_PM_RESUME, CS_EVENT_PRI_LOW); } skt->socket.flags &= ~SS_DEBOUNCED; - } else + } else { + unsigned int old_state = skt->state; socket_shutdown(skt); + if (old_state & SOCKET_PRESENT) + module_put(skt->owner); + } skt->state &= ~SOCKET_SUSPEND; return CS_SUCCESS; } +static void socket_remove(struct pcmcia_socket *skt) +{ + socket_shutdown(skt); + module_put(skt->owner); +} + +/* + * Process a socket card detect status change. + * + * If we don't have a card already present, delay the detect event for + * about 20ms (to be on the safe side) before reading the socket status. + * + * Some i82365-based systems send multiple SS_DETECT events during card + * insertion, and the "card present" status bit seems to bounce. This + * will probably be true with GPIO-based card detection systems after + * the product has aged. + */ +static void socket_detect_change(struct pcmcia_socket *skt) +{ + if (!(skt->state & SOCKET_SUSPEND)) { + int status; + + if (!(skt->state & SOCKET_PRESENT)) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(cs_to_timeout(2)); + } + + get_socket_status(skt, &status); + if ((skt->state & SOCKET_PRESENT) && + !(status & SS_DETECT)) + socket_remove(skt); + if (!(skt->state & SOCKET_PRESENT) && + (status & SS_DETECT)) + socket_insert(skt); + } +} + static int pccardd(void *__skt) { struct pcmcia_socket *skt = __skt; @@ -809,17 +844,8 @@ if (events) { down(&skt->skt_sem); - if (events & SS_DETECT && !(skt->state & SOCKET_SUSPEND)) { - int status; - - get_socket_status(skt, &status); - if ((skt->state & SOCKET_PRESENT) && - !(status & SS_DETECT)) - socket_shutdown(skt); - if (!(skt->state & SOCKET_PRESENT) && - (status & SS_DETECT)) - socket_insert(skt); - } + if (events & SS_DETECT) + socket_detect_change(skt); if (events & SS_BATDEAD) send_event(skt, CS_EVENT_BATTERY_DEAD, CS_EVENT_PRI_LOW); if (events & SS_BATWARN) @@ -839,21 +865,17 @@ } remove_wait_queue(&skt->thread_wait, &wait); - socket_shutdown(skt); - complete_and_exit(&skt->thread_done, 0); } -static void parse_events(void *info, u_int events) +void pcmcia_parse_events(struct pcmcia_socket *s, u_int events) { - struct pcmcia_socket *s = info; - spin_lock(&s->thread_lock); s->thread_events |= events; spin_unlock(&s->thread_lock); wake_up(&s->thread_wait); -} /* parse_events */ +} /* pcmcia_parse_events */ /*====================================================================== @@ -1114,9 +1136,6 @@ handle->event_handler = NULL; } - if (--s->real_clients == 0) - register_callback(s, NULL, NULL); - return CS_SUCCESS; } /* deregister_client */ @@ -1531,11 +1550,6 @@ if (client == NULL) return CS_OUT_OF_RESOURCE; - if (++s->real_clients == 1) { - register_callback(s, &parse_events, s); - parse_events(s, SS_DETECT); - } - *handle = client; client->state &= ~CLIENT_UNBOUND; client->Socket = s; @@ -2213,7 +2227,7 @@ if (ret != 0) break; - socket_shutdown(skt); + socket_remove(skt); ret = CS_SUCCESS; } while (0); up(&skt->skt_sem); @@ -2504,6 +2518,7 @@ EXPORT_SYMBOL(dead_socket); EXPORT_SYMBOL(CardServices); EXPORT_SYMBOL(MTDHelperEntry); +EXPORT_SYMBOL(pcmcia_parse_events); struct class pcmcia_socket_class = { .name = "pcmcia_socket", diff -Nru a/drivers/pcmcia/i82092.c b/drivers/pcmcia/i82092.c --- a/drivers/pcmcia/i82092.c Tue Jul 1 18:44:39 2003 +++ b/drivers/pcmcia/i82092.c Tue Jul 1 18:44:39 2003 @@ -64,10 +64,8 @@ /* the pccard structure and its functions */ static struct pccard_operations i82092aa_operations = { - .owner = THIS_MODULE, .init = i82092aa_init, .suspend = i82092aa_suspend, - .register_callback = i82092aa_register_callback, .get_status = i82092aa_get_status, .get_socket = i82092aa_get_socket, .set_socket = i82092aa_set_socket, @@ -85,12 +83,6 @@ 3 = operational card */ int io_base; /* base io address of the socket */ - unsigned int pending_events; /* Pending events on this interface */ - - void (*handler)(void *info, u_int events); - /* callback to the driver of the card */ - void *info; /* to be passed to the handler */ - struct pcmcia_socket socket; struct pci_dev *dev; /* The PCI device for the socket */ }; @@ -142,6 +134,7 @@ sockets[i].socket.map_size = 0x1000; sockets[i].socket.irq_mask = 0; sockets[i].socket.pci_irq = dev->irq; + sockets[i].socket.owner = THIS_MODULE; sockets[i].number = i; @@ -324,23 +317,6 @@ /* Interrupt handler functionality */ -static void i82092aa_bh(void *dummy) -{ - unsigned int events; - int i; - - for (i=0; i < socket_count; i++) { - events = xchg(&(sockets[i].pending_events),0); - printk("events = %x \n",events); - if (sockets[i].handler) - sockets[i].handler(sockets[i].info, events); - } -} - - -static DECLARE_WORK(i82092aa_task, i82092aa_bh, NULL); - - static irqreturn_t i82092aa_interrupt(int irq, void *dev, struct pt_regs *regs) { int i; @@ -367,8 +343,7 @@ csc = indirect_read(i,I365_CSC); /* card status change register */ - if ((csc==0) || /* no events on this socket */ - (sockets[i].handler==NULL)) /* no way to handle events */ + if (csc==0) /* no events on this socket */ continue; handled = 1; events = 0; @@ -389,8 +364,7 @@ } if (events) { - sockets[i].pending_events |= events; - schedule_work(&i82092aa_task); + pcmcia_parse_events(&sockets[i].socket, events); } active |= events; } @@ -475,16 +449,6 @@ return retval; } -static int i82092aa_register_callback(struct pcmcia_socket *socket, void (*handler)(void *, unsigned int), void * info) -{ - unsigned int sock = container_of(socket, struct socket_info, socket)->number; - enter("i82092aa_register_callback"); - sockets[sock].handler = handler; - sockets[sock].info = info; - leave("i82092aa_register_callback"); - return 0; -} /* i82092aa_register_callback */ - static int i82092aa_get_status(struct pcmcia_socket *socket, u_int *value) { unsigned int sock = container_of(socket, struct socket_info, socket)->number; diff -Nru a/drivers/pcmcia/i82092aa.h b/drivers/pcmcia/i82092aa.h --- a/drivers/pcmcia/i82092aa.h Tue Jul 1 18:44:32 2003 +++ b/drivers/pcmcia/i82092aa.h Tue Jul 1 18:44:32 2003 @@ -35,7 +35,6 @@ static int i82092aa_set_mem_map(struct pcmcia_socket *socket, struct pccard_mem_map *mem); static int i82092aa_init(struct pcmcia_socket *socket); static int i82092aa_suspend(struct pcmcia_socket *socket); -static int i82092aa_register_callback(struct pcmcia_socket *socket, void (*handler)(void *, unsigned int), void * info); #endif diff -Nru a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c --- a/drivers/pcmcia/i82365.c Tue Jul 1 18:44:37 2003 +++ b/drivers/pcmcia/i82365.c Tue Jul 1 18:44:37 2003 @@ -164,8 +164,6 @@ ioaddr_t ioaddr; u_short psock; u_char cs_irq, intr; - void (*handler)(void *info, u_int events); - void *info; union { cirrus_state_t cirrus; vg46x_state_t vg46x; @@ -863,35 +861,6 @@ /*====================================================================*/ -static u_int pending_events[8]; -static spinlock_t pending_event_lock = SPIN_LOCK_UNLOCKED; - -static void pcic_bh(void *dummy) -{ - u_int events; - int i; - - for (i=0; i < sockets; i++) { - spin_lock_irq(&pending_event_lock); - events = pending_events[i]; - pending_events[i] = 0; - spin_unlock_irq(&pending_event_lock); - /* - SS_DETECT events need a small delay here. The reason for this is that - the "is there a card" electronics need time to see the card after the - "we have a card coming in" electronics have seen it. - */ - if (events & SS_DETECT) - mdelay(4); - if (socket[i].handler) - socket[i].handler(socket[i].info, events); - } -} - -static DECLARE_WORK(pcic_task, pcic_bh, NULL); - -static unsigned long last_detect_jiffies; - static irqreturn_t pcic_interrupt(int irq, void *dev, struct pt_regs *regs) { @@ -911,26 +880,12 @@ handled = 1; ISA_LOCK(i, flags); csc = i365_get(i, I365_CSC); - if ((csc == 0) || (!socket[i].handler) || - (i365_get(i, I365_IDENT) & 0x70)) { + if ((csc == 0) || (i365_get(i, I365_IDENT) & 0x70)) { ISA_UNLOCK(i, flags); continue; } events = (csc & I365_CSC_DETECT) ? SS_DETECT : 0; - - - /* Several sockets will send multiple "new card detected" - events in rapid succession. However, the rest of the pcmcia expects - only one such event. We just ignore these events by having a - timeout */ - - if (events) { - if ((jiffies - last_detect_jiffies)<(HZ/20)) - events = 0; - last_detect_jiffies = jiffies; - - } - + if (i365_get(i, I365_INTCTL) & I365_PC_IOCARD) events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0; else { @@ -941,12 +896,9 @@ ISA_UNLOCK(i, flags); DEBUG(2, "i82365: socket %d event 0x%02x\n", i, events); - if (events) { - spin_lock(&pending_event_lock); - pending_events[i] |= events; - spin_unlock(&pending_event_lock); - schedule_work(&pcic_task); - } + if (events) + pcmcia_parse_events(&socket[i].socket, events); + active |= events; } if (!active) break; @@ -968,16 +920,6 @@ /*====================================================================*/ -static int pcic_register_callback(struct pcmcia_socket *s, void (*handler)(void *, unsigned int), void * info) -{ - unsigned int sock = container_of(s, struct i82365_socket, socket)->number; - socket[sock].handler = handler; - socket[sock].info = info; - return 0; -} /* pcic_register_callback */ - -/*====================================================================*/ - static int i365_get_status(u_short sock, u_int *value) { u_int status; @@ -1400,10 +1342,8 @@ } static struct pccard_operations pcic_operations = { - .owner = THIS_MODULE, .init = pcic_init, .suspend = pcic_suspend, - .register_callback = pcic_register_callback, .get_status = pcic_get_status, .get_socket = pcic_get_socket, .set_socket = pcic_set_socket, @@ -1464,6 +1404,7 @@ for (i = 0; i < sockets; i++) { socket[i].socket.dev.dev = &i82365_device.dev; socket[i].socket.ss_entry = &pcic_operations; + socket[i].socket.owner = THIS_MODULE; socket[i].number = i; ret = pcmcia_register_socket(&socket[i].socket); if (ret && i--) { diff -Nru a/drivers/pcmcia/sa11xx_core.c b/drivers/pcmcia/sa11xx_core.c --- a/drivers/pcmcia/sa11xx_core.c Tue Jul 1 18:44:32 2003 +++ b/drivers/pcmcia/sa11xx_core.c Tue Jul 1 18:44:32 2003 @@ -38,15 +38,13 @@ #include #include #include -#include #include #include -#include #include #include #include -#include #include +#include #include #include @@ -263,29 +261,27 @@ return ret; } +static spinlock_t status_lock = SPIN_LOCK_UNLOCKED; -/* sa1100_pcmcia_task_handler() - * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - * Processes serviceable socket events using the "eventd" thread context. - * - * Event processing (specifically, the invocation of the Card Services event - * callback) occurs in this thread rather than in the actual interrupt - * handler due to the use of scheduling operations in the PCMCIA core. +/* sa1100_check_status() + * ^^^^^^^^^^^^^^^^^^^^^ */ -static void sa1100_pcmcia_task_handler(void *data) +static void sa1100_check_status(struct sa1100_pcmcia_socket *skt) { - struct sa1100_pcmcia_socket *skt = data; unsigned int events; DEBUG(4, "%s(): entering PCMCIA monitoring thread\n", __FUNCTION__); do { unsigned int status; + unsigned long flags; status = sa1100_pcmcia_skt_state(skt); + spin_lock_irqsave(&status_lock, flags); events = (status ^ skt->status) & skt->cs_state.csc_mask; skt->status = status; + spin_unlock_irqrestore(&status_lock, flags); DEBUG(2, "events: %s%s%s%s%s%s\n", events == 0 ? "" : "", @@ -295,8 +291,8 @@ events & SS_BATWARN ? "BATWARN " : "", events & SS_STSCHG ? "STSCHG " : ""); - if (events && skt->handler != NULL) - skt->handler(skt->handler_info, events); + if (events) + pcmcia_parse_events(&skt->socket, events); } while (events); } @@ -311,7 +307,7 @@ mod_timer(&skt->poll_timer, jiffies + SA1100_PCMCIA_POLL_PERIOD); - schedule_work(&skt->work); + sa1100_check_status(skt); } @@ -330,44 +326,11 @@ DEBUG(3, "%s(): servicing IRQ %d\n", __FUNCTION__, irq); - schedule_work(&skt->work); + sa1100_check_status(skt); return IRQ_HANDLED; } -/* sa1100_pcmcia_register_callback() - * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - * Implements the register_callback() operation for the in-kernel - * PCMCIA service (formerly SS_RegisterCallback in Card Services). If - * the function pointer `handler' is not NULL, remember the callback - * location in the state for `sock', and increment the usage counter - * for the driver module. (The callback is invoked from the interrupt - * service routine, sa1100_pcmcia_interrupt(), to notify Card Services - * of interesting events.) Otherwise, clear the callback pointer in the - * socket state and decrement the module usage count. - * - * Returns: 0 - */ -static int -sa1100_pcmcia_register_callback(struct pcmcia_socket *sock, - void (*handler)(void *, unsigned int), - void *info) -{ - struct sa1100_pcmcia_socket *skt = to_sa1100_socket(sock); - - if (handler) { - if (!try_module_get(skt->ops->owner)) - return -ENODEV; - skt->handler_info = info; - skt->handler = handler; - } else { - skt->handler = NULL; - module_put(skt->ops->owner); - } - - return 0; -} - /* sa1100_pcmcia_get_status() * ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -655,10 +618,8 @@ static struct pccard_operations sa11xx_pcmcia_operations = { - .owner = THIS_MODULE, .init = sa1100_pcmcia_sock_init, .suspend = sa1100_pcmcia_suspend, - .register_callback = sa1100_pcmcia_register_callback, .get_status = sa1100_pcmcia_get_status, .get_socket = sa1100_pcmcia_get_socket, .set_socket = sa1100_pcmcia_set_socket, @@ -765,9 +726,8 @@ memset(skt, 0, sizeof(*skt)); skt->socket.ss_entry = &sa11xx_pcmcia_operations; + skt->socket.owner = ops->owner; skt->socket.dev.dev = dev; - - INIT_WORK(&skt->work, sa1100_pcmcia_task_handler, skt); init_timer(&skt->poll_timer); skt->poll_timer.function = sa1100_pcmcia_poll_event; diff -Nru a/drivers/pcmcia/sa11xx_core.h b/drivers/pcmcia/sa11xx_core.h --- a/drivers/pcmcia/sa11xx_core.h Tue Jul 1 18:44:36 2003 +++ b/drivers/pcmcia/sa11xx_core.h Tue Jul 1 18:44:36 2003 @@ -59,8 +59,6 @@ unsigned int status; socket_state_t cs_state; - void (*handler)(void *, unsigned int); - void *handler_info; unsigned short spd_io[MAX_IO_WIN]; unsigned short spd_mem[MAX_WIN]; @@ -75,7 +73,6 @@ unsigned int irq_state; struct timer_list poll_timer; - struct work_struct work; }; struct pcmcia_low_level { diff -Nru a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c --- a/drivers/pcmcia/tcic.c Tue Jul 1 18:44:35 2003 +++ b/drivers/pcmcia/tcic.c Tue Jul 1 18:44:35 2003 @@ -116,8 +116,6 @@ struct tcic_socket { u_short psock; - void (*handler)(void *info, u_int events); - void *info; u_char last_sstat; u_char id; struct pcmcia_socket socket; @@ -433,10 +431,9 @@ for (i = 0; i < sock; i++) { if ((i == ignore) || is_active(i)) continue; socket_table[sockets].psock = i; - socket_table[sockets].handler = NULL; - socket_table[sockets].info = NULL; socket_table[sockets].id = get_tcic_id(); + socket_table[sockets].socket.owner = THIS_MODULE; /* only 16-bit cards, memory windows must be size-aligned */ /* No PCI or CardBus support */ socket_table[sockets].socket.features = SS_CAP_PCCARD | SS_CAP_MEM_ALIGN; @@ -558,26 +555,6 @@ /*====================================================================*/ -static u_int pending_events[2]; -static spinlock_t pending_event_lock = SPIN_LOCK_UNLOCKED; - -static void tcic_bh(void *dummy) -{ - u_int events; - int i; - - for (i=0; i < sockets; i++) { - spin_lock_irq(&pending_event_lock); - events = pending_events[i]; - pending_events[i] = 0; - spin_unlock_irq(&pending_event_lock); - if (socket_table[i].handler) - socket_table[i].handler(socket_table[i].info, events); - } -} - -static DECLARE_WORK(tcic_task, tcic_bh, NULL); - static irqreturn_t tcic_interrupt(int irq, void *dev, struct pt_regs *regs) { int i, quick = 0; @@ -605,7 +582,7 @@ tcic_setb(TCIC_ICSR, TCIC_ICSR_CLEAR); quick = 1; } - if ((latch == 0) || (socket_table[psock].handler == NULL)) + if (latch == 0) continue; events = (latch & TCIC_SSTAT_CD) ? SS_DETECT : 0; events |= (latch & TCIC_SSTAT_WP) ? SS_WRPROT : 0; @@ -617,10 +594,7 @@ events |= (latch & TCIC_SSTAT_LBAT2) ? SS_BATWARN : 0; } if (events) { - spin_lock(&pending_event_lock); - pending_events[i] |= events; - spin_unlock(&pending_event_lock); - schedule_work(&tcic_task); + pcmcia_parse_events(&socket_table[i].socket, events); } } @@ -645,16 +619,6 @@ /*====================================================================*/ -static int tcic_register_callback(struct pcmcia_socket *sock, void (*handler)(void *, unsigned int), void * info) -{ - u_short psock = container_of(sock, struct tcic_socket, socket)->psock; - socket_table[psock].handler = handler; - socket_table[psock].info = info; - return 0; -} /* tcic_register_callback */ - -/*====================================================================*/ - static int tcic_get_status(struct pcmcia_socket *sock, u_int *value) { u_short psock = container_of(sock, struct tcic_socket, socket)->psock; @@ -915,10 +879,8 @@ } static struct pccard_operations tcic_operations = { - .owner = THIS_MODULE, .init = tcic_init, .suspend = tcic_suspend, - .register_callback = tcic_register_callback, .get_status = tcic_get_status, .get_socket = tcic_get_socket, .set_socket = tcic_set_socket, diff -Nru a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h --- a/drivers/pcmcia/ti113x.h Tue Jul 1 18:44:34 2003 +++ b/drivers/pcmcia/ti113x.h Tue Jul 1 18:44:34 2003 @@ -175,6 +175,27 @@ new = reg & ~I365_INTR_ENA; if (new != reg) exca_writeb(socket, I365_INTCTL, new); + + /* + * If ISA interrupts don't work, then fall back to routing card + * interrupts to the PCI interrupt of the socket. + */ + if (!socket->socket.irq_mask) { + int irqmux, devctl; + + printk (KERN_INFO "ti113x: Routing card interrupts to PCI\n"); + + devctl = config_readb(socket, TI113X_DEVICE_CONTROL); + devctl &= ~TI113X_DCR_IMODE_MASK; + + irqmux = config_readl(socket, TI122X_IRQMUX); + irqmux = (irqmux & ~0x0f) | 0x02; /* route INTA */ + irqmux = (irqmux & ~0xf0) | 0x20; /* route INTB */ + + config_writel(socket, TI122X_IRQMUX, irqmux); + config_writeb(socket, TI113X_DEVICE_CONTROL, devctl); + } + socket->socket.ss_entry->init = ti_init; return 0; } @@ -239,6 +260,17 @@ ti113x_override(socket); socket->socket.ss_entry->init = ti1250_init; return 0; +} + + +static int ti12xx_override(struct yenta_socket *socket) +{ + /* make sure that memory burst is active */ + ti_sysctl(socket) = config_readl(socket, TI113X_SYSTEM_CONTROL); + ti_sysctl(socket) |= TI122X_SCR_MRBURSTUP; + config_writel(socket, TI113X_SYSTEM_CONTROL, ti_sysctl(socket)); + + return ti113x_override(socket); } #endif /* CONFIG_CARDBUS */ diff -Nru a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c --- a/drivers/pcmcia/yenta_socket.c Tue Jul 1 18:44:36 2003 +++ b/drivers/pcmcia/yenta_socket.c Tue Jul 1 18:44:36 2003 @@ -250,7 +250,6 @@ if (state->flags & SS_DEBOUNCED) { /* The insertion debounce period has ended. Clear any pending insertion events */ - socket->events &= ~SS_DETECT; state->flags &= ~SS_DEBOUNCED; /* SS_DEBOUNCED is oneshot */ } yenta_set_power(socket, state); @@ -420,19 +419,6 @@ } -static void yenta_bh(void *data) -{ - struct yenta_socket *socket = data; - unsigned int events; - - spin_lock_irq(&socket->event_lock); - events = socket->events; - socket->events = 0; - spin_unlock_irq(&socket->event_lock); - if (socket->handler) - socket->handler(socket->info, events); -} - static irqreturn_t yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs) { unsigned int events; @@ -440,10 +426,7 @@ events = yenta_events(socket); if (events) { - spin_lock(&socket->event_lock); - socket->events |= events; - spin_unlock(&socket->event_lock); - schedule_work(&socket->tq_task); + pcmcia_parse_events(&socket->socket, events); return IRQ_HANDLED; } return IRQ_NONE; @@ -771,21 +754,9 @@ } -static int yenta_register_callback(struct pcmcia_socket *sock, void (*handler)(void *, unsigned int), void * info) -{ - struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); - - socket->handler = handler; - socket->info = info; - return 0; -} - - static struct pccard_operations yenta_socket_operations = { - .owner = THIS_MODULE, .init = yenta_init, .suspend = yenta_suspend, - .register_callback = yenta_register_callback, .get_status = yenta_get_status, .get_socket = yenta_get_socket, .set_socket = yenta_set_socket, @@ -807,23 +778,30 @@ unsigned short device; int (*override) (struct yenta_socket *socket); } cardbus_override[] = { - { PD(TI,1130), &ti113x_override }, { PD(TI,1031), &ti_override }, - { PD(TI,1131), &ti113x_override }, - { PD(TI,1250), &ti1250_override }, - { PD(TI,1220), &ti_override }, - { PD(TI,1221), &ti_override }, + + /* TBD: Check if these TI variants can use more + * advanced overrides instead */ { PD(TI,1210), &ti_override }, - { PD(TI,1450), &ti_override }, - { PD(TI,1225), &ti_override }, - { PD(TI,1251A), &ti_override }, { PD(TI,1211), &ti_override }, + { PD(TI,1251A), &ti_override }, { PD(TI,1251B), &ti_override }, - { PD(TI,1410), ti1250_override }, { PD(TI,1420), &ti_override }, + { PD(TI,1450), &ti_override }, { PD(TI,4410), &ti_override }, { PD(TI,4451), &ti_override }, + { PD(TI,1130), &ti113x_override }, + { PD(TI,1131), &ti113x_override }, + + { PD(TI,1220), &ti12xx_override }, + { PD(TI,1221), &ti12xx_override }, + { PD(TI,1225), &ti12xx_override }, + { PD(TI,1520), &ti12xx_override }, + + { PD(TI,1250), &ti1250_override }, + { PD(TI,1410), &ti1250_override }, + { PD(RICOH,RL5C465), &ricoh_override }, { PD(RICOH,RL5C466), &ricoh_override }, { PD(RICOH,RL5C475), &ricoh_override }, @@ -853,11 +831,11 @@ socket->socket.ss_entry = ¥ta_socket_operations; socket->socket.dev.dev = &dev->dev; socket->socket.driver_data = socket; + socket->socket.owner = THIS_MODULE; /* prepare struct yenta_socket */ socket->dev = dev; pci_set_drvdata(dev, socket); - spin_lock_init(&socket->event_lock); /* * Do some basic sanity checking.. @@ -899,8 +877,6 @@ } /* We must finish initialization here */ - - INIT_WORK(&socket->tq_task, yenta_bh, socket); if (!socket->cb_irq || request_irq(socket->cb_irq, yenta_interrupt, SA_SHIRQ, socket->dev->dev.name, socket)) { /* No IRQ or request_irq failed. Poll */ diff -Nru a/drivers/pcmcia/yenta_socket.h b/drivers/pcmcia/yenta_socket.h --- a/drivers/pcmcia/yenta_socket.h Tue Jul 1 18:44:34 2003 +++ b/drivers/pcmcia/yenta_socket.h Tue Jul 1 18:44:34 2003 @@ -99,11 +99,6 @@ struct pci_dev *dev; int cb_irq, io_irq; void *base; - void (*handler)(void *, unsigned int); - void *info; - spinlock_t event_lock; - unsigned int events; - struct work_struct tq_task; struct timer_list poll_timer; struct pcmcia_socket socket; diff -Nru a/drivers/pnp/interface.c b/drivers/pnp/interface.c --- a/drivers/pnp/interface.c Tue Jul 1 18:44:32 2003 +++ b/drivers/pnp/interface.c Tue Jul 1 18:44:32 2003 @@ -323,14 +323,14 @@ if (!strnicmp(buf,"auto",4)) { if (dev->active) goto done; - pnp_init_resources(&dev->res); + pnp_init_resource_table(&dev->res); retval = pnp_auto_config_dev(dev); goto done; } if (!strnicmp(buf,"clear",5)) { if (dev->active) goto done; - pnp_init_resources(&dev->res); + pnp_init_resource_table(&dev->res); goto done; } if (!strnicmp(buf,"get",3)) { @@ -345,7 +345,7 @@ if (dev->active) goto done; buf += 3; - pnp_init_resources(&dev->res); + pnp_init_resource_table(&dev->res); down(&pnp_res_mutex); while (1) { while (isspace(*buf)) diff -Nru a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c --- a/drivers/pnp/isapnp/core.c Tue Jul 1 18:44:35 2003 +++ b/drivers/pnp/isapnp/core.c Tue Jul 1 18:44:35 2003 @@ -458,7 +458,7 @@ dev->capabilities |= PNP_READ; dev->capabilities |= PNP_WRITE; dev->capabilities |= PNP_DISABLE; - pnp_init_resources(&dev->res); + pnp_init_resource_table(&dev->res); return dev; } @@ -1020,7 +1020,7 @@ static int isapnp_get_resources(struct pnp_dev *dev, struct pnp_resource_table * res) { int ret; - pnp_init_resources(res); + pnp_init_resource_table(res); isapnp_cfg_begin(dev->card->number, dev->number); ret = isapnp_read_resources(dev, res); isapnp_cfg_end(); diff -Nru a/drivers/pnp/manager.c b/drivers/pnp/manager.c --- a/drivers/pnp/manager.c Tue Jul 1 18:44:38 2003 +++ b/drivers/pnp/manager.c Tue Jul 1 18:44:38 2003 @@ -190,10 +190,9 @@ * @table: pointer to the desired resource table * */ -void pnp_init_resources(struct pnp_resource_table *table) +void pnp_init_resource_table(struct pnp_resource_table *table) { int idx; - down(&pnp_res_mutex); for (idx = 0; idx < PNP_MAX_IRQ; idx++) { table->irq_resource[idx].name = NULL; table->irq_resource[idx].start = -1; @@ -218,7 +217,6 @@ table->mem_resource[idx].end = 0; table->mem_resource[idx].flags = IORESOURCE_AUTO; } - up(&pnp_res_mutex); } /** @@ -226,7 +224,7 @@ * @res - the resources to clean * */ -static void pnp_clean_resources(struct pnp_resource_table * res) +static void pnp_clean_resource_table(struct pnp_resource_table * res) { int idx; for (idx = 0; idx < PNP_MAX_IRQ; idx++) { @@ -278,7 +276,7 @@ return -ENODEV; down(&pnp_res_mutex); - pnp_clean_resources(&dev->res); /* start with a fresh slate */ + pnp_clean_resource_table(&dev->res); /* start with a fresh slate */ if (dev->independent) { port = dev->independent->port; mem = dev->independent->mem; @@ -351,7 +349,7 @@ return 1; fail: - pnp_clean_resources(&dev->res); + pnp_clean_resource_table(&dev->res); up(&pnp_res_mutex); return 0; } @@ -510,7 +508,7 @@ /* release the resources so that other devices can use them */ down(&pnp_res_mutex); - pnp_clean_resources(&dev->res); + pnp_clean_resource_table(&dev->res); up(&pnp_res_mutex); return 1; @@ -539,4 +537,4 @@ EXPORT_SYMBOL(pnp_activate_dev); EXPORT_SYMBOL(pnp_disable_dev); EXPORT_SYMBOL(pnp_resource_change); -EXPORT_SYMBOL(pnp_init_resources); +EXPORT_SYMBOL(pnp_init_resource_table); diff -Nru a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c --- a/drivers/pnp/pnpbios/core.c Tue Jul 1 18:44:31 2003 +++ b/drivers/pnp/pnpbios/core.c Tue Jul 1 18:44:31 2003 @@ -937,7 +937,7 @@ /* clear out the damaged flags */ if (!dev->active) - pnp_init_resources(&dev->res); + pnp_init_resource_table(&dev->res); pnp_add_device(dev); pnpbios_interface_attach_device(node); diff -Nru a/drivers/pnp/resource.c b/drivers/pnp/resource.c --- a/drivers/pnp/resource.c Tue Jul 1 18:44:35 2003 +++ b/drivers/pnp/resource.c Tue Jul 1 18:44:35 2003 @@ -85,7 +85,6 @@ int pnp_register_irq_resource(struct pnp_option *option, struct pnp_irq *data) { - int i; struct pnp_irq *ptr; if (!option) return -EINVAL; @@ -101,9 +100,13 @@ option->irq = data; #ifdef CONFIG_PCI - for (i=0; i<16; i++) - if (data->map & (1<map & (1< * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001 * - * $Revision: 1.99 $ + * $Revision: 1.101 $ */ #include @@ -32,7 +32,7 @@ /* * SECTION: Constant definitions to be used within this file */ -#define DASD_CHANQ_MAX_SIZE 5 +#define DASD_CHANQ_MAX_SIZE 4 /* * SECTION: exported variables of dasd.c @@ -803,24 +803,18 @@ * 2) delayed start of request where start_IO failed with -EBUSY * 3) timeout for missing state change interrupts * The head of the ccw queue will have status DASD_CQR_IN_IO for 1), - * DASD_CQR_QUEUED for 2) and DASD_CQR_PENDING for 3). + * DASD_CQR_QUEUED for 2) and 3). */ static void dasd_timeout_device(unsigned long ptr) { unsigned long flags; struct dasd_device *device; - struct dasd_ccw_req *cqr; device = (struct dasd_device *) ptr; spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); /* re-activate first request in queue */ - if (!list_empty(&device->ccw_queue)) { - cqr = list_entry(device->ccw_queue.next, - struct dasd_ccw_req, list); - if (cqr->status == DASD_CQR_PENDING) - cqr->status = DASD_CQR_QUEUED; - } + device->stopped &= ~DASD_STOPPED_PENDING; spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); dasd_schedule_bh(device); } @@ -861,10 +855,6 @@ /* * Handles the state change pending interrupt. - * Search for the device related request queue and check if the first - * cqr in queue in in status 'DASD_CQR_PENDING'. - * If so the status is set to 'DASD_CQR_QUEUED' to reactivate - * the device. */ static void do_state_change_pending(void *data) @@ -874,29 +864,12 @@ struct dasd_device *device; } *p; struct dasd_device *device; - struct dasd_ccw_req *cqr; p = data; device = p->device; DBF_EVENT(DBF_NOTICE, "State change Interrupt for bus_id %s", device->cdev->dev.bus_id); - - spin_lock_irq(get_ccwdev_lock(device->cdev)); - /* re-activate first request in queue */ - if (!list_empty(&device->ccw_queue)) { - cqr = list_entry(device->ccw_queue.next, - struct dasd_ccw_req, list); - if (cqr == NULL) { - MESSAGE (KERN_DEBUG, - "got state change pending interrupt on" - "an idle device: bus_id %s", - device->cdev->dev.bus_id); - return; - } - if (cqr->status == DASD_CQR_PENDING) - cqr->status = DASD_CQR_QUEUED; - } - spin_unlock_irq(get_ccwdev_lock(device->cdev)); + device->stopped &= ~DASD_STOPPED_PENDING; dasd_schedule_bh(device); dasd_put_device(device); kfree(p); @@ -1036,7 +1009,8 @@ if (cqr->list.next != &device->ccw_queue) { next = list_entry(cqr->list.next, struct dasd_ccw_req, list); - if (next->status == DASD_CQR_QUEUED) { + if ((next->status == DASD_CQR_QUEUED) && + (!device->stopped)) { if (device->discipline->start_IO(next) == 0) expires = next->expires; else @@ -1264,7 +1238,8 @@ if (list_empty(&device->ccw_queue)) return; cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list); - if (cqr->status == DASD_CQR_QUEUED) { + if ((cqr->status == DASD_CQR_QUEUED) && + (!device->stopped)) { /* try to start the first I/O that can be started */ rc = device->discipline->start_IO(cqr); if (rc == 0) diff -Nru a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c --- a/drivers/s390/block/dasd_3990_erp.c Tue Jul 1 18:44:37 2003 +++ b/drivers/s390/block/dasd_3990_erp.c Tue Jul 1 18:44:37 2003 @@ -5,7 +5,7 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000, 2001 * - * $Revision: 1.24 $ + * $Revision: 1.25 $ */ #include @@ -221,13 +221,6 @@ * Block the given device request queue to prevent from further * processing until the started timer has expired or an related * interrupt was received. - * - * PARAMETER - * erp request to be blocked - * expires time to wait until restart (in jiffies) - * - * RETURN VALUES - * void */ static void dasd_3990_erp_block_queue(struct dasd_ccw_req * erp, int expires) @@ -238,7 +231,9 @@ DEV_MESSAGE(KERN_INFO, device, "blocking request queue for %is", expires); - erp->status = DASD_CQR_PENDING; + device->stopped |= DASD_STOPPED_PENDING; + erp->status = DASD_CQR_QUEUED; + dasd_set_timer(device, expires); } @@ -453,9 +448,11 @@ if (sense[25] == 0x1D) { /* state change pending */ - DEV_MESSAGE(KERN_INFO, device, "%s", - "waiting for state change pending " "int"); - + DEV_MESSAGE(KERN_INFO, device, + "waiting for state change pending " + "interrupt, %d retries left", + erp->retries); + dasd_3990_erp_block_queue(erp, 30*HZ); } else { diff -Nru a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c --- a/drivers/s390/block/dasd_eckd.c Tue Jul 1 18:44:31 2003 +++ b/drivers/s390/block/dasd_eckd.c Tue Jul 1 18:44:31 2003 @@ -7,7 +7,7 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.42 $ + * $Revision: 1.46 $ */ #include @@ -80,7 +80,13 @@ static int dasd_eckd_probe (struct ccw_device *cdev) { - return dasd_generic_probe (cdev, &dasd_eckd_discipline); + int ret; + + ret = dasd_generic_probe (cdev, &dasd_eckd_discipline); + if (ret) + return ret; + ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP); + return 0; } static int @@ -204,7 +210,7 @@ data->ep_sys_time = get_clock (); de_ccw->count = sizeof (struct DE_eckd_data); - de_ccw->flags = CCW_FLAG_SLI; + de_ccw->flags |= CCW_FLAG_SLI; } return; @@ -281,19 +287,11 @@ /* check for sequential prestage - enhance cylinder range */ if (data->attributes.operation == DASD_SEQ_PRESTAGE || data->attributes.operation == DASD_SEQ_ACCESS) { - - if (end.cyl + private->attrib.nr_cyl < geo.cyl) { + + if (end.cyl + private->attrib.nr_cyl < geo.cyl) end.cyl += private->attrib.nr_cyl; - DBF_DEV_EVENT(DBF_NOTICE, device, - "Enhanced DE Cylinder from %x to %x", - (totrk / geo.head), end.cyl); - } else { + else end.cyl = (geo.cyl - 1); - DBF_DEV_EVENT(DBF_NOTICE, device, - "Enhanced DE Cylinder from %x to " - "End of device %x", - (totrk / geo.head), end.cyl); - } } data->beg_ext.cyl = beg.cyl; @@ -512,12 +510,6 @@ private->rdc_data.cu_type, private->rdc_data.cu_model.model); return 0; - - /* get characteristis via diag to determine the kind of - * minidisk under VM needed beacause XRC is not support - * by VM (jet). Can be removed as soon as VM supports XRC - * FIXME: TBD ??? HUM - */ } static struct dasd_ccw_req * @@ -1130,13 +1122,16 @@ return -ENODEV; cqr = dasd_smalloc_request(dasd_eckd_discipline.name, - 1, 0, device); + 1, 32, device); if (cqr == NULL) { MESSAGE(KERN_WARNING, "%s", "No memory to allocate initialization request"); return -ENOMEM; } cqr->cpaddr->cmd_code = DASD_ECKD_CCW_RELEASE; + cqr->cpaddr->flags |= CCW_FLAG_SLI; + cqr->cpaddr->count = 32; + cqr->cpaddr->cda = (__u32)(addr_t) cqr->data; cqr->device = device; cqr->retries = 0; cqr->expires = 10 * HZ; @@ -1145,14 +1140,14 @@ rc = dasd_sleep_on_immediatly(cqr); - dasd_kfree_request(cqr, cqr->device); + dasd_sfree_request(cqr, cqr->device); return rc; } /* * Reserve device ioctl. * Options are set to 'synchronous wait for interrupt' and - * 'timeout the request'. This leads to an terminate IO if + * 'timeout the request'. This leads to a terminate IO if * the interrupt is outstanding for a certain time. */ static int @@ -1170,14 +1165,16 @@ return -ENODEV; cqr = dasd_smalloc_request(dasd_eckd_discipline.name, - 1, 0, device); - + 1, 32, device); if (cqr == NULL) { MESSAGE(KERN_WARNING, "%s", "No memory to allocate initialization request"); return -ENOMEM; } cqr->cpaddr->cmd_code = DASD_ECKD_CCW_RESERVE; + cqr->cpaddr->flags |= CCW_FLAG_SLI; + cqr->cpaddr->count = 32; + cqr->cpaddr->cda = (__u32)(addr_t) cqr->data; cqr->device = device; cqr->retries = 0; cqr->expires = 10 * HZ; @@ -1186,11 +1183,7 @@ rc = dasd_sleep_on_immediatly(cqr); - if (rc == -EIO) { - /* Request got an error or has been timed out. */ - dasd_eckd_release(bdev, no, args); - } - dasd_kfree_request(cqr, cqr->device); + dasd_sfree_request(cqr, cqr->device); return rc; } @@ -1214,13 +1207,16 @@ return -ENODEV; cqr = dasd_smalloc_request(dasd_eckd_discipline.name, - 1, 0, device); + 1, 32, device); if (cqr == NULL) { MESSAGE(KERN_WARNING, "%s", "No memory to allocate initialization request"); return -ENOMEM; } cqr->cpaddr->cmd_code = DASD_ECKD_CCW_SLCK; + cqr->cpaddr->flags |= CCW_FLAG_SLI; + cqr->cpaddr->count = 32; + cqr->cpaddr->cda = (__u32)(addr_t) cqr->data; cqr->device = device; cqr->retries = 0; cqr->expires = 10 * HZ; @@ -1229,11 +1225,7 @@ rc = dasd_sleep_on_immediatly(cqr); - if (rc == -EIO) { - /* Request got an error or has been timed out. */ - dasd_eckd_release(bdev, no, args); - } - dasd_kfree_request(cqr, cqr->device); + dasd_sfree_request(cqr, cqr->device); return rc; } @@ -1330,17 +1322,13 @@ private = (struct dasd_eckd_private *) device->private; - DBF_DEV_EVENT(DBF_ERR, device, - "cache operation mode got " - "%x (%i cylinder prestage)", - attrib.operation, attrib.nr_cyl); - private->attrib = attrib; DBF_DEV_EVENT(DBF_ERR, device, "cache operation mode set to " "%x (%i cylinder prestage)", private->attrib.operation, private->attrib.nr_cyl); + return 0; } diff -Nru a/drivers/s390/block/dasd_erp.c b/drivers/s390/block/dasd_erp.c --- a/drivers/s390/block/dasd_erp.c Tue Jul 1 18:44:32 2003 +++ b/drivers/s390/block/dasd_erp.c Tue Jul 1 18:44:32 2003 @@ -7,7 +7,7 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001 * - * $Revision: 1.9 $ + * $Revision: 1.10 $ */ #include @@ -86,48 +86,31 @@ atomic_dec(&device->ref_count); } + /* - * DESCRIPTION - * sets up the default-ERP struct dasd_ccw_req, namely one, which performs - * a TIC to the original channel program with a retry counter of 16 - * - * PARAMETER - * cqr failed CQR - * - * RETURN VALUES - * erp CQR performing the ERP + * dasd_default_erp_action just retries the current cqr */ struct dasd_ccw_req * dasd_default_erp_action(struct dasd_ccw_req * cqr) { struct dasd_device *device; - struct dasd_ccw_req *erp; - MESSAGE(KERN_DEBUG, "%s", "Default ERP called... "); device = cqr->device; - erp = dasd_alloc_erp_request((char *) &cqr->magic, 1, 0, device); - if (IS_ERR(erp)) { - DEV_MESSAGE(KERN_ERR, device, "%s", - "Unable to allocate request for default ERP"); - cqr->status = DASD_CQR_FAILED; - cqr->stopclk = get_clock(); - return cqr; - } - - erp->cpaddr->cmd_code = CCW_CMD_TIC; - erp->cpaddr->cda = (__u32) (addr_t) cqr->cpaddr; - erp->function = dasd_default_erp_action; - erp->refers = cqr; - erp->device = device; - erp->magic = cqr->magic; - erp->retries = 16; - erp->status = DASD_CQR_FILLED; - - list_add(&erp->list, &device->ccw_queue); - erp->status = DASD_CQR_QUEUED; - - return erp; + /* just retry - there is nothing to save ... I got no sense data.... */ + if (cqr->retries > 0) { + DEV_MESSAGE (KERN_DEBUG, device, + "default ERP called (%i retries left)", + cqr->retries); + cqr->status = DASD_CQR_QUEUED; + } else { + DEV_MESSAGE (KERN_WARNING, device, "%s", + "default ERP called (NO retry left)"); + + cqr->status = DASD_CQR_FAILED; + cqr->stopclk = get_clock (); + } + return cqr; } /* end dasd_default_erp_action */ /* diff -Nru a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c --- a/drivers/s390/block/dasd_fba.c Tue Jul 1 18:44:36 2003 +++ b/drivers/s390/block/dasd_fba.c Tue Jul 1 18:44:36 2003 @@ -4,7 +4,7 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.29 $ + * $Revision: 1.30 $ */ #include @@ -57,7 +57,13 @@ static int dasd_fba_probe(struct ccw_device *cdev) { - return dasd_generic_probe (cdev, &dasd_fba_discipline); + int ret; + + ret = dasd_generic_probe (cdev, &dasd_fba_discipline); + if (ret) + return ret; + ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP); + return 0; } static int diff -Nru a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h --- a/drivers/s390/block/dasd_int.h Tue Jul 1 18:44:36 2003 +++ b/drivers/s390/block/dasd_int.h Tue Jul 1 18:44:36 2003 @@ -6,7 +6,7 @@ * Bugreports.to..: * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 * - * $Revision: 1.40 $ + * $Revision: 1.42 $ */ #ifndef DASD_INT_H @@ -188,7 +188,6 @@ #define DASD_CQR_DONE 0x03 /* request is completed successfully */ #define DASD_CQR_ERROR 0x04 /* request is completed with error */ #define DASD_CQR_FAILED 0x05 /* request is finally failed */ -#define DASD_CQR_PENDING 0x06 /* request is waiting for interrupt - ERP only */ /* Signature for error recovery functions. */ typedef struct dasd_ccw_req *(*dasd_erp_fn_t) (struct dasd_ccw_req *); @@ -279,6 +278,7 @@ /* Device state and target state. */ int state, target; + int stopped; /* device (ccw_device_start) was stopped */ /* Open and reference count. */ atomic_t ref_count; @@ -305,6 +305,12 @@ struct dasd_profile_info_t profile; #endif }; + +/* reasons why device (ccw_device_start) was stopped */ +#define DASD_STOPPED_NOT_ACC 1 /* not accessible */ +#define DASD_STOPPED_QUIESCE 2 /* Quiesced */ +#define DASD_STOPPED_PENDING 4 /* long busy */ + void dasd_put_device_wake(struct dasd_device *); diff -Nru a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c --- a/drivers/s390/block/dasd_ioctl.c Tue Jul 1 18:44:35 2003 +++ b/drivers/s390/block/dasd_ioctl.c Tue Jul 1 18:44:35 2003 @@ -169,6 +169,58 @@ } /* + * Quiesce device. + */ +static int +dasd_ioctl_quiesce(struct block_device *bdev, int no, long args) +{ + struct dasd_device *device; + unsigned long flags; + + if (!capable (CAP_SYS_ADMIN)) + return -EACCES; + + device = bdev->bd_disk->private_data; + if (device == NULL) + return -ENODEV; + + DEV_MESSAGE (KERN_DEBUG, device, "%s", + "Quiesce IO on device"); + spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); + device->stopped |= DASD_STOPPED_QUIESCE; + spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); + return 0; +} + + +/* + * Quiesce device. + */ +static int +dasd_ioctl_resume(struct block_device *bdev, int no, long args) +{ + struct dasd_device *device; + unsigned long flags; + + if (!capable (CAP_SYS_ADMIN)) + return -EACCES; + + device = bdev->bd_disk->private_data; + if (device == NULL) + return -ENODEV; + + DEV_MESSAGE (KERN_DEBUG, device, "%s", + "resume IO on device"); + + spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); + device->stopped &= ~DASD_STOPPED_QUIESCE; + spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); + + dasd_schedule_bh (device); + return 0; +} + +/* * performs formatting of _device_ according to _fdata_ * Note: The discipline's format_function is assumed to deliver formatting * commands to format a single unit of the device. In terms of the ECKD @@ -438,6 +490,8 @@ { { BIODASDDISABLE, dasd_ioctl_disable }, { BIODASDENABLE, dasd_ioctl_enable }, + { BIODASDQUIESCE, dasd_ioctl_quiesce }, + { BIODASDRESUME, dasd_ioctl_resume }, { BIODASDFMT, dasd_ioctl_format }, { BIODASDINFO, dasd_ioctl_information }, { BIODASDINFO2, dasd_ioctl_information }, diff -Nru a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c --- a/drivers/s390/block/xpram.c Tue Jul 1 18:44:36 2003 +++ b/drivers/s390/block/xpram.c Tue Jul 1 18:44:36 2003 @@ -487,7 +487,7 @@ unregister_blkdev(XPRAM_MAJOR, XPRAM_NAME); devfs_remove("slram"); sys_device_unregister(&xpram_sys_device); - sysdev_class_unregister(&xpram_sys_class); + sysdev_class_unregister(&xpram_sysclass); } static int __init xpram_init(void) @@ -511,7 +511,7 @@ rc = sys_device_register(&xpram_sys_device); if (rc) { - sysdev_class_unregister(&xpram_syclass); + sysdev_class_unregister(&xpram_sysclass); return rc; } rc = xpram_setup_blkdev(); diff -Nru a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c --- a/drivers/s390/char/con3215.c Tue Jul 1 18:44:36 2003 +++ b/drivers/s390/char/con3215.c Tue Jul 1 18:44:36 2003 @@ -1215,6 +1215,7 @@ return ret; } tty3215_driver = driver; + return 0; } static void __exit diff -Nru a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c --- a/drivers/s390/char/tape_core.c Tue Jul 1 18:44:33 2003 +++ b/drivers/s390/char/tape_core.c Tue Jul 1 18:44:33 2003 @@ -372,6 +372,8 @@ device->cdev = cdev; cdev->handler = tape_do_irq; + ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP); + return 0; } @@ -903,7 +905,7 @@ { tape_dbf_area = debug_register ( "tape", 1, 2, 3*sizeof(long)); debug_register_view(tape_dbf_area, &debug_sprintf_view); - DBF_EVENT(3, "tape init: ($Revision: 1.25 $)\n"); + DBF_EVENT(3, "tape init: ($Revision: 1.26 $)\n"); tape_proc_init(); tapechar_init (); tapeblock_init (); @@ -928,7 +930,7 @@ MODULE_AUTHOR("(C) 2001 IBM Deutschland Entwicklung GmbH by Carsten Otte and " "Michael Holzheu (cotte@de.ibm.com,holzheu@de.ibm.com)"); MODULE_DESCRIPTION("Linux on zSeries channel attached " - "tape device driver ($Revision: 1.25 $)"); + "tape device driver ($Revision: 1.26 $)"); module_init(tape_init); module_exit(tape_exit); diff -Nru a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c --- a/drivers/s390/cio/ccwgroup.c Tue Jul 1 18:44:35 2003 +++ b/drivers/s390/cio/ccwgroup.c Tue Jul 1 18:44:35 2003 @@ -1,7 +1,7 @@ /* * drivers/s390/cio/ccwgroup.c * bus driver for ccwgroup - * $Revision: 1.6 $ + * $Revision: 1.7 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -196,10 +196,12 @@ value = simple_strtoul(buf, 0, 0); - if (value) + if (value == 1) ccwgroup_set_online(gdev); - else + else if (value == 0) ccwgroup_set_offline(gdev); + else + return -EINVAL; return count; } @@ -211,7 +213,7 @@ online = (to_ccwgroupdev(dev)->state == CCWGROUP_ONLINE); - return sprintf(buf, online ? "1\n" : "0\n"); + return sprintf(buf, online ? "yes\n" : "no\n"); } static DEVICE_ATTR(online, 0644, ccwgroup_online_show, ccwgroup_online_store); diff -Nru a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c --- a/drivers/s390/cio/chsc.c Tue Jul 1 18:44:35 2003 +++ b/drivers/s390/cio/chsc.c Tue Jul 1 18:44:35 2003 @@ -1,7 +1,7 @@ /* * drivers/s390/cio/chsc.c * S/390 common I/O routines -- channel subsystem call - * $Revision: 1.69 $ + * $Revision: 1.73 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -322,10 +322,6 @@ sprintf(dbf_txt, "chpr%x", chpid); CIO_TRACE_EVENT(2, dbf_txt); - /* - * TODO: the chpid may be not the chpid with the link incident, - * but the chpid the report came in through. How to handle??? - */ clear_bit(chpid, chpids); if (!test_and_clear_bit(chpid, chpids_known)) return; /* we didn't know the chpid anyway */ @@ -469,9 +465,40 @@ free_page((unsigned long)page); } +static int +__get_chpid_from_lir(void *data) +{ + struct lir { + u8 iq; + u8 ic; + u16 sci; + /* incident-node descriptor */ + u32 indesc[28]; + /* attached-node descriptor */ + u32 andesc[28]; + /* incident-specific information */ + u32 isinfo[28]; + } *lir; + + lir = (struct lir*) data; + if (!(lir->iq&0x80)) + /* NULL link incident record */ + return -EINVAL; + if (!(lir->indesc[0]&0xc0000000)) + /* node descriptor not valid */ + return -EINVAL; + if (!(lir->indesc[0]&0x10000000)) + /* don't handle device-type nodes - FIXME */ + return -EINVAL; + /* Byte 3 contains the chpid. Could also be CTCA, but we don't care */ + + return (u16) (lir->indesc[0]&0x000000ff); +} + static void do_process_crw(void *ignore) { + int chpid; struct { struct chsc_header request; u32 reserved1; @@ -487,10 +514,8 @@ u16 rsid; /* reporting source id */ u32 reserved5; u32 reserved6; - u32 ccdf; /* content-code dependent field */ - u32 reserved7; - u32 reserved8; - u32 reserved9; + u32 ccdf[96]; /* content-code dependent field */ + /* ccdf has to be big enough for a link-incident record */ } *sei_area; /* @@ -560,9 +585,14 @@ case 1: /* link incident*/ CIO_CRW_EVENT(4, "chsc_process_crw: " "channel subsystem reports link incident," - " source is chpid %x\n", sei_area->rsid); - - s390_set_chpid_offline(sei_area->rsid); + " reporting source is chpid %x\n", + sei_area->rsid); + chpid = __get_chpid_from_lir(sei_area->ccdf); + if (chpid < 0) + CIO_CRW_EVENT(4, "%s: Invalid LIR, skipping\n", + __FUNCTION__); + else + s390_set_chpid_offline(chpid); break; case 2: /* i/o resource accessibiliy */ diff -Nru a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h --- a/drivers/s390/cio/css.h Tue Jul 1 18:44:39 2003 +++ b/drivers/s390/cio/css.h Tue Jul 1 18:44:39 2003 @@ -72,9 +72,9 @@ struct { unsigned int fast:1; /* post with "channel end" */ unsigned int repall:1; /* report every interrupt status */ + unsigned int pgroup:1; /* do path grouping */ } __attribute__ ((packed)) options; struct { - unsigned int pgid_supp:1; /* "path group ID" supported */ unsigned int pgid_single:1; /* use single path for Set PGID */ unsigned int esid:1; /* Ext. SenseID supported by HW */ unsigned int dosense:1; /* delayed SENSE required */ diff -Nru a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c --- a/drivers/s390/cio/device.c Tue Jul 1 18:44:36 2003 +++ b/drivers/s390/cio/device.c Tue Jul 1 18:44:36 2003 @@ -1,7 +1,7 @@ /* * drivers/s390/cio/device.c * bus driver for ccw devices - * $Revision: 1.54 $ + * $Revision: 1.58 $ * * Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -298,20 +298,19 @@ online_store (struct device *dev, const char *buf, size_t count) { struct ccw_device *cdev = to_ccwdev(dev); - unsigned int value; + int i; + char *tmp; if (!cdev->drv) return count; - sscanf(buf, "%u", &value); - - if (value) { - if (cdev->drv->set_online) - ccw_device_set_online(cdev); - } else { - if (cdev->drv->set_offline) - ccw_device_set_offline(cdev); - } + i = simple_strtoul(buf, &tmp, 16); + if (i == 1 && cdev->drv->set_online) + ccw_device_set_online(cdev); + else if (i == 0 && cdev->drv->set_offline) + ccw_device_set_offline(cdev); + else + return -EINVAL; return count; } @@ -405,11 +404,14 @@ * This allows to trigger an unconditional reserve ccw to eckd dasds * (if the device is something else, there should be no problems more than * a command reject; we don't have any means of finding out the device's - * type if it was boxed at ipl/attach). + * type if it was boxed at ipl/attach for older devices and under VM). */ void -ccw_device_add_stlck(struct ccw_device *cdev) +ccw_device_add_stlck(void *data) { + struct ccw_device *cdev; + + cdev = (struct ccw_device *)data; device_create_file(&cdev->dev, &dev_attr_steal_lock); } @@ -470,6 +472,8 @@ if (ret) printk(KERN_WARNING "%s: could not add attributes to %04x\n", __func__, sch->irq); + if (cdev->private->state == DEV_STATE_BOXED) + device_create_file(&cdev->dev, &dev_attr_steal_lock); out: put_device(&sch->dev); } @@ -493,6 +497,8 @@ if (cdev->dev.release) cdev->dev.release(&cdev->dev); break; + case DEV_STATE_BOXED: + /* Device did not respond in time. */ case DEV_STATE_OFFLINE: /* * We can't register the device in interrupt context so @@ -501,9 +507,6 @@ INIT_WORK(&cdev->private->kick_work, io_subchannel_register, (void *) cdev); queue_work(ccw_device_work, &cdev->private->kick_work); - break; - case DEV_STATE_BOXED: - /* Device did not respond in time. */ break; } if (atomic_dec_and_test(&ccw_device_init_count)) diff -Nru a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h --- a/drivers/s390/cio/device.h Tue Jul 1 18:44:37 2003 +++ b/drivers/s390/cio/device.h Tue Jul 1 18:44:37 2003 @@ -95,7 +95,7 @@ void ccw_device_call_handler(struct ccw_device *); -void ccw_device_add_stlck(struct ccw_device *); +void ccw_device_add_stlck(void *); int ccw_device_stlck(struct ccw_device *); /* qdio needs this. */ diff -Nru a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c --- a/drivers/s390/cio/device_fsm.c Tue Jul 1 18:44:35 2003 +++ b/drivers/s390/cio/device_fsm.c Tue Jul 1 18:44:35 2003 @@ -132,11 +132,11 @@ CIO_DEBUG(KERN_WARNING, 2, "SenseID : boxed device %04X on subchannel %04X\n", sch->schib.pmcw.dev, sch->irq); - ccw_device_add_stlck(cdev); break; } io_subchannel_recog_done(cdev); - wake_up(&cdev->private->wait_q); + if (state != DEV_STATE_NOT_OPER) + wake_up(&cdev->private->wait_q); } /* @@ -159,22 +159,65 @@ } /* + * Finished with online/offline processing. + */ +static void +ccw_device_done(struct ccw_device *cdev, int state) +{ + struct subchannel *sch; + + sch = to_subchannel(cdev->dev.parent); + + if (state != DEV_STATE_ONLINE) + cio_disable_subchannel(sch); + + /* Reset device status. */ + memset(&cdev->private->irb, 0, sizeof(struct irb)); + + cdev->private->state = state; + + + if (state == DEV_STATE_BOXED) { + CIO_DEBUG(KERN_WARNING, 2, + "Boxed device %04X on subchannel %04X\n", + sch->schib.pmcw.dev, sch->irq); + INIT_WORK(&cdev->private->kick_work, + ccw_device_add_stlck, (void *) cdev); + queue_work(ccw_device_work, &cdev->private->kick_work); + } + + wake_up(&cdev->private->wait_q); + + if (state != DEV_STATE_ONLINE) + put_device (&cdev->dev); +} + +/* * Function called from device_pgid.c after sense path ground has completed. */ void ccw_device_sense_pgid_done(struct ccw_device *cdev, int err) { + struct subchannel *sch; + + sch = to_subchannel(cdev->dev.parent); switch (err) { case 0: - cdev->private->state = DEV_STATE_SENSE_ID; - ccw_device_sense_id_start(cdev); + /* Start Path Group verification. */ + sch->vpm = 0; /* Start with no path groups set. */ + cdev->private->state = DEV_STATE_VERIFY; + ccw_device_verify_start(cdev); break; case -ETIME: /* Sense path group id stopped by timeout. */ case -EUSERS: /* device is reserved for someone else. */ - ccw_device_recog_done(cdev, DEV_STATE_BOXED); + ccw_device_done(cdev, DEV_STATE_BOXED); + break; + case -EOPNOTSUPP: /* path grouping not supported, just set online. */ + cdev->private->options.pgroup = 0; + ccw_device_done(cdev, DEV_STATE_ONLINE); break; default: - ccw_device_recog_done(cdev, DEV_STATE_NOT_OPER); + ccw_device_done(cdev, DEV_STATE_NOT_OPER); break; } } @@ -198,11 +241,15 @@ ccw_device_set_timeout(cdev, 60*HZ); /* - * First thing we should do is a sensePGID in order to find out how - * we can proceed with the recognition process. + * We used to start here with a sense pgid to find out whether a device + * is locked by someone else. Unfortunately, the sense pgid command + * code has other meanings on devices predating the path grouping + * algorithm, so we start with sense id and box the device after an + * timeout (or if sense pgid during path verification detects the device + * is locked, as may happen on newer devices). */ - cdev->private->state = DEV_STATE_SENSE_PGID; - ccw_device_sense_pgid_start(cdev); + cdev->private->state = DEV_STATE_SENSE_ID; + ccw_device_sense_id_start(cdev); return 0; } @@ -218,29 +265,6 @@ ccw_device_set_timeout(cdev, 3*HZ); } -/* - * Finished with online/offline processing. - */ -static void -ccw_device_done(struct ccw_device *cdev, int state) -{ - struct subchannel *sch; - - sch = to_subchannel(cdev->dev.parent); - - if (state != DEV_STATE_ONLINE) - cio_disable_subchannel(sch); - - /* Reset device status. */ - memset(&cdev->private->irb, 0, sizeof(struct irb)); - - cdev->private->state = state; - - wake_up(&cdev->private->wait_q); - - if (state != DEV_STATE_ONLINE) - put_device (&cdev->dev); -} void ccw_device_verify_done(struct ccw_device *cdev, int err) @@ -276,16 +300,15 @@ dev_fsm_event(cdev, DEV_EVENT_NOTOPER); return -ENODEV; } - /* Is Set Path Group supported? */ - if (!cdev->private->flags.pgid_supp) { + /* Do we want to do path grouping? */ + if (!cdev->private->options.pgroup) { /* No, set state online immediately. */ ccw_device_done(cdev, DEV_STATE_ONLINE); return 0; } - /* Start Path Group verification. */ - sch->vpm = 0; /* Start with no path groups set. */ - cdev->private->state = DEV_STATE_VERIFY; - ccw_device_verify_start(cdev); + /* Do a SensePGID first. */ + cdev->private->state = DEV_STATE_SENSE_PGID; + ccw_device_sense_pgid_start(cdev); return 0; } @@ -321,8 +344,8 @@ } if (sch->schib.scsw.actl != 0) return -EBUSY; - /* Is Set Path Group supported? */ - if (!cdev->private->flags.pgid_supp) { + /* Are we doing path grouping? */ + if (!cdev->private->options.pgroup) { /* No, set state offline immediately. */ ccw_device_done(cdev, DEV_STATE_OFFLINE); return 0; @@ -643,9 +666,9 @@ [DEV_EVENT_VERIFY] ccw_device_nop, }, [DEV_STATE_SENSE_PGID] { - [DEV_EVENT_NOTOPER] ccw_device_recog_notoper, + [DEV_EVENT_NOTOPER] ccw_device_online_notoper, [DEV_EVENT_INTERRUPT] ccw_device_sense_pgid_irq, - [DEV_EVENT_TIMEOUT] ccw_device_recog_timeout, + [DEV_EVENT_TIMEOUT] ccw_device_onoff_timeout, [DEV_EVENT_VERIFY] ccw_device_nop, }, [DEV_STATE_SENSE_ID] { diff -Nru a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c --- a/drivers/s390/cio/device_ops.c Tue Jul 1 18:44:36 2003 +++ b/drivers/s390/cio/device_ops.c Tue Jul 1 18:44:36 2003 @@ -37,6 +37,7 @@ return -EINVAL; cdev->private->options.fast = (flags & CCWDEV_EARLY_NOTIFICATION) != 0; cdev->private->options.repall = (flags & CCWDEV_REPORT_ALL) != 0; + cdev->private->options.pgroup = (flags & CCWDEV_DO_PATHGROUP) != 0; return 0; } diff -Nru a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c --- a/drivers/s390/cio/device_pgid.c Tue Jul 1 18:44:35 2003 +++ b/drivers/s390/cio/device_pgid.c Tue Jul 1 18:44:35 2003 @@ -84,7 +84,6 @@ cdev->private->state = DEV_STATE_SENSE_PGID; cdev->private->imask = 0x80; cdev->private->iretry = 5; - cdev->private->flags.pgid_supp = 0; memset (&cdev->private->pgid, 0, sizeof (struct pgid)); ret = __ccw_device_sense_pgid_start(cdev); if (ret) @@ -165,14 +164,13 @@ switch (__ccw_device_check_sense_pgid(cdev)) { /* 0, -ETIME, -EOPNOTSUPP, -EAGAIN, -EACCES or -EUSERS */ case 0: /* Sense Path Group ID successful. */ - cdev->private->flags.pgid_supp = 1; opm = sch->schib.pmcw.pim & sch->schib.pmcw.pam & sch->schib.pmcw.pom; for (i=0;i<8;i++) { if (opm == (0x80 << i)) { /* Don't group single path devices. */ - cdev->private->flags.pgid_supp = 0; + cdev->private->options.pgroup = 0; break; } } @@ -181,7 +179,7 @@ sizeof(struct pgid)); /* fall through. */ case -EOPNOTSUPP: /* Sense Path Group ID not supported */ - ccw_device_sense_pgid_done(cdev, 0); + ccw_device_sense_pgid_done(cdev, -EOPNOTSUPP); break; case -ETIME: /* Sense path group id stopped by timeout. */ ccw_device_sense_pgid_done(cdev, -ETIME); diff -Nru a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c --- a/drivers/s390/cio/qdio.c Tue Jul 1 18:44:36 2003 +++ b/drivers/s390/cio/qdio.c Tue Jul 1 18:44:36 2003 @@ -55,7 +55,7 @@ #include "ioasm.h" #include "chsc.h" -#define VERSION_QDIO_C "$Revision: 1.49 $" +#define VERSION_QDIO_C "$Revision: 1.51 $" /****************** MODULE PARAMETER VARIABLES ********************/ MODULE_AUTHOR("Utz Bacher "); @@ -74,6 +74,8 @@ static struct qdio_perf_stats perf_stats; #endif /* QDIO_PERFORMANCE_STATS */ +static int hydra_thinints; + static int indicator_used[INDICATORS_PER_CACHELINE]; static __u32 * volatile indicators; static __u32 volatile spare_indicator; @@ -88,12 +90,12 @@ #endif /* QDIO_DBF_LIKE_HELL */ /* iQDIO stuff: */ -static volatile struct qdio_q *iq_list=NULL; /* volatile as it could change - during a while loop */ -static spinlock_t iq_list_lock=SPIN_LOCK_UNLOCKED; +static volatile struct qdio_q *tiq_list=NULL; /* volatile as it could change + during a while loop */ +static spinlock_t ttiq_list_lock=SPIN_LOCK_UNLOCKED; static int register_thinint_result; -static void iqdio_tl(unsigned long); -static DECLARE_TASKLET(iqdio_tasklet,iqdio_tl,0); +static void tiqdio_tl(unsigned long); +static DECLARE_TASKLET(tiqdio_tasklet,tiqdio_tl,0); /* not a macro, as one of the arguments is atomic_read */ static inline int @@ -173,7 +175,7 @@ /* * unfortunately, we can't just xchg the values; in do_QDIO we want to reserve * the q in any case, so that we'll not be interrupted when we are in - * qdio_mark_iq... shouldn't have a really bad impact, as reserving almost + * qdio_mark_tiq... shouldn't have a really bad impact, as reserving almost * ever works (last famous words) */ static inline int @@ -195,7 +197,8 @@ } static inline int -qdio_siga_sync(struct qdio_q *q) +qdio_siga_sync(struct qdio_q *q, unsigned int gpr2, + unsigned int gpr3) { int cc; @@ -206,17 +209,21 @@ perf_stats.siga_syncs++; #endif /* QDIO_PERFORMANCE_STATS */ - if (q->is_input_q) - cc = do_siga_sync(q->irq, 0, q->mask); - else - cc = do_siga_sync(q->irq, q->mask, 0); - + cc = do_siga_sync(q->irq, gpr2, gpr3); if (cc) QDIO_DBF_HEX3(0,trace,&cc,sizeof(int*)); return cc; } +static inline int +qdio_siga_sync_q(struct qdio_q *q) +{ + if (q->is_input_q) + return qdio_siga_sync(q, 0, q->mask); + return qdio_siga_sync(q, q->mask, 0); +} + /* * returns QDIO_SIGA_ERROR_ACCESS_EXCEPTION as cc, when SIGA returns * an access exception @@ -304,7 +311,7 @@ } static inline volatile void -iqdio_clear_summary_bit(__u32 *location) +tiqdio_clear_summary_bit(__u32 *location) { QDIO_DBF_TEXT5(0,trace,"clrsummb"); QDIO_DBF_HEX5(0,trace,&location,sizeof(void*)); @@ -313,7 +320,7 @@ } static inline volatile void -iqdio_set_summary_bit(__u32 *location) +tiqdio_set_summary_bit(__u32 *location) { QDIO_DBF_TEXT5(0,trace,"setsummb"); QDIO_DBF_HEX5(0,trace,&location,sizeof(void*)); @@ -322,21 +329,21 @@ } static inline void -iqdio_sched_tl(void) +tiqdio_sched_tl(void) { - tasklet_hi_schedule(&iqdio_tasklet); + tasklet_hi_schedule(&tiqdio_tasklet); } static inline void -qdio_mark_iq(struct qdio_q *q) +qdio_mark_tiq(struct qdio_q *q) { unsigned long flags; QDIO_DBF_TEXT4(0,trace,"mark iq"); QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); - spin_lock_irqsave(&iq_list_lock,flags); - if (atomic_read(&q->is_in_shutdown)) + spin_lock_irqsave(&ttiq_list_lock,flags); + if (unlikely(atomic_read(&q->is_in_shutdown))) goto out_unlock; if (!q->is_input_q) @@ -345,23 +352,23 @@ if ((q->list_prev) || (q->list_next)) goto out_unlock; - if (!iq_list) { - iq_list=q; + if (!tiq_list) { + tiq_list=q; q->list_prev=q; q->list_next=q; } else { - q->list_next=iq_list; - q->list_prev=iq_list->list_prev; - iq_list->list_prev->list_next=q; - iq_list->list_prev=q; + q->list_next=tiq_list; + q->list_prev=tiq_list->list_prev; + tiq_list->list_prev->list_next=q; + tiq_list->list_prev=q; } - spin_unlock_irqrestore(&iq_list_lock,flags); + spin_unlock_irqrestore(&ttiq_list_lock,flags); - iqdio_set_summary_bit((__u32*)q->dev_st_chg_ind); - iqdio_sched_tl(); + tiqdio_set_summary_bit((__u32*)q->dev_st_chg_ind); + tiqdio_sched_tl(); return; out_unlock: - spin_unlock_irqrestore(&iq_list_lock,flags); + spin_unlock_irqrestore(&ttiq_list_lock,flags); return; } @@ -371,7 +378,7 @@ QDIO_DBF_TEXT4(0,trace,"mark q"); QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); - if (atomic_read(&q->is_in_shutdown)) + if (unlikely(atomic_read(&q->is_in_shutdown))) return; tasklet_schedule(&q->tasklet); @@ -410,7 +417,7 @@ * checking for PRIMED state */ if (q->is_iqdio_q) - iqdio_set_summary_bit((__u32*)q->dev_st_chg_ind); + tiqdio_set_summary_bit((__u32*)q->dev_st_chg_ind); return 0; #else /* QDIO_USE_PROCESSING_STATE */ @@ -434,27 +441,27 @@ if ((!q->list_prev)||(!q->list_next)) return; - if ((q->is_iqdio_q)&&(q->is_input_q)) { + if ((q->is_thinint_q)&&(q->is_input_q)) { /* iQDIO */ - spin_lock_irqsave(&iq_list_lock,flags); + spin_lock_irqsave(&ttiq_list_lock,flags); if (q->list_next==q) { /* q was the only interesting q */ - iq_list=NULL; + tiq_list=NULL; q->list_next=NULL; q->list_prev=NULL; } else { q->list_next->list_prev=q->list_prev; q->list_prev->list_next=q->list_next; - iq_list=q->list_next; + tiq_list=q->list_next; q->list_next=NULL; q->list_prev=NULL; } - spin_unlock_irqrestore(&iq_list_lock,flags); + spin_unlock_irqrestore(&ttiq_list_lock,flags); } } static inline unsigned long -iqdio_clear_global_summary(void) +tiqdio_clear_global_summary(void) { unsigned long time; @@ -467,6 +474,223 @@ return time; } + +/************************* OUTBOUND ROUTINES *******************************/ + +inline static int +qdio_get_outbound_buffer_frontier(struct qdio_q *q) +{ + int f,f_mod_no; + volatile char *slsb; + int first_not_to_check; + char dbf_text[15]; + + QDIO_DBF_TEXT4(0,trace,"getobfro"); + QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); + + slsb=&q->slsb.acc.val[0]; + f_mod_no=f=q->first_to_check; + /* + * f points to already processed elements, so f+no_used is correct... + * ... but: we don't check 128 buffers, as otherwise + * qdio_has_outbound_q_moved would return 0 + */ + first_not_to_check=f+qdio_min(atomic_read(&q->number_of_buffers_used), + (QDIO_MAX_BUFFERS_PER_Q-1)); + + if ((!q->is_iqdio_q)&&(!q->hydra_gives_outbound_pcis)) + SYNC_MEMORY; + +check_next: + if (f==first_not_to_check) + goto out; + + switch(slsb[f_mod_no]) { + + /* the hydra has not fetched the output yet */ + case SLSB_CU_OUTPUT_PRIMED: + QDIO_DBF_TEXT5(0,trace,"outpprim"); + break; + + /* the hydra got it */ + case SLSB_P_OUTPUT_EMPTY: + atomic_dec(&q->number_of_buffers_used); + f++; + f_mod_no=f&(QDIO_MAX_BUFFERS_PER_Q-1); + QDIO_DBF_TEXT5(0,trace,"outpempt"); + goto check_next; + + case SLSB_P_OUTPUT_ERROR: + QDIO_DBF_TEXT3(0,trace,"outperr"); + sprintf(dbf_text,"%x-%x-%x",f_mod_no, + q->sbal[f_mod_no]->element[14].sbalf.value, + q->sbal[f_mod_no]->element[15].sbalf.value); + QDIO_DBF_TEXT3(1,trace,dbf_text); + QDIO_DBF_HEX2(1,sbal,q->sbal[f_mod_no],256); + + /* kind of process the buffer */ + set_slsb(&q->slsb.acc.val[f_mod_no], SLSB_P_OUTPUT_NOT_INIT); + + /* + * we increment the frontier, as this buffer + * was processed obviously + */ + atomic_dec(&q->number_of_buffers_used); + f_mod_no=(f_mod_no+1)&(QDIO_MAX_BUFFERS_PER_Q-1); + + if (q->qdio_error) + q->error_status_flags|= + QDIO_STATUS_MORE_THAN_ONE_QDIO_ERROR; + q->qdio_error=SLSB_P_OUTPUT_ERROR; + q->error_status_flags|=QDIO_STATUS_LOOK_FOR_ERROR; + + break; + + /* no new buffers */ + default: + QDIO_DBF_TEXT5(0,trace,"outpni"); + } +out: + return (q->first_to_check=f_mod_no); +} + +/* all buffers are processed */ +inline static int +qdio_is_outbound_q_done(struct qdio_q *q) +{ + int no_used; + char dbf_text[15]; + + no_used=atomic_read(&q->number_of_buffers_used); + + if (no_used) { + sprintf(dbf_text,"oqisnt%02x",no_used); + QDIO_DBF_TEXT4(0,trace,dbf_text); + } else { + QDIO_DBF_TEXT4(0,trace,"oqisdone"); + } + QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); + return (no_used==0); +} + +inline static int +qdio_has_outbound_q_moved(struct qdio_q *q) +{ + int i; + + i=qdio_get_outbound_buffer_frontier(q); + + if ( (i!=GET_SAVED_FRONTIER(q)) || + (q->error_status_flags&QDIO_STATUS_LOOK_FOR_ERROR) ) { + SAVE_FRONTIER(q,i); + SAVE_TIMESTAMP(q); + QDIO_DBF_TEXT4(0,trace,"oqhasmvd"); + QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); + return 1; + } else { + QDIO_DBF_TEXT4(0,trace,"oqhsntmv"); + QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); + return 0; + } +} + +inline static void +qdio_kick_outbound_q(struct qdio_q *q) +{ + int result; + + QDIO_DBF_TEXT4(0,trace,"kickoutq"); + QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); + + if (!q->siga_out) + return; + + result=qdio_siga_output(q); + + if (!result) + return; + + if (q->siga_error) + q->error_status_flags|=QDIO_STATUS_MORE_THAN_ONE_SIGA_ERROR; + q->error_status_flags |= QDIO_STATUS_LOOK_FOR_ERROR; + q->siga_error=result; +} + +inline static void +qdio_kick_outbound_handler(struct qdio_q *q) +{ + int start, end, real_end, count; + char dbf_text[15]; + + start = q->first_element_to_kick; + /* last_move_ftc was just updated */ + real_end = GET_SAVED_FRONTIER(q); + end = (real_end+QDIO_MAX_BUFFERS_PER_Q-1)& + (QDIO_MAX_BUFFERS_PER_Q-1); + count = (end+QDIO_MAX_BUFFERS_PER_Q+1-start)& + (QDIO_MAX_BUFFERS_PER_Q-1); + + QDIO_DBF_TEXT4(0,trace,"kickouth"); + QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); + + sprintf(dbf_text,"s=%2xc=%2x",start,count); + QDIO_DBF_TEXT4(0,trace,dbf_text); + + if (q->state==QDIO_IRQ_STATE_ACTIVE) + q->handler(q->cdev,QDIO_STATUS_OUTBOUND_INT| + q->error_status_flags, + q->qdio_error,q->siga_error,q->q_no,start,count, + q->int_parm); + + /* for the next time: */ + q->first_element_to_kick=real_end; + q->qdio_error=0; + q->siga_error=0; + q->error_status_flags=0; +} + +static void +qdio_outbound_processing(struct qdio_q *q) +{ + QDIO_DBF_TEXT4(0,trace,"qoutproc"); + QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); + + if (unlikely(qdio_reserve_q(q))) { + qdio_release_q(q); +#ifdef QDIO_PERFORMANCE_STATS + o_p_c++; +#endif /* QDIO_PERFORMANCE_STATS */ + /* as we're sissies, we'll check next time */ + if (likely(!atomic_read(&q->is_in_shutdown))) { + qdio_mark_q(q); + QDIO_DBF_TEXT4(0,trace,"busy,agn"); + } + return; + } +#ifdef QDIO_PERFORMANCE_STATS + o_p_nc++; + perf_stats.tl_runs++; +#endif /* QDIO_PERFORMANCE_STATS */ + + if (qdio_has_outbound_q_moved(q)) + qdio_kick_outbound_handler(q); + + if (q->is_iqdio_q) { + /* + * for asynchronous queues, we better check, if the fill + * level is too high + */ + if (atomic_read(&q->number_of_buffers_used)> + IQDIO_FILL_LEVEL_TO_POLL) + qdio_mark_q(q); + + } else if (!q->hydra_gives_outbound_pcis) + if (!qdio_is_outbound_q_done(q)) + qdio_mark_q(q); + + qdio_release_q(q); +} + /************************* INBOUND ROUTINES *******************************/ @@ -650,8 +874,8 @@ * we will return 0 below, as there is nothing to do, except scheduling * ourselves for the next time. */ - iqdio_set_summary_bit((__u32*)q->dev_st_chg_ind); - iqdio_sched_tl(); + tiqdio_set_summary_bit((__u32*)q->dev_st_chg_ind); + tiqdio_sched_tl(); return 0; } @@ -725,14 +949,15 @@ count=0; while (1) { count++; - if (i==end) break; + if (i==end) + break; i=(i+1)&(QDIO_MAX_BUFFERS_PER_Q-1); } sprintf(dbf_text,"s=%2xc=%2x",start,count); QDIO_DBF_TEXT4(0,trace,dbf_text); - if (q->state==QDIO_IRQ_STATE_ACTIVE) + if (likely(q->state==QDIO_IRQ_STATE_ACTIVE)) q->handler(q->cdev, QDIO_STATUS_INBOUND_INT|q->error_status_flags, q->qdio_error,q->siga_error,q->q_no,start,count, @@ -751,8 +976,12 @@ } static inline void -iqdio_inbound_processing(struct qdio_q *q) +tiqdio_inbound_processing(struct qdio_q *q) { + struct qdio_irq *irq_ptr; + struct qdio_q *oq; + int i; + QDIO_DBF_TEXT4(0,trace,"iqinproc"); QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); @@ -761,7 +990,7 @@ * interrupt ourselves and call qdio_unmark_q, as is_in_shutdown might * be set */ - if (qdio_reserve_q(q)) { + if (unlikely(qdio_reserve_q(q))) { qdio_release_q(q); #ifdef QDIO_PERFORMANCE_STATS ii_p_c++; @@ -770,13 +999,13 @@ * as we might just be about to stop polling, we make * sure that we check again at least once more */ - iqdio_sched_tl(); + tiqdio_sched_tl(); return; } #ifdef QDIO_PERFORMANCE_STATS ii_p_nc++; #endif /* QDIO_PERFORMANCE_STATS */ - if (atomic_read(&q->is_in_shutdown)) { + if (unlikely(atomic_read(&q->is_in_shutdown))) { qdio_unmark_q(q); goto out; } @@ -784,10 +1013,34 @@ if (!(*(q->dev_st_chg_ind))) goto out; - iqdio_clear_summary_bit((__u32*)q->dev_st_chg_ind); + tiqdio_clear_summary_bit((__u32*)q->dev_st_chg_ind); - if (!q->siga_sync_done_on_thinints) - SYNC_MEMORY; + if (q->hydra_gives_outbound_pcis) { + if (!q->siga_sync_done_on_thinints) { + SYNC_MEMORY_ALL; + } else if ((!q->siga_sync_done_on_outb_tis)&& + (q->hydra_gives_outbound_pcis)) { + SYNC_MEMORY_ALL_OUTB; + } + } else { + SYNC_MEMORY; + } + /* + * maybe we have to do work on our outbound queues... at least + * we have to check Hydra outbound-int-capable thinint-capable + * queues + */ + if (q->hydra_gives_outbound_pcis) { + irq_ptr = (struct qdio_irq*)q->irq_ptr; + for (i=0;ino_output_qs;i++) { + oq = irq_ptr->output_qs[i]; +#ifdef QDIO_PERFORMANCE_STATS + perf_stats.tl_runs--; +#endif /* QDIO_PERFORMANCE_STATS */ + if (!qdio_is_outbound_q_done(oq)) + qdio_outbound_processing(oq); + } + } if (!qdio_has_inbound_q_moved(q)) goto out; @@ -799,8 +1052,8 @@ * we set the flags to get into the stuff next time, * see also comment in qdio_stop_polling */ - iqdio_set_summary_bit((__u32*)q->dev_st_chg_ind); - iqdio_sched_tl(); + tiqdio_set_summary_bit((__u32*)q->dev_st_chg_ind); + tiqdio_sched_tl(); } out: qdio_release_q(q); @@ -814,13 +1067,13 @@ QDIO_DBF_TEXT4(0,trace,"qinproc"); QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); - if (qdio_reserve_q(q)) { + if (unlikely(qdio_reserve_q(q))) { qdio_release_q(q); #ifdef QDIO_PERFORMANCE_STATS i_p_c++; #endif /* QDIO_PERFORMANCE_STATS */ /* as we're sissies, we'll check next time */ - if (!atomic_read(&q->is_in_shutdown)) { + if (likely(!atomic_read(&q->is_in_shutdown))) { qdio_mark_q(q); QDIO_DBF_TEXT4(0,trace,"busy,agn"); } @@ -849,229 +1102,14 @@ qdio_release_q(q); } -/************************* OUTBOUND ROUTINES *******************************/ - -inline static int -qdio_get_outbound_buffer_frontier(struct qdio_q *q) -{ - int f,f_mod_no; - volatile char *slsb; - int first_not_to_check; - char dbf_text[15]; - - QDIO_DBF_TEXT4(0,trace,"getobfro"); - QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); - - slsb=&q->slsb.acc.val[0]; - f_mod_no=f=q->first_to_check; - /* - * f points to already processed elements, so f+no_used is correct... - * ... but: we don't check 128 buffers, as otherwise - * qdio_has_outbound_q_moved would return 0 - */ - first_not_to_check=f+qdio_min(atomic_read(&q->number_of_buffers_used), - (QDIO_MAX_BUFFERS_PER_Q-1)); - - if ((!q->is_iqdio_q)&&(!q->hydra_gives_outbound_pcis)) - SYNC_MEMORY; - -check_next: - if (f==first_not_to_check) - goto out; - - switch(slsb[f_mod_no]) { - - /* the hydra has not fetched the output yet */ - case SLSB_CU_OUTPUT_PRIMED: - QDIO_DBF_TEXT5(0,trace,"outpprim"); - break; - - /* the hydra got it */ - case SLSB_P_OUTPUT_EMPTY: - atomic_dec(&q->number_of_buffers_used); - f++; - f_mod_no=f&(QDIO_MAX_BUFFERS_PER_Q-1); - QDIO_DBF_TEXT5(0,trace,"outpempt"); - goto check_next; - - case SLSB_P_OUTPUT_ERROR: - QDIO_DBF_TEXT3(0,trace,"outperr"); - sprintf(dbf_text,"%x-%x-%x",f_mod_no, - q->sbal[f_mod_no]->element[14].sbalf.value, - q->sbal[f_mod_no]->element[15].sbalf.value); - QDIO_DBF_TEXT3(1,trace,dbf_text); - QDIO_DBF_HEX2(1,sbal,q->sbal[f_mod_no],256); - - /* kind of process the buffer */ - set_slsb(&q->slsb.acc.val[f_mod_no], SLSB_P_OUTPUT_NOT_INIT); - - /* - * we increment the frontier, as this buffer - * was processed obviously - */ - atomic_dec(&q->number_of_buffers_used); - f_mod_no=(f_mod_no+1)&(QDIO_MAX_BUFFERS_PER_Q-1); - - if (q->qdio_error) - q->error_status_flags|= - QDIO_STATUS_MORE_THAN_ONE_QDIO_ERROR; - q->qdio_error=SLSB_P_OUTPUT_ERROR; - q->error_status_flags|=QDIO_STATUS_LOOK_FOR_ERROR; - - break; - - /* no new buffers */ - default: - QDIO_DBF_TEXT5(0,trace,"outpni"); - } -out: - return (q->first_to_check=f_mod_no); -} - -/* all buffers are processed */ -inline static int -qdio_is_outbound_q_done(struct qdio_q *q) -{ - int no_used; - char dbf_text[15]; - - no_used=atomic_read(&q->number_of_buffers_used); - - if (no_used) { - sprintf(dbf_text,"oqisnt%02x",no_used); - QDIO_DBF_TEXT4(0,trace,dbf_text); - } else { - QDIO_DBF_TEXT4(0,trace,"oqisdone"); - } - QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); - return (no_used==0); -} - -inline static int -qdio_has_outbound_q_moved(struct qdio_q *q) -{ - int i; - - i=qdio_get_outbound_buffer_frontier(q); - - if ( (i!=GET_SAVED_FRONTIER(q)) || - (q->error_status_flags&QDIO_STATUS_LOOK_FOR_ERROR) ) { - SAVE_FRONTIER(q,i); - SAVE_TIMESTAMP(q); - QDIO_DBF_TEXT4(0,trace,"oqhasmvd"); - QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); - return 1; - } else { - QDIO_DBF_TEXT4(0,trace,"oqhsntmv"); - QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); - return 0; - } -} - -inline static void -qdio_kick_outbound_q(struct qdio_q *q) -{ - int result; - - QDIO_DBF_TEXT4(0,trace,"kickoutq"); - QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); - - if (!q->siga_out) - return; - - result=qdio_siga_output(q); - - if (!result) - return; - - if (q->siga_error) - q->error_status_flags|=QDIO_STATUS_MORE_THAN_ONE_SIGA_ERROR; - q->error_status_flags |= QDIO_STATUS_LOOK_FOR_ERROR; - q->siga_error=result; -} - -inline static void -qdio_kick_outbound_handler(struct qdio_q *q) -{ - int start, end, real_end, count; - char dbf_text[15]; - - start = q->first_element_to_kick; - /* last_move_ftc was just updated */ - real_end = GET_SAVED_FRONTIER(q); - end = (real_end+QDIO_MAX_BUFFERS_PER_Q-1)& - (QDIO_MAX_BUFFERS_PER_Q-1); - count = (end+QDIO_MAX_BUFFERS_PER_Q+1-start)& - (QDIO_MAX_BUFFERS_PER_Q-1); - - QDIO_DBF_TEXT4(0,trace,"kickouth"); - QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); - - sprintf(dbf_text,"s=%2xc=%2x",start,count); - QDIO_DBF_TEXT4(0,trace,dbf_text); - - if (q->state==QDIO_IRQ_STATE_ACTIVE) - q->handler(q->cdev,QDIO_STATUS_OUTBOUND_INT| - q->error_status_flags, - q->qdio_error,q->siga_error,q->q_no,start,count, - q->int_parm); - - /* for the next time: */ - q->first_element_to_kick=real_end; - q->qdio_error=0; - q->siga_error=0; - q->error_status_flags=0; -} - -static void qdio_outbound_processing(struct qdio_q *q) -{ - QDIO_DBF_TEXT4(0,trace,"qoutproc"); - QDIO_DBF_HEX4(0,trace,&q,sizeof(void*)); - - if (qdio_reserve_q(q)) { - qdio_release_q(q); -#ifdef QDIO_PERFORMANCE_STATS - o_p_c++; -#endif /* QDIO_PERFORMANCE_STATS */ - /* as we're sissies, we'll check next time */ - if (!atomic_read(&q->is_in_shutdown)) { - qdio_mark_q(q); - QDIO_DBF_TEXT4(0,trace,"busy,agn"); - } - return; - } -#ifdef QDIO_PERFORMANCE_STATS - o_p_nc++; - perf_stats.tl_runs++; -#endif /* QDIO_PERFORMANCE_STATS */ - - if (qdio_has_outbound_q_moved(q)) - qdio_kick_outbound_handler(q); - - if (q->is_iqdio_q) { - /* - * for asynchronous queues, we better check, if the fill - * level is too high - */ - if (atomic_read(&q->number_of_buffers_used)> - IQDIO_FILL_LEVEL_TO_POLL) - qdio_mark_q(q); - - } else if (!q->hydra_gives_outbound_pcis) - if (!qdio_is_outbound_q_done(q)) - qdio_mark_q(q); - - qdio_release_q(q); -} - /************************* MAIN ROUTINES *******************************/ #ifdef QDIO_USE_PROCESSING_STATE static inline int -iqdio_do_inbound_checks(struct qdio_q *q, int q_laps) +tiqdio_do_inbound_checks(struct qdio_q *q, int q_laps) { if (!q) { - iqdio_sched_tl(); + tiqdio_sched_tl(); return 0; } @@ -1082,7 +1120,7 @@ if (q->siga_sync) return 2; - if (qdio_reserve_q(q)) { + if (unlikely(qdio_reserve_q(q))) { qdio_release_q(q); #ifdef QDIO_PERFORMANCE_STATS ii_p_c++; @@ -1096,8 +1134,8 @@ * sanity -- we'd get here without setting the * dev st chg ind */ - iqdio_set_summary_bit((__u32*)q->dev_st_chg_ind); - iqdio_sched_tl(); + tiqdio_set_summary_bit((__u32*)q->dev_st_chg_ind); + tiqdio_sched_tl(); return 0; } if (qdio_stop_polling(q)) { @@ -1112,8 +1150,8 @@ * we set the flags to get into the stuff * next time, see also comment in qdio_stop_polling */ - iqdio_set_summary_bit((__u32*)q->dev_st_chg_ind); - iqdio_sched_tl(); + tiqdio_set_summary_bit((__u32*)q->dev_st_chg_ind); + tiqdio_sched_tl(); qdio_release_q(q); return 1; @@ -1121,7 +1159,7 @@ #endif /* QDIO_USE_PROCESSING_STATE */ static inline void -iqdio_inbound_checks(void) +tiqdio_inbound_checks(void) { struct qdio_q *q; #ifdef QDIO_USE_PROCESSING_STATE @@ -1135,20 +1173,20 @@ again: #endif /* QDIO_USE_PROCESSING_STATE */ - q=(struct qdio_q*)iq_list; + q=(struct qdio_q*)tiq_list; do { if (!q) break; - iqdio_inbound_processing(q); + tiqdio_inbound_processing(q); q=(struct qdio_q*)q->list_next; - } while (q!=(struct qdio_q*)iq_list); + } while (q!=(struct qdio_q*)tiq_list); #ifdef QDIO_USE_PROCESSING_STATE - q=(struct qdio_q*)iq_list; + q=(struct qdio_q*)tiq_list; do { int ret; - ret = iqdio_do_inbound_checks(q, q_laps); + ret = tiqdio_do_inbound_checks(q, q_laps); switch (ret) { case 0: return; @@ -1161,17 +1199,12 @@ q_laps++; goto again; } - } while (q!=(struct qdio_q*)iq_list); + } while (q!=(struct qdio_q*)tiq_list); #endif /* QDIO_USE_PROCESSING_STATE */ } static void -iqdio_check_for_polling(void) -{ -} - -static void -iqdio_tl(unsigned long data) +tiqdio_tl(unsigned long data) { QDIO_DBF_TEXT4(0,trace,"iqdio_tl"); @@ -1179,8 +1212,7 @@ perf_stats.tl_runs++; #endif /* QDIO_PERFORMANCE_STATS */ - iqdio_inbound_checks(); - iqdio_check_for_polling(); + tiqdio_inbound_checks(); } /********************* GENERAL HELPER_ROUTINES ***********************/ @@ -1298,6 +1330,7 @@ q->int_parm=int_parm; irq_ptr->input_qs[i]=q; q->irq=irq_ptr->irq; + q->irq_ptr = irq_ptr; q->cdev = cdev; q->mask=1<<(31-i); q->q_no=i; @@ -1308,10 +1341,11 @@ q->dev_st_chg_ind=irq_ptr->dev_st_chg_ind; q->tasklet.data=(unsigned long)q; + /* q->is_thinint_q isn't valid at this time, but + * irq_ptr->is_thinint_irq is */ q->tasklet.func=(void(*)(unsigned long)) - ( - (q_format==QDIO_IQDIO_QFMT)?&iqdio_inbound_processing: - &qdio_inbound_processing); + ((irq_ptr->is_thinint_irq)?&tiqdio_inbound_processing: + &qdio_inbound_processing); /* for (j=0;jtiming.last_transfer_times[j]=(qdio_get_micros()/ @@ -1376,6 +1410,7 @@ q->is_input_q=0; q->irq=irq_ptr->irq; q->cdev = cdev; + q->irq_ptr = irq_ptr; q->mask=1<<(31-i); q->q_no=i; q->first_to_check=0; @@ -1454,7 +1489,7 @@ } static int -iqdio_thinint_handler(void) +tiqdio_thinint_handler(void) { QDIO_DBF_TEXT4(0,trace,"thin_int"); @@ -1464,10 +1499,9 @@ #endif /* QDIO_PERFORMANCE_STATS */ /* VM will do the SVS for us */ if (!MACHINE_IS_VM) - iqdio_clear_global_summary(); + tiqdio_clear_global_summary(); - iqdio_inbound_checks(); - iqdio_check_for_polling(); + tiqdio_inbound_checks(); return 0; } @@ -1814,9 +1848,10 @@ } static unsigned int -iqdio_check_chsc_availability(void) +tiqdio_check_chsc_availability(void) { int result; + char dbf_text[15]; struct { struct chsc_header request; @@ -1871,6 +1906,12 @@ result=-ENOENT; goto exit; } + + /* Check for hydra thin interrupts. */ + hydra_thinints = ((scsc_area->general_char[2] & 0x10000000) + == 0x10000000); + sprintf(dbf_text,"hydra_ti%1x", hydra_thinints); + QDIO_DBF_TEXT0(0,setup,dbf_text); exit: free_page ((unsigned long) scsc_area); return result; @@ -1878,7 +1919,7 @@ static unsigned int -iqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero) +tiqdio_set_subchannel_ind(struct qdio_irq *irq_ptr, int reset_to_zero) { unsigned long real_addr_local_summary_bit; unsigned long real_addr_dev_st_chg_ind; @@ -1907,7 +1948,7 @@ u32 reserved7; } *scssc_area; - if (!irq_ptr->is_iqdio_irq) + if (!irq_ptr->is_thinint_irq) return -ENODEV; if (reset_to_zero) { @@ -1936,7 +1977,7 @@ scssc_area->subchannel_indicator_addr = real_addr_dev_st_chg_ind; scssc_area->ks = QDIO_STORAGE_KEY; scssc_area->kc = QDIO_STORAGE_KEY; - scssc_area->isc = IQDIO_THININT_ISC; + scssc_area->isc = TIQDIO_THININT_ISC; scssc_area->subsystem_id = (1<<16) + irq_ptr->irq; result = chsc(scssc_area); @@ -1972,7 +2013,7 @@ } static unsigned int -iqdio_set_delay_target(struct qdio_irq *irq_ptr, unsigned long delay_target) +tiqdio_set_delay_target(struct qdio_irq *irq_ptr, unsigned long delay_target) { unsigned int resp_code; int result; @@ -1992,7 +2033,7 @@ u32 reserved6; } *scsscf_area; - if (!irq_ptr->is_iqdio_irq) + if (!irq_ptr->is_thinint_irq) return -ENODEV; scsscf_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA); @@ -2082,7 +2123,7 @@ for (i=0;ino_output_qs;i++) atomic_set(&irq_ptr->output_qs[i]->is_in_shutdown,1); - tasklet_kill(&iqdio_tasklet); + tasklet_kill(&tiqdio_tasklet); for (i=0;ino_input_qs;i++) { qdio_unmark_q(irq_ptr->input_qs[i]); @@ -2145,9 +2186,9 @@ static inline void qdio_cleanup_finish(struct ccw_device *cdev, struct qdio_irq *irq_ptr) { - if (irq_ptr->is_iqdio_irq) { + if (irq_ptr->is_thinint_irq) { qdio_put_indicator((__u32*)irq_ptr->dev_st_chg_ind); - iqdio_set_subchannel_ind(irq_ptr,1); + tiqdio_set_subchannel_ind(irq_ptr,1); /* reset adapter interrupt indicators */ } @@ -2156,6 +2197,7 @@ cdev->handler=irq_ptr->original_int_handler; qdio_set_state(irq_ptr,QDIO_IRQ_STATE_INACTIVE); + } int @@ -2228,13 +2270,14 @@ qdio_allocate_fill_input_desc(struct qdio_irq *irq_ptr, int i, int iqfmt) { irq_ptr->input_qs[i]->is_iqdio_q = iqfmt; + irq_ptr->input_qs[i]->is_thinint_q = irq_ptr->is_thinint_irq; irq_ptr->qdr->qdf0[i].sliba=(unsigned long)(irq_ptr->input_qs[i]->slib); irq_ptr->qdr->qdf0[i].sla=(unsigned long)(irq_ptr->input_qs[i]->sl); irq_ptr->qdr->qdf0[i].slsba= - (unsigned long)(&irq_ptr->input_qs[i]->slsb.acc.val[0]); + (unsigned long)(&irq_ptr->input_qs[i]->slsb.acc.val[0]); irq_ptr->qdr->qdf0[i].akey=QDIO_STORAGE_KEY; irq_ptr->qdr->qdf0[i].bkey=QDIO_STORAGE_KEY; @@ -2247,9 +2290,9 @@ int j, int iqfmt) { irq_ptr->output_qs[i]->is_iqdio_q = iqfmt; + irq_ptr->output_qs[i]->is_thinint_q = irq_ptr->is_thinint_irq; - irq_ptr->qdr->qdf0[i+j].sliba= - (unsigned long)(irq_ptr->output_qs[i]->slib); + irq_ptr->qdr->qdf0[i+j].sliba=(unsigned long)(irq_ptr->output_qs[i]->slib); irq_ptr->qdr->qdf0[i+j].sla=(unsigned long)(irq_ptr->output_qs[i]->sl); @@ -2279,6 +2322,13 @@ irq_ptr->qdioac&CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS; irq_ptr->input_qs[i]->hydra_gives_outbound_pcis= irq_ptr->hydra_gives_outbound_pcis; + irq_ptr->input_qs[i]->siga_sync_done_on_outb_tis= + ((irq_ptr->qdioac& + (CHSC_FLAG_SIGA_SYNC_DONE_ON_OUTB_PCIS| + CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS))== + (CHSC_FLAG_SIGA_SYNC_DONE_ON_OUTB_PCIS| + CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS)); + } } @@ -2298,6 +2348,13 @@ irq_ptr->qdioac&CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS; irq_ptr->output_qs[i]->hydra_gives_outbound_pcis= irq_ptr->hydra_gives_outbound_pcis; + irq_ptr->output_qs[i]->siga_sync_done_on_outb_tis= + ((irq_ptr->qdioac& + (CHSC_FLAG_SIGA_SYNC_DONE_ON_OUTB_PCIS| + CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS))== + (CHSC_FLAG_SIGA_SYNC_DONE_ON_OUTB_PCIS| + CHSC_FLAG_SIGA_SYNC_DONE_ON_THININTS)); + } } @@ -2414,6 +2471,7 @@ struct ciw *ciw; int result; int is_iqdio; + char dbf_text[15]; if ( (init_data->no_input_qs>QDIO_MAX_QUEUES_PER_IRQ) || (init_data->no_output_qs>QDIO_MAX_QUEUES_PER_IRQ) || @@ -2460,9 +2518,18 @@ irq_ptr->no_input_qs=init_data->no_input_qs; irq_ptr->no_output_qs=init_data->no_output_qs; - irq_ptr->is_iqdio_irq=(init_data->q_format==QDIO_IQDIO_QFMT)?1:0; + if (init_data->q_format==QDIO_IQDIO_QFMT) { + irq_ptr->is_iqdio_irq=1; + irq_ptr->is_thinint_irq=1; + } else { + irq_ptr->is_iqdio_irq=0; + irq_ptr->is_thinint_irq=hydra_thinints; + } + sprintf(dbf_text,"is_i_t%1x%1x", + irq_ptr->is_iqdio_irq,irq_ptr->is_thinint_irq); + QDIO_DBF_TEXT2(0,setup,dbf_text); - if (irq_ptr->is_iqdio_irq) { + if (irq_ptr->is_thinint_irq) { irq_ptr->dev_st_chg_ind=qdio_get_indicator(); QDIO_DBF_HEX1(0,setup,&irq_ptr->dev_st_chg_ind,sizeof(void*)); if (!irq_ptr->dev_st_chg_ind) { @@ -2522,10 +2589,10 @@ /* fill in qib */ irq_ptr->qib.qfmt=init_data->q_format; - if (init_data->no_input_qs) irq_ptr->qib.isliba= - (unsigned long)(irq_ptr->input_qs[0]->slib); - if (init_data->no_output_qs) irq_ptr->qib.osliba=(unsigned long) - (irq_ptr->output_qs[0]->slib); + if (init_data->no_input_qs) + irq_ptr->qib.isliba=(unsigned long)(irq_ptr->input_qs[0]->slib); + if (init_data->no_output_qs) + irq_ptr->qib.osliba=(unsigned long)(irq_ptr->output_qs[0]->slib); memcpy(irq_ptr->qib.ebcnam,init_data->adapter_name,8); qdio_set_impl_params(irq_ptr,init_data->qib_param_field_format, @@ -2567,21 +2634,16 @@ irq_ptr->original_int_handler = init_data->cdev->handler; init_data->cdev->handler = qdio_handler; - /* the iqdio CHSC stuff */ - if (irq_ptr->is_iqdio_irq) { -/* iqdio_enable_adapter_int_facility(irq_ptr);*/ - - if (iqdio_check_chsc_availability()) { - QDIO_PRINT_ERR("Not all CHSCs supported. " \ - "Continuing.\n"); - } - result=iqdio_set_subchannel_ind(irq_ptr,0); + /* the thinint CHSC stuff */ + if (irq_ptr->is_thinint_irq) { + + result = tiqdio_set_subchannel_ind(irq_ptr,0); if (result) { up(&irq_ptr->setting_up_sema); qdio_cleanup(init_data->cdev, QDIO_FLAG_CLEANUP_USING_CLEAR); return result; } - iqdio_set_delay_target(irq_ptr,IQDIO_DELAY_TARGET); + tiqdio_set_delay_target(irq_ptr,TIQDIO_DELAY_TARGET); } up(&irq_ptr->setting_up_sema); @@ -2620,7 +2682,7 @@ ccw_device_set_options(cdev, 0); result=ccw_device_start_timeout(cdev,&irq_ptr->ccw, - QDIO_DOING_ESTABLISH,0,0, + QDIO_DOING_ESTABLISH,0, 0, QDIO_ESTABLISH_TIMEOUT); if (result) { result2=ccw_device_start_timeout(cdev,&irq_ptr->ccw, @@ -2721,14 +2783,14 @@ goto out; for (i=0;ino_input_qs;i++) { - if (irq_ptr->is_iqdio_irq) { + if (irq_ptr->is_thinint_irq) { /* * that way we know, that, if we will get interrupted - * by iqdio_inbound_processing, qdio_unmark_q will + * by tiqdio_inbound_processing, qdio_unmark_q will * not be called */ qdio_reserve_q(irq_ptr->input_qs[i]); - qdio_mark_iq(irq_ptr->input_qs[i]); + qdio_mark_tiq(irq_ptr->input_qs[i]); qdio_release_q(irq_ptr->input_qs[i]); } } @@ -2958,7 +3020,7 @@ perf_stats.siga_ins); _OUTP_IT("Number of SIGA out's issued : %u\n", perf_stats.siga_outs); - _OUTP_IT("Number of PCI's caught : %u\n", + _OUTP_IT("Number of PCIs caught : %u\n", perf_stats.pcis); _OUTP_IT("Number of adapter interrupts caught : %u\n", perf_stats.thinints); @@ -3032,11 +3094,11 @@ } static void -iqdio_register_thinints(void) +tiqdio_register_thinints(void) { char dbf_text[20]; register_thinint_result= - s390_register_adapter_interrupt(&iqdio_thinint_handler); + s390_register_adapter_interrupt(&tiqdio_thinint_handler); if (register_thinint_result) { sprintf(dbf_text,"regthn%x",(register_thinint_result&0xff)); QDIO_DBF_TEXT0(0,setup,dbf_text); @@ -3048,10 +3110,10 @@ } static void -iqdio_unregister_thinints(void) +tiqdio_unregister_thinints(void) { if (!register_thinint_result) - s390_unregister_adapter_interrupt(&iqdio_thinint_handler); + s390_unregister_adapter_interrupt(&tiqdio_thinint_handler); } static int @@ -3191,7 +3253,11 @@ #endif /* QDIO_PERFORMANCE_STATS */ qdio_add_procfs_entry(); - iqdio_register_thinints(); + + if (tiqdio_check_chsc_availability()) + QDIO_PRINT_ERR("Not all CHSCs supported. Continuing.\n"); + + tiqdio_register_thinints(); return 0; } @@ -3199,7 +3265,7 @@ static void __exit cleanup_QDIO(void) { - iqdio_unregister_thinints(); + tiqdio_unregister_thinints(); qdio_remove_procfs_entry(); qdio_release_qdio_memory(); qdio_unregister_dbf_views(); diff -Nru a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h --- a/drivers/s390/cio/qdio.h Tue Jul 1 18:44:33 2003 +++ b/drivers/s390/cio/qdio.h Tue Jul 1 18:44:33 2003 @@ -1,7 +1,7 @@ #ifndef _CIO_QDIO_H #define _CIO_QDIO_H -#define VERSION_CIO_QDIO_H "$Revision: 1.16 $" +#define VERSION_CIO_QDIO_H "$Revision: 1.18 $" //#define QDIO_DBF_LIKE_HELL @@ -21,10 +21,18 @@ #define QDIO_TIMER_POLL_VALUE 1 #define IQDIO_TIMER_POLL_VALUE 1 -#define IQDIO_FILL_LEVEL_TO_POLL (QDIO_MAX_BUFFERS_PER_Q*4/3) +/* + * unfortunately this can't be (QDIO_MAX_BUFFERS_PER_Q*4/3) or so -- as + * we never know, whether we'll get initiative again, e.g. to give the + * transmit skb's back to the stack, however the stack may be waiting for + * them... therefore we define 4 as threshold to start polling (which + * will stop as soon as the asynchronous queue catches up) + * btw, this only applies to the asynchronous HiperSockets queue + */ +#define IQDIO_FILL_LEVEL_TO_POLL 4 -#define IQDIO_THININT_ISC 3 -#define IQDIO_DELAY_TARGET 0 +#define TIQDIO_THININT_ISC 3 +#define TIQDIO_DELAY_TARGET 0 #define QDIO_BUSY_BIT_PATIENCE 2000 /* in microsecs */ #define IQDIO_GLOBAL_LAPS 2 /* GLOBAL_LAPS are not used as we */ #define IQDIO_GLOBAL_LAPS_INT 1 /* don't global summary */ @@ -465,7 +473,13 @@ #define atomic_swap(a,b) xchg((int*)a.counter,b) -#define SYNC_MEMORY if (q->siga_sync) qdio_siga_sync(q) +/* unlikely as the later the better */ +#define SYNC_MEMORY if (unlikely(q->siga_sync)) qdio_siga_sync_q(q) +#define SYNC_MEMORY_ALL if (unlikely(q->siga_sync)) \ + qdio_siga_sync(q,~0U,~0U) +#define SYNC_MEMORY_ALL_OUTB if (unlikely(q->siga_sync)) \ + qdio_siga_sync(q,~0U,0) + #define NOW qdio_get_micros() #define SAVE_TIMESTAMP(q) q->timing.last_transfer_time=NOW #define GET_SAVED_TIMESTAMP(q) (q->timing.last_transfer_time) @@ -511,6 +525,7 @@ struct ccw_device *cdev; unsigned int is_iqdio_q; + unsigned int is_thinint_q; /* bit 0 means queue 0, bit 1 means queue 1, ... */ unsigned int mask; @@ -532,6 +547,7 @@ unsigned int siga_out; unsigned int siga_sync; unsigned int siga_sync_done_on_thinints; + unsigned int siga_sync_done_on_outb_tis; unsigned int hydra_gives_outbound_pcis; /* used to save beginning position when calling dd_handlers */ @@ -540,6 +556,8 @@ atomic_t use_count; atomic_t is_in_shutdown; + void *irq_ptr; + #ifdef QDIO_USE_TIMERS_FOR_POLLING struct timer_list timer; atomic_t timer_already_set; @@ -596,6 +614,7 @@ int irq; unsigned int is_iqdio_irq; + unsigned int is_thinint_irq; unsigned int hydra_gives_outbound_pcis; unsigned int sync_done_on_outb_pcis; diff -Nru a/drivers/s390/cio/requestirq.c b/drivers/s390/cio/requestirq.c --- a/drivers/s390/cio/requestirq.c Tue Jul 1 18:44:36 2003 +++ b/drivers/s390/cio/requestirq.c Tue Jul 1 18:44:36 2003 @@ -1,7 +1,7 @@ /* * drivers/s390/cio/requestirq.c * S/390 common I/O routines -- enabling and disabling of devices - * $Revision: 1.44 $ + * $Revision: 1.45 $ * * Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH, * IBM Corporation @@ -45,11 +45,15 @@ /* * Let's build our path group ID here. */ + if (MACHINE_NEW_STIDP) + global_pgid.cpu_addr = 0x8000; + else { #ifdef CONFIG_SMP - global_pgid.cpu_addr = hard_smp_processor_id(); + global_pgid.cpu_addr = hard_smp_processor_id(); #else - global_pgid.cpu_addr = 0; + global_pgid.cpu_addr = 0; #endif + } global_pgid.cpu_id = ((cpuid_t *) __LC_CPUID)->ident; global_pgid.cpu_model = ((cpuid_t *) __LC_CPUID)->machine; global_pgid.tod_high = (__u32) (get_clock() >> 32); diff -Nru a/drivers/s390/net/Kconfig b/drivers/s390/net/Kconfig --- a/drivers/s390/net/Kconfig Tue Jul 1 18:44:37 2003 +++ b/drivers/s390/net/Kconfig Tue Jul 1 18:44:37 2003 @@ -30,9 +30,56 @@ vehicle networking under VM or VIF. This option is also available as a module which will be called iucv.ko. If unsure, say "Y". + +config QETH + tristate "Gigabit Ethernet device support" + depends on NETDEVICES && IP_MULTICAST && QDIO + help + This driver supports the IBM S/390 and zSeries OSA Express adapters + in QDIO mode (all media types), HiperSockets interfaces and VM GuestLAN + interfaces in QDIO and HIPER mode. + + For details please refer to the documentation provided by IBM at + + + This driver is also available as a module (code which can be + inserted in and removed from the running kernel whenever you + want). If you want to compile it as a module, say 'M' here and + read file Documentation/modules.txt. + + +comment "Gigabit Ethernet default settings" + depends on QETH + +# FIXME IPV6=m && QETH=y +config QETH_IPV6 + bool "IPv6 support for gigabit ethernet" + depends on QETH && IPV6 + help + If CONFIG_QETH is switched on, this option will include IPv6 + support in the qeth device driver. + +# FIXME VLAN_8021Q=m && QETH=y +config QETH_VLAN + bool "VLAN support for gigabit ethernet" + depends on QETH && VLAN_8021Q + help + If CONFIG_QETH is switched on, this option will include IEEE + 802.1q VLAN support in the qeth device driver. + +config QETH_PERF_STATS + bool "Performance statistics in /proc" + depends on QETH + help + When switched on, this option will add a file in the proc-fs + (/proc/qeth_perf_stats) containing performance statistics. It + may slightly impact performance, so this is only recommended for + internal tuning of the device driver. + config CCWGROUP tristate - depends on LCS || CTC - default m if LCS!=y && CTC!=y - default y if LCS=y || CTC=y + depends on LCS || CTC || QETH + default m if LCS!=y && CTC!=y && QETH!=y + default y if LCS=y || CTC=y || QETH=y + endmenu diff -Nru a/drivers/s390/net/Makefile b/drivers/s390/net/Makefile --- a/drivers/s390/net/Makefile Tue Jul 1 18:44:34 2003 +++ b/drivers/s390/net/Makefile Tue Jul 1 18:44:34 2003 @@ -8,3 +8,6 @@ obj-$(CONFIG_CTC) += ctc.o fsm.o cu3088.o obj-$(CONFIG_IUCV) += netiucv.o obj-$(CONFIG_LCS) += lcs.o cu3088.o +qeth_mod-objs := qeth.o qeth_mpc.o +obj-$(CONFIG_QETH) += qeth_mod.o + diff -Nru a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c --- a/drivers/s390/net/ctcmain.c Tue Jul 1 18:44:34 2003 +++ b/drivers/s390/net/ctcmain.c Tue Jul 1 18:44:34 2003 @@ -1,5 +1,5 @@ /* - * $Id: ctcmain.c,v 1.42 2003/05/23 17:45:57 felfert Exp $ + * $Id: ctcmain.c,v 1.43 2003/05/27 11:34:23 mschwide Exp $ * * CTC / ESCON network driver * @@ -36,7 +36,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.42 $ + * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.43 $ * */ @@ -272,7 +272,7 @@ print_banner(void) { static int printed = 0; - char vbuf[] = "$Revision: 1.42 $"; + char vbuf[] = "$Revision: 1.43 $"; char *version = vbuf; if (printed) @@ -2752,7 +2752,7 @@ dev->type = ARPHRD_SLIP; dev->tx_queue_len = 100; dev->flags = IFF_POINTOPOINT | IFF_NOARP; - SET_MODULE_OWNER(&tun->dev); + SET_MODULE_OWNER(dev); return dev; } diff -Nru a/drivers/s390/net/ctctty.c b/drivers/s390/net/ctctty.c --- a/drivers/s390/net/ctctty.c Tue Jul 1 18:44:35 2003 +++ b/drivers/s390/net/ctctty.c Tue Jul 1 18:44:35 2003 @@ -1,5 +1,5 @@ /* - * $Id: ctctty.c,v 1.11 2003/05/06 09:40:55 mschwide Exp $ + * $Id: ctctty.c,v 1.12 2003/06/17 11:36:44 mschwide Exp $ * * CTC / ESCON network driver, tty interface. * diff -Nru a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c --- a/drivers/s390/net/lcs.c Tue Jul 1 18:44:32 2003 +++ b/drivers/s390/net/lcs.c Tue Jul 1 18:44:32 2003 @@ -11,7 +11,7 @@ * Frank Pavlic (pavlic@de.ibm.com) and * Martin Schwidefsky * - * $Revision: 1.51 $ $Date: 2003/03/28 08:54:40 $ + * $Revision: 1.53 $ $Date: 2003/06/17 11:36:45 $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -58,7 +58,7 @@ /** * initialization string for output */ -#define VERSION_LCS_C "$Revision: 1.51 $" +#define VERSION_LCS_C "$Revision: 1.53 $" static char version[] __initdata = "LCS driver ("VERSION_LCS_C "/" VERSION_LCS_H ")"; @@ -1785,7 +1785,7 @@ dev->set_multicast_list = lcs_set_multicast_list; #endif dev->get_stats = lcs_getstats; - SET_MODULE_OWNER(&tun->dev); + SET_MODULE_OWNER(dev); if (register_netdev(dev) != 0) goto out; netif_stop_queue(dev); diff -Nru a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c --- a/drivers/s390/net/netiucv.c Tue Jul 1 18:44:35 2003 +++ b/drivers/s390/net/netiucv.c Tue Jul 1 18:44:35 2003 @@ -1,5 +1,5 @@ /* - * $Id: netiucv.c,v 1.19 2003/04/08 16:00:17 mschwide Exp $ + * $Id: netiucv.c,v 1.20 2003/05/27 11:34:24 mschwide Exp $ * * IUCV network driver * @@ -30,7 +30,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * RELEASE-TAG: IUCV network driver $Revision: 1.19 $ + * RELEASE-TAG: IUCV network driver $Revision: 1.20 $ * */ @@ -1631,7 +1631,7 @@ dev->type = ARPHRD_SLIP; dev->tx_queue_len = NETIUCV_QUEUELEN_DEFAULT; dev->flags = IFF_POINTOPOINT | IFF_NOARP; - SET_MODULE_OWNER(&tun->dev); + SET_MODULE_OWNER(dev); return dev; } @@ -1717,7 +1717,7 @@ static void netiucv_banner(void) { - char vbuf[] = "$Revision: 1.19 $"; + char vbuf[] = "$Revision: 1.20 $"; char *version = vbuf; if ((version = strchr(version, ':'))) { diff -Nru a/drivers/s390/net/qeth.c b/drivers/s390/net/qeth.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/s390/net/qeth.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,11182 @@ +/* + * + * linux/drivers/s390/net/qeth.c ($Revision: 1.118 $) + * + * Linux on zSeries OSA Express and HiperSockets support + * + * Copyright 2000,2003 IBM Corporation + * + * Author(s): Utz Bacher + * Cornelia Huck (2.5 integration, + * numerous bugfixes) + * Frank Pavlic (query/purge ARP, SNMP, fixes) + * Andreas Herrmann (bugfixes) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * The driver supports in general all QDIO driven network devices on the + * Hydra card. + * + * For all devices, three channels must be available to the driver. One + * channel is the read channel, one is the write channel and the third + * one is the channel used to control QDIO. + * + * There are several stages from the channel recognition to the running + * network device: + * - The channels are scanned and ordered due to the parameters (see + * MODULE_PARM_DESC) + * - The card is hardsetup: this means, that the communication channels + * are prepared + * - The card is softsetup: this means, that commands are issued + * to activate the network parameters + * - After that, data can flow through the card (transported by QDIO) + * + *IPA Takeover: + * /proc/qeth_ipa_takeover provides the possibility to add and remove + * certain ranges of IP addresses to the driver. As soon as these + * addresses have to be set by the driver, the driver uses the OSA + * Address Takeover mechanism. + * reading out of the proc-file displays the registered addresses; + * writing into it changes the information. Only one command at one + * time must be written into the file. Subsequent commands are ignored. + * The following commands are available: + * inv4 + * inv6 + * add4 /[:] + * add6 /[:] + * del4 /[:] + * del6 /[:] + * inv4 and inv6 toggle the IPA takeover behaviour for all interfaces: + * when inv4 was input once, all addresses specified with add4 are not + * set using the takeover mechanism, but all other IPv4 addresses are set so. + * + * add# adds an address range, del# deletes an address range. # corresponds + * to the IP version (4 or 6). + * is a 8 or 32byte hexadecimal view of the IP address. + * specifies the number of bits which are set in the network mask. + * is optional and specifies the interface name to which the + * address range is bound. + * E. g. + * add4 C0a80100/24 + * activates all addresses in the 192.168.10 subnet for address takeover. + * Note, that the address is not taken over before an according ifconfig + * is executed. + * + *VIPA: + * add_vipa4 : + * add_vipa6 : + * del_vipa4 : + * del_vipa6 : + * + * the specified address is set/unset as VIPA on the specified interface. + * use the src_vipa package to exploit this out of arbitrary applications. + * + *Proxy ARP: + * + * add_rxip4 : + * add_rxip6 : + * del_rxip4 : + * del_rxip6 : + * + * the specified address is set/unset as "do not fail a gratuitous ARP" + * on the specified interface. this can be used to act as a proxy ARP. + */ + +static void volatile +qeth_eyecatcher(void) +{ + return; +} + +#undef DEBUG + +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_PROC_FS +#include +#endif /* CONFIG_PROC_FS */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "qeth_mpc.h" +#include "qeth.h" + +/****************** MODULE PARAMETER VARIABLES ********************/ +static int qeth_sparebufs = 0; +MODULE_PARM(qeth_sparebufs, "i"); +MODULE_PARM_DESC(qeth_sparebufs, "the number of pre-allocated spare buffers " + "reserved for low memory situations"); + +/****************** MODULE STUFF **********************************/ +#define VERSION_QETH_C "$Revision: 1.118 $" +static const char *version = "qeth S/390 OSA-Express driver (" + VERSION_QETH_C "/" VERSION_QETH_H "/" VERSION_QETH_MPC_H + QETH_VERSION_IPV6 QETH_VERSION_VLAN ")"; + +MODULE_AUTHOR("Utz Bacher "); +MODULE_DESCRIPTION("Linux on zSeries OSA Express and HiperSockets support\n" \ + "Copyright 2000,2003 IBM Corporation\n"); +MODULE_LICENSE("GPL"); + +/******************** HERE WE GO ***********************************/ + +#define PROCFILE_SLEEP_SEM_MAX_VALUE 0 +#define PROCFILE_IOCTL_SEM_MAX_VALUE 3 +static struct semaphore qeth_procfile_ioctl_lock; +static struct semaphore qeth_procfile_ioctl_sem; +static struct qeth_card *firstcard = NULL; + +static struct sparebufs sparebufs[MAX_SPARE_BUFFERS]; +static int sparebuffer_count; + +static unsigned int known_devices[][10] = QETH_MODELLIST_ARRAY; + +static spinlock_t setup_lock = SPIN_LOCK_UNLOCKED; +static rwlock_t list_lock = RW_LOCK_UNLOCKED; + +static debug_info_t *qeth_dbf_setup = NULL; +static debug_info_t *qeth_dbf_data = NULL; +static debug_info_t *qeth_dbf_misc = NULL; +static debug_info_t *qeth_dbf_control = NULL; +static debug_info_t *qeth_dbf_trace = NULL; +static debug_info_t *qeth_dbf_sense = NULL; +static debug_info_t *qeth_dbf_qerr = NULL; + +static int proc_file_registration; +#ifdef QETH_PERFORMANCE_STATS +static int proc_perf_file_registration; +#define NOW qeth_get_micros() +#endif /* QETH_PERFORMANCE_STATS */ +static int proc_ipato_file_registration; + +static int ipato_inv4 = 0, ipato_inv6 = 0; +static struct ipato_entry *ipato_entries = NULL; +static spinlock_t ipato_list_lock = SPIN_LOCK_UNLOCKED; + +struct tempinfo{ + char *data; + int len; +}; + +/* thought I could get along without forward declarations... + * just lazyness here */ +static int qeth_reinit_thread(void *); +static void qeth_schedule_recovery(struct qeth_card *card); + +inline static int +QETH_IP_VERSION(struct sk_buff *skb) +{ + switch (skb->protocol) { + case ETH_P_IPV6: + return 6; + case ETH_P_IP: + return 4; + default: + return 0; + } +} + +/* not a macro, as one of the arguments is atomic_read */ +static inline int +qeth_min(int a, int b) +{ + if (a < b) + return a; + else + return b; +} + +static inline unsigned int +qeth_get_millis(void) +{ + __u64 time; + + asm volatile ("STCK %0":"=m" (time)); + return (int) (time >> 22); /* time>>12 is microseconds, we divide it + by 1024 */ +} + +#ifdef QETH_PERFORMANCE_STATS +static inline unsigned int +qeth_get_micros(void) +{ + __u64 time; + + asm volatile ("STCK %0":"=m" (time)); + return (int) (time >> 12); +} +#endif /* QETH_PERFORMANCE_STATS */ + +static void +qeth_delay_millis(unsigned long msecs) +{ + unsigned int start; + + start = qeth_get_millis(); + while (qeth_get_millis() - start < msecs) ; +} + +static void +qeth_wait_nonbusy(unsigned int timeout) +{ + unsigned int start; + char dbf_text[15]; + + sprintf(dbf_text, "wtnb%4x", timeout); + QETH_DBF_TEXT3(0, trace, dbf_text); + + start = qeth_get_millis(); + for (;;) { + set_task_state(current, TASK_INTERRUPTIBLE); + if (qeth_get_millis() - start > timeout) { + goto out; + } + schedule_timeout(((start + timeout - + qeth_get_millis()) >> 10) * HZ); + } +out: + set_task_state(current, TASK_RUNNING); +} + +static void +qeth_get_mac_for_ipm(__u32 ipm, char *mac, struct net_device *dev) +{ + if (dev->type == ARPHRD_IEEE802_TR) + ip_tr_mc_map(ipm, mac); + else + ip_eth_mc_map(ipm, mac); +} + +#define atomic_swap(a,b) xchg((int*)a.counter,b) + +static int inline +my_spin_lock_nonbusy(struct qeth_card *card, spinlock_t * lock) +{ + for (;;) { + if (card) { + if (atomic_read(&card->shutdown_phase)) + return -1; + } + if (spin_trylock(lock)) + return 0; + qeth_wait_nonbusy(QETH_IDLE_WAIT_TIME); + } +} + +#ifdef CONFIG_ARCH_S390X +#define QETH_GET_ADDR(x) ((__u32)(unsigned long)x) +#else /* CONFIG_ARCH_S390X */ +#define QETH_GET_ADDR(x) ((__u32)x) +#endif /* CONFIG_ARCH_S390X */ + +static int +qeth_does_card_exist(struct qeth_card *card) +{ + struct qeth_card *c = firstcard; + int rc = 0; + + read_lock(&list_lock); + while (c) { + if (c == card) { + rc = 1; + break; + } + c = c->next; + } + read_unlock(&list_lock); + return rc; +} + +static int +qeth_getxdigit(char c) +{ + if ((c >= '0') && (c <= '9')) + return c - '0'; + if ((c >= 'a') && (c <= 'f')) + return c + 10 - 'a'; + if ((c >= 'A') && (c <= 'F')) + return c + 10 - 'A'; + return -1; +} + +static struct qeth_card * +qeth_get_card_by_name(char *name) +{ + struct qeth_card *card; + + read_lock(&list_lock); + card = firstcard; + while (card) { + if (!strncmp(name, card->dev_name, DEV_NAME_LEN)) + break; + card = card->next; + } + read_unlock(&list_lock); + + return card; +} + +static void +qeth_convert_addr_to_text(int version, __u8 * addr, char *text) +{ + if (version == 4) { + sprintf(text, "%02x%02x%02x%02x", + addr[0], addr[1], addr[2], addr[3]); + } else { + sprintf(text, "%02x%02x%02x%02x%02x%02x%02x%02x" + "%02x%02x%02x%02x%02x%02x%02x%02x", + addr[0], addr[1], addr[2], addr[3], + addr[4], addr[5], addr[6], addr[7], + addr[8], addr[9], addr[10], addr[11], + addr[12], addr[13], addr[14], addr[15]); + } +} + +static int +qeth_convert_text_to_addr(int version, char *text, __u8 * addr) +{ + int olen = (version == 4) ? 4 : 16; + + while (olen--) { + if ((!isxdigit(*text)) || (!isxdigit(*(text + 1)))) + return -EINVAL; + *addr = + (qeth_getxdigit(*text) << 4) + qeth_getxdigit(*(text + 1)); + addr++; + text += 2; + } + return 0; +} + +static void +qeth_add_ipato_entry(int version, __u8 * addr, int mask_bits, char *dev_name) +{ + struct ipato_entry *entry, *e; + int len = (version == 4) ? 4 : 16; + + entry = + (struct ipato_entry *) kmalloc(sizeof (struct ipato_entry), + GFP_KERNEL); + if (!entry) { + PRINT_ERR("not enough memory for ipato allocation\n"); + return; + } + entry->version = version; + memcpy(entry->addr, addr, len); + if (dev_name) { + strncpy(entry->dev_name, dev_name, DEV_NAME_LEN); + if (qeth_get_card_by_name(dev_name)->options.ena_ipat != + ENABLE_TAKEOVER) + PRINT_WARN("IP takeover is not enabled on %s! " + "Ignoring line\n", dev_name); + } else + memset(entry->dev_name, 0, DEV_NAME_LEN); + entry->mask_bits = mask_bits; + entry->next = NULL; + + spin_lock(&ipato_list_lock); + if (ipato_entries) { + e = ipato_entries; + while (e) { + if ((e->version == version) && + (e->mask_bits == mask_bits) && + (((dev_name) && !strncmp(e->dev_name, dev_name, + DEV_NAME_LEN)) || + (!dev_name)) && (!memcmp(e->addr, addr, len))) { + PRINT_INFO("ipato to be added does already " + "exist\n"); + kfree(entry); + goto out; + } + if (e->next) + e = e->next; + else + break; + } + e->next = entry; + } else + ipato_entries = entry; + out: + spin_unlock(&ipato_list_lock); +} + +static void +qeth_del_ipato_entry(int version, __u8 * addr, int mask_bits, char *dev_name) +{ + struct ipato_entry *e, *e_before; + int len = (version == 4) ? 4 : 16; + int found = 0; + + spin_lock(&ipato_list_lock); + e = ipato_entries; + if ((e->version == version) && + (e->mask_bits == mask_bits) && (!memcmp(e->addr, addr, len))) { + ipato_entries = e->next; + kfree(e); + } else + while (e) { + e_before = e; + e = e->next; + if (!e) + break; + if ((e->version == version) && + (e->mask_bits == mask_bits) && + (((dev_name) && !strncmp(e->dev_name, dev_name, + DEV_NAME_LEN)) || + (!dev_name)) && (!memcmp(e->addr, addr, len))) { + e_before->next = e->next; + kfree(e); + found = 1; + break; + } + } + if (!found) + PRINT_INFO("ipato to be deleted does not exist\n"); + spin_unlock(&ipato_list_lock); +} + +static void +qeth_convert_addr_to_bits(__u8 * addr, char *bits, int len) +{ + int i, j; + __u8 octet; + + for (i = 0; i < len; i++) { + octet = addr[i]; + for (j = 7; j >= 0; j--) { + bits[i * 8 + j] = (octet & 1) ? 1 : 0; + octet >>= 1; + } + } +} + +static int +qeth_is_ipa_covered_by_ipato_entries(int version, __u8 * addr, + struct qeth_card *card) +{ + char *memarea, *addr_bits, *entry_bits; + int len = (version == 4) ? 4 : 16; + int invert = (version == 4) ? ipato_inv4 : ipato_inv6; + int result = 0; + struct ipato_entry *e; + + if (card->options.ena_ipat != ENABLE_TAKEOVER) { + return 0; + } + + memarea = kmalloc(256, GFP_KERNEL); + if (!memarea) { + PRINT_ERR("not enough memory to check out whether to " + "use ipato\n"); + return 0; + } + addr_bits = memarea; + entry_bits = memarea + 128; + qeth_convert_addr_to_bits(addr, addr_bits, len); + e = ipato_entries; + while (e) { + qeth_convert_addr_to_bits(e->addr, entry_bits, len); + if ((!memcmp(addr_bits, entry_bits, + __min(len * 8, e->mask_bits))) && + ((e->dev_name[0] && + (!strncmp(e->dev_name, card->dev_name, DEV_NAME_LEN))) || + (!e->dev_name[0]))) { + result = 1; + break; + } + e = e->next; + } + + kfree(memarea); + if (invert) + return !result; + else + return result; +} + +static void +qeth_set_dev_flag_running(struct qeth_card *card) +{ + if (card) { + card->dev->flags |= IFF_RUNNING; + } +} + +static void +qeth_set_dev_flag_norunning(struct qeth_card *card) +{ + if (card) { + card->dev->flags &= ~IFF_RUNNING; + } +} + +static void +qeth_restore_dev_flag_state(struct qeth_card *card) +{ + if (card) { + if (card->saved_dev_flags & IFF_RUNNING) + card->dev->flags |= IFF_RUNNING; + else + card->dev->flags &= ~IFF_RUNNING; + } +} + +static void +qeth_save_dev_flag_state(struct qeth_card *card) +{ + if (card) { + card->saved_dev_flags = card->dev->flags & IFF_RUNNING; + } +} + +static int +qeth_open(struct net_device *dev) +{ + struct qeth_card *card; + + card = (struct qeth_card *) dev->priv; + QETH_DBF_TEXT2(0, trace, "open"); + QETH_DBF_TEXT2(0, setup, "open"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + QETH_DBF_TEXT2(0, setup, card->rdev->dev.bus_id); + + qeth_save_dev_flag_state(card); + + netif_start_queue(dev); + atomic_set(&((struct qeth_card *) dev->priv)->is_open, 1); + + return 0; +} + +static int +qeth_set_config(struct net_device *dev, struct ifmap *map) +{ + QETH_DBF_TEXT3(0, trace, "nscf"); + QETH_DBF_TEXT3(0, trace, + ((struct qeth_card *)dev->priv)->rdev->dev.bus_id); + + return -EOPNOTSUPP; +} + +static int +qeth_is_multicast_skb_at_all(struct sk_buff *skb, int version) +{ + int i; + if (skb->dst && skb->dst->neighbour) { + i = skb->dst->neighbour->type; + return ((i == RTN_BROADCAST) || + (i == RTN_MULTICAST) || (i == RTN_ANYCAST)) ? i : 0; + } + /* ok, we've to try it somehow else */ + if (version == 4) { + return ((skb->nh.raw[16] & 0xf0) == 0xe0) ? RTN_MULTICAST : 0; + } else if (version == 6) { + return (skb->nh.raw[24] == 0xff) ? RTN_MULTICAST : 0; + } else { + PRINT_STUPID("QETH_IP_VERSION is %x\n", version); + PRINT_STUPID("skb->protocol=x%x=%i\n", + skb->protocol, skb->protocol); + HEXDUMP16(STUPID, "skb:", skb->data); + } + return 0; +} + +static int +qeth_get_prioqueue(struct qeth_card *card, struct sk_buff *skb, + int multicast, int version) +{ + if (!version) + return QETH_DEFAULT_QUEUE; + switch (card->no_queues) { + case 1: + return 0; + case 4: + if ((card->can_do_async_iqd) && + (card->options.async_iqd == ASYNC_IQD)) { + return card->no_queues - 1; + } + if (card->is_multicast_different) { + if (multicast) { + return card->is_multicast_different & + (card->no_queues - 1); + } else { + return 0; + } + } + if (card->options.do_prio_queueing) { + if (version == 4) { + if (card->options.do_prio_queueing == + PRIO_QUEUEING_TOS) { + if (skb->nh.iph->tos & + IP_TOS_NOTIMPORTANT) { + return 3; + } + if (skb->nh.iph->tos & IP_TOS_LOWDELAY) { + return 0; + } + if (skb->nh.iph->tos & + IP_TOS_HIGHTHROUGHPUT) { + return 1; + } + if (skb->nh.iph->tos & + IP_TOS_HIGHRELIABILITY) { + return 2; + } + return QETH_DEFAULT_QUEUE; + } + if (card->options.do_prio_queueing == + PRIO_QUEUEING_PREC) { + return 3 - (skb->nh.iph->tos >> 6); + } + } else if (version == 6) { + /******************** + ******************** + *TODO: IPv6!!! + ********************/ + } + return card->options.default_queue; + } else + return card->options.default_queue; + default: + return 0; + } +} + +static void +qeth_wakeup(struct qeth_card *card) +{ + QETH_DBF_TEXT5(0, trace, "wkup"); + QETH_DBF_TEXT5(0, trace, card->rdev->dev.bus_id); + + atomic_set(&card->data_has_arrived, 1); + spin_lock(&card->wait_q_lock); + if (atomic_read(&card->wait_q_active)) { + wake_up(&card->wait_q); + } + spin_unlock(&card->wait_q_lock); +} + +static int +qeth_check_idx_response(unsigned char *buffer) +{ + if (!buffer) + return 0; + if ((buffer[2] & 0xc0) == 0xc0) { + return -EIO; + } + return 0; +} + +static int +qeth_get_cards_problem(struct ccw_device *cdev, unsigned char *buffer, + int dstat, int cstat, int rqparam, + char *irb, char *sense) +{ + char dbf_text[15]; + int problem = 0; + struct qeth_card *card; + + card = cdev->dev.driver_data; + + if (atomic_read(&card->shutdown_phase)) + return 0; + if (dstat & DEV_STAT_UNIT_CHECK) { + if (sense[SENSE_RESETTING_EVENT_BYTE] & + SENSE_RESETTING_EVENT_FLAG) { + QETH_DBF_TEXT1(0, trace, "REVN"); + QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id); + problem = PROBLEM_RESETTING_EVENT_INDICATOR; + goto out; + } + if (sense[SENSE_COMMAND_REJECT_BYTE] & + SENSE_COMMAND_REJECT_FLAG) { + QETH_DBF_TEXT1(0, trace, "CREJ"); + QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id); + problem = PROBLEM_COMMAND_REJECT; + goto out; + } + if ((sense[2] == 0xaf) && (sense[3] == 0xfe)) { + QETH_DBF_TEXT1(0, trace, "AFFE"); + QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id); + problem = PROBLEM_AFFE; + goto out; + } + if ((!sense[0]) && (!sense[1]) && (!sense[2]) && (!sense[3])) { + QETH_DBF_TEXT1(0, trace, "ZSNS"); + QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id); + problem = PROBLEM_ZERO_SENSE_DATA; + goto out; + } + QETH_DBF_TEXT1(0, trace, "GCHK"); + QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id); + problem = PROBLEM_GENERAL_CHECK; + goto out; + } + if (cstat & (SCHN_STAT_CHN_CTRL_CHK | SCHN_STAT_INTF_CTRL_CHK | + SCHN_STAT_CHN_DATA_CHK | SCHN_STAT_CHAIN_CHECK | + SCHN_STAT_PROT_CHECK | SCHN_STAT_PROG_CHECK)) { + QETH_DBF_TEXT1(0, trace, "GCHK"); + QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id); + QETH_DBF_HEX1(0, misc, irb, __max(QETH_DBF_MISC_LEN, 64)); + PRINT_WARN("check on device %s, dstat=x%x, cstat=x%x, " + "rqparam=x%x\n", + cdev->dev.bus_id, dstat, cstat, rqparam); + HEXDUMP16(WARN, "irb: ", irb); + HEXDUMP16(WARN, "irb: ", ((char *) irb) + 32); + problem = PROBLEM_GENERAL_CHECK; + goto out; + } + if (qeth_check_idx_response(buffer)) { + PRINT_WARN("received an IDX TERMINATE on device %s " + "with cause code 0x%02x%s\n", + card->rdev->dev.bus_id, buffer[4], + (buffer[4] == + 0x22) ? " -- try another portname" : ""); + QETH_DBF_TEXT1(0, trace, "RTRM"); + QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id); + problem = PROBLEM_RECEIVED_IDX_TERMINATE; + goto out; + } + if (IS_IPA(buffer) && !IS_IPA_REPLY(buffer)) { + if (*(PDU_ENCAPSULATION(buffer)) == IPA_CMD_STOPLAN) { + atomic_set(&card->is_startlaned, 0); + /* we don't do a netif_stop_queue(card->dev); + we better discard all packets -- + the outage could take longer */ + PRINT_WARN("Link failure on %s (CHPID 0x%X) -- " + "there is a network problem or someone " + "pulled the cable or disabled the port." + "Discarding outgoing packets.\n", + card->dev_name, card->chpid); + QETH_DBF_TEXT1(0, trace, "CBOT"); + QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id); + qeth_set_dev_flag_norunning(card); + problem = 0; + goto out; + } + if (*(PDU_ENCAPSULATION(buffer)) == IPA_CMD_STARTLAN) { + if (!atomic_read(&card->is_startlaned)) { + atomic_set(&card->is_startlaned, 1); + problem = PROBLEM_CARD_HAS_STARTLANED; + } + goto out; + } + if (*(PDU_ENCAPSULATION(buffer)) == IPA_CMD_REGISTER_LOCAL_ADDR) { + QETH_DBF_TEXT3(0, trace, "irla"); + QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id); + } + if (*(PDU_ENCAPSULATION(buffer)) == + IPA_CMD_UNREGISTER_LOCAL_ADDR) { + QETH_DBF_TEXT3(0, trace, "irla"); + QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id); + } + PRINT_WARN("probably a problem on %s: received data is IPA, " + "but not a reply: command=0x%x\n", card->dev_name, + *(PDU_ENCAPSULATION(buffer) + 1)); + QETH_DBF_TEXT1(0, trace, "INRP"); + QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id); + goto out; + } + /* no probs */ +out: + if (problem) { + QETH_DBF_TEXT3(0, trace, "gcpr"); + QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "%2x%2x%4x", dstat, cstat, problem); + QETH_DBF_TEXT3(0, trace, dbf_text); + sprintf(dbf_text, "%8x", rqparam); + QETH_DBF_TEXT3(0, trace, dbf_text); + if (buffer) + QETH_DBF_HEX3(0, trace, &buffer, sizeof (void *)); + QETH_DBF_HEX3(0, trace, &irb, sizeof (void *)); + QETH_DBF_HEX3(0, trace, &sense, sizeof (void *)); + } + atomic_set(&card->problem, problem); + return problem; +} + +static void +qeth_issue_next_read(struct qeth_card *card) +{ + int result, result2; + char dbf_text[15]; + + QETH_DBF_TEXT5(0, trace, "isnr"); + QETH_DBF_TEXT5(0, trace, card->rdev->dev.bus_id); + + /* set up next read ccw */ + memcpy(&card->dma_stuff->read_ccw, READ_CCW, sizeof (struct ccw1)); + card->dma_stuff->read_ccw.count = QETH_BUFSIZE; + /* recbuf is not yet used by read channel program */ + card->dma_stuff->read_ccw.cda = QETH_GET_ADDR(card->dma_stuff->recbuf); + + /* + * we don't spin_lock_irqsave(get_ccwdev_lock(card->rdev),flags), as + * we are only called in the interrupt handler + */ + result = ccw_device_start(card->rdev, &card->dma_stuff->read_ccw, + MPC_SETUP_STATE, 0, 0); + if (result) { + qeth_delay_millis(QETH_WAIT_BEFORE_2ND_DOIO); + result2 = + ccw_device_start(card->rdev, &card->dma_stuff->read_ccw, + MPC_SETUP_STATE, 0, 0); + PRINT_WARN("read handler on device %s, read: ccw_device_start " + "returned %i, next try returns %i\n", + card->rdev->dev.bus_id, result, result2); + QETH_DBF_TEXT1(0, trace, "IsNR"); + QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "%04x%04x", (__s16) result, (__s16) result2); + QETH_DBF_TEXT1(0, trace, dbf_text); + } +} + +static int +qeth_is_to_recover(struct qeth_card *card, int problem) +{ + switch (problem) { + case PROBLEM_CARD_HAS_STARTLANED: + return 1; + case PROBLEM_RECEIVED_IDX_TERMINATE: + if (atomic_read(&card->in_recovery)) { + return 1; + } else { + qeth_set_dev_flag_norunning(card); + return 0; + } + case PROBLEM_ACTIVATE_CHECK_CONDITION: + return 1; + case PROBLEM_RESETTING_EVENT_INDICATOR: + return 1; + case PROBLEM_COMMAND_REJECT: + return 0; + case PROBLEM_ZERO_SENSE_DATA: + return 0; + case PROBLEM_GENERAL_CHECK: + return 1; + case PROBLEM_BAD_SIGA_RESULT: + return 1; + case PROBLEM_USER_TRIGGERED_RECOVERY: + return 1; + case PROBLEM_AFFE: + return 1; + case PROBLEM_MACHINE_CHECK: + return 1; + case PROBLEM_TX_TIMEOUT: + return 1; + } + return 0; +} + +static int +qeth_get_spare_buf(void) +{ + int i = 0; + char dbf_text[15]; + + while (i < sparebuffer_count) { + if (!atomic_compare_and_swap(SPAREBUF_FREE, SPAREBUF_USED, + &sparebufs[i].status)) { + sprintf(dbf_text, "gtspb%3x", i); + QETH_DBF_TEXT4(0, trace, dbf_text); + return i; + } + i++; + } + QETH_DBF_TEXT3(0, trace, "nospbuf"); + + return -1; +} + +static void +qeth_put_spare_buf(int no) +{ + char dbf_text[15]; + + sprintf(dbf_text, "ptspb%3x", no); + QETH_DBF_TEXT4(0, trace, dbf_text); + atomic_set(&sparebufs[no].status, SPAREBUF_FREE); +} + +static inline void +qeth_put_buffer_pool_entry(struct qeth_card *card, int entry_no) +{ + if (entry_no & SPAREBUF_MASK) + qeth_put_spare_buf(entry_no & (~SPAREBUF_MASK)); + else + card->inbound_buffer_pool_entry_used[entry_no] = BUFFER_UNUSED; +} + +static inline int +qeth_get_empty_buffer_pool_entry(struct qeth_card *card) +{ + int i; + int max_buffers = card->options.inbound_buffer_count; + + for (i = 0; i < max_buffers; i++) { + if (xchg((int *) &card->inbound_buffer_pool_entry_used[i], + BUFFER_USED) == BUFFER_UNUSED) + return i; + } + return -1; +} + +static inline void +qeth_clear_input_buffer(struct qeth_card *card, int bufno) +{ + struct qdio_buffer *buffer; + int i; + int elements, el_m_1; + char dbf_text[15]; + + QETH_DBF_TEXT6(0, trace, "clib"); + QETH_DBF_TEXT6(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "bufno%3x", bufno); + QETH_DBF_TEXT6(0, trace, dbf_text); + + buffer = &card->inbound_qdio_buffers[bufno]; + elements = BUFFER_MAX_ELEMENTS; + el_m_1 = elements - 1; + + for (i = 0; i < elements; i++) { + if (i == el_m_1) + buffer->element[i].flags = SBAL_FLAGS_LAST_ENTRY; + else + buffer->element[i].flags = 0; + + buffer->element[i].length = PAGE_SIZE; + buffer->element[i].addr = INBOUND_BUFFER_POS(card, bufno, i); + } +} + +static void +qeth_queue_input_buffer(struct qeth_card *card, int bufno, + unsigned int under_int) +{ + int count = 0, start = 0, stop = 0, pos; + int result; + int cnt1, cnt2 = 0; + int wrapped = 0; + int i; + int requeue_counter; + char dbf_text[15]; + int no; + + QETH_DBF_TEXT5(0, trace, "qibf"); + QETH_DBF_TEXT5(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "%4x%4x", under_int, bufno); + QETH_DBF_TEXT5(0, trace, dbf_text); + atomic_inc(&card->requeue_counter); + if (atomic_read(&card->requeue_counter) <= QETH_REQUEUE_THRESHOLD) + return; + + if (!spin_trylock(&card->requeue_input_lock)) { + QETH_DBF_TEXT5(0, trace, "qibl"); + QETH_DBF_TEXT5(0, trace, card->rdev->dev.bus_id); + return; + } + requeue_counter = atomic_read(&card->requeue_counter); + pos = atomic_read(&card->requeue_position); + + start = pos; + /* + * omit the situation with 128 simultaneously + * enqueued buffers, as then we can't benefit from PCI + * avoidance anymore -- therefore we let count not grow as + * big as requeue_counter + */ + while ((!atomic_read(&card->inbound_buffer_refcnt[pos])) && + (count < requeue_counter - 1)) { + no = qeth_get_empty_buffer_pool_entry(card); + if (no == -1) { + if (count) + break; + no = qeth_get_spare_buf(); + if (no == -1) { + PRINT_ERR("%s: no more input buffers " + "available! Inbound traffic could " + "be lost! Try increasing the bufcnt " + "parameter\n", + card->dev_name); + QETH_DBF_TEXT2(1, trace, "QINB"); + QETH_DBF_TEXT2(1, trace, card->rdev->dev.bus_id); + goto out; + } + card->inbound_buffer_entry_no[pos] = + no | SPAREBUF_MASK; + } + card->inbound_buffer_entry_no[pos] = no; + atomic_set(&card->inbound_buffer_refcnt[pos], 1); + count++; + if (pos >= QDIO_MAX_BUFFERS_PER_Q - 1) { + pos = 0; + wrapped = 1; + } else + pos++; + } + /* stop points to the position after the last element */ + stop = pos; + + QETH_DBF_TEXT3(0, trace, "qibi"); + QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "%4x", requeue_counter); + QETH_DBF_TEXT3(0, trace, dbf_text); + sprintf(dbf_text, "%4x%4x", start, stop); + QETH_DBF_TEXT3(0, trace, dbf_text); + + if (wrapped) { + cnt1 = QDIO_MAX_BUFFERS_PER_Q - start; + cnt2 = stop; + } else { + cnt1 = count; + /* cnt2 is already set to 0 */ + } + + atomic_sub(count, &card->requeue_counter); + /* + * this is the only place where card->requeue_position is + * written to, so that's ok (as it is in a lock) + */ + atomic_set(&card->requeue_position, + (atomic_read(&card->requeue_position) + count) + & (QDIO_MAX_BUFFERS_PER_Q - 1)); + + if (cnt1) { + for (i = start; i < start + cnt1; i++) { + qeth_clear_input_buffer(card, i); + } + result = do_QDIO(card->ddev, + QDIO_FLAG_SYNC_INPUT | under_int, + 0, start, cnt1, NULL); + if (result) { + PRINT_WARN("qeth_queue_input_buffer's " + "do_QDIO returnd %i (device %s)\n", + result, card->ddev->dev.bus_id); + QETH_DBF_TEXT1(0, trace, "QIDQ"); + QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "%4x%4x", result, requeue_counter); + QETH_DBF_TEXT1(0, trace, dbf_text); + sprintf(dbf_text, "%4x%4x", start, cnt1); + QETH_DBF_TEXT1(1, trace, dbf_text); + } + } + if (cnt2) { + for (i = 0; i < cnt2; i++) { + qeth_clear_input_buffer(card, i); + } + result = do_QDIO(card->ddev, + QDIO_FLAG_SYNC_INPUT | under_int, 0, + 0, cnt2, NULL); + if (result) { + PRINT_WARN("qeth_queue_input_buffer's " + "do_QDIO returnd %i (device %s)\n", + result, card->ddev->dev.bus_id); + QETH_DBF_TEXT1(0, trace, "QIDQ"); + QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "%4x%4x", result, requeue_counter); + QETH_DBF_TEXT1(0, trace, dbf_text); + sprintf(dbf_text, "%4x%4x", 0, cnt2); + QETH_DBF_TEXT1(1, trace, dbf_text); + } + } +out: + spin_unlock(&card->requeue_input_lock); + +} + +static inline struct sk_buff * +qeth_get_skb(unsigned int len) +{ + struct sk_buff *skb; + +#ifdef QETH_VLAN + skb = dev_alloc_skb(len + VLAN_HLEN); + if (skb) + skb_reserve(skb, VLAN_HLEN); +#else /* QETH_VLAN */ + skb = dev_alloc_skb(len); +#endif /* QETH_VLAN */ + return skb; +} + +static struct sk_buff * +qeth_get_next_skb(struct qeth_card *card, + int *element_ptr, int *pos_in_el_ptr, + void **hdr_ptr, struct qdio_buffer *buffer) +{ + int length; + char *data_ptr; + int step, len_togo, element, pos_in_el; + int curr_len; + int max_elements; + struct sk_buff *skb; + char dbf_text[15]; + + max_elements = BUFFER_MAX_ELEMENTS; + +#define SBALE_LEN(x) ((x>=max_elements)?0:(buffer->element[x].length)) +#define SBALE_ADDR(x) (buffer->element[x].addr) + + element = *element_ptr; + + if (element >= max_elements) { + PRINT_WARN("device %s: error in interpreting buffer (data " + "too long), %i elements.\n", + card->rdev->dev.bus_id, element); + QETH_DBF_TEXT0(0, trace, "IEDL"); + QETH_DBF_TEXT0(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "%4x%4x", *element_ptr, *pos_in_el_ptr); + QETH_DBF_TEXT0(1, trace, dbf_text); + QETH_DBF_HEX0(0, misc, buffer, QETH_DBF_MISC_LEN); + QETH_DBF_HEX0(0, misc, buffer + QETH_DBF_MISC_LEN, + QETH_DBF_MISC_LEN); + return NULL; + } + + pos_in_el = *pos_in_el_ptr; + + curr_len = SBALE_LEN(element); + if (curr_len > PAGE_SIZE) { + PRINT_WARN("device %s: bad element length in element %i: " + "0x%x\n", card->rdev->dev.bus_id, element, curr_len); + QETH_DBF_TEXT0(0, trace, "BELN"); + QETH_DBF_TEXT0(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "%4x", curr_len); + QETH_DBF_TEXT0(0, trace, dbf_text); + sprintf(dbf_text, "%4x%4x", *element_ptr, *pos_in_el_ptr); + QETH_DBF_TEXT0(1, trace, dbf_text); + QETH_DBF_HEX0(0, misc, buffer, QETH_DBF_MISC_LEN); + QETH_DBF_HEX0(0, misc, buffer + QETH_DBF_MISC_LEN, + QETH_DBF_MISC_LEN); + return NULL; + } + /* header fits in current element? */ + if (curr_len < pos_in_el + QETH_HEADER_SIZE) { + if (!pos_in_el) { + QETH_DBF_TEXT6(0, trace, "gnmh"); + QETH_DBF_TEXT6(0, trace, card->rdev->dev.bus_id); + return NULL; /* no more data in buffer */ + } + /* set hdr to next element */ + element++; + pos_in_el = 0; + curr_len = SBALE_LEN(element); + /* does it fit in there? */ + if (curr_len < QETH_HEADER_SIZE) { + QETH_DBF_TEXT6(0, trace, "gdnf"); + QETH_DBF_TEXT6(0, trace, card->rdev->dev.bus_id); + return NULL; + } + } + + *hdr_ptr = SBALE_ADDR(element) + pos_in_el; + + length = *(__u16 *) ((char *) (*hdr_ptr) + QETH_HEADER_LEN_POS); + + QETH_DBF_TEXT6(0, trace, "gdHd"); + QETH_DBF_TEXT6(0, trace, card->rdev->dev.bus_id); + QETH_DBF_HEX6(0, trace, hdr_ptr, sizeof (void *)); + + pos_in_el += QETH_HEADER_SIZE; + if (curr_len <= pos_in_el) { + /* switch to next element for data */ + pos_in_el = 0; + element++; + curr_len = SBALE_LEN(element); + if (!curr_len) { + PRINT_WARN("device %s: inb. buffer with more headers " + "than data areas (%i elements).\n", + card->rdev->dev.bus_id, element); + QETH_DBF_TEXT0(0, trace, "IEMH"); + QETH_DBF_TEXT0(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "%2x%2x%4x", element, *element_ptr, + *pos_in_el_ptr); + QETH_DBF_TEXT0(1, trace, dbf_text); + QETH_DBF_HEX0(0, misc, buffer, QETH_DBF_MISC_LEN); + QETH_DBF_HEX0(0, misc, buffer + QETH_DBF_MISC_LEN, + QETH_DBF_MISC_LEN); + return NULL; + } + } + + data_ptr = SBALE_ADDR(element) + pos_in_el; + + if (card->options.fake_ll == FAKE_LL) { + skb = qeth_get_skb(length + QETH_FAKE_LL_LEN); + if (!skb) + goto nomem; + skb_pull(skb, QETH_FAKE_LL_LEN); + if (!skb) { + dev_kfree_skb_irq(skb); + goto nomem; + } + } else { + skb = qeth_get_skb(length); + if (!skb) + goto nomem; + } + + if (card->easy_copy_cap) + memcpy(skb_put(skb, length), data_ptr, length); + + QETH_DBF_HEX6(0, trace, &data_ptr, sizeof (void *)); + QETH_DBF_HEX6(0, trace, &skb, sizeof (void *)); + + len_togo = length; + while (1) { + step = qeth_min(len_togo, curr_len - pos_in_el); + if (!step) { + PRINT_WARN("device %s: unexpected end of buffer, " + "length of element %i is 0. Discarding " + "packet.\n", + card->rdev->dev.bus_id, element); + QETH_DBF_TEXT0(0, trace, "IEUE"); + QETH_DBF_TEXT0(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "%2x%2x%4x", element, *element_ptr, + *pos_in_el_ptr); + QETH_DBF_TEXT0(0, trace, dbf_text); + sprintf(dbf_text, "%4x%4x", len_togo, step); + QETH_DBF_TEXT0(0, trace, dbf_text); + sprintf(dbf_text, "%4x%4x", curr_len, pos_in_el); + QETH_DBF_TEXT0(1, trace, dbf_text); + QETH_DBF_HEX0(0, misc, buffer, QETH_DBF_MISC_LEN); + QETH_DBF_HEX0(0, misc, buffer + QETH_DBF_MISC_LEN, + QETH_DBF_MISC_LEN); + dev_kfree_skb_irq(skb); + return NULL; + } + if (!card->easy_copy_cap) + memcpy(skb_put(skb, step), data_ptr, step); + len_togo -= step; + if (len_togo) { + pos_in_el = 0; + element++; + curr_len = SBALE_LEN(element); + data_ptr = SBALE_ADDR(element); + } else { +#ifdef QETH_INBOUND_PACKING_1_PACKET_PER_SBALE + element++; + /* we don't need to calculate curr_len */ + pos_in_el = 0; +#else /* QETH_INBOUND_PACKING_1_PACKET_PER_SBALE */ + pos_in_el += step; +#endif /* QETH_INBOUND_PACKING_1_PACKET_PER_SBALE */ + break; + } + } + + sprintf(dbf_text, "%4x%4x", element, pos_in_el); + QETH_DBF_TEXT6(0, trace, dbf_text); + + *element_ptr = element; + *pos_in_el_ptr = pos_in_el; + + return skb; + +nomem: + if (net_ratelimit()) { + PRINT_WARN("no memory for packet from %s\n", card->dev_name); + } + QETH_DBF_TEXT0(0, trace, "NOMM"); + QETH_DBF_TEXT0(0, trace, card->rdev->dev.bus_id); + return NULL; +} + +static inline void +__qeth_rebuild_skb_fake_ll(struct qeth_card *card, struct sk_buff *skb, + void *hdr_ptr) +{ + skb->mac.raw = skb->data - QETH_FAKE_LL_LEN; + switch (skb->pkt_type) { + case PACKET_MULTICAST: + switch (skb->protocol) { +#ifdef QETH_IPV6 + case __constant_htons(ETH_P_IPV6): + ndisc_mc_map((struct in6_addr *) + skb->data + QETH_FAKE_LL_V6_ADDR_POS, + skb->mac.raw + QETH_FAKE_LL_DEST_MAC_POS, + card->dev, 0); + break; +#endif /* QETH_IPV6 */ + case __constant_htons(ETH_P_IP): + qeth_get_mac_for_ipm(*(__u32*) + skb->data + QETH_FAKE_LL_V4_ADDR_POS, + skb->mac.raw + QETH_FAKE_LL_DEST_MAC_POS, + card->dev); + break; + default: + memcpy(skb->mac.raw + QETH_FAKE_LL_DEST_MAC_POS, + card->dev->dev_addr, QETH_FAKE_LL_ADDR_LEN); + } + break; + case PACKET_BROADCAST: + memset(skb->mac.raw + QETH_FAKE_LL_DEST_MAC_POS, + 0xff, QETH_FAKE_LL_ADDR_LEN); + break; + default: + memcpy(skb->mac.raw + QETH_FAKE_LL_DEST_MAC_POS, + card->dev->dev_addr, QETH_FAKE_LL_ADDR_LEN); + } + + if (*(__u8 *) (hdr_ptr + 11) & QETH_EXT_HEADER_SRC_MAC_ADDRESS) { + memcpy(skb->mac.raw + QETH_FAKE_LL_SRC_MAC_POS, + hdr_ptr + QETH_FAKE_LL_SRC_MAC_POS_IN_QDIO_HDR, + QETH_FAKE_LL_ADDR_LEN); + } else { + /* clear source MAC for security reasons */ + memset(skb->mac.raw + QETH_FAKE_LL_DEST_MAC_POS, + 0, QETH_FAKE_LL_ADDR_LEN); + } + memcpy(skb->mac.raw + QETH_FAKE_LL_PROT_POS, + &skb->protocol, QETH_FAKE_LL_PROT_LEN); + +} + +static inline void +__qeth_rebuild_skb_vlan(struct qeth_card *card, struct sk_buff *skb, + void *hdr_ptr) +{ +#ifdef QETH_VLAN + __u16 *vlan_tag; + + if (*(__u8 *) (hdr_ptr + 11) & QETH_EXT_HEADER_VLAN_FRAME) { + + vlan_tag = (__u16 *) skb_push(skb, VLAN_HLEN); + /* + if (*(__u8*)(hdr_ptr+11) & + QETH_EXT_HEADER_INCLUDE_VLAN_TAG) { + *vlan_tag = *(__u16*)(hdr_ptr+28); + *(vlan_tag+1)= *(__u16*)(hdr_ptr+30); + } else { + */ + *vlan_tag = *(__u16 *) (hdr_ptr + 12); + *(vlan_tag + 1) = skb->protocol; + /* + } + */ + skb->protocol = __constant_htons(ETH_P_8021Q); + } +#endif +} + +static inline void +__qeth_rebuild_skb(struct qeth_card *card, struct sk_buff *skb, void *hdr_ptr) +{ + char dbf_text[15]; + int version; + unsigned short cast_type; + + version = ((*(__u16 *) (hdr_ptr)) & (QETH_HEADER_IPV6)) ? 6 : 4; + skb->protocol = htons((version == 4) ? ETH_P_IP : + (version == 6) ? ETH_P_IPV6 : ETH_P_ALL); + cast_type = (*(__u16 *) (hdr_ptr)) & (QETH_CAST_FLAGS); + switch (cast_type) { + case QETH_CAST_UNICAST: + skb->pkt_type = PACKET_HOST; + break; + case QETH_CAST_MULTICAST: + skb->pkt_type = PACKET_MULTICAST; + break; + case QETH_CAST_BROADCAST: + skb->pkt_type = PACKET_BROADCAST; + break; + case QETH_CAST_ANYCAST: + case QETH_CAST_NOCAST: + QETH_DBF_TEXT2(0, trace, "ribf"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "castan%2x", cast_type); + QETH_DBF_TEXT2(1, trace, dbf_text); + skb->pkt_type = PACKET_HOST; + break; + default: + PRINT_WARN("adapter is using an unknown casting value " + "of 0x%x. Using unicasting instead.\n", + cast_type); + skb->pkt_type = PACKET_HOST; + QETH_DBF_TEXT2(0, trace, "ribf"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "castun%2x", cast_type); + QETH_DBF_TEXT2(1, trace, dbf_text); + } + + if (card->options.fake_ll == FAKE_LL) + __qeth_rebuild_skb_fake_ll(card, skb, hdr_ptr); + else + skb->mac.raw = skb->data; + + skb->ip_summed = card->options.checksum_type; + if (card->options.checksum_type == HW_CHECKSUMMING) { + /* do we have a checksummed packet? */ + if (*(__u8 *) (hdr_ptr + 11) & QETH_EXT_HEADER_CSUM_TRANSP_REQ) { + /* skb->ip_summed is set already */ + + /* + * vlan is not an issue here, it's still in + * the QDIO header, not pushed in the skb yet + */ + int ip_len = (skb->data[0] & 0x0f) << 2; + + if (*(__u8 *) (hdr_ptr + 11) & + QETH_EXT_HEADER_CSUM_TRANSP_FRAME_TYPE) { + /* get the UDP checksum */ + skb->csum = *(__u16 *) + (&skb->data[ip_len + + QETH_UDP_CSUM_OFFSET]); + } else { + /* get the TCP checksum */ + skb->csum = *(__u16 *) + (&skb->data[ip_len + + QETH_TCP_CSUM_OFFSET]); + } + } else { + /* make the stack check it */ + skb->ip_summed = SW_CHECKSUMMING; + } + } + __qeth_rebuild_skb_vlan(card, skb, hdr_ptr); +} + +static void +qeth_read_in_buffer(struct qeth_card *card, int buffer_no) +{ + struct sk_buff *skb; + void *hdr_ptr; + int element = 0, pos_in_el = 0; + struct qdio_buffer *buffer; + int i; + int max_elements; + char dbf_text[15]; + struct net_device *dev; + + dev = card->dev; + max_elements = BUFFER_MAX_ELEMENTS; + + buffer = &card->inbound_qdio_buffers[buffer_no]; + + /* inform about errors */ + if (buffer->element[15].flags & 0xff) { + PRINT_WARN("on device %s: incoming SBALF 15 on buffer " + "0x%x are 0x%x\n", + card->rdev->dev.bus_id, buffer_no, + buffer->element[15].flags & 0xff); + sprintf(dbf_text, "SF%s%2x%2x", + card->rdev->dev.bus_id, buffer_no, + buffer->element[15].flags & 0xff); + QETH_DBF_HEX1(1, trace, dbf_text, QETH_DBF_TRACE_LEN); + } + + for (i = 0; i < max_elements - 1; i++) { + if (buffer->element[i].flags & SBAL_FLAGS_LAST_ENTRY) { + buffer->element[i + 1].length = 0; + break; + } + } +#ifdef QETH_PERFORMANCE_STATS + card->perf_stats.bufs_rec++; +#endif /* QETH_PERFORMANCE_STATS */ + + sprintf(dbf_text, "ribX%s", card->rdev->dev.bus_id); + dbf_text[3] = buffer_no; + QETH_DBF_HEX6(0, trace, dbf_text, QETH_DBF_TRACE_LEN); + + while ((skb = qeth_get_next_skb(card, &element, &pos_in_el, + &hdr_ptr, buffer))) { + +#ifdef QETH_PERFORMANCE_STATS + card->perf_stats.skbs_rec++; +#endif /* QETH_PERFORMANCE_STATS */ + + if (skb) { + skb->dev = dev; + +#ifdef QETH_IPV6 + if ((*(__u16 *) (hdr_ptr)) & (QETH_HEADER_PASSTHRU)) + skb->protocol = card->type_trans(skb, dev); + else +#endif /* QETH_IPV6 */ + __qeth_rebuild_skb(card, skb, hdr_ptr); + +#ifdef QETH_PERFORMANCE_STATS + card->perf_stats.inbound_time += + NOW - card->perf_stats.inbound_start_time; + card->perf_stats.inbound_cnt++; +#endif /* QETH_PERFORMANCE_STATS */ + + QETH_DBF_TEXT6(0, trace, "rxpk"); + QETH_DBF_TEXT6(0, trace, card->rdev->dev.bus_id); + + netif_rx(skb); + dev->last_rx = jiffies; + card->stats->rx_packets++; + card->stats->rx_bytes += skb->len; + } else { + PRINT_WARN("%s: dropped packet, no buffers " + "available.\n", card->dev_name); + QETH_DBF_TEXT2(1, trace, "DROP"); + QETH_DBF_TEXT2(1, trace, card->rdev->dev.bus_id); + card->stats->rx_dropped++; + } + } + atomic_set(&card->inbound_buffer_refcnt[buffer_no], 0); + qeth_put_buffer_pool_entry(card, + card->inbound_buffer_entry_no[buffer_no]); +} + +static inline void +__qeth_fill_header_add_vlan(struct qeth_hdr *hdr, struct sk_buff *skb, + int version) +{ +#ifdef QETH_VLAN + struct qeth_card *card; + + /* before we're going to overwrite this location with next hop ip */ + card = (struct qeth_card *) skb->dev->priv; + if ((card->vlangrp != NULL) && + vlan_tx_tag_present(skb) && (version == 4)) { + hdr->ext_flags = QETH_EXT_HEADER_VLAN_FRAME; + hdr->vlan_id = vlan_tx_tag_get(skb); + } +#endif +} + +static __u8 +__qeth_get_flags_v4(int multicast) +{ + if (multicast == RTN_MULTICAST) + return QETH_CAST_MULTICAST; + if (multicast == RTN_BROADCAST) + return QETH_CAST_BROADCAST; + return QETH_CAST_UNICAST; +} + +static __u8 +__qeth_get_flags_v6(int multicast) +{ + if (multicast == RTN_MULTICAST) + return QETH_CAST_MULTICAST | + QETH_HEADER_PASSTHRU | QETH_HEADER_IPV6; + if (multicast == RTN_ANYCAST) + return QETH_CAST_ANYCAST | + QETH_HEADER_PASSTHRU | QETH_HEADER_IPV6; + if (multicast == RTN_BROADCAST) + return QETH_CAST_BROADCAST | + QETH_HEADER_PASSTHRU | QETH_HEADER_IPV6; + return QETH_CAST_UNICAST | +#ifdef QETH_IPV6 + QETH_HEADER_PASSTHRU | +#endif /* QETH_IPV6 */ + QETH_HEADER_IPV6; +} + +static void +qeth_fill_header(struct qeth_hdr *hdr, struct sk_buff *skb, + int version, int multicast) +{ + char dbf_text[15]; + + hdr->id = 1; + hdr->ext_flags = 0; + + __qeth_fill_header_add_vlan(hdr, skb, version); + + hdr->length = skb->len - QETH_HEADER_SIZE; /* as skb->len includes + the header now */ + + /* yes, I know this is doubled code, but a small little bit + faster maybe */ + if (version == 4) { /* IPv4 */ + hdr->flags = __qeth_get_flags_v4(multicast); + *((__u32 *) (&hdr->dest_addr[0])) = 0; + *((__u32 *) (&hdr->dest_addr[4])) = 0; + *((__u32 *) (&hdr->dest_addr[8])) = 0; + if ((skb->dst) && (skb->dst->neighbour)) { + *((__u32 *) (&hdr->dest_addr[12])) = + *((__u32 *) skb->dst->neighbour->primary_key); + } else { + /* fill in destination address used in ip header */ + *((__u32 *) (&hdr->dest_addr[12])) = skb->nh.iph->daddr; + } + } else if (version == 6) { /* IPv6 or passthru */ + hdr->flags = __qeth_get_flags_v6(multicast); + if ((skb->dst) && (skb->dst->neighbour)) { + memcpy(hdr->dest_addr, + skb->dst->neighbour->primary_key, 16); + } else { + /* fill in destination address used in ip header */ + memcpy(hdr->dest_addr, &skb->nh.ipv6h->daddr, 16); + } + } else { /* passthrough */ + if (!memcmp(skb->data + QETH_HEADER_SIZE, + skb->dev->broadcast, 6)) { /* broadcast? */ + hdr->flags = QETH_CAST_BROADCAST | QETH_HEADER_PASSTHRU; + } else { + hdr->flags = QETH_CAST_UNICAST | QETH_HEADER_PASSTHRU; + } + } + sprintf(dbf_text, "filhdr%2x", version); + QETH_DBF_TEXT6(0, trace, dbf_text); + sprintf(dbf_text, "%2x", multicast); + QETH_DBF_TEXT6(0, trace, dbf_text); + QETH_DBF_HEX6(0, trace, &skb, sizeof (void *)); + QETH_DBF_HEX6(0, trace, &skb->data, sizeof (void *)); + QETH_DBF_HEX6(0, misc, hdr, __max(QETH_HEADER_SIZE, QETH_DBF_MISC_LEN)); + QETH_DBF_HEX6(0, data, skb->data, + __max(QETH_DBF_DATA_LEN, QETH_DBF_DATA_LEN)); +} + +static int inline +qeth_fill_buffer(struct qdio_buffer *buffer, char *dataptr, + int length, int element) +{ + int length_here; + int first_lap = 1; + char dbf_text[15]; + int first_element = element; + + while (length > 0) { + /* length_here is the remaining amount of data in this page */ + length_here = + PAGE_SIZE - ((unsigned long) dataptr & (PAGE_SIZE - 1)); + if (length < length_here) + length_here = length; + + buffer->element[element].addr = dataptr; + buffer->element[element].length = length_here; + length -= length_here; + if (!length) { + if (first_lap) { + buffer->element[element].flags = 0; + } else { + buffer->element[element].flags = + SBAL_FLAGS_LAST_FRAG; + } + } else { + if (first_lap) { + buffer->element[element].flags = + SBAL_FLAGS_FIRST_FRAG; + } else { + buffer->element[element].flags = + SBAL_FLAGS_MIDDLE_FRAG; + } + } + dataptr = dataptr + length_here; + element++; + if (element > QDIO_MAX_ELEMENTS_PER_BUFFER) { + PRINT_ERR("qeth_fill_buffer: IP packet too big!\n"); + QETH_DBF_TEXT1(0, trace, "IPpktobg"); + QETH_DBF_HEX1(1, trace, &dataptr, sizeof (void *)); + buffer->element[first_element].length = 0; + break; + } + first_lap = 0; + } + sprintf(dbf_text, "filbuf%2x", element); + QETH_DBF_TEXT6(0, trace, dbf_text); + QETH_DBF_HEX3(0, misc, buffer, QETH_DBF_MISC_LEN); + QETH_DBF_HEX3(0, misc, buffer + QETH_DBF_MISC_LEN, QETH_DBF_MISC_LEN); + + return element; +} + +static void +qeth_flush_packed_packets(struct qeth_card *card, int queue, int under_int) +{ + struct qdio_buffer *buffer; + int result; + int position; + int position_for_do_qdio; + char dbf_text[15]; + int last_pci; + + position = card->outbound_first_free_buffer[queue]; + /* can happen, when in the time between deciding to pack and sending + the next packet the lower mark was reached: */ + if (!card->outbound_ringbuffer[queue]->ringbuf_element[position]. + next_element_to_fill) + return; + + buffer = &card->outbound_ringbuffer[queue]->buffer[position]; + buffer->element[card->outbound_ringbuffer[queue]-> + ringbuf_element[position]. + next_element_to_fill - 1].flags |= + SBAL_FLAGS_LAST_ENTRY; + + card->dev->trans_start = jiffies; + +#ifdef QETH_PERFORMANCE_STATS + if (card->outbound_buffer_send_state[queue][position] == + SEND_STATE_DONT_PACK) { + card->perf_stats.bufs_sent_dont_pack++; + } else if (card->outbound_buffer_send_state[queue][position] == + SEND_STATE_PACK) { + card->perf_stats.bufs_sent_pack++; + } + card->perf_stats.bufs_sent++; +#endif /* QETH_PERFORMANCE_STATS */ + + position_for_do_qdio = position; + + position = (position + 1) & (QDIO_MAX_BUFFERS_PER_Q - 1); + card->outbound_first_free_buffer[queue] = position; + + card->outbound_bytes_in_buffer[queue] = 0; + /* we can override that, as we have at most 127 buffers enqueued */ + card->outbound_ringbuffer[queue]->ringbuf_element[position]. + next_element_to_fill = 0; + + atomic_inc(&card->outbound_used_buffers[queue]); + + QETH_DBF_TEXT5(0, trace, "flsp"); + QETH_DBF_TEXT5(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "%4x%2x%2x", position_for_do_qdio, under_int, queue); + QETH_DBF_TEXT5(0, trace, dbf_text); + QETH_DBF_HEX5(0, misc, buffer, QETH_DBF_MISC_LEN); + QETH_DBF_HEX5(0, misc, buffer + QETH_DBF_MISC_LEN, QETH_DBF_MISC_LEN); + + /* + * we always set the outbound pci flag, don't care, whether the + * adapter honors it or not + */ + switch (card->send_state[queue]) { + case SEND_STATE_DONT_PACK: + if (atomic_read(&card->outbound_used_buffers[queue]) + < HIGH_WATERMARK_PACK - WATERMARK_FUZZ) + break; + /* set the PCI bit */ + card->outbound_ringbuffer[queue]-> + buffer[position_for_do_qdio].element[0].flags |= 0x40; + atomic_set(&card->last_pci_pos[queue], position_for_do_qdio); + break; + case SEND_STATE_PACK: + last_pci = atomic_read(&card->last_pci_pos[queue]); + if (position_for_do_qdio < last_pci) + last_pci -= QDIO_MAX_BUFFERS_PER_Q; + /* so: + * last_pci is the position of the last pci we've set + * position_for_do_qdio is the position we will send out now + * outbound_used_buffers is the number of buffers used (means + * all buffers hydra has, inclusive position_for_do_qdio) + * + * we have to request a pci, if we have got the buffer of the + * last_pci position back. + * + * position_for_do_qdio-outbound_used_buffers is the newest + * buffer that we got back from hydra + * + * if this is greater or equal than the last_pci position, + * we should request a pci, as no pci request is + * outstanding anymore + */ + if (position_for_do_qdio - + atomic_read(&card->outbound_used_buffers[queue]) >= + last_pci) { + /* set the PCI bit */ + card->outbound_ringbuffer[queue]-> + buffer[position_for_do_qdio]. + element[0].flags |= 0x40; + atomic_set(&card->last_pci_pos[queue], + position_for_do_qdio); + } + } + + /* + * this has to be at the end, otherwise a buffer could be flushed + * twice (see comment in qeth_do_send_packet) + */ + result = do_QDIO(card->ddev, QDIO_FLAG_SYNC_OUTPUT | under_int, queue, + position_for_do_qdio, 1, NULL); + + if (result) { + PRINT_WARN("Outbound do_QDIO returned %i " + "(device %s)\n", result, card->ddev->dev.bus_id); + QETH_DBF_TEXT5(0, trace, "FLSP"); + QETH_DBF_TEXT5(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "odoQ%4x", result); + QETH_DBF_TEXT5(0, trace, dbf_text); + sprintf(dbf_text, "%4x%2x%2x", position_for_do_qdio, + under_int, queue); + QETH_DBF_TEXT5(0, trace, dbf_text); + QETH_DBF_HEX5(0, misc, buffer, QETH_DBF_MISC_LEN); + QETH_DBF_HEX5(0, misc, buffer + QETH_DBF_MISC_LEN, + QETH_DBF_MISC_LEN); + } +} + +#define ERROR_NONE 0 +#define ERROR_RETRY 1 +#define ERROR_LINK_FAILURE 2 +#define ERROR_KICK_THAT_PUPPY 3 +static inline int +qeth_determine_send_error(int cc, int qdio_error, int sbalf15) +{ + char dbf_text[15]; + + switch (cc & 3) { + case 0: + if (qdio_error) + return ERROR_LINK_FAILURE; + return ERROR_NONE; + case 2: + if (cc & QDIO_SIGA_ERROR_B_BIT_SET) { + QETH_DBF_TEXT3(0, trace, "sigacc2b"); + return ERROR_KICK_THAT_PUPPY; + } + if (qeth_sbalf15_in_retrieable_range(sbalf15)) + return ERROR_RETRY; + return ERROR_LINK_FAILURE; + /* look at qdio_error and sbalf 15 */ + case 1: + PRINT_WARN("siga returned cc 1! cc=0x%x, " + "qdio_error=0x%x, sbalf15=0x%x\n", + cc, qdio_error, sbalf15); + + QETH_DBF_TEXT3(0, trace, "siga-cc1"); + QETH_DBF_TEXT2(0, qerr, "siga-cc1"); + sprintf(dbf_text, "%1x%2x%2x", cc, qdio_error, sbalf15); + QETH_DBF_TEXT3(0, trace, dbf_text); + QETH_DBF_TEXT2(0, qerr, dbf_text); + return ERROR_LINK_FAILURE; + case 3: + QETH_DBF_TEXT3(0, trace, "siga-cc3"); + return ERROR_KICK_THAT_PUPPY; + } + return ERROR_LINK_FAILURE; /* should never happen */ +} + +static void +qeth_free_buffer(struct qeth_card *card, int queue, int bufno, + int qdio_error, int siga_error) +{ + struct sk_buff *skb; + int error; + int retries; + int sbalf15; + char dbf_text[15]; + struct qdio_buffer *buffer; + + switch (card->outbound_buffer_send_state[queue][bufno]) { + case SEND_STATE_DONT_PACK: /* fallthrough */ + case SEND_STATE_PACK: + QETH_DBF_TEXT5(0, trace, "frbf"); + QETH_DBF_TEXT5(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "%2x%2x%4x", queue, bufno, + card->outbound_buffer_send_state[queue][bufno]); + QETH_DBF_TEXT5(0, trace, dbf_text); + + buffer = &card->outbound_ringbuffer[queue]->buffer[bufno]; + sbalf15 = buffer->element[15].flags & 0xff; + error = + qeth_determine_send_error(siga_error, qdio_error, sbalf15); + if (error == ERROR_KICK_THAT_PUPPY) { + sprintf(dbf_text, "KP%s%2x", + card->rdev->dev.bus_id, queue); + QETH_DBF_TEXT2(0, trace, dbf_text); + QETH_DBF_TEXT2(0, qerr, dbf_text); + QETH_DBF_TEXT2(1, setup, dbf_text); + sprintf(dbf_text, "%2x%2x%2x%2x", bufno, + siga_error, qdio_error, sbalf15); + QETH_DBF_TEXT2(1, trace, dbf_text); + QETH_DBF_TEXT2(1, qerr, dbf_text); + PRINT_ERR("Outbound queue x%x on device %s (%s); " + "errs: siga: x%x, qdio: x%x, flags15: " + "x%x. The device will be taken down.\n", + queue, card->rdev->dev.bus_id, card->dev_name, + siga_error, qdio_error, sbalf15); + netif_stop_queue(card->dev); + qeth_set_dev_flag_norunning(card); + atomic_set(&card->problem, PROBLEM_BAD_SIGA_RESULT); + qeth_schedule_recovery(card); + } else if (error == ERROR_RETRY) { + /* analyze, how many retries we did so far */ + retries = card->send_retries[queue][bufno]; + + sprintf(dbf_text, "Rt%s%2x", + card->rdev->dev.bus_id, queue); + QETH_DBF_TEXT4(0, trace, dbf_text); + sprintf(dbf_text, "b%2x:%2x%2x", bufno, + sbalf15, retries); + QETH_DBF_TEXT4(0, trace, dbf_text); + + if (++retries > SEND_RETRIES_ALLOWED) { + error = ERROR_LINK_FAILURE; + QETH_DBF_TEXT4(1, trace, "ndegelnd"); + } + /* else error stays RETRY for the switch statemnet */ + } else if (error == ERROR_LINK_FAILURE) { + /* we don't want to log failures resulting from + * too many retries */ + QETH_DBF_TEXT3(1, trace, "Fail"); + QETH_DBF_TEXT3(1, trace, card->rdev->dev.bus_id); + QETH_DBF_HEX3(0, misc, buffer, QETH_DBF_MISC_LEN); + QETH_DBF_HEX3(0, misc, buffer + QETH_DBF_MISC_LEN, + QETH_DBF_MISC_LEN); + } + + while ((skb = skb_dequeue(&card->outbound_ringbuffer[queue]-> + ringbuf_element[bufno].skb_list))) { + switch (error) { + case ERROR_NONE: + atomic_dec(&skb->users); + dev_kfree_skb_irq(skb); + break; + case ERROR_RETRY: + QETH_DBF_TEXT3(0, qerr, "RETRY!!!"); + QETH_DBF_TEXT4(0, trace, "RETRY!!!"); + atomic_dec(&skb->users); + /* retry packet async (quickly) ... */ + atomic_dec(&skb->users); + dev_kfree_skb_irq(skb); + break; + case ERROR_LINK_FAILURE: + case ERROR_KICK_THAT_PUPPY: + QETH_DBF_TEXT4(0, trace, "endeglnd"); + dst_link_failure(skb); + atomic_dec(&skb->users); + dev_kfree_skb_irq(skb); + break; + } + } + break; + default: + PRINT_WARN("oops... wrong send_state on %s. " + "shouldn't happen " + "(line %i). q=%i, bufno=x%x, state=%i\n", + card->dev_name, __LINE__, queue, bufno, + card->outbound_buffer_send_state[queue][bufno]); + QETH_DBF_TEXT0(1, trace, "UPSf"); + QETH_DBF_TEXT0(1, qerr, "UPSf"); + QETH_DBF_TEXT0(1, trace, card->rdev->dev.bus_id); + QETH_DBF_TEXT0(1, qerr, card->rdev->dev.bus_id); + sprintf(dbf_text, "%2x%2x%4x", queue, bufno, + card->outbound_buffer_send_state[queue][bufno]); + QETH_DBF_TEXT0(1, trace, dbf_text); + QETH_DBF_TEXT0(1, qerr, dbf_text); + } + card->outbound_buffer_send_state[queue][bufno] = SEND_STATE_INACTIVE; + card->send_retries[queue][bufno] = 0; +} + +static void +qeth_free_all_skbs(struct qeth_card *card) +{ + int q, b; + + for (q = 0; q < card->no_queues; q++) + for (b = 0; b < QDIO_MAX_BUFFERS_PER_Q; b++) + if (card->outbound_buffer_send_state[q][b] != + SEND_STATE_INACTIVE) + qeth_free_buffer(card, q, b, 0, 0); +} + +static inline void +qeth_flush_buffer(struct qeth_card *card, int queue, int under_int) +{ + char dbf_text[15]; + QETH_DBF_TEXT5(0, trace, "flsb"); + QETH_DBF_TEXT5(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "%2x%2x%2x", queue, under_int, + card->outbound_buffer_send_state[queue] + [card->outbound_first_free_buffer[queue]]); + QETH_DBF_TEXT5(0, trace, dbf_text); + + switch (card->outbound_buffer_send_state[queue] + [card->outbound_first_free_buffer[queue]]) { + case SEND_STATE_DONT_PACK: + break; + case SEND_STATE_PACK: + qeth_flush_packed_packets(card, queue, under_int); + break; + default: + break; + } +} + +#ifdef QETH_VLAN +void +qeth_insert_ipv6_vlan_tag(struct sk_buff *__skb) +{ + + /* Move the mac addresses to the beginning of the new header. + * We are using three memcpys instead of one memmove to save cycles. + */ +#define TMP_CPYSIZE 4 + __u16 *tag; + tag = (__u16 *) skb_push(__skb, VLAN_HLEN); + memcpy(__skb->data, __skb->data + TMP_CPYSIZE, TMP_CPYSIZE); + memcpy(__skb->data + TMP_CPYSIZE, + __skb->data + (2 * TMP_CPYSIZE), TMP_CPYSIZE); + memcpy(__skb->data + (2 * TMP_CPYSIZE), + __skb->data + (3 * TMP_CPYSIZE), TMP_CPYSIZE); + tag = (__u16 *) (__skb->data + (3 * TMP_CPYSIZE)); + + /*first two bytes = ETH_P_8021Q (0x8100) + *second two bytes = VLANID + */ + + *tag = __constant_htons(ETH_P_8021Q); + *(tag + 1) = vlan_tx_tag_get(__skb); + *(tag + 1) = htons(*(tag + 1)); +#undef TMP_CPYSIZE +} +#endif + +static inline void +__qeth_add_vlan_tag(struct qeth_card *card, struct sk_buff *skb, int version) +{ +#ifdef QETH_VLAN + if ((card->vlangrp != NULL) && + vlan_tx_tag_present(skb) && (version == 6)) { + qeth_insert_ipv6_vlan_tag(skb); + } +#endif +} + +static void +qeth_send_packet_fast(struct qeth_card *card, struct sk_buff *skb, + struct net_device *dev, + int queue, int version, int multicast) +{ + struct qeth_ringbuffer_element *mybuffer; + int position; + struct qeth_hdr *hdr; + char *dataptr; + char dbf_text[15]; + struct sk_buff *nskb; + + position = card->outbound_first_free_buffer[queue]; + + card->outbound_buffer_send_state[queue][position] = + SEND_STATE_DONT_PACK; + + mybuffer = &card->outbound_ringbuffer[queue]->ringbuf_element[position]; + if (skb_headroom(skb) < QETH_HEADER_SIZE) { + if ((version) && (!card->realloc_message)) { + card->realloc_message = 1; + PRINT_WARN("%s: not enough headroom in skb. " + "Increasing the " + "add_hhlen parameter by %i may help.\n", + card->dev_name, + QETH_HEADER_SIZE - skb_headroom(skb)); + } + PRINT_STUPID("%s: not enough headroom in skb (missing: %i)\n", + card->dev_name, + QETH_HEADER_SIZE - skb_headroom(skb)); + QETH_DBF_TEXT3(0, trace, "NHRf"); + QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "%2x%2x%2x%2x", skb_headroom(skb), + version, multicast, queue); + QETH_DBF_TEXT3(0, trace, dbf_text); + QETH_DBF_HEX3(0, trace, &skb->head, sizeof (void *)); + QETH_DBF_HEX3(0, trace, &skb->data, sizeof (void *)); + nskb = skb_realloc_headroom(skb, QETH_HEADER_SIZE); + if (!nskb) { + PRINT_WARN("%s: could not realloc headroom\n", + card->dev_name); + QETH_DBF_TEXT2(0, trace, "CNRf"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + dev_kfree_skb_irq(skb); + return; + } + dev_kfree_skb_irq(skb); + skb = nskb; + } + __qeth_add_vlan_tag(card, skb, version); + hdr = (struct qeth_hdr *) (skb_push(skb, QETH_HEADER_SIZE)); + /* + * sanity check, the Linux memory allocation scheme should + * never present us cases like this one (the 32bytes header plus + * the first 40 bytes of the paket cross a 4k boundary) + */ + dataptr = (char *) hdr; + if ((((unsigned long) dataptr) & (~(PAGE_SIZE - 1))) != + (((unsigned long) dataptr + QETH_HEADER_SIZE + + QETH_IP_HEADER_SIZE) & (~(PAGE_SIZE - 1)))) { + PRINT_ERR("%s: packet misaligned -- the first %i bytes " + "are not in the same page. Discarding packet!\n", + card->dev_name, + QETH_HEADER_SIZE + QETH_IP_HEADER_SIZE); + PRINT_ERR("head=%p, data=%p\n", skb->head, skb->data); + QETH_DBF_TEXT1(0, trace, "PMAf"); + QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "%2x%2x%2x%2x", skb_headroom(skb), + version, multicast, queue); + QETH_DBF_TEXT1(0, trace, dbf_text); + QETH_DBF_HEX1(0, trace, &skb->head, sizeof (void *)); + QETH_DBF_HEX1(1, trace, &skb->data, sizeof (void *)); + dev_kfree_skb_irq(skb); + return; + } + + atomic_inc(&skb->users); + skb_queue_tail(&mybuffer->skb_list, skb); + qeth_fill_header(hdr, skb, version, multicast); + /* we need to write to next_element_to_fill as + qeth_flush_packed_packets checks it */ + card->outbound_ringbuffer[queue]->ringbuf_element[position]. + next_element_to_fill = + qeth_fill_buffer(&card->outbound_ringbuffer[queue]-> + buffer[position], (char *) hdr, skb->len, 0); + +#ifdef QETH_PERFORMANCE_STATS + card->perf_stats.skbs_sent_dont_pack++; +#endif /* QETH_PERFORMANCE_STATS */ + + qeth_flush_packed_packets(card, queue, 0); +} + +/* no checks, if all elements are used, as then we would not be here (at most + 127 buffers are enqueued) */ +static void +qeth_send_packet_packed(struct qeth_card *card, struct sk_buff *skb, + struct net_device *dev, + int queue, int version, int multicast) +{ + struct qeth_ringbuffer_element *mybuffer; + int elements_needed; + int element_to_fill; + int buffer_no; + int length; + char *dataptr; + struct qeth_hdr *hdr; + char dbf_text[15]; + struct sk_buff *nskb; + + /* sanity check, dev->hard_header_len should prevent this */ + if (skb_headroom(skb) < QETH_HEADER_SIZE) { + if ((version) && (!card->realloc_message)) { + card->realloc_message = 1; + PRINT_WARN("%s: not enough headroom in skb. " + "Try increasing the " + "add_hhlen parameter by %i.\n", + card->dev_name, + QETH_HEADER_SIZE - skb_headroom(skb)); + } + PRINT_STUPID("%s: not enough headroom in skb (missing: %i)\n", + card->dev_name, + QETH_HEADER_SIZE - skb_headroom(skb)); + QETH_DBF_TEXT3(0, trace, "NHRp"); + QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "%2x%2x%2x%2x", skb_headroom(skb), + version, multicast, queue); + QETH_DBF_TEXT3(0, trace, dbf_text); + QETH_DBF_HEX3(0, trace, &skb->head, sizeof (void *)); + QETH_DBF_HEX3(0, trace, &skb->data, sizeof (void *)); + nskb = skb_realloc_headroom(skb, QETH_HEADER_SIZE); + if (!nskb) { + PRINT_WARN("%s: could not realloc headroom\n", + card->dev_name); + QETH_DBF_TEXT2(0, trace, "CNRp"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + dev_kfree_skb_irq(skb); + return; + } + dev_kfree_skb_irq(skb); + skb = nskb; + } + __qeth_add_vlan_tag(card, skb, version); + hdr = (struct qeth_hdr *) (skb_push(skb, QETH_HEADER_SIZE)); + + length = skb->len; + + /* + * sanity check, the Linux memory allocation scheme should + * never present us cases like this one (the 32bytes header plus + * the first 40 bytes of the paket cross a 4k boundary) + */ + dataptr = (char *) hdr; + if ((((unsigned long) dataptr) & (~(PAGE_SIZE - 1))) != + (((unsigned long) dataptr + QETH_HEADER_SIZE + + QETH_IP_HEADER_SIZE) & (~(PAGE_SIZE - 1)))) { + PRINT_ERR("%s: packet misaligned -- the first %i bytes " + "are not in the same page. Discarding packet!\n", + card->dev_name, + QETH_HEADER_SIZE + QETH_IP_HEADER_SIZE); + QETH_DBF_TEXT1(0, trace, "PMAp"); + QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "%2x%2x%2x%2x", skb_headroom(skb), + version, multicast, queue); + QETH_DBF_TEXT1(0, trace, dbf_text); + QETH_DBF_HEX1(0, trace, &skb->head, sizeof (void *)); + QETH_DBF_HEX1(1, trace, &skb->data, sizeof (void *)); + dev_kfree_skb_irq(skb); + return; + } + + buffer_no = card->outbound_first_free_buffer[queue]; + + element_to_fill = card->outbound_ringbuffer[queue]-> + ringbuf_element[buffer_no].next_element_to_fill; + + elements_needed = 1 + (((((unsigned long) dataptr) & (PAGE_SIZE - 1)) + + length) >> PAGE_SHIFT); + if ((elements_needed > (QDIO_MAX_ELEMENTS_PER_BUFFER - element_to_fill)) + || + ((elements_needed == + (QDIO_MAX_ELEMENTS_PER_BUFFER - element_to_fill)) + && ((element_to_fill >> PAGE_SHIFT) == + card->outbound_bytes_in_buffer[queue]))) { + qeth_flush_packed_packets(card, queue, 0); + element_to_fill = 0; + card->outbound_bytes_in_buffer[queue] = 0; + buffer_no = (buffer_no + 1) & (QDIO_MAX_BUFFERS_PER_Q - 1); + } + + if (!element_to_fill) + card->outbound_buffer_send_state[queue][buffer_no] + = SEND_STATE_PACK; + +#ifdef QETH_PERFORMANCE_STATS + card->perf_stats.skbs_sent_pack++; +#endif /* QETH_PERFORMANCE_STATS */ + + mybuffer = + &card->outbound_ringbuffer[queue]->ringbuf_element[buffer_no]; + atomic_inc(&skb->users); + skb_queue_tail(&mybuffer->skb_list, skb); + qeth_fill_header(hdr, skb, version, multicast); + card->outbound_bytes_in_buffer[queue] += length + QETH_HEADER_SIZE; + card->outbound_ringbuffer[queue]->ringbuf_element[buffer_no]. + next_element_to_fill = + qeth_fill_buffer(&card->outbound_ringbuffer[queue]-> + buffer[buffer_no], + dataptr, length, element_to_fill); +} + +static void +qeth_alloc_spare_bufs(void) +{ + int i; + int dont_alloc_more = 0; + char dbf_text[15]; + + sparebuffer_count = 0; + for (i = 0; i < qeth_sparebufs; i++) { + if (!dont_alloc_more) { + sparebufs[i].buf = (char *) + kmalloc(DEFAULT_BUFFER_SIZE, GFP_KERNEL); + if (sparebufs[i].buf) + sparebuffer_count++; + else + dont_alloc_more = 1; + } + atomic_set(&sparebufs[i].status, (dont_alloc_more) ? + SPAREBUF_UNAVAIL : SPAREBUF_FREE); + } + sprintf(dbf_text, "alspb%3x", sparebuffer_count); + QETH_DBF_TEXT2(0, trace, dbf_text); + + PRINT_INFO("allocated %i spare buffers\n", sparebuffer_count); +} + +static void +qeth_free_all_spare_bufs(void) +{ + int i; + + QETH_DBF_TEXT2(0, trace, "frealspb"); + + for (i = 0; i < qeth_sparebufs; i++) + if (atomic_read(&sparebufs[i].status) != SPAREBUF_UNAVAIL) { + kfree(sparebufs[i].buf); + atomic_set(&sparebufs[i].status, SPAREBUF_UNAVAIL); + } +} + +static __inline__ int +atomic_return_sub(int i, atomic_t * v) +{ + int old_val, new_val; + __CS_LOOP(old_val, new_val, v, i, "sr"); + return old_val; +} + +static inline void +__qeth_dump_packet_info(struct qeth_card *card, int version, int multicast, + int queue) +{ + char dbf_text[15]; + + QETH_DBF_TEXT6(0, trace, "dsp:"); + QETH_DBF_TEXT6(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "%c %c%4x", + (version == 4) ? '4' : ((version == 6) ? '6' : '0'), + (multicast) ? 'm' : '_', queue); + QETH_DBF_TEXT6(0, trace, dbf_text); + sprintf(dbf_text, "%4x%4x", + card->outbound_first_free_buffer[queue], + atomic_read(&card->outbound_used_buffers[queue])); + QETH_DBF_TEXT6(0, trace, dbf_text); + if (qeth_sbal_packing_on_card(card->type)) { + switch (card->send_state[queue]) { + case SEND_STATE_DONT_PACK: + QETH_DBF_TEXT6(0, trace, "usngfast"); + break; + case SEND_STATE_PACK: + QETH_DBF_TEXT6(0, trace, "usngpack"); + break; + } + } else { + QETH_DBF_TEXT6(0, trace, "usngfast"); + } +} + +static inline void +__qeth_switch_state_if_needed(struct qeth_card *card, int queue) +{ + if (atomic_read(&card->outbound_used_buffers[queue]) + >= HIGH_WATERMARK_PACK) { + card->send_state[queue] = SEND_STATE_PACK; + QETH_DBF_TEXT3(0, trace, "stchup"); + QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id); +#ifdef QETH_PERFORMANCE_STATS + card->perf_stats.sc_dp_p++; +#endif /* QETH_PERFORMANCE_STATS */ + } +} + +static int +qeth_do_send_packet(struct qeth_card *card, struct sk_buff *skb, + struct net_device *dev) +{ + int queue, result = 0; + int multicast, version; + + version = QETH_IP_VERSION(skb); + multicast = qeth_is_multicast_skb_at_all(skb, version); + queue = qeth_get_prioqueue(card, skb, multicast, version); + + __qeth_dump_packet_info(card, version, multicast, queue); + + if (atomic_read(&card->outbound_used_buffers[queue]) + >= QDIO_MAX_BUFFERS_PER_Q - 1) { + QETH_DBF_TEXT2(1, trace, "cdbs"); + QETH_DBF_TEXT2(1, trace, card->rdev->dev.bus_id); + netif_stop_queue(dev); + return -EBUSY; + } + + /* + * we are not called under int, so we just spin + * happens around once a second under heavy traffic. takes a little + * bit less than 10usec in avg. on a z900 + */ + if (atomic_compare_and_swap(QETH_LOCK_UNLOCKED, QETH_LOCK_NORMAL, + &card->outbound_ringbuffer_lock[queue])) { + QETH_DBF_TEXT2(0, trace, "SPIN"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + while (atomic_compare_and_swap + (QETH_LOCK_UNLOCKED, QETH_LOCK_NORMAL, + &card->outbound_ringbuffer_lock[queue])) ; + QETH_DBF_TEXT2(0, trace, "spin"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + } +#ifdef QETH_PERFORMANCE_STATS + card->perf_stats.skbs_sent++; +#endif /* QETH_PERFORMANCE_STATS */ + + if (qeth_sbal_packing_on_card(card->type)) { + switch (card->send_state[queue]) { + case SEND_STATE_DONT_PACK: + qeth_send_packet_fast(card, skb, dev, queue, + version, multicast); + __qeth_switch_state_if_needed(card, queue); + break; + case SEND_STATE_PACK: + qeth_send_packet_packed(card, skb, dev, queue, + version, multicast); + break; + default: + result = -EBUSY; + QETH_DBF_TEXT0(1, trace, "UPSs"); + QETH_DBF_TEXT0(1, trace, card->rdev->dev.bus_id); + PRINT_ALL("oops... shouldn't happen (line %i:%i).\n", + __LINE__, card->send_state[queue]); + } + } else { + qeth_send_packet_fast(card, skb, dev, queue, + version, multicast); + } + + /* ATOMIC: (NORMAL->UNLOCKED, FLUSH->NORMAL) */ + while (atomic_dec_return(&card->outbound_ringbuffer_lock[queue])) { + qeth_flush_buffer(card, queue, 0); + card->send_state[queue] = SEND_STATE_DONT_PACK; + } +#ifdef QETH_PERFORMANCE_STATS + card->perf_stats.outbound_time += + NOW - card->perf_stats.outbound_start_time; + card->perf_stats.outbound_cnt++; +#endif /* QETH_PERFORMANCE_STATS */ + + card->stats->tx_packets++; + card->stats->tx_bytes += skb->len; + + return result; +} + +static int +qeth_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct qeth_card *card; + int result; + + card = (struct qeth_card *) (dev->priv); + + if (skb == NULL) + return 0; + + QETH_DBF_HEX4(0, data, skb->data, __max(QETH_DBF_DATA_LEN, skb->len)); + + netif_stop_queue(dev); + + if (!card) { + QETH_DBF_TEXT2(0, trace, "XMNSNOCD"); + dst_link_failure(skb); + dev_kfree_skb_irq(skb); + return 0; + } +#ifdef QETH_PERFORMANCE_STATS + card->perf_stats.outbound_start_time = NOW; +#endif /* QETH_PERFORMANCE_STATS */ + + if (!atomic_read(&card->is_startlaned)) { + card->stats->tx_carrier_errors++; + QETH_DBF_TEXT2(0, trace, "XMNS"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + dst_link_failure(skb); + dev_kfree_skb_irq(skb); + return 0; + } + + result = qeth_do_send_packet(card, skb, dev); + + if (!result) + netif_wake_queue(card->dev); + + return result; +} + +static struct net_device_stats * +qeth_get_stats(struct net_device *dev) +{ + struct qeth_card *card; + + card = (struct qeth_card *) (dev->priv); + + QETH_DBF_TEXT3(0, trace, "gtst"); + QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id); + + return card->stats; +} + +static int +qeth_change_mtu(struct net_device *dev, int new_mtu) +{ + struct qeth_card *card; + char dbf_text[15]; + + card = (struct qeth_card *) (dev->priv); + + QETH_DBF_TEXT2(0, trace, "mtu"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "%8x", new_mtu); + QETH_DBF_TEXT2(0, trace, dbf_text); + + if (new_mtu < 64) + return -EINVAL; + if (new_mtu > 65535) + return -EINVAL; + if ((!qeth_is_supported(IPA_IP_FRAGMENTATION)) && + (!qeth_mtu_is_valid(card, new_mtu))) + return -EINVAL; + dev->mtu = new_mtu; + return 0; +} + +static void +qeth_start_softsetup_thread(struct qeth_card *card) +{ + if (!atomic_read(&card->shutdown_phase)) { + QETH_DBF_TEXT2(0, trace, "stss"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + up(&card->softsetup_thread_sem); + } +} + +static int +qeth_sleepon(struct qeth_card *card, int timeout) +{ + unsigned long flags; + unsigned long start; + int retval; + char dbf_text[15]; + + DECLARE_WAITQUEUE(current_wait_q, current); + + QETH_DBF_TEXT5(0, trace, "slpn"); + QETH_DBF_TEXT5(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "%08x", timeout); + QETH_DBF_TEXT5(0, trace, dbf_text); + + add_wait_queue(&card->wait_q, ¤t_wait_q); + atomic_set(&card->wait_q_active, 1); + start = qeth_get_millis(); + for (;;) { + set_task_state(current, TASK_INTERRUPTIBLE); + if (atomic_read(&card->data_has_arrived)) { + atomic_set(&card->data_has_arrived, 0); + retval = 0; + goto out; + } + if (qeth_get_millis() - start > timeout) { + retval = -ETIME; + goto out; + } + schedule_timeout(((start + timeout - + qeth_get_millis()) >> 10) * HZ); + } +out: + spin_lock_irqsave(&card->wait_q_lock, flags); + atomic_set(&card->wait_q_active, 0); + spin_unlock_irqrestore(&card->wait_q_lock, flags); + + /* we've got to check once again to close the window */ + if (atomic_read(&card->data_has_arrived)) { + atomic_set(&card->data_has_arrived, 0); + retval = 0; + } + + set_task_state(current, TASK_RUNNING); + remove_wait_queue(&card->wait_q, ¤t_wait_q); + + return retval; +} + +static void +qeth_wakeup_ioctl(struct qeth_card *card) +{ + + QETH_DBF_TEXT5(0, trace, "wkup"); + QETH_DBF_TEXT5(0, trace, card->rdev->dev.bus_id); + + atomic_set(&card->ioctl_data_has_arrived, 1); + spin_lock(&card->ioctl_wait_q_lock); + if (atomic_read(&card->ioctl_wait_q_active)) { + wake_up(&card->ioctl_wait_q); + } + spin_unlock(&card->ioctl_wait_q_lock); +} + +static int +qeth_sleepon_ioctl(struct qeth_card *card, int timeout) +{ + unsigned long flags; + unsigned long start; + int retval; + char dbf_text[15]; + + DECLARE_WAITQUEUE(current_wait_q, current); + + QETH_DBF_TEXT5(0, trace, "ioctlslpn"); + QETH_DBF_TEXT5(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "%08x", timeout); + QETH_DBF_TEXT5(0, trace, dbf_text); + + add_wait_queue(&card->ioctl_wait_q, ¤t_wait_q); + atomic_set(&card->ioctl_wait_q_active, 1); + start = qeth_get_millis(); + for (;;) { + set_task_state(current, TASK_INTERRUPTIBLE); + if (atomic_read(&card->ioctl_data_has_arrived)) { + atomic_set(&card->ioctl_data_has_arrived, 0); + retval = 0; + goto out; + } + if (qeth_get_millis() - start > timeout) { + retval = -ETIME; + goto out; + } + schedule_timeout(((start + timeout - + qeth_get_millis()) >> 10) * HZ); + } +out: + spin_lock_irqsave(&card->ioctl_wait_q_lock, flags); + atomic_set(&card->ioctl_wait_q_active, 0); + spin_unlock_irqrestore(&card->ioctl_wait_q_lock, flags); + + /* we've got to check once again to close the window */ + if (atomic_read(&card->ioctl_data_has_arrived)) { + atomic_set(&card->ioctl_data_has_arrived, 0); + retval = 0; + } + + set_task_state(current, TASK_RUNNING); + remove_wait_queue(&card->ioctl_wait_q, ¤t_wait_q); + + return retval; +} + +/*SNMP IOCTL on Procfile */ + +static void +qeth_wakeup_procfile(void) +{ + QETH_DBF_TEXT5(0, trace, "procwkup"); + if (atomic_read(&qeth_procfile_ioctl_sem.count) < + PROCFILE_SLEEP_SEM_MAX_VALUE) + up(&qeth_procfile_ioctl_sem); +} + +static int +qeth_sleepon_procfile(void) +{ + QETH_DBF_TEXT5(0, trace, "procslp"); + if (down_interruptible(&qeth_procfile_ioctl_sem)) { + up(&qeth_procfile_ioctl_sem); + return -ERESTARTSYS; + } + return 0; +} + +/* SNMP END */ + +static char * +qeth_send_control_data(struct qeth_card *card, unsigned char *buffer, + int len, unsigned long intparam) +{ + unsigned long flags; + int result, result2; + char dbf_text[15]; + unsigned char *rec_buf; + int setip = (intparam & IPA_SETIP_FLAG) ? 1 : 0; + +again: + if (atomic_read(&card->shutdown_phase) == QETH_REMOVE_CARD_QUICK) + return NULL; + if (atomic_read(&card->escape_softsetup)) + return NULL; + + /* we lock very early to synchronize access to seqnos */ + if (atomic_swap(&card->write_busy, 1)) { + qeth_wait_nonbusy(QETH_IDLE_WAIT_TIME); + QETH_DBF_TEXT2(0, trace, "LSCD"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + goto again; + } + memcpy(card->dma_stuff->sendbuf, card->send_buf, QETH_BUFSIZE); + + memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(buffer), + &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH); + card->seqno.trans_hdr++; + + memcpy(QETH_PDU_HEADER_SEQ_NO(buffer), + &card->seqno.pdu_hdr, QETH_SEQ_NO_LENGTH); + card->seqno.pdu_hdr++; + memcpy(QETH_PDU_HEADER_ACK_SEQ_NO(buffer), + &card->seqno.pdu_hdr_ack, QETH_SEQ_NO_LENGTH); + + /* there is noone doing this except sleep and this function */ + atomic_set(&card->data_has_arrived, 0); + + memcpy(&card->dma_stuff->write_ccw, WRITE_CCW, sizeof (struct ccw1)); + card->dma_stuff->write_ccw.count = len; + card->dma_stuff->write_ccw.cda = + QETH_GET_ADDR(card->dma_stuff->sendbuf); + + QETH_DBF_TEXT2(0, trace, "scdw"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "%8x", len); + QETH_DBF_TEXT4(0, trace, dbf_text); + QETH_DBF_HEX4(0, trace, &intparam, QETH_DBF_TRACE_LEN); + QETH_DBF_HEX2(0, control, buffer, QETH_DBF_CONTROL_LEN); + + spin_lock_irqsave(get_ccwdev_lock(card->wdev), flags); + result = ccw_device_start(card->wdev, &card->dma_stuff->write_ccw, + intparam, 0, 0); + if (result) { + qeth_delay_millis(QETH_WAIT_BEFORE_2ND_DOIO); + result2 = ccw_device_start(card->wdev, + &card->dma_stuff->write_ccw, + intparam, 0, 0); + if (result2 != -ENODEV) + PRINT_WARN("qeth_send_control_data: do_IO " + "returned %i, next try returns %i\n", + result, result2); + result = result2; + } + spin_unlock_irqrestore(get_ccwdev_lock(card->wdev), flags); + + if (result) { + QETH_DBF_TEXT2(0, trace, "scd:doio"); + sprintf(dbf_text, "%4x", (__s16) result); + QETH_DBF_TEXT2(0, trace, dbf_text); + return NULL; + } + + if (intparam == IPA_IOCTL_STATE) { + if (qeth_sleepon_ioctl(card, QETH_IPA_TIMEOUT)) { + QETH_DBF_TEXT2(0, trace, "scd:ioctime"); + /* re-enable qeth_send_control_data again */ + atomic_set(&card->write_busy, 0); + return NULL; + } + rec_buf = card->ipa_buf; + QETH_DBF_TEXT2(0, trace, "scro"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + } else { + if (qeth_sleepon(card, (setip) ? QETH_IPA_TIMEOUT : + QETH_MPC_TIMEOUT)) { + QETH_DBF_TEXT2(0, trace, "scd:time"); + /* re-enable qeth_send_control_data again */ + atomic_set(&card->write_busy, 0); + return NULL; + } + rec_buf = card->ipa_buf; + QETH_DBF_TEXT2(0, trace, "scri"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + } + QETH_DBF_HEX2(0, control, rec_buf, QETH_DBF_CONTROL_LEN); + + memcpy(&card->seqno.pdu_hdr_ack, + QETH_PDU_HEADER_SEQ_NO(rec_buf), QETH_SEQ_NO_LENGTH); + + return rec_buf; +} + +static int +qeth_send_ipa_cmd(struct qeth_card *card, struct ipa_cmd *cmd, int update_cmd, + int ipatype) +{ + unsigned char *buffer; + struct ipa_cmd *reply; + int ipa_cmd; + int result; + + /* don't muck around with ipv6 if there's no use to do so */ + if ((cmd->prot_version == 6) && (!qeth_is_supported(IPA_IPv6))) + return 0; + + ipa_cmd = cmd->command; + + memcpy(card->send_buf, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE); + + memcpy(QETH_IPA_CMD_DEST_ADDR(card->send_buf), + &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH); + + memcpy(card->send_buf + IPA_PDU_HEADER_SIZE, + cmd, sizeof (struct ipa_cmd)); + + buffer = qeth_send_control_data(card, card->send_buf, + IPA_PDU_HEADER_SIZE + + sizeof (struct ipa_cmd), ipatype); + + if (!buffer) { + if (atomic_read(&card->escape_softsetup)) + result = 0; + else + result = -1; + } else { + reply = (struct ipa_cmd *) PDU_ENCAPSULATION(buffer); + if ((update_cmd) && (reply)) + memcpy(cmd, reply, sizeof (struct ipa_cmd)); + result = reply->return_code; + + /* some special sausages: */ + if ((ipa_cmd == IPA_CMD_SETASSPARMS) && (result == 0)) { + result = reply->data.setassparms.return_code; + } + if ((ipa_cmd == IPA_CMD_SETADAPTERPARMS) && (result == 0)) { + result = reply->data.setadapterparms.return_code; + } + } + return result; +} + +static void +qeth_fill_ipa_cmd(struct qeth_card *card, struct ipa_cmd *cmd, + __u8 command, int ip_vers) +{ + memset(cmd, 0, sizeof (struct ipa_cmd)); + cmd->command = command; + cmd->initiator = INITIATOR_HOST; + cmd->seq_no = card->seqno.ipa++; + cmd->adapter_type = qeth_get_adapter_type_for_ipa(card->link_type); + cmd->rel_adapter_no = (__u8) card->options.portno; + cmd->prim_version_no = 1; + cmd->param_count = 1; + cmd->prot_version = ip_vers; + cmd->ipa_supported = 0; + cmd->ipa_enabled = 0; +} + +static int +qeth_send_startstoplan(struct qeth_card *card, __u8 ipacmd, __u16 ip_vers) +{ + struct ipa_cmd cmd; + int result; + + qeth_fill_ipa_cmd(card, &cmd, ipacmd, 0); + cmd.param_count = 0; + cmd.prot_version = ip_vers; + cmd.ipa_supported = 0; + cmd.ipa_enabled = 0; + + result = qeth_send_ipa_cmd(card, &cmd, 0, IPA_CMD_STATE); + return result; +} + +static int +qeth_send_startlan(struct qeth_card *card, __u16 ip_vers) +{ + int result; + char dbf_text[15]; + + QETH_DBF_TEXT4(0, trace, "stln"); + QETH_DBF_TEXT4(0, trace, card->rdev->dev.bus_id); + + result = qeth_send_startstoplan(card, IPA_CMD_STARTLAN, ip_vers); + if (!result) + atomic_set(&card->is_startlaned, 1); + + if (result) { + QETH_DBF_TEXT2(0, trace, "STRTLNFL"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "%4x", result); + QETH_DBF_TEXT2(0, trace, dbf_text); + } + + return result; +} + +static int +qeth_send_stoplan(struct qeth_card *card) +{ +#ifdef QETH_SEND_STOPLAN_ON_SHUTDOWN + int result; + char dbf_text[15]; + + atomic_set(&card->is_startlaned, 0); + + QETH_DBF_TEXT4(0, trace, "spln"); + QETH_DBF_TEXT4(0, trace, card->rdev->dev.bus_id); + + result = qeth_send_startstoplan(card, IPA_CMD_STOPLAN, 4); + + if (result) { + QETH_DBF_TEXT2(0, trace, "STPLNFLD"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "%4x", result); + QETH_DBF_TEXT2(0, trace, dbf_text); + } + + return result; +#else /* QETH_SEND_STOPLAN_ON_SHUTDOWN */ + return 0; +#endif /* QETH_SEND_STOPLAN_ON_SHUTDOWN */ +} + +static int +qeth_send_qipassist(struct qeth_card *card, short ip_vers) +{ + struct ipa_cmd cmd; + int result; + + qeth_fill_ipa_cmd(card, &cmd, IPA_CMD_QIPASSIST, ip_vers); + + result = qeth_send_ipa_cmd(card, &cmd, 1, IPA_CMD_STATE); + + if (!result) { + if (ip_vers == 4) { + card->ipa_supported = cmd.ipa_supported; + card->ipa_enabled = cmd.ipa_enabled; + } else { + card->ipa6_supported = cmd.ipa_supported; + card->ipa6_enabled = cmd.ipa_enabled; + } + } + + return result; +} + +/* QUERY ARP FUNCTIONS */ + +static int +qeth_send_ipa_arpcmd(struct qeth_card *card, struct arp_cmd *cmd, + int update_cmd, int ipatype, __u32 req_size) +{ + unsigned char *buffer; + int ipa_cmd; + int result; + __u16 s1, s2; + + /* don't muck around with ipv6 if there's no use to do so */ + if ((cmd->prot_version == 6) && (!qeth_is_supported(IPA_IPv6))) + return 0; + result = 0; + ipa_cmd = cmd->command; + + memcpy(card->send_buf, IPA_PDU_HEADER, IPA_PDU_HEADER_SIZE); + memcpy(QETH_IPA_CMD_DEST_ADDR(card->send_buf), + &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH); + memcpy(card->send_buf + IPA_PDU_HEADER_SIZE, + cmd, sizeof (struct arp_cmd)); + + if (req_size) { + /* adjust sizes for big requests */ + s1 = (__u32) IPA_PDU_HEADER_SIZE + SNMP_BASE_CMDLENGTH + + req_size; + s2 = (__u32) SNMP_BASE_CMDLENGTH + req_size; + memcpy(QETH_IPA_PDU_LEN_TOTAL(card->send_buf), &s1, 2); + memcpy(QETH_IPA_PDU_LEN_PDU1(card->send_buf), &s2, 2); + memcpy(QETH_IPA_PDU_LEN_PDU2(card->send_buf), &s2, 2); + memcpy(QETH_IPA_PDU_LEN_PDU3(card->send_buf), &s2, 2); + } + + buffer = qeth_send_control_data(card, card->send_buf, + IPA_PDU_HEADER_SIZE + + sizeof (struct arp_cmd), ipatype); + if (!buffer) + result = -ENODATA; + else + result = card->ioctl_returncode; + return result; +} + +static int +qeth_ioctl_handle_snmp_data(struct qeth_card *card, struct arp_cmd *reply) +{ + __u16 data_len; + +#define SNMP_HEADER_SIZE_WITH_TOKEN 36 + + data_len = *((__u16*)QETH_IPA_PDU_LEN_PDU1(card->dma_stuff->recbuf)); + if (reply->data.setadapterparms.frame_seq_no == 1) + data_len = data_len - + (__u16)((char*)reply->data.setadapterparms.data. + snmp_subcommand.snmp_data - (char*)reply); + else + data_len = data_len - + (__u16)((char*)&reply->data.setadapterparms.data. + snmp_subcommand.snmp_request - (char*)reply); + + if (reply->data.setadapterparms.frame_seq_no == 1) { + + if (card->ioctl_buffersize <= (SNMP_HEADER_SIZE_WITH_TOKEN + + reply->data.setadapterparms. + frames_used_total * + ARP_DATA_SIZE)) { + + card->ioctl_returncode = ARP_RETURNCODE_ERROR; + reply->data.setadapterparms.data.snmp_subcommand. + snmp_returncode = -ENOMEM; + } else { + card->ioctl_returncode = ARP_RETURNCODE_SUCCESS; + card->number_of_entries = 0; + memcpy(((char *)card->ioctl_data_buffer), + reply->data.setadapterparms.snmp_token, + SNMP_HEADER_SIZE_WITH_TOKEN); + card->ioctl_buffer_pointer = card->ioctl_data_buffer+ + SNMP_HEADER_SIZE_WITH_TOKEN; + } + } + + if (card->ioctl_returncode != ARP_RETURNCODE_ERROR && + reply->data.setadapterparms.frame_seq_no <= + reply->data.setadapterparms.frames_used_total) { + + if (reply->data.setadapterparms.return_code == + IPA_REPLY_SUCCESS) { + + if (reply->data.setadapterparms.frame_seq_no == 1) + memcpy(card->ioctl_buffer_pointer, + reply->data.setadapterparms.data. + snmp_subcommand.snmp_data, data_len); + else + memcpy(card->ioctl_buffer_pointer, + (char*)&reply->data.setadapterparms. + data.snmp_subcommand.snmp_request, + data_len); + + card->ioctl_buffer_pointer = + card->ioctl_buffer_pointer + data_len; + card->ioctl_returncode = ARP_RETURNCODE_SUCCESS; + + if (reply->data.setadapterparms.frame_seq_no == + reply->data.setadapterparms.frames_used_total) { + card->ioctl_returncode = + ARP_RETURNCODE_LASTREPLY; + } + } else { + card->ioctl_returncode = ARP_RETURNCODE_ERROR; + memset(card->ioctl_data_buffer, 0, + card->ioctl_buffersize); + reply->data.setadapterparms.data.snmp_subcommand. + snmp_returncode = + reply->data.setadapterparms.return_code; + } + } +#undef SNMP_HEADER_SIZE_WITH_TOKEN + + return card->ioctl_returncode; +} + +static int +qeth_ioctl_handle_arp_data(struct qeth_card *card, struct arp_cmd *reply) +{ + + if (reply->data.setassparms.seq_no == 1) { + if (card->ioctl_buffersize <= + (sizeof (__u16) + sizeof (int) + + reply->data.setassparms.number_of_replies * + ARP_DATA_SIZE)) { + + card->ioctl_returncode = ARP_RETURNCODE_ERROR; + + } else { + card->ioctl_returncode = ARP_RETURNCODE_SUCCESS; + card->number_of_entries = 0; + card->ioctl_buffer_pointer = + card->ioctl_data_buffer + sizeof (__u16) + + sizeof (int); + } + } + + if (card->ioctl_returncode != ARP_RETURNCODE_ERROR && + reply->data.setassparms.seq_no <= + reply->data.setassparms.number_of_replies) { + + if (reply->data.setassparms.return_code == IPA_REPLY_SUCCESS) { + + card->number_of_entries = card->number_of_entries + + reply->data.setassparms. + data.queryarp_data.number_of_entries; + memcpy(card->ioctl_buffer_pointer, + reply->data.setassparms.data.queryarp_data. + arp_data, ARP_DATA_SIZE); + card->ioctl_buffer_pointer = card-> + ioctl_buffer_pointer + ARP_DATA_SIZE; + card->ioctl_returncode = ARP_RETURNCODE_SUCCESS; + if (reply->data.setassparms.seq_no == + reply->data.setassparms.number_of_replies) { + memcpy(card->ioctl_data_buffer, + &reply->data.setassparms.data. + queryarp_data.osa_setbitmask, + sizeof (__u16)); + card->ioctl_returncode = + ARP_RETURNCODE_LASTREPLY; + } + } else { + + card->ioctl_returncode = ARP_RETURNCODE_ERROR; + memset(card->ioctl_data_buffer, 0, + card->ioctl_buffersize); + } + } + return card->ioctl_returncode; +} + +static int +qeth_look_for_arp_data(struct qeth_card *card) +{ + struct arp_cmd *reply; + int result; + + reply = (struct arp_cmd *) PDU_ENCAPSULATION(card->dma_stuff->recbuf); + + if ((reply->command == IPA_CMD_SETASSPARMS) && + (reply->data.setassparms.assist_no == IPA_ARP_PROCESSING) && + (reply->data.setassparms.command_code == + IPA_CMD_ASS_ARP_FLUSH_CACHE)) { + result = ARP_FLUSH; + } else if ((reply->command == IPA_CMD_SETASSPARMS) && + (reply->data.setassparms.assist_no == IPA_ARP_PROCESSING) && + (reply->data.setassparms.command_code == + IPA_CMD_ASS_ARP_QUERY_INFO) && + (card->ioctl_returncode == ARP_RETURNCODE_SUCCESS)) { + + result = qeth_ioctl_handle_arp_data(card, reply); + + } else if ((reply->command == IPA_CMD_SETADAPTERPARMS) && + (reply->data.setadapterparms.command_code == + IPA_SETADP_SET_SNMP_CONTROL) && + (card->ioctl_returncode == ARP_RETURNCODE_SUCCESS)) { + + result = qeth_ioctl_handle_snmp_data(card, reply); + } else + result = ARP_RETURNCODE_NOARPDATA; + + return result; +} + +static int +qeth_queryarp(struct qeth_card *card, struct ifreq *req, int version, + __u32 assist_no, __u16 command_code, char *c_data, __u16 len) +{ + int data_size; + struct arp_cmd *cmd; + int result; + + cmd = (struct arp_cmd *) kmalloc(sizeof (struct arp_cmd), GFP_KERNEL); + if (!cmd) { + return IPA_REPLY_FAILED; + } + + memcpy(&data_size, c_data, sizeof (int)); + + qeth_fill_ipa_cmd(card, (struct ipa_cmd *) cmd, IPA_CMD_SETASSPARMS, + version); + + cmd->data.setassparms.assist_no = assist_no; + cmd->data.setassparms.length = 8 + len; + cmd->data.setassparms.command_code = command_code; + cmd->data.setassparms.return_code = 0; + cmd->data.setassparms.seq_no = 0; + + card->ioctl_buffersize = data_size; + card->ioctl_data_buffer = (char *) vmalloc(data_size); + if (!card->ioctl_data_buffer) { + kfree(cmd); + return IPA_REPLY_FAILED; + } + + card->ioctl_returncode = ARP_RETURNCODE_SUCCESS; + + result = qeth_send_ipa_arpcmd(card, cmd, 1, IPA_IOCTL_STATE, 0); + + if ((result == ARP_RETURNCODE_ERROR) || (result == -ENODATA)) { + result = IPA_REPLY_FAILED; + } else { + result = IPA_REPLY_SUCCESS; + memcpy(((char *) (card->ioctl_data_buffer)) + sizeof (__u16), + &(card->number_of_entries), sizeof (int)); + copy_to_user(req->ifr_ifru.ifru_data, + card->ioctl_data_buffer, data_size); + } + card->ioctl_buffer_pointer = NULL; + vfree(card->ioctl_data_buffer); + kfree(cmd); + card->number_of_entries = 0; + card->ioctl_buffersize = 0; + + return result; +} + +static int +snmp_set_setadapterparms_command(struct qeth_card *card, + struct arp_cmd *cmd, struct ifreq *req, + char *data, __u16 len, + __u16 command_code, int req_size) +{ + __u32 data_size; + + memcpy(&data_size, data, sizeof (__u32)); + + card->ioctl_buffersize = data_size; + card->ioctl_data_buffer = (char *) vmalloc(data_size); + if (!card->ioctl_data_buffer) { + return -ENOMEM; + } + card->ioctl_returncode = ARP_RETURNCODE_SUCCESS; + + memcpy(cmd->data.setadapterparms.snmp_token, + data + SNMP_REQUEST_DATA_OFFSET, req_size); + + cmd->data.setadapterparms.cmdlength = SNMP_SETADP_CMDLENGTH + req_size; + cmd->data.setadapterparms.command_code = command_code; + cmd->data.setadapterparms.frames_used_total = 1; + cmd->data.setadapterparms.frame_seq_no = 1; + + return 0; +} +static int +qeth_send_snmp_control(struct qeth_card *card, struct ifreq *req, + __u32 command, __u16 command_code, + char *c_data, __u16 len) +{ + struct arp_cmd *cmd; + __u32 result, req_size; + + cmd = (struct arp_cmd *) kmalloc(sizeof (struct arp_cmd), GFP_KERNEL); + if (!cmd) { + return IPA_REPLY_FAILED; + } + + qeth_fill_ipa_cmd(card, (struct ipa_cmd *) cmd, command, 4); + + memcpy(&req_size, ((char *) c_data) + sizeof (__u32), sizeof (__u32)); + + if (snmp_set_setadapterparms_command(card, cmd, req, c_data, + len, command_code, req_size)) { + kfree(cmd); + return IPA_REPLY_FAILED; + } + + result = qeth_send_ipa_arpcmd(card, cmd, 1, IPA_IOCTL_STATE, req_size); + + if (result == -ENODATA) { + result = IPA_REPLY_FAILED; + goto snmp_out; + } + if (result == ARP_RETURNCODE_ERROR) { + copy_to_user(req->ifr_ifru.ifru_data + SNMP_REQUEST_DATA_OFFSET, + card->ioctl_data_buffer, card->ioctl_buffersize); + result = IPA_REPLY_FAILED; + } else { + copy_to_user(req->ifr_ifru.ifru_data + SNMP_REQUEST_DATA_OFFSET, + card->ioctl_data_buffer, card->ioctl_buffersize); + result = IPA_REPLY_SUCCESS; + } +snmp_out: + card->number_of_entries = 0; + card->ioctl_buffersize = 0; + card->ioctl_buffer_pointer = NULL; + vfree(card->ioctl_data_buffer); + kfree(cmd); + + return result; +} + +static int +qeth_send_setassparms(struct qeth_card *card, int version, __u32 assist_no, + __u16 command_code, long data, __u16 len) +{ + struct ipa_cmd cmd; + int result; + + qeth_fill_ipa_cmd(card, &cmd, IPA_CMD_SETASSPARMS, version); + + cmd.data.setassparms.assist_no = assist_no; + cmd.data.setassparms.length = 8 + len; + cmd.data.setassparms.command_code = command_code; + cmd.data.setassparms.return_code = 0; + cmd.data.setassparms.seq_no = 0; + + if (len <= sizeof (__u32)) + cmd.data.setassparms.data.flags_32bit = (__u32) data; + else if (len > sizeof (__u32)) + memcpy(&cmd.data.setassparms.data, (void *) data, + qeth_min(len, PAGE_SIZE)); + if (command_code != IPA_CMD_ASS_START) { + result = qeth_send_ipa_cmd(card, &cmd, 0, + ((assist_no == IPA_ARP_PROCESSING) && + (command_code != + IPA_CMD_ASS_ARP_FLUSH_CACHE)) ? + IPA_IOCTL_STATE : IPA_CMD_STATE); + + } else + result = qeth_send_ipa_cmd(card, &cmd, 0, IPA_CMD_STATE); + + return result; +} + +static int +qeth_send_setadapterparms_query(struct qeth_card *card) +{ + struct ipa_cmd cmd; + int result; + + qeth_fill_ipa_cmd(card, &cmd, IPA_CMD_SETADAPTERPARMS, + IPA_SETADAPTERPARMS_IP_VERSION); + cmd.data.setadapterparms.cmdlength = sizeof (struct ipa_setadp_cmd); + cmd.data.setadapterparms.command_code = + IPA_SETADP_QUERY_COMMANDS_SUPPORTED; + cmd.data.setadapterparms.frames_used_total = 1; + cmd.data.setadapterparms.frame_seq_no = 1; + result = qeth_send_ipa_cmd(card, &cmd, 1, IPA_CMD_STATE); + + if (cmd.data.setadapterparms.data.query_cmds_supp.lan_type & 0x7f) + card->link_type = cmd.data.setadapterparms.data. + query_cmds_supp.lan_type; + + card->adp_supported = + cmd.data.setadapterparms.data.query_cmds_supp.supported_cmds; + + return result; +} + +static int +qeth_send_setadapterparms_mode(struct qeth_card *card, __u32 command, + __u32 mode) +{ + + struct ipa_cmd cmd; + int result; + + qeth_fill_ipa_cmd(card, &cmd, IPA_CMD_SETADAPTERPARMS, + IPA_SETADAPTERPARMS_IP_VERSION); + cmd.data.setadapterparms.cmdlength = sizeof (struct ipa_setadp_cmd); + cmd.data.setadapterparms.command_code = command; + cmd.data.setadapterparms.frames_used_total = 1; + cmd.data.setadapterparms.frame_seq_no = 1; + cmd.data.setadapterparms.data.mode = mode; + result = qeth_send_ipa_cmd(card, &cmd, 0, IPA_CMD_STATE); + + return result; +} + +static int +qeth_send_setadapterparms_change_addr(struct qeth_card *card, + __u32 command, + __u32 subcmd, __u8 * mac_addr, + int addr_len) +{ + struct ipa_cmd cmd; + int result; + + qeth_fill_ipa_cmd(card, &cmd, IPA_CMD_SETADAPTERPARMS, + IPA_SETADAPTERPARMS_IP_VERSION); + cmd.data.setadapterparms.cmdlength = sizeof (struct ipa_setadp_cmd); + cmd.data.setadapterparms.command_code = command; + cmd.data.setadapterparms.frames_used_total = 1; + cmd.data.setadapterparms.frame_seq_no = 1; + cmd.data.setadapterparms.data.change_addr.cmd = subcmd; + cmd.data.setadapterparms.data.change_addr.addr_size = addr_len; + memcpy(&cmd.data.setadapterparms.data.change_addr.addr, + mac_addr, addr_len); + + result = qeth_send_ipa_cmd(card, &cmd, 1, IPA_CMD_STATE); + + memcpy(mac_addr, &cmd.data.setadapterparms.data.change_addr.addr, + addr_len); + + return result; +} + +static int +qeth_send_setassparms_simple_with_data(struct qeth_card *card, + __u32 assist_no, + __u16 command_code, long data) +{ + return qeth_send_setassparms(card, 4, assist_no, command_code, data, 4); +} + +static int +qeth_send_setassparms_simple_without_data(struct qeth_card *card, + __u32 assist_no, __u16 command_code) +{ + return qeth_send_setassparms(card, 4, assist_no, command_code, 0, 0); +} + +static int +qeth_send_setassparms_simple_without_data6(struct qeth_card *card, + __u32 assist_no, __u16 command_code) +{ + return qeth_send_setassparms(card, 6, assist_no, command_code, 0, 0); +} + +static int +qeth_send_setdelip(struct qeth_card *card, __u8 * ip, __u8 * netmask, + int ipacmd, short ip_vers, unsigned int flags) +{ + struct ipa_cmd cmd; + int ip_len = (ip_vers == 6) ? 16 : 4; + + qeth_fill_ipa_cmd(card, &cmd, ipacmd, ip_vers); + + if (ip_vers == 6) { + memcpy(&cmd.data.setdelip6.ip, ip, ip_len); + memcpy(&cmd.data.setdelip6.netmask, netmask, ip_len); + cmd.data.setdelip6.flags = flags; + } else { + memcpy(&cmd.data.setdelip4.ip, ip, ip_len); + memcpy(&cmd.data.setdelip4.netmask, netmask, ip_len); + cmd.data.setdelip4.flags = flags; + } + + return qeth_send_ipa_cmd(card, &cmd, 0, IPA_CMD_STATE | + ((ipacmd == + IPA_CMD_SETIP) ? IPA_SETIP_FLAG : 0)); +} + +static int +qeth_send_setdelipm(struct qeth_card *card, __u8 * ip, __u8 * mac, + int ipacmd, short ip_vers) +{ + struct ipa_cmd cmd; + int ip_len = (ip_vers == 6) ? 16 : 4; + + qeth_fill_ipa_cmd(card, &cmd, ipacmd, ip_vers); + memcpy(&cmd.data.setdelipm.mac, mac, 6); + if (ip_vers == 6) { + memcpy(&cmd.data.setdelipm.ip6, ip, ip_len); + } else { + memcpy(&cmd.data.setdelipm.ip4_6, ip, ip_len); + } + + return qeth_send_ipa_cmd(card, &cmd, 0, IPA_CMD_STATE | + ((ipacmd == + IPA_CMD_SETIPM) ? IPA_SETIP_FLAG : 0)); +} + +#define PRINT_SETIP_ERROR(x) \ + if (result) \ + PRINT_ERR("setip%c: return code 0x%x (%s)\n",x,result, \ + (result==0xe002)?"invalid mtu size": \ + (result==0xe005)?"duplicate ip address": \ + (result==0xe0a5)?"duplicate ip address": \ + (result==0xe006)?"ip table full": \ + (result==0xe008)?"startlan not received": \ + (result==0xe009)?"setip already received": \ + (result==0xe00a)?"dup network ip address": \ + (result==0xe00b)?"mblk no free main task entry": \ + (result==0xe00d)?"invalid ip version": \ + (result==0xe00e)?"unsupported arp assist cmd": \ + (result==0xe00f)?"arp assist not enabled": \ + (result==0xe080)?"startlan disabled": \ + (result==-1)?"IPA communication timeout": \ + "unknown return code") + +static inline int +qeth_send_setip(struct qeth_card *card, __u8 * ip, + __u8 * netmask, short ip_vers, int use_retries) +{ + int result; + int retries; + char dbf_text[15]; + int takeover = 0; + + retries = (use_retries) ? QETH_SETIP_RETRIES : 1; + if (qeth_is_ipa_covered_by_ipato_entries(ip_vers, ip, card)) { + QETH_DBF_TEXT2(0, trace, "ipto"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + if (ip_vers == 4) { + *((__u32 *) (&dbf_text[0])) = *((__u32 *) ip); + *((__u32 *) (&dbf_text[4])) = *((__u32 *) netmask); + QETH_DBF_HEX2(0, trace, dbf_text, QETH_DBF_TRACE_LEN); + } else { + QETH_DBF_HEX2(0, trace, ip, QETH_DBF_TRACE_LEN); + QETH_DBF_HEX2(0, trace, ip + QETH_DBF_TRACE_LEN, + QETH_DBF_TRACE_LEN); + QETH_DBF_HEX2(0, trace, netmask, QETH_DBF_TRACE_LEN); + QETH_DBF_HEX2(0, trace, netmask + QETH_DBF_TRACE_LEN, + QETH_DBF_TRACE_LEN); + } + takeover = 1; + } else { + } +retry: + result = qeth_send_setdelip(card, ip, netmask, IPA_CMD_SETIP, ip_vers, + (takeover) ? IPA_SETIP_TAKEOVER_FLAGS : + IPA_SETIP_FLAGS); + PRINT_SETIP_ERROR(' '); + + if (result) { + QETH_DBF_TEXT2(0, trace, "SETIPFLD"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "%4x", result); + QETH_DBF_TEXT2(0, trace, dbf_text); + } + + if (((result == -1) || (result == 0xe080)) && (retries--)) { + QETH_DBF_TEXT2(0, trace, "sipr"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + if (ip_vers == 4) { + *((__u32 *) (&dbf_text[0])) = *((__u32 *) ip); + *((__u32 *) (&dbf_text[4])) = *((__u32 *) netmask); + QETH_DBF_HEX2(0, trace, dbf_text, QETH_DBF_TRACE_LEN); + } else { + QETH_DBF_HEX2(0, trace, ip, QETH_DBF_TRACE_LEN); + QETH_DBF_HEX2(0, trace, ip + QETH_DBF_TRACE_LEN, + QETH_DBF_TRACE_LEN); + QETH_DBF_HEX2(0, trace, netmask, QETH_DBF_TRACE_LEN); + QETH_DBF_HEX2(0, trace, netmask + QETH_DBF_TRACE_LEN, + QETH_DBF_TRACE_LEN); + } + PRINT_WARN("trying again...\n"); + goto retry; + } + + return result; +} + +static inline int +qeth_send_delip(struct qeth_card *card, __u8 * ip, + __u8 * netmask, short ip_vers) +{ + return qeth_send_setdelip(card, ip, netmask, IPA_CMD_DELIP, ip_vers, + IPA_DELIP_FLAGS); +} + +static inline int +qeth_send_setipm(struct qeth_card *card, __u8 * ip, + __u8 * mac, short ip_vers, int use_retries) +{ + int result; + int retries; + char dbf_text[15]; + + retries = (use_retries) ? QETH_SETIP_RETRIES : 1; + if (qeth_is_ipa_covered_by_ipato_entries(ip_vers, ip, card)) { + QETH_DBF_TEXT2(0, trace, "imto"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + if (ip_vers == 4) { + *((__u32 *) (&dbf_text[0])) = *((__u32 *) ip); + QETH_DBF_HEX2(0, trace, dbf_text, QETH_DBF_TRACE_LEN); + } else { + QETH_DBF_HEX2(0, trace, ip, QETH_DBF_TRACE_LEN); + QETH_DBF_HEX2(0, trace, ip + QETH_DBF_TRACE_LEN, + QETH_DBF_TRACE_LEN); + } + } + +retry: + result = qeth_send_setdelipm(card, ip, mac, IPA_CMD_SETIPM, ip_vers); + PRINT_SETIP_ERROR('m'); + + if (result) { + QETH_DBF_TEXT2(0, trace, "SETIMFLD"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "%4x", result); + QETH_DBF_TEXT2(0, trace, dbf_text); + } + + if ((result == -1) && (retries--)) { + QETH_DBF_TEXT2(0, trace, "simr"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + if (ip_vers == 4) { + sprintf(dbf_text, "%08x", *((__u32 *) ip)); + QETH_DBF_TEXT2(0, trace, dbf_text); + } else { + QETH_DBF_HEX2(0, trace, ip, QETH_DBF_TRACE_LEN); + QETH_DBF_HEX2(0, trace, ip + QETH_DBF_TRACE_LEN, + QETH_DBF_TRACE_LEN); + } + QETH_DBF_HEX2(0, trace, mac, OSA_ADDR_LEN); + PRINT_WARN("trying again...\n"); + goto retry; + } + + return result; +} + +static inline int +qeth_send_delipm(struct qeth_card *card, __u8 * ip, __u8 * mac, short ip_vers) +{ + return qeth_send_setdelipm(card, ip, mac, IPA_CMD_DELIPM, ip_vers); +} + +static int +qeth_add_vipa_entry(struct qeth_card *card, int version, __u8 * addr, int flag) +{ + struct qeth_vipa_entry *entry, *e; + int result = 0; + + entry = + (struct qeth_vipa_entry *) kmalloc(sizeof (struct qeth_vipa_entry), + GFP_KERNEL); + if (!entry) { + PRINT_ERR("not enough memory for vipa handling\n"); + return -ENOMEM; + } + entry->version = version; + entry->flag = flag; + memcpy(entry->ip, addr, 16); + entry->state = VIPA_2_B_ADDED; + + write_lock(&card->vipa_list_lock); + e = card->vipa_list; + while (e) { + if (e->version != version) + goto next; + if (memcmp(e->ip, addr, (version == 4) ? 4 : 16)) + goto next; + if (flag == IPA_SETIP_VIPA_FLAGS) { + PRINT_ERR("vipa already set\n"); + } else { + PRINT_ERR("rxip already set\n"); + } + kfree(entry); + result = -EALREADY; + goto out; + next: + e = e->next; + } + entry->next = card->vipa_list; + card->vipa_list = entry; +out: + write_unlock(&card->vipa_list_lock); + return result; +} + +static int +qeth_del_vipa_entry(struct qeth_card *card, int version, __u8 * addr, int flag) +{ + struct qeth_vipa_entry *e; + int result = 0; + + write_lock(&card->vipa_list_lock); + e = card->vipa_list; + while (e) { + if (e->version != version) + goto next; + if (e->flag != flag) + goto next; + if (memcmp(e->ip, addr, (version == 4) ? 4 : 16)) + goto next; + e->state = VIPA_2_B_REMOVED; + goto out; + next: + e = e->next; + } + if (flag == IPA_SETIP_VIPA_FLAGS) { + PRINT_ERR("vipa not found\n"); + } else { + PRINT_ERR("rxip not found\n"); + } + result = -ENOENT; +out: + write_unlock(&card->vipa_list_lock); + return result; +} + +static void +qeth_set_vipas(struct qeth_card *card, int set_only) +{ + struct qeth_vipa_entry *e, *le = NULL, *ne; /* ne stands for new entry, + le is last entry */ + char dbf_text[15]; + int result; + __u8 netmask[16] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + struct qeth_vipa_entry *priv_add_list = NULL; + struct qeth_vipa_entry *priv_del_list = NULL; + + write_lock(&card->vipa_list_lock); + e = card->vipa_list; + while (e) { + switch (e->state) { + case VIPA_2_B_ADDED: + if (!set_only) + break; + if (!atomic_read(&card->is_open)) + break; + /* we don't want to hold the lock for a long time... + * so we clone the entry */ + ne = (struct qeth_vipa_entry *) + kmalloc(sizeof (struct qeth_vipa_entry), + GFP_KERNEL); + if (ne) { + ne->version = e->version; + memcpy(ne->ip, e->ip, 16); + ne->next = priv_add_list; + priv_add_list = ne; + + e->state = VIPA_ESTABLISHED; + } else { + PRINT_ERR("not enough for internal vipa " + "handling... trying to set " + "vipa next time.\n"); + qeth_start_softsetup_thread(card); + } + break; + case VIPA_2_B_REMOVED: + if (set_only) + break; + if (le) + le->next = e->next; + else + card->vipa_list = e->next; + ne = e->next; + e->next = priv_del_list; + priv_del_list = e; + e = ne; + continue; + case VIPA_ESTABLISHED: + if (atomic_read(&card->is_open)) + break; + /* we don't want to hold the lock for a long time... + * so we clone the entry */ + ne = (struct qeth_vipa_entry *) + kmalloc(sizeof (struct qeth_vipa_entry), + GFP_KERNEL); + if (ne) { + ne->version = e->version; + memcpy(ne->ip, e->ip, 16); + ne->next = priv_del_list; + priv_del_list = ne; + + e->state = VIPA_2_B_ADDED; + } else { + PRINT_ERR("not enough for internal vipa " + "handling... VIPA/RXIP remains set " + "although device is stopped.\n"); + qeth_start_softsetup_thread(card); + } + break; + default: + break; + } + le = e; + e = e->next; + } + write_unlock(&card->vipa_list_lock); + + while (priv_add_list) { + result = qeth_send_setdelip(card, priv_add_list->ip, netmask, + IPA_CMD_SETIP, + priv_add_list->version, + priv_add_list->flag); + PRINT_SETIP_ERROR('s'); + + if (result) { + QETH_DBF_TEXT2(0, trace, "SETSVFLD"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "%4x", result); + QETH_DBF_TEXT2(0, trace, dbf_text); + if (priv_add_list->version == 4) { + PRINT_ERR("going to leave vipa/rxip %08x" + "unset...\n", + *((__u32 *) & priv_add_list->ip[0])); + sprintf(dbf_text, "%08x", + *((__u32 *) & priv_add_list->ip[0])); + QETH_DBF_TEXT2(0, trace, dbf_text); + } else { + PRINT_ERR("going to leave vipa/rxip " + "%08x%08x%08x%08x unset...\n", + *((__u32 *) & priv_add_list->ip[0]), + *((__u32 *) & priv_add_list->ip[4]), + *((__u32 *) & priv_add_list->ip[8]), + *((__u32 *) & priv_add_list->ip[12])); + QETH_DBF_HEX2(0, trace, &priv_add_list->ip[0], + QETH_DBF_TRACE_LEN); + QETH_DBF_HEX2(0, trace, &priv_add_list->ip[8], + QETH_DBF_TRACE_LEN); + } + } + e = priv_add_list; + priv_add_list = priv_add_list->next; + kfree(e); + } + + while (priv_del_list) { + result = qeth_send_setdelip(card, priv_del_list->ip, netmask, + IPA_CMD_DELIP, + priv_del_list->version, + priv_del_list->flag); + if (result) { + QETH_DBF_TEXT2(0, trace, "DELSVFLD"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "%4x", result); + QETH_DBF_TEXT2(0, trace, dbf_text); + if (priv_del_list->version == 4) { + PRINT_ERR("could not delete vipa/rxip " + "%08x...\n", + *((__u32 *) & priv_del_list->ip[0])); + sprintf(dbf_text, "%08x", + *((__u32 *) & priv_del_list->ip[0])); + QETH_DBF_TEXT2(0, trace, dbf_text); + } else { + PRINT_ERR("could not delete vipa/rxip " + "%08x%08x%08x%08x...\n", + *((__u32 *) & priv_del_list->ip[0]), + *((__u32 *) & priv_del_list->ip[4]), + *((__u32 *) & priv_del_list->ip[8]), + *((__u32 *) & priv_del_list->ip[12])); + QETH_DBF_HEX2(0, trace, &priv_del_list->ip[0], + QETH_DBF_TRACE_LEN); + QETH_DBF_HEX2(0, trace, &priv_del_list->ip[8], + QETH_DBF_TRACE_LEN); + } +/* in case of problems, it's better if we just display a message and + * don't requeue the entry back... + write_lock(&card->vipa_list_lock); + e=card->vipa_list; + card->vipa_list=priv_del_list; + priv_del_list=priv_del_list->next; + card->vipa_list->next=e; + card->vipa_list->state=VIPA_ESTABLISHED; + write_unlock(&card->vipa_list_lock); + continue; +*/ + } + e = priv_del_list; + priv_del_list = priv_del_list->next; + kfree(e); + } +} + +static void +qeth_refresh_vipa_states(struct qeth_card *card) +{ + struct qeth_vipa_entry *e; + + write_lock(&card->vipa_list_lock); + e = card->vipa_list; + while (e) { + if (e->state == VIPA_ESTABLISHED) + e->state = VIPA_2_B_ADDED; + e = e->next; + } + write_unlock(&card->vipa_list_lock); +} + +static inline int +qeth_send_setrtg(struct qeth_card *card, int routing_type, short ip_vers) +{ + struct ipa_cmd cmd; + + qeth_fill_ipa_cmd(card, &cmd, IPA_CMD_SETRTG, ip_vers); + /* strip off RESET_ROUTING_FLAG */ + cmd.data.setrtg.type = (routing_type) & (ROUTER_MASK); + + return qeth_send_ipa_cmd(card, &cmd, 0, IPA_CMD_STATE); +} + +static int +qeth_is_ipa_in_list(struct in_ifaddr *ip, struct in_ifaddr *list) +{ + while (list) { + if (ip->ifa_address == list->ifa_address) + return 1; + list = list->ifa_next; + } + return 0; +} + +#ifdef QETH_IPV6 +static int +qeth_is_ipa_in_list6(struct inet6_ifaddr *ip, struct inet6_ifaddr *list) +{ + while (list) { + if (!memcmp(&ip->addr.s6_addr, &list->addr.s6_addr, 16)) + return 1; + list = list->if_next; + } + return 0; +} + +static int +qeth_add_ifa6_to_list(struct inet6_ifaddr **list, struct inet6_ifaddr *ifa) +{ + struct inet6_ifaddr *i; + + if (*list == NULL) { + *list = ifa; + } else { + if (qeth_is_ipa_in_list6(ifa, *list)) + return -EALREADY; + i = *list; + while (i->if_next) { + i = i->if_next; + } + i->if_next = ifa; + } + ifa->if_next = NULL; + return 0; +} +#endif /* QETH_IPV6 */ + +static int +qeth_add_ifa_to_list(struct in_ifaddr **list, struct in_ifaddr *ifa) +{ + struct in_ifaddr *i; + + if (*list == NULL) { + *list = ifa; + } else { + if (qeth_is_ipa_in_list(ifa, *list)) + return -EALREADY; + i = *list; + while (i->ifa_next) { + i = i->ifa_next; + } + i->ifa_next = ifa; + } + ifa->ifa_next = NULL; + return 0; +} + +static void +__qeth_setips_ipv6(struct qeth_card *card, int use_setip_retries) +{ +#ifdef QETH_IPV6 + int result; + char dbf_text[15]; + struct inet6_ifaddr *addr6; + __u8 netmask[16]; + +#define FILL_NETMASK(len) { \ + int i,j; \ + for (i=0;i<16;i++) { \ + j=(len)-(i*8); \ + netmask[i]=(__u8)(0xFF00>>j); \ + } \ +} + /* here we go with IPv6 */ + addr6 = card->ip_current_state.ip6_ifa; + while (addr6) { + if (qeth_is_ipa_in_list6(addr6, card->ip_new_state.ip6_ifa)) { + addr6 = addr6->if_next; + continue; + } + QETH_DBF_TEXT3(0, trace, "setipdl6"); + QETH_DBF_HEX3(0, trace, &addr6->addr.s6_addr, + QETH_DBF_TRACE_LEN); + QETH_DBF_HEX3(0, trace, + ((char *) (&addr6->addr.s6_addr)) + + QETH_DBF_TRACE_LEN, QETH_DBF_TRACE_LEN); + sprintf(dbf_text, "nmsk%4u", addr6->prefix_len); + QETH_DBF_TEXT3(0, trace, dbf_text); + FILL_NETMASK(addr6->prefix_len); + result = qeth_send_delip(card, + (__u8 *) & addr6->addr.s6_addr, + (__u8 *) & netmask, 6); + if (result) { + PRINT_ERR("was not able to delete ip " + "%04x:%04x:%04x:%04x:%04x:%04x:" + "%04x:%04x/%u on device %s " + "(result: 0x%x), " + "trying to continue\n", + addr6->addr.s6_addr16[0], + addr6->addr.s6_addr16[1], + addr6->addr.s6_addr16[2], + addr6->addr.s6_addr16[3], + addr6->addr.s6_addr16[4], + addr6->addr.s6_addr16[5], + addr6->addr.s6_addr16[6], + addr6->addr.s6_addr16[7], + addr6->prefix_len, + card->rdev->dev.bus_id, result); + sprintf(dbf_text, "std6%4x", result); + QETH_DBF_TEXT3(0, trace, dbf_text); + } + addr6 = addr6->if_next; + } + + addr6 = card->ip_new_state.ip6_ifa; + while (addr6) { + if (qeth_is_ipa_in_list6(addr6, + card->ip_current_state.ip6_ifa)) { + addr6 = addr6->if_next; + continue; + } + QETH_DBF_TEXT3(0, trace, "setipst6"); + QETH_DBF_HEX3(0, trace, &addr6->addr.s6_addr, + QETH_DBF_TRACE_LEN); + QETH_DBF_HEX3(0, trace, + ((char *) (&addr6->addr.s6_addr)) + + QETH_DBF_TRACE_LEN, QETH_DBF_TRACE_LEN); + sprintf(dbf_text, "nmsk%4u", addr6->prefix_len); + QETH_DBF_TEXT3(0, trace, dbf_text); + FILL_NETMASK(addr6->prefix_len); + result = qeth_send_setip(card, + (__u8 *) & addr6->addr.s6_addr, + (__u8 *) & netmask, 6, + use_setip_retries); + if (!result) { + addr6 = addr6->if_next; + continue; + } + PRINT_ERR("was not able to set ip " + "%04x:%04x:%04x:%04x:%04x:%04x:" + "%04x:%04x/%u on device %s " + "(result: 0x%x), trying to continue\n", + addr6->addr.s6_addr16[0], + addr6->addr.s6_addr16[1], + addr6->addr.s6_addr16[2], + addr6->addr.s6_addr16[3], + addr6->addr.s6_addr16[4], + addr6->addr.s6_addr16[5], + addr6->addr.s6_addr16[6], + addr6->addr.s6_addr16[7], + addr6->prefix_len, + card->rdev->dev.bus_id, result); + sprintf(dbf_text, "sts6%4x", result); + QETH_DBF_TEXT3(0, trace, dbf_text); + addr6 = addr6->if_next; + } +#endif /* QETH_IPV6 */ +} + +static int +qeth_setips(struct qeth_card *card, int use_setip_retries) +{ + struct in_ifaddr *addr; + int result; + char dbf_text[15]; + + QETH_DBF_TEXT3(0, trace, "stip"); + QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id); + + addr = card->ip_current_state.ip_ifa; + while (addr) { + if (!qeth_is_ipa_in_list(addr, card->ip_new_state.ip_ifa)) { + QETH_DBF_TEXT3(0, trace, "setipdel"); + *((__u32 *) (&dbf_text[0])) = + *((__u32 *) & addr->ifa_address); + *((__u32 *) (&dbf_text[4])) = + *((__u32 *) & addr->ifa_mask); + QETH_DBF_HEX3(0, trace, dbf_text, QETH_DBF_TRACE_LEN); + result = + qeth_send_delip(card, (__u8 *) & addr->ifa_address, + (__u8 *) & addr->ifa_mask, 4); + if (result) { + PRINT_ERR("was not able to delete ip " + "%08x/%08x on device %s " + "(result: 0x%x), " + "trying to continue\n", + addr->ifa_address, addr->ifa_mask, + card->rdev->dev.bus_id, result); + sprintf(dbf_text, "stdl%4x", result); + QETH_DBF_TEXT3(0, trace, dbf_text); + } + } + addr = addr->ifa_next; + } + + addr = card->ip_new_state.ip_ifa; + while (addr) { + if (qeth_is_ipa_in_list(addr, card->ip_current_state.ip_ifa)) { + addr = addr->ifa_next; + continue; + } + QETH_DBF_TEXT3(0, trace, "setipset"); + *((__u32 *) (&dbf_text[0])) = *((__u32 *) & addr->ifa_address); + *((__u32 *) (&dbf_text[4])) = *((__u32 *) & addr->ifa_mask); + QETH_DBF_HEX3(0, trace, dbf_text, QETH_DBF_TRACE_LEN); + result = qeth_send_setip(card, (__u8 *) & addr->ifa_address, + (__u8 *) & addr->ifa_mask, 4, + use_setip_retries); + if (!result) { + addr = addr->ifa_next; + continue; + } + PRINT_ERR("was not able to set ip " + "%08x/%08x on device %s, trying to continue\n", + addr->ifa_address, addr->ifa_mask, + card->rdev->dev.bus_id); + sprintf(dbf_text, "stst%4x", result); + QETH_DBF_TEXT3(0, trace, dbf_text); + addr = addr->ifa_next; + } + + __qeth_setips_ipv6(card, use_setip_retries); + + return 0; +} + +static int +qeth_is_ipma_in_list(struct qeth_ipm_mac *ipma, struct qeth_ipm_mac *list) +{ + while (list) { + if ((!memcmp(ipma->ip, list->ip, 16)) && + (!memcmp(ipma->mac, list->mac, 6))) + return 1; + list = list->next; + } + return 0; +} + +static void +qeth_remove_mc_ifa_from_list(struct qeth_ipm_mac **list, + struct qeth_ipm_mac *ipma) +{ + struct qeth_ipm_mac *i, *li = NULL; + + if ((!(*list)) || (!ipma)) + return; + + if (*list == ipma) { + *list = ipma->next; + } else { + i = *list; + while (i) { + if (i == ipma) { + li->next = i->next; + } else { + li = i; + } + i = i->next; + } + } +} + +static int +qeth_add_mc_ifa_to_list(struct qeth_ipm_mac **list, struct qeth_ipm_mac *ipma) +{ + struct qeth_ipm_mac *i; + + if (qeth_is_ipma_in_list(ipma, *list)) + return -EALREADY; + + if (*list == NULL) { + *list = ipma; + } else { + i = *list; + while (i->next) { + i = i->next; + } + i->next = ipma; + } + ipma->next = NULL; + return 0; +} + +static void +__qeth_setipms_ipv6(struct qeth_card *card, int use_setipm_retries) +{ +#ifdef QETH_IPV6 + struct qeth_ipm_mac *addr; + int result; + char dbf_text[15]; + + /* here we go with IPv6 */ + addr = card->ip_mc_current_state.ipm6_ifa; + while (addr) { + if (!qeth_is_ipma_in_list(addr, + card->ip_mc_new_state.ipm6_ifa)) { + QETH_DBF_TEXT3(0, trace, "setimdl6"); + QETH_DBF_HEX3(0, trace, &addr->ip[0], + QETH_DBF_TRACE_LEN); + QETH_DBF_HEX3(0, trace, + (&addr->ip[0]) + QETH_DBF_TRACE_LEN, + QETH_DBF_TRACE_LEN); + QETH_DBF_HEX3(0, trace, &addr->mac, + QETH_DBF_TRACE_LEN); + result = qeth_send_delipm(card, + (__u8 *) & addr->ip[0], + (__u8 *) addr->mac, 6); + if (result) { + PRINT_ERR("was not able to delete " + "multicast ip %04x:%04x:" + "%04x:%04x:%04x:%04x:%04x:%04x/" + "%02x%02x%02x%02x%02x%02x " + "on device %s (result: 0x%x), " + "trying to continue\n", + *((__u16 *) & addr->ip[0]), + *((__u16 *) & addr->ip[2]), + *((__u16 *) & addr->ip[4]), + *((__u16 *) & addr->ip[6]), + *((__u16 *) & addr->ip[8]), + *((__u16 *) & addr->ip[10]), + *((__u16 *) & addr->ip[12]), + *((__u16 *) & addr->ip[14]), + addr->mac[0], addr->mac[1], + addr->mac[2], addr->mac[3], + addr->mac[4], addr->mac[5], + card->rdev->dev.bus_id, result); + sprintf(dbf_text, "smd6%4x", result); + QETH_DBF_TEXT3(0, trace, dbf_text); + } + } + addr = addr->next; + } + + addr = card->ip_mc_new_state.ipm6_ifa; + while (addr) { + if (qeth_is_ipma_in_list(addr, + card->ip_mc_current_state.ipm6_ifa)) { + addr = addr->next; + continue; + } + QETH_DBF_TEXT3(0, trace, "setimst6"); + QETH_DBF_HEX3(0, trace, &addr->ip[0], QETH_DBF_TRACE_LEN); + QETH_DBF_HEX3(0, trace, (&addr->ip[0]) + QETH_DBF_TRACE_LEN, + QETH_DBF_TRACE_LEN); + QETH_DBF_HEX3(0, trace, &addr->mac, QETH_DBF_TRACE_LEN); + result = qeth_send_setipm(card, + (__u8 *) & addr->ip[0], + (__u8 *) addr->mac, 6, + use_setipm_retries); + if (result) { + PRINT_ERR("was not able to set " + "multicast ip %04x:%04x:" + "%04x:%04x:%04x:%04x:%04x:%04x/" + "%02x%02x%02x%02x%02x%02x " + "on device %s (result: 0x%x), " + "trying to continue\n", + *((__u16 *) & addr->ip[0]), + *((__u16 *) & addr->ip[2]), + *((__u16 *) & addr->ip[4]), + *((__u16 *) & addr->ip[6]), + *((__u16 *) & addr->ip[8]), + *((__u16 *) & addr->ip[10]), + *((__u16 *) & addr->ip[12]), + *((__u16 *) & addr->ip[14]), + addr->mac[0], addr->mac[1], + addr->mac[2], addr->mac[3], + addr->mac[4], addr->mac[5], + card->rdev->dev.bus_id, result); + sprintf(dbf_text, "sms6%4x", result); + QETH_DBF_TEXT3(0, trace, dbf_text); + qeth_remove_mc_ifa_from_list + (&card->ip_mc_current_state.ipm6_ifa, addr); + } + addr = addr->next; + } +#endif /* QETH_IPV6 */ +} + +static int +qeth_setipms(struct qeth_card *card, int use_setipm_retries) +{ + struct qeth_ipm_mac *addr; + int result; + char dbf_text[15]; + + QETH_DBF_TEXT3(0, trace, "stim"); + QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id); + + if (!qeth_is_supported(IPA_MULTICASTING)) + return 0; + addr = card->ip_mc_current_state.ipm_ifa; + while (addr) { + if (!qeth_is_ipma_in_list(addr, + card->ip_mc_new_state.ipm_ifa)) { + QETH_DBF_TEXT3(0, trace, "setimdel"); + sprintf(dbf_text, "%08x", *((__u32 *) & addr->ip[0])); + QETH_DBF_TEXT3(0, trace, dbf_text); + *((__u32 *) (&dbf_text[0])) = *((__u32 *) & addr->mac); + *((__u32 *) (&dbf_text[4])) = + *(((__u32 *) & addr->mac) + 1); + QETH_DBF_HEX3(0, trace, dbf_text, + QETH_DBF_TRACE_LEN); + result = qeth_send_delipm(card, + (__u8 *) & addr->ip[0], + (__u8 *) addr->mac, 4); + if (result) { + PRINT_ERR("was not able to delete " + "multicast ip %08x/" + "%02x%02x%02x%02x%02x%02x " + "on device %s " + "(result: 0x%x), " + "trying to continue\n", + *((__u32 *) & addr->ip[0]), + addr->mac[0], addr->mac[1], + addr->mac[2], addr->mac[3], + addr->mac[4], addr->mac[5], + card->rdev->dev.bus_id, result); + sprintf(dbf_text, "smdl%4x", result); + QETH_DBF_TEXT3(0, trace, dbf_text); + } + } + addr = addr->next; + } + + addr = card->ip_mc_new_state.ipm_ifa; + while (addr) { + if (qeth_is_ipma_in_list(addr, + card->ip_mc_current_state.ipm_ifa)) { + addr = addr->next; + continue; + } + QETH_DBF_TEXT3(0, trace, "setimset"); + sprintf(dbf_text, "%08x", *((__u32 *) & addr->ip[0])); + QETH_DBF_TEXT3(0, trace, dbf_text); + *((__u32 *) (&dbf_text[0])) = *((__u32 *) & addr->mac); + *((__u32 *) (&dbf_text[4])) = *(((__u32 *) & addr->mac) + 1); + QETH_DBF_HEX3(0, trace, dbf_text, QETH_DBF_TRACE_LEN); + result = qeth_send_setipm(card, (__u8 *) & addr->ip[0], + (__u8 *) addr->mac, 4, + use_setipm_retries); + if (result) { + PRINT_ERR("was not able to set multicast ip %08x/" + "%02x%02x%02x%02x%02x%02x " + "on device %s (result: 0x%x), " + "trying to continue\n", + *((__u32 *) & addr->ip[0]), + addr->mac[0], addr->mac[1], + addr->mac[2], addr->mac[3], + addr->mac[4], addr->mac[5], + card->rdev->dev.bus_id, result); + sprintf(dbf_text, "smst%4x", result); + QETH_DBF_TEXT3(0, trace, dbf_text); + qeth_remove_mc_ifa_from_list + (&card->ip_mc_current_state.ipm_ifa, addr); + } + addr = addr->next; + } + __qeth_setipms_ipv6(card, use_setipm_retries); + return 0; +} + +static void +qeth_clone_ifa(struct in_ifaddr *src, struct in_ifaddr *dest) +{ + memcpy(dest, src, sizeof (struct in_ifaddr)); + dest->ifa_next = NULL; +} + +#ifdef QETH_IPV6 +static void +qeth_clone_ifa6(struct inet6_ifaddr *src, struct inet6_ifaddr *dest) +{ + memcpy(dest, src, sizeof (struct inet6_ifaddr)); + dest->if_next = NULL; +} +#endif /* QETH_IPV6 */ + +#define QETH_STANDARD_RETVALS \ + ret_val=-EIO; \ + if (result==IPA_REPLY_SUCCESS) ret_val=0; \ + if (result==IPA_REPLY_FAILED) ret_val=-EIO; \ + if (result==IPA_REPLY_OPNOTSUPP) ret_val=-EOPNOTSUPP + +static int +qeth_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + char *data; + int result, i, ret_val; + int version = 4; + struct qeth_card *card; + char dbf_text[15]; + char buff[100]; + + card = (struct qeth_card *) dev->priv; + + PRINT_STUPID("CALL: qeth_do_ioctl called with cmd %i (=0x%x).\n", cmd, + cmd); + QETH_DBF_TEXT2(0, trace, "ioct"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "cmd=%4x", cmd); + QETH_DBF_TEXT2(0, trace, dbf_text); + QETH_DBF_HEX2(0, trace, &rq, sizeof (void *)); + + if ((cmd < SIOCDEVPRIVATE) || (cmd > SIOCDEVPRIVATE + 5)) + return -EOPNOTSUPP; + copy_from_user(buff, rq->ifr_ifru.ifru_data, sizeof (buff)); + data = buff; + + if ((!atomic_read(&card->is_registered)) || + (!atomic_read(&card->is_hardsetup))) + return -ENODEV; + + if (atomic_read(&card->shutdown_phase)) + return -ENODEV; + + spin_lock(&card->ioctl_lock); + + if (atomic_read(&card->shutdown_phase)) { + ret_val = -ENODEV; + goto out; + } + if ((!atomic_read(&card->is_registered)) || + (!atomic_read(&card->is_hardsetup))) { + ret_val = -ENODEV; + goto out; + } + + switch (cmd) { + case SIOCDEVPRIVATE + 0: + if (!capable(CAP_NET_ADMIN)) { + ret_val = -EPERM; + break; + } + result = + qeth_send_setassparms(card, version, IPA_ARP_PROCESSING, + IPA_CMD_ASS_ARP_SET_NO_ENTRIES, + rq->ifr_ifru.ifru_ivalue, 4); + QETH_STANDARD_RETVALS; + if (result == 3) + ret_val = -EINVAL; + break; + case SIOCDEVPRIVATE + 1: + if (!capable(CAP_NET_ADMIN)) { + ret_val = -EPERM; + break; + } + result = qeth_queryarp(card, rq, version, IPA_ARP_PROCESSING, + IPA_CMD_ASS_ARP_QUERY_INFO, data, 4); + + QETH_STANDARD_RETVALS; + break; + case SIOCDEVPRIVATE + 2: + if (!capable(CAP_NET_ADMIN)) { + ret_val = -EPERM; + break; + } + for (i = 12; i < 24; i++) + if (data[i]) + version = 6; + result = + qeth_send_setassparms(card, version, IPA_ARP_PROCESSING, + IPA_CMD_ASS_ARP_ADD_ENTRY, + (long) data, 56); + QETH_STANDARD_RETVALS; + break; + case SIOCDEVPRIVATE + 3: + if (!capable(CAP_NET_ADMIN)) { + ret_val = -EPERM; + break; + } + for (i = 4; i < 12; i++) + if (data[i]) + version = 6; + result = + qeth_send_setassparms(card, version, IPA_ARP_PROCESSING, + IPA_CMD_ASS_ARP_REMOVE_ENTRY, + (long) data, 16); + QETH_STANDARD_RETVALS; + break; + case SIOCDEVPRIVATE + 4: + if (!capable(CAP_NET_ADMIN)) { + ret_val = -EPERM; + break; + } + result = + qeth_send_setassparms(card, version, IPA_ARP_PROCESSING, + IPA_CMD_ASS_ARP_FLUSH_CACHE, 0, 0); + QETH_STANDARD_RETVALS; + break; + case SIOCDEVPRIVATE + 5: + + result = + qeth_send_snmp_control(card, rq, IPA_CMD_SETADAPTERPARMS, + IPA_SETADP_SET_SNMP_CONTROL, data, + 4); + QETH_STANDARD_RETVALS; + break; + + default: + ret_val = -EOPNOTSUPP; + goto out; + } +out: + spin_unlock(&card->ioctl_lock); + + sprintf(dbf_text, "ret=%4x", ret_val); + QETH_DBF_TEXT2(0, trace, dbf_text); + + return ret_val; +} + +static void +qeth_clear_ifamc_list(struct qeth_ipm_mac **ifa_list) +{ + struct qeth_ipm_mac *ifa; + while (*ifa_list) { + ifa = *ifa_list; + *ifa_list = ifa->next; + kfree(ifa); + } +} + +#ifdef QETH_IPV6 +static void +qeth_clear_ifa6_list(struct inet6_ifaddr **ifa_list) +{ + struct inet6_ifaddr *ifa; + while (*ifa_list) { + ifa = *ifa_list; + *ifa_list = ifa->if_next; + kfree(ifa); + } +} + +static inline void +__qeth_append_vlan_ipas_v6(struct qeth_card *card) +{ +#ifdef QETH_VLAN + char dbf_text[15]; + struct vlan_group *card_group; + int i; + int remove; + struct inet6_ifaddr *ifa, *ifanew; + + /* + * append all known VLAN IP Addresses corresponding to the real device + * card->dev->ifindex + */ + QETH_DBF_TEXT4(0, trace, "to-vip6s"); + if ((!qeth_is_supported(IPA_FULL_VLAN)) || (!atomic_read(&card->is_open))) + return; + + card_group = (struct vlan_group *) card->vlangrp; + + if (!card_group) + return; + for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { + if (!card_group->vlan_devices[i] || + !(card_group->vlan_devices[i]->flags & IFF_UP) || + !(struct inet6_dev *) card_group->vlan_devices[i]->ip6_ptr) + continue; + ifa = ((struct inet6_dev *) + card_group->vlan_devices[i]->ip6_ptr)->addr_list; + + while (ifa) { + ifanew = kmalloc(sizeof(struct inet6_ifaddr), + GFP_KERNEL); + if (!ifanew) { + PRINT_WARN("No memory for IP address " + "handling. Some of the IPs " + "will not be set on %s.\n", + card->dev_name); + QETH_DBF_TEXT2(0, trace, "TOIPNMEM"); + } else { + qeth_clone_ifa6(ifa, ifanew); + remove = qeth_add_ifa6_to_list + (&card->ip_new_state.ip6_ifa, ifanew); + QETH_DBF_HEX4(0, trace, + &ifanew->addr.s6_addr, + QETH_DBF_TRACE_LEN); + QETH_DBF_HEX4(0, trace, + &ifanew->addr.s6_addr + + QETH_DBF_TRACE_LEN, + QETH_DBF_TRACE_LEN); + sprintf(dbf_text, "pref%4u", ifanew->prefix_len); + QETH_DBF_TEXT4(0, trace, dbf_text); + if (remove) { + kfree(ifanew); + QETH_DBF_TEXT4(0, trace, "alrdv6rm"); + } + } + ifa = ifa->if_next; + } + } +#endif +} + +static inline void +__qeth_append_vlan_ipas_v6_mc(struct qeth_card *card) +{ +#ifdef QETH_VLAN + struct vlan_group *card_group; + int i; + int remove; + struct inet6_dev *in6_vdev; + char buf[MAX_ADDR_LEN]; + struct qeth_ipm_mac *ipmanew; + struct ifmcaddr6 *im6; + + QETH_DBF_TEXT4(0, trace, "tovipm6s"); + if (!qeth_is_supported(IPA_FULL_VLAN) || !atomic_read(&card->is_open)) + return; + + card_group = (struct vlan_group *) card->vlangrp; + if (!card_group) + return; + + for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { + if (!card_group->vlan_devices[i] || + !(card_group->vlan_devices[i]->flags & IFF_UP)) + continue; + + in6_vdev = in6_dev_get(card_group->vlan_devices[i]); + if (!in6_vdev) { + QETH_DBF_TEXT2(0, trace, "id26"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + continue; + } + + read_lock(&in6_vdev->lock); + for (im6 = in6_vdev->mc_list; im6; im6 = im6->next) { + ndisc_mc_map(&im6->mca_addr, buf, + card_group->vlan_devices[i], 0); + ipmanew = (struct qeth_ipm_mac *) + kmalloc(sizeof(struct qeth_ipm_mac), GFP_KERNEL); + if (!ipmanew) { + PRINT_WARN("No memory for IPM address " + "handling. Multicast IP " + "%04x:%04x:%04x:%04x:%04x:" + "%04x:%04x:%04x" + "will not be set on %s.\n", + im6->mca_addr.s6_addr16[0], + im6->mca_addr.s6_addr16[1], + im6->mca_addr.s6_addr16[2], + im6->mca_addr.s6_addr16[3], + im6->mca_addr.s6_addr16[4], + im6->mca_addr.s6_addr16[5], + im6->mca_addr.s6_addr16[6], + im6->mca_addr.s6_addr16[7], + card->dev_name); + QETH_DBF_TEXT2(0, trace, "TOIPMNMM"); + } else { + memset(ipmanew, 0, sizeof(struct qeth_ipm_mac)); + memcpy(ipmanew->mac, buf,OSA_ADDR_LEN); + memcpy(ipmanew->ip, im6->mca_addr.s6_addr, 16); + ipmanew->next = NULL; + remove = qeth_add_mc_ifa_to_list + (&card->ip_mc_new_state.ipm6_ifa, + ipmanew); + QETH_DBF_HEX4(0, trace, &ipmanew->ip, + QETH_DBF_TRACE_LEN); + QETH_DBF_HEX4(0, trace, &ipmanew->ip + + QETH_DBF_TRACE_LEN, + QETH_DBF_TRACE_LEN); + QETH_DBF_HEX4(0, trace, &ipmanew->mac, + QETH_DBF_TRACE_LEN); + + if (remove) { + QETH_DBF_TEXT4(0, trace, "mlrdv6rm"); + kfree(ipmanew); + } + } + } + read_unlock(&in6_vdev->lock); + in6_dev_put(in6_vdev); + } +#endif +} + +static struct inet6_dev * +__qeth_get_mc_lock_v6(struct qeth_card *card) +{ + struct inet6_dev *in6_dev; + + in6_dev = in6_dev_get(card->dev); + + if (!in6_dev) { + QETH_DBF_TEXT2(0, trace, "id16"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + return ERR_PTR(-ENODEV); + } + read_lock(&in6_dev->lock); + return in6_dev; +} + +static void +__qeth_takeover_ip_ipms6_mc(struct qeth_card *card, struct inet6_dev *in6_dev) +{ + int remove; + struct qeth_ipm_mac *ipmanew; + struct ifmcaddr6 *im6; + char buf[MAX_ADDR_LEN]; + + QETH_DBF_TEXT4(0, trace, "to-ipm6s"); + if (atomic_read(&card->is_open)) + for (im6 = in6_dev->mc_list; im6; im6 = im6->next) { + ndisc_mc_map(&im6->mca_addr, buf, card->dev, 0); + ipmanew = + (struct qeth_ipm_mac *) + kmalloc(sizeof (struct qeth_ipm_mac), GFP_KERNEL); + if (!ipmanew) { + PRINT_WARN("No memory for IPM address " + "handling. Multicast IP " + "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x" + "will not be set on %s.\n", + im6->mca_addr.s6_addr16[0], + im6->mca_addr.s6_addr16[1], + im6->mca_addr.s6_addr16[2], + im6->mca_addr.s6_addr16[3], + im6->mca_addr.s6_addr16[4], + im6->mca_addr.s6_addr16[5], + im6->mca_addr.s6_addr16[6], + im6->mca_addr.s6_addr16[7], + card->dev_name); + QETH_DBF_TEXT2(0, trace, "TOIPMNMM"); + } else { + memset(ipmanew, 0, + sizeof (struct qeth_ipm_mac)); + memcpy(ipmanew->mac, buf, OSA_ADDR_LEN); + memcpy(ipmanew->ip, im6->mca_addr.s6_addr, 16); + ipmanew->next = NULL; + remove = + qeth_add_mc_ifa_to_list(&card-> + ip_mc_new_state. + ipm6_ifa, ipmanew); + QETH_DBF_HEX4(0, trace, &ipmanew->ip, + QETH_DBF_TRACE_LEN); + QETH_DBF_HEX4(0, trace, + &ipmanew->ip + QETH_DBF_TRACE_LEN, + QETH_DBF_TRACE_LEN); + QETH_DBF_HEX4(0, trace, &ipmanew->mac, + QETH_DBF_TRACE_LEN); + if (remove) { + QETH_DBF_TEXT4(0, trace, "mlrdy6rm"); + kfree(ipmanew); + } + } + } + __qeth_append_vlan_ipas_v6_mc(card); + + read_unlock(&in6_dev->lock); + in6_dev_put(in6_dev); +} +#endif /* QETH_IPV6 */ + +static void +qeth_takeover_ip_ipms6(struct qeth_card *card) +{ +#ifdef QETH_IPV6 + struct inet6_ifaddr *ifa, *ifanew; + char dbf_text[15]; + int remove; + struct inet6_dev *in6_dev; + + QETH_DBF_TEXT3(0, trace, "tip6"); + QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id); + /* unicast */ + /* clear ip_current_state */ + qeth_clear_ifa6_list(&card->ip_current_state.ip6_ifa); + /* take it over */ + card->ip_current_state.ip6_ifa = card->ip_new_state.ip6_ifa; + card->ip_new_state.ip6_ifa = NULL; + + in6_dev = __qeth_get_mc_lock_v6(card); + if (PTR_ERR(in6_dev) == -ENODEV) + return; + /* get new one, we try to have the same order as ifa_list in device + structure, for what reason ever */ + QETH_DBF_TEXT4(0, trace, "to-ip6s"); + if ((atomic_read(&card->is_open)) && (card->dev->ip6_ptr) && + (((struct inet6_dev *) card->dev->ip6_ptr)->addr_list)) { + ifa = ((struct inet6_dev *) card->dev->ip6_ptr)->addr_list; + + while (ifa) { + ifanew = + kmalloc(sizeof (struct inet6_ifaddr), GFP_KERNEL); + if (!ifanew) { + PRINT_WARN("No memory for IP address " + "handling. Some of the IPs " + "will not be set on %s.\n", + card->dev_name); + QETH_DBF_TEXT2(0, trace, "TOIPNMEM"); + } else { + qeth_clone_ifa6(ifa, ifanew); + remove = + qeth_add_ifa6_to_list(&card->ip_new_state. + ip6_ifa, ifanew); + QETH_DBF_HEX4(0, trace, &ifanew->addr.s6_addr, + QETH_DBF_TRACE_LEN); + QETH_DBF_HEX4(0, trace, + &ifanew->addr.s6_addr + + QETH_DBF_TRACE_LEN, + QETH_DBF_TRACE_LEN); + sprintf(dbf_text, "pref%4u", + ifanew->prefix_len); + QETH_DBF_TEXT4(0, trace, dbf_text); + if (remove) { + kfree(ifanew); + QETH_DBF_TEXT4(0, trace, "alrdy6rm"); + } + } + ifa = ifa->if_next; + } + } + + __qeth_append_vlan_ipas_v6(card); + + __qeth_takeover_ip_ipms6_mc(card, in6_dev); +#endif /* QETH_IPV6 */ +} + +static void +qeth_clear_ifa4_list(struct in_ifaddr **ifa_list) +{ + struct in_ifaddr *ifa; + while (*ifa_list) { + ifa = *ifa_list; + *ifa_list = ifa->ifa_next; + kfree(ifa); + } +} + +static inline void +__qeth_append_vlan_ipas_v4(struct qeth_card *card) +{ +#ifdef QETH_VLAN + struct in_ifaddr *ifa, *ifanew; + char dbf_text[15]; + struct vlan_group *card_group; + int i; + int remove; + struct in_device *vin4_dev; + + /* + * append all known VLAN IP Addresses corresponding to the real device + * card->dev->ifindex + */ + QETH_DBF_TEXT4(0, trace, "to-vips"); + if (!qeth_is_supported(IPA_FULL_VLAN) || !atomic_read(&card->is_open)) + return; + + card_group = (struct vlan_group *) card->vlangrp; + if (!card_group) + return; + + for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { + vin4_dev = in_dev_get(card->dev); + if (!vin4_dev) { + QETH_DBF_TEXT2(0, trace, "nodvhol2"); + QETH_DBF_TEXT2(0, trace, card->dev_name); + continue; + } + read_lock(&vin4_dev->lock); + + if ((card_group->vlan_devices[i]) && + (card_group->vlan_devices[i]->flags & IFF_UP)) { + ifa = ((struct in_device *) + card_group->vlan_devices[i]->ip_ptr)->ifa_list; + while (ifa) { + ifanew = kmalloc(sizeof(struct in_ifaddr), + GFP_KERNEL); + if (!ifanew) { + PRINT_WARN("No memory for IP address " + "handling. Some of the IPs " + "will not be set on %s.\n", + card->dev_name); + QETH_DBF_TEXT2(0, trace, "TOIPNMEM"); + } else { + qeth_clone_ifa(ifa, ifanew); + remove = qeth_add_ifa_to_list + (&card->ip_new_state.ip_ifa, + ifanew); + *((__u32*) (&dbf_text[0])) = + *((__u32*) &ifanew->ifa_address); + *((__u32*) (&dbf_text[4])) = + *((__u32*) &ifanew->ifa_mask); + QETH_DBF_TEXT4(0, trace, dbf_text); + if (remove) { + kfree(ifanew); + QETH_DBF_TEXT4(0, trace, + "alrdv4rm"); + } + } + ifa = ifa->ifa_next; + } + } + + read_unlock(&vin4_dev->lock); + in_dev_put(vin4_dev); + } +#endif /* QETH_VLAN */ + +} + +static inline void +__qeth_append_vlan_ipas_v4_mc(struct qeth_card *card) +{ +#ifdef QETH_VLAN + char dbf_text[15]; + int i; + int remove; + struct vlan_group *card_group; + struct in_device *vin4_dev; + struct qeth_ipm_mac *ipmanew; + struct ip_mc_list *im4; + char buf[MAX_ADDR_LEN]; + __u32 maddr; + + QETH_DBF_TEXT4(0, trace, "to-vipms"); + if (!qeth_is_supported(IPA_FULL_VLAN) || !atomic_read(&card->is_open)) + return; + + card_group = (struct vlan_group *) card->vlangrp; + if (!card_group) + return; + + for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { + if (!card_group->vlan_devices[i] || + !(card_group->vlan_devices[i]->flags & IFF_UP)) + continue; + + vin4_dev = in_dev_get(card_group->vlan_devices[i]); + if (!vin4_dev) { + QETH_DBF_TEXT2(0, trace, "novdhol3"); + QETH_DBF_TEXT2(0, trace, card->dev_name); + QETH_DBF_TEXT2(0, trace, + card_group->vlan_devices[i]->name); + continue; + } + read_lock(&vin4_dev->lock); + for (im4 = vin4_dev->mc_list; im4; im4 = im4->next) { + qeth_get_mac_for_ipm(im4->multiaddr, buf, vin4_dev->dev); + ipmanew = (struct qeth_ipm_mac *) + kmalloc(sizeof(struct qeth_ipm_mac), GFP_KERNEL); + if (!ipmanew) { + PRINT_WARN("No memory for IPM address " + "handling. Multicast VLAN IP %08x" + "will not be set on %s.\n", + (__u32) im4->multiaddr, + card->dev_name); + QETH_DBF_TEXT2(0, trace, "TOIPMNMM"); + } else { + memset(ipmanew, 0, sizeof(struct qeth_ipm_mac)); + memcpy(ipmanew->mac, buf, OSA_ADDR_LEN); + maddr = im4->multiaddr; + memcpy(&(ipmanew->ip[0]), &maddr, 4); + memset(&(ipmanew->ip[4]), 0xff, 12); + ipmanew->next = NULL; + remove = qeth_add_mc_ifa_to_list + (&card->ip_mc_new_state.ipm_ifa, + ipmanew); + sprintf(dbf_text, "%08x", + *((__u32 *) &ipmanew->ip)); + QETH_DBF_TEXT4(0, trace, dbf_text); + QETH_DBF_HEX4(0, trace, &ipmanew->mac, + QETH_DBF_TRACE_LEN); + if (remove) { + QETH_DBF_TEXT4(0, trace, "mlrdv4rm"); + kfree(ipmanew); + } + } + } + read_unlock(&vin4_dev->lock); + in_dev_put(vin4_dev); + } +#endif /* QETH_VLAN */ + +} + +static struct in_device * +__qeth_get_mc_lock(struct qeth_card *card) +{ + struct in_device *in4_dev; + + /* multicast */ + /* clear ip_mc_current_state */ + qeth_clear_ifamc_list(&card->ip_mc_current_state.ipm_ifa); + /* take it over */ + card->ip_mc_current_state.ipm_ifa = card->ip_mc_new_state.ipm_ifa; + /* get new one, we try to have the same order as ifa_list in device + structure, for what reason ever */ + card->ip_mc_new_state.ipm_ifa = NULL; + + in4_dev = in_dev_get(card->dev); + if (!in4_dev) { + QETH_DBF_TEXT2(0, trace, "nodvhol1"); + QETH_DBF_TEXT2(0, trace, card->dev_name); + return ERR_PTR(-ENODEV); + } + read_lock(&in4_dev->lock); + return in4_dev; +} + +static void +__qeth_takeover_ip_ipms_mc(struct qeth_card *card, struct in_device *in4_dev) +{ + char dbf_text[15]; + int remove; + struct qeth_ipm_mac *ipmanew; + struct ip_mc_list *im4; + char buf[MAX_ADDR_LEN]; + __u32 maddr; + + QETH_DBF_TEXT4(0, trace, "to-ipms"); + if (atomic_read(&card->is_open)) + for (im4 = in4_dev->mc_list; im4; im4 = im4->next) { + qeth_get_mac_for_ipm(im4->multiaddr, buf, in4_dev->dev); + ipmanew = + (struct qeth_ipm_mac *) + kmalloc(sizeof (struct qeth_ipm_mac), GFP_KERNEL); + if (!ipmanew) { + PRINT_WARN("No memory for IPM address " + "handling. Multicast IP %08x" + "will not be set on %s.\n", + (__u32) im4->multiaddr, + card->dev_name); + QETH_DBF_TEXT2(0, trace, "TOIPMNMM"); + } else { + memset(ipmanew, 0, + sizeof (struct qeth_ipm_mac)); + memcpy(ipmanew->mac, buf, OSA_ADDR_LEN); + maddr = im4->multiaddr; + memcpy(&(ipmanew->ip[0]), &maddr, 4); + memset(&(ipmanew->ip[4]), 0xff, 12); + ipmanew->next = NULL; + remove = + qeth_add_mc_ifa_to_list(&card-> + ip_mc_new_state. + ipm_ifa, ipmanew); + sprintf(dbf_text, "%08x", + *((__u32 *) & ipmanew->ip)); + QETH_DBF_TEXT4(0, trace, dbf_text); + QETH_DBF_HEX4(0, trace, &ipmanew->mac, + QETH_DBF_TRACE_LEN); + if (remove) { + QETH_DBF_TEXT4(0, trace, "mlrdy4rm"); + kfree(ipmanew); + } + } + } + __qeth_append_vlan_ipas_v4(card); + + read_unlock(&in4_dev->lock); + in_dev_put(in4_dev); + +} + +static void +qeth_takeover_ip_ipms(struct qeth_card *card) +{ + struct in_ifaddr *ifa, *ifanew; + char dbf_text[15]; + int remove; + struct in_device *in4_dev; + + QETH_DBF_TEXT3(0, trace, "tips"); + QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id); + /* unicast */ + /* clear ip_current_state */ + qeth_clear_ifa4_list(&card->ip_current_state.ip_ifa); + /* take it over */ + card->ip_current_state.ip_ifa = card->ip_new_state.ip_ifa; + card->ip_new_state.ip_ifa = NULL; + + in4_dev = __qeth_get_mc_lock(card); + if (PTR_ERR(in4_dev) == -ENODEV) + return; + + /* get new one, we try to have the same order as ifa_list in device + structure, for what reason ever */ + QETH_DBF_TEXT4(0, trace, "to-ips"); + if ((atomic_read(&card->is_open)) && (card->dev->ip_ptr) && + (((struct in_device *) card->dev->ip_ptr)->ifa_list)) { + ifa = ((struct in_device *) card->dev->ip_ptr)->ifa_list; + + while (ifa) { + ifanew = kmalloc(sizeof (struct in_ifaddr), GFP_KERNEL); + if (!ifanew) { + PRINT_WARN("No memory for IP address " + "handling. Some of the IPs " + "will not be set on %s.\n", + card->dev_name); + QETH_DBF_TEXT2(0, trace, "TOIPNMEM"); + } else { + qeth_clone_ifa(ifa, ifanew); + remove = + qeth_add_ifa_to_list(&card->ip_new_state. + ip_ifa, ifanew); + *((__u32 *) (&dbf_text[0])) = + *((__u32 *) & ifanew->ifa_address); + *((__u32 *) (&dbf_text[4])) = + *((__u32 *) & ifanew->ifa_mask); + QETH_DBF_TEXT4(0, trace, dbf_text); + if (remove) { + kfree(ifanew); + QETH_DBF_TEXT4(0, trace, "alrdy4rm"); + } + } + + ifa = ifa->ifa_next; + } + } + __qeth_append_vlan_ipas_v4(card); + + __qeth_takeover_ip_ipms_mc(card, in4_dev); +} + +static void +qeth_get_unique_id(struct qeth_card *card) +{ +#ifdef QETH_IPV6 + struct ipa_cmd cmd; + int result; + char dbf_text[15]; + + if (!qeth_is_supported(IPA_IPv6)) { + card->unique_id = UNIQUE_ID_IF_CREATE_ADDR_FAILED | + UNIQUE_ID_NOT_BY_CARD; + return; + } + qeth_fill_ipa_cmd(card, &cmd, IPA_CMD_CREATE_ADDR, 6); + + *((__u16 *) & cmd.data.create_destroy_addr.unique_id[6]) = + card->unique_id; + + result = qeth_send_ipa_cmd(card, &cmd, 1, IPA_CMD_STATE); + + if (result) { + card->unique_id = UNIQUE_ID_IF_CREATE_ADDR_FAILED | + UNIQUE_ID_NOT_BY_CARD; + PRINT_WARN("couldn't get a unique id from the card on device " + "%s (result=x%x), using default id. ipv6 " + "autoconfig on other lpars may lead to duplicate " + "ip addresses. please use manually " + "configured ones.\n", + card->rdev->dev.bus_id, result); + QETH_DBF_TEXT2(0, trace, "unid fld"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "%4x", result); + QETH_DBF_TEXT2(0, trace, dbf_text); + } else { + card->unique_id = + *((__u16 *) & cmd.data.create_destroy_addr.unique_id[6]); + QETH_DBF_TEXT2(0, setup, "uniqueid"); + QETH_DBF_TEXT2(0, setup, card->rdev->dev.bus_id); + sprintf(dbf_text, "%4x", card->unique_id); + QETH_DBF_TEXT2(0, setup, dbf_text); + } +#else /* QETH_IPV6 */ + card->unique_id = + UNIQUE_ID_IF_CREATE_ADDR_FAILED | UNIQUE_ID_NOT_BY_CARD; +#endif /* QETH_IPV6 */ +} + +static void +qeth_put_unique_id(struct qeth_card *card) +{ +#ifdef QETH_IPV6 + struct ipa_cmd cmd; + int result; + char dbf_text[15]; + + /* is also true, if ipv6 is not supported on the card */ + if ((card->unique_id & UNIQUE_ID_NOT_BY_CARD) == UNIQUE_ID_NOT_BY_CARD) + return; + + qeth_fill_ipa_cmd(card, &cmd, IPA_CMD_DESTROY_ADDR, 6); + *((__u16 *) & cmd.data.create_destroy_addr.unique_id[6]) = + card->unique_id; + memcpy(&cmd.data.create_destroy_addr.unique_id[0], card->dev->dev_addr, + OSA_ADDR_LEN); + + result = qeth_send_ipa_cmd(card, &cmd, 1, IPA_CMD_STATE); + + if (result) { + QETH_DBF_TEXT2(0, trace, "unibkfld"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "%4x", result); + QETH_DBF_TEXT2(0, trace, dbf_text); + } +#else /* QETH_IPV6 */ + card->unique_id = + UNIQUE_ID_IF_CREATE_ADDR_FAILED | UNIQUE_ID_NOT_BY_CARD; +#endif /* QETH_IPV6 */ +} + +static inline void +__qeth_setparms_hstr(struct qeth_card *card) +{ + char dbf_text[15]; + int result; + + if ((card->link_type != QETH_MPC_LINK_TYPE_HSTR) && + (card->link_type != QETH_MPC_LINK_TYPE_LANE_TR)) + return; + + QETH_DBF_TEXT3(0, trace, "hstr"); + QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id); + + if (qeth_is_adp_supported(IPA_SETADP_SET_BROADCAST_MODE)) { + result = qeth_send_setadapterparms_mode + (card, IPA_SETADP_SET_BROADCAST_MODE, + card->options.broadcast_mode); + if (result) { + PRINT_WARN("couldn't set broadcast mode on " + "device %s: x%x\n", + card->rdev->dev.bus_id, result); + QETH_DBF_TEXT1(0, trace, "STBRDCST"); + QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "%4x", result); + QETH_DBF_TEXT1(1, trace, dbf_text); + } + } else if (card->options.broadcast_mode) { + PRINT_WARN("set adapter parameters not available " + "to set broadcast mode, using ALLRINGS " + "on device %s:\n", card->rdev->dev.bus_id); + QETH_DBF_TEXT1(0, trace, "NOBC"); + QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id); + } + + if (qeth_is_adp_supported(IPA_SETADP_SET_BROADCAST_MODE)) { + result = qeth_send_setadapterparms_mode + (card, IPA_SETADP_ALTER_MAC_ADDRESS, + card->options.macaddr_mode); + if (result) { + PRINT_WARN("couldn't set macaddr mode on " + "device %s: x%x\n", card->rdev->dev.bus_id, + result); + QETH_DBF_TEXT1(0, trace, "STMACMOD"); + QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "%4x", result); + QETH_DBF_TEXT1(1, trace, dbf_text); + } + } else if (card->options.macaddr_mode) { + PRINT_WARN("set adapter parameters not available " + "to set macaddr mode, using NONCANONICAL " + "on device %s:\n", card->rdev->dev.bus_id); + QETH_DBF_TEXT1(0, trace, "NOMA"); + QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id); + } +} + +static void +qeth_do_setadapterparms_stuff(struct qeth_card *card) +{ + int result; + char dbf_text[15]; + + if (!qeth_is_supported(IPA_SETADAPTERPARMS)) { + return; + } + + QETH_DBF_TEXT4(0, trace, "stap"); + QETH_DBF_TEXT4(0, trace, card->rdev->dev.bus_id); + + result = qeth_send_setadapterparms_query(card); + + if (result) { + PRINT_WARN("couldn't set adapter parameters on device %s: " + "x%x\n", card->rdev->dev.bus_id, result); + QETH_DBF_TEXT1(0, trace, "SETADPFL"); + QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "%4x", result); + QETH_DBF_TEXT1(1, trace, dbf_text); + return; + } + + sprintf(dbf_text, "spap%4x", card->adp_supported); + QETH_DBF_TEXT2(0, trace, dbf_text); + + if (qeth_is_adp_supported(IPA_SETADP_ALTER_MAC_ADDRESS)) { + QETH_DBF_TEXT3(0, trace, "rdmc"); + QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id); + QETH_DBF_TEXT2(0, setup, "rdmc"); + QETH_DBF_TEXT2(0, setup, card->rdev->dev.bus_id); + + result = qeth_send_setadapterparms_change_addr(card, + IPA_SETADP_ALTER_MAC_ADDRESS, + CHANGE_ADDR_READ_MAC, + card->dev-> + dev_addr, + OSA_ADDR_LEN); + if (result) { + PRINT_WARN("couldn't get MAC address on " + "device %s: x%x\n", + card->rdev->dev.bus_id, result); + QETH_DBF_TEXT1(0, trace, "NOMACADD"); + QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "%4x", result); + QETH_DBF_TEXT1(1, trace, dbf_text); + } else { + QETH_DBF_HEX2(0, setup, card->dev->dev_addr, + __max(OSA_ADDR_LEN, QETH_DBF_SETUP_LEN)); + QETH_DBF_HEX3(0, trace, card->dev->dev_addr, + __max(OSA_ADDR_LEN, QETH_DBF_TRACE_LEN)); + } + } + __qeth_setparms_hstr(card); +} + +static inline void +__qeth_start_vlan_assist(struct qeth_card *card) +{ +#ifdef QETH_VLAN + char dbf_text[15]; + int result; + + if (!qeth_is_supported(IPA_FULL_VLAN)) { + PRINT_WARN("VLAN not supported on %s\n", + card->dev_name); + QETH_DBF_TEXT2(0, trace, "vlnotsup"); + return; + } + result = qeth_send_setassparms_simple_without_data(card, + IPA_VLAN_PRIO, + IPA_CMD_ASS_START); + QETH_DBF_TEXT2(0, trace, "enavlan"); + if (result) { + PRINT_WARN("Could not start vlan " + "assist on %s: 0x%x, continuing\n", + card->dev_name, result); + sprintf(dbf_text, "VLAN%4x", result); + QETH_DBF_TEXT2(0, trace, dbf_text); + return; + } + card->dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; +#endif /* QETH_VLAN */ +} + +static inline void +__qeth_start_mc_assist(struct qeth_card *card) +{ + char dbf_text[15]; + int result; + + if (!qeth_is_supported(IPA_MULTICASTING)) { + PRINT_WARN("multicasting not supported on %s\n", + card->dev_name); + QETH_DBF_TEXT2(0, trace, "mcnotsup"); + return; + } + result = qeth_send_setassparms_simple_without_data(card, + IPA_MULTICASTING, + IPA_CMD_ASS_START); + QETH_DBF_TEXT2(0, trace, "enamcass"); + if (result) { + PRINT_WARN("Could not start multicast " + "assist on %s: 0x%x, continuing\n", + card->dev_name, result); + sprintf(dbf_text, "MCAS%4x", result); + QETH_DBF_TEXT2(0, trace, dbf_text); + return; + } + card->dev->flags |= IFF_MULTICAST; +} + +static int +__qeth_softsetup_enable_ipv6(struct qeth_card *card, int do_a_startlan6) +{ + int result; + char dbf_text[15]; + + if (do_a_startlan6) { + QETH_DBF_TEXT2(0, trace, "startln6"); + netif_stop_queue(card->dev); + result = qeth_send_startlan(card, 6); + if (result) { + sprintf(dbf_text, "stl6%4x", result); + QETH_DBF_TEXT2(0, trace, dbf_text); + atomic_set(&card->is_softsetup, 0); + /* do not return an error */ + if (result == 0xe080) + result = 0; + return result; + } + } + netif_wake_queue(card->dev); + + QETH_DBF_TEXT2(0, trace, "qipassi6"); + result = qeth_send_qipassist(card, 6); + if (result) { + PRINT_WARN("couldn't send QIPASSIST6 on %s: 0x%x\n", + card->dev_name, result); + sprintf(dbf_text, "QIP6%4x", result); + QETH_DBF_TEXT2(0, trace, dbf_text); + atomic_set(&card->is_softsetup, 0); + return result; + } + + sprintf(dbf_text, "%4x%4x", card->ipa6_supported, card->ipa6_enabled); + QETH_DBF_TEXT2(0, trace, dbf_text); + + QETH_DBF_TEXT2(0, trace, "enaipv46"); + result = qeth_send_setassparms_simple_with_data(card, IPA_IPv6, + IPA_CMD_ASS_START, 3); + if (result) { + PRINT_WARN("Could not enable IPv4&6 assist " + "on %s: 0x%x, continuing\n", + card->dev_name, result); + sprintf(dbf_text, "I46A%4x", result); + QETH_DBF_TEXT2(0, trace, dbf_text); + /* go on */ + } + + QETH_DBF_TEXT2(0, trace, "enaipv6"); + result = qeth_send_setassparms_simple_without_data6(card, IPA_IPv6, + IPA_CMD_ASS_START); + if (result) { + PRINT_WARN("Could not start IPv6 assist " + "on %s: 0x%x, continuing\n", + card->dev_name, result); + sprintf(dbf_text, "I6AS%4x", result); + QETH_DBF_TEXT2(0, trace, dbf_text); + /* go on */ + } + + QETH_DBF_TEXT2(0, trace, "enapstr6"); + result = qeth_send_setassparms_simple_without_data6(card, IPA_PASSTHRU, + IPA_CMD_ASS_START); + if (result) { + PRINT_WARN("Could not enable passthrough " + "on %s: 0x%x, continuing\n", + card->dev_name, result); + sprintf(dbf_text, "PSTR%4x", result); + QETH_DBF_TEXT2(0, trace, dbf_text); + /* go on */ + } + return 0; +} + +static int +__qeth_softsetup_start_assists(struct qeth_card *card) +{ + int result; + char dbf_text[15]; + int do_a_startlan6 = 0; + + if (atomic_read(&card->is_softsetup)) + return 0; + + atomic_set(&card->enable_routing_attempts4, QETH_ROUTING_ATTEMPTS); +#ifdef QETH_IPV6 + atomic_set(&card->enable_routing_attempts6, QETH_ROUTING_ATTEMPTS); +#endif /* QETH_IPV6 */ + if ((!atomic_read(&card->is_startlaned)) && + (atomic_read(&card->startlan_attempts))) { + atomic_dec(&card->startlan_attempts); + QETH_DBF_TEXT2(0, trace, "startlan"); + netif_stop_queue(card->dev); + result = qeth_send_startlan(card, 4); + if (result) { + PRINT_WARN("couldn't send STARTLAN on %s " + "(CHPID 0x%X): 0x%x (%s)\n", + card->dev_name, card->chpid, result, + (result == 0xe080) ? + "startlan disabled (link " + "failure -- please check the " + "network, plug in the cable or " + "enable the OSA port" : + "unknown return code"); + sprintf(dbf_text, "stln%4x", result); + QETH_DBF_TEXT2(0, trace, dbf_text); + atomic_set(&card->is_softsetup, 0); + atomic_set(&card->is_startlaned, 0); + /* do not return an error */ + if (result == 0xe080) { + result = 0; + } + return result; + } + do_a_startlan6 = 1; + } + netif_wake_queue(card->dev); + + qeth_do_setadapterparms_stuff(card); + + if (!qeth_is_supported(IPA_ARP_PROCESSING)) { + PRINT_WARN("oops... ARP processing not supported " + "on %s!\n", card->dev_name); + QETH_DBF_TEXT1(0, trace, "NOarpPRC"); + } else { + QETH_DBF_TEXT2(0, trace, "enaARPpr"); + result = qeth_send_setassparms_simple_without_data + (card, IPA_ARP_PROCESSING, IPA_CMD_ASS_START); + if (result) { + PRINT_WARN("Could not start ARP processing " + "assist on %s: 0x%x\n", + card->dev_name, result); + sprintf(dbf_text, "ARPp%4x", result); + QETH_DBF_TEXT2(0, trace, dbf_text); + atomic_set(&card->is_softsetup, 0); + return result; + } + } + + if (qeth_is_supported(IPA_IP_FRAGMENTATION)) { + PRINT_INFO("IP fragmentation supported on " + "%s... :-)\n", card->dev_name); + /* start it */ + QETH_DBF_TEXT2(0, trace, "enaipfrg"); + result = qeth_send_setassparms_simple_without_data + (card, IPA_IP_FRAGMENTATION, IPA_CMD_ASS_START); + if (result) { + PRINT_WARN("Could not start IP fragmenting " + "assist on %s: 0x%x, continuing\n", + card->dev_name, result); + sprintf(dbf_text, "IFRG%4x", result); + QETH_DBF_TEXT2(0, trace, dbf_text); + /* go on */ + } + } + if (card->options.fake_ll == FAKE_LL) { + if (qeth_is_supported(IPA_SOURCE_MAC_AVAIL)) { + /* start it */ + QETH_DBF_TEXT2(0, trace, "enainsrc"); + result = qeth_send_setassparms_simple_without_data + (card, IPA_SOURCE_MAC_AVAIL, IPA_CMD_ASS_START); + if (result) { + PRINT_WARN + ("Could not start inbound source " + "assist on %s: 0x%x, continuing\n", + card->dev_name, result); + sprintf(dbf_text, "INSR%4x", result); + QETH_DBF_TEXT2(0, trace, dbf_text); + /* go on */ + } + } else { + PRINT_INFO("Inbound source addresses not " + "supported on %s\n", card->dev_name); + } + } + __qeth_start_vlan_assist(card); + __qeth_start_mc_assist(card); + + if (!qeth_is_supported(IPA_IPv6)) { + QETH_DBF_TEXT2(0, trace, "ipv6ntsp"); + PRINT_WARN("IPv6 not supported on %s\n", card->dev_name); + } else { + result = __qeth_softsetup_enable_ipv6(card, do_a_startlan6); + if (result != 0) + return result; + } + + card->broadcast_capable = 0; + if (!qeth_is_supported(IPA_FILTERING)) { + QETH_DBF_TEXT2(0, trace, "filtntsp"); + PRINT_WARN("Broadcasting not supported on %s\n", + card->dev_name); + } else { + QETH_DBF_TEXT2(0, trace, "enafiltr"); + result = qeth_send_setassparms_simple_without_data + (card, IPA_FILTERING, IPA_CMD_ASS_START); + if (result) { + PRINT_WARN("Could not enable broadcast " + "filtering on %s: " + "0x%x, continuing\n", + card->dev_name, result); + sprintf(dbf_text, "FLT1%4x", result); + QETH_DBF_TEXT2(0, trace, dbf_text); + goto go_on_filt; + } + result = qeth_send_setassparms_simple_with_data + (card, IPA_FILTERING, IPA_CMD_ASS_CONFIGURE, 1); + if (result) { + PRINT_WARN("Could not set up broadcast " + "filtering on %s: " + "0x%x, continuing\n", + card->dev_name, result); + sprintf(dbf_text, "FLT2%4x", result); + QETH_DBF_TEXT2(0, trace, dbf_text); + goto go_on_filt; + } + card->dev->flags |= IFF_BROADCAST; + card->broadcast_capable = 1; + } +go_on_filt: + if (card->options.checksum_type == HW_CHECKSUMMING) { + if (!qeth_is_supported(IPA_INBOUND_CHECKSUM)) { + PRINT_WARN("Inbound HW checksumming not " + "supported on %s, continuing " + "using inbound sw checksumming\n", + card->dev_name); + QETH_DBF_TEXT2(0, trace, "ibckntsp"); + card->options.checksum_type = SW_CHECKSUMMING; + } else { + QETH_DBF_TEXT2(0, trace, "ibcksupp"); + result = qeth_send_setassparms_simple_without_data + (card, IPA_INBOUND_CHECKSUM, + IPA_CMD_ASS_START); + if (result) { + PRINT_WARN("Could not start inbound " + "checksumming on %s: 0x%x, " + "continuing using " + "inbound sw checksumming\n", + card->dev_name, result); + sprintf(dbf_text, "SIBC%4x", result); + QETH_DBF_TEXT2(0, trace, dbf_text); + card->options.checksum_type = SW_CHECKSUMMING; + goto go_on_checksum; + } + result=qeth_send_setassparms_simple_with_data + (card,IPA_INBOUND_CHECKSUM, + IPA_CMD_ASS_ENABLE, IPA_CHECKSUM_ENABLE_MASK); + if (result) { + PRINT_WARN("Could not enable inbound " \ + "checksumming on %s: 0x%x, " \ + "continuing using " \ + "inbound sw checksumming\n", + card->dev_name,result); + sprintf(dbf_text,"EIBC%4x",result); + QETH_DBF_TEXT2(0,trace,dbf_text); + card->options.checksum_type = SW_CHECKSUMMING; + goto go_on_checksum; + + } + } + } +go_on_checksum: + atomic_set(&card->is_softsetup, 1); + return 0; +} + +static inline void +__qeth_softsetup_routingv4(struct qeth_card *card) +{ + int result; + char dbf_text[15]; + + if (!atomic_read(&card->enable_routing_attempts4)) + return; + + if (!card->options.routing_type4) { + atomic_set(&card->enable_routing_attempts4, 0); + atomic_set(&card->rt4fld, 0); + return; + } + + sprintf(dbf_text, "strtg4%2x", card->options.routing_type4); + QETH_DBF_TEXT2(0, trace, dbf_text); + result = qeth_send_setrtg(card, card->options.routing_type4, 4); + if (!result) { /* routing set correctly */ + atomic_set(&card->enable_routing_attempts4, 0); + atomic_set(&card->rt4fld, 0); + return; + } + if (atomic_dec_return(&card->enable_routing_attempts4)) { + PRINT_WARN("couldn't set up v4 routing type " + "on %s: 0x%x (%s).\nWill try " + "next time again.\n", + card->dev_name, result, + ((result == 0xe010) || (result == 0xe008)) ? + "primary already defined" + : ((result == 0xe011) || (result == 0xe009)) ? + "secondary already defined" + : (result == 0xe012) ? "invalid indicator" : + "unknown return code"); + sprintf(dbf_text, "sRT4%4x", result); + atomic_set(&card->rt4fld, 1); + QETH_DBF_TEXT2(0, trace, dbf_text); + } else { + PRINT_WARN("couldn't set up v4 routing type " + "on %s: 0x%x (%s).\nTrying to " + "continue without routing.\n", + card->dev_name, result, + ((result == 0xe010) || (result == 0xe008)) ? + "primary already defined" + : ((result == 0xe011) || (result == 0xe009)) ? + "secondary already defined" + : (result == 0xe012) ? "invalid indicator" : + "unknown return code"); + sprintf(dbf_text, "SRT4%4x", result); + QETH_DBF_TEXT2(0, trace, dbf_text); + atomic_set(&card->rt4fld, 1); + } +} + +static void +__qeth_softsetup_routingv6(struct qeth_card *card) +{ +#ifdef QETH_IPV6 + int result; + char dbf_text[15]; + + if (!atomic_read(&card->enable_routing_attempts6)) + return; + + if (!card->options.routing_type6) { + atomic_set(&card->enable_routing_attempts6, 0); + atomic_set(&card->rt6fld, 0); + return; + } + sprintf(dbf_text, "strtg6%2x", card->options.routing_type6); + QETH_DBF_TEXT2(0, trace, dbf_text); + result = qeth_send_setrtg(card, card->options.routing_type6, 6); + if (!result) { /* routing set correctly */ + atomic_set(&card->enable_routing_attempts6, 0); + atomic_set(&card->rt6fld, 0); + return; + } + if (atomic_dec_return(&card->enable_routing_attempts6)) { + PRINT_WARN("couldn't set up v6 routing type " + "on %s: 0x%x (%s).\nWill try " + "next time again.\n", + card->dev_name, result, + ((result == 0xe010) || (result == 0xe008)) ? + "primary already defined" + : ((result == 0xe011) || (result == 0xe009)) ? + "secondary already defined" + : (result == 0xe012) ? "invalid indicator" : + "unknown return code"); + sprintf(dbf_text, "sRT6%4x", result); + QETH_DBF_TEXT2(0, trace, dbf_text); + atomic_set(&card->rt6fld, 1); + } else { + PRINT_WARN("couldn't set up v6 routing type " + "on %s: 0x%x (%s).\nTrying to " + "continue without routing.\n", + card->dev_name, result, + ((result == 0xe010) || (result == 0xe008)) ? + "primary already defined" + : ((result == 0xe011) || (result == 0xe009)) ? + "secondary already defined" + : (result == 0xe012) ? "invalid indicator" : + "unknown return code"); + sprintf(dbf_text, "SRT6%4x", result); + QETH_DBF_TEXT2(0, trace, dbf_text); + atomic_set(&card->rt6fld, 1); + } +#endif /* QETH_IPV6 */ +} + +static int +qeth_softsetup_card(struct qeth_card *card, int wait_for_lock) +{ + int result; + char dbf_text[15]; + int use_setip_retries = 1; + + if (wait_for_lock == QETH_WAIT_FOR_LOCK) { + spin_lock(&card->softsetup_lock); + } else if (wait_for_lock == QETH_DONT_WAIT_FOR_LOCK) { + if (!spin_trylock(&card->softsetup_lock)) { + return -EAGAIN; + } + } else if (wait_for_lock == QETH_LOCK_ALREADY_HELD) { + use_setip_retries = 0; /* we are in recovery and don't want + to repeat setting ips on and on */ + } else { + return -EINVAL; + } + + qeth_save_dev_flag_state(card); + + QETH_DBF_TEXT1(0, trace, wait_for_lock?"sscw":"sscn"); + QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id); + + result = __qeth_softsetup_start_assists(card); + if (result) + goto out; + + __qeth_softsetup_routingv4(card); + __qeth_softsetup_routingv6(card); + + QETH_DBF_TEXT2(0, trace, "delvipa"); + qeth_set_vipas(card, 0); + QETH_DBF_TEXT2(0, trace, "toip/ms"); + qeth_takeover_ip_ipms(card); + qeth_takeover_ip_ipms6(card); + QETH_DBF_TEXT2(0, trace, "setvipa"); + qeth_set_vipas(card, 1); + + result = qeth_setips(card, use_setip_retries); + if (result) { /* by now, qeth_setips does not return errors */ + PRINT_WARN("couldn't set up IPs on %s: 0x%x\n", + card->dev_name, result); + sprintf(dbf_text, "SSIP%4x", result); + QETH_DBF_TEXT2(0, trace, dbf_text); + atomic_set(&card->is_softsetup, 0); + goto out; + } + result = qeth_setipms(card, use_setip_retries); + if (result) { /* by now, qeth_setipms does not return errors */ + PRINT_WARN("couldn't set up multicast IPs on %s: 0x%x\n", + card->dev_name, result); + sprintf(dbf_text, "ssim%4x", result); + QETH_DBF_TEXT2(0, trace, dbf_text); + atomic_set(&card->is_softsetup, 0); + goto out; + } +out: + if (!result) { + netif_wake_queue(card->dev); + } + if (wait_for_lock != QETH_LOCK_ALREADY_HELD) + spin_unlock(&card->softsetup_lock); + return result; +} + +static int +qeth_softsetup_thread(void *param) +{ + char name[15]; + struct qeth_card *card = (struct qeth_card *) param; + + /* set a nice name ... */ + sprintf(name, "qethsoftd%s", card->rdev->dev.bus_id); + daemonize(name); + + QETH_DBF_TEXT2(0, trace, "ssth"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + + atomic_set(&card->softsetup_thread_is_running, 1); + for (;;) { + if (atomic_read(&card->shutdown_phase)) + goto out; + down_interruptible(&card->softsetup_thread_sem); + QETH_DBF_TEXT2(0, trace, "ssst"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + if (atomic_read(&card->shutdown_phase)) + goto out; + while (qeth_softsetup_card(card, QETH_DONT_WAIT_FOR_LOCK) + == -EAGAIN) { + if (atomic_read(&card->shutdown_phase)) + goto out; + qeth_wait_nonbusy(QETH_IDLE_WAIT_TIME); + } + QETH_DBF_TEXT2(0, trace, "sssd"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + netif_wake_queue(card->dev); + } +out: + atomic_set(&card->softsetup_thread_is_running, 0); + + QETH_DBF_TEXT2(0, trace, "lsst"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + + return 0; +} + +static void +qeth_softsetup_thread_starter(void *data) +{ + struct qeth_card *card = (struct qeth_card *) data; + + QETH_DBF_TEXT4(0, trace, "ssts"); + QETH_DBF_TEXT4(0, trace, card->rdev->dev.bus_id); + sema_init(&card->softsetup_thread_sem, 0); + kernel_thread(qeth_softsetup_thread, card, SIGCHLD); +} + +static void +qeth_start_reinit_thread(struct qeth_card *card) +{ + /* we allow max 2 reinit threads, one could be just about to + * finish and the next would be waiting. another waiting + * reinit_thread is not necessary. */ + if (atomic_read(&card->reinit_counter) < 2) { + atomic_inc(&card->reinit_counter); + if (atomic_read(&card->shutdown_phase)) { + atomic_dec(&card->reinit_counter); + return; + } + QETH_DBF_TEXT2(0, trace, "stri"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + PRINT_STUPID("starting reinit-thread\n"); + kernel_thread(qeth_reinit_thread, card, SIGCHLD); + } +} + +static void +qeth_recover(void *data) +{ + struct qeth_card *card; + int i; + char dbf_text[15]; + + card = (struct qeth_card *) data; + + QETH_DBF_TEXT2(0, trace, "recv"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + + if (atomic_compare_and_swap(0, 1, &card->in_recovery)) + return; + + i = atomic_read(&card->problem); + + sprintf(dbf_text, "PROB%4x", i); + QETH_DBF_TEXT2(0, trace, dbf_text); + + if (i != PROBLEM_TX_TIMEOUT) + PRINT_WARN("recovery was scheduled on device %s (%s) with " + "problem 0x%x\n", + card->rdev->dev.bus_id, card->dev_name, i); + switch (i) { + case PROBLEM_RECEIVED_IDX_TERMINATE: + if (atomic_read(&card->in_recovery)) + atomic_set(&card->break_out, QETH_BREAKOUT_AGAIN); + break; + case PROBLEM_CARD_HAS_STARTLANED: + PRINT_WARN("You are lucky! Somebody either fixed the " + "network problem, plugged the cable back in " + "or enabled the OSA port on %s (CHPID 0x%X). " + "The link has come up.\n", + card->dev_name, card->chpid); + sprintf(dbf_text, "CBIN%4x", i); + QETH_DBF_TEXT1(0, trace, dbf_text); + atomic_set(&card->is_softsetup, 0); + qeth_set_dev_flag_running(card); + atomic_set(&card->enable_routing_attempts4, + QETH_ROUTING_ATTEMPTS); + qeth_clear_ifa4_list(&card->ip_new_state.ip_ifa); +#ifdef QETH_IPV6 + atomic_set(&card->enable_routing_attempts6, + QETH_ROUTING_ATTEMPTS); + qeth_clear_ifa6_list(&card->ip_new_state.ip6_ifa); +#endif /* QETH_IPV6 */ + qeth_clear_ifamc_list(&card->ip_mc_new_state.ipm_ifa); +#ifdef QETH_IPV6 + qeth_clear_ifamc_list(&card->ip_mc_new_state.ipm6_ifa); +#endif /* QETH_IPV6 */ + qeth_refresh_vipa_states(card); + qeth_start_softsetup_thread(card); + atomic_set(&card->in_recovery, 0); + break; + case PROBLEM_RESETTING_EVENT_INDICATOR: + /* we do nothing here */ + break; + case PROBLEM_ACTIVATE_CHECK_CONDITION: + case PROBLEM_GENERAL_CHECK: + case PROBLEM_USER_TRIGGERED_RECOVERY: + case PROBLEM_AFFE: + case PROBLEM_MACHINE_CHECK: + case PROBLEM_BAD_SIGA_RESULT: + case PROBLEM_TX_TIMEOUT: + qeth_start_reinit_thread(card); + break; + } +} + +static void +qeth_schedule_recovery(struct qeth_card *card) +{ + if (card) { + INIT_WORK(&card->tqueue, qeth_recover, card); + schedule_work(&card->tqueue); + } else { + QETH_DBF_TEXT2(1, trace, "scdnocrd"); + PRINT_WARN("recovery requested to be scheduled " + "with no card!\n"); + } +} + +static void +qeth_qdio_input_handler(struct ccw_device *cdev, unsigned int status, + unsigned int qdio_error, unsigned int siga_error, + unsigned int queue, + int first_element, int count, unsigned long card_ptr) +{ + struct net_device *dev; + struct qeth_card *card; + int problem; + int sbalf15; + char dbf_text[15]; + + sprintf(dbf_text, "qibhn%s", cdev->dev.bus_id); + QETH_DBF_HEX6(0, trace, dbf_text, QETH_DBF_TRACE_LEN); + + card = (struct qeth_card *) card_ptr; + +#ifdef QETH_PERFORMANCE_STATS + card->perf_stats.inbound_start_time = NOW; +#endif /* QETH_PERFORMANCE_STATS */ + dev = card->dev; + + if (status & QDIO_STATUS_LOOK_FOR_ERROR) { + if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION) { + problem = PROBLEM_ACTIVATE_CHECK_CONDITION; + atomic_set(&card->problem, problem); + QETH_DBF_TEXT1(0, trace, "IHACTQCK"); + sprintf(dbf_text, "%4x%4x", first_element, count); + QETH_DBF_TEXT1(0, trace, dbf_text); + sprintf(dbf_text, "%4x%4x", queue, status); + QETH_DBF_TEXT1(0, trace, dbf_text); + QETH_DBF_TEXT1(1, trace, "qscd"); + QETH_DBF_TEXT1(1, trace, card->rdev->dev.bus_id); + qeth_schedule_recovery(card); + return; + } + sbalf15 = (card->inbound_qdio_buffers[(first_element + count - 1) + & QDIO_MAX_BUFFERS_PER_Q]. + element[15].flags) && 0xff; + PRINT_STUPID("inbound qdio transfer error on device %s. " + "qdio_error=0x%x (more than one: %c), " + "siga_error=0x%x (more than one: %c), " + "sbalf15=x%x, bufno=x%x\n", cdev->dev.bus_id, + qdio_error, + (status & QDIO_STATUS_MORE_THAN_ONE_QDIO_ERROR) ? + 'y' : 'n', siga_error, + (status & QDIO_STATUS_MORE_THAN_ONE_SIGA_ERROR) ? + 'y' : 'n', sbalf15, first_element); + QETH_DBF_TEXT1(0, trace, "IQTI"); + QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id); + QETH_DBF_TEXT1(0, qerr, "IQTI"); + QETH_DBF_TEXT1(0, qerr, card->rdev->dev.bus_id); + sprintf(dbf_text, "%4x%4x", first_element, count); + QETH_DBF_TEXT1(0, trace, dbf_text); + QETH_DBF_TEXT1(0, qerr, dbf_text); + sprintf(dbf_text, "%2x%4x%2x", queue, status, sbalf15); + QETH_DBF_TEXT1(0, trace, dbf_text); + QETH_DBF_TEXT1(0, qerr, dbf_text); + sprintf(dbf_text, "%4x%4x", qdio_error, siga_error); + QETH_DBF_TEXT1(0, trace, dbf_text); + QETH_DBF_TEXT1(0, qerr, dbf_text); + /* we inform about error more detailed in + * qeth_read_in_buffer() */ + } + + for (;;) { + qeth_read_in_buffer(card, first_element); + qeth_queue_input_buffer(card, first_element, + QDIO_FLAG_UNDER_INTERRUPT); + count--; + if (count) + first_element = (first_element + 1) & + (QDIO_MAX_BUFFERS_PER_Q - 1); + else + break; + } +} + +static void +__qeth_try_to_flush_packets(struct qeth_card *card, int last_pci_hit, + unsigned int queue) +{ + int switch_state; + + switch_state = (atomic_read(&card->outbound_used_buffers[queue]) <= + LOW_WATERMARK_PACK); + /* first_element is the last buffer that we got back from hydra */ + if (!switch_state && !last_pci_hit) + return;; + QETH_DBF_TEXT3(0, trace, "stchcw"); + QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id); + if (atomic_swap(&card->outbound_ringbuffer_lock[queue], QETH_LOCK_FLUSH) + == QETH_LOCK_UNLOCKED) { + /* + * we stop the queue as we try to not run onto the + * outbound_ringbuffer_lock -- this will not prevent it totally, + * but reduce it. in high traffic situations, it saves around + * 20us per second, hopefully this is amortized by calling + * netif_... + */ + netif_stop_queue(card->dev); + qeth_flush_packed_packets(card, queue, + QDIO_FLAG_UNDER_INTERRUPT); + /* + * only switch state to non-packing, if the amount of used + * buffers decreased + */ + if (switch_state) + card->send_state[queue] = SEND_STATE_DONT_PACK; + netif_wake_queue(card->dev); + atomic_set(&card->outbound_ringbuffer_lock[queue], + QETH_LOCK_UNLOCKED); + } + /* + * if the lock was UNLOCKED, we flush ourselves, otherwise this is done + * in do_send_packet when the lock is released + */ +#ifdef QETH_PERFORMANCE_STATS + card->perf_stats.sc_p_dp++; +#endif /* QETH_PERFORMANCE_STATS */ +} + +static void +qeth_qdio_output_handler(struct ccw_device *cdev, + unsigned int status, + unsigned int qdio_error, + unsigned int siga_error, + unsigned int queue, + int first_element, int count, unsigned long card_ptr) +{ + struct qeth_card *card; + int mycnt, problem, buffers_used; + int sbalf15; + char dbf_text[15]; + int last_pci_hit = 0; + int last_pci; + + sprintf(dbf_text, "qouthn%s", cdev->dev.bus_id); + QETH_DBF_HEX6(0, trace, dbf_text, QETH_DBF_TRACE_LEN); + + mycnt = count; + card = (struct qeth_card *) card_ptr; + + if (status & QDIO_STATUS_LOOK_FOR_ERROR) { + if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION) { + problem = PROBLEM_ACTIVATE_CHECK_CONDITION; + atomic_set(&card->problem, problem); + QETH_DBF_TEXT1(0, trace, "OHACTQCK"); + sprintf(dbf_text, "%4x%4x", first_element, count); + QETH_DBF_TEXT1(0, trace, dbf_text); + sprintf(dbf_text, "%4x%4x", queue, status); + QETH_DBF_TEXT1(0, trace, dbf_text); + QETH_DBF_TEXT1(1, trace, "qscd"); + QETH_DBF_TEXT1(1, trace, card->rdev->dev.bus_id); + qeth_schedule_recovery(card); + goto out; + } + sbalf15 = (card->outbound_ringbuffer[queue]-> + buffer[(first_element + count - 1) & QDIO_MAX_BUFFERS_PER_Q]. + element[15].flags) & 0xff; + PRINT_STUPID("outbound qdio transfer error on device %s, " + "queue=%i. qdio_error=0x%x (more than one: %c)," + " siga_error=0x%x (more than one: %c), " + "sbalf15=x%x, bufno=x%x\n", + cdev->dev.bus_id, queue, qdio_error, status & + QDIO_STATUS_MORE_THAN_ONE_QDIO_ERROR ? 'y' : 'n', + siga_error, status & + QDIO_STATUS_MORE_THAN_ONE_SIGA_ERROR ? 'y' : 'n', + sbalf15, first_element); + QETH_DBF_TEXT1(0, trace, "IQTO"); + QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id); + QETH_DBF_TEXT1(0, qerr, "IQTO"); + QETH_DBF_TEXT1(0, qerr, card->rdev->dev.bus_id); + sprintf(dbf_text, "%4x%4x", first_element, count); + QETH_DBF_TEXT1(0, trace, dbf_text); + QETH_DBF_TEXT1(0, qerr, dbf_text); + sprintf(dbf_text, "%2x%4x%2x", queue, status, sbalf15); + QETH_DBF_TEXT1(0, trace, dbf_text); + QETH_DBF_TEXT1(0, qerr, dbf_text); + sprintf(dbf_text, "%4x%4x", qdio_error, siga_error); + QETH_DBF_TEXT1(0, trace, dbf_text); + QETH_DBF_TEXT1(0, qerr, dbf_text); + /* we maybe do recovery or dst_link_failures + * in qeth_free_buffer */ + } + + if (mycnt) { + last_pci = atomic_read(&card->last_pci_pos[queue]); + for (;;) { + qeth_free_buffer(card, queue, first_element, + qdio_error, siga_error); + if (first_element == last_pci) + last_pci_hit = 1; + mycnt--; + if (mycnt > 0) + first_element = (first_element + 1) & + (QDIO_MAX_BUFFERS_PER_Q - 1); + else + break; + } + } + + buffers_used = atomic_return_sub(count, + &card->outbound_used_buffers[queue]); + + switch (card->send_state[queue]) { + case SEND_STATE_PACK: + __qeth_try_to_flush_packets(card, last_pci_hit, queue); + break; + default: + break; + } + + /* we don't have to start the queue, if it was started already */ + if (buffers_used < QDIO_MAX_BUFFERS_PER_Q - 1) + return; + +out: + netif_wake_queue(card->dev); +} + +static long +__qeth_check_irb_error(struct ccw_device *cdev, struct irb *irb) +{ + if (!IS_ERR(irb)) + return 0; + + switch (PTR_ERR(irb)) { + case -EIO: + PRINT_WARN("i/o-error on device %s\n", cdev->dev.bus_id); + break; + case -ETIMEDOUT: + PRINT_WARN("timeout on device %s\n", cdev->dev.bus_id); + break; + default: + PRINT_WARN("unknown error %d on device %s\n", PTR_ERR(irb), + cdev->dev.bus_id); + } + return PTR_ERR(irb); +} + +static void +qeth_interrupt_handler_read(struct ccw_device *cdev, unsigned long intparm, + struct irb *irb) +{ + int cstat, dstat; + int problem; + struct qeth_card *card; + int rqparam; + char dbf_text[15]; + int result; + + if (__qeth_check_irb_error(cdev, irb)) + return; + + cstat = irb->scsw.cstat; + dstat = irb->scsw.dstat; + rqparam = intparm; + + sprintf(dbf_text, "rint%s", cdev->dev.bus_id); + QETH_DBF_TEXT4(0, trace, dbf_text); + sprintf(dbf_text, "%4x%4x", cstat, dstat); + QETH_DBF_TEXT4(0, trace, dbf_text); + sprintf(dbf_text, "%4x", rqparam); + QETH_DBF_TEXT4(0, trace, dbf_text); + + card = cdev->dev.driver_data; + if (!card) + return; + + if (irb->scsw.fctl & (SCSW_FCTL_CLEAR_FUNC | SCSW_FCTL_HALT_FUNC)) { + atomic_set(&card->clear_succeeded0, 1); + wake_up(&card->wait_q); + return; + } + + if (!rqparam) { + PRINT_STUPID("got unsolicited interrupt in read handler " + "for %s\n", cdev->dev.bus_id); + return; + } + + if ((dstat == 0) && (cstat == 0)) + return; + + if (irb->esw.esw0.erw.cons) { + PRINT_WARN("sense data available on read channel.\n"); + HEXDUMP16(WARN, "irb: ", irb); + HEXDUMP16(WARN, "sense data: ", irb->ecw); + sprintf(dbf_text, "RSNS%s", cdev->dev.bus_id); + QETH_DBF_TEXT1(0, trace, dbf_text); + QETH_DBF_HEX0(0, sense, irb, QETH_DBF_SENSE_LEN); + } + + if (cstat != 0) { + PRINT_WARN("got nonzero-nonpci channel status in read_" + "handler (device %s, devstat 0x%02x, schstat " + "0x%02x, rqparam 0x%x)\n", cdev->dev.bus_id, + dstat, cstat, rqparam); + } + + problem = qeth_get_cards_problem(cdev, card->dma_stuff->recbuf, + dstat, cstat, rqparam, + (char *) irb, (char *) irb->ecw); + + /* detect errors in dstat here */ + if ((dstat & DEV_STAT_UNIT_EXCEP) || (dstat & DEV_STAT_UNIT_CHECK)) { + PRINT_WARN("unit check/exception in read_handler " + "(device %s, devstat 0x%02x, schstat 0x%02x, " + "rqparam 0x%x)\n", + cdev->dev.bus_id, dstat, cstat, rqparam); + + if (!atomic_read(&card->is_hardsetup)) { + if ((problem) && (qeth_is_to_recover(card, problem))) + atomic_set(&card->break_out, + QETH_BREAKOUT_AGAIN); + else + atomic_set(&card->break_out, + QETH_BREAKOUT_LEAVE); + goto wakeup_out; + } else + goto recover; + } + + if (!(dstat & DEV_STAT_CHN_END)) { + PRINT_WARN("didn't get device end in read_handler " + "(device %s, devstat 0x%02x, schstat 0x%02x, " + "rqparam 0x%x)\n", + cdev->dev.bus_id, dstat, cstat, rqparam); + goto wakeup_out; + } + + if ((rqparam == IDX_ACTIVATE_WRITE_STATE) || (rqparam == NOP_STATE)) { + goto wakeup_out; + } + + /* at this point, (maybe channel end and) device end has appeared */ + + /* we don't start the next read until we have examined the buffer. */ + if ((rqparam != IDX_ACTIVATE_READ_STATE) && + (rqparam != IDX_ACTIVATE_WRITE_STATE)) + qeth_issue_next_read(card); + +recover: + if (qeth_is_to_recover(card, problem)) { + QETH_DBF_TEXT2(1, trace, "rscd"); + QETH_DBF_TEXT2(1, trace, card->rdev->dev.bus_id); + qeth_schedule_recovery(card); + goto wakeup_out; + } + + if (!IS_IPA(card->dma_stuff->recbuf) || + IS_IPA_REPLY(card->dma_stuff->recbuf)) { + /* setup or unknown data */ + result = qeth_look_for_arp_data(card); + switch (result) { + case ARP_RETURNCODE_ERROR: + case ARP_RETURNCODE_LASTREPLY: + qeth_wakeup_ioctl(card); + return; + default: + break; + } + } + +wakeup_out: + memcpy(card->ipa_buf, card->dma_stuff->recbuf, QETH_BUFSIZE); + qeth_wakeup(card); +} + +static void +qeth_interrupt_handler_write(struct ccw_device *cdev, unsigned long intparm, + struct irb *irb) +{ + int cstat, dstat, rqparam; + struct qeth_card *card; + int problem; + char dbf_text[15]; + + if (__qeth_check_irb_error(cdev, irb)) + return; + + cstat = irb->scsw.cstat; + dstat = irb->scsw.dstat; + rqparam = intparm; + + sprintf(dbf_text, "wint%s", cdev->dev.bus_id); + QETH_DBF_TEXT4(0, trace, dbf_text); + sprintf(dbf_text, "%4x%4x", cstat, dstat); + QETH_DBF_TEXT4(0, trace, dbf_text); + sprintf(dbf_text, "%4x", rqparam); + QETH_DBF_TEXT4(0, trace, dbf_text); + + card = cdev->dev.driver_data; + if (!card) + return; + + if (irb->scsw.fctl & (SCSW_FCTL_CLEAR_FUNC | SCSW_FCTL_HALT_FUNC)) { + atomic_set(&card->clear_succeeded1, 1); + wake_up(&card->wait_q); + goto out; + } + + if (!rqparam) { + PRINT_STUPID("got unsolicited interrupt in write handler " + "for %s\n", cdev->dev.bus_id); + return; + } + + if ((dstat == 0) && (cstat == 0)) + goto out; + + if (irb->esw.esw0.erw.cons) { + PRINT_WARN("sense data available on write channel.\n"); + HEXDUMP16(WARN, "irb: ", irb); + HEXDUMP16(WARN, "sense data: ", irb->ecw); + sprintf(dbf_text, "WSNS%s", cdev->dev.bus_id); + QETH_DBF_TEXT1(0, trace, dbf_text); + QETH_DBF_HEX0(0, sense, irb, QETH_DBF_SENSE_LEN); + } + + if (cstat != 0) { + PRINT_WARN("got nonzero channel status in write_handler " + "(device %s, devstat 0x%02x, schstat 0x%02x, " + "rqparam 0x%x)\n", + cdev->dev.bus_id, dstat, cstat, rqparam); + } + + problem = qeth_get_cards_problem(cdev, NULL, + dstat, cstat, rqparam, + (char *) irb, (char *) irb->ecw); + + /* detect errors in dstat here */ + if ((dstat & DEV_STAT_UNIT_EXCEP) || (dstat & DEV_STAT_UNIT_CHECK)) { + PRINT_WARN("unit check/exception in write_handler " + "(device %s, devstat 0x%02x, schstat 0x%02x, " + "rqparam 0x%x)\n", + cdev->dev.bus_id, dstat, cstat, rqparam); + if (!atomic_read(&card->is_hardsetup)) { + if (problem == PROBLEM_RESETTING_EVENT_INDICATOR) { + atomic_set(&card->break_out, + QETH_BREAKOUT_AGAIN); + qeth_wakeup(card); + goto out; + } + atomic_set(&card->break_out, QETH_BREAKOUT_LEAVE); + goto out; + } else + goto recover; + } + + if (dstat == DEV_STAT_DEV_END) + goto out; + + if (!(dstat & DEV_STAT_CHN_END)) { + PRINT_WARN("didn't get device end in write_handler " + "(device %s, devstat 0x%02x, schstat 0x%02x, " + "rqparam 0x%x)\n", + cdev->dev.bus_id, dstat, cstat, rqparam); + goto out; + } + +recover: + if (qeth_is_to_recover(card, problem)) { + QETH_DBF_TEXT2(1, trace, "wscd"); + QETH_DBF_TEXT2(1, trace, card->rdev->dev.bus_id); + qeth_schedule_recovery(card); + goto out; + } + + /* at this point, (maybe channel end and) device end has appeared */ + if ((rqparam == IDX_ACTIVATE_READ_STATE) || + (rqparam == IDX_ACTIVATE_WRITE_STATE) || (rqparam == NOP_STATE)) { + qeth_wakeup(card); + goto out; + } + + /* well, a write has been done successfully. */ + +out: + /* all statuses are final statuses on the write channel */ + atomic_set(&card->write_busy, 0); +} + +static void +qeth_interrupt_handler_qdio(struct ccw_device *cdev, unsigned long intparm, + struct irb *irb) +{ + int cstat, dstat, rqparam; + char dbf_text[15]; + struct qeth_card *card; + + if (__qeth_check_irb_error(cdev, irb)) + return; + + cstat = irb->scsw.cstat; + dstat = irb->scsw.dstat; + rqparam = intparm; + + sprintf(dbf_text, "qint%s", cdev->dev.bus_id); + QETH_DBF_TEXT4(0, trace, dbf_text); + sprintf(dbf_text, "%4x%4x", cstat, dstat); + QETH_DBF_TEXT4(0, trace, dbf_text); + sprintf(dbf_text, "%4x", rqparam); + QETH_DBF_TEXT4(0, trace, dbf_text); + + card = cdev->dev.driver_data; + if (!card) + return; + + if (irb->scsw.fctl & (SCSW_FCTL_CLEAR_FUNC | SCSW_FCTL_HALT_FUNC)) { + atomic_set(&card->clear_succeeded2, 1); + wake_up(&card->wait_q); + return; + } + + if (!rqparam) { + PRINT_STUPID("got unsolicited interrupt in qdio handler, " + "device%s\n", cdev->dev.bus_id); + return; + } + + if ((dstat == 0) && (cstat == 0)) + return; + + if (irb->esw.esw0.erw.cons) { + PRINT_WARN("sense data available on qdio channel.\n"); + HEXDUMP16(WARN, "irb: ", irb); + HEXDUMP16(WARN, "sense data: ", irb->ecw); + sprintf(dbf_text, "QSNS%s", cdev->dev.bus_id); + QETH_DBF_TEXT1(0, trace, dbf_text); + QETH_DBF_HEX0(0, sense, irb, QETH_DBF_SENSE_LEN); + } + + if ((rqparam == READ_CONF_DATA_STATE) || (rqparam == NOP_STATE)) { + qeth_wakeup(card); + return; + } + + if (cstat != 0) { + sprintf(dbf_text, "qchk%s", cdev->dev.bus_id); + QETH_DBF_TEXT2(0, trace, dbf_text); + sprintf(dbf_text, "%4x%4x", cstat, dstat); + QETH_DBF_TEXT2(0, trace, dbf_text); + sprintf(dbf_text, "%4x", rqparam); + QETH_DBF_TEXT2(0, trace, dbf_text); + PRINT_WARN("got nonzero channel status in qdio_handler " + "(device %s, devstat 0x%02x, schstat 0x%02x)\n", + cdev->dev.bus_id, dstat, cstat); + } + + if (dstat & ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END)) { + PRINT_WARN("got the following dstat on the qdio channel: " + "device %s, dstat 0x%02x, cstat 0x%02x, " + "rqparam=%i\n", + cdev->dev.bus_id, dstat, cstat, rqparam); + } + +} + +static int +qeth_register_netdev(struct qeth_card *card) +{ + int result; + + QETH_DBF_TEXT3(0, trace, "rgnd"); + QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id); + + result = register_netdev(card->dev); + + return result; +} + +static void +qeth_unregister_netdev(struct qeth_card *card) +{ + QETH_DBF_TEXT3(0, trace, "nrgn"); + QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id); + + unregister_netdev(card->dev); +} + +static int +qeth_stop(struct net_device *dev) +{ + struct qeth_card *card; + + card = (struct qeth_card *) dev->priv; + QETH_DBF_TEXT2(0, trace, "stop"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + QETH_DBF_TEXT2(0, setup, "stop"); + QETH_DBF_TEXT2(0, setup, card->rdev->dev.bus_id); + + qeth_save_dev_flag_state(card); + + netif_stop_queue(dev); + atomic_set(&((struct qeth_card *) dev->priv)->is_open, 0); + + return 0; +} + +static void +qeth_softshutdown(struct qeth_card *card) +{ + QETH_DBF_TEXT3(0, trace, "ssht"); + QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id); + + qeth_send_stoplan(card); +} + +static void +__qeth_clear_card_halt_clear(struct qeth_card *card, int halt) +{ + unsigned long flags0, flags1, flags2; + int ret0, ret1, ret2; + + atomic_set(&card->clear_succeeded0, 0); + atomic_set(&card->clear_succeeded1, 0); + atomic_set(&card->clear_succeeded2, 0); + + spin_lock_irqsave(get_ccwdev_lock(card->rdev), flags0); + if (halt) + ret0 = ccw_device_halt(card->rdev, CLEAR_STATE); + else + ret0 = ccw_device_clear(card->rdev, CLEAR_STATE); + spin_unlock_irqrestore(get_ccwdev_lock(card->rdev), flags0); + + spin_lock_irqsave(get_ccwdev_lock(card->wdev), flags1); + if (halt) + ret1 = ccw_device_halt(card->wdev, CLEAR_STATE); + else + ret1 = ccw_device_clear(card->wdev, CLEAR_STATE); + spin_unlock_irqrestore(get_ccwdev_lock(card->wdev), flags1); + + spin_lock_irqsave(get_ccwdev_lock(card->ddev), flags2); + if (halt) + ret2 = ccw_device_halt(card->ddev, CLEAR_STATE); + else + ret2 = ccw_device_clear(card->ddev, CLEAR_STATE); + spin_unlock_irqrestore(get_ccwdev_lock(card->ddev), flags2); + + /* The device owns us an interrupt. */ + if ((ret0 == 0) && (atomic_read(&card->clear_succeeded0) == 0)) + wait_event(card->wait_q, + atomic_read(&card->clear_succeeded0) == 1); + if ((ret1 == 0) && (atomic_read(&card->clear_succeeded1) == 0)) + wait_event(card->wait_q, + atomic_read(&card->clear_succeeded1) == 1); + if ((ret2 == 0) && (atomic_read(&card->clear_succeeded2) == 0)) + wait_event(card->wait_q, + atomic_read(&card->clear_succeeded2) == 1); +} + +static void +qeth_clear_card(struct qeth_card *card, int qdio_clean, int use_halt) +{ + QETH_DBF_TEXT3(0, trace, qdio_clean?"clrq":"clr"); + QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id); + QETH_DBF_TEXT1(0, setup, qdio_clean?"clrq":"clr"); + QETH_DBF_TEXT1(0, setup, card->rdev->dev.bus_id); + + atomic_set(&card->write_busy, 0); + if (qdio_clean) + qdio_cleanup(card->ddev, + (card->type == QETH_CARD_TYPE_IQD) ? + QDIO_FLAG_CLEANUP_USING_HALT : + QDIO_FLAG_CLEANUP_USING_CLEAR); + + if (use_halt) + __qeth_clear_card_halt_clear(card, 1); + + __qeth_clear_card_halt_clear(card, 0); +} + +static void +qeth_free_card(struct qeth_card *card) +{ + int i, j; + int element_count; + struct qeth_vipa_entry *e, *e2; + + if (!card) + return; + + QETH_DBF_TEXT3(0, trace, "free"); + QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id); + QETH_DBF_TEXT1(0, setup, "free"); + QETH_DBF_TEXT1(0, setup, card->rdev->dev.bus_id); + + write_lock(&card->vipa_list_lock); + e = card->vipa_list; + while (e) { + e2 = e->next; + kfree(e); + e = e2; + } + write_unlock(&card->vipa_list_lock); + + element_count = (card->options.memusage == MEMUSAGE_DISCONTIG) ? + BUFFER_MAX_ELEMENTS : 1; + for (i = 0; i < card->options.inbound_buffer_count; i++) { + for (j = 0; j < element_count; j++) { + if (card->inbound_buffer_pool_entry[i][j]) { + kfree(card->inbound_buffer_pool_entry[i][j]); + card->inbound_buffer_pool_entry[i][j] = NULL; + } + } + } + for (i = 0; i < card->no_queues; i++) + if (card->outbound_ringbuffer[i]) + vfree(card->outbound_ringbuffer[i]); + + if (card->stats) + kfree(card->stats); + if (card->dma_stuff) + kfree(card->dma_stuff); + if (card->dev) + kfree(card->dev); + vfree(card); /* we checked against NULL already */ +} + +/* also locked from outside (setup_lock) */ +static void +qeth_remove_card_from_list(struct qeth_card *card) +{ + struct qeth_card *cn; + unsigned long flags0, flags1, flags2; + + write_lock(&list_lock); + if (!card) { + QETH_DBF_TEXT2(0, trace, "RMCWNOCD"); + PRINT_WARN("qeth_remove_card_from_list call with no card!\n"); + write_unlock(&list_lock); + return; + } + + QETH_DBF_TEXT3(0, trace, "rmcl"); + QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id); + + /* check first, if card is in list */ + if (!firstcard) { + QETH_DBF_TEXT2(0, trace, "NOCRDINL"); + PRINT_WARN + ("qeth_remove_card_from_list called on empty card list!!\n"); + write_unlock(&list_lock); + return; + } + + spin_lock_irqsave(get_ccwdev_lock(card->rdev), flags0); + spin_lock_irqsave(get_ccwdev_lock(card->wdev), flags1); + spin_lock_irqsave(get_ccwdev_lock(card->ddev), flags2); + + if (firstcard == card) + firstcard = card->next; + else { + cn = firstcard; + while (cn->next) { + if (cn->next == card) { + cn->next = card->next; + card->next = NULL; + break; + } + cn = cn->next; + } + } + + spin_unlock_irqrestore(get_ccwdev_lock(card->ddev), flags2); + spin_unlock_irqrestore(get_ccwdev_lock(card->wdev), flags1); + spin_unlock_irqrestore(get_ccwdev_lock(card->rdev), flags0); + + write_unlock(&list_lock); + +} + +static void +qeth_delete_all_ips(struct qeth_card *card) +{ + struct qeth_vipa_entry *e; + + if (atomic_read(&card->is_softsetup)) { + qeth_clear_ifa4_list(&card->ip_new_state.ip_ifa); + qeth_clear_ifamc_list(&card->ip_mc_new_state.ipm_ifa); + +#ifdef QETH_IPV6 + qeth_clear_ifa6_list(&card->ip_new_state.ip6_ifa); + qeth_clear_ifamc_list(&card->ip_mc_new_state.ipm6_ifa); +#endif /* QETH_IPV6 */ + + write_lock(&card->vipa_list_lock); + e = card->vipa_list; + while (e) { + e->state = VIPA_2_B_REMOVED; + e = e->next; + } + write_unlock(&card->vipa_list_lock); + qeth_start_softsetup_thread(card); + } +} + +static void +qeth_remove_card(struct qeth_card *card, int method) +{ + if (!card) + return; + + QETH_DBF_TEXT2(0, trace, "rmcd"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + QETH_DBF_TEXT1(0, setup, "rmcd"); + QETH_DBF_TEXT1(0, setup, card->rdev->dev.bus_id); + + if (method == QETH_REMOVE_CARD_PROPER) { + atomic_set(&card->shutdown_phase, QETH_REMOVE_CARD_PROPER); + if (atomic_read(&card->is_open)) { + qeth_stop(card->dev); + qeth_wait_nonbusy(QETH_REMOVE_WAIT_TIME); + } + qeth_delete_all_ips(card); + } else { + atomic_set(&card->shutdown_phase, QETH_REMOVE_CARD_QUICK); + } + atomic_set(&card->write_busy, 0); + + QETH_DBF_TEXT4(0, trace, "freeskbs"); + qeth_free_all_skbs(card); + + QETH_DBF_TEXT2(0, trace, "upthrsem"); + + up(&card->softsetup_thread_sem); + up(&card->reinit_thread_sem); + while ((atomic_read(&card->softsetup_thread_is_running)) || + (atomic_read(&card->reinit_counter))) { + qeth_wait_nonbusy(QETH_WAIT_FOR_THREAD_TIME); + } + + if (method == QETH_REMOVE_CARD_PROPER) { + QETH_DBF_TEXT4(0, trace, "softshut"); + qeth_softshutdown(card); + qeth_wait_nonbusy(QETH_REMOVE_WAIT_TIME); + } + + atomic_set(&card->is_startlaned, 0); /* paranoia, qeth_stop + should prevent + further calls of + hard_start_xmit */ + + if (atomic_read(&card->is_registered)) { + QETH_DBF_TEXT2(0, trace, "unregdev"); + qeth_unregister_netdev(card); + qeth_wait_nonbusy(QETH_REMOVE_WAIT_TIME); + atomic_set(&card->is_registered, 0); + } + + qeth_put_unique_id(card); + + QETH_DBF_TEXT2(0, trace, "clrcard"); + if (atomic_read(&card->is_hardsetup)) { + PRINT_STUPID("clearing card %s\n", card->dev_name); + qeth_clear_card(card, 1, 0); + } + + atomic_set(&card->is_hardsetup, 0); + atomic_set(&card->is_softsetup, 0); + + QETH_DBF_TEXT2(0, trace, "cardrmvd"); + +} + +static void +qeth_destructor(struct net_device *dev) +{ + struct qeth_card *card; + + card = (struct qeth_card *) (dev->priv); + QETH_DBF_TEXT2(0, trace, "dstr"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); +} + +static void +qeth_set_multicast_list(struct net_device *dev) +{ + struct qeth_card *card = dev->priv; + + QETH_DBF_TEXT2(0, trace, "smcl"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + + qeth_start_softsetup_thread(card); +} + +static int +qeth_set_mac_address(struct net_device *dev, void *addr) +{ + struct qeth_card *card; + + card = (struct qeth_card *) dev->priv; + QETH_DBF_TEXT2(0, trace, "stmc"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + + return -EOPNOTSUPP; +} + +static int +qeth_neigh_setup(struct net_device *dev, struct neigh_parms *np) +{ + struct qeth_card *card; + + card = (struct qeth_card *) dev->priv; + QETH_DBF_TEXT2(0, trace, "ngst"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + + return 0; +} + +static void +qeth_generate_tokens(struct qeth_card *card) +{ + card->token.issuer_rm_w = 0x00010103UL; + card->token.cm_filter_w = 0x00010108UL; + card->token.cm_connection_w = 0x0001010aUL; + card->token.ulp_filter_w = 0x0001010bUL; + card->token.ulp_connection_w = 0x0001010dUL; +} + +static int +qeth_peer_func_level(int level) +{ + if ((level & 0xff) == 8) + return (level & 0xff) + 0x400; + if (((level >> 8) & 3) == 1) + return (level & 0xff) + 0x200; + return level; /* hmmm... don't know what to do with that level. */ +} + +static int +qeth_idx_activate_read(struct qeth_card *card) +{ + int result, result2; + __u16 temp; + unsigned long flags; + char dbf_text[15]; + + result = result2 = 0; + + memcpy(&card->dma_stuff->write_ccw, WRITE_CCW, sizeof (struct ccw1)); + card->dma_stuff->write_ccw.count = IDX_ACTIVATE_SIZE; + card->dma_stuff->write_ccw.cda = + QETH_GET_ADDR(card->dma_stuff->sendbuf); + + memcpy(card->dma_stuff->sendbuf, IDX_ACTIVATE_READ, IDX_ACTIVATE_SIZE); + memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(card->dma_stuff->sendbuf), + &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH); + + memcpy(QETH_IDX_ACT_ISSUER_RM_TOKEN(card->dma_stuff->sendbuf), + &card->token.issuer_rm_w, QETH_MPC_TOKEN_LENGTH); + memcpy(QETH_IDX_ACT_FUNC_LEVEL(card->dma_stuff->sendbuf), + &card->func_level, 2); + + temp = _ccw_device_get_device_number(card->ddev); + memcpy(QETH_IDX_ACT_QDIO_DEV_CUA(card->dma_stuff->sendbuf), &temp, 2); + temp = (card->cula << 8) + card->unit_addr2; + memcpy(QETH_IDX_ACT_QDIO_DEV_REALADDR(card->dma_stuff->sendbuf), + &temp, 2); + + QETH_DBF_TEXT2(0, trace, "iarw"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + QETH_DBF_HEX2(0, control, card->dma_stuff->sendbuf, + QETH_DBF_CONTROL_LEN); + + spin_lock_irqsave(get_ccwdev_lock(card->rdev), flags); + result = ccw_device_start(card->rdev, &card->dma_stuff->write_ccw, + IDX_ACTIVATE_WRITE_STATE, 0, 0); + if (result) { + qeth_delay_millis(QETH_WAIT_BEFORE_2ND_DOIO); + result2 = ccw_device_start(card->rdev, + &card->dma_stuff->write_ccw, + IDX_ACTIVATE_WRITE_STATE, 0, 0); + sprintf(dbf_text, "IRW1%4x", result); + QETH_DBF_TEXT2(0, trace, dbf_text); + sprintf(dbf_text, "IRW2%4x", result2); + QETH_DBF_TEXT2(0, trace, dbf_text); + PRINT_WARN("qeth_idx_activate_read (write): do_IO returned " + "%i, next try returns %i\n", result, result2); + } + spin_unlock_irqrestore(get_ccwdev_lock(card->rdev), flags); + + if (atomic_read(&card->break_out)) { + QETH_DBF_TEXT3(0, trace, "IARWBRKO"); + return -EIO; + } + + if (qeth_sleepon(card, QETH_MPC_TIMEOUT)) { + QETH_DBF_TEXT1(0, trace, "IRWT"); + QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id); + PRINT_ERR("IDX_ACTIVATE(wr) on read channel device %s: " + "timeout\n", card->rdev->dev.bus_id); + return -EIO; + } + +/* start reading on read channel, card->read_ccw is not yet used */ + memcpy(&card->dma_stuff->read_ccw, READ_CCW, sizeof (struct ccw1)); + card->dma_stuff->read_ccw.count = QETH_BUFSIZE; + card->dma_stuff->read_ccw.cda = QETH_GET_ADDR(card->dma_stuff->recbuf); + + spin_lock_irqsave(get_ccwdev_lock(card->rdev), flags); + result2 = 0; + result = ccw_device_start(card->rdev, &card->dma_stuff->read_ccw, + IDX_ACTIVATE_READ_STATE, 0, 0); + if (result) { + qeth_delay_millis(QETH_WAIT_BEFORE_2ND_DOIO); + result2 = ccw_device_start(card->rdev, + &card->dma_stuff->read_ccw, + IDX_ACTIVATE_READ_STATE, 0, 0); + sprintf(dbf_text, "IRR1%4x", result); + QETH_DBF_TEXT2(0, trace, dbf_text); + sprintf(dbf_text, "IRR2%4x", result2); + QETH_DBF_TEXT2(0, trace, dbf_text); + PRINT_WARN("qeth_idx_activate_read (read): do_IO " + "returned %i, next try returns %i\n", + result, result2); + } + spin_unlock_irqrestore(get_ccwdev_lock(card->rdev), flags); + + if (result2) { + result = result2; + if (result) + return result; + } + + if (qeth_sleepon(card, QETH_MPC_TIMEOUT)) { + QETH_DBF_TEXT1(0, trace, "IRRT"); + QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id); + PRINT_ERR("IDX_ACTIVATE(rd) on read channel device %s: " + "timeout\n", card->rdev->dev.bus_id); + return -EIO; + } + QETH_DBF_TEXT2(0, trace, "iarr"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + QETH_DBF_HEX2(0, control, card->dma_stuff->recbuf, + QETH_DBF_CONTROL_LEN); + + if (!(QETH_IS_IDX_ACT_POS_REPLY(card->dma_stuff->recbuf))) { + QETH_DBF_TEXT1(0, trace, "IRNR"); + QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id); + PRINT_ERR("IDX_ACTIVATE on read channel device %s: negative " + "reply\n", card->rdev->dev.bus_id); + return -EIO; + } + + card->portname_required = + ((!QETH_IDX_NO_PORTNAME_REQUIRED(card->dma_stuff->recbuf)) && + (card->type == QETH_CARD_TYPE_OSAE));; + + memcpy(&temp, QETH_IDX_ACT_FUNC_LEVEL(card->dma_stuff->recbuf), 2); + if (temp != qeth_peer_func_level(card->func_level)) { + QETH_DBF_TEXT1(0, trace, "IRFL"); + QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "%4x%4x", card->func_level, temp); + QETH_DBF_TEXT1(0, trace, dbf_text); + PRINT_WARN("IDX_ACTIVATE on read channel device %s: function " + "level mismatch (sent: 0x%x, received: 0x%x)\n", + card->rdev->dev.bus_id, card->func_level, temp); + result = -EIO; + } + + memcpy(&card->token.issuer_rm_r, + QETH_IDX_ACT_ISSUER_RM_TOKEN(card->dma_stuff->recbuf), + QETH_MPC_TOKEN_LENGTH); + + memcpy(&card->level[0], + QETH_IDX_REPLY_LEVEL(card->dma_stuff->recbuf), QETH_MCL_LENGTH); + + return result; +} + +static int +qeth_idx_activate_write(struct qeth_card *card) +{ + int result, result2; + __u16 temp; + unsigned long flags; + char dbf_text[15]; + + result = result2 = 0; + + memcpy(&card->dma_stuff->write_ccw, WRITE_CCW, sizeof (struct ccw1)); + card->dma_stuff->write_ccw.count = IDX_ACTIVATE_SIZE; + card->dma_stuff->write_ccw.cda = + QETH_GET_ADDR(card->dma_stuff->sendbuf); + + memcpy(card->dma_stuff->sendbuf, IDX_ACTIVATE_WRITE, IDX_ACTIVATE_SIZE); + memcpy(QETH_TRANSPORT_HEADER_SEQ_NO(card->dma_stuff->sendbuf), + &card->seqno.trans_hdr, QETH_SEQ_NO_LENGTH); + card->seqno.trans_hdr++; + + memcpy(QETH_IDX_ACT_ISSUER_RM_TOKEN(card->dma_stuff->sendbuf), + &card->token.issuer_rm_w, QETH_MPC_TOKEN_LENGTH); + memcpy(QETH_IDX_ACT_FUNC_LEVEL(card->dma_stuff->sendbuf), + &card->func_level, 2); + + temp = _ccw_device_get_device_number(card->ddev); + memcpy(QETH_IDX_ACT_QDIO_DEV_CUA(card->dma_stuff->sendbuf), &temp, 2); + temp = (card->cula << 8) + card->unit_addr2; + memcpy(QETH_IDX_ACT_QDIO_DEV_REALADDR(card->dma_stuff->sendbuf), + &temp, 2); + + QETH_DBF_TEXT2(0, trace, "iaww"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + QETH_DBF_HEX2(0, control, card->dma_stuff->sendbuf, + QETH_DBF_CONTROL_LEN); + + spin_lock_irqsave(get_ccwdev_lock(card->wdev), flags); + result = ccw_device_start(card->wdev, &card->dma_stuff->write_ccw, + IDX_ACTIVATE_WRITE_STATE, 0, 0); + if (result) { + qeth_delay_millis(QETH_WAIT_BEFORE_2ND_DOIO); + result2 = ccw_device_start(card->wdev, + &card->dma_stuff->write_ccw, + IDX_ACTIVATE_WRITE_STATE, 0, 0); + sprintf(dbf_text, "IWW1%4x", result); + QETH_DBF_TEXT2(0, trace, dbf_text); + sprintf(dbf_text, "IWW2%4x", result2); + QETH_DBF_TEXT2(0, trace, dbf_text); + PRINT_WARN("qeth_idx_activate_write (write): do_IO " + "returned %i, next try returns %i\n", + result, result2); + } + spin_unlock_irqrestore(get_ccwdev_lock(card->wdev), flags); + + if (atomic_read(&card->break_out)) { + QETH_DBF_TEXT3(0, trace, "IAWWBRKO"); + return -EIO; + } + + if (qeth_sleepon(card, QETH_MPC_TIMEOUT)) { + QETH_DBF_TEXT1(0, trace, "IWWT"); + QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id); + PRINT_ERR("IDX_ACTIVATE(wr) on write channel device %s: " + "timeout\n", card->wdev->dev.bus_id); + return -EIO; + } + + QETH_DBF_TEXT3(0, trace, "idxawrrd"); + /* start one read on write channel */ + memcpy(&card->dma_stuff->read_ccw, READ_CCW, sizeof (struct ccw1)); + card->dma_stuff->read_ccw.count = QETH_BUFSIZE; + /* recbuf and card->read_ccw is not yet used by any other + read channel program */ + card->dma_stuff->read_ccw.cda = QETH_GET_ADDR(card->dma_stuff->recbuf); + + spin_lock_irqsave(get_ccwdev_lock(card->wdev), flags); + result2 = 0; + result = ccw_device_start(card->wdev, &card->dma_stuff->read_ccw, + IDX_ACTIVATE_READ_STATE, 0, 0); + if (result) { + qeth_delay_millis(QETH_WAIT_BEFORE_2ND_DOIO); + result2 = ccw_device_start(card->wdev, + &card->dma_stuff->read_ccw, + IDX_ACTIVATE_READ_STATE, 0, 0); + sprintf(dbf_text, "IWR1%4x", result); + QETH_DBF_TEXT2(0, trace, dbf_text); + sprintf(dbf_text, "IWR2%4x", result2); + QETH_DBF_TEXT2(0, trace, dbf_text); + PRINT_WARN("qeth_idx_activate_write (read): do_IO returned " + "%i, next try returns %i\n", result, result2); + } + + spin_unlock_irqrestore(get_ccwdev_lock(card->wdev), flags); + + if (result2) { + result = result2; + if (result) + return result; + } + + if (qeth_sleepon(card, QETH_MPC_TIMEOUT)) { + QETH_DBF_TEXT1(0, trace, "IWRT"); + QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id); + PRINT_ERR("IDX_ACTIVATE(rd) on write channel device %s: " + "timeout\n", card->wdev->dev.bus_id); + return -EIO; + } + QETH_DBF_TEXT2(0, trace, "iawr"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + QETH_DBF_HEX2(0, control, card->dma_stuff->recbuf, + QETH_DBF_CONTROL_LEN); + + if (!(QETH_IS_IDX_ACT_POS_REPLY(card->dma_stuff->recbuf))) { + QETH_DBF_TEXT1(0, trace, "IWNR"); + QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id); + PRINT_ERR("IDX_ACTIVATE on write channel device %s: negative " + "reply\n", card->wdev->dev.bus_id); + return -EIO; + } + + memcpy(&temp, QETH_IDX_ACT_FUNC_LEVEL(card->dma_stuff->recbuf), 2); + if ((temp & ~0x0100) != qeth_peer_func_level(card->func_level)) { + QETH_DBF_TEXT1(0, trace, "IWFM"); + QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "%4x%4x", card->func_level, temp); + QETH_DBF_TEXT1(0, trace, dbf_text); + PRINT_WARN("IDX_ACTIVATE on write channel device %s: function " + "level mismatch (sent: 0x%x, received: 0x%x)\n", + card->wdev->dev.bus_id, card->func_level, temp); + result = -EIO; + } + + return result; +} + +static int +qeth_cm_enable(struct qeth_card *card) +{ + unsigned char *buffer; + int result; + char dbf_text[15]; + + memcpy(card->send_buf, CM_ENABLE, CM_ENABLE_SIZE); + + memcpy(QETH_CM_ENABLE_ISSUER_RM_TOKEN(card->send_buf), + &card->token.issuer_rm_r, QETH_MPC_TOKEN_LENGTH); + memcpy(QETH_CM_ENABLE_FILTER_TOKEN(card->send_buf), + &card->token.cm_filter_w, QETH_MPC_TOKEN_LENGTH); + + buffer = qeth_send_control_data(card, card->send_buf, + CM_ENABLE_SIZE, MPC_SETUP_STATE); + + if (!buffer) { + QETH_DBF_TEXT2(0, trace, "CME:NOBF"); + return -EIO; + } + + memcpy(&card->token.cm_filter_r, + QETH_CM_ENABLE_RESP_FILTER_TOKEN(buffer), QETH_MPC_TOKEN_LENGTH); + + result = qeth_check_idx_response(buffer); + + sprintf(dbf_text, "cme=%4x", result); + QETH_DBF_TEXT3(0, trace, dbf_text); + + return result; +} + +static int +qeth_cm_setup(struct qeth_card *card) +{ + unsigned char *buffer; + int result; + char dbf_text[15]; + + memcpy(card->send_buf, CM_SETUP, CM_SETUP_SIZE); + + memcpy(QETH_CM_SETUP_DEST_ADDR(card->send_buf), + &card->token.issuer_rm_r, QETH_MPC_TOKEN_LENGTH); + memcpy(QETH_CM_SETUP_CONNECTION_TOKEN(card->send_buf), + &card->token.cm_connection_w, QETH_MPC_TOKEN_LENGTH); + memcpy(QETH_CM_SETUP_FILTER_TOKEN(card->send_buf), + &card->token.cm_filter_r, QETH_MPC_TOKEN_LENGTH); + + buffer = qeth_send_control_data(card, card->send_buf, + CM_SETUP_SIZE, MPC_SETUP_STATE); + + if (!buffer) { + QETH_DBF_TEXT2(0, trace, "CMS:NOBF"); + return -EIO; + } + + memcpy(&card->token.cm_connection_r, + QETH_CM_SETUP_RESP_DEST_ADDR(buffer), QETH_MPC_TOKEN_LENGTH); + + result = qeth_check_idx_response(buffer); + + sprintf(dbf_text, "cms=%4x", result); + QETH_DBF_TEXT3(0, trace, dbf_text); + + return result; +} + +static int +qeth_ulp_enable(struct qeth_card *card) +{ + unsigned char *buffer; + __u16 mtu, framesize; + __u16 len; + __u8 link_type; + int result; + char dbf_text[15]; + + memcpy(card->send_buf, ULP_ENABLE, ULP_ENABLE_SIZE); + + *(QETH_ULP_ENABLE_LINKNUM(card->send_buf)) = + (__u8) card->options.portno; + + memcpy(QETH_ULP_ENABLE_DEST_ADDR(card->send_buf), + &card->token.cm_connection_r, QETH_MPC_TOKEN_LENGTH); + memcpy(QETH_ULP_ENABLE_FILTER_TOKEN(card->send_buf), + &card->token.ulp_filter_w, QETH_MPC_TOKEN_LENGTH); + + memcpy(QETH_ULP_ENABLE_PORTNAME_AND_LL(card->send_buf), + card->options.portname, 9); + + buffer = qeth_send_control_data(card, card->send_buf, + ULP_ENABLE_SIZE, MPC_SETUP_STATE); + + if (!buffer) { + QETH_DBF_TEXT2(0, trace, "ULE:NOBF"); + return -EIO; + } + + memcpy(&card->token.ulp_filter_r, + QETH_ULP_ENABLE_RESP_FILTER_TOKEN(buffer), + QETH_MPC_TOKEN_LENGTH); + + /* to be done before qeth_init_ringbuffers and qeth_init_dev */ + if (qeth_get_mtu_out_of_mpc(card->type)) { + memcpy(&framesize, QETH_ULP_ENABLE_RESP_MAX_MTU(buffer), 2); + mtu = qeth_get_mtu_outof_framesize(framesize); + + QETH_DBF_TEXT2(0, trace, "ule"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + sprintf(dbf_text, "mtu=%4x", mtu); + QETH_DBF_TEXT2(0, trace, dbf_text); + + if (!mtu) + return -EINVAL; + + card->max_mtu = mtu; + card->initial_mtu = mtu; + card->inbound_buffer_size = mtu + 2 * PAGE_SIZE; + } else { + card->initial_mtu = qeth_get_initial_mtu_for_card(card); + card->max_mtu = qeth_get_max_mtu_for_card(card->type); + card->inbound_buffer_size = DEFAULT_BUFFER_SIZE; + } + + memcpy(&len, QETH_ULP_ENABLE_RESP_DIFINFO_LEN(buffer), 2); + if (len >= QETH_MPC_DIFINFO_LEN_INDICATES_LINK_TYPE) { + memcpy(&link_type, QETH_ULP_ENABLE_RESP_LINK_TYPE(buffer), 1); + card->link_type = link_type; + sprintf(dbf_text, "link=%2x", link_type); + QETH_DBF_TEXT2(0, trace, dbf_text); + } else + card->link_type = 0; + + result = qeth_check_idx_response(buffer); + + sprintf(dbf_text, "ule=%4x", result); + QETH_DBF_TEXT3(0, trace, dbf_text); + + return result; +} + +static int +qeth_ulp_setup(struct qeth_card *card) +{ + unsigned char *buffer; + __u16 temp; + int result; + char dbf_text[15]; + + memcpy(card->send_buf, ULP_SETUP, ULP_SETUP_SIZE); + + memcpy(QETH_ULP_SETUP_DEST_ADDR(card->send_buf), + &card->token.cm_connection_r, QETH_MPC_TOKEN_LENGTH); + memcpy(QETH_ULP_SETUP_CONNECTION_TOKEN(card->send_buf), + &card->token.ulp_connection_w, QETH_MPC_TOKEN_LENGTH); + memcpy(QETH_ULP_SETUP_FILTER_TOKEN(card->send_buf), + &card->token.ulp_filter_r, QETH_MPC_TOKEN_LENGTH); + + temp = _ccw_device_get_device_number(card->ddev); + memcpy(QETH_ULP_SETUP_CUA(card->send_buf), &temp, 2); + temp = (card->cula << 8) + card->unit_addr2; + memcpy(QETH_ULP_SETUP_REAL_DEVADDR(card->send_buf), &temp, 2); + + buffer = qeth_send_control_data(card, card->send_buf, + ULP_SETUP_SIZE, MPC_SETUP_STATE); + + if (!buffer) { + QETH_DBF_TEXT2(0, trace, "ULS:NOBF"); + return -EIO; + } + + memcpy(&card->token.ulp_connection_r, + QETH_ULP_SETUP_RESP_CONNECTION_TOKEN(buffer), + QETH_MPC_TOKEN_LENGTH); + + result = qeth_check_idx_response(buffer); + + sprintf(dbf_text, "uls=%4x", result); + QETH_DBF_TEXT3(0, trace, dbf_text); + + return result; +} + +static int +qeth_qdio_establish(struct qeth_card *card) +{ + int result; + char *adapter_area; + char dbf_text[15]; + void **input_array, **output_array, **ptr; + int i, j; + struct qdio_initialize init_data; + + adapter_area = vmalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof(char)); + if (!adapter_area) + return -ENOMEM; + + memset(adapter_area, 0, QDIO_MAX_BUFFERS_PER_Q * sizeof(char)); + + adapter_area[0] = _ascebc['P']; + adapter_area[1] = _ascebc['C']; + adapter_area[2] = _ascebc['I']; + adapter_area[3] = _ascebc['T']; + *((unsigned int *) (&adapter_area[4])) = PCI_THRESHOLD_A; + *((unsigned int *) (&adapter_area[8])) = PCI_THRESHOLD_B; + *((unsigned int *) (&adapter_area[12])) = PCI_TIMER_VALUE; + + input_array = vmalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof (void *)); + if (!input_array) { + vfree(adapter_area); + return -ENOMEM; + } + ptr = input_array; + for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++) { + *ptr = (void *) virt_to_phys(&card->inbound_qdio_buffers[j]); + ptr++; + } + + output_array = vmalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof (void *) * + card->no_queues); + if (!output_array) { + vfree(input_array); + vfree(adapter_area); + return -ENOMEM; + } + ptr = output_array; + for (i = 0; i < card->no_queues; i++) + for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++) { + *ptr = (void *) virt_to_phys + (&card->outbound_ringbuffer[i]->buffer[j]); + ptr++; + } + + init_data.cdev = card->ddev; + init_data.q_format = qeth_get_q_format(card->type); + init_data.qib_param_field_format = 0; + init_data.qib_param_field = adapter_area; + init_data.input_slib_elements = NULL; + init_data.output_slib_elements = NULL; + init_data.min_input_threshold = card->options.polltime; + init_data.max_input_threshold = card->options.polltime; + init_data.min_output_threshold = QETH_MIN_OUTPUT_THRESHOLD; + init_data.max_output_threshold = QETH_MAX_OUTPUT_THRESHOLD; + init_data.no_input_qs = 1; + init_data.no_output_qs = card->no_queues; + init_data.input_handler = qeth_qdio_input_handler; + init_data.output_handler = qeth_qdio_output_handler; + init_data.int_parm = (unsigned long) card; + init_data.flags = QDIO_INBOUND_0COPY_SBALS | + QDIO_OUTBOUND_0COPY_SBALS | QDIO_USE_OUTBOUND_PCIS; + init_data.input_sbal_addr_array = input_array; + init_data.output_sbal_addr_array = output_array; + + result = qdio_initialize(&init_data); + + vfree(input_array); + vfree(output_array); + vfree(adapter_area); + + sprintf(dbf_text, "qde=%4i", result); + QETH_DBF_TEXT3(0, trace, dbf_text); + + return result; +} + +static int +qeth_qdio_activate(struct qeth_card *card) +{ + int result; + char dbf_text[15]; + + result = qdio_activate(card->ddev, 0); + + sprintf(dbf_text, "qda=%4x", result); + QETH_DBF_TEXT3(0, trace, dbf_text); + + return result; +} + +static int +qeth_dm_act(struct qeth_card *card) +{ + unsigned char *buffer; + int result; + char dbf_text[15]; + + memcpy(card->send_buf, DM_ACT, DM_ACT_SIZE); + + memcpy(QETH_DM_ACT_DEST_ADDR(card->send_buf), + &card->token.cm_connection_r, QETH_MPC_TOKEN_LENGTH); + memcpy(QETH_DM_ACT_CONNECTION_TOKEN(card->send_buf), + &card->token.ulp_connection_r, QETH_MPC_TOKEN_LENGTH); + + buffer = qeth_send_control_data(card, card->send_buf, + DM_ACT_SIZE, MPC_SETUP_STATE); + + if (!buffer) { + QETH_DBF_TEXT2(0, trace, "DMA:NOBF"); + return -EIO; + } + + result = qeth_check_idx_response(buffer); + + sprintf(dbf_text, "dma=%4x", result); + QETH_DBF_TEXT3(0, trace, dbf_text); + + return result; +} + +static inline int +__qeth_verify_dev_vlan(struct net_device *dev,struct qeth_card *card) +{ +#ifdef QETH_VLAN + struct vlan_group *vlan_grp; + int i; + int result = 0; + + /* check all vlan devices */ + vlan_grp = (struct vlan_group *) card->vlangrp; + if (vlan_grp) { + for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { + if (vlan_grp->vlan_devices[i] == dev) { + result = QETH_VERIFY_IS_VLAN_DEV; + } + } + } + return result; +#endif + return 0; +} + +#if defined(QETH_VLAN)||defined(QETH_IPV6) +static int +qeth_verify_dev(struct net_device *dev) +{ + struct qeth_card *tmp; + int result = 0; + + read_lock(&list_lock); + tmp = firstcard; + for (; tmp && (!result); tmp = tmp->next) { + if (atomic_read(&tmp->shutdown_phase)) + continue; + if (dev == tmp->dev) { + result = QETH_VERIFY_IS_REAL_DEV; + } + result = __qeth_verify_dev_vlan(dev, tmp); + } + read_unlock(&list_lock); + return result; +} +#endif /* defined(QETH_VLAN)||defined(QETH_IPV6) */ + +static int +qeth_verify_card(struct qeth_card *card) +{ + struct qeth_card *tmp; + int result = 0; + + read_lock(&list_lock); + tmp = firstcard; + while (tmp) { + if ((card == tmp) && (!atomic_read(&card->shutdown_phase))) { + result = 1; + break; + } + tmp = tmp->next; + } + read_unlock(&list_lock); + return result; +} + +static inline struct qeth_card * +__qeth_get_card_from_dev(struct net_device *dev) +{ +#ifdef QETH_VLAN + if (qeth_verify_dev(dev) == QETH_VERIFY_IS_VLAN_DEV) + return (struct qeth_card *) VLAN_DEV_INFO(dev)->real_dev->priv; + else +#endif + return (struct qeth_card *) dev->priv; +} + +#ifdef QETH_IPV6 +/* FIXME: don't put extern declarations in a c file, use a header that's + * shared with the definition for this! */ +extern struct neigh_table arp_tbl; +static int (*qeth_old_arp_constructor) (struct neighbour *); +static struct neigh_ops arp_direct_ops_template = { + .family = AF_INET, + .destructor = NULL, + .solicit = NULL, + .error_report = NULL, + .output = dev_queue_xmit, + .connected_output = dev_queue_xmit, + .hh_output = dev_queue_xmit, + .queue_xmit = dev_queue_xmit +}; + +/* + * FIXME: + * as we have neighbour structures point to this structure, even + * after our life time, this will stay in memory as a leak + */ +static struct neigh_ops *arp_direct_ops; + + +static int +qeth_arp_constructor(struct neighbour *neigh) +{ + char dbf_text[15]; + struct net_device *dev = neigh->dev; + struct in_device *in_dev = in_dev_get(dev); + + if (in_dev == NULL) + return -EINVAL; + + QETH_DBF_TEXT4(0, trace, "arpconst"); + if (!qeth_verify_dev(dev)) { + + in_dev_put(in_dev); + return qeth_old_arp_constructor(neigh); + } + + neigh->type = inet_addr_type(*(u32 *) neigh->primary_key); + if (in_dev->arp_parms) + neigh->parms = in_dev->arp_parms; + + in_dev_put(in_dev); + + sprintf(dbf_text, "%08x", ntohl(*((__u32 *) (neigh->primary_key)))); + QETH_DBF_TEXT4(0, trace, dbf_text); + QETH_DBF_HEX4(0, trace, &neigh, sizeof (void *)); + + neigh->nud_state = NUD_NOARP; + neigh->ops = arp_direct_ops; + neigh->output = neigh->ops->queue_xmit; + return 0; +} + +static int +qeth_hard_header(struct sk_buff *skb, struct net_device *dev, + unsigned short type, void *daddr, void *saddr, unsigned len) +{ + struct qeth_card *card; + + QETH_DBF_TEXT5(0, trace, "hardhdr"); + + card = __qeth_get_card_from_dev(dev); + return card->hard_header(skb, dev, type, daddr, saddr, len); +} + +static void +qeth_header_cache_update(struct hh_cache *hh, + struct net_device *dev, unsigned char *haddr) +{ + struct qeth_card *card; + + card = (struct qeth_card *) dev->priv; + QETH_DBF_TEXT5(0, trace, "hdrcheup"); + return card->header_cache_update(hh, dev, haddr); +} + +static int +qeth_rebuild_header(struct sk_buff *skb) +{ + struct qeth_card *card; + QETH_DBF_TEXT5(0, trace, "rebldhdr"); + if (skb->protocol == __constant_htons(ETH_P_IP)) + return 0; + + card = __qeth_get_card_from_dev(skb->dev); + + return card->rebuild_header(skb); +} + +int +qeth_ipv6_generate_eui64(u8 * eui, struct net_device *dev) +{ + switch (dev->type) { + case ARPHRD_ETHER: + case ARPHRD_FDDI: + case ARPHRD_IEEE802_TR: + if (dev->addr_len != ETH_ALEN) + return -1; + memcpy(eui, dev->dev_addr, 3); + memcpy(eui + 5, dev->dev_addr + 3, 3); + eui[3] = (dev->dev_id >> 8) & 0xff; + eui[4] = dev->dev_id & 0xff; + return 0; + } + return -1; + +} +#endif /* QETH_IPV6 */ + +static void +qeth_ipv6_init_card(struct qeth_card *card) +{ +#ifdef QETH_IPV6 + card->hard_header = qeth_get_hard_header(card->link_type); + card->rebuild_header = qeth_get_rebuild_header(card->link_type); + card->hard_header_cache = qeth_get_hard_header_cache(card->link_type); + card->header_cache_update = + qeth_get_header_cache_update(card->link_type); + card->type_trans = qeth_get_type_trans(card->link_type); + card->dev->dev_id = card->unique_id & 0xffff; + if (!(card->unique_id & UNIQUE_ID_NOT_BY_CARD)) + card->dev->generate_eui64 = qeth_ipv6_generate_eui64; +#endif /* QETH_IPV6 */ +} + +#ifdef QETH_VLAN +static void +qeth_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) +{ + struct qeth_card *card; + card = (struct qeth_card *) dev->priv; + spin_lock_irq(&card->vlan_lock); + card->vlangrp = grp; + spin_unlock_irq(&card->vlan_lock); +} +static void +qeth_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) +{ + struct qeth_card *card; + card = (struct qeth_card *) dev->priv; + spin_lock_irq(&card->vlan_lock); + if (card->vlangrp) + card->vlangrp->vlan_devices[vid] = NULL; + spin_unlock_irq(&card->vlan_lock); +} +#endif + +static void +qeth_tx_timeout(struct net_device *dev) +{ + struct qeth_card *card; + + card = (struct qeth_card *) dev->priv; + QETH_DBF_TEXT2(1, trace, "XMTO"); + QETH_DBF_TEXT2(1, trace, card->rdev->dev.bus_id); + card->stats->tx_errors++; + atomic_set(&card->problem, PROBLEM_TX_TIMEOUT); + qeth_schedule_recovery(card); +} + +static void* +__qeth_rebuild_header_func(struct qeth_card *card) +{ +#ifdef QETH_IPV6 + return (!(qeth_get_additional_dev_flags(card->type) & IFF_NOARP)) ? + (qeth_get_rebuild_header(card->link_type) ? + qeth_rebuild_header : NULL) : NULL; +#endif /* QETH_IPV6 */ + return NULL; +} + +static void* +__qeth_hard_header_func(struct qeth_card *card) +{ +#ifdef QETH_IPV6 + return (!(qeth_get_additional_dev_flags(card->type) & IFF_NOARP)) ? + (qeth_get_hard_header(card->link_type) ? + qeth_hard_header : NULL) : NULL; +#endif /* QETH_IPV6 */ + return NULL; +} + +static void* +__qeth_header_cache_update_func(struct qeth_card *card) +{ +#ifdef QETH_IPV6 + return (!(qeth_get_additional_dev_flags(card->type) & IFF_NOARP)) ? + (qeth_get_header_cache_update(card->link_type) ? + qeth_header_cache_update : NULL) : NULL; +#endif /* QETH_IPV6 */ + return NULL; +} + +static void* +__qeth_hard_header_cache_func(struct qeth_card *card) +{ +#ifdef QETH_IPV6 + return (!(qeth_get_additional_dev_flags(card->type) & IFF_NOARP)) ? + qeth_get_hard_header_cache(card->link_type) : NULL; +#endif /* QETH_IPV6 */ + return NULL; +} + +static int +qeth_init_dev(struct net_device *dev) +{ + struct qeth_card *card; + + card = (struct qeth_card *) dev->priv; + + QETH_DBF_TEXT3(0, trace, "inid"); + QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id); + + dev->tx_timeout = &qeth_tx_timeout; + dev->watchdog_timeo = QETH_TX_TIMEOUT; + dev->open = qeth_open; + dev->stop = qeth_stop; + dev->set_config = qeth_set_config; + dev->hard_start_xmit = qeth_hard_start_xmit; + dev->do_ioctl = qeth_do_ioctl; + dev->get_stats = qeth_get_stats; + dev->change_mtu = qeth_change_mtu; +#ifdef QETH_VLAN + dev->vlan_rx_register = qeth_vlan_rx_register; + dev->vlan_rx_kill_vid = qeth_vlan_rx_kill_vid; +#endif + dev->rebuild_header = __qeth_rebuild_header_func(card); + dev->hard_header = __qeth_hard_header_func(card); + dev->header_cache_update = __qeth_header_cache_update_func(card); + dev->hard_header_cache = __qeth_hard_header_cache_func(card); + dev->hard_header_parse = NULL; + dev->destructor = qeth_destructor; + dev->set_multicast_list = qeth_set_multicast_list; + dev->set_mac_address = qeth_set_mac_address; + dev->neigh_setup = qeth_neigh_setup; + + dev->flags |= qeth_get_additional_dev_flags(card->type); + + dev->flags |= ((card->options.fake_broadcast == FAKE_BROADCAST) || + (card->broadcast_capable)) ? IFF_BROADCAST : 0; + + /* is done in hardsetup_card... see comment below + qeth_send_qipassist(card,4);*/ + + /* that was the old place. one id. we need to make sure, that + * hydra knows about us going to use the same id again, so we + * do that in hardsetup_card every time + qeth_get_unique_id(card);*/ + + dev->tx_queue_len = qeth_get_device_tx_q_len(card->type); + dev->hard_header_len = + qeth_get_hlen(card->link_type) + card->options.add_hhlen; + dev->addr_len = OSA_ADDR_LEN; /* is ok for eth, tr, atm lane */ + SET_MODULE_OWNER(dev); + netif_start_queue(dev); + + dev->mtu = card->initial_mtu; + + qeth_ipv6_init_card(card); + + return 0; +} + +static int +qeth_get_unitaddr(struct qeth_card *card) +{ + char *prcd; + int result = 0; + char dbf_text[15]; + int length; + + QETH_DBF_TEXT3(0, trace, "gtua"); + QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id); + + result = read_conf_data(card->ddev, (void **) &prcd, &length); + if (result) { + sprintf(dbf_text, "rcd%4x", result); + QETH_DBF_TEXT3(0, trace, dbf_text); + PRINT_ERR("read_conf_data for device %s returned %i\n", + card->ddev->dev.bus_id, result); + return result; + } + + card->chpid = prcd[30]; + card->unit_addr2 = prcd[31]; + card->cula = prcd[63]; + card->is_guest_lan= ((prcd[0x10] == _ascebc['V']) && + (prcd[0x11] == _ascebc['M'])); + + sprintf(dbf_text, "chpid:%02x", card->chpid); + QETH_DBF_TEXT2(0, trace, dbf_text); + sprintf(dbf_text, "unad2:%02x", card->unit_addr2); + QETH_DBF_TEXT2(0, trace, dbf_text); + sprintf(dbf_text, "cula:%02x", card->cula); + QETH_DBF_TEXT2(0, trace, dbf_text); + + return 0; +} + +static int +qeth_send_nops(struct qeth_card *card) +{ + int result, result2; + unsigned long saveflags; + + card->dma_stuff->write_ccw.cmd_code = CCW_NOP_CMD; + card->dma_stuff->write_ccw.flags = CCW_FLAG_SLI; + card->dma_stuff->write_ccw.count = CCW_NOP_COUNT; + card->dma_stuff->write_ccw.cda = (unsigned long) NULL; + +#define DO_SEND_NOP(cdev) \ +do { \ + QETH_DBF_TEXT3(0, trace, "snnp"); \ + QETH_DBF_TEXT3(0, trace, cdev->dev.bus_id); \ +\ + spin_lock_irqsave(get_ccwdev_lock(cdev),saveflags); \ + ccw_device_set_options(cdev, 0); \ + result=ccw_device_start(cdev,&card->dma_stuff->write_ccw, \ + NOP_STATE,0,0); \ + if (result) { \ + qeth_delay_millis(QETH_WAIT_BEFORE_2ND_DOIO); \ + result2=ccw_device_start(cdev,&card->dma_stuff->write_ccw, \ + NOP_STATE,0,0); \ + PRINT_WARN("qeth_send_nops on device %s: do_IO returned %i, " \ + "next try returns %i\n", \ + cdev->dev.bus_id,result,result2); \ + result=result2; \ + } \ + spin_unlock_irqrestore(get_ccwdev_lock(cdev),saveflags); \ +\ + if (result) goto exit; \ +\ + if (qeth_sleepon(card,QETH_NOP_TIMEOUT)) { \ + QETH_DBF_TEXT2(0,trace,"snnp:tme"); \ + result=-EIO; \ + goto exit; \ + } \ +} while (0) + + DO_SEND_NOP(card->rdev); + DO_SEND_NOP(card->wdev); + DO_SEND_NOP(card->ddev); + +exit: + return result; +} + +static void +qeth_clear_card_structures(struct qeth_card *card) +{ + int i, j; + + if (!card) { + QETH_DBF_TEXT2(0, trace, "clrCRDnc"); + return; + } + + QETH_DBF_TEXT3(0, trace, "clcs"); + QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id); + + atomic_set(&card->is_startlaned, 0); + + for (i = 0; i < QETH_MAX_QUEUES; i++) { + card->send_state[i] = SEND_STATE_DONT_PACK; + card->outbound_first_free_buffer[i] = 0; + atomic_set(&card->outbound_used_buffers[i], 0); + atomic_set(&card->outbound_ringbuffer_lock[i], 0); + + for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++) { + card->outbound_buffer_send_state[i][j] = + SEND_STATE_DONT_PACK; + card->send_retries[i][j] = 0; + + if (i < card->no_queues) { + card->outbound_ringbuffer[i]-> + ringbuf_element[j].next_element_to_fill = 0; + card->outbound_bytes_in_buffer[i] = 0; + skb_queue_head_init(&card-> + outbound_ringbuffer[i]-> + ringbuf_element[j]. + skb_list); + } + } + } + + for (i = 0; i < card->options.inbound_buffer_count; i++) { + xchg((int *) &card->inbound_buffer_pool_entry_used[i], + BUFFER_UNUSED); + } + + spin_lock_init(&card->requeue_input_lock); + atomic_set(&card->requeue_position, 0); + atomic_set(&card->requeue_counter, 0); + + card->seqno.trans_hdr = 0; + card->seqno.pdu_hdr = 0; + card->seqno.pdu_hdr_ack = 0; + card->seqno.ipa = 0; + + qeth_clear_ifa4_list(&card->ip_current_state.ip_ifa); + qeth_clear_ifa4_list(&card->ip_new_state.ip_ifa); + qeth_clear_ifamc_list(&card->ip_mc_current_state.ipm_ifa); + qeth_clear_ifamc_list(&card->ip_mc_new_state.ipm_ifa); + +#ifdef QETH_IPV6 + qeth_clear_ifa6_list(&card->ip_current_state.ip6_ifa); + qeth_clear_ifa6_list(&card->ip_new_state.ip6_ifa); + qeth_clear_ifamc_list(&card->ip_mc_current_state.ipm6_ifa); + qeth_clear_ifamc_list(&card->ip_mc_new_state.ipm6_ifa); +#endif /* QETH_IPV6 */ +} + +static void +qeth_init_input_buffers(struct qeth_card *card) +{ + int i; + + /* slowly, slowly (we don't want to enqueue all buffers + * at one time) */ + for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++) { + atomic_set(&card->inbound_buffer_refcnt[i], 1); + } + for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++) { + atomic_set(&card->inbound_buffer_refcnt[i], 0); + /* only try to queue as many buffers as we have at all */ + if (i < card->options.inbound_buffer_count) + qeth_queue_input_buffer(card,i,0); + } + qdio_synchronize(card->ddev, QDIO_FLAG_SYNC_INPUT, 0); +} + +/* initializes all the structures for a card */ +static int +qeth_hardsetup_card(struct qeth_card *card, int in_recovery) +{ + int result, q, breakout; + unsigned long flags; + int laps = QETH_HARDSETUP_LAPS; + int clear_laps; + int cleanup_qdio; + char dbf_text[15]; + int i, r; + + /* setup name and so on */ + atomic_set(&card->shutdown_phase, 0); + + if (atomic_read(&card->is_hardsetup)) { + QETH_DBF_TEXT2(1, trace, "hscd"); + QETH_DBF_TEXT2(1, trace, card->rdev->dev.bus_id); + PRINT_ALL("card is already hardsetup.\n"); + return 0; + } + + cleanup_qdio = in_recovery; /* if we are in recovery, we clean + the qdio stuff up */ + + spin_lock(&card->hardsetup_lock); + atomic_set(&card->write_busy, 0); + + do { + if (in_recovery) { + PRINT_STUPID("qeth: recovery: quiescing %s...\n", + card->dev_name); + QETH_DBF_TEXT2(0, trace, "Rqsc"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + qeth_wait_nonbusy(QETH_QUIESCE_WAIT_BEFORE_CLEAR); + } + clear_laps = QETH_HARDSETUP_CLEAR_LAPS; + do { + if (in_recovery) + PRINT_STUPID("clearing card %s\n", + card->dev_name); + qeth_clear_card(card, cleanup_qdio, + (card->type == QETH_CARD_TYPE_OSAE)); + result = qeth_send_nops(card); + breakout = atomic_read(&card->break_out); + } while ((--clear_laps) && (result)); + if (result) { + goto exit; + } + + if (in_recovery) { + PRINT_STUPID("qeth: recovery: still quiescing %s...\n", + card->dev_name); + QETH_DBF_TEXT2(0, trace, "RQsc"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + qeth_wait_nonbusy(QETH_QUIESCE_WAIT_AFTER_CLEAR); + } else { + atomic_set(&card->shutdown_phase, 0); + } + + cleanup_qdio = 0; /* qdio was cleaned now, if necessary */ + + result = qeth_get_unitaddr(card); + if (result) + goto exit; + + qeth_generate_tokens(card); + +#define PRINT_TOKENS do { \ + sprintf(dbf_text,"stra "); \ + memcpy(&dbf_text[4],&card->seqno.trans_hdr,4); \ + QETH_DBF_HEX3(0,trace,dbf_text,QETH_DBF_TRACE_LEN); \ + sprintf(dbf_text,"spdu "); \ + memcpy(&dbf_text[4],&card->seqno.pdu_hdr,4); \ + QETH_DBF_HEX3(0,trace,dbf_text,QETH_DBF_TRACE_LEN); \ + sprintf(dbf_text,"spda "); \ + memcpy(&dbf_text[4],&card->seqno.pdu_hdr_ack,4); \ + QETH_DBF_HEX3(0,trace,dbf_text,QETH_DBF_TRACE_LEN); \ + sprintf(dbf_text,"sipa "); \ + memcpy(&dbf_text[4],&card->seqno.ipa,4); \ + QETH_DBF_HEX3(0,trace,dbf_text,QETH_DBF_TRACE_LEN); \ + sprintf(dbf_text,"tisw "); \ + memcpy(&dbf_text[4],&card->token.issuer_rm_w,4); \ + QETH_DBF_HEX3(0,trace,dbf_text,QETH_DBF_TRACE_LEN); \ + sprintf(dbf_text,"tisr "); \ + memcpy(&dbf_text[4],&card->token.issuer_rm_r,4); \ + QETH_DBF_HEX3(0,trace,dbf_text,QETH_DBF_TRACE_LEN); \ + sprintf(dbf_text,"tcfw "); \ + memcpy(&dbf_text[4],&card->token.cm_filter_w,4); \ + QETH_DBF_HEX3(0,trace,dbf_text,QETH_DBF_TRACE_LEN); \ + sprintf(dbf_text,"tcfr "); \ + memcpy(&dbf_text[4],&card->token.cm_filter_r,4); \ + QETH_DBF_HEX3(0,trace,dbf_text,QETH_DBF_TRACE_LEN); \ + sprintf(dbf_text,"tccw "); \ + memcpy(&dbf_text[4],&card->token.cm_connection_w,4); \ + QETH_DBF_HEX3(0,trace,dbf_text,QETH_DBF_TRACE_LEN); \ + sprintf(dbf_text,"tccr "); \ + memcpy(&dbf_text[4],&card->token.cm_connection_r,4); \ + QETH_DBF_HEX3(0,trace,dbf_text,QETH_DBF_TRACE_LEN); \ + sprintf(dbf_text,"tufw "); \ + memcpy(&dbf_text[4],&card->token.ulp_filter_w,4); \ + QETH_DBF_HEX3(0,trace,dbf_text,QETH_DBF_TRACE_LEN); \ + sprintf(dbf_text,"tufr "); \ + memcpy(&dbf_text[4],&card->token.ulp_filter_r,4); \ + QETH_DBF_HEX3(0,trace,dbf_text,QETH_DBF_TRACE_LEN); \ + sprintf(dbf_text,"tucw "); \ + memcpy(&dbf_text[4],&card->token.ulp_connection_w,4); \ + QETH_DBF_HEX3(0,trace,dbf_text,QETH_DBF_TRACE_LEN); \ + sprintf(dbf_text,"tucr "); \ + memcpy(&dbf_text[4],&card->token.ulp_connection_r,4); \ + QETH_DBF_HEX3(0,trace,dbf_text,QETH_DBF_TRACE_LEN); \ + } while (0) + + PRINT_TOKENS; + + /* card->break_out and problem will be set here to 0 + * (in each lap) (there can't be a problem at this + * early time) */ + atomic_set(&card->problem, 0); + atomic_set(&card->break_out, 0); + +#define CHECK_ERRORS \ + breakout=atomic_read(&card->break_out); \ + if (breakout==QETH_BREAKOUT_AGAIN) \ + continue; \ + else if (breakout==QETH_BREAKOUT_LEAVE) { \ + result=-EIO; \ + goto exit; \ + } \ + if (result) goto exit + + QETH_DBF_TEXT2(0, trace, "hsidxard"); + result = qeth_idx_activate_read(card); + CHECK_ERRORS; + + PRINT_TOKENS; + QETH_DBF_TEXT2(0, trace, "hsidxawr"); + result = qeth_idx_activate_write(card); + CHECK_ERRORS; + + QETH_DBF_TEXT2(0, trace, "hsissurd"); + /* from here, there will always be an outstanding read */ + spin_lock_irqsave(get_ccwdev_lock(card->rdev), flags); + qeth_issue_next_read(card); + spin_unlock_irqrestore(get_ccwdev_lock(card->rdev), flags); + + PRINT_TOKENS; + QETH_DBF_TEXT2(0, trace, "hscmenab"); + result = qeth_cm_enable(card); + CHECK_ERRORS; + + PRINT_TOKENS; + QETH_DBF_TEXT2(0, trace, "hscmsetu"); + result = qeth_cm_setup(card); + CHECK_ERRORS; + + PRINT_TOKENS; + QETH_DBF_TEXT2(0, trace, "hsulpena"); + result = qeth_ulp_enable(card); + CHECK_ERRORS; + + PRINT_TOKENS; + QETH_DBF_TEXT2(0, trace, "hsulpset"); + result = qeth_ulp_setup(card); + CHECK_ERRORS; + + cleanup_qdio = 1; + + QETH_DBF_TEXT2(0, trace, "hsqdioes"); + result = qeth_qdio_establish(card); + CHECK_ERRORS; + + PRINT_TOKENS; + QETH_DBF_TEXT2(0, trace, "hsqdioac"); + result = qeth_qdio_activate(card); + CHECK_ERRORS; + + PRINT_TOKENS; + QETH_DBF_TEXT2(0, trace, "hsdmact"); + result = qeth_dm_act(card); + CHECK_ERRORS; + } while ((laps--) && (breakout == QETH_BREAKOUT_AGAIN)); + if (breakout == QETH_BREAKOUT_AGAIN) { + QETH_DBF_TEXT2(0, trace, "hsnr"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + PRINT_ERR("qeth: recovery not successful on device " + "%s/%s/%s; giving up.\n", + card->rdev->dev.bus_id, + card->wdev->dev.bus_id, card->ddev->dev.bus_id); + result = -EIO; + goto exit; + } + + qeth_clear_ifa4_list(&card->ip_current_state.ip_ifa); + qeth_clear_ifa4_list(&card->ip_new_state.ip_ifa); + qeth_clear_ifamc_list(&card->ip_mc_current_state.ipm_ifa); + qeth_clear_ifamc_list(&card->ip_mc_new_state.ipm_ifa); + +#ifdef QETH_IPV6 + qeth_clear_ifa6_list(&card->ip_current_state.ip6_ifa); + qeth_clear_ifa6_list(&card->ip_new_state.ip6_ifa); + qeth_clear_ifamc_list(&card->ip_mc_current_state.ipm6_ifa); + qeth_clear_ifamc_list(&card->ip_mc_new_state.ipm6_ifa); +#endif /* QETH_IPV6 */ + + if (!atomic_read(&card->is_registered)) { + card->dev->dev_addr[0] = 0; /* we don't know the mac addr yet */ + card->dev->dev_addr[1] = 0; + card->dev->dev_addr[2] = 0; + card->dev->dev_addr[3] = 0; + card->dev->dev_addr[4] = 0; + card->dev->dev_addr[5] = 0; + card->dev->broadcast[0] = card->dev->broadcast[1] = 0xff; + card->dev->broadcast[2] = card->dev->broadcast[3] = 0xff; + card->dev->broadcast[4] = card->dev->broadcast[5] = 0xff; + + card->dev->type = qeth_get_arphrd_type(card->type, + card->link_type); + + card->dev->init = qeth_init_dev; + + if (card->options.memusage == MEMUSAGE_CONTIG) { + card->easy_copy_cap = + qeth_determine_easy_copy_cap(card->type); + } else + card->easy_copy_cap = 0; + card->ipa_timeout = qeth_get_ipa_timeout(card->type); + } + + atomic_set(&card->is_hardsetup, 1); + atomic_set(&card->is_softsetup, 0); + atomic_set(&card->startlan_attempts, 1); + + for (q = 0; q < card->no_queues; q++) + card->send_state[q] = SEND_STATE_DONT_PACK; + + /* we need to know first, whether we should include a value + * into eui-64 address generation */ + QETH_DBF_TEXT2(0, trace, "qipassi4"); + r = qeth_send_qipassist(card, 4); + if (r) { + PRINT_WARN("couldn't send QIPASSIST4 on %s: " + "0x%x\n", card->dev_name, r); + sprintf(dbf_text, "QIP4%4x", r); + QETH_DBF_TEXT2(0, trace, dbf_text); + } + + sprintf(dbf_text, "%4x%4x", card->ipa_supported, card->ipa_enabled); + QETH_DBF_TEXT2(0, trace, dbf_text); + + qeth_get_unique_id(card); + + /* print out status */ + if (in_recovery) { + qeth_clear_card_structures(card); + qeth_init_input_buffers(card); + QETH_DBF_TEXT1(0, trace, "RECOVSUC"); + PRINT_INFO("qeth: recovered device %s/%s/%s (%s) " + "successfully.\n", + card->rdev->dev.bus_id, + card->wdev->dev.bus_id, + card->ddev->dev.bus_id, card->dev_name); + } else { + QETH_DBF_TEXT2(0, trace, "hrdsetok"); + + switch (card->type) { + case QETH_CARD_TYPE_OSAE: + /* + * VM will use a non-zero first character to indicate + * a HiperSockets like reporting of the level + * OSA sets the first character to zero + */ + if (!card->level[0]) { + sprintf(card->level, "%02x%02x", card->level[2], + card->level[3]); + card->level[QETH_MCL_LENGTH] = 0; + break; + } + /* fallthrough */ + case QETH_CARD_TYPE_IQD: + card->level[0] = (char) _ebcasc[(__u8) card->level[0]]; + card->level[1] = (char) _ebcasc[(__u8) card->level[1]]; + card->level[2] = (char) _ebcasc[(__u8) card->level[2]]; + card->level[3] = (char) _ebcasc[(__u8) card->level[3]]; + card->level[QETH_MCL_LENGTH] = 0; + break; + default: + memset(&card->level[0], 0, QETH_MCL_LENGTH + 1); + } + + sprintf(dbf_text, "lvl:%s", card->level); + QETH_DBF_TEXT2(0, setup, dbf_text); + + if (card->portname_required) { + sprintf(dbf_text, "%s", card->options.portname + 1); + for (i = 0; i < 8; i++) + dbf_text[i] = + (char) _ebcasc[(__u8) dbf_text[i]]; + dbf_text[8] = 0; + printk("qeth: Device %s/%s/%s is a%s card%s%s%s\n" + "with link type %s (portname: %s)\n", + card->rdev->dev.bus_id, + card->wdev->dev.bus_id, + card->ddev->dev.bus_id, + qeth_get_cardname(card->type, + card->is_guest_lan), + (card->level[0]) ? " (level: " : "", + (card->level[0]) ? card->level : "", + (card->level[0]) ? ")" : "", + qeth_get_link_type_name(card->type, + card->link_type), + dbf_text); + } else { + if (card->options.portname[0]) + printk("qeth: Device %s/%s/%s is a%s " + "card%s%s%s\nwith link type %s " + "(no portname needed by interface).\n", + card->rdev->dev.bus_id, + card->wdev->dev.bus_id, + card->ddev->dev.bus_id, + qeth_get_cardname(card->type, + card->is_guest_lan), + (card->level[0]) ? " (level: " : "", + (card->level[0]) ? card->level : "", + (card->level[0]) ? ")" : "", + qeth_get_link_type_name(card->type, + card->link_type)); + else + printk("qeth: Device %s/%s/%s is a%s " + "card%s%s%s\nwith link type %s.\n", + card->rdev->dev.bus_id, + card->wdev->dev.bus_id, + card->ddev->dev.bus_id, + qeth_get_cardname(card->type, + card->is_guest_lan), + (card->level[0]) ? " (level: " : "", + (card->level[0]) ? card->level : "", + (card->level[0]) ? ")" : "", + qeth_get_link_type_name(card->type, + card->link_type)); + } + } + +exit: + spin_unlock(&card->hardsetup_lock); + return result; +} + +static int +qeth_reinit_thread(void *param) +{ + struct qeth_card *card = (struct qeth_card *) param; + int already_registered; + int already_hardsetup; + int retry = QETH_RECOVERY_HARDSETUP_RETRY; + int result; + char name[15]; + + QETH_DBF_TEXT1(0, trace, "RINI"); + QETH_DBF_TEXT1(0, trace, card->rdev->dev.bus_id); + + /* set a nice name ... */ + sprintf(name, "qethrinid%s", card->rdev->dev.bus_id); + daemonize(name); + + if (atomic_read(&card->shutdown_phase)) + goto out_wakeup; + down_interruptible(&card->reinit_thread_sem); + if (atomic_read(&card->shutdown_phase)) + goto out_wakeup; + + QETH_DBF_TEXT1(0, trace, "ri-gotin"); + PRINT_STUPID("entering recovery (reinit) thread for device %s\n", + card->dev_name); + + atomic_set(&card->is_startlaned, 0); + atomic_set(&card->is_softsetup, 0); + + read_lock(&list_lock); + if (!qeth_verify_card(card)) + goto out; + QETH_DBF_TEXT1(0, trace, "ri-vrfd"); + + atomic_set(&card->write_busy, 0); + qeth_set_dev_flag_norunning(card); + already_hardsetup = atomic_read(&card->is_hardsetup); + already_registered = atomic_read(&card->is_registered); + if (already_hardsetup) { + atomic_set(&card->is_hardsetup, 0); + + if (-1 == my_spin_lock_nonbusy(card, &setup_lock)) + goto out; + if (atomic_read(&card->shutdown_phase)) + goto out_wakeup; + + atomic_set(&card->escape_softsetup, 1); + + if (-1 == my_spin_lock_nonbusy(card, &card->softsetup_lock)) { + atomic_set(&card->escape_softsetup, 0); + goto out; + } + atomic_set(&card->escape_softsetup, 0); + if (atomic_read(&card->shutdown_phase)) { + spin_unlock(&card->softsetup_lock); + goto out_wakeup; + } + if (!qeth_verify_card(card)) + goto out; + + if (already_registered) + netif_stop_queue(card->dev); + + qeth_wait_nonbusy(QETH_QUIESCE_NETDEV_TIME); + + atomic_set(&card->is_startlaned, 0); + + QETH_DBF_TEXT1(0, trace, "ri-frskb"); + qeth_free_all_skbs(card); + do { + QETH_DBF_TEXT1(0, trace, "ri-hrdst"); + result = qeth_hardsetup_card(card, 1); + } while (result && (retry--)); + + /* tries to remove old ips, that's paranoid, but ok */ + qeth_clear_ifa4_list(&card->ip_new_state.ip_ifa); + qeth_clear_ifamc_list(&card->ip_mc_new_state.ipm_ifa); + +#ifdef QETH_IPV6 + qeth_clear_ifa6_list(&card->ip_new_state.ip6_ifa); + qeth_clear_ifamc_list(&card->ip_mc_new_state.ipm6_ifa); +#endif /* QETH_IPV6 */ + + if (result) { + QETH_DBF_TEXT1(0, trace, "ri-nosuc"); + PRINT_ERR("qeth: RECOVERY WAS NOT SUCCESSFUL ON %s " + "(%s/%s/%s), GIVING UP, " + "OUTGOING PACKETS WILL BE DISCARDED!\n", + card->dev_name, + card->rdev->dev.bus_id, + card->wdev->dev.bus_id, + card->ddev->dev.bus_id); + /* early leave hard_start_xmit! */ + atomic_set(&card->is_startlaned, 0); + qeth_wakeup_procfile(); + } else { + QETH_DBF_TEXT1(0, trace, "ri-sftst"); + qeth_softsetup_card(card, QETH_LOCK_ALREADY_HELD); + spin_unlock(&card->softsetup_lock); + + if (!already_registered) { + QETH_DBF_TEXT1(0, trace, "ri-regcd"); + qeth_register_netdev(card); + } + qeth_restore_dev_flag_state(card); + netif_wake_queue(card->dev); + qeth_wakeup_procfile(); + } + spin_unlock(&setup_lock); + } +out: + atomic_set(&card->in_recovery, 0); + read_unlock(&list_lock); + QETH_DBF_TEXT1(0, trace, "ri-leave"); +out_wakeup: + up(&card->reinit_thread_sem); + atomic_dec(&card->reinit_counter); + + return 0; +} + +static void +qeth_fill_qeth_card_options(struct qeth_card *card) +{ + int i; + + card->options.portname[0] = 0; + for (i = 1; i < 9; i++) + card->options.portname[i] = _ascebc[' ']; + strcpy(card->options.devname, " "); + card->options.routing_type4 = NO_ROUTER; +#ifdef QETH_IPV6 + card->options.routing_type6 = NO_ROUTER; +#endif /* QETH_IPV6 */ + card->options.portno = 0; + card->options.checksum_type = QETH_CHECKSUM_DEFAULT; + card->options.do_prio_queueing = QETH_PRIOQ_DEFAULT; + card->options.default_queue = QETH_DEFAULT_QUEUE; + card->options.inbound_buffer_count = DEFAULT_BUFFER_COUNT; + card->options.polltime = QETH_MAX_INPUT_THRESHOLD; + card->options.memusage = MEMUSAGE_DISCONTIG; + card->options.macaddr_mode = MACADDR_NONCANONICAL; + card->options.broadcast_mode = BROADCAST_ALLRINGS; + card->options.fake_broadcast = DONT_FAKE_BROADCAST; + card->options.ena_ipat = ENABLE_TAKEOVER; + card->options.add_hhlen = DEFAULT_ADD_HHLEN; + card->options.fake_ll = DONT_FAKE_LL; + card->options.async_iqd = SYNC_IQD; +} + +static struct qeth_card * +qeth_alloc_card(void) +{ + struct qeth_card *card; + + QETH_DBF_TEXT3(0, trace, "alloccrd"); + card = (struct qeth_card *) vmalloc(sizeof (struct qeth_card)); + if (!card) + goto exit_card; + memset(card, 0, sizeof (struct qeth_card)); + init_waitqueue_head(&card->wait_q); + init_waitqueue_head(&card->ioctl_wait_q); + + qeth_fill_qeth_card_options(card); + + card->dma_stuff = + (struct qeth_dma_stuff *) kmalloc(sizeof (struct qeth_dma_stuff), + GFP_KERNEL | GFP_DMA); + if (!card->dma_stuff) + goto exit_dma; + memset(card->dma_stuff, 0, sizeof (struct qeth_dma_stuff)); + + card->dma_stuff->recbuf = (char *) kmalloc(QETH_BUFSIZE, + GFP_KERNEL | GFP_DMA); + if (!card->dma_stuff->recbuf) + goto exit_dma1; + memset(card->dma_stuff->recbuf, 0, QETH_BUFSIZE); + + card->dma_stuff->sendbuf = (char *) kmalloc(QETH_BUFSIZE, + GFP_KERNEL | GFP_DMA); + if (!card->dma_stuff->sendbuf) + goto exit_dma2; + memset(card->dma_stuff->sendbuf, 0, QETH_BUFSIZE); + + card->dev = (struct net_device *) kmalloc(sizeof (struct net_device), + GFP_KERNEL); + if (!card->dev) + goto exit_dev; + memset(card->dev, 0, sizeof (struct net_device)); + + card->stats = + (struct net_device_stats *) + kmalloc(sizeof (struct net_device_stats), GFP_KERNEL); + if (!card->stats) + goto exit_stats; + memset(card->stats, 0, sizeof (struct net_device_stats)); + + spin_lock_init(&card->wait_q_lock); + spin_lock_init(&card->softsetup_lock); + spin_lock_init(&card->hardsetup_lock); + spin_lock_init(&card->ioctl_lock); +#ifdef QETH_VLAN + spin_lock_init(&card->vlan_lock); + card->vlangrp = NULL; +#endif + card->unique_id = 0; + sema_init(&card->reinit_thread_sem, 0); + up(&card->reinit_thread_sem); + + /* setup card stuff */ + card->ip_current_state.ip_ifa = NULL; + card->ip_new_state.ip_ifa = NULL; + card->ip_mc_current_state.ipm_ifa = NULL; + card->ip_mc_new_state.ipm_ifa = NULL; + +#ifdef QETH_IPV6 + card->ip_current_state.ip6_ifa = NULL; + card->ip_new_state.ip6_ifa = NULL; + card->ip_mc_current_state.ipm6_ifa = NULL; + card->ip_mc_new_state.ipm6_ifa = NULL; +#endif /* QETH_IPV6 */ + + /* setup net_device stuff */ + card->dev->priv = card; + + strncpy(card->dev->name, card->dev_name, IFNAMSIZ); + + /* setup net_device_stats stuff */ + /* =nothing yet */ + + /* and return to the sender */ + return card; + + /* these are quick exits in case of failures of the kmallocs */ +exit_stats: + kfree(card->dev); +exit_dev: + kfree(card->dma_stuff->sendbuf); +exit_dma2: + kfree(card->dma_stuff->recbuf); +exit_dma1: + kfree(card->dma_stuff); +exit_dma: + kfree(card); +exit_card: + return NULL; +} + +static int +qeth_init_ringbuffers1(struct qeth_card *card) +{ + int i, j; + + QETH_DBF_TEXT3(0, trace, "irb1"); + QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id); + + for (i = 0; i < card->no_queues; i++) { + card->outbound_ringbuffer[i] = + vmalloc(sizeof (struct qeth_ringbuffer)); + if (!card->outbound_ringbuffer[i]) { + for (j = i - 1; j >= 0; j--) { + vfree(card->outbound_ringbuffer[j]); + card->outbound_ringbuffer[j] = NULL; + } + return -ENOMEM; + } + memset(card->outbound_ringbuffer[i], 0, + sizeof (struct qeth_ringbuffer)); + for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++) + skb_queue_head_init(&card->outbound_ringbuffer[i]-> + ringbuf_element[j].skb_list); + } + + return 0; +} + +static int +qeth_init_ringbuffers2(struct qeth_card *card) +{ + int i, j; + int failed = 0; + int discont_mem, element_count; + long alloc_size; + + QETH_DBF_TEXT3(0, trace, "irb2"); + QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id); + + discont_mem = (card->options.memusage == MEMUSAGE_DISCONTIG); + element_count = (discont_mem) ? BUFFER_MAX_ELEMENTS : 1; + alloc_size = (discont_mem) ? PAGE_SIZE : BUFFER_SIZE; + if (discont_mem) { + for (i = 0; i < card->options.inbound_buffer_count; i++) { + for (j = 0; j < element_count; j++) { + card->inbound_buffer_pool_entry[i][j] = + kmalloc(alloc_size, GFP_KERNEL); + if (!card->inbound_buffer_pool_entry[i][j]) { + failed = 1; + goto out; + } + } + card->inbound_buffer_pool_entry_used[i] = BUFFER_UNUSED; + } + } else { + for (i = 0; i < card->options.inbound_buffer_count; i++) { + card->inbound_buffer_pool_entry[i][0] = + kmalloc(alloc_size, GFP_KERNEL); + if (!card->inbound_buffer_pool_entry[i][0]) + failed = 1; + for (j = 1; j < element_count; j++) + card->inbound_buffer_pool_entry[i][j] = + card->inbound_buffer_pool_entry[i][0] + + PAGE_SIZE * j; + card->inbound_buffer_pool_entry_used[i] = BUFFER_UNUSED; + } + } + +out: + if (failed) { + for (i = 0; i < card->options.inbound_buffer_count; i++) { + for (j = 0; j < QDIO_MAX_ELEMENTS_PER_BUFFER; j++) { + if (card->inbound_buffer_pool_entry[i][j]) { + if (j < element_count) + kfree(card-> + inbound_buffer_pool_entry + [i][j]); + card->inbound_buffer_pool_entry + [i][j] = NULL; + } + } + } + for (i = 0; i < card->no_queues; i++) { + vfree(card->outbound_ringbuffer[i]); + card->outbound_ringbuffer[i] = NULL; + } + return -ENOMEM; + } + + spin_lock_init(&card->requeue_input_lock); + + return 0; +} + +/* also locked from outside (setup_lock) */ +static void +qeth_insert_card_into_list(struct qeth_card *card) +{ + QETH_DBF_TEXT3(0, trace, "icil"); + QETH_DBF_TEXT3(0, trace, card->rdev->dev.bus_id); + + write_lock(&list_lock); + card->next = firstcard; + firstcard = card; + write_unlock(&list_lock); +} + +static int +qeth_determine_card_type(struct qeth_card *card) +{ + int i = 0; + char dbf_text[15]; + + while (known_devices[i][4]) { + if ((card->rdev->id.dev_type == known_devices[i][2]) && + (card->rdev->id.dev_model == known_devices[i][3])) { + card->type = known_devices[i][4]; + if (card->options.ena_ipat == ENABLE_TAKEOVER) + card->func_level = known_devices[i][6]; + else + card->func_level = known_devices[i][7]; + card->no_queues = known_devices[i][8]; + card->is_multicast_different = known_devices[i][9]; + QETH_DBF_TEXT2(0, setup, card->rdev->dev.bus_id); + sprintf(dbf_text, "ctyp%4x", card->type); + QETH_DBF_TEXT2(0, setup, dbf_text); + return 0; + } + i++; + } + card->type = QETH_CARD_TYPE_UNKNOWN; + QETH_DBF_TEXT2(0, setup, card->rdev->dev.bus_id); + sprintf(dbf_text, "ctypUNKN"); + QETH_DBF_TEXT2(0, setup, dbf_text); + PRINT_ERR("unknown card type on device %s\n", card->rdev->dev.bus_id); + return -ENOENT; +} + +static int +qeth_getint(char *s, int longint) +{ + int cnt; + int hex; + int result; + char c; + + if (!s) + return -1; + hex = ((s[0] == '0') && ((s[1] == 'x') || (s[1] == 'X'))) ? 1 : 0; + cnt = (hex) ? 2 : 0; /* start from the first real digit */ + if (!(s[cnt])) + return -1; + result = 0; + while ((c = s[cnt++])) { + if (hex) { + if (isxdigit(c)) + result = result * 16 + qeth_getxdigit(c); + else + return -1; + } else { + if (isdigit(c)) + result = result * 10 + c - '0'; + else + return -1; + } + /* prevent overflow, 0xffff is enough for us */ + if (longint) { + if (result > 0xfffffff) + return -1; + } else { + if (result > 0xffff) + return -1; + } + } + return result; +} + +static void +__qeth_correct_routing_status_v4(struct qeth_card *card) +{ + if (card->options.routing_type4 == NO_ROUTER) + return; + + if (card->type == QETH_CARD_TYPE_IQD) { + /* if it's not a mc router, it's no router */ + if ((card->options.routing_type4 == PRIMARY_ROUTER) || + (card->options.routing_type4 == SECONDARY_ROUTER)) { + PRINT_WARN("routing not applicable, reset " + "routing status for ipv4. \n"); + card->options.routing_type4 = NO_ROUTER; + } + card->options.do_prio_queueing = NO_PRIO_QUEUEING; + } else { + /* if it's a mc router, it's no router */ + if ((card->options.routing_type4 == MULTICAST_ROUTER) || + (card->options.routing_type4 == PRIMARY_CONNECTOR) || + (card->options.routing_type4 == SECONDARY_CONNECTOR)) { + PRINT_WARN("routing not applicable, reset " + "routing status for ipv4. (Did you mean " + "primary_router or secondary_router?)\n"); + card->options.routing_type4 = NO_ROUTER; + } + } +} + +static void +__qeth_correct_routing_status_v6(struct qeth_card *card) +{ +#ifdef QETH_IPV6 + if (card->options.routing_type6 == NO_ROUTER) + return; + if (card->type == QETH_CARD_TYPE_IQD) { + /* if it's not a mc router, it's no router */ + if ((card->options.routing_type6 == PRIMARY_ROUTER) || + (card->options.routing_type6 == SECONDARY_ROUTER)) { + PRINT_WARN("routing not applicable, reset " + "routing status for ipv6. \n"); + card->options.routing_type6 = NO_ROUTER; + } + card->options.do_prio_queueing = NO_PRIO_QUEUEING; + } else { + /* if it's a mc router, it's no router */ + if ((card->options.routing_type6 == MULTICAST_ROUTER) || + (card->options.routing_type6 == PRIMARY_CONNECTOR) || + (card->options.routing_type6 == SECONDARY_CONNECTOR)) { + PRINT_WARN("routing not applicable, reset " + "routing status for ipv6. (Did you mean " + "primary_router or secondary_router?)\n"); + card->options.routing_type6 = NO_ROUTER; + } + } +#endif /* QETH_IPV6 */ +} + +static void +qeth_correct_routing_status(struct qeth_card *card) +{ + __qeth_correct_routing_status_v4(card); + __qeth_correct_routing_status_v6(card); +} + +static struct net_device * +qeth_init_netdev(struct net_device *dev) +{ + + struct qeth_card *card = NULL; + int result; + char dbf_text[15]; + + if (!dev) { + PRINT_ERR("qeth_init_netdev called with no device!\n"); + goto out; + } + + card = (struct qeth_card *) dev->priv; + strcpy(card->dev_name, dev->name); + result = qeth_register_netdev(card); + if (result) { + PRINT_ALL(" register_netdev %s -- rc=%i\n", + ((struct qeth_card *) firstcard->dev->priv)-> + dev_name, result); + sprintf(dbf_text, "rgnd%4x", (__u16) result); + QETH_DBF_TEXT2(1, trace, dbf_text); + atomic_set(&card->is_registered, 0); + goto out; + } + strcpy(card->dev_name, dev->name); + atomic_set(&card->write_busy, 0); + atomic_set(&card->is_registered, 1); + + result = qeth_softsetup_card(card, QETH_WAIT_FOR_LOCK); + + if (!result) { + qeth_init_input_buffers(card); + } else { + QETH_DBF_TEXT2(0, trace, "SSFAILED"); + PRINT_WARN("soft-setup of card failed!\n"); + } + + INIT_WORK(&card->tqueue, qeth_softsetup_thread_starter, card); + schedule_work(&card->tqueue); +out: + qeth_wakeup_procfile(); + return dev; + +} + +static int +qeth_dev_event(struct notifier_block *this, unsigned long event, void *ptr) +{ + struct qeth_card *card; + struct net_device *dev = (struct net_device *) ptr; + char dbf_text[15]; + + sprintf(dbf_text, "devevent"); + QETH_DBF_TEXT3(0, trace, dbf_text); + QETH_DBF_HEX3(0, trace, &event, sizeof (unsigned long)); + QETH_DBF_HEX3(0, trace, &dev, sizeof (void *)); + + card = __qeth_get_card_from_dev(dev); + if (qeth_does_card_exist(card)) { + qeth_save_dev_flag_state(card); + switch (event) { + default: + qeth_start_softsetup_thread(card); + break; + } + } + + return NOTIFY_DONE; +} + +static int +qeth_ip_event(struct notifier_block *this, unsigned long event, void *ptr) +{ + struct qeth_card *card; + struct in_ifaddr *ifa = (struct in_ifaddr *) ptr; + struct net_device *dev = ifa->ifa_dev->dev; + char dbf_text[15]; + + sprintf(dbf_text, "ipevent"); + QETH_DBF_TEXT3(0, trace, dbf_text); + QETH_DBF_HEX3(0, trace, &event, sizeof (unsigned long)); + QETH_DBF_HEX3(0, trace, &dev, sizeof (void *)); + sprintf(dbf_text, "%08x", ifa->ifa_address); + QETH_DBF_TEXT3(0, trace, dbf_text); + sprintf(dbf_text, "%08x", ifa->ifa_mask); + QETH_DBF_TEXT3(0, trace, dbf_text); + + card = __qeth_get_card_from_dev(dev); + if (qeth_does_card_exist(card)) { + QETH_DBF_HEX3(0, trace, &card, sizeof (void *)); + qeth_save_dev_flag_state(card); + qeth_start_softsetup_thread(card); + } + + return NOTIFY_DONE; +} + +#ifdef QETH_IPV6 +static int +qeth_ip6_event(struct notifier_block *this, unsigned long event, void *ptr) +{ + struct qeth_card *card; + struct inet6_ifaddr *ifa = (struct inet6_ifaddr *) ptr; + struct net_device *dev = ifa->idev->dev; + char dbf_text[15]; + + sprintf(dbf_text, "ip6event"); + QETH_DBF_TEXT3(0, trace, dbf_text); + QETH_DBF_HEX3(0, trace, &event, sizeof (unsigned long)); + QETH_DBF_HEX3(0, trace, &dev, sizeof (void *)); + QETH_DBF_HEX3(0, trace, ifa->addr.s6_addr, QETH_DBF_TRACE_LEN); + QETH_DBF_HEX3(0, trace, ifa->addr.s6_addr + QETH_DBF_TRACE_LEN, + QETH_DBF_TRACE_LEN); + + card = __qeth_get_card_from_dev(dev); + if (qeth_does_card_exist(card)) { + QETH_DBF_HEX3(0, trace, &card, sizeof (void *)); + qeth_save_dev_flag_state(card); + qeth_start_softsetup_thread(card); + } + + return NOTIFY_DONE; +} +#endif /* QETH_IPV6 */ + +static int +qeth_reboot_event(struct notifier_block *this, unsigned long event, void *ptr) +{ + struct qeth_card *card; + + read_lock(&list_lock); + if (firstcard) { + card = firstcard; + clear_another_one: + if (card->type == QETH_CARD_TYPE_IQD) { + ccw_device_halt(card->ddev, 0); + ccw_device_clear(card->rdev, 0); + ccw_device_clear(card->wdev, 0); + ccw_device_clear(card->ddev, 0); + } else { + ccw_device_clear(card->ddev, 0); + ccw_device_clear(card->rdev, 0); + ccw_device_clear(card->wdev, 0); + } + if (card->next) { + card = card->next; + goto clear_another_one; + } + } + read_unlock(&list_lock); + + return 0; +} + +static struct notifier_block qeth_dev_notifier = { + qeth_dev_event, + 0 +}; + +static struct notifier_block qeth_ip_notifier = { + qeth_ip_event, + 0 +}; + +#ifdef QETH_IPV6 +static struct notifier_block qeth_ip6_notifier = { + qeth_ip6_event, + 0 +}; +#endif /* QETH_IPV6 */ + +static struct notifier_block qeth_reboot_notifier = { + qeth_reboot_event, + 0 +}; + +static void +qeth_register_notifiers(void) +{ + int r; + + QETH_DBF_TEXT5(0, trace, "regnotif"); + /* register to be notified on events */ + r = register_netdevice_notifier(&qeth_dev_notifier); + + r = register_inetaddr_notifier(&qeth_ip_notifier); +#ifdef QETH_IPV6 + r = register_inet6addr_notifier(&qeth_ip6_notifier); +#endif /* QETH_IPV6 */ + r = register_reboot_notifier(&qeth_reboot_notifier); +} + +static void __exit +qeth_unregister_notifiers(void) +{ + int r; + + QETH_DBF_TEXT5(0, trace, "unregnot"); + r = unregister_netdevice_notifier(&qeth_dev_notifier); + r = unregister_inetaddr_notifier(&qeth_ip_notifier); +#ifdef QETH_IPV6 + r = unregister_inet6addr_notifier(&qeth_ip6_notifier); +#endif /* QETH_IPV6 */ + r = unregister_reboot_notifier(&qeth_reboot_notifier); + +} + +static int +qeth_procfile_open(struct inode *inode, struct file *file) +{ + int length = 0; + struct qeth_card *card; + char checksum_str[5], queueing_str[14], router_str[8], bufsize_str[4]; + char *buffer; + int rc = 0; + int size; + struct tempinfo *info; + + info = (struct tempinfo *) vmalloc(sizeof (struct tempinfo)); + if (info == NULL) { + PRINT_WARN("No memory available for data\n"); + return -ENOMEM; + } else { + file->private_data = (void *) info; + } + + /* lock all the stuff */ + read_lock(&list_lock); + card = firstcard; + size = 200; /* 2 lines plus some sanity space */ + while (card) { + size += 90; /* if device name is > 10 chars, (should never + happen...), we'll need that */ + card = card->next; + } + + buffer = info->data = (char *) vmalloc(size); + if (info->data == NULL) { + PRINT_WARN("No memory available for data\n"); + vfree(info); + rc = -ENOMEM; + goto out; + } + + QETH_DBF_TEXT2(0, trace, "procread"); + length += sprintf(buffer + length, + "devices CHPID " + "device cardtype port chksum prio-q'ing " + "rtr fsz C cnt\n"); + length += sprintf(buffer + length, + "-------------------- --- ----" + "------ -------------- -- -- ---------- " + "--- --- - ---\n"); + card = firstcard; + while (card) { + strcpy(checksum_str, + (card->options.checksum_type == SW_CHECKSUMMING) ? "SW" : + (card->options.checksum_type == HW_CHECKSUMMING) ? "HW" : + "no"); + if (card->options.do_prio_queueing == NO_PRIO_QUEUEING) { + sprintf(queueing_str, "always_q_%i", + card->options.default_queue); + } else { + strcpy(queueing_str, (card->options.do_prio_queueing + == + PRIO_QUEUEING_PREC) ? "by_prec." : + "by_ToS"); + } + + /* FIXME: this is really a mess... */ + +#ifdef QETH_IPV6 + if (atomic_read(&card->rt4fld) && atomic_read(&card->rt6fld)) + strcpy(router_str, "no"); + else if (atomic_read(&card->rt4fld) + || atomic_read(&card->rt6fld)) + strcpy(router_str, "mix"); +#else/* QETH_IPV6 */ + if (atomic_read(&card->rt4fld)) + strcpy(router_str, "no"); +#endif /* QETH_IPV6 */ + else if (((card->options.routing_type4 & ROUTER_MASK) == + PRIMARY_ROUTER) +#ifdef QETH_IPV6 + && + ((card->options.routing_type6 & ROUTER_MASK) == + PRIMARY_ROUTER) +#endif /* QETH_IPV6 */ + ) { + strcpy(router_str, "pri"); + } else + if (((card->options.routing_type4 & ROUTER_MASK) == + SECONDARY_ROUTER) +#ifdef QETH_IPV6 + && + ((card->options.routing_type6 & ROUTER_MASK) == + SECONDARY_ROUTER) +#endif /* QETH_IPV6 */ + ) { + strcpy(router_str, "sec"); + } else + if (((card->options.routing_type4 & ROUTER_MASK) == + MULTICAST_ROUTER) +#ifdef QETH_IPV6 + && + ((card->options.routing_type6 & ROUTER_MASK) == + MULTICAST_ROUTER) +#endif /* QETH_IPV6 */ + ) { + strcpy(router_str, "mc"); + } else + if (((card->options.routing_type4 & ROUTER_MASK) == + PRIMARY_CONNECTOR) +#ifdef QETH_IPV6 + && + ((card->options.routing_type6 & ROUTER_MASK) == + PRIMARY_CONNECTOR) +#endif /* QETH_IPV6 */ + ) { + strcpy(router_str, "p.c"); + } else + if (((card->options.routing_type4 & ROUTER_MASK) == + SECONDARY_CONNECTOR) +#ifdef QETH_IPV6 + && + ((card->options.routing_type6 & ROUTER_MASK) == + SECONDARY_CONNECTOR) +#endif /* QETH_IPV6 */ + ) { + strcpy(router_str, "s.c"); + } else + if (((card->options.routing_type4 & ROUTER_MASK) == + NO_ROUTER) +#ifdef QETH_IPV6 + && + ((card->options.routing_type6 & ROUTER_MASK) == + NO_ROUTER) +#endif /* QETH_IPV6 */ + ) { + strcpy(router_str, "no"); + } else { + strcpy(router_str, "mix"); + } + strcpy(bufsize_str, + (BUFFER_SIZE == 16384) ? "16k" : + (BUFFER_SIZE == 24576) ? "24k" : + (BUFFER_SIZE == 32768) ? "32k" : + (BUFFER_SIZE == 40960) ? "40k" : "64k"); + + if (!atomic_read(&card->is_startlaned)) { + length += sprintf(buffer + length, + "%s/%s/%s x%02X %10s %14s %2i" + " +++ CABLE PULLED +++\n", + card->rdev->dev.bus_id, + card->wdev->dev.bus_id, + card->ddev->dev.bus_id, + card->chpid, + card->dev_name, + qeth_get_cardname_short + (card->type, card->link_type, + card->is_guest_lan), + card->options.portno); + } else { + length += sprintf(buffer + length, + "%s/%s/%s x%02X %10s %14s %2i" + " %2s %10s %3s %3s %c %3i\n", + card->rdev->dev.bus_id, + card->wdev->dev.bus_id, + card->ddev->dev.bus_id, + card->chpid, card->dev_name, + qeth_get_cardname_short + (card->type, card->link_type, + card->is_guest_lan), + card->options.portno, checksum_str, + queueing_str, router_str, bufsize_str, + (card->options.memusage == + MEMUSAGE_CONTIG) ? 'c' : ' ', + card->options.inbound_buffer_count); + } + card = card->next; + } + +out: + info->len = length; + /* unlock all the stuff */ + read_unlock(&list_lock); + return rc; +} + +#define _OUTP_IT(x...) c+=sprintf(buffer+c,x) + +#ifdef QETH_PERFORMANCE_STATS +static int +qeth_perf_procfile_read(char *buffer, char **buffer_location, + off_t offset, int buffer_length, int *eof, void *data) +{ + int c = 0; + struct qeth_card *card; + /* we are always called with buffer_length=4k, so we all + deliver on the first read */ + if (offset > 0) + return 0; + + QETH_DBF_TEXT2(0, trace, "perfpfrd"); + + card = firstcard; + + while (card) { + _OUTP_IT("For card with devnos %s/%s/%s (%s):\n", + card->rdev->dev.bus_id, + card->wdev->dev.bus_id, + card->ddev->dev.bus_id, card->dev_name); + _OUTP_IT(" Skb's/buffers received : %i/%i\n", + card->perf_stats.skbs_rec, card->perf_stats.bufs_rec); + _OUTP_IT(" Skb's/buffers sent : %i/%i\n", + card->perf_stats.skbs_sent, + card->perf_stats.bufs_sent); + _OUTP_IT("\n"); + _OUTP_IT(" Skb's/buffers sent without packing : %i/%i\n", + card->perf_stats.skbs_sent_dont_pack, + card->perf_stats.bufs_sent_dont_pack); + _OUTP_IT(" Skb's/buffers sent with packing : %i/%i\n", + card->perf_stats.skbs_sent_pack, + card->perf_stats.bufs_sent_pack); + _OUTP_IT("\n"); + _OUTP_IT(" Packing state changes no pkg.->packing : %i/%i\n", + card->perf_stats.sc_dp_p, card->perf_stats.sc_p_dp); + _OUTP_IT(" Current buffer usage (outbound q's) : " + "%i/%i/%i/%i\n", + atomic_read(&card->outbound_used_buffers[0]), + atomic_read(&card->outbound_used_buffers[1]), + atomic_read(&card->outbound_used_buffers[2]), + atomic_read(&card->outbound_used_buffers[3])); + _OUTP_IT("\n"); + _OUTP_IT(" Inbound time (in us) : %i\n", + card->perf_stats.inbound_time); + _OUTP_IT(" Inbound cnt : %i\n", + card->perf_stats.inbound_cnt); + _OUTP_IT(" Outbound time (in us, incl QDIO) : %i\n", + card->perf_stats.outbound_time); + _OUTP_IT(" Outbound cnt : %i\n", + card->perf_stats.outbound_cnt); + _OUTP_IT(" Watermarks: L/H=%i/%i\n", + LOW_WATERMARK_PACK, HIGH_WATERMARK_PACK); + _OUTP_IT("\n"); + + card = card->next; + } + + return c; +} + +static struct proc_dir_entry *qeth_perf_proc_file; + +#endif /* QETH_PERFORMANCE_STATS */ + +static int +qeth_ipato_procfile_open(struct inode *inode, struct file *file) +{ + char text[33]; + struct ipato_entry *ipato_entry; + struct qeth_card *card; + struct qeth_vipa_entry *vipa_entry; + int rc = 0; + struct tempinfo *info; + int size; + char entry_type[5]; + + info = (struct tempinfo *) vmalloc(sizeof (struct tempinfo)); + if (info == NULL) { + PRINT_WARN("No memory available for data\n"); + return -ENOMEM; + } else { + file->private_data = (void *) info; + } + info->len = 0; + + QETH_DBF_TEXT2(0, trace, "ipatorea"); + /* lock all the stuff */ + spin_lock(&ipato_list_lock); + read_lock(&list_lock); + + size = 64; /* for inv4/6 etc. */ + + ipato_entry = ipato_entries; + while (ipato_entry) { + ipato_entry = ipato_entry->next; + size += 64; + } + card = firstcard; + while (card) { + read_lock(&card->vipa_list_lock); + vipa_entry = card->vipa_list; + while (vipa_entry) { + vipa_entry = vipa_entry->next; + size += 64; + } + /*read_unlock(&card->vipa_list_lock); don't unlock it here */ + card = card->next; + } + info->data = (char *) vmalloc(size); + if (info->data == NULL) { + PRINT_WARN("No memory available for data\n"); + vfree(info); + rc = -ENOMEM; + goto out; + } +#define _IOUTP_IT(x...) info->len+=sprintf(info->data+info->len,x) + if (ipato_inv4) + _IOUTP_IT("inv4\n"); + ipato_entry = ipato_entries; + text[8] = 0; + while (ipato_entry) { + if (ipato_entry->version == 4) { + qeth_convert_addr_to_text(4, ipato_entry->addr, text); + _IOUTP_IT("add4 %s/%i%s%s\n", text, + ipato_entry->mask_bits, + ipato_entry->dev_name[0] ? ":" : "", + ipato_entry->dev_name[0] ? + ipato_entry->dev_name : ""); + } + ipato_entry = ipato_entry->next; + } + + if (ipato_inv6) + _IOUTP_IT("inv6\n"); + ipato_entry = ipato_entries; + text[32] = 0; + while (ipato_entry) { + if (ipato_entry->version == 6) { + qeth_convert_addr_to_text(6, ipato_entry->addr, text); + _IOUTP_IT("add6 %s/%i%s%s\n", text, + ipato_entry->mask_bits, + ipato_entry->dev_name[0] ? ":" : "", + ipato_entry->dev_name[0] ? + ipato_entry->dev_name : ""); + } + ipato_entry = ipato_entry->next; + } + card = firstcard; + while (card) { + vipa_entry = card->vipa_list; + while (vipa_entry) { + strcpy(entry_type, (vipa_entry->flag == + IPA_SETIP_VIPA_FLAGS) ? + "vipa" : "rxip"); + if (vipa_entry->version == 4) { + _IOUTP_IT("add_%s4 %02x%02x%02x%02x:%s\n", + entry_type, + vipa_entry->ip[0], + vipa_entry->ip[1], + vipa_entry->ip[2], + vipa_entry->ip[3], card->dev_name); + } else { + _IOUTP_IT("add_%s6 %02x%02x%02x%02x" + "%02x%02x%02x%02x" + "%02x%02x%02x%02x" + "%02x%02x%02x%02x:%s\n", + entry_type, + vipa_entry->ip[0], + vipa_entry->ip[1], + vipa_entry->ip[2], + vipa_entry->ip[3], + vipa_entry->ip[4], + vipa_entry->ip[5], + vipa_entry->ip[6], + vipa_entry->ip[7], + vipa_entry->ip[8], + vipa_entry->ip[9], + vipa_entry->ip[10], + vipa_entry->ip[11], + vipa_entry->ip[12], + vipa_entry->ip[13], + vipa_entry->ip[14], + vipa_entry->ip[15], card->dev_name); + } + vipa_entry = vipa_entry->next; + } + card = card->next; + } +out: + /* unlock all the stuff */ + card = firstcard; + while (card) { + /*read_lock(&card->vipa_list_lock); don't lock it here */ + read_unlock(&card->vipa_list_lock); + card = card->next; + } + read_unlock(&list_lock); + spin_unlock(&ipato_list_lock); + + return rc; +} + +static ssize_t +qeth_procfile_read(struct file *file, char *user_buf, + size_t user_len, loff_t * offset) +{ + loff_t len; + struct tempinfo *p_info = (struct tempinfo *) file->private_data; + + if (*offset >= p_info->len) { + return 0; + } else { + len = __min(user_len, (p_info->len - *offset)); + if (copy_to_user(user_buf, &(p_info->data[*offset]), len)) + return -EFAULT; + (*offset) += len; + return len; + } +} + +/* ATT: this is also the procfile release function for the ipato + * procfs entry */ +static int +qeth_procfile_release(struct inode *inode, struct file *file) +{ + struct tempinfo *p_info = (struct tempinfo *) file->private_data; + + if (p_info) { + if (p_info->data) + vfree(p_info->data); + vfree(p_info); + } + + return 0; +} + +static ssize_t +qeth_ipato_procfile_write(struct file *file, + const char *user_buffer, + size_t user_len, loff_t * offset) +{ + int add, version; + char text[33]; + __u8 addr[16]; + int len, i, flag; + int mask_bits; + char *buffer; + int dev_name_there; + char *dev_name_ptr; + struct qeth_card *card; +#define BUFFER_LEN (10+32+1+5+1+DEV_NAME_LEN+1) + + if (*offset > 0) + return user_len; + buffer = + vmalloc(__max(__max(user_len + 1, BUFFER_LEN), QETH_DBF_MISC_LEN)); + + if (buffer == NULL) + return -ENOMEM; + /* BUFFER_LEN=command incl. blank+addr+slash+mask_bits+ + * colon+DEV_NAME_LEN+zero */ + memset(buffer, 0, BUFFER_LEN); + + if (copy_from_user(buffer, user_buffer, user_len)) { + vfree(buffer); + return -EFAULT; + } + + QETH_DBF_TEXT2(0, trace, "ipatowri"); + QETH_DBF_TEXT2(0, misc, buffer); + if (!strncmp(buffer, "inv4", 4)) { + ipato_inv4 = 1 - ipato_inv4; + goto out; + } + if (!strncmp(buffer, "inv6", 4)) { + ipato_inv6 = 1 - ipato_inv6; + goto out; + } + if ((!strncmp(buffer, "add4 ", 5)) || + (!strncmp(buffer, "add6 ", 5)) || + (!strncmp(buffer, "del4 ", 5)) || (!strncmp(buffer, "del6 ", 5))) { + text[8] = 0; + text[32] = 0; + add = !strncmp(buffer, "add", 3); + version = (buffer[3] == '4') ? 4 : 6; + len = (version == 4) ? 8 : 32; + strncpy(text, buffer + 5, len); + if (qeth_convert_text_to_addr(version, text, addr)) { + PRINT_ERR("error in parsing ipato information " + "(addr)\n"); + goto out; + } + strncpy(text, buffer + 5 + len + 1, 10); + /* we prepare mask_bits for qeth_getints */ + dev_name_there = 0; + for (i = 5 + len + 1; i < BUFFER_LEN; i++) { + if (*(buffer + i) == '\n') { + *(buffer + i) = 0; + break; + } + if (*(buffer + i) == ':') { + *(buffer + i) = 0; /* so that qeth_getint works */ + dev_name_there = i; + break; + } + if (*(buffer + i) == 0) + break; + } + mask_bits = qeth_getint(buffer + 5 + len + 1, 0); + if ((mask_bits < 0) + || (mask_bits > ((version == 4) ? 32 : 128))) { + PRINT_ERR("error in parsing ipato information " + "(mask bits)\n"); + goto out; + } + if (dev_name_there) { + dev_name_ptr = buffer + dev_name_there + 1; + /* wipe out the linefeed */ + for (i = dev_name_there + 1; + i < dev_name_there + 1 + DEV_NAME_LEN + 1; i++) + if (*(buffer + i) == '\n') + *(buffer + i) = 0; + } else + dev_name_ptr = NULL; + + if (add) + qeth_add_ipato_entry(version, addr, mask_bits, + dev_name_ptr); + else + qeth_del_ipato_entry(version, addr, mask_bits, + dev_name_ptr); + goto out; + } + if ((!strncmp(buffer, "add_vipa4 ", 10)) || + (!strncmp(buffer, "add_rxip4 ", 10)) || + (!strncmp(buffer, "add_vipa6 ", 10)) || + (!strncmp(buffer, "add_rxip6 ", 10)) || + (!strncmp(buffer, "del_vipa4 ", 10)) || + (!strncmp(buffer, "del_rxip4 ", 10)) || + (!strncmp(buffer, "del_vipa6 ", 10)) || + (!strncmp(buffer, "del_rxip6 ", 10))) { + text[8] = 0; + text[32] = 0; + add = !strncmp(buffer, "add", 3); + flag = + (!strncmp(buffer + 4, "vipa", 4)) ? IPA_SETIP_VIPA_FLAGS : + IPA_SETIP_TAKEOVER_FLAGS; + version = (buffer[8] == '4') ? 4 : 6; + len = (version == 4) ? 8 : 32; + strncpy(text, buffer + 10, len); + if (qeth_convert_text_to_addr(version, text, addr)) { + PRINT_ERR("error in parsing vipa/rxip information " + "(addr)\n"); + goto out; + } + if (*(buffer + 10 + len) != ':') { + PRINT_ERR("error in parsing vipa/rxip information " + "(no interface)\n"); + goto out; + } + /* interface name is at buffer+10+len+1 */ + /* wipe out the \n */ + for (i = 10 + len + 1; i < 10 + len + 1 + DEV_NAME_LEN + 1; i++) + if (*(buffer + i) == '\n') + *(buffer + i) = 0; + card = qeth_get_card_by_name(buffer + 10 + len + 1); + if (!card) { + PRINT_ERR("error in parsing vipa/rxip information " + "(unknown interface)\n"); + goto out; + } + if (add) + i = qeth_add_vipa_entry(card, version, addr, flag); + else + i = qeth_del_vipa_entry(card, version, addr, flag); + if (!i) + qeth_start_softsetup_thread(card); + goto out; + } + PRINT_ERR("unknown ipato information command\n"); +out: + vfree(buffer); + *offset = *offset + user_len; +#undef BUFFER_LEN + return user_len; +} + +static int +qeth_procfile_getinterfaces(unsigned long arg) +{ + struct qeth_card *card; + + char parms[16]; + char *buffer; + char *buffer_pointer; + __u32 version, valid_fields, qeth_version, number_of_devices, if_index; + __u32 data_size, data_len; + unsigned long ioctl_flags; + int result = 0; + + /* the struct of version 0 is: + typedef struct dev_list + { + char device_name[IFNAME_MAXLEN]; // OSA-Exp device name (e.g. eth0) + __u32 if_index; // interface index from kernel + __u32 flags; // device charateristics + } __attribute__((packed)) DEV_LIST; + + typedef struct osaexp_dev_ver0 + { + __u32 version; // structure version + __u32 valid_fields; // bitmask of fields that are really filled + __u32 qeth_version; // qeth driver version + __u32 number_of_devices; // number of OSA Express devices + struct dev_list devices[0]; // list of OSA Express devices + } __attribute__((packed)) OSAEXP_DEV_VER0; + */ + + version = 0; + valid_fields = 0; + qeth_version = 0; + number_of_devices = 0; + + copy_from_user((void *) parms, (void *) arg, sizeof (parms)); + memcpy(&data_size, parms, sizeof (__u32)); + + if (!(data_size > 0)) + return -EFAULT; + if (data_size > IOCTL_MAX_TRANSFER_SIZE) + return -EFAULT; + if (!access_ok(VERIFY_WRITE, (void *) arg, data_size)) + return -EFAULT; + + read_lock(&list_lock); + card = firstcard; +#define IOCTL_USER_STRUCT_SIZE (DEV_NAME_LEN*sizeof(char)) + \ + sizeof(__u32) + sizeof(__u32) + while (card) { + if (card->type == QETH_CARD_TYPE_OSAE) + number_of_devices = + number_of_devices + IOCTL_USER_STRUCT_SIZE; + card = card->next; + } +#undef IOCTL_USER_STRUCT_SIZE + if ((number_of_devices + 4 * sizeof (__u32)) >= data_size) { + result = -ENOMEM; + goto out; + } + + number_of_devices = 0; + card = firstcard; + buffer = (char *) vmalloc(data_size); + if (!buffer) { + result = -EFAULT; + goto out; + } + buffer_pointer = ((char *) (buffer)) + (4 * sizeof (__u32)); + while (card) { + if ((card->type == QETH_CARD_TYPE_OSAE) && + (atomic_read(&card->is_hardsetup)) && + (atomic_read(&card->is_registered))) { + + memcpy(buffer_pointer, card->dev_name, DEV_NAME_LEN); + buffer_pointer = buffer_pointer + DEV_NAME_LEN; + if_index = card->dev->ifindex; + memcpy(buffer_pointer, &if_index, sizeof (__u32)); + buffer_pointer = buffer_pointer + sizeof (__u32); + memcpy(buffer_pointer, &ioctl_flags, sizeof (__u32)); + buffer_pointer = buffer_pointer + sizeof (__u32); + number_of_devices = number_of_devices + 1; + } + card = card->next; + } + + /* we copy the real size */ + data_len = buffer_pointer - buffer; + + buffer_pointer = buffer; + /* copy the header information at the beginning of the buffer */ + memcpy(buffer_pointer, &version, sizeof (__u32)); + memcpy(((char *) buffer_pointer) + sizeof (__u32), &valid_fields, + sizeof (__u32)); + memcpy(((char *) buffer_pointer) + (2 * sizeof (__u32)), &qeth_version, + sizeof (__u32)); + memcpy(((char *) buffer_pointer) + (3 * sizeof (__u32)), + &number_of_devices, sizeof (__u32)); + copy_to_user((char *) arg, buffer, data_len); + vfree(buffer); +out: + read_unlock(&list_lock); + return result; + +#undef PARMS_BUFFERLENGTH + +}; + +static int +qeth_procfile_interfacechanges(unsigned long arg) +{ + return qeth_sleepon_procfile(); + +} + +static int +qeth_procfile_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + + int result; + down_interruptible(&qeth_procfile_ioctl_lock); + switch (cmd) { + + case QETH_IOCPROC_OSAEINTERFACES: + result = qeth_procfile_getinterfaces(arg); + break; + case QETH_IOCPROC_INTERFACECHANGES: + result = qeth_procfile_interfacechanges(arg); + break; + default: + result = -EOPNOTSUPP; + } + up(&qeth_procfile_ioctl_lock); + return result; +}; + +static struct file_operations qeth_procfile_fops = { + ioctl:qeth_procfile_ioctl, + read:qeth_procfile_read, + open:qeth_procfile_open, + release:qeth_procfile_release, +}; + +static struct proc_dir_entry *qeth_proc_file; + +static struct file_operations qeth_ipato_procfile_fops = { + read:qeth_procfile_read, /* same as above! */ + write:qeth_ipato_procfile_write, + open:qeth_ipato_procfile_open, + release:qeth_procfile_release /* same as above! */ +}; + +static struct proc_dir_entry *qeth_ipato_proc_file; + +static inline void +__qeth_add_procfs_perf(void) +{ +#ifdef QETH_PERFORMANCE_STATS + proc_perf_file_registration = 0; + qeth_perf_proc_file = create_proc_entry(QETH_PERF_PROCFILE_NAME, + S_IFREG | 0444, &proc_root); + if (qeth_perf_proc_file) { + qeth_perf_proc_file->read_proc = &qeth_perf_procfile_read; + } else + proc_perf_file_registration = -1; + + if (proc_perf_file_registration) + PRINT_WARN("was not able to register perf. proc-file (%i).\n", + proc_perf_file_registration); +#endif /* QETH_PERFORMANCE_STATS */ +} + +static void +qeth_add_procfs_entries(void) +{ + proc_file_registration = 0; + qeth_proc_file = create_proc_entry(QETH_PROCFILE_NAME, + S_IFREG | 0444, &proc_root); + if (qeth_proc_file) { + qeth_proc_file->proc_fops = &qeth_procfile_fops; + sema_init(&qeth_procfile_ioctl_sem, + PROCFILE_SLEEP_SEM_MAX_VALUE); + sema_init(&qeth_procfile_ioctl_lock, + PROCFILE_IOCTL_SEM_MAX_VALUE); + } else + proc_file_registration = -1; + + if (proc_file_registration) + PRINT_WARN("was not able to register proc-file (%i).\n", + proc_file_registration); + proc_ipato_file_registration = 0; + qeth_ipato_proc_file = create_proc_entry(QETH_IPA_PROCFILE_NAME, + S_IFREG | 0644, &proc_root); + if (qeth_ipato_proc_file) { + qeth_ipato_proc_file->proc_fops = &qeth_ipato_procfile_fops; + } else + proc_ipato_file_registration = -1; + + if (proc_ipato_file_registration) + PRINT_WARN("was not able to register ipato-proc-file (%i).\n", + proc_ipato_file_registration); + __qeth_add_procfs_perf(); +} + +static void __exit +qeth_remove_procfs_entries(void) +{ + if (!proc_file_registration) /* means if it went ok earlier */ + remove_proc_entry(QETH_PROCFILE_NAME, &proc_root); + + if (!proc_ipato_file_registration) /* means if it went ok earlier */ + remove_proc_entry(QETH_IPA_PROCFILE_NAME, &proc_root); + +#ifdef QETH_PERFORMANCE_STATS + if (!proc_perf_file_registration) /* means if it went ok earlier */ + remove_proc_entry(QETH_PERF_PROCFILE_NAME, &proc_root); +#endif /* QETH_PERFORMANCE_STATS */ +} + +static int +qeth_register_dbf_views(void) +{ + qeth_dbf_setup = debug_register(QETH_DBF_SETUP_NAME, + QETH_DBF_SETUP_INDEX, + QETH_DBF_SETUP_NR_AREAS, + QETH_DBF_SETUP_LEN); + if (!qeth_dbf_setup) + return -ENOMEM; + + debug_register_view(qeth_dbf_setup, &debug_hex_ascii_view); + debug_set_level(qeth_dbf_setup, QETH_DBF_SETUP_LEVEL); + + qeth_dbf_misc = debug_register(QETH_DBF_MISC_NAME, + QETH_DBF_MISC_INDEX, + QETH_DBF_MISC_NR_AREAS, + QETH_DBF_MISC_LEN); + if (!qeth_dbf_misc) + return -ENOMEM; + + debug_register_view(qeth_dbf_misc, &debug_hex_ascii_view); + debug_set_level(qeth_dbf_misc, QETH_DBF_MISC_LEVEL); + + qeth_dbf_data = debug_register(QETH_DBF_DATA_NAME, + QETH_DBF_DATA_INDEX, + QETH_DBF_DATA_NR_AREAS, + QETH_DBF_DATA_LEN); + if (!qeth_dbf_data) + return -ENOMEM; + + debug_register_view(qeth_dbf_data, &debug_hex_ascii_view); + debug_set_level(qeth_dbf_data, QETH_DBF_DATA_LEVEL); + + qeth_dbf_control = debug_register(QETH_DBF_CONTROL_NAME, + QETH_DBF_CONTROL_INDEX, + QETH_DBF_CONTROL_NR_AREAS, + QETH_DBF_CONTROL_LEN); + if (!qeth_dbf_control) + return -ENOMEM; + + debug_register_view(qeth_dbf_control, &debug_hex_ascii_view); + debug_set_level(qeth_dbf_control, QETH_DBF_CONTROL_LEVEL); + + qeth_dbf_sense = debug_register(QETH_DBF_SENSE_NAME, + QETH_DBF_SENSE_INDEX, + QETH_DBF_SENSE_NR_AREAS, + QETH_DBF_SENSE_LEN); + if (!qeth_dbf_sense) + return -ENOMEM; + + debug_register_view(qeth_dbf_sense, &debug_hex_ascii_view); + debug_set_level(qeth_dbf_sense, QETH_DBF_SENSE_LEVEL); + + qeth_dbf_qerr = debug_register(QETH_DBF_QERR_NAME, + QETH_DBF_QERR_INDEX, + QETH_DBF_QERR_NR_AREAS, + QETH_DBF_QERR_LEN); + if (!qeth_dbf_qerr) + return -ENOMEM; + + debug_register_view(qeth_dbf_qerr, &debug_hex_ascii_view); + debug_set_level(qeth_dbf_qerr, QETH_DBF_QERR_LEVEL); + + qeth_dbf_trace = debug_register(QETH_DBF_TRACE_NAME, + QETH_DBF_TRACE_INDEX, + QETH_DBF_TRACE_NR_AREAS, + QETH_DBF_TRACE_LEN); + if (!qeth_dbf_trace) + return -ENOMEM; + + debug_register_view(qeth_dbf_trace, &debug_hex_ascii_view); + debug_set_level(qeth_dbf_trace, QETH_DBF_TRACE_LEVEL); + + return 0; +} + +static void +qeth_unregister_dbf_views(void) +{ + if (qeth_dbf_setup) + debug_unregister(qeth_dbf_setup); + if (qeth_dbf_qerr) + debug_unregister(qeth_dbf_qerr); + if (qeth_dbf_sense) + debug_unregister(qeth_dbf_sense); + if (qeth_dbf_misc) + debug_unregister(qeth_dbf_misc); + if (qeth_dbf_data) + debug_unregister(qeth_dbf_data); + if (qeth_dbf_control) + debug_unregister(qeth_dbf_control); + if (qeth_dbf_trace) + debug_unregister(qeth_dbf_trace); +} + +#ifdef QETH_IPV6 +static int +qeth_ipv6_init(void) +{ + qeth_old_arp_constructor = arp_tbl.constructor; + write_lock(&arp_tbl.lock); + arp_tbl.constructor = qeth_arp_constructor; + write_unlock(&arp_tbl.lock); + + /* generate the memory leak here - FIXME*/ + arp_direct_ops = (struct neigh_ops*) + kmalloc(sizeof(struct neigh_ops), GFP_KERNEL); + if (!arp_direct_ops) + return -ENOMEM; + + memcpy(arp_direct_ops, &arp_direct_ops_template, + sizeof(struct neigh_ops)); + return 0; + +} + +static void +qeth_ipv6_uninit(void) +{ + write_lock(&arp_tbl.lock); + arp_tbl.constructor = qeth_old_arp_constructor; + write_unlock(&arp_tbl.lock); +} +#endif /* QETH_IPV6 */ + +static int +qeth_get_internal_functions(void) +{ + struct net_device *dev; + + dev = (struct net_device *) kmalloc(sizeof (struct net_device), + GFP_KERNEL); + if (!dev) { + PRINT_ERR("Not enough memory for internal functions.\n"); + return -ENOMEM; + } +#ifdef CONFIG_NET_ETHERNET + ether_setup(dev); + qeth_my_eth_header = dev->hard_header; + qeth_my_eth_rebuild_header = dev->rebuild_header; + qeth_my_eth_header_cache = dev->hard_header_cache; + qeth_my_eth_header_cache_update = dev->header_cache_update; +#endif +#ifdef CONFIG_TR + tr_setup(dev); + qeth_my_tr_header = dev->hard_header; + qeth_my_tr_rebuild_header = dev->rebuild_header; +#endif + + kfree(dev); + + return 0; +} + +static struct ccw_device_id qeth_ids[] = { + {CCW_DEVICE(0x1731, 0x01), driver_info:QETH_CARD_TYPE_OSAE}, + {CCW_DEVICE(0x1731, 0x05), driver_info:QETH_CARD_TYPE_IQD}, + {}, +}; + +MODULE_DEVICE_TABLE(ccw, qeth_ids); + +static struct ccw_driver qeth_ccw_driver = { + .name = "qeth", + .ids = qeth_ids, + .probe = ccwgroup_probe_ccwdev, + .remove = ccwgroup_remove_ccwdev, +}; + +static struct device qeth_root_dev = { + .name = "QETH Devices", + .bus_id = "qeth", +}; + +static struct ccwgroup_driver qeth_ccwgroup_driver; +static ssize_t +qeth_group_store(struct device_driver *drv, const char *buf, size_t count) +{ + const char *start, *end; + char bus_ids[3][BUS_ID_SIZE], *argv[3]; + int i; + + pr_debug("group_store %s\n", buf); + start = buf; + for (i = 0; i < 3; i++) { + static const char delim[] = { ',', ',', '\n' }; + int len; + + if (!(end = strchr(start, delim[i]))) + return count; + len = min_t(ptrdiff_t, BUS_ID_SIZE, end - start); + strncpy(bus_ids[i], start, len); + bus_ids[i][len] = '\0'; + start = end + 1; + argv[i] = bus_ids[i]; + } + pr_debug("creating qeth group device from '%s', '%s' and '%s'\n", + bus_ids[0], bus_ids[1], bus_ids[2]); + ccwgroup_create(&qeth_root_dev, qeth_ccwgroup_driver.driver_id, + &qeth_ccw_driver, 3, argv); + return count; +} + +static DRIVER_ATTR(group, 0200, 0, qeth_group_store); + +static ssize_t +qeth_bufcnt_show(struct device *dev, char *buf) +{ + struct qeth_card *card = dev->driver_data; + + if (!card) + return -EINVAL; + + return sprintf(buf, "%i\n", card->options.inbound_buffer_count); +} + +static ssize_t +qeth_bufcnt_store(struct device *dev, const char *buf, size_t count) +{ + struct qeth_card *card = dev->driver_data; + unsigned long cnt; + char *tmp; + + if (!card) + return count; + + if (atomic_read(&card->is_softsetup)) + return -EPERM; + + cnt = simple_strtoul(buf, &tmp, 16); + cnt = (cnt < BUFCNT_MIN) ? BUFCNT_MIN : + ((cnt > BUFCNT_MAX) ? BUFCNT_MAX : cnt); + card->options.inbound_buffer_count = cnt; + + return count; +} + +static DEVICE_ATTR(bufcnt, 0644, qeth_bufcnt_show, qeth_bufcnt_store); + +static ssize_t +qeth_portname_show(struct device *dev, char *buf) +{ + struct qeth_card *card = dev->driver_data; + char tmp[9]; + int i; + + if (!card) + return -EINVAL; + + if (card->portname_required) { + sprintf(tmp, "%s", card->options.portname + 1); + for (i = 0; i < 8; i++) + tmp[i] = (char) _ebcasc[(__u8) tmp[i]]; + tmp[8] = 0; + return sprintf(buf, "%s\n", tmp); + } else + return sprintf(buf, "%s\n", "no portname required"); +} + +static ssize_t +qeth_portname_store(struct device *dev, const char *buf, size_t count) +{ + struct qeth_card *card = dev->driver_data; + char *tmp; + int i; + + if (!card) + return count; + + if (atomic_read(&card->is_hardsetup)) + return -EPERM; + + /* Remove trailing '\n'. */ + tmp = strsep((char **) &buf, "\n"); + if ((strlen(tmp) > 8) || (strlen(tmp) < 2)) + return -EINVAL; + + card->options.portname[0] = strlen(tmp); + /* for beauty reasons: */ + for (i = 1; i < 9; i++) + card->options.portname[i] = ' '; + strcpy(card->options.portname + 1, tmp); + for (i = 1; i < 9; i++) + card->options.portname[i] = + _ascebc[(unsigned char)card->options.portname[i]]; + + return count; +} + +static DEVICE_ATTR(portname, 0644, qeth_portname_show, qeth_portname_store); + +static ssize_t +qeth_route4_show(struct device *dev, char *buf) +{ + struct qeth_card *card = dev->driver_data; + + if (!card) + return -EINVAL; + + if (atomic_read(&card->rt4fld)) + return sprintf(buf, "%s\n", "no"); + + switch (card->options.routing_type4 & ROUTER_MASK) { + case PRIMARY_ROUTER: + return sprintf(buf, "%s\n", "primary router"); + case SECONDARY_ROUTER: + return sprintf(buf, "%s\n", "secondary router"); + case MULTICAST_ROUTER: + return sprintf(buf, "%s\n", "multicast router"); + case PRIMARY_CONNECTOR: + return sprintf(buf, "%s\n", "primary connector"); + case SECONDARY_CONNECTOR: + return sprintf(buf, "%s\n", "secondary connector"); + default: + return sprintf(buf, "%s\n", "no"); + } +} + +static ssize_t +qeth_route4_store(struct device *dev, const char *buf, size_t count) +{ + struct qeth_card *card = dev->driver_data; + int cnt; + char *tmp; + + if (!card) + return count; + + /* Remove trailing '\n'. */ + tmp = strsep((char **) &buf, "\n"); + cnt = strlen(tmp); + if (!strncmp(tmp, "primary_router", cnt)) { + QETH_DBF_TEXT2(0, trace, "pri4"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + card->options.routing_type4 = + PRIMARY_ROUTER | RESET_ROUTING_FLAG; + } else if (!strncmp(tmp, "secondary_router", cnt)) { + QETH_DBF_TEXT2(0, trace, "sec4"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + card->options.routing_type4 = + SECONDARY_ROUTER | RESET_ROUTING_FLAG; + } else if (!strncmp(tmp, "multicast_router", cnt)) { + QETH_DBF_TEXT2(0, trace, "mcr4"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + + card->options.routing_type4 = + MULTICAST_ROUTER | RESET_ROUTING_FLAG; + } else if (!strncmp(tmp, "primary_connector", cnt)) { + QETH_DBF_TEXT2(0, trace, "prc4"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + + card->options.routing_type4 = + PRIMARY_CONNECTOR | RESET_ROUTING_FLAG; + } else if (!strncmp(tmp, "secondary_connector", cnt)) { + QETH_DBF_TEXT2(0, trace, "scc4"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + + card->options.routing_type4 = + SECONDARY_CONNECTOR | RESET_ROUTING_FLAG; + } else if (!strncmp(tmp, "no_router", cnt)) { + QETH_DBF_TEXT2(0, trace, "nor4"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + + card->options.routing_type4 = NO_ROUTER | RESET_ROUTING_FLAG; + } else { + PRINT_WARN("unknown command input in route4 attribute\n"); + return -EINVAL; + } + __qeth_correct_routing_status_v4(card); + atomic_set(&card->enable_routing_attempts4, QETH_ROUTING_ATTEMPTS); + if (atomic_read(&card->is_softsetup)) + qeth_start_softsetup_thread(card); + return count; +} + +static DEVICE_ATTR(route4, 0644, qeth_route4_show, qeth_route4_store); + +static ssize_t +qeth_route6_show(struct device *dev, char *buf) +{ +#ifdef QETH_IPV6 + struct qeth_card *card = dev->driver_data; + + if (!card) + return -EINVAL; + + if (atomic_read(&card->rt6fld)) + return sprintf(buf, "%s\n", "no"); + + switch (card->options.routing_type6 & ROUTER_MASK) { + case PRIMARY_ROUTER: + return sprintf(buf, "%s\n", "primary router"); + case SECONDARY_ROUTER: + return sprintf(buf, "%s\n", "secondary router"); + case MULTICAST_ROUTER: + return sprintf(buf, "%s\n", "multicast router"); + case PRIMARY_CONNECTOR: + return sprintf(buf, "%s\n", "primary connector"); + case SECONDARY_CONNECTOR: + return sprintf(buf, "%s\n", "secondary connector"); + default: + return sprintf(buf, "%s\n", "no"); + } +#endif /* QETH_IPV6 */ + return sprintf(buf, "%s\n", "n/a"); +} + +static ssize_t +qeth_route6_store(struct device *dev, const char *buf, size_t count) +{ +#ifdef QETH_IPV6 + struct qeth_card *card = dev->driver_data; + int cnt; + char *tmp; + + if (!card) + return count; + + /* Remove trailing '\n'. */ + tmp = strsep((char **) &buf, "\n"); + cnt = strlen(tmp); + if (!strncmp(tmp, "primary_router", cnt)) { + QETH_DBF_TEXT2(0, trace, "pri6"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + card->options.routing_type6 = + PRIMARY_ROUTER | RESET_ROUTING_FLAG; + } else if (!strncmp(tmp, "secondary_router", cnt)) { + QETH_DBF_TEXT2(0, trace, "sec6"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + card->options.routing_type6 = + SECONDARY_ROUTER | RESET_ROUTING_FLAG; + } else if (!strncmp(tmp, "multicast_router", cnt)) { + QETH_DBF_TEXT2(0, trace, "mcr6"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + + card->options.routing_type6 = + MULTICAST_ROUTER | RESET_ROUTING_FLAG; + } else if (!strncmp(tmp, "primary_connector", cnt)) { + QETH_DBF_TEXT2(0, trace, "prc6"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + + card->options.routing_type6 = + PRIMARY_CONNECTOR | RESET_ROUTING_FLAG; + } else if (!strncmp(tmp, "secondary_connector", cnt)) { + QETH_DBF_TEXT2(0, trace, "scc6"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + + card->options.routing_type6 = + SECONDARY_CONNECTOR | RESET_ROUTING_FLAG; + } else if (!strncmp(tmp, "no_router", cnt)) { + QETH_DBF_TEXT2(0, trace, "nor6"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + + card->options.routing_type6 = NO_ROUTER | RESET_ROUTING_FLAG; + } else { + PRINT_WARN("unknown command input in route6 attribute\n"); + return -EINVAL; + } + __qeth_correct_routing_status_v6(card); + atomic_set(&card->enable_routing_attempts6, QETH_ROUTING_ATTEMPTS); + if (atomic_read(&card->is_softsetup)) + qeth_start_softsetup_thread(card); + return count; +#endif /* QETH_IPV6 */ + return -EINVAL; +} + +static DEVICE_ATTR(route6, 0644, qeth_route6_show, qeth_route6_store); + + +static ssize_t +qeth_checksum_show(struct device *dev, char *buf) +{ + struct qeth_card *card = dev->driver_data; + + if (!card) + return -EINVAL; + + switch (card->options.checksum_type) { + case SW_CHECKSUMMING: + return sprintf(buf, "%s\n", "sw"); + case HW_CHECKSUMMING: + return sprintf(buf, "%s\n", "hw"); + default: + return sprintf(buf, "%s\n", "no"); + } +} + +static ssize_t +qeth_checksum_store(struct device *dev, const char *buf, size_t count) +{ + struct qeth_card *card = dev->driver_data; + char *tmp; + int cnt; + + if (!card) + return count; + + if (atomic_read(&card->is_hardsetup)) + return -EPERM; + + /* Remove trailing '\n'. */ + tmp = strsep((char **) &buf, "\n"); + cnt = strlen(tmp); + if (!strncmp(tmp, "sw_checksumming", cnt)) + card->options.checksum_type = SW_CHECKSUMMING; + else if (!strncmp(tmp, "hw_checksumming", cnt)) + card->options.checksum_type = HW_CHECKSUMMING; + else if (!strncmp(tmp, "no_checksumming", cnt)) + card->options.checksum_type = NO_CHECKSUMMING; + else + PRINT_WARN("unknown checksumming type '%s'\n", tmp); + + return count; +} + +static DEVICE_ATTR(checksumming, 0644, qeth_checksum_show, qeth_checksum_store); + +static ssize_t +qeth_prioq_show(struct device *dev, char *buf) +{ + struct qeth_card *card = dev->driver_data; + + if (!card) + return -EINVAL; + + switch (card->options.do_prio_queueing) { + case PRIO_QUEUEING_PREC: + return sprintf(buf, "%s\n", "by precedence"); + case PRIO_QUEUEING_TOS: + return sprintf(buf, "%s\n", "by type of service"); + default: + return sprintf(buf, "always queue %i\n", + card->options.default_queue); + } +} + +static ssize_t +qeth_prioq_store(struct device *dev, const char *buf, size_t count) +{ + struct qeth_card *card = dev->driver_data; + char *tmp; + int cnt; + + if (!card) + return count; + + if (atomic_read(&card->is_hardsetup)) + return -EPERM; + + /* Remove trailing '\n'. */ + tmp = strsep((char **) &buf, "\n"); + cnt = strlen(tmp); + if (!strncmp(tmp, "prio_queueing_prec", cnt)) + card->options.do_prio_queueing = PRIO_QUEUEING_PREC; + else if (!strncmp(tmp, "prio_queueing_tos", cnt)) + card->options.do_prio_queueing = PRIO_QUEUEING_TOS; + else if (!strncmp(tmp, "no_prio_queueing:0", cnt)) { + card->options.do_prio_queueing = NO_PRIO_QUEUEING; + card->options.default_queue = 0; + } else if (!strncmp(tmp, "no_prio_queueing:1", cnt)) { + card->options.do_prio_queueing = NO_PRIO_QUEUEING; + card->options.default_queue = 1; + } else if (!strncmp(tmp, "no_prio_queueing:2", cnt)) { + card->options.do_prio_queueing = NO_PRIO_QUEUEING; + card->options.default_queue = 2; + } else if (!strncmp(tmp, "no_prio_queueing:3", cnt)) { + card->options.do_prio_queueing = NO_PRIO_QUEUEING; + card->options.default_queue = 3; + } else if (!strncmp(tmp, "no_prio_queueing", cnt)) { + card->options.do_prio_queueing = NO_PRIO_QUEUEING; + card->options.default_queue = QETH_DEFAULT_QUEUE; + } else + PRINT_WARN("unknown queueing type '%s'\n", tmp); + + return count; +} + +static DEVICE_ATTR(priority_queueing, 0644, qeth_prioq_show, qeth_prioq_store); + +static ssize_t +qeth_portno_show(struct device *dev, char *buf) +{ + struct qeth_card *card = dev->driver_data; + + if (!card) + return -EINVAL; + + return sprintf(buf, "%i\n", card->options.portno); +} + +static ssize_t +qeth_portno_store(struct device *dev, const char *buf, size_t count) +{ + struct qeth_card *card = dev->driver_data; + char *tmp; + int i; + + if (!card) + return count; + + if (atomic_read(&card->is_hardsetup)) + return -EPERM; + + i = simple_strtoul(buf, &tmp, 16); + if ((i < 0) || (i > MAX_PORTNO)) { + PRINT_ERR("portno %i out of range\n", i); + return -EINVAL; + } + card->options.portno = i; + + return count; +} + +static DEVICE_ATTR(portno, 0644, qeth_portno_show, qeth_portno_store); + +static ssize_t +qeth_contig_show(struct device *dev, char *buf) +{ + struct qeth_card *card = dev->driver_data; + + if (!card) + return -EINVAL; + + return sprintf(buf, "%s\n", + (card->options.memusage == MEMUSAGE_CONTIG)?"yes":"no"); +} + +static ssize_t +qeth_contig_store(struct device *dev, const char *buf, size_t count) +{ + struct qeth_card *card = dev->driver_data; + int i; + char *tmp; + + if (!card) + return count; + + if (atomic_read(&card->is_hardsetup)) + return -EPERM; + + i = simple_strtoul(buf, &tmp, 16); + if (i == 0) + card->options.memusage = MEMUSAGE_DISCONTIG; + else if (i == 1) + card->options.memusage = MEMUSAGE_CONTIG; + else + return -EINVAL; + + return count; +} + +static DEVICE_ATTR(contig, 0644, qeth_contig_show, qeth_contig_store); + +static ssize_t +qeth_polltime_show(struct device *dev, char *buf) +{ + struct qeth_card *card = dev->driver_data; + + if (!card) + return -EINVAL; + + return sprintf(buf, "%i\n", card->options.polltime); +} + +static ssize_t +qeth_polltime_store(struct device *dev, const char *buf, size_t count) +{ + struct qeth_card *card = dev->driver_data; + char *tmp; + int i; + + if (!card) + return count; + + if (atomic_read(&card->is_hardsetup)) + return -EPERM; + + i = simple_strtoul(buf, &tmp, 16); + if (i < 0) { + PRINT_ERR("polltime %i invalid\n", i); + return -EINVAL; + } + card->options.polltime = i; + + return count; +} + +static DEVICE_ATTR(polltime, 0644, qeth_polltime_show, qeth_polltime_store); + +static ssize_t +qeth_hhlen_show(struct device *dev, char *buf) +{ + struct qeth_card *card = dev->driver_data; + + if (!card) + return -EINVAL; + + return sprintf(buf, "%i\n", card->options.add_hhlen); +} + +static ssize_t +qeth_hhlen_store(struct device *dev, const char *buf, size_t count) +{ + struct qeth_card *card = dev->driver_data; + char *tmp; + int i; + + if (!card) + return count; + + if (atomic_read(&card->is_hardsetup)) + return -EPERM; + + i = simple_strtoul(buf, &tmp, 16); + if ((i < 0) || (i > MAX_ADD_HHLEN)) { + PRINT_ERR("add_hhlen out of range\n"); + return -EINVAL; + } + card->options.add_hhlen = i; + + return count; +} + +static DEVICE_ATTR(add_hhlen, 0644, qeth_hhlen_show, qeth_hhlen_store); + +static ssize_t +qeth_takeover_show(struct device *dev, char *buf) +{ + struct qeth_card *card = dev->driver_data; + + if (!card) + return -EINVAL; + + return sprintf(buf, "%s\n", + (card->options.ena_ipat == ENABLE_TAKEOVER)?"yes":"no"); +} + +static ssize_t +qeth_takeover_store(struct device *dev, const char *buf, size_t count) +{ + struct qeth_card *card = dev->driver_data; + int i; + char *tmp; + + if (!card) + return count; + + if (atomic_read(&card->is_hardsetup)) + return -EPERM; + + i = simple_strtoul(buf, &tmp, 16); + if (i == 0) + card->options.ena_ipat = ENABLE_TAKEOVER; + else if (i == 1) + card->options.ena_ipat = DISABLE_TAKEOVER; + else + return -EINVAL; + + return count; +} + +static DEVICE_ATTR(enable_takeover, 0644, qeth_takeover_show, qeth_takeover_store); + +static ssize_t +qeth_macaddr_show(struct device *dev, char *buf) +{ + struct qeth_card *card = dev->driver_data; + + if (!card) + return -EINVAL; + + return sprintf(buf, "%s\n", + (card->options.macaddr_mode == MACADDR_CANONICAL)?"yes":"no"); +} + +static ssize_t +qeth_macaddr_store(struct device *dev, const char *buf, size_t count) +{ + struct qeth_card *card = dev->driver_data; + int i; + char *tmp; + + if (!card) + return count; + + if (atomic_read(&card->is_hardsetup)) + return -EPERM; + + i = simple_strtoul(buf, &tmp, 16); + if (i == 0) + card->options.macaddr_mode = MACADDR_NONCANONICAL; + else if (i == 1) + card->options.macaddr_mode = MACADDR_CANONICAL; + else + return -EINVAL; + + return count; +} + +static DEVICE_ATTR(canonical_macaddr, 0644, qeth_macaddr_show, qeth_macaddr_store); + +static ssize_t +qeth_fakebr_show(struct device *dev, char *buf) +{ + struct qeth_card *card = dev->driver_data; + + if (!card) + return -EINVAL; + + return sprintf(buf, "%s\n", + (card->options.fake_broadcast == FAKE_BROADCAST)?"yes":"no"); +} + +static ssize_t +qeth_fakebr_store(struct device *dev, const char *buf, size_t count) +{ + struct qeth_card *card = dev->driver_data; + int i; + char *tmp; + + if (!card) + return count; + + if (atomic_read(&card->is_hardsetup)) + return -EPERM; + + i = simple_strtoul(buf, &tmp, 16); + if (i == 0) + card->options.fake_broadcast = DONT_FAKE_BROADCAST; + else if (i == 1) + card->options.fake_broadcast = FAKE_BROADCAST; + else + return -EINVAL; + + return count; +} + +static DEVICE_ATTR(fake_broadcast, 0644, qeth_fakebr_show, qeth_fakebr_store); + +static ssize_t +qeth_fakell_show(struct device *dev, char *buf) +{ + struct qeth_card *card = dev->driver_data; + + if (!card) + return -EINVAL; + + return sprintf(buf, "%s\n", + (card->options.fake_ll == FAKE_LL)?"yes":"no"); +} + +static ssize_t +qeth_fakell_store(struct device *dev, const char *buf, size_t count) +{ + struct qeth_card *card = dev->driver_data; + int i; + char *tmp; + + if (!card) + return count; + + if (atomic_read(&card->is_hardsetup)) + return -EPERM; + + i = simple_strtoul(buf, &tmp, 16); + if (i == 0) + card->options.fake_ll = DONT_FAKE_LL; + else if (i == 1) + card->options.fake_ll = FAKE_LL; + else + return -EINVAL; + + return count; +} + +static DEVICE_ATTR(fake_ll, 0644, qeth_fakell_show, qeth_fakell_store); + +static ssize_t +qeth_hsi_show(struct device *dev, char *buf) +{ + struct qeth_card *card = dev->driver_data; + + if (!card) + return -EINVAL; + + return sprintf(buf, "%s\n", + (card->options.async_iqd == ASYNC_IQD)?"async":"sync"); +} + +static ssize_t +qeth_hsi_store(struct device *dev, const char *buf, size_t count) +{ + struct qeth_card *card = dev->driver_data; + int i; + char *tmp; + + if (!card) + return count; + + if (atomic_read(&card->is_hardsetup)) + return -EPERM; + + i = simple_strtoul(buf, &tmp, 16); + if (i == 0) + card->options.async_iqd = SYNC_IQD; + else if (i == 1) + card->options.async_iqd = ASYNC_IQD; + else + return -EINVAL; + + return count; +} + +static DEVICE_ATTR(async_hsi, 0644, qeth_hsi_show, qeth_hsi_store); + +static ssize_t +qeth_broadcast_show(struct device *dev, char *buf) +{ + struct qeth_card *card = dev->driver_data; + + if (!card) + return -EINVAL; + + return sprintf(buf, "%s\n", + (card->options.broadcast_mode == BROADCAST_ALLRINGS) + ?"allrings":"local"); +} + +static ssize_t +qeth_broadcast_store(struct device *dev, const char *buf, size_t count) +{ + struct qeth_card *card = dev->driver_data; + char *tmp; + int cnt; + + if (!card) + return count; + + if (atomic_read(&card->is_hardsetup)) + return -EPERM; + + /* Remove trailing '\n'. */ + tmp = strsep((char **) &buf, "\n"); + cnt = strlen(tmp); + if (!strncmp(tmp, "broadcast_allrings", cnt)) + card->options.broadcast_mode = BROADCAST_ALLRINGS; + else if (!strncmp(tmp, "broadcast_local", cnt)) + card->options.broadcast_mode = BROADCAST_LOCAL; + else + PRINT_WARN("unknown broadcast type '%s'\n", tmp); + + return count; +} + +static DEVICE_ATTR(broadcast_mode, 0644, qeth_broadcast_show, qeth_broadcast_store); + +static ssize_t +qeth_recover_store(struct device *dev, const char *buf, size_t count) +{ + struct qeth_card *card = dev->driver_data; + int i; + char *tmp; + + if (!card) + return count; + + i = simple_strtoul(buf, &tmp, 16); + if (i == 1) { + QETH_DBF_TEXT2(0, trace, "UTRC"); + QETH_DBF_TEXT2(0, trace, card->rdev->dev.bus_id); + atomic_set(&card->problem, PROBLEM_USER_TRIGGERED_RECOVERY); + qeth_schedule_recovery(card); + return count; + } else + return -EINVAL; +} + +static DEVICE_ATTR(recover, 0200, 0, qeth_recover_store); + +static inline int +__qeth_create_attributes(struct device *dev) +{ + int ret; + + ret = device_create_file(dev, &dev_attr_bufcnt); + if (ret != 0) + goto out_nobufcnt; + + ret = device_create_file(dev, &dev_attr_portname); + if (ret != 0) + goto out_noportname; + + ret = device_create_file(dev, &dev_attr_route4); + if (ret != 0) + goto out_noroute4; + + ret = device_create_file(dev, &dev_attr_route6); + if (ret != 0) + goto out_noroute6; + + ret = device_create_file(dev, &dev_attr_checksumming); + if (ret != 0) + goto out_nochecksum; + + ret = device_create_file(dev, &dev_attr_priority_queueing); + if (ret != 0) + goto out_noprioq; + + ret = device_create_file(dev, &dev_attr_portno); + if (ret != 0) + goto out_noportno; + + ret = device_create_file(dev, &dev_attr_contig); + if (ret != 0) + goto out_nocontig; + + ret = device_create_file(dev, &dev_attr_polltime); + if (ret != 0) + goto out_nopolltime; + + ret = device_create_file(dev, &dev_attr_add_hhlen); + if (ret != 0) + goto out_nohhlen; + + ret = device_create_file(dev, &dev_attr_enable_takeover); + if (ret != 0) + goto out_noipat; + + ret = device_create_file(dev, &dev_attr_canonical_macaddr); + if (ret != 0) + goto out_nomac; + + ret = device_create_file(dev, &dev_attr_fake_broadcast); + if (ret != 0) + goto out_nofakebr; + + ret = device_create_file(dev, &dev_attr_fake_ll); + if (ret != 0) + goto out_nofakell; + + ret = device_create_file(dev, &dev_attr_async_hsi); + if (ret != 0) + goto out_nohsi; + + ret = device_create_file(dev, &dev_attr_broadcast_mode); + if (ret != 0) + goto out_nobrmode; + + ret = device_create_file(dev, &dev_attr_recover); + if (ret != 0) + goto out_norecover; + + return 0; + +out_norecover: + device_remove_file(dev, &dev_attr_broadcast_mode); +out_nobrmode: + device_remove_file(dev, &dev_attr_async_hsi); +out_nohsi: + device_remove_file(dev, &dev_attr_fake_ll); +out_nofakell: + device_remove_file(dev, &dev_attr_fake_broadcast); +out_nofakebr: + device_remove_file(dev, &dev_attr_canonical_macaddr); +out_nomac: + device_remove_file(dev, &dev_attr_enable_takeover); +out_noipat: + device_remove_file(dev, &dev_attr_add_hhlen); +out_nohhlen: + device_remove_file(dev, &dev_attr_polltime); +out_nopolltime: + device_remove_file(dev, &dev_attr_contig); +out_nocontig: + device_remove_file(dev, &dev_attr_portno); +out_noportno: + device_remove_file(dev, &dev_attr_priority_queueing); +out_noprioq: + device_remove_file(dev, &dev_attr_checksumming); +out_nochecksum: + device_remove_file(dev, &dev_attr_route6); +out_noroute6: + device_remove_file(dev, &dev_attr_route4); +out_noroute4: + device_remove_file(dev, &dev_attr_portname); +out_noportname: + device_remove_file(dev, &dev_attr_bufcnt); +out_nobufcnt: + return ret; +} + +static int +qeth_probe_device(struct ccwgroup_device *gdev) +{ + struct qeth_card *card; + int ret; + + if (!get_device(&gdev->dev)) + return -ENODEV; + + card = qeth_alloc_card(); + if (!card) { + put_device(&gdev->dev); + return -ENOMEM; + } + + gdev->dev.driver_data = card; + + card->rdev = gdev->cdev[0]; + gdev->cdev[0]->handler = qeth_interrupt_handler_read; + gdev->cdev[0]->dev.driver_data = card; + + card->wdev = gdev->cdev[1]; + gdev->cdev[1]->handler = qeth_interrupt_handler_write; + gdev->cdev[1]->dev.driver_data = card; + + card->ddev = gdev->cdev[2]; + gdev->cdev[2]->handler = qeth_interrupt_handler_qdio; + gdev->cdev[2]->dev.driver_data = card; + + ret = __qeth_create_attributes(&gdev->dev); + if (ret != 0) + goto out; + + snprintf(gdev->dev.name, DEVICE_NAME_SIZE, "qeth device"); + return 0; +out: + put_device(&gdev->dev); + qeth_free_card(card); + return ret; +} + +/* + * Replaces qeth_probe and qeth_attach_handler. + * This is called after piping to the 'online' attribute, + * when all parameters are ready. + */ +static int +qeth_activate(struct qeth_card *card) +{ + int result; + + PRINT_STUPID("%s: got devices %s, %s, %s\n", + __func__, + rdev->dev.bus_id, wdev->dev.bus_id, ddev->dev.bus_id); + + ccw_device_set_online(card->rdev); + ccw_device_set_online(card->wdev); + ccw_device_set_online(card->ddev); + + QETH_DBF_TEXT1(0, setup, "activ"); + QETH_DBF_TEXT1(0, setup, card->rdev->dev.bus_id); + QETH_DBF_HEX1(0, setup, &card, sizeof (void *)); + QETH_DBF_HEX1(0, setup, &card->dev, sizeof (void *)); + QETH_DBF_HEX1(0, setup, &card->stats, sizeof (void *)); + + QETH_DBF_HEX2(0, misc, &card->options, QETH_DBF_MISC_LEN); + + if (qeth_determine_card_type(card)) { + PRINT_WARN("%s: not a valid card type\n", __func__); + goto out; + } + + qeth_insert_card_into_list(card); + + qeth_correct_routing_status(card); + + result = qeth_init_ringbuffers1(card); + if (result) { + PRINT_WARN("%s: could not init ringbuffers1\n", __func__); + goto out_remove; + } + + result = qeth_hardsetup_card(card, 0); + if (result) { + goto out_remove; + } + + result = qeth_init_ringbuffers2(card); + if (result) { + PRINT_WARN("%s: could not init ringbuffers2\n", __func__); + goto out_remove; + } + + /* this was previously done in chandev_initnetdevice */ + snprintf(card->dev->name, 8, "%s%%d", + qeth_get_dev_basename(card->type, card->link_type)); + qeth_init_netdev(card->dev); + + return 0; /* success */ + +out_remove: + qeth_remove_card(card, QETH_REMOVE_CARD_QUICK); + qeth_remove_card_from_list(card); + +out: + QETH_DBF_TEXT4(0, trace, "freecard"); + + ccw_device_set_offline(card->ddev); + ccw_device_set_offline(card->wdev); + ccw_device_set_offline(card->rdev); + + return -ENODEV; +} + +static int +qeth_remove_device(struct ccwgroup_device *gdev) +{ + struct qeth_card *card = gdev->dev.driver_data; + + gdev->dev.driver_data = NULL; + if (card) + kfree(card); + put_device(&gdev->dev); + return 0; +} + +static int +qeth_set_online(struct ccwgroup_device *gdev) +{ + struct qeth_card *card = gdev->dev.driver_data; + int ret; + + BUG_ON(!card); + + ret = qeth_activate(card); + if (ret == 0) + snprintf(gdev->dev.name, DEVICE_NAME_SIZE, "%s", + qeth_get_cardname_short(card->type, card->link_type, + card->is_guest_lan)); + return ret; +} + +static int +qeth_set_offline(struct ccwgroup_device *gdev) +{ + struct qeth_card *card = gdev->dev.driver_data; + + if (!card) + return -ENODEV; + + qeth_remove_card(card, QETH_REMOVE_CARD_PROPER); + qeth_remove_card_from_list(card); + + QETH_DBF_TEXT4(0, trace, "freecard"); + + ccw_device_set_offline(card->ddev); + ccw_device_set_offline(card->wdev); + ccw_device_set_offline(card->rdev); + + return 0; +} + +static struct ccwgroup_driver qeth_ccwgroup_driver = { + .name = "qeth", + .driver_id = 0xD8C5E3C8, + .probe = qeth_probe_device, + .remove = qeth_remove_device, + .set_online = qeth_set_online, + .set_offline = qeth_set_offline, +}; + +static int __init +qeth_init(void) +{ + int result; + + qeth_eyecatcher(); + + printk(KERN_INFO "qeth: loading %s\n", version); + + result = qeth_get_internal_functions(); + if (result) + goto out; + + qeth_alloc_spare_bufs(); + +#ifdef QETH_IPV6 + if (qeth_ipv6_init()) { + PRINT_ERR("Out of memory during ipv6 init.\n"); + goto out_sparebufs; + } +#endif /* QETH_IPV6 */ + + result = qeth_register_dbf_views(); + if (result) { + PRINT_ERR("not enough memory for dbf. Will not load module.\n"); + goto out_ipv6; + } + + result = ccwgroup_driver_register(&qeth_ccwgroup_driver); + if (result) + goto out_dbf; + + result = ccw_driver_register(&qeth_ccw_driver); + if (result) + goto out_gdrv; + + result = driver_create_file(&qeth_ccwgroup_driver.driver, + &driver_attr_group); + if (result) + goto out_cdrv; + + result = device_register(&qeth_root_dev); + if (result) + goto out_file; + + qeth_register_notifiers(); + qeth_add_procfs_entries(); + + return 0; + +out_file: + driver_remove_file(&qeth_ccwgroup_driver.driver, &driver_attr_group); +out_cdrv: + ccw_driver_unregister(&qeth_ccw_driver); +out_gdrv: + ccwgroup_driver_unregister(&qeth_ccwgroup_driver); +out_dbf: + qeth_unregister_dbf_views(); +out_ipv6: +#ifdef QETH_IPV6 + qeth_ipv6_uninit(); +out_sparebufs: +#endif /* QETH_IPV6 */ + qeth_free_all_spare_bufs(); +out: + return result; +} + +static void __exit +qeth_exit(void) +{ +#ifdef QETH_IPV6 + qeth_ipv6_uninit(); +#endif /* QETH_IPV6 */ + qeth_unregister_notifiers(); + + qeth_remove_procfs_entries(); + + QETH_DBF_TEXT1(0, trace, "cleanup."); + + driver_remove_file(&qeth_ccwgroup_driver.driver, &driver_attr_group); + ccw_driver_unregister(&qeth_ccw_driver); + ccwgroup_driver_unregister(&qeth_ccwgroup_driver); + device_unregister(&qeth_root_dev); + + while (firstcard) { + struct qeth_card *card = firstcard; + qeth_remove_card(card, QETH_REMOVE_CARD_QUICK); + qeth_remove_card_from_list(card); + qeth_free_card(card); + } + + qeth_free_all_spare_bufs(); + + qeth_unregister_dbf_views(); + + printk("qeth: %s: module removed\n", version); +} + +EXPORT_SYMBOL(qeth_eyecatcher); + +module_init(qeth_init); +module_exit(qeth_exit); diff -Nru a/drivers/s390/net/qeth.h b/drivers/s390/net/qeth.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/s390/net/qeth.h Tue Jul 1 18:44:39 2003 @@ -0,0 +1,1341 @@ +/* + * linux/drivers/s390/net/qeth.h + * + * Linux on zSeries OSA Express and HiperSockets support + * + * Copyright 2000,2003 IBM Corporation + * Author(s): Utz Bacher + * + */ +#ifndef __QETH_H__ +#define __QETH_H__ + +#include + +#define QETH_NAME " qeth" + +#define VERSION_QETH_H "$Revision: 1.47 $" + +/******************** CONFIG STUFF ***********************/ +//#define QETH_DBF_LIKE_HELL + +#ifdef CONFIG_QETH_IPV6 +#define QETH_IPV6 +#define QETH_VERSION_IPV6 ":IPv6" +#else +#define QETH_VERSION_IPV6 "" +#endif /* CONFIG_QETH_IPV6 */ + +#ifdef CONFIG_QETH_VLAN +#define QETH_VLAN +#define QETH_VERSION_VLAN ":VLAN" +#else +#define QETH_VERSION_VLAN "" +#endif /* CONFIG_QETH_VLAN */ + +/* these values match CHECKSUM_* in include/linux/skbuff.h */ +#define SW_CHECKSUMMING 0 +#define HW_CHECKSUMMING 1 +#define NO_CHECKSUMMING 2 + +#define QETH_CHECKSUM_DEFAULT NO_CHECKSUMMING + +#define QETH_PRIOQ_DEFAULT NO_PRIO_QUEUEING +#define QETH_DEFAULT_QUEUE 2 + +/******************** CONFIG STUFF END ***********************/ +/********************* TUNING STUFF **************************/ +#define HIGH_WATERMARK_PACK 5 +#define LOW_WATERMARK_PACK 2 +#define WATERMARK_FUZZ 2 + +#define QETH_MAX_INPUT_THRESHOLD 500 +#define QETH_MAX_OUTPUT_THRESHOLD 300 /* ? */ + +/* only the MAX values are used */ +#define QETH_MIN_INPUT_THRESHOLD 1 +#define QETH_MIN_OUTPUT_THRESHOLD 1 + +#define QETH_REQUEUE_THRESHOLD (card->options.inbound_buffer_count/4) + +#ifdef CONFIG_QETH_PERF_STATS +#define QETH_PERFORMANCE_STATS +#endif /* CONFIG_QETH_PERF_STATS */ + +#ifdef QETH_DBF_LIKE_HELL +#define QETH_VERBOSE_LEVEL 8 +#else /* QETH_DBF_LIKE_HELL */ +#define QETH_VERBOSE_LEVEL 5 +#endif /* QETH_DBF_LIKE_HELL */ + +#define PCI_THRESHOLD_A (card->options.inbound_buffer_count+1) +/* buffers we have to be behind before we get a PCI */ +#define PCI_THRESHOLD_B 0 /* enqueued free buffers left before we get a PCI */ +#define PCI_TIMER_VALUE 3 /* not used, unless the microcode gets patched */ + +#define DEFAULT_SPARE_BUFFERS 0 +#define MAX_SPARE_BUFFERS 1024 +#define SPAREBUF_MASK 65536 +#define MAX_PORTNO 15 + +#define QETH_PROCFILE_NAME "qeth" +#define QETH_PERF_PROCFILE_NAME "qeth_perf" +#define QETH_IPA_PROCFILE_NAME "qeth_ipa_takeover" + +#define SEND_RETRIES_ALLOWED 5 +#define QETH_ROUTING_ATTEMPTS 2 + +#define QETH_HARDSETUP_LAPS 5 +#define QETH_HARDSETUP_CLEAR_LAPS 3 +#define QETH_RECOVERY_HARDSETUP_RETRY 2 + +/************************* DEBUG FACILITY STUFF *********************/ + +#define QETH_DBF_HEX(ex,name,level,addr,len) \ + do { \ + if (ex) \ + debug_exception(qeth_dbf_##name,level,(void*)addr,len); \ + else \ + debug_event(qeth_dbf_##name,level,(void*)addr,len); \ + } while (0) +#define QETH_DBF_TEXT(ex,name,level,text) \ + do { \ + if (ex) \ + debug_text_exception(qeth_dbf_##name,level,text); \ + else \ + debug_text_event(qeth_dbf_##name,level,text); \ + } while (0) + +#define QETH_DBF_HEX0(ex,name,addr,len) QETH_DBF_HEX(ex,name,0,addr,len) +#define QETH_DBF_HEX1(ex,name,addr,len) QETH_DBF_HEX(ex,name,1,addr,len) +#define QETH_DBF_HEX2(ex,name,addr,len) QETH_DBF_HEX(ex,name,2,addr,len) +#ifdef QETH_DBF_LIKE_HELL +#define QETH_DBF_HEX3(ex,name,addr,len) QETH_DBF_HEX(ex,name,3,addr,len) +#define QETH_DBF_HEX4(ex,name,addr,len) QETH_DBF_HEX(ex,name,4,addr,len) +#define QETH_DBF_HEX5(ex,name,addr,len) QETH_DBF_HEX(ex,name,5,addr,len) +#define QETH_DBF_HEX6(ex,name,addr,len) QETH_DBF_HEX(ex,name,6,addr,len) +#else /* QETH_DBF_LIKE_HELL */ +#define QETH_DBF_HEX3(ex,name,addr,len) do {} while (0) +#define QETH_DBF_HEX4(ex,name,addr,len) do {} while (0) +#define QETH_DBF_HEX5(ex,name,addr,len) do {} while (0) +#define QETH_DBF_HEX6(ex,name,addr,len) do {} while (0) +#endif /* QETH_DBF_LIKE_HELL */ + +#define QETH_DBF_TEXT0(ex,name,text) QETH_DBF_TEXT(ex,name,0,text) +#define QETH_DBF_TEXT1(ex,name,text) QETH_DBF_TEXT(ex,name,1,text) +#define QETH_DBF_TEXT2(ex,name,text) QETH_DBF_TEXT(ex,name,2,text) +#ifdef QETH_DBF_LIKE_HELL +#define QETH_DBF_TEXT3(ex,name,text) QETH_DBF_TEXT(ex,name,3,text) +#define QETH_DBF_TEXT4(ex,name,text) QETH_DBF_TEXT(ex,name,4,text) +#define QETH_DBF_TEXT5(ex,name,text) QETH_DBF_TEXT(ex,name,5,text) +#define QETH_DBF_TEXT6(ex,name,text) QETH_DBF_TEXT(ex,name,6,text) +#else /* QETH_DBF_LIKE_HELL */ +#define QETH_DBF_TEXT3(ex,name,text) do {} while (0) +#define QETH_DBF_TEXT4(ex,name,text) do {} while (0) +#define QETH_DBF_TEXT5(ex,name,text) do {} while (0) +#define QETH_DBF_TEXT6(ex,name,text) do {} while (0) +#endif /* QETH_DBF_LIKE_HELL */ + +#define QETH_DBF_SETUP_NAME "qeth_setup" +#define QETH_DBF_SETUP_LEN 8 +#define QETH_DBF_SETUP_INDEX 3 +#define QETH_DBF_SETUP_NR_AREAS 1 +#ifdef QETH_DBF_LIKE_HELL +#define QETH_DBF_SETUP_LEVEL 6 +#else /* QETH_DBF_LIKE_HELL */ +#define QETH_DBF_SETUP_LEVEL 3 +#endif /* QETH_DBF_LIKE_HELL */ + +#define QETH_DBF_MISC_NAME "qeth_misc" +#define QETH_DBF_MISC_LEN 128 +#define QETH_DBF_MISC_INDEX 1 +#define QETH_DBF_MISC_NR_AREAS 1 +#ifdef QETH_DBF_LIKE_HELL +#define QETH_DBF_MISC_LEVEL 6 +#else /* QETH_DBF_LIKE_HELL */ +#define QETH_DBF_MISC_LEVEL 2 +#endif /* QETH_DBF_LIKE_HELL */ + +#define QETH_DBF_DATA_NAME "qeth_data" +#define QETH_DBF_DATA_LEN 96 +#define QETH_DBF_DATA_INDEX 3 +#define QETH_DBF_DATA_NR_AREAS 1 +#ifdef QETH_DBF_LIKE_HELL +#define QETH_DBF_DATA_LEVEL 6 +#else /* QETH_DBF_LIKE_HELL */ +#define QETH_DBF_DATA_LEVEL 2 +#endif /* QETH_DBF_LIKE_HELL */ + +#define QETH_DBF_CONTROL_NAME "qeth_control" +/* buffers are 255 bytes long, but no prob */ +#define QETH_DBF_CONTROL_LEN 256 +#define QETH_DBF_CONTROL_INDEX 3 +#define QETH_DBF_CONTROL_NR_AREAS 2 +#ifdef QETH_DBF_LIKE_HELL +#define QETH_DBF_CONTROL_LEVEL 6 +#else /* QETH_DBF_LIKE_HELL */ +#define QETH_DBF_CONTROL_LEVEL 2 +#endif /* QETH_DBF_LIKE_HELL */ + +#define QETH_DBF_TRACE_NAME "qeth_trace" +#define QETH_DBF_TRACE_LEN 8 +#ifdef QETH_DBF_LIKE_HELL +#define QETH_DBF_TRACE_INDEX 3 +#else /* QETH_DBF_LIKE_HELL */ +#define QETH_DBF_TRACE_INDEX 2 +#endif /* QETH_DBF_LIKE_HELL */ +#define QETH_DBF_TRACE_NR_AREAS 2 +#ifdef QETH_DBF_LIKE_HELL +#define QETH_DBF_TRACE_LEVEL 6 +#else /* QETH_DBF_LIKE_HELL */ +#define QETH_DBF_TRACE_LEVEL 2 +#endif /* QETH_DBF_LIKE_HELL */ + +#define QETH_DBF_SENSE_NAME "qeth_sense" +#define QETH_DBF_SENSE_LEN 64 +#define QETH_DBF_SENSE_INDEX 1 +#define QETH_DBF_SENSE_NR_AREAS 1 +#ifdef QETH_DBF_LIKE_HELL +#define QETH_DBF_SENSE_LEVEL 6 +#else /* QETH_DBF_LIKE_HELL */ +#define QETH_DBF_SENSE_LEVEL 2 +#endif /* QETH_DBF_LIKE_HELL */ + +#define QETH_DBF_QERR_NAME "qeth_qerr" +#define QETH_DBF_QERR_LEN 8 +#define QETH_DBF_QERR_INDEX 1 +#define QETH_DBF_QERR_NR_AREAS 2 +#ifdef QETH_DBF_LIKE_HELL +#define QETH_DBF_QERR_LEVEL 6 +#else /* QETH_DBF_LIKE_HELL */ +#define QETH_DBF_QERR_LEVEL 2 +#endif /* QETH_DBF_LIKE_HELL */ +/****************** END OF DEBUG FACILITY STUFF *********************/ + +/********************* CARD DATA STUFF **************************/ + +#define QETH_MAX_PARAMS 150 + +#define QETH_CARD_TYPE_UNKNOWN 0 +#define QETH_CARD_TYPE_OSAE 10 +#define QETH_CARD_TYPE_IQD 1234 + +#define QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT 0x0101 +#define QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT 0x0101 +#define QETH_IDX_FUNC_LEVEL_IQD_ENA_IPAT 0x4108 +#define QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT 0x5108 + +#define QETH_MAX_QUEUES 4 + +#define UNIQUE_ID_IF_CREATE_ADDR_FAILED 0xfffe +#define UNIQUE_ID_NOT_BY_CARD 0x10000 + +/* + * CU type & model, Dev type & model, card_type, odd_even_restriction, + * func level, no of queues, multicast is different (multicast-queue_no + 0x100) + */ +#define QETH_MODELLIST_ARRAY \ + {{0x1731,0x01,0x1732,0x01,QETH_CARD_TYPE_OSAE,1, \ + QETH_IDX_FUNC_LEVEL_OSAE_ENA_IPAT, \ + QETH_IDX_FUNC_LEVEL_OSAE_DIS_IPAT, \ + QETH_MAX_QUEUES,0}, \ + {0x1731,0x05,0x1732,0x05,QETH_CARD_TYPE_IQD,0, \ + QETH_IDX_FUNC_LEVEL_IQD_ENA_IPAT, \ + QETH_IDX_FUNC_LEVEL_IQD_DIS_IPAT, \ + QETH_MAX_QUEUES,0x103}, \ + {0,0,0,0,0,0,0,0,0}} + +#define QETH_MPC_DIFINFO_LEN_INDICATES_LINK_TYPE 0x18 + /* only the first two bytes are looked at in qeth_get_cardname_short */ +#define QETH_MPC_LINK_TYPE_FAST_ETHERNET 0x01 +#define QETH_MPC_LINK_TYPE_HSTR 0x02 +#define QETH_MPC_LINK_TYPE_GIGABIT_ETHERNET 0x03 +#define QETH_MPC_LINK_TYPE_10GIGABIT_ETHERNET 0x10 +#define QETH_MPC_LINK_TYPE_LANE_ETH100 0x81 +#define QETH_MPC_LINK_TYPE_LANE_TR 0x82 +#define QETH_MPC_LINK_TYPE_LANE_ETH1000 0x83 +#define QETH_MPC_LINK_TYPE_LANE 0x88 +#define QETH_MPC_LINK_TYPE_ATM_NATIVE 0x90 + +#define DEFAULT_ADD_HHLEN 0 +#define MAX_ADD_HHLEN 1024 + +#define QETH_HEADER_SIZE 32 +#define QETH_IP_HEADER_SIZE 40 +#define QETH_HEADER_LEN_POS 8 +/* flags for the header: */ +#define QETH_HEADER_PASSTHRU 0x10 +#define QETH_HEADER_IPV6 0x80 + +#define QETH_CAST_FLAGS 0x07 +#define QETH_CAST_UNICAST 6 +#define QETH_CAST_MULTICAST 4 +#define QETH_CAST_BROADCAST 5 +#define QETH_CAST_ANYCAST 7 +#define QETH_CAST_NOCAST 0 + +/* VLAN defines */ +#define QETH_EXT_HEADER_VLAN_FRAME 0x01 +#define QETH_EXT_HEADER_TOKEN_ID 0x02 +#define QETH_EXT_HEADER_INCLUDE_VLAN_TAG 0x04 + +#define QETH_EXT_HEADER_SRC_MAC_ADDRESS 0x08 +#define QETH_EXT_HEADER_CSUM_HDR_REQ 0x10 +#define QETH_EXT_HEADER_CSUM_TRANSP_REQ 0x20 +#define QETH_EXT_HEADER_CSUM_TRANSP_FRAME_TYPE 0x40 + +#define QETH_UDP_CSUM_OFFSET 6 +#define QETH_TCP_CSUM_OFFSET 16 + +#define QETH_VERIFY_IS_REAL_DEV 1 +#define QETH_VERIFY_IS_VLAN_DEV 2 + +inline static unsigned int +qeth_get_ipa_timeout(int cardtype) +{ + switch (cardtype) { + case QETH_CARD_TYPE_IQD: + return 2000; + default: + return 20000; + } +} + +inline static unsigned short +qeth_get_additional_dev_flags(int cardtype) +{ + switch (cardtype) { + case QETH_CARD_TYPE_IQD: + return IFF_NOARP; +#ifdef QETH_IPV6 + default: + return 0; +#else /* QETH_IPV6 */ + default: + return IFF_NOARP; +#endif /* QETH_IPV6 */ + } +} + +inline static int +qeth_get_hlen(__u8 link_type) +{ +#ifdef QETH_IPV6 + switch (link_type) { + case QETH_MPC_LINK_TYPE_HSTR: + case QETH_MPC_LINK_TYPE_LANE_TR: + return QETH_HEADER_SIZE + TR_HLEN; + default: +#ifdef QETH_VLAN + return QETH_HEADER_SIZE + VLAN_ETH_HLEN; +#else + return QETH_HEADER_SIZE + ETH_HLEN; +#endif + } +#else /* QETH_IPV6 */ +#ifdef QETH_VLAN + return QETH_HEADER_SIZE + VLAN_HLEN; +#else + return QETH_HEADER_SIZE; +#endif + +#endif /* QETH_IPV6 */ +} + +static int (*qeth_my_eth_header) (struct sk_buff *, struct net_device *, + unsigned short, void *, void *, unsigned); +#ifdef CONFIG_TR +static int (*qeth_my_tr_header) (struct sk_buff *, struct net_device *, + unsigned short, void *, void *, unsigned); +#endif /* CONFIG_TR */ +static int (*qeth_my_eth_rebuild_header) (struct sk_buff *); +#ifdef CONFIG_TR +static int (*qeth_my_tr_rebuild_header) (struct sk_buff *); +#endif /* CONFIG_TR */ +static int (*qeth_my_eth_header_cache) (struct neighbour *, struct hh_cache *); +static void (*qeth_my_eth_header_cache_update) (struct hh_cache *, + struct net_device *, + unsigned char *); + +#ifdef QETH_IPV6 +typedef int (*__qeth_temp1) (struct sk_buff *, struct net_device *, + unsigned short, void *, void *, unsigned); +inline static __qeth_temp1 +qeth_get_hard_header(__u8 link_type) +{ + switch (link_type) { +#ifdef CONFIG_TR + case QETH_MPC_LINK_TYPE_HSTR: + case QETH_MPC_LINK_TYPE_LANE_TR: + return qeth_my_tr_header; +#endif /* CONFIG_TR */ + default: + return qeth_my_eth_header; + } +} + +typedef int (*__qeth_temp2) (struct sk_buff *); +inline static __qeth_temp2 +qeth_get_rebuild_header(__u8 link_type) +{ + switch (link_type) { +#ifdef CONFIG_TR + case QETH_MPC_LINK_TYPE_HSTR: + case QETH_MPC_LINK_TYPE_LANE_TR: + return qeth_my_tr_rebuild_header; +#endif /* CONFIG_TR */ + default: + return qeth_my_eth_rebuild_header; + } +} + +typedef int (*__qeth_temp3) (struct neighbour *, struct hh_cache *); +inline static __qeth_temp3 +qeth_get_hard_header_cache(__u8 link_type) +{ + switch (link_type) { + case QETH_MPC_LINK_TYPE_HSTR: + case QETH_MPC_LINK_TYPE_LANE_TR: + return NULL; + default: + return qeth_my_eth_header_cache; + } +} + +typedef void (*__qeth_temp4) (struct hh_cache *, struct net_device *, + unsigned char *); +inline static __qeth_temp4 +qeth_get_header_cache_update(__u8 link_type) +{ + switch (link_type) { + case QETH_MPC_LINK_TYPE_HSTR: + case QETH_MPC_LINK_TYPE_LANE_TR: + return NULL; + default: + return qeth_my_eth_header_cache_update; + } +} + +static unsigned short +qeth_eth_type_trans(struct sk_buff *skb, struct net_device *dev) +{ + struct ethhdr *eth; + + skb->mac.raw = skb->data; + skb_pull(skb, ETH_ALEN * 2 + sizeof (short)); + eth = skb->mac.ethernet; + + if (*eth->h_dest & 1) { + if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN) == 0) + skb->pkt_type = PACKET_BROADCAST; + else + skb->pkt_type = PACKET_MULTICAST; + } else { + skb->pkt_type = PACKET_OTHERHOST; + } + if (ntohs(eth->h_proto) >= 1536) + return eth->h_proto; + if (*(unsigned short *) (skb->data) == 0xFFFF) + return htons(ETH_P_802_3); + return htons(ETH_P_802_2); +} + +typedef unsigned short (*__qeth_temp5) (struct sk_buff *, struct net_device *); +inline static __qeth_temp5 +qeth_get_type_trans(__u8 link_type) +{ + switch (link_type) { +#ifdef CONFIG_TR + case QETH_MPC_LINK_TYPE_HSTR: + case QETH_MPC_LINK_TYPE_LANE_TR: + return tr_type_trans; +#endif + default: + return qeth_eth_type_trans; + } +} +#endif /* QETH_IPV6 */ + +inline static const char * +qeth_get_link_type_name(int cardtype, __u8 linktype) +{ + switch (cardtype) { + case QETH_CARD_TYPE_UNKNOWN: + return "unknown"; + case QETH_CARD_TYPE_OSAE: + switch (linktype) { + case QETH_MPC_LINK_TYPE_FAST_ETHERNET: + return "Fast Eth"; + case QETH_MPC_LINK_TYPE_HSTR: + return "HSTR"; + case QETH_MPC_LINK_TYPE_GIGABIT_ETHERNET: + return "Gigabit Eth"; + case QETH_MPC_LINK_TYPE_LANE_ETH100: + return "LANE Eth100"; + case QETH_MPC_LINK_TYPE_LANE_TR: + return "LANE TR"; + case QETH_MPC_LINK_TYPE_LANE_ETH1000: + return "LANE Eth1000"; + default: + return "unknown"; + } + case QETH_CARD_TYPE_IQD: + return "magic"; + default: + return "unknown"; + } +} + +inline static const char * +qeth_get_dev_basename(int cardtype, __u8 link_type) +{ + switch (cardtype) { + case QETH_CARD_TYPE_UNKNOWN: + return "eth"; + case QETH_CARD_TYPE_OSAE: + switch (link_type) { + case QETH_MPC_LINK_TYPE_LANE_TR: + /* fallthrough */ + case QETH_MPC_LINK_TYPE_HSTR: + return "tr"; + default: + return "eth"; + } + case QETH_CARD_TYPE_IQD: + return "hsi"; + default: + return "eth"; + } +} + +/* inbound: */ +#define DEFAULT_BUFFER_SIZE 65536 +#define DEFAULT_BUFFER_COUNT 128 +#define BUFCNT_MIN 8 +#define BUFCNT_MAX 128 +#define BUFFER_SIZE (card->inbound_buffer_size) +#define BUFFER_MAX_ELEMENTS (BUFFER_SIZE>>12) + /* 8k for each pair header-buffer: */ + +inline static int +qeth_sbal_packing_on_card(int cardtype) +{ + switch (cardtype) { + case QETH_CARD_TYPE_IQD: + return 0; + default: + return 1; + } +} + +/* + * do it this way round -> __MODULE_STRING needs with + * QETH_PRIO_NICE_LEVELS a single number + */ +#define QETH_MAX_PRIO_QUEUES QETH_PRIO_NICE_LEVELS+1 + +static inline int +qeth_sbalf15_in_retrieable_range(int sbalf15) +{ + return ((sbalf15 >= 15) && (sbalf15 <= 31)); +} + +#define INBOUND_BUFFER_POS(card,bufno,sbale) \ + ( (bufno&SPAREBUF_MASK)? \ + ( \ + (sparebufs[bufno&(~SPAREBUF_MASK)].buf+ \ + PAGE_SIZE*sbale) \ + ):( \ + (card->inbound_buffer_pool_entry[card-> \ + inbound_buffer_entry_no[bufno]][sbale]) \ + ) ) + +#define SPAREBUF_UNAVAIL 0 +#define SPAREBUF_FREE 1 +#define SPAREBUF_USED 2 + +struct sparebufs { + char *buf; + atomic_t status; +}; + +#define SEND_STATE_INACTIVE 0 +#define SEND_STATE_DONT_PACK 1 +#define SEND_STATE_PACK 2 + +#define QETH_LOCK_UNLOCKED 0 +#define QETH_LOCK_NORMAL 1 +#define QETH_LOCK_FLUSH 2 + +#define QETH_MAX_DEVICES 16 + /* DEPENDENCY ON QETH_MAX_DEVICES. + *__MOUDLE_STRING expects simple literals */ +#define QETH_MAX_DEVICES_TIMES_4 64 +#define QETH_MAX_DEVNAMES 16 +#define QETH_DEVNAME "eth" + +#define QETH_TX_TIMEOUT 100*HZ /* 100 seconds */ + +#define QETH_REMOVE_WAIT_TIME 200 +#define QETH_WAIT_FOR_THREAD_TIME 20 +#define QETH_IDLE_WAIT_TIME 10 +#define QETH_WAIT_BEFORE_2ND_DOIO 1000 + +#define QETH_MAX_PARM_LEN 128 + +#define QETH_FAKE_LL_LEN ETH_HLEN /* 14 */ +#define QETH_FAKE_LL_PROT_LEN 2 +#define QETH_FAKE_LL_ADDR_LEN ETH_ALEN /* 6 */ +#define QETH_FAKE_LL_DEST_MAC_POS 0 +#define QETH_FAKE_LL_SRC_MAC_POS 6 +#define QETH_FAKE_LL_SRC_MAC_POS_IN_QDIO_HDR 6 +#define QETH_FAKE_LL_PROT_POS 12 +#define QETH_FAKE_LL_V4_ADDR_POS 16 +#define QETH_FAKE_LL_V6_ADDR_POS 24 + +#define DEV_NAME_LEN 16 +#define IOCTL_MAX_TRANSFER_SIZE 65535 + +#define IP_TOS_LOWDELAY 0x10 +#define IP_TOS_HIGHTHROUGHPUT 0x08 +#define IP_TOS_HIGHRELIABILITY 0x04 +#define IP_TOS_NOTIMPORTANT 0x02 + +#define QETH_RCD_LENGTH 128 + +#define __max(a,b) ( ((a)>(b))?(a):(b) ) +#define __min(a,b) ( ((a)<(b))?(a):(b) ) +#define QETH_BUFSIZE __max(__max(IPA_PDU_HEADER_SIZE+sizeof(struct arp_cmd), \ + IPA_PDU_HEADER_SIZE+sizeof(struct ipa_cmd)), \ + QETH_RCD_LENGTH) + +#define QETH_FINAL_STATUS_TIMEOUT 1500 +#define QETH_CLEAR_TIMEOUT 1500 +#define QETH_RCD_TIMEOUT 1500 +#define QETH_NOP_TIMEOUT 1500 +#define QETH_QUIESCE_NETDEV_TIME 300 +#define QETH_QUIESCE_WAIT_BEFORE_CLEAR 4000 +#define QETH_QUIESCE_WAIT_AFTER_CLEAR 4000 + +#define NOP_STATE 0x1001 +#define READ_CONF_DATA_STATE 0x1002 +#define IDX_ACTIVATE_READ_STATE 0x1003 +#define IDX_ACTIVATE_WRITE_STATE 0x1004 +#define MPC_SETUP_STATE 0x1005 +#define CLEAR_STATE 0x1006 +#define IPA_CMD_STATE 0x1007 +#define IPA_IOCTL_STATE 0x1009 +#define IPA_SETIP_FLAG 0x100000 + +#define QETH_REMOVE_CARD_PROPER 1 +#define QETH_REMOVE_CARD_QUICK 2 + +#define NO_PRIO_QUEUEING 0 +#define PRIO_QUEUEING_PREC 1 +#define PRIO_QUEUEING_TOS 2 +#define NO_ROUTER 0 +#define PRIMARY_ROUTER 1 +#define SECONDARY_ROUTER 2 +#define MULTICAST_ROUTER 3 +#define PRIMARY_CONNECTOR 4 +#define SECONDARY_CONNECTOR 5 +#define ROUTER_MASK 0xf /* used to remove SET_ROUTING_FLAG + from routing_type */ +#define RESET_ROUTING_FLAG 0x10 /* used to indicate, that setting + the routing type is desired */ +#define BROADCAST_ALLRINGS 0 +#define BROADCAST_LOCAL 1 +#define MACADDR_NONCANONICAL 0 +#define MACADDR_CANONICAL 1 +#define MEMUSAGE_DISCONTIG 0 +#define MEMUSAGE_CONTIG 1 +#define ENABLE_TAKEOVER 0 +#define DISABLE_TAKEOVER 1 +#define FAKE_BROADCAST 0 +#define DONT_FAKE_BROADCAST 1 + +#define FAKE_LL 0 +#define DONT_FAKE_LL 1 +#define SYNC_IQD 0 +#define ASYNC_IQD 1 + +#define QETH_BREAKOUT_LEAVE 1 +#define QETH_BREAKOUT_AGAIN 2 + +#define QETH_WAIT_FOR_LOCK 0 +#define QETH_DONT_WAIT_FOR_LOCK 1 +#define QETH_LOCK_ALREADY_HELD 2 + +#define PROBLEM_CARD_HAS_STARTLANED 1 +#define PROBLEM_RECEIVED_IDX_TERMINATE 2 +#define PROBLEM_ACTIVATE_CHECK_CONDITION 3 +#define PROBLEM_RESETTING_EVENT_INDICATOR 4 +#define PROBLEM_COMMAND_REJECT 5 +#define PROBLEM_ZERO_SENSE_DATA 6 +#define PROBLEM_GENERAL_CHECK 7 +#define PROBLEM_BAD_SIGA_RESULT 8 +#define PROBLEM_USER_TRIGGERED_RECOVERY 9 +#define PROBLEM_AFFE 10 +#define PROBLEM_MACHINE_CHECK 11 +#define PROBLEM_TX_TIMEOUT 12 + +#define SENSE_COMMAND_REJECT_BYTE 0 +#define SENSE_COMMAND_REJECT_FLAG 0x80 +#define SENSE_RESETTING_EVENT_BYTE 1 +#define SENSE_RESETTING_EVENT_FLAG 0x80 + +#define DEFAULT_RCD_CMD 0x72 +#define DEFAULT_RCD_COUNT 0x80 + +#define BUFFER_USED 1 +#define BUFFER_UNUSED -1 + +typedef int (*reg_notifier_t) (struct notifier_block *); + +struct ipato_entry { + int version; + __u8 addr[16]; + int mask_bits; + char dev_name[DEV_NAME_LEN]; + struct ipato_entry *next; +}; + +struct qeth_vipa_entry { + int version; + __u8 ip[16]; + int flag; + volatile int state; + struct qeth_vipa_entry *next; +}; + +struct ip_state { + struct in_ifaddr *ip_ifa; /* pointer to IPv4 adresses */ + struct inet6_ifaddr *ip6_ifa; +}; + +struct qeth_ipm_mac { + __u8 mac[ETH_ALEN]; + __u8 ip[16]; + struct qeth_ipm_mac *next; +}; + +struct ip_mc_state { + struct qeth_ipm_mac *ipm_ifa; + struct qeth_ipm_mac *ipm6_ifa; +}; + +struct addr_request { + struct addr_request *next; + int request_type; + __u8 mac[ETH_ALEN]; + __u8 ip[16]; +}; + +struct qeth_card_options { + char devname[DEV_NAME_LEN]; + volatile int routing_type4; +#ifdef QETH_IPV6 + volatile int routing_type6; +#endif /* QETH_IPV6 */ + int checksum_type; + int do_prio_queueing; + int default_queue; + int inbound_buffer_count; + int polltime; + char portname[9]; + int portno; + int memusage; + int broadcast_mode; + int macaddr_mode; + int ena_ipat; + int fake_broadcast; + int add_hhlen; + int fake_ll; + int async_iqd; +}; + +struct qeth_hdr { + __u8 id; + __u8 flags; + __u16 inbound_checksum; + __u32 token; + __u16 length; + __u8 vlan_prio; + __u8 ext_flags; + __u16 vlan_id; + __u16 frame_offset; + __u8 dest_addr[16]; +}; + +struct qeth_ringbuffer_element { + struct sk_buff_head skb_list; + int next_element_to_fill; +} __attribute__ ((packed)); + +struct qeth_ringbuffer { + struct qdio_buffer buffer[QDIO_MAX_BUFFERS_PER_Q]; + struct qeth_ringbuffer_element ringbuf_element[QDIO_MAX_BUFFERS_PER_Q]; +}__attribute__ ((packed, aligned(PAGE_SIZE))); + +struct qeth_dma_stuff { + unsigned char *sendbuf; + unsigned char *recbuf; + struct ccw1 read_ccw; + struct ccw1 write_ccw; +}__attribute__ ((packed, aligned(PAGE_SIZE))); + +struct qeth_perf_stats { + unsigned int skbs_rec; + unsigned int bufs_rec; + + unsigned int skbs_sent; + unsigned int bufs_sent; + + unsigned int skbs_sent_dont_pack; + unsigned int bufs_sent_dont_pack; + unsigned int skbs_sent_pack; + unsigned int bufs_sent_pack; + unsigned int skbs_sent_pack_better; + unsigned int bufs_sent_pack_better; + + unsigned int sc_dp_p; + unsigned int sc_p_dp; + + __u64 inbound_start_time; + unsigned int inbound_cnt; + unsigned int inbound_time; + __u64 outbound_start_time; + unsigned int outbound_cnt; + unsigned int outbound_time; +}; + +/* ugly. I know. */ +struct qeth_card { /* pointed to by dev->priv */ + int easy_copy_cap; + + /* pointer to options (defaults + parameters) */ + struct qeth_card_options options; + + atomic_t is_startlaned; /* card did not get a stoplan */ + /* also 0 when card is gone after a + * machine check */ + + __u8 link_type; + + int is_guest_lan; + + /* inbound buffer management */ + atomic_t inbound_buffer_refcnt[QDIO_MAX_BUFFERS_PER_Q]; + struct qdio_buffer inbound_qdio_buffers[QDIO_MAX_BUFFERS_PER_Q]; + /* inbound data area */ + void *inbound_buffer_pool_entry[QDIO_MAX_BUFFERS_PER_Q] + [QDIO_MAX_ELEMENTS_PER_BUFFER]; + volatile int inbound_buffer_pool_entry_used[QDIO_MAX_BUFFERS_PER_Q]; + int inbound_buffer_entry_no[QDIO_MAX_BUFFERS_PER_Q]; + + /* for requeueing of buffers */ + spinlock_t requeue_input_lock; + atomic_t requeue_position; + atomic_t requeue_counter; + + /* outbound QDIO stuff */ + volatile int send_state[QETH_MAX_QUEUES]; + volatile int outbound_first_free_buffer[QETH_MAX_QUEUES]; + atomic_t outbound_used_buffers[QETH_MAX_QUEUES]; + int outbound_buffer_send_state[QETH_MAX_QUEUES] + [QDIO_MAX_BUFFERS_PER_Q]; + int send_retries[QETH_MAX_QUEUES][QDIO_MAX_BUFFERS_PER_Q]; + volatile int outbound_bytes_in_buffer[QETH_MAX_QUEUES]; + struct qeth_ringbuffer *outbound_ringbuffer[QETH_MAX_QUEUES]; + atomic_t outbound_ringbuffer_lock[QETH_MAX_QUEUES]; + atomic_t last_pci_pos[QETH_MAX_QUEUES]; + +#ifdef QETH_IPV6 + int (*hard_header) (struct sk_buff *, struct net_device *, + unsigned short, void *, void *, unsigned); + int (*rebuild_header) (struct sk_buff *); + int (*hard_header_cache) (struct neighbour *, struct hh_cache *); + void (*header_cache_update) (struct hh_cache *, struct net_device *, + unsigned char *); + unsigned short (*type_trans) (struct sk_buff *, struct net_device *); +#endif /* QETH_IPV6 */ + +#ifdef QETH_VLAN + struct vlan_group *vlangrp; + spinlock_t vlan_lock; +#endif + + char dev_name[DEV_NAME_LEN]; /* pointed to by dev->name */ + struct net_device *dev; + struct net_device_stats *stats; + + int no_queues; + +#ifdef QETH_PERFORMANCE_STATS + struct qeth_perf_stats perf_stats; +#endif /* QETH_PERFORMANCE_STATS */ + + /* our state */ + atomic_t is_registered; /* card registered as netdev? */ + atomic_t is_hardsetup; /* card has gone through hardsetup */ + atomic_t is_softsetup; /* card is setup by softsetup */ + atomic_t is_open; /* card is in use */ + + /* prevents deadlocks :-O */ + spinlock_t softsetup_lock; + spinlock_t hardsetup_lock; + spinlock_t ioctl_lock; + atomic_t softsetup_thread_is_running; + struct semaphore softsetup_thread_sem; + struct work_struct tqueue_sst; + + atomic_t escape_softsetup; /* active, when recovery has to + wait for softsetup */ + struct semaphore reinit_thread_sem; + atomic_t in_recovery; + atomic_t reinit_counter; + + /* problem management */ + atomic_t break_out; + atomic_t problem; + struct work_struct tqueue; + + struct { + __u32 trans_hdr; + __u32 pdu_hdr; + __u32 pdu_hdr_ack; + __u32 ipa; + } seqno; + + struct { + __u32 issuer_rm_w; + __u32 issuer_rm_r; + __u32 cm_filter_w; + __u32 cm_filter_r; + __u32 cm_connection_w; + __u32 cm_connection_r; + __u32 ulp_filter_w; + __u32 ulp_filter_r; + __u32 ulp_connection_w; + __u32 ulp_connection_r; + } token; + + /* this is card-related */ + int type; + __u16 func_level; + int initial_mtu; + int max_mtu; + int inbound_buffer_size; + + int is_multicast_different; /* if multicast traffic is to be sent + on a different queue, this is the + queue+no_queues */ + int can_do_async_iqd; /* 1 only on IQD that provides async + unicast sigas */ + __u32 ipa_supported; + __u32 ipa_enabled; + __u32 ipa6_supported; + __u32 ipa6_enabled; + __u32 adp_supported; + + atomic_t startlan_attempts; + atomic_t enable_routing_attempts4; + atomic_t rt4fld; +#ifdef QETH_IPV6 + atomic_t enable_routing_attempts6; + atomic_t rt6fld; +#endif /* QETH_IPV6 */ + int unique_id; + + /* device and I/O data */ + struct ccw_device *rdev; + struct ccw_device *wdev; + struct ccw_device *ddev; + unsigned short unit_addr2; + unsigned short cula; + unsigned short chpid; + + unsigned char ipa_buf[QETH_BUFSIZE]; + unsigned char send_buf[QETH_BUFSIZE]; + +/* IOCTL Stuff */ + unsigned char *ioctl_data_buffer; + unsigned char *ioctl_buffer_pointer; + int ioctl_returncode; + int ioctl_buffersize; + int number_of_entries; + + atomic_t ioctl_data_has_arrived; + wait_queue_head_t ioctl_wait_q; + atomic_t ioctl_wait_q_active; + spinlock_t ioctl_wait_q_lock; + +/* stuff under 2 gb */ + struct qeth_dma_stuff *dma_stuff; + + unsigned int ipa_timeout; + + atomic_t write_busy; + + /* vipa stuff */ + rwlock_t vipa_list_lock; + struct qeth_vipa_entry *vipa_list; + + /* state information when doing I/O */ + atomic_t shutdown_phase; + atomic_t data_has_arrived; + wait_queue_head_t wait_q; + atomic_t wait_q_active; + spinlock_t wait_q_lock; /* for wait_q_active and wait_q */ + + atomic_t clear_succeeded0; + atomic_t clear_succeeded1; + atomic_t clear_succeeded2; + + /* bookkeeping of IP and multicast addresses */ + struct ip_state ip_current_state; + struct ip_state ip_new_state; + + struct ip_mc_state ip_mc_current_state; + struct ip_mc_state ip_mc_new_state; + + int broadcast_capable; + int portname_required; + + int realloc_message; + + char level[QETH_MCL_LENGTH + 1]; + + volatile int saved_dev_flags; + + /* for our linked list */ + struct qeth_card *next; +}; + +inline static int +qeth_get_arphrd_type(int cardtype, int linktype) +{ + switch (cardtype) { + case QETH_CARD_TYPE_OSAE: + switch (linktype) { + case QETH_MPC_LINK_TYPE_LANE_TR: + /* fallthrough */ + case QETH_MPC_LINK_TYPE_HSTR: + return ARPHRD_IEEE802; + default: + return ARPHRD_ETHER; + } + case QETH_CARD_TYPE_IQD: + return ARPHRD_ETHER; + default: + return ARPHRD_ETHER; + } +} + +inline static int +qeth_determine_easy_copy_cap(int cardtype) +{ + switch (cardtype) { + case QETH_CARD_TYPE_UNKNOWN: + return 0; /* better be cautious */ + case QETH_CARD_TYPE_OSAE: + return 1; + case QETH_CARD_TYPE_IQD: + return 0; + default: + return 0; /* ?? */ + } +} + +inline static __u8 +qeth_get_adapter_type_for_ipa(int link_type) +{ + switch (link_type) { + case QETH_MPC_LINK_TYPE_HSTR: + return 2; + default: + return 1; + } +} + +inline static const char * +qeth_get_cardname(int cardtype, int is_guest_lan) +{ + + if (is_guest_lan) { + switch (cardtype) { + case QETH_CARD_TYPE_UNKNOWN: + return "n unknown"; + case QETH_CARD_TYPE_OSAE: + return " Guest LAN QDIO"; + case QETH_CARD_TYPE_IQD: + return " Guest LAN Hiper"; + default: return + " strange"; + } + } else { + switch (cardtype) { + case QETH_CARD_TYPE_UNKNOWN: + return "n unknown"; + case QETH_CARD_TYPE_OSAE: + return "n OSD Express"; + case QETH_CARD_TYPE_IQD: + return " HiperSockets"; + default: + return " strange"; + } + } +} + +/* max length to be returned: 14 */ +inline static const char * +qeth_get_cardname_short(int cardtype, __u8 link_type, int is_guest_lan) +{ + switch (cardtype) { + case QETH_CARD_TYPE_UNKNOWN: + return "unknown"; + case QETH_CARD_TYPE_OSAE: + if (is_guest_lan) + return "GuestLAN QDIO"; + switch (link_type) { + case QETH_MPC_LINK_TYPE_FAST_ETHERNET: + return "OSD_100"; + case QETH_MPC_LINK_TYPE_HSTR: + return "HSTR"; + case QETH_MPC_LINK_TYPE_GIGABIT_ETHERNET: + return "OSD_1000"; + case QETH_MPC_LINK_TYPE_LANE_ETH100: + return "OSD_FE_LANE"; + case QETH_MPC_LINK_TYPE_LANE_TR: + return "OSD_TR_LANE"; + case QETH_MPC_LINK_TYPE_LANE_ETH1000: + return "OSD_GbE_LANE"; + case QETH_MPC_LINK_TYPE_LANE: + return "OSD_ATM_LANE"; + default: + return "OSD_Express"; + } + case QETH_CARD_TYPE_IQD: + return is_guest_lan ? "GuestLAN Hiper" : "HiperSockets"; + default: + return " strange"; + } +} + +inline static int +qeth_mtu_is_valid(struct qeth_card * card, int mtu) +{ + switch (card->type) { + case QETH_CARD_TYPE_UNKNOWN: + return 1; + case QETH_CARD_TYPE_OSAE: + return ((mtu >= 576) && (mtu <= 61440)); + case QETH_CARD_TYPE_IQD: + return ((mtu >= 576) && (mtu <= card->max_mtu + 4096 - 32)); + default: + return 1; + } +} + +inline static int +qeth_get_initial_mtu_for_card(struct qeth_card * card) +{ + switch (card->type) { + case QETH_CARD_TYPE_UNKNOWN: + return 1500; + case QETH_CARD_TYPE_IQD: + return card->max_mtu; + case QETH_CARD_TYPE_OSAE: + switch (card->link_type) { + case QETH_MPC_LINK_TYPE_HSTR: + case QETH_MPC_LINK_TYPE_LANE_TR: + return 2000; + default: + return 1492; + } + default: + return 1500; + } +} + +inline static int +qeth_get_max_mtu_for_card(int cardtype) +{ + switch (cardtype) { + case QETH_CARD_TYPE_UNKNOWN: + return 61440; + case QETH_CARD_TYPE_OSAE: + return 61440; + case QETH_CARD_TYPE_IQD: + return 57344; + default: + return 1500; + } +} + +inline static int +qeth_get_mtu_out_of_mpc(int cardtype) +{ + switch (cardtype) { + case QETH_CARD_TYPE_IQD: + return 1; + default: + return 0; + } +} + +inline static int +qeth_get_mtu_outof_framesize(int framesize) +{ + switch (framesize) { + case 0x4000: + return 8192; + case 0x6000: + return 16384; + case 0xa000: + return 32768; + case 0xffff: + return 57344; + default: + return 0; + } +} + +inline static int +qeth_get_buffersize_for_card(int cardtype) +{ + switch (cardtype) { + case QETH_CARD_TYPE_UNKNOWN: + return 65536; + case QETH_CARD_TYPE_OSAE: + return 65536; + case QETH_CARD_TYPE_IQD: + return 16384; + default: + return 65536; + } +} + +inline static int +qeth_get_min_number_of_buffers(int cardtype) +{ + switch (cardtype) { + case QETH_CARD_TYPE_UNKNOWN: + return 32; + case QETH_CARD_TYPE_OSAE: + return 32; + case QETH_CARD_TYPE_IQD: + return 64; + default: + return 64; + } +} + +inline static int +qeth_get_q_format(int cardtype) +{ + switch (cardtype) { + case QETH_CARD_TYPE_IQD: + return 2; + default: + return 0; + } +} + +inline static int +qeth_get_device_tx_q_len(int cardtype) +{ + return 100; +} + +inline static int +qeth_get_max_number_of_buffers(int cardtype) +{ + return 127; +} + +/******************** OUTPUT FACILITIES **************************/ + +#ifdef PRINT_INFO +#undef PRINTK_HEADER +#undef PRINT_STUPID +#undef PRINT_ALL +#undef PRINT_INFO +#undef PRINT_WARN +#undef PRINT_ERR +#undef PRINT_CRIT +#undef PRINT_ALERT +#undef PRINT_EMERG +#endif /* PRINT_INFO */ + +#define PRINTK_HEADER QETH_NAME ": " + +#if QETH_VERBOSE_LEVEL>8 +#define PRINT_STUPID(x...) printk( KERN_DEBUG PRINTK_HEADER x) +#else +#define PRINT_STUPID(x...) +#endif + +#if QETH_VERBOSE_LEVEL>7 +#define PRINT_ALL(x...) printk( KERN_DEBUG PRINTK_HEADER x) +#else +#define PRINT_ALL(x...) +#endif + +#if QETH_VERBOSE_LEVEL>6 +#define PRINT_INFO(x...) printk( KERN_INFO PRINTK_HEADER x) +#else +#define PRINT_INFO(x...) +#endif + +#if QETH_VERBOSE_LEVEL>5 +#define PRINT_WARN(x...) printk( KERN_WARNING PRINTK_HEADER x) +#else +#define PRINT_WARN(x...) +#endif + +#if QETH_VERBOSE_LEVEL>4 +#define PRINT_ERR(x...) printk( KERN_ERR PRINTK_HEADER x) +#else +#define PRINT_ERR(x...) +#endif + +#if QETH_VERBOSE_LEVEL>3 +#define PRINT_CRIT(x...) printk( KERN_CRIT PRINTK_HEADER x) +#else +#define PRINT_CRIT(x...) +#endif + +#if QETH_VERBOSE_LEVEL>2 +#define PRINT_ALERT(x...) printk( KERN_ALERT PRINTK_HEADER x) +#else +#define PRINT_ALERT(x...) +#endif + +#if QETH_VERBOSE_LEVEL>1 +#define PRINT_EMERG(x...) printk( KERN_EMERG PRINTK_HEADER x) +#else +#define PRINT_EMERG(x...) +#endif + +#define HEXDUMP16(importance,header,ptr) \ +PRINT_##importance(header "%02x %02x %02x %02x %02x %02x %02x %02x " \ + "%02x %02x %02x %02x %02x %02x %02x %02x\n", \ + *(((char*)ptr)),*(((char*)ptr)+1),*(((char*)ptr)+2), \ + *(((char*)ptr)+3),*(((char*)ptr)+4),*(((char*)ptr)+5), \ + *(((char*)ptr)+6),*(((char*)ptr)+7),*(((char*)ptr)+8), \ + *(((char*)ptr)+9),*(((char*)ptr)+10),*(((char*)ptr)+11), \ + *(((char*)ptr)+12),*(((char*)ptr)+13), \ + *(((char*)ptr)+14),*(((char*)ptr)+15)); \ +PRINT_##importance(header "%02x %02x %02x %02x %02x %02x %02x %02x " \ + "%02x %02x %02x %02x %02x %02x %02x %02x\n", \ + *(((char*)ptr)+16),*(((char*)ptr)+17), \ + *(((char*)ptr)+18),*(((char*)ptr)+19), \ + *(((char*)ptr)+20),*(((char*)ptr)+21), \ + *(((char*)ptr)+22),*(((char*)ptr)+23), \ + *(((char*)ptr)+24),*(((char*)ptr)+25), \ + *(((char*)ptr)+26),*(((char*)ptr)+27), \ + *(((char*)ptr)+28),*(((char*)ptr)+29), \ + *(((char*)ptr)+30),*(((char*)ptr)+31)); + +#endif /* __QETH_H__ */ diff -Nru a/drivers/s390/net/qeth_mpc.c b/drivers/s390/net/qeth_mpc.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/s390/net/qeth_mpc.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,161 @@ +/* + * linux/drivers/s390/net/qeth_mpc.c + * + * Linux on zSeries OSA Express and HiperSockets support + * + * Copyright 2000,2003 IBM Corporation + * Author(s): Utz Bacher + * + */ +#include +#include "qeth_mpc.h" + +unsigned char IDX_ACTIVATE_READ[]={ + 0x00,0x00,0x80,0x00, 0x00,0x00,0x00,0x00, + 0x19,0x01,0x01,0x80, 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, 0x00,0x00,0xc8,0xc1, + 0xd3,0xd3,0xd6,0xd3, 0xc5,0x40,0x00,0x00, + 0x00,0x00 +}; + +unsigned char IDX_ACTIVATE_WRITE[]={ + 0x00,0x00,0x80,0x00, 0x00,0x00,0x00,0x00, + 0x15,0x01,0x01,0x80, 0x00,0x00,0x00,0x00, + 0xff,0xff,0x00,0x00, 0x00,0x00,0xc8,0xc1, + 0xd3,0xd3,0xd6,0xd3, 0xc5,0x40,0x00,0x00, + 0x00,0x00 +}; + +unsigned char CM_ENABLE[]={ + 0x00,0xe0,0x00,0x00, 0x00,0x00,0x00,0x01, + 0x00,0x00,0x00,0x14, 0x00,0x00,0x00,0x63, + 0x10,0x00,0x00,0x01, + 0x00,0x00,0x00,0x00, + 0x81,0x7e,0x00,0x01, 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, 0x00,0x24,0x00,0x23, + 0x00,0x00,0x23,0x05, 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, + 0x01,0x00,0x00,0x23, 0x00,0x00,0x00,0x40, + 0x00,0x0c,0x41,0x02, 0x00,0x17,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x0b,0x04,0x01, + 0x7e,0x04,0x05,0x00, 0x01,0x01,0x0f, + 0x00, + 0x0c,0x04,0x02,0xff, 0xff,0xff,0xff,0xff, + 0xff,0xff,0xff +}; + +unsigned char CM_SETUP[]={ + 0x00,0xe0,0x00,0x00, 0x00,0x00,0x00,0x02, + 0x00,0x00,0x00,0x14, 0x00,0x00,0x00,0x64, + 0x10,0x00,0x00,0x01, + 0x00,0x00,0x00,0x00, + 0x81,0x7e,0x00,0x01, 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, 0x00,0x24,0x00,0x24, + 0x00,0x00,0x24,0x05, 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, + 0x01,0x00,0x00,0x24, 0x00,0x00,0x00,0x40, + 0x00,0x0c,0x41,0x04, 0x00,0x18,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x09,0x04,0x04, + 0x05,0x00,0x01,0x01, 0x11, + 0x00,0x09,0x04, + 0x05,0x05,0x00,0x00, 0x00,0x00, + 0x00,0x06, + 0x04,0x06,0xc8,0x00 +}; + +unsigned char ULP_ENABLE[]={ + 0x00,0xe0,0x00,0x00, 0x00,0x00,0x00,0x03, + 0x00,0x00,0x00,0x14, 0x00,0x00,0x00,0x6b, + 0x10,0x00,0x00,0x01, + 0x00,0x00,0x00,0x00, + 0x41,0x7e,0x00,0x01, 0x00,0x00,0x00,0x01, + 0x00,0x00,0x00,0x00, 0x00,0x24,0x00,0x2b, + 0x00,0x00,0x2b,0x05, 0x20,0x01,0x00,0x00, + 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, + 0x01,0x00,0x00,0x2b, 0x00,0x00,0x00,0x40, + 0x00,0x0c,0x41,0x02, 0x00,0x1f,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x0b,0x04,0x01, + 0x03,0x04,0x05,0x00, 0x01,0x01,0x12, + 0x00, + 0x14,0x04,0x0a,0x00, 0x20,0x00,0x00,0xff, + 0xff,0x00,0x08,0xc8, 0xe8,0xc4,0xf1,0xc7, + 0xf1,0x00,0x00 +}; + +unsigned char ULP_SETUP[]={ + 0x00,0xe0,0x00,0x00, 0x00,0x00,0x00,0x04, + 0x00,0x00,0x00,0x14, 0x00,0x00,0x00,0x6c, + 0x10,0x00,0x00,0x01, + 0x00,0x00,0x00,0x00, + 0x41,0x7e,0x00,0x01, 0x00,0x00,0x00,0x02, + 0x00,0x00,0x00,0x01, 0x00,0x24,0x00,0x2c, + 0x00,0x00,0x2c,0x05, 0x20,0x01,0x00,0x00, + 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, + 0x01,0x00,0x00,0x2c, 0x00,0x00,0x00,0x40, + 0x00,0x0c,0x41,0x04, 0x00,0x20,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x09,0x04,0x04, + 0x05,0x00,0x01,0x01, 0x14, + 0x00,0x09,0x04, + 0x05,0x05,0x30,0x01, 0x00,0x00, + 0x00,0x06, + 0x04,0x06,0x40,0x00, + 0x00,0x08,0x04,0x0b, + 0x00,0x00,0x00,0x00 +}; + +unsigned char DM_ACT[]={ + 0x00,0xe0,0x00,0x00, 0x00,0x00,0x00,0x05, + 0x00,0x00,0x00,0x14, 0x00,0x00,0x00,0x55, + 0x10,0x00,0x00,0x01, + 0x00,0x00,0x00,0x00, + 0x41,0x7e,0x00,0x01, 0x00,0x00,0x00,0x03, + 0x00,0x00,0x00,0x02, 0x00,0x24,0x00,0x15, + 0x00,0x00,0x2c,0x05, 0x20,0x01,0x00,0x00, + 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, + 0x01,0x00,0x00,0x15, 0x00,0x00,0x00,0x40, + 0x00,0x0c,0x43,0x60, 0x00,0x09,0x00,0x00, + 0x00,0x00,0x00,0x00, + 0x00,0x09,0x04,0x04, + 0x05,0x40,0x01,0x01, 0x00 +}; + +unsigned char IPA_PDU_HEADER[]={ + 0x00,0xe0,0x00,0x00, 0x77,0x77,0x77,0x77, + 0x00,0x00,0x00,0x14, 0x00,0x00, + (IPA_PDU_HEADER_SIZE+sizeof(struct ipa_cmd))/256, + (IPA_PDU_HEADER_SIZE+sizeof(struct ipa_cmd))%256, + 0x10,0x00,0x00,0x01, + 0x00,0x00,0x00,0x00, + 0xc1,0x03,0x00,0x01, 0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00, 0x00,0x24,0x00,sizeof(struct ipa_cmd), + 0x00,0x00,sizeof(struct ipa_cmd),0x05, 0x77,0x77,0x77,0x77, + 0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00, + 0x01,0x00,sizeof(struct ipa_cmd)/256,sizeof(struct ipa_cmd)%256, + 0x00,0x00,0x00,0x40, +}; + +unsigned char WRITE_CCW[]={ + 0x01,CCW_FLAG_SLI,0,0, + 0,0,0,0 +}; + +unsigned char READ_CCW[]={ + 0x02,CCW_FLAG_SLI,0,0, + 0,0,0,0 +}; + + + + + + + + + + + + diff -Nru a/drivers/s390/net/qeth_mpc.h b/drivers/s390/net/qeth_mpc.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/s390/net/qeth_mpc.h Tue Jul 1 18:44:40 2003 @@ -0,0 +1,442 @@ +/* + * linux/drivers/s390/net/qeth_mpc.h + * + * Linux on zSeries OSA Express and HiperSockets support + * + * Copyright 2000,2003 IBM Corporation + * Author(s): Utz Bacher + * + */ +#ifndef __QETH_MPC_H__ +#define __QETH_MPC_H__ + +#define VERSION_QETH_MPC_H "$Revision: 1.15 $" + +#define QETH_IPA_TIMEOUT (card->ipa_timeout) +#define QETH_MPC_TIMEOUT 2000 +#define QETH_ADDR_TIMEOUT 1000 + +#define QETH_SETIP_RETRIES 2 + +#define IDX_ACTIVATE_SIZE 0x22 +#define CM_ENABLE_SIZE 0x63 +#define CM_SETUP_SIZE 0x64 +#define ULP_ENABLE_SIZE 0x6b +#define ULP_SETUP_SIZE 0x6c +#define DM_ACT_SIZE 0x55 + +#define QETH_MPC_TOKEN_LENGTH 4 +#define QETH_SEQ_NO_LENGTH 4 +#define QETH_IPA_SEQ_NO_LENGTH 2 + +#define QETH_TRANSPORT_HEADER_SEQ_NO(buffer) (buffer+4) +#define QETH_PDU_HEADER_SEQ_NO(buffer) (buffer+0x1c) +#define QETH_PDU_HEADER_ACK_SEQ_NO(buffer) (buffer+0x20) + +extern unsigned char IDX_ACTIVATE_READ[]; + +extern unsigned char IDX_ACTIVATE_WRITE[]; + +#define QETH_IDX_ACT_ISSUER_RM_TOKEN(buffer) (buffer+0x0c) +#define QETH_IDX_NO_PORTNAME_REQUIRED(buffer) ((buffer)[0x0b]&0x80) +#define QETH_IDX_ACT_FUNC_LEVEL(buffer) (buffer+0x10) +#define QETH_IDX_ACT_DATASET_NAME(buffer) (buffer+0x16) +#define QETH_IDX_ACT_QDIO_DEV_CUA(buffer) (buffer+0x1e) +#define QETH_IDX_ACT_QDIO_DEV_REALADDR(buffer) (buffer+0x20) + +#define QETH_IS_IDX_ACT_POS_REPLY(buffer) (((buffer)[0x08]&3)==2) + +#define QETH_IDX_REPLY_LEVEL(buffer) (buffer+0x12) +#define QETH_MCL_LENGTH 4 + +extern unsigned char CM_ENABLE[]; + +#define QETH_CM_ENABLE_ISSUER_RM_TOKEN(buffer) (buffer+0x2c) +#define QETH_CM_ENABLE_FILTER_TOKEN(buffer) (buffer+0x53) +#define QETH_CM_ENABLE_USER_DATA(buffer) (buffer+0x5b) + +#define QETH_CM_ENABLE_RESP_FILTER_TOKEN(buffer) (PDU_ENCAPSULATION(buffer)+ \ + 0x13) + +extern unsigned char CM_SETUP[]; + +#define QETH_CM_SETUP_DEST_ADDR(buffer) (buffer+0x2c) +#define QETH_CM_SETUP_CONNECTION_TOKEN(buffer) (buffer+0x51) +#define QETH_CM_SETUP_FILTER_TOKEN(buffer) (buffer+0x5a) + +#define QETH_CM_SETUP_RESP_DEST_ADDR(buffer) (PDU_ENCAPSULATION(buffer)+ \ + 0x1a) + +extern unsigned char ULP_ENABLE[]; + +#define QETH_ULP_ENABLE_LINKNUM(buffer) (buffer+0x61) +#define QETH_ULP_ENABLE_DEST_ADDR(buffer) (buffer+0x2c) +#define QETH_ULP_ENABLE_FILTER_TOKEN(buffer) (buffer+0x53) +#define QETH_ULP_ENABLE_PORTNAME_AND_LL(buffer) (buffer+0x62) + +#define QETH_ULP_ENABLE_RESP_FILTER_TOKEN(buffer) (PDU_ENCAPSULATION(buffer)+ \ + 0x13) +#define QETH_ULP_ENABLE_RESP_MAX_MTU(buffer) (PDU_ENCAPSULATION(buffer)+ 0x1f) +#define QETH_ULP_ENABLE_RESP_DIFINFO_LEN(buffer) (PDU_ENCAPSULATION(buffer)+ \ + 0x17) +#define QETH_ULP_ENABLE_RESP_LINK_TYPE(buffer) (PDU_ENCAPSULATION(buffer)+ \ + 0x2b) + +extern unsigned char ULP_SETUP[]; + +#define QETH_ULP_SETUP_DEST_ADDR(buffer) (buffer+0x2c) +#define QETH_ULP_SETUP_CONNECTION_TOKEN(buffer) (buffer+0x51) +#define QETH_ULP_SETUP_FILTER_TOKEN(buffer) (buffer+0x5a) +#define QETH_ULP_SETUP_CUA(buffer) (buffer+0x68) +#define QETH_ULP_SETUP_REAL_DEVADDR(buffer) (buffer+0x6a) + +#define QETH_ULP_SETUP_RESP_CONNECTION_TOKEN(buffer) (PDU_ENCAPSULATION \ + (buffer)+0x1a) + +extern unsigned char DM_ACT[]; + +#define QETH_DM_ACT_DEST_ADDR(buffer) (buffer+0x2c) +#define QETH_DM_ACT_CONNECTION_TOKEN(buffer) (buffer+0x51) + +#define IPA_CMD_STARTLAN 0x01 +#define IPA_CMD_STOPLAN 0x02 +#define IPA_CMD_SETIP 0xb1 +#define IPA_CMD_DELIP 0xb7 +#define IPA_CMD_QIPASSIST 0xb2 +#define IPA_CMD_SETASSPARMS 0xb3 +#define IPA_CMD_SETIPM 0xb4 +#define IPA_CMD_DELIPM 0xb5 +#define IPA_CMD_SETRTG 0xb6 +#define IPA_CMD_SETADAPTERPARMS 0xb8 +#define IPA_CMD_ADD_ADDR_ENTRY 0xc1 +#define IPA_CMD_DELETE_ADDR_ENTRY 0xc2 +#define IPA_CMD_CREATE_ADDR 0xc3 +#define IPA_CMD_DESTROY_ADDR 0xc4 +#define IPA_CMD_REGISTER_LOCAL_ADDR 0xd1 +#define IPA_CMD_UNREGISTER_LOCAL_ADDR 0xd2 + +#define INITIATOR_HOST 0 +#define INITIATOR_HYDRA 1 + +#define PRIM_VERSION_IPA 1 + +#define PROT_VERSION_SNA 1 /* hahaha */ +#define PROT_VERSION_IPv4 4 +#define PROT_VERSION_IPv6 6 + +#define OSA_ADDR_LEN 6 +#define IPA_SETADAPTERPARMS_IP_VERSION PROT_VERSION_IPv4 +#define SR_INFO_LEN 16 + +#define IPA_ARP_PROCESSING 0x00000001L +#define IPA_INBOUND_CHECKSUM 0x00000002L +#define IPA_OUTBOUND_CHECKSUM 0x00000004L +#define IPA_IP_FRAGMENTATION 0x00000008L +#define IPA_FILTERING 0x00000010L +#define IPA_IPv6 0x00000020L +#define IPA_MULTICASTING 0x00000040L +#define IPA_IP_REASSEMBLY 0x00000080L +#define IPA_QUERY_ARP_COUNTERS 0x00000100L +#define IPA_QUERY_ARP_ADDR_INFO 0x00000200L +#define IPA_SETADAPTERPARMS 0x00000400L +#define IPA_VLAN_PRIO 0x00000800L +#define IPA_PASSTHRU 0x00001000L +#define IPA_FULL_VLAN 0x00004000L +#define IPA_SOURCE_MAC_AVAIL 0x00010000L + +#define IPA_SETADP_QUERY_COMMANDS_SUPPORTED 0x01 +#define IPA_SETADP_ALTER_MAC_ADDRESS 0x02 +#define IPA_SETADP_ADD_DELETE_GROUP_ADDRESS 0x04 +#define IPA_SETADP_ADD_DELETE_FUNCTIONAL_ADDR 0x08 +#define IPA_SETADP_SET_ADDRESSING_MODE 0x10 +#define IPA_SETADP_SET_CONFIG_PARMS 0x20 +#define IPA_SETADP_SET_CONFIG_PARMS_EXTENDED 0x40 +#define IPA_SETADP_SET_BROADCAST_MODE 0x80 +#define IPA_SETADP_SEND_OSA_MESSAGE 0x0100 +#define IPA_SETADP_SET_SNMP_CONTROL 0x0200 +#define IPA_SETADP_READ_SNMP_PARMS 0x0400 +#define IPA_SETADP_WRITE_SNMP_PARMS 0x0800 +#define IPA_SETADP_QUERY_CARD_INFO 0x1000 + +#define CHANGE_ADDR_READ_MAC 0 +#define CHANGE_ADDR_REPLACE_MAC 1 +#define CHANGE_ADDR_ADD_MAC 2 +#define CHANGE_ADDR_DEL_MAC 4 +#define CHANGE_ADDR_RESET_MAC 8 +#define CHANGE_ADDR_READ_ADDR 0 +#define CHANGE_ADDR_ADD_ADDR 1 +#define CHANGE_ADDR_DEL_ADDR 2 +#define CHANGE_ADDR_FLUSH_ADDR_TABLE 4 + +/* we assumed, that the card is named card */ +#define qeth_is_supported(str) (card->ipa_supported&str) +#define qeth_is_supported6(str) (card->ipa6_supported&str) +#define qeth_is_adp_supported(str) (card->adp_supported&str) + +/* the same for all assist parms: */ +#define IPA_CMD_ASS_START 0x0001 +#define IPA_CMD_ASS_STOP 0x0002 + +#define IPA_CMD_ASS_CONFIGURE 0x0003 +#define IPA_CMD_ASS_ENABLE 0x0004 + +#define IPA_CMD_ASS_ARP_SET_NO_ENTRIES 0x0003 +#define IPA_CMD_ASS_ARP_QUERY_CACHE 0x0004 +#define IPA_CMD_ASS_ARP_ADD_ENTRY 0x0005 +#define IPA_CMD_ASS_ARP_REMOVE_ENTRY 0x0006 +#define IPA_CMD_ASS_ARP_FLUSH_CACHE 0x0007 +#define IPA_CMD_ASS_ARP_QUERY_INFO 0x0104 +#define IPA_CMD_ASS_ARP_QUERY_STATS 0x0204 + +#define IPA_CHECKSUM_ENABLE_MASK 0x001a + +#define IPA_CMD_ASS_FILTER_SET_TYPES 0x0003 + +#define IPA_CMD_ASS_IPv6_SET_FUNCTIONS 0x0003 + +#define IPA_REPLY_SUCCESS 0 +#define IPA_REPLY_FAILED 1 +#define IPA_REPLY_OPNOTSUPP 2 +#define IPA_REPLY_OPNOTSUPP2 4 +#define IPA_REPLY_NOINFO 8 + +#define IPA_SETIP_FLAGS 0 +#define IPA_SETIP_VIPA_FLAGS 1 +#define IPA_SETIP_TAKEOVER_FLAGS 2 + +#define VIPA_2_B_ADDED 0 +#define VIPA_ESTABLISHED 1 +#define VIPA_2_B_REMOVED 2 + +#define IPA_DELIP_FLAGS 0 + +#define IPA_SETADP_CMDSIZE 40 + +struct ipa_setadp_cmd { + __u32 supp_hw_cmds; + __u32 reserved1; + __u16 cmdlength; + __u16 reserved2; + __u32 command_code; + __u16 return_code; + __u8 frames_used_total; + __u8 frame_seq_no; + __u32 reserved3; + union { + struct { + __u32 no_lantypes_supp; + __u8 lan_type; + __u8 reserved1[3]; + __u32 supported_cmds; + __u8 reserved2[8]; + } query_cmds_supp; + struct { + __u32 cmd; + __u32 addr_size; + __u32 no_macs; + __u8 addr[OSA_ADDR_LEN]; + } change_addr; + __u32 mode; + } data; +}; + +struct ipa_cmd{ + __u8 command; + __u8 initiator; + __u16 seq_no; + __u16 return_code; + __u8 adapter_type; + __u8 rel_adapter_no; + __u8 prim_version_no; + __u8 param_count; + __u16 prot_version; + __u32 ipa_supported; + __u32 ipa_enabled; + union { + struct { + __u8 ip[4]; + __u8 netmask[4]; + __u32 flags; + } setdelip4; + struct { + __u8 ip[16]; + __u8 netmask[16]; + __u32 flags; + } setdelip6; + struct { + __u32 assist_no; + __u16 length; + __u16 command_code; + __u16 return_code; + __u8 number_of_replies; + __u8 seq_no; + union { + __u32 flags_32bit; + struct { + __u8 mac[6]; + __u8 reserved[2]; + __u8 ip[16]; + __u8 reserved2[32]; + } add_arp_entry; + __u8 ip[16]; + } data; + } setassparms; + struct { + __u8 mac[6]; + __u8 padding[2]; + __u8 ip6[12]; + __u8 ip4_6[4]; + } setdelipm; + struct { + __u8 type; + } setrtg; + struct ipa_setadp_cmd setadapterparms; + struct { + __u32 command; +#define ADDR_FRAME_TYPE_DIX 1 +#define ADDR_FRAME_TYPE_802_3 2 +#define ADDR_FRAME_TYPE_TR_WITHOUT_SR 0x10 +#define ADDR_FRAME_TYPE_TR_WITH_SR 0x20 + __u32 frame_type; + __u32 cmd_flags; + __u8 ip_addr[16]; + __u32 tag_field; + __u8 mac_addr[6]; + __u8 reserved[10]; + __u32 sr_len; + __u8 sr_info[SR_INFO_LEN]; + } add_addr_entry; + struct { + __u32 command; + __u32 cmd_flags; + __u8 ip_addr[16]; + __u32 tag_field; + } delete_addr_entry; + struct { + __u8 unique_id[8]; + } create_destroy_addr; + } data; +}__attribute__ ((packed)); + +#define QETH_IOC_MAGIC 0x22 +#define QETH_IOCPROC_OSAEINTERFACES _IOWR(QETH_IOC_MAGIC, 1, arg) +#define QETH_IOCPROC_INTERFACECHANGES _IOWR(QETH_IOC_MAGIC, 2, arg) + +#define SNMP_QUERY_CARD_INFO 0x00000002L +#define SNMP_REGISETER_MIB 0x00000004L +#define SNMP_GET_OID 0x00000010L +#define SNMP_SET_OID 0x00000011L +#define SNMP_GET_NEXT_OID 0x00000012L +#define SNMP_QUERY_ALERTS 0x00000020L +#define SNMP_SET_TRAP 0x00000021L + + +#define ARP_DATA_SIZE 3968 +#define ARP_FLUSH -3 +#define ARP_RETURNCODE_NOARPDATA -2 +#define ARP_RETURNCODE_ERROR -1 +#define ARP_RETURNCODE_SUCCESS 0 +#define ARP_RETURNCODE_LASTREPLY 1 + +#define SNMP_BASE_CMDLENGTH 44 +#define SNMP_SETADP_CMDLENGTH 16 +#define SNMP_REQUEST_DATA_OFFSET 16 + +struct snmp_ipa_setadp_cmd { + __u32 supp_hw_cmds; + __u32 reserved1; + __u16 cmdlength; + __u16 reserved2; + __u32 command_code; + __u16 return_code; + __u8 frames_used_total; + __u8 frame_seq_no; + __u32 reserved3; + __u8 snmp_token[16]; + union { + struct { + __u32 snmp_request; + __u32 snmp_interface; + __u32 snmp_returncode; + __u32 snmp_firmwarelevel; + __u32 snmp_seqno; + __u8 snmp_data[ARP_DATA_SIZE]; + } snmp_subcommand; + } data; +}__attribute__ ((packed)); + + +struct arp_cmd { + __u8 command; + __u8 initiator; + __u16 seq_no; + __u16 return_code; + __u8 adapter_type; + __u8 rel_adapter_no; + __u8 prim_version_no; + __u8 param_count; + __u16 prot_version; + __u32 ipa_supported; + __u32 ipa_enabled; + union { + struct { + __u32 assist_no; + __u16 length; + __u16 command_code; + __u16 return_code; + __u8 number_of_replies; + __u8 seq_no; + union { + struct { + __u16 tcpip_requestbitmask; + __u16 osa_setbitmask; + __u32 number_of_entries; + __u8 arp_data[ARP_DATA_SIZE]; + } queryarp_data; + } data; + } setassparms; + struct snmp_ipa_setadp_cmd setadapterparms; + } data; +}__attribute__ ((packed)); + + + +#define IPA_PDU_HEADER_SIZE 0x40 +#define QETH_IPA_PDU_LEN_TOTAL(buffer) (buffer+0x0e) +#define QETH_IPA_PDU_LEN_PDU1(buffer) (buffer+0x26) +#define QETH_IPA_PDU_LEN_PDU2(buffer) (buffer+0x2a) +#define QETH_IPA_PDU_LEN_PDU3(buffer) (buffer+0x3a) + +extern unsigned char IPA_PDU_HEADER[]; + +#define QETH_IPA_CMD_DEST_ADDR(buffer) (buffer+0x2c) + +#define PDU_ENCAPSULATION(buffer) \ + (buffer+ \ + *(buffer+ (*(buffer+0x0b))+ *(buffer+*(buffer+0x0b)+0x11) +0x07)) + +#define IS_IPA(buffer) ((buffer) && ( *(buffer+ ((*(buffer+0x0b))+4) )==0xc1) ) + +#define IS_IPA_REPLY(buffer) ( (buffer) && ( (*(PDU_ENCAPSULATION(buffer)+1))==INITIATOR_HOST ) ) + +#define CCW_NOP_CMD 0x03 +#define CCW_NOP_COUNT 1 + +extern unsigned char WRITE_CCW[]; + +extern unsigned char READ_CCW[]; + +#endif /* __QETH_MPC_H__ */ + + + + + + + + + + + + + diff -Nru a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c --- a/drivers/scsi/53c700.c Tue Jul 1 18:44:32 2003 +++ b/drivers/scsi/53c700.c Tue Jul 1 18:44:32 2003 @@ -133,7 +133,6 @@ #include #include #include -#include #include #include "scsi.h" @@ -564,8 +563,7 @@ { if(SCp->sc_data_direction != SCSI_DATA_NONE && SCp->sc_data_direction != SCSI_DATA_UNKNOWN) { - enum dma_data_direction direction = - (enum dma_data_direction)scsi_to_pci_dma_dir(SCp->sc_data_direction); + enum dma_data_direction direction = SCp->sc_data_direction; if(SCp->use_sg) { dma_unmap_sg(hostdata->dev, SCp->buffer, SCp->use_sg, direction); @@ -1842,7 +1840,7 @@ } /* now build the scatter gather list */ - direction = (enum dma_data_direction)scsi_to_pci_dma_dir(SCp->sc_data_direction); + direction = SCp->sc_data_direction; if(move_ins != 0) { int i; int sg_count; @@ -2039,8 +2037,15 @@ return 0; } +/* NULL exit routine to keep modutils happy */ +STATIC void __exit +NCR_700_exit(void) +{ +} + EXPORT_SYMBOL(NCR_700_detect); EXPORT_SYMBOL(NCR_700_release); EXPORT_SYMBOL(NCR_700_intr); module_init(NCR_700_init); +module_exit(NCR_700_exit); diff -Nru a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig --- a/drivers/scsi/Kconfig Tue Jul 1 18:44:37 2003 +++ b/drivers/scsi/Kconfig Tue Jul 1 18:44:37 2003 @@ -1,3 +1,27 @@ +menu "SCSI device support" + +config SCSI + tristate "SCSI device support" + ---help--- + If you want to use a SCSI hard disk, SCSI tape drive, SCSI CD-ROM or + any other SCSI device under Linux, say Y and make sure that you know + the name of your SCSI host adapter (the card inside your computer + that "speaks" the SCSI protocol, also called SCSI controller), + because you will be asked for it. + + You also need to say Y here if you have a device which speaks + the SCSI protocol. Examples of this include the parallel port + version of the IOMEGA ZIP drive, USB storage devices, Fibre + Channel, FireWire storage and the IDE-SCSI emulation driver. + + This driver is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called scsi_mod. If you want to compile it as + a module, say M here and read and + . However, do not compile this as a + module if your root file system (the one containing the directory /) + is located on a SCSI device. + comment "SCSI support type (disk, tape, CD-ROM)" depends on SCSI @@ -5,9 +29,10 @@ tristate "SCSI disk support" depends on SCSI ---help--- - If you want to use a SCSI hard disk or the SCSI or parallel port - version of the IOMEGA ZIP drive under Linux, say Y and read the - SCSI-HOWTO, the Disk-HOWTO and the Multi-Disk-HOWTO, available from + If you want to use SCSI hard disks, Fibre Channel disks, + USB storage or the SCSI or parallel port version of + the IOMEGA ZIP drive, say Y and read the SCSI-HOWTO, + the Disk-HOWTO and the Multi-Disk-HOWTO, available from . This is NOT for SCSI CD-ROMs. @@ -65,10 +90,10 @@ tristate "SCSI CDROM support" depends on SCSI ---help--- - If you want to use a SCSI CD-ROM under Linux, say Y and read the - SCSI-HOWTO and the CD-ROM-HOWTO at - . Also make sure to say Y - or M to "ISO 9660 CD-ROM file system support" later. + If you want to use a SCSI or FireWire CD-ROM under Linux, + say Y and read the SCSI-HOWTO and the CDROM-HOWTO at + . Also make sure to say + Y or M to "ISO 9660 CD-ROM file system support" later. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). @@ -953,26 +978,16 @@ used on the add-in Bluefish, Barracuda & Shrike SCSI cards. Say Y here if you have one of these machines or cards. -config SCSI_NCR53C8XX - tristate "NCR53C8XX SCSI support" - depends on PCI && SCSI_SYM53C8XX_2!=y && SCSI_ZALON!=y && SCSI - ---help--- - This is the BSD ncr driver adapted to Linux for the NCR53C8XX family - of PCI-SCSI controllers. This driver supports parity checking, - tagged command queuing and fast synchronous data transfers up to 80 - MB/s with wide FAST-40 LVD devices and controllers. - - Recent versions of the 53C8XX chips are better supported by the - option "SYM53C8XX SCSI support", below. - - Note: there is yet another driver for the 53c8xx family of - controllers ("NCR53c7,8xx SCSI support" above). If you want to use - them both, you need to say M to both and build them as modules, but - only one may be active at a time. If you have a 53c8xx board, you - probably do not want to use the "NCR53c7,8xx SCSI support". +config SCSI_NCR_Q720 + tristate "NCR Quad 720 MCA SCSI support" + depends on MCA && SCSI + help + This is a driver for the MicroChannel Quad 720 card produced by + NCR and commonly used in 345x/35xx/4100 class machines. It always + tries to negotiate sync and uses tag command queueing. - Please read for more - information. + Unless you have an NCR manufactured machine, the chances are that + you do not have this SCSI card, so say N. config SCSI_SYM53C8XX tristate "SYM53C8XX SCSI support" @@ -1002,8 +1017,8 @@ information. config SCSI_NCR53C8XX_DEFAULT_TAGS - int "default tagged command queue depth" - depends on PCI && SCSI_SYM53C8XX_2!=y && (SCSI_NCR53C8XX || SCSI_SYM53C8XX || SCSI_ZALON) + int " default tagged command queue depth" + depends on (SCSI_SYM53C8XX || SCSI_ZALON || SCSI_NCR_Q720) default "8" ---help--- "Tagged command queuing" is a feature of SCSI-2 which improves @@ -1028,8 +1043,8 @@ There is no safe option other than using good SCSI devices. config SCSI_NCR53C8XX_MAX_TAGS - int "maximum number of queued commands" - depends on PCI && SCSI_SYM53C8XX_2!=y && (SCSI_NCR53C8XX || SCSI_SYM53C8XX || SCSI_ZALON) + int " maximum number of queued commands" + depends on (SCSI_SYM53C8XX || SCSI_ZALON || SCSI_NCR_Q720) default "32" ---help--- This option allows you to specify the maximum number of commands @@ -1045,8 +1060,8 @@ There is no safe option and the default answer is recommended. config SCSI_NCR53C8XX_SYNC - int "synchronous transfers frequency in MHz" - depends on PCI && SCSI_SYM53C8XX_2!=y && (SCSI_NCR53C8XX || SCSI_SYM53C8XX || SCSI_ZALON) + int " synchronous transfers frequency in MHz" + depends on (SCSI_SYM53C8XX || SCSI_ZALON || SCSI_NCR_Q720) default "20" ---help--- The SCSI Parallel Interface-2 Standard defines 5 classes of transfer @@ -1079,8 +1094,8 @@ terminations and SCSI conformant devices. config SCSI_NCR53C8XX_PROFILE - bool "enable profiling" - depends on PCI && SCSI_SYM53C8XX_2!=y && (SCSI_NCR53C8XX || SCSI_SYM53C8XX || SCSI_ZALON) + bool " enable profiling" + depends on (SCSI_SYM53C8XX || SCSI_ZALON || SCSI_NCR_Q720) help This option allows you to enable profiling information gathering. These statistics are not very accurate due to the low frequency @@ -1090,8 +1105,8 @@ The normal answer therefore is N. config SCSI_NCR53C8XX_IOMAPPED - bool "use normal IO" - depends on PCI && SCSI_SYM53C8XX_2!=y && (SCSI_NCR53C8XX || SCSI_SYM53C8XX) && !SCSI_ZALON + bool " use normal IO" + depends on SCSI_SYM53C8XX && !(SCSI_ZALON || SCSI_NCR_Q720) help If you say Y here, the driver will use normal IO, as opposed to memory mapped IO. Memory mapped IO has less latency than normal IO @@ -1103,8 +1118,8 @@ related problems. config SCSI_NCR53C8XX_PQS_PDS - bool "include support for the NCR PQS/PDS SCSI card" - depends on (SCSI_NCR53C8XX || SCSI_SYM53C8XX) && SCSI_SYM53C8XX + bool " include support for the NCR PQS/PDS SCSI card" + depends on SCSI_SYM53C8XX help Say Y here if you have a special SCSI adapter produced by NCR corporation called a PCI Quad SCSI or PCI Dual SCSI. You do not need @@ -1115,8 +1130,8 @@ The common answer here is N, but answering Y is safe. config SCSI_NCR53C8XX_NO_DISCONNECT - bool "not allow targets to disconnect" - depends on PCI && SCSI_SYM53C8XX_2!=y && (SCSI_NCR53C8XX || SCSI_SYM53C8XX || SCSI_ZALON) && SCSI_NCR53C8XX_DEFAULT_TAGS=0 + bool " not allow targets to disconnect" + depends on (SCSI_SYM53C8XX || SCSI_ZALON || SCSI_NCR_Q720) && SCSI_NCR53C8XX_DEFAULT_TAGS=0 help This option is only provided for safety if you suspect some SCSI device of yours to not support properly the target-disconnect @@ -1125,8 +1140,8 @@ than 1 device on a SCSI bus. The normal answer therefore is N. config SCSI_NCR53C8XX_SYMBIOS_COMPAT - bool "assume boards are SYMBIOS compatible (EXPERIMENTAL)" - depends on PCI && SCSI_SYM53C8XX_2!=y && (SCSI_NCR53C8XX || SCSI_SYM53C8XX || SCSI_ZALON) && EXPERIMENTAL + bool " assume boards are SYMBIOS compatible (EXPERIMENTAL)" + depends on (SCSI_SYM53C8XX || SCSI_ZALON || SCSI_NCR_Q720 ) && EXPERIMENTAL ---help--- This option allows you to enable some features depending on GPIO wiring. These General Purpose Input/Output pins can be used for @@ -1823,3 +1838,4 @@ source "drivers/scsi/pcmcia/Kconfig" +endmenu diff -Nru a/drivers/scsi/Makefile b/drivers/scsi/Makefile --- a/drivers/scsi/Makefile Tue Jul 1 18:44:37 2003 +++ b/drivers/scsi/Makefile Tue Jul 1 18:44:37 2003 @@ -68,6 +68,7 @@ obj-$(CONFIG_SCSI_GENERIC_NCR5380_MMIO) += g_NCR5380_mmio.o obj-$(CONFIG_SCSI_NCR53C406A) += NCR53c406a.o obj-$(CONFIG_SCSI_NCR_D700) += NCR_D700.o 53c700.o +obj-$(CONFIG_SCSI_NCR_Q720) += NCR_Q720_mod.o obj-$(CONFIG_SCSI_SYM53C416) += sym53c416.o obj-$(CONFIG_SCSI_QLOGIC_FAS) += qlogicfas.o obj-$(CONFIG_SCSI_QLOGIC_ISP) += qlogicisp.o @@ -81,7 +82,6 @@ obj-$(CONFIG_SCSI_DTC3280) += dtc.o obj-$(CONFIG_SCSI_SYM53C8XX_2) += sym53c8xx_2/ obj-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o -obj-$(CONFIG_SCSI_NCR53C8XX) += ncr53c8xx.o obj-$(CONFIG_SCSI_ZALON) += zalon7xx.o obj-$(CONFIG_SCSI_EATA_PIO) += eata_pio.o obj-$(CONFIG_SCSI_7000FASST) += wd7000.o @@ -133,7 +133,17 @@ sr_mod-objs := sr.o sr_ioctl.o sr_vendor.o initio-objs := ini9100u.o i91uscsi.o a100u2w-objs := inia100.o i60uscsi.o +ncr53c8xx-flags-$(CONFIG_SCSI_ZALON) \ + := -DCONFIG_NCR53C8XX_PREFETCH \ + -DCONFIG_SCSI_NCR53C8XX_NO_WORD_TRANSFERS \ + -DCONFIG_SCSI_NCR53C8XX_NO_NVRAM \ + -DSCSI_NCR_BIG_ENDIAN -DSIMULATED_INTFLY +ncr53c8xx-flags-$(CONFIG_SCSI_NCR_Q720) \ + := -DCONFIG_SCSI_NCR53C8XX_NO_NVRAM \ + -DSIMULATED_INTFLY +CFLAGS_ncr53c8xx.o := $(ncr53c8xx-flags-y) $(ncr53c8xx-flags-m) zalon7xx-objs := zalon.o ncr53c8xx.o +NCR_Q720_mod-objs := NCR_Q720.o ncr53c8xx.o cpqfc-objs := cpqfcTSinit.o cpqfcTScontrol.o cpqfcTSi2c.o \ cpqfcTSworker.o cpqfcTStrigger.o diff -Nru a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c --- a/drivers/scsi/NCR53C9x.c Tue Jul 1 18:44:33 2003 +++ b/drivers/scsi/NCR53C9x.c Tue Jul 1 18:44:33 2003 @@ -893,7 +893,7 @@ int esp_proc_info(struct Scsi_Host *shost, char *buffer, char **start, off_t offset, int length, int inout) { - struct NCR_ESP *esp = (struct NCR_ESP *) SCpnt->device->host->hostdata; + struct NCR_ESP *esp = (struct NCR_ESP *)shost->hostdata; if(inout) return -EINVAL; /* not yet */ diff -Nru a/drivers/scsi/NCR_Q720.c b/drivers/scsi/NCR_Q720.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/scsi/NCR_Q720.c Tue Jul 1 18:44:40 2003 @@ -0,0 +1,354 @@ +/* -*- mode: c; c-basic-offset: 8 -*- */ + +/* NCR Quad 720 MCA SCSI Driver + * + * Copyright (C) 2003 by James.Bottomley@HansenPartnership.com + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "scsi.h" +#include "hosts.h" + +#include "ncr53c8xx.h" + +#include "NCR_Q720.h" + +static ncr_chip q720_chip __initdata = { + .device_id = PSEUDO_720_ID, + .revision_id = 0x0f, + .name = "720", + .burst_max = 3, + .offset_max = 8, + .nr_divisor = 4, + .features = FE_WIDE | FE_DIFF | FE_VARCLK, +}; + +MODULE_AUTHOR("James Bottomley"); +MODULE_DESCRIPTION("NCR Quad 720 SCSI Driver"); +MODULE_LICENSE("GPL"); + +#define NCR_Q720_VERSION "0.9" + +/* We needs this helper because we have up to four hosts per struct device */ +struct NCR_Q720_private { + struct device *dev; + __u32 mem_base; + __u32 phys_mem_base; + __u32 mem_size; + __u8 irq; + __u8 siops; + __u8 irq_enable; + struct Scsi_Host *hosts[4]; +}; + +Scsi_Host_Template NCR_Q720_tpnt = { + .module = THIS_MODULE, + .proc_name = "NCR_Q720", +}; + +static irqreturn_t +NCR_Q720_intr(int irq, void *data, struct pt_regs * regs) +{ + struct NCR_Q720_private *p = (struct NCR_Q720_private *)data; + __u8 sir = (readb(p->mem_base + 0x0d) & 0xf0) >> 4; + __u8 siop; + + sir |= ~p->irq_enable; + + if(sir == 0xff) + return IRQ_NONE; + + + while((siop = ffz(sir)) < p->siops) { + sir |= 1<hosts[siop], regs); + } + return IRQ_HANDLED; +} + +static int __init +NCR_Q720_probe_one(struct NCR_Q720_private *p, int siop, + int irq, int slot, __u32 paddr, __u32 vaddr) +{ + ncr_device device; + __u8 scsi_id; + static int unit = 0; + __u8 scsr1 = readb(vaddr + NCR_Q720_SCSR_OFFSET + 1); + __u8 differential = readb(vaddr + NCR_Q720_SCSR_OFFSET) & 0x20; + __u8 version; + + scsi_id = scsr1 >> 4; + /* enable burst length 16 (FIXME: should allow this) */ + scsr1 |= 0x02; + /* force a siop reset */ + scsr1 |= 0x04; + writeb(scsr1, vaddr + NCR_Q720_SCSR_OFFSET + 1); + udelay(10); + version = readb(vaddr + 0x18) >> 4; + + memset(&device, 0, sizeof(ncr_device)); + /* Initialise ncr_device structure with items required by ncr_attach. */ + device.chip = q720_chip; + device.chip.revision_id = version; + device.host_id = scsi_id; + device.dev = p->dev; + device.slot.base = paddr; + device.slot.base_c = paddr; + device.slot.base_v = vaddr; + device.slot.irq = irq; + device.differential = differential ? 2 : 0; + printk("Q720 probe unit %d (siop%d) at 0x%lx, diff = %d, vers = %d\n", unit, siop, + (unsigned long)paddr, differential, version); + + p->hosts[siop] = ncr_attach(&NCR_Q720_tpnt, unit++, &device); + + if (!p->hosts[siop]) + goto fail; + + p->irq_enable |= (1<hosts[siop], p->dev); + + return 0; + + fail: + return -ENODEV; +} + +/* Detect a Q720 card. Note, because of the setup --- the chips are + * essentially connectecd to the MCA bus independently, it is easier + * to set them up as two separate host adapters, rather than one + * adapter with two channels */ +static int __init +NCR_Q720_probe(struct device *dev) +{ + struct NCR_Q720_private *p; + static int banner = 1; + struct mca_device *mca_dev = to_mca_device(dev); + int slot = mca_dev->slot; + int found = 0; + int irq, i, siops; + __u8 pos2, pos4, asr2, asr9, asr10; + __u16 io_base; + __u32 base_addr, mem_size; + __u32 mem_base; + + p = kmalloc(sizeof(*p), GFP_KERNEL); + if (!p) + return -ENOMEM; + + memset(p, 0, sizeof(*p)); + pos2 = mca_device_read_pos(mca_dev, 2); + /* enable device */ + pos2 |= NCR_Q720_POS2_BOARD_ENABLE | NCR_Q720_POS2_INTERRUPT_ENABLE; + mca_device_write_pos(mca_dev, 2, pos2); + + io_base = (pos2 & NCR_Q720_POS2_IO_MASK) << NCR_Q720_POS2_IO_SHIFT; + + + if(banner) { + printk(KERN_NOTICE "NCR Q720: Driver Version " NCR_Q720_VERSION "\n" + "NCR Q720: Copyright (c) 2003 by James.Bottomley@HansenPartnership.com\n" + "NCR Q720:\n"); + banner = 0; + } + io_base = mca_device_transform_ioport(mca_dev, io_base); + + /* OK, this is phase one of the bootstrap, we now know the + * I/O space base address. All the configuration registers + * are mapped here (including pos) */ + + /* sanity check I/O mapping */ + i = inb(io_base) | (inb(io_base+1)<<8); + if(i != NCR_Q720_MCA_ID) { + printk(KERN_ERR "NCR_Q720, adapter failed to I/O map registers correctly at 0x%x(0x%x)\n", io_base, i); + return -ENODEV; + } + + /* Phase II, find the ram base and memory map the board register */ + pos4 = inb(io_base + 4); + /* enable streaming data */ + pos4 |= 0x01; + outb(pos4, io_base + 4); + base_addr = (pos4 & 0x7e) << 20; + base_addr += (pos4 & 0x80) << 23; + asr10 = inb(io_base + 0x12); + base_addr += (asr10 & 0x80) << 24; + base_addr += (asr10 & 0x70) << 23; + + /* OK, got the base addr, now we need to find the ram size, + * enable and map it */ + asr9 = inb(io_base + 0x11); + i = (asr9 & 0xc0) >> 6; + if(i == 0) + mem_size = 1024; + else + mem_size = 1 << (19 + i); + + /* enable the sram mapping */ + asr9 |= 0x20; + + /* disable the rom mapping */ + asr9 &= ~0x10; + + outb(asr9, io_base + 0x11); + + if(!request_mem_region(base_addr, mem_size, "NCR_Q720")) { + printk(KERN_ERR "NCR_Q720: Failed to claim memory region 0x%lx\n-0x%lx", + (unsigned long)base_addr, + (unsigned long)(base_addr + mem_size)); + goto out_free; + } + + mem_base = (__u32)ioremap(base_addr, mem_size); + + /* now also enable accesses in asr 2 */ + asr2 = inb(io_base + 0x0a); + + asr2 |= 0x01; + + outb(asr2, io_base + 0x0a); + + /* get the number of SIOPs (this should be 2 or 4) */ + siops = ((asr2 & 0xe0) >> 5) + 1; + + /* sanity check mapping (again) */ + i = readw(mem_base); + if(i != NCR_Q720_MCA_ID) { + printk(KERN_ERR "NCR_Q720, adapter failed to memory map registers correctly at 0x%lx(0x%x)\n", (unsigned long)base_addr, i); + goto out_release; + } + + irq = readb(mem_base + 5) & 0x0f; + + + /* now do the bus related transforms */ + irq = mca_device_transform_irq(mca_dev, irq); + + printk(KERN_NOTICE "NCR Q720: found in slot %d irq = %d mem base = 0x%lx siops = %d\n", slot, irq, (unsigned long)base_addr, siops); + printk(KERN_NOTICE "NCR Q720: On board ram %dk\n", mem_size/1024); + + p->dev = dev; + p->mem_base = mem_base; + p->phys_mem_base = base_addr; + p->mem_size = mem_size; + p->irq = irq; + p->siops = siops; + + if (request_irq(irq, NCR_Q720_intr, SA_SHIRQ, "NCR_Q720", p)) { + printk(KERN_ERR "NCR_Q720: request irq %d failed\n", irq); + goto out_release; + } + /* disable all the siop interrupts */ + for(i = 0; i < siops; i++) { + __u32 reg_scsr1 = mem_base + NCR_Q720_CHIP_REGISTER_OFFSET + + i*NCR_Q720_SIOP_SHIFT + NCR_Q720_SCSR_OFFSET + 1; + __u8 scsr1 = readb(reg_scsr1); + scsr1 |= 0x01; + writeb(scsr1, reg_scsr1); + } + + /* plumb in all 720 chips */ + for (i = 0; i < siops; i++) { + __u32 siop_v_base = mem_base + NCR_Q720_CHIP_REGISTER_OFFSET + + i*NCR_Q720_SIOP_SHIFT; + __u32 siop_p_base = base_addr + NCR_Q720_CHIP_REGISTER_OFFSET + + i*NCR_Q720_SIOP_SHIFT; + __u16 port = io_base + NCR_Q720_CHIP_REGISTER_OFFSET + + i*NCR_Q720_SIOP_SHIFT; + int err; + + outb(0xff, port + 0x40); + outb(0x07, port + 0x41); + if ((err = NCR_Q720_probe_one(p, i, irq, slot, + siop_p_base, siop_v_base)) != 0) + printk("Q720: SIOP%d: probe failed, error = %d\n", + i, err); + else + found++; + } + + if (!found) { + kfree(p); + return -ENODEV; + } + + mca_device_set_claim(mca_dev, 1); + strlcpy(dev->name, "NCR_Q720", sizeof(dev->name)); + dev_set_drvdata(dev, p); + + return 0; + + out_release: + iounmap((void *)mem_base); + release_mem_region(base_addr, mem_size); + out_free: + kfree(p); + + return -ENODEV; +} + +static void __exit +NCR_Q720_remove_one(struct Scsi_Host *host) +{ + scsi_remove_host(host); + ncr53c8xx_release(host); +} + +static int __exit +NCR_Q720_remove(struct device *dev) +{ + struct NCR_Q720_private *p = dev_get_drvdata(dev); + int i; + + for (i = 0; i < p->siops; i++) + if(p->hosts[i]) + NCR_Q720_remove_one(p->hosts[i]); + + iounmap((void *)p->mem_base); + release_mem_region(p->phys_mem_base, p->mem_size); + free_irq(p->irq, p); + kfree(p); + return 0; +} + +static short NCR_Q720_id_table[] = { NCR_Q720_MCA_ID, 0 }; + +struct mca_driver NCR_Q720_driver = { + .id_table = NCR_Q720_id_table, + .driver = { + .name = "NCR_Q720", + .bus = &mca_bus_type, + .probe = NCR_Q720_probe, + .remove = __devexit_p(NCR_Q720_remove), + }, +}; + +static int __init +NCR_Q720_init(void) +{ + return mca_register_driver(&NCR_Q720_driver); +} + +static void __exit +NCR_Q720_exit(void) +{ + mca_unregister_driver(&NCR_Q720_driver); + //scsi_sysfs_release_attributes(&NCR_Q720_driver_template); +} + +module_init(NCR_Q720_init); +module_exit(NCR_Q720_exit); diff -Nru a/drivers/scsi/NCR_Q720.h b/drivers/scsi/NCR_Q720.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/scsi/NCR_Q720.h Tue Jul 1 18:44:39 2003 @@ -0,0 +1,28 @@ +/* -*- mode: c; c-basic-offset: 8 -*- */ + +/* NCR Quad 720 MCA SCSI Driver + * + * Copyright (C) 2003 by James.Bottomley@HansenPartnership.com + */ + +#ifndef _NCR_Q720_H +#define _NCR_Q720_H + +/* The MCA identifier */ +#define NCR_Q720_MCA_ID 0x0720 + +#define NCR_Q720_CLOCK_MHZ 30 + +#define NCR_Q720_POS2_BOARD_ENABLE 0x01 +#define NCR_Q720_POS2_INTERRUPT_ENABLE 0x02 +#define NCR_Q720_POS2_PARITY_DISABLE 0x04 +#define NCR_Q720_POS2_IO_MASK 0xf8 +#define NCR_Q720_POS2_IO_SHIFT 8 + +#define NCR_Q720_CHIP_REGISTER_OFFSET 0x200 +#define NCR_Q720_SCSR_OFFSET 0x070 +#define NCR_Q720_SIOP_SHIFT 0x080 + +#endif + + diff -Nru a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c --- a/drivers/scsi/aacraid/aachba.c Tue Jul 1 18:44:34 2003 +++ b/drivers/scsi/aacraid/aachba.c Tue Jul 1 18:44:34 2003 @@ -39,25 +39,6 @@ #include "aacraid.h" -/* SCSI Commands */ -/* TODO dmb - use the ones defined in include/scsi/scsi.h*/ -#define SS_TEST 0x00 /* Test unit ready */ -#define SS_REZERO 0x01 /* Rezero unit */ -#define SS_REQSEN 0x03 /* Request Sense */ -#define SS_REASGN 0x07 /* Reassign blocks */ -#define SS_READ 0x08 /* Read 6 */ -#define SS_WRITE 0x0A /* Write 6 */ -#define SS_INQUIR 0x12 /* inquiry */ -#define SS_ST_SP 0x1B /* Start/Stop unit */ -#define SS_LOCK 0x1E /* prevent/allow medium removal */ -#define SS_RESERV 0x16 /* Reserve */ -#define SS_RELES 0x17 /* Release */ -#define SS_MODESEN 0x1A /* Mode Sense 6 */ -#define SS_RDCAP 0x25 /* Read Capacity */ -#define SM_READ 0x28 /* Read 10 */ -#define SM_WRITE 0x2A /* Write 10 */ -#define SS_SEEK 0x2B /* Seek */ - /* values for inqd_pdt: Peripheral device type in plain English */ #define INQD_PDT_DA 0x00 /* Direct-access (DISK) device */ #define INQD_PDT_PROC 0x03 /* Processor device */ @@ -583,10 +564,10 @@ scsi_to_pci_dma_dir(scsicmd->sc_data_direction)); readreply = (struct aac_read_reply *)fib_data(fibptr); if (le32_to_cpu(readreply->status) == ST_OK) - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; else { printk(KERN_WARNING "read_callback: read failed, status = %d\n", readreply->status); - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION; + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION; set_sense((u8 *) &sense_data[cid], SENKEY_HW_ERR, SENCODE_INTERNAL_TARGET_FAILURE, @@ -628,10 +609,10 @@ writereply = (struct aac_write_reply *) fib_data(fibptr); if (le32_to_cpu(writereply->status) == ST_OK) - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; else { printk(KERN_WARNING "write_callback: write failed, status = %d\n", writereply->status); - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION; + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION; set_sense((u8 *) &sense_data[cid], SENKEY_HW_ERR, SENCODE_INTERNAL_TARGET_FAILURE, @@ -658,7 +639,7 @@ /* * Get block address and transfer length */ - if (scsicmd->cmnd[0] == SS_READ) /* 6 byte command */ + if (scsicmd->cmnd[0] == READ_6) /* 6 byte command */ { dprintk((KERN_DEBUG "aachba: received a read(6) command on target %d.\n", cid)); @@ -748,7 +729,7 @@ /* * For some reason, the Fib didn't queue, return QUEUE_FULL */ - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | QUEUE_FULL; + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_TASK_SET_FULL; aac_io_done(scsicmd); fib_complete(cmd_fibcontext); fib_free(cmd_fibcontext); @@ -768,7 +749,7 @@ /* * Get block address and transfer length */ - if (scsicmd->cmnd[0] == SS_WRITE) /* 6 byte command */ + if (scsicmd->cmnd[0] == WRITE_6) /* 6 byte command */ { lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3]; count = scsicmd->cmnd[4]; @@ -854,7 +835,7 @@ /* * For some reason, the Fib didn't queue, return QUEUE_FULL */ - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | QUEUE_FULL; + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_TASK_SET_FULL; aac_io_done(scsicmd); fib_complete(cmd_fibcontext); @@ -905,9 +886,9 @@ */ if (fsa_dev_ptr->valid[cid] == 0) { switch (scsicmd->cmnd[0]) { - case SS_INQUIR: - case SS_RDCAP: - case SS_TEST: + case INQUIRY: + case READ_CAPACITY: + case TEST_UNIT_READY: spin_unlock_irq(host->host_lock); probe_container(dev, cid); spin_lock_irq(host->host_lock); @@ -942,11 +923,11 @@ /* * else Command for the controller itself */ - else if ((scsicmd->cmnd[0] != SS_INQUIR) && /* only INQUIRY & TUR cmnd supported for controller */ - (scsicmd->cmnd[0] != SS_TEST)) + else if ((scsicmd->cmnd[0] != INQUIRY) && /* only INQUIRY & TUR cmnd supported for controller */ + (scsicmd->cmnd[0] != TEST_UNIT_READY)) { dprintk((KERN_WARNING "Only INQUIRY & TUR command supported for controller, rcvd = 0x%x.\n", scsicmd->cmnd[0])); - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION; + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION; set_sense((u8 *) &sense_data[cid], SENKEY_ILLEGAL, SENCODE_INVALID_COMMAND, @@ -958,7 +939,7 @@ /* Handle commands here that don't really require going out to the adapter */ switch (scsicmd->cmnd[0]) { - case SS_INQUIR: + case INQUIRY: { struct inquiry_data *inq_data_ptr; @@ -981,11 +962,11 @@ inq_data_ptr->inqd_pdt = INQD_PDT_PROC; /* Processor device */ else inq_data_ptr->inqd_pdt = INQD_PDT_DA; /* Direct/random access device */ - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; __aac_io_done(scsicmd); return 0; } - case SS_RDCAP: + case READ_CAPACITY: { int capacity; char *cp; @@ -1002,18 +983,34 @@ cp[6] = 2; cp[7] = 0; - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; __aac_io_done(scsicmd); return 0; } - case SS_MODESEN: + case MODE_SENSE: { char *mode_buf; dprintk((KERN_DEBUG "MODE SENSE command.\n")); mode_buf = scsicmd->request_buffer; + mode_buf[0] = 3; /* Mode data length */ + mode_buf[1] = 0; /* Medium type - default */ + mode_buf[2] = 0; /* Device-specific param, bit 8: 0/1 = write enabled/protected */ + mode_buf[3] = 0; /* Block descriptor length */ + + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; + __aac_io_done(scsicmd); + + return 0; + } + case MODE_SENSE_10: + { + char *mode_buf; + + dprintk((KERN_DEBUG "MODE SENSE 10 byte command.\n")); + mode_buf = scsicmd->request_buffer; mode_buf[0] = 0; /* Mode data length (MSB) */ mode_buf[1] = 6; /* Mode data length (LSB) */ mode_buf[2] = 0; /* Medium type - default */ @@ -1023,48 +1020,48 @@ mode_buf[6] = 0; /* Block descriptor length (MSB) */ mode_buf[7] = 0; /* Block descriptor length (LSB) */ - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; __aac_io_done(scsicmd); return 0; } - case SS_REQSEN: + case REQUEST_SENSE: dprintk((KERN_DEBUG "REQUEST SENSE command.\n")); memcpy(scsicmd->sense_buffer, &sense_data[cid], sizeof (struct sense_data)); memset(&sense_data[cid], 0, sizeof (struct sense_data)); - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; __aac_io_done(scsicmd); return (0); - case SS_LOCK: + case ALLOW_MEDIUM_REMOVAL: dprintk((KERN_DEBUG "LOCK command.\n")); if (scsicmd->cmnd[4]) fsa_dev_ptr->locked[cid] = 1; else fsa_dev_ptr->locked[cid] = 0; - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; __aac_io_done(scsicmd); return 0; /* * These commands are all No-Ops */ - case SS_TEST: - case SS_RESERV: - case SS_RELES: - case SS_REZERO: - case SS_REASGN: - case SS_SEEK: - case SS_ST_SP: - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD; + case TEST_UNIT_READY: + case RESERVE: + case RELEASE: + case REZERO_UNIT: + case REASSIGN_BLOCKS: + case SEEK_10: + case START_STOP: + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; __aac_io_done(scsicmd); return (0); } switch (scsicmd->cmnd[0]) { - case SS_READ: - case SM_READ: + case READ_6: + case READ_10: /* * Hack to keep track of ordinal number of the device that * corresponds to a container. Needed to convert @@ -1081,8 +1078,8 @@ spin_lock_irq(host->host_lock); return ret; - case SS_WRITE: - case SM_WRITE: + case WRITE_6: + case WRITE_10: spin_unlock_irq(host->host_lock); ret = aac_write(scsicmd, cid); spin_lock_irq(host->host_lock); @@ -1092,7 +1089,7 @@ * Unhandled commands */ printk(KERN_WARNING "Unhandled SCSI Command: 0x%x.\n", scsicmd->cmnd[0]); - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION; + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION; set_sense((u8 *) &sense_data[cid], SENKEY_ILLEGAL, SENCODE_INVALID_COMMAND, ASENCODE_INVALID_COMMAND, 0, 0, 0, 0); @@ -1250,7 +1247,7 @@ printk(KERN_WARNING "aac_srb_callback: srb failed, status = %d\n", le32_to_cpu(srbreply->status)); len = (srbreply->sense_data_size > sizeof(scsicmd->sense_buffer))? sizeof(scsicmd->sense_buffer):srbreply->sense_data_size; - scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION; + scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION; memcpy(scsicmd->sense_buffer, srbreply->sense_data, len); } @@ -1373,7 +1370,7 @@ } if (le32_to_cpu(srbreply->scsi_status) == 0x02 ){ // Check Condition int len; - scsicmd->result |= CHECK_CONDITION; + scsicmd->result |= SAM_STAT_CHECK_CONDITION; len = (srbreply->sense_data_size > sizeof(scsicmd->sense_buffer))? sizeof(scsicmd->sense_buffer):srbreply->sense_data_size; printk(KERN_WARNING "aac_srb_callback: check condition, status = %d len=%d\n", le32_to_cpu(srbreply->status), len); @@ -1501,7 +1498,7 @@ /* * For some reason, the Fib didn't queue, return QUEUE_FULL */ - scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | QUEUE_FULL; + scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_TASK_SET_FULL; __aac_io_done(scsicmd); fib_complete(cmd_fibcontext); diff -Nru a/drivers/scsi/aha1740.c b/drivers/scsi/aha1740.c --- a/drivers/scsi/aha1740.c Tue Jul 1 18:44:33 2003 +++ b/drivers/scsi/aha1740.c Tue Jul 1 18:44:33 2003 @@ -8,6 +8,7 @@ * * This file is aha1740.c, written and * Copyright (C) 1992,1993 Brad McLean + * brad@saturn.gaylord.com or brad@bradpc.gaylord.com. * * Modifications to makecode and queuecommand * for proper handling of multiple devices courteously @@ -23,6 +24,9 @@ * * Reworked for new_eh and new locking by Alan Cox * + * Converted to EISA and generic DMA APIs by Marc Zyngier + * , 4/2003. + * * For the avoidance of doubt the "preferred form" of this code is one which * is in an open non patent encumbered format. Where cryptographic key signing * forms part of the process of creating an executable the information @@ -39,6 +43,10 @@ #include #include #include +#include +#include +#include +#include #include #include @@ -58,478 +66,550 @@ #define DEB(x) #endif -/* -static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/aha1740.c,v 1.1 1992/07/24 06:27:38 root Exp root $"; -*/ - struct aha1740_hostdata { - unsigned int slot; - unsigned int translation; - unsigned int last_ecb_used; - struct ecb ecb[AHA1740_ECBS]; + struct eisa_device *edev; + unsigned int translation; + unsigned int last_ecb_used; + dma_addr_t ecb_dma_addr; + struct ecb ecb[AHA1740_ECBS]; +}; + +struct aha1740_sg { + struct aha1740_chain sg_chain[AHA1740_SCATTER]; + dma_addr_t sg_dma_addr; + dma_addr_t buf_dma_addr; }; #define HOSTDATA(host) ((struct aha1740_hostdata *) &host->hostdata) -static spinlock_t aha1740_lock = SPIN_LOCK_UNLOCKED; +static inline struct ecb *ecb_dma_to_cpu (struct Scsi_Host *host, + dma_addr_t dma) +{ + struct aha1740_hostdata *hdata = HOSTDATA (host); + dma_addr_t offset; -/* One for each IRQ level (9-15) */ -static struct Scsi_Host * aha_host[8] = {NULL, }; + offset = dma - hdata->ecb_dma_addr; -static int aha1740_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start, off_t offset, - int length, int inout) + return (struct ecb *)(((char *) hdata->ecb) + (unsigned int) offset); +} + +static inline dma_addr_t ecb_cpu_to_dma (struct Scsi_Host *host, void *cpu) { - int len; - struct aha1740_hostdata *host; + struct aha1740_hostdata *hdata = HOSTDATA (host); + dma_addr_t offset; + + offset = (char *) cpu - (char *) hdata->ecb; + + return hdata->ecb_dma_addr + offset; +} - if (inout) - return-ENOSYS; +static int aha1740_proc_info(struct Scsi_Host *shpnt, char *buffer, + char **start, off_t offset, + int length, int inout) +{ + int len; + struct aha1740_hostdata *host; - host = HOSTDATA(shpnt); + if (inout) + return-ENOSYS; - len = sprintf(buffer, "aha174x at IO:%lx, IRQ %d, SLOT %d.\n" - "Extended translation %sabled.\n", - shpnt->io_port, shpnt->irq, host->slot, - host->translation ? "en" : "dis"); + host = HOSTDATA(shpnt); - if (offset > len) { - *start = buffer; - return 0; - } + len = sprintf(buffer, "aha174x at IO:%lx, IRQ %d, SLOT %d.\n" + "Extended translation %sabled.\n", + shpnt->io_port, shpnt->irq, host->edev->slot, + host->translation ? "en" : "dis"); + + if (offset > len) { + *start = buffer; + return 0; + } - *start = buffer + offset; - len -= offset; - if (len > length) - len = length; - return len; + *start = buffer + offset; + len -= offset; + if (len > length) + len = length; + return len; } - static int aha1740_makecode(unchar *sense, unchar *status) { - struct statusword - { - ushort don:1, /* Command Done - No Error */ - du:1, /* Data underrun */ - :1, qf:1, /* Queue full */ - sc:1, /* Specification Check */ - dor:1, /* Data overrun */ - ch:1, /* Chaining Halted */ - intr:1, /* Interrupt issued */ - asa:1, /* Additional Status Available */ - sns:1, /* Sense information Stored */ - :1, ini:1, /* Initialization Required */ - me:1, /* Major error or exception */ - :1, eca:1, /* Extended Contingent alliance */ - :1; - } status_word; - int retval = DID_OK; + struct statusword + { + ushort don:1, /* Command Done - No Error */ + du:1, /* Data underrun */ + :1, qf:1, /* Queue full */ + sc:1, /* Specification Check */ + dor:1, /* Data overrun */ + ch:1, /* Chaining Halted */ + intr:1, /* Interrupt issued */ + asa:1, /* Additional Status Available */ + sns:1, /* Sense information Stored */ + :1, ini:1, /* Initialization Required */ + me:1, /* Major error or exception */ + :1, eca:1, /* Extended Contingent alliance */ + :1; + } status_word; + int retval = DID_OK; - status_word = * (struct statusword *) status; + status_word = * (struct statusword *) status; #ifdef DEBUG - printk("makecode from %x,%x,%x,%x %x,%x,%x,%x", - status[0], status[1], status[2], status[3], - sense[0], sense[1], sense[2], sense[3]); + printk("makecode from %x,%x,%x,%x %x,%x,%x,%x", + status[0], status[1], status[2], status[3], + sense[0], sense[1], sense[2], sense[3]); #endif - if (!status_word.don) /* Anything abnormal was detected */ - { - if ( (status[1]&0x18) || status_word.sc ) /*Additional info available*/ - { - /* Use the supplied info for further diagnostics */ - switch ( status[2] ) - { - case 0x12: - if ( status_word.dor ) - retval=DID_ERROR; /* It's an Overrun */ - /* If not overrun, assume underrun and ignore it! */ - case 0x00: /* No info, assume no error, should not occur */ - break; - case 0x11: - case 0x21: - retval=DID_TIME_OUT; - break; - case 0x0a: - retval=DID_BAD_TARGET; - break; - case 0x04: - case 0x05: - retval=DID_ABORT; - /* Either by this driver or the AHA1740 itself */ - break; - default: - retval=DID_ERROR; /* No further diagnostics possible */ - } + if (!status_word.don) { /* Anything abnormal was detected */ + if ( (status[1]&0x18) || status_word.sc ) { + /*Additional info available*/ + /* Use the supplied info for further diagnostics */ + switch ( status[2] ) { + case 0x12: + if ( status_word.dor ) + retval=DID_ERROR; /* It's an Overrun */ + /* If not overrun, assume underrun and + * ignore it! */ + case 0x00: /* No info, assume no error, should + * not occur */ + break; + case 0x11: + case 0x21: + retval=DID_TIME_OUT; + break; + case 0x0a: + retval=DID_BAD_TARGET; + break; + case 0x04: + case 0x05: + retval=DID_ABORT; + /* Either by this driver or the + * AHA1740 itself */ + break; + default: + retval=DID_ERROR; /* No further + * diagnostics + * possible */ + } + } else { + /* Michael suggests, and Brad concurs: */ + if ( status_word.qf ) { + retval = DID_TIME_OUT; /* forces a redo */ + /* I think this specific one should + * not happen -Brad */ + printk("aha1740.c: WARNING: AHA1740 queue overflow!\n"); + } else + if ( status[0]&0x60 ) { + /* Didn't find a better error */ + retval = DID_ERROR; + } + /* In any other case return DID_OK so for example + CONDITION_CHECKS make it through to the appropriate + device driver */ + } } - else - { /* Michael suggests, and Brad concurs: */ - if ( status_word.qf ) - { - retval = DID_TIME_OUT; /* forces a redo */ - /* I think this specific one should not happen -Brad */ - printk("aha1740.c: WARNING: AHA1740 queue overflow!\n"); - } - else if ( status[0]&0x60 ) - { - retval = DID_ERROR; /* Didn't find a better error */ - } - /* In any other case return DID_OK so for example - CONDITION_CHECKS make it through to the appropriate - device driver */ - } - } - /* Under all circumstances supply the target status -Michael */ - return status[3] | retval << 16; + /* Under all circumstances supply the target status -Michael */ + return status[3] | retval << 16; } static int aha1740_test_port(unsigned int base) { - char name[4], tmp; - - /* Okay, look for the EISA ID's */ - name[0]= 'A' -1 + ((tmp = inb(HID0(base))) >> 2); /* First character */ - name[1]= 'A' -1 + ((tmp & 3) << 3); - name[1]+= ((tmp = inb(HID1(base))) >> 5)&0x7; /* Second Character */ - name[2]= 'A' -1 + (tmp & 0x1f); /* Third Character */ - name[3]=0; - tmp = inb(HID2(base)); - if ( strcmp ( name, HID_MFG ) || inb(HID2(base)) != HID_PRD ) - return 0; /* Not an Adaptec 174x */ - -/* if ( inb(HID3(base)) != HID_REV ) - printk("aha174x: Warning; board revision of %d; expected %d\n", - inb(HID3(base)),HID_REV); */ - - if ( inb(EBCNTRL(base)) != EBCNTRL_VALUE ) - { - printk("aha174x: Board detected, but EBCNTRL = %x, so disabled it.\n", - inb(EBCNTRL(base))); - return 0; - } - - if ( inb(PORTADR(base)) & PORTADDR_ENH ) - return 1; /* Okay, we're all set */ + if ( inb(PORTADR(base)) & PORTADDR_ENH ) + return 1; /* Okay, we're all set */ - printk("aha174x: Board detected, but not in enhanced mode, so disabled it.\n"); - return 0; + printk("aha174x: Board detected, but not in enhanced mode, so disabled it.\n"); + return 0; } /* A "high" level interrupt handler */ static irqreturn_t aha1740_intr_handle(int irq, void *dev_id, - struct pt_regs *regs) + struct pt_regs *regs) { - struct Scsi_Host *host = aha_host[irq - 9]; - void (*my_done)(Scsi_Cmnd *); - int errstatus, adapstat; - int number_serviced; - struct ecb *ecbptr; - Scsi_Cmnd *SCtmp; - unsigned int base; - unsigned long flags; - int handled = 0; - - if (!host) - panic("aha1740.c: Irq from unknown host!\n"); - spin_lock_irqsave(host->host_lock, flags); - base = host->io_port; - number_serviced = 0; - - while(inb(G2STAT(base)) & G2STAT_INTPEND) - { - handled = 1; - DEB(printk("aha1740_intr top of loop.\n")); - adapstat = inb(G2INTST(base)); - ecbptr = (struct ecb *) isa_bus_to_virt(inl(MBOXIN0(base))); - outb(G2CNTRL_IRST,G2CNTRL(base)); /* interrupt reset */ + struct Scsi_Host *host = (struct Scsi_Host *) dev_id; + void (*my_done)(Scsi_Cmnd *); + int errstatus, adapstat; + int number_serviced; + struct ecb *ecbptr; + Scsi_Cmnd *SCtmp; + unsigned int base; + unsigned long flags; + int handled = 0; + struct aha1740_sg *sgptr; + struct eisa_device *edev; + + if (!host) + panic("aha1740.c: Irq from unknown host!\n"); + spin_lock_irqsave(host->host_lock, flags); + base = host->io_port; + number_serviced = 0; + edev = HOSTDATA(host)->edev; + + while(inb(G2STAT(base)) & G2STAT_INTPEND) { + handled = 1; + DEB(printk("aha1740_intr top of loop.\n")); + adapstat = inb(G2INTST(base)); + ecbptr = ecb_dma_to_cpu (host, inl(MBOXIN0(base))); + outb(G2CNTRL_IRST,G2CNTRL(base)); /* interrupt reset */ - switch ( adapstat & G2INTST_MASK ) - { - case G2INTST_CCBRETRY: - case G2INTST_CCBERROR: - case G2INTST_CCBGOOD: - /* Host Ready -> Mailbox in complete */ - outb(G2CNTRL_HRDY,G2CNTRL(base)); - if (!ecbptr) - { - printk("Aha1740 null ecbptr in interrupt (%x,%x,%x,%d)\n", - inb(G2STAT(base)),adapstat, - inb(G2INTST(base)), number_serviced++); - continue; - } - SCtmp = ecbptr->SCpnt; - if (!SCtmp) - { - printk("Aha1740 null SCtmp in interrupt (%x,%x,%x,%d)\n", - inb(G2STAT(base)),adapstat, - inb(G2INTST(base)), number_serviced++); - continue; - } - if (SCtmp->host_scribble) - kfree(SCtmp->host_scribble); - /* Fetch the sense data, and tuck it away, in the required slot. - The Adaptec automatically fetches it, and there is no - guarantee that we will still have it in the cdb when we come - back */ - if ( (adapstat & G2INTST_MASK) == G2INTST_CCBERROR ) - { - memcpy(SCtmp->sense_buffer, ecbptr->sense, - sizeof(SCtmp->sense_buffer)); - errstatus = aha1740_makecode(ecbptr->sense,ecbptr->status); - } - else - errstatus = 0; - DEB(if (errstatus) printk("aha1740_intr_handle: returning %6x\n", - errstatus)); - SCtmp->result = errstatus; - my_done = ecbptr->done; - memset(ecbptr,0,sizeof(struct ecb)); - if ( my_done ) - my_done(SCtmp); - break; - case G2INTST_HARDFAIL: - printk(KERN_ALERT "aha1740 hardware failure!\n"); - panic("aha1740.c"); /* Goodbye */ - case G2INTST_ASNEVENT: - printk("aha1740 asynchronous event: %02x %02x %02x %02x %02x\n", - adapstat, inb(MBOXIN0(base)), inb(MBOXIN1(base)), - inb(MBOXIN2(base)), inb(MBOXIN3(base))); /* Say What? */ - /* Host Ready -> Mailbox in complete */ - outb(G2CNTRL_HRDY,G2CNTRL(base)); - break; - case G2INTST_CMDGOOD: - /* set immediate command success flag here: */ - break; - case G2INTST_CMDERROR: - /* Set immediate command failure flag here: */ - break; + switch ( adapstat & G2INTST_MASK ) { + case G2INTST_CCBRETRY: + case G2INTST_CCBERROR: + case G2INTST_CCBGOOD: + /* Host Ready -> Mailbox in complete */ + outb(G2CNTRL_HRDY,G2CNTRL(base)); + if (!ecbptr) { + printk("Aha1740 null ecbptr in interrupt (%x,%x,%x,%d)\n", + inb(G2STAT(base)),adapstat, + inb(G2INTST(base)), number_serviced++); + continue; + } + SCtmp = ecbptr->SCpnt; + if (!SCtmp) { + printk("Aha1740 null SCtmp in interrupt (%x,%x,%x,%d)\n", + inb(G2STAT(base)),adapstat, + inb(G2INTST(base)), number_serviced++); + continue; + } + sgptr = (struct aha1740_sg *) SCtmp->host_scribble; + if (SCtmp->use_sg) { + /* We used scatter-gather. + Do the unmapping dance. */ + dma_unmap_sg (&edev->dev, + (struct scatterlist *) SCtmp->request_buffer, + SCtmp->use_sg, + SCtmp->sc_data_direction); + } else { + dma_unmap_single (&edev->dev, + sgptr->buf_dma_addr, + SCtmp->request_bufflen, + DMA_BIDIRECTIONAL); + } + + /* Free the sg block */ + dma_free_coherent (&edev->dev, + sizeof (struct aha1740_sg), + SCtmp->host_scribble, + sgptr->sg_dma_addr); + + /* Fetch the sense data, and tuck it away, in + the required slot. The Adaptec + automatically fetches it, and there is no + guarantee that we will still have it in the + cdb when we come back */ + if ( (adapstat & G2INTST_MASK) == G2INTST_CCBERROR ) { + memcpy(SCtmp->sense_buffer, ecbptr->sense, + sizeof(SCtmp->sense_buffer)); + errstatus = aha1740_makecode(ecbptr->sense,ecbptr->status); + } else + errstatus = 0; + DEB(if (errstatus) + printk("aha1740_intr_handle: returning %6x\n", + errstatus)); + SCtmp->result = errstatus; + my_done = ecbptr->done; + memset(ecbptr,0,sizeof(struct ecb)); + if ( my_done ) + my_done(SCtmp); + break; + + case G2INTST_HARDFAIL: + printk(KERN_ALERT "aha1740 hardware failure!\n"); + panic("aha1740.c"); /* Goodbye */ + + case G2INTST_ASNEVENT: + printk("aha1740 asynchronous event: %02x %02x %02x %02x %02x\n", + adapstat, + inb(MBOXIN0(base)), + inb(MBOXIN1(base)), + inb(MBOXIN2(base)), + inb(MBOXIN3(base))); /* Say What? */ + /* Host Ready -> Mailbox in complete */ + outb(G2CNTRL_HRDY,G2CNTRL(base)); + break; + + case G2INTST_CMDGOOD: + /* set immediate command success flag here: */ + break; + + case G2INTST_CMDERROR: + /* Set immediate command failure flag here: */ + break; + } + number_serviced++; } - number_serviced++; - } - spin_unlock_irqrestore(host->host_lock, flags); - return IRQ_RETVAL(handled); + spin_unlock_irqrestore(host->host_lock, flags); + return IRQ_RETVAL(handled); } static int aha1740_queuecommand(Scsi_Cmnd * SCpnt, void (*done)(Scsi_Cmnd *)) { - unchar direction; - unchar *cmd = (unchar *) SCpnt->cmnd; - unchar target = SCpnt->device->id; - struct aha1740_hostdata *host = HOSTDATA(SCpnt->device->host); - unsigned long flags; - void *buff = SCpnt->request_buffer; - int bufflen = SCpnt->request_bufflen; - int ecbno; - DEB(int i); - - if(*cmd == REQUEST_SENSE) - { - SCpnt->result = 0; - done(SCpnt); - return 0; - } + unchar direction; + unchar *cmd = (unchar *) SCpnt->cmnd; + unchar target = SCpnt->device->id; + struct aha1740_hostdata *host = HOSTDATA(SCpnt->device->host); + unsigned long flags; + void *buff = SCpnt->request_buffer; + int bufflen = SCpnt->request_bufflen; + dma_addr_t sg_dma; + struct aha1740_sg *sgptr; + int ecbno; + DEB(int i); + + if(*cmd == REQUEST_SENSE) { + SCpnt->result = 0; + done(SCpnt); + return 0; + } #ifdef DEBUG - if (*cmd == READ_10 || *cmd == WRITE_10) - i = xscsi2int(cmd+2); - else if (*cmd == READ_6 || *cmd == WRITE_6) - i = scsi2int(cmd+2); - else - i = -1; - printk("aha1740_queuecommand: dev %d cmd %02x pos %d len %d ", - target, *cmd, i, bufflen); - printk("scsi cmd:"); - for (i = 0; i < SCpnt->cmd_len; i++) printk("%02x ", cmd[i]); - printk("\n"); + if (*cmd == READ_10 || *cmd == WRITE_10) + i = xscsi2int(cmd+2); + else if (*cmd == READ_6 || *cmd == WRITE_6) + i = scsi2int(cmd+2); + else + i = -1; + printk("aha1740_queuecommand: dev %d cmd %02x pos %d len %d ", + target, *cmd, i, bufflen); + printk("scsi cmd:"); + for (i = 0; i < SCpnt->cmd_len; i++) printk("%02x ", cmd[i]); + printk("\n"); #endif - /* locate an available ecb */ - - spin_lock_irqsave(&aha1740_lock, flags); - ecbno = host->last_ecb_used + 1; /* An optimization */ - if (ecbno >= AHA1740_ECBS) - ecbno = 0; - do { - if (!host->ecb[ecbno].cmdw) - break; - ecbno++; + /* locate an available ecb */ + spin_lock_irqsave(&SCpnt->device->host->host_lock, flags); + ecbno = host->last_ecb_used + 1; /* An optimization */ if (ecbno >= AHA1740_ECBS) - ecbno = 0; - } while (ecbno != host->last_ecb_used); + ecbno = 0; + do { + if (!host->ecb[ecbno].cmdw) + break; + ecbno++; + if (ecbno >= AHA1740_ECBS) + ecbno = 0; + } while (ecbno != host->last_ecb_used); - if (host->ecb[ecbno].cmdw) - panic("Unable to find empty ecb for aha1740.\n"); + if (host->ecb[ecbno].cmdw) + panic("Unable to find empty ecb for aha1740.\n"); - host->ecb[ecbno].cmdw = AHA1740CMD_INIT; /* SCSI Initiator Command - doubles as reserved flag */ + host->ecb[ecbno].cmdw = AHA1740CMD_INIT; /* SCSI Initiator Command + doubles as reserved flag */ - host->last_ecb_used = ecbno; - spin_unlock_irqrestore(&aha1740_lock, flags); + host->last_ecb_used = ecbno; + spin_unlock_irqrestore(&SCpnt->device->host->host_lock, flags); #ifdef DEBUG - printk("Sending command (%d %x)...", ecbno, done); + printk("Sending command (%d %x)...", ecbno, done); #endif - host->ecb[ecbno].cdblen = SCpnt->cmd_len; /* SCSI Command Descriptor Block Length */ + host->ecb[ecbno].cdblen = SCpnt->cmd_len; /* SCSI Command + * Descriptor Block + * Length */ - direction = 0; - if (*cmd == READ_10 || *cmd == READ_6) - direction = 1; - else if (*cmd == WRITE_10 || *cmd == WRITE_6) direction = 0; - - memcpy(host->ecb[ecbno].cdb, cmd, SCpnt->cmd_len); - - if (SCpnt->use_sg) - { - struct scatterlist * sgpnt; - struct aha1740_chain * cptr; - int i; - DEB(unsigned char * ptr); - - host->ecb[ecbno].sg = 1; /* SCSI Initiator Command w/scatter-gather*/ - SCpnt->host_scribble = (unsigned char *)kmalloc(512, GFP_KERNEL); - if(SCpnt->host_scribble == NULL) - { + if (*cmd == READ_10 || *cmd == READ_6) + direction = 1; + else if (*cmd == WRITE_10 || *cmd == WRITE_6) + direction = 0; + + memcpy(host->ecb[ecbno].cdb, cmd, SCpnt->cmd_len); + + SCpnt->host_scribble = dma_alloc_coherent (&host->edev->dev, + sizeof (struct aha1740_sg), + &sg_dma, GFP_ATOMIC); + if(SCpnt->host_scribble == NULL) { printk(KERN_WARNING "aha1740: out of memory in queuecommand!\n"); return 1; } - sgpnt = (struct scatterlist *) SCpnt->request_buffer; - cptr = (struct aha1740_chain *) SCpnt->host_scribble; - for(i=0; iuse_sg; i++) - { - cptr[i].datalen = sgpnt[i].length; - cptr[i].dataptr = isa_virt_to_bus(page_address(sgpnt[i].page) + sgpnt[i].offset); - } - host->ecb[ecbno].datalen = SCpnt->use_sg * sizeof(struct aha1740_chain); - host->ecb[ecbno].dataptr = isa_virt_to_bus(cptr); + sgptr = (struct aha1740_sg *) SCpnt->host_scribble; + sgptr->sg_dma_addr = sg_dma; + + if (SCpnt->use_sg) { + struct scatterlist * sgpnt; + struct aha1740_chain * cptr; + int i, count; + DEB(unsigned char * ptr); + + host->ecb[ecbno].sg = 1; /* SCSI Initiator Command + * w/scatter-gather*/ + sgpnt = (struct scatterlist *) SCpnt->request_buffer; + cptr = sgptr->sg_chain; + count = dma_map_sg (&host->edev->dev, sgpnt, SCpnt->use_sg, + SCpnt->sc_data_direction); + for(i=0; i < count; i++) { + cptr[i].datalen = sg_dma_len (sgpnt + i); + cptr[i].dataptr = sg_dma_address (sgpnt + i); + } + host->ecb[ecbno].datalen = count*sizeof(struct aha1740_chain); + host->ecb[ecbno].dataptr = sg_dma; #ifdef DEBUG - printk("cptr %x: ",cptr); - ptr = (unsigned char *) cptr; - for(i=0;i<24;i++) printk("%02x ", ptr[i]); + printk("cptr %x: ",cptr); + ptr = (unsigned char *) cptr; + for(i=0;i<24;i++) printk("%02x ", ptr[i]); #endif - } - else - { - SCpnt->host_scribble = NULL; - host->ecb[ecbno].datalen = bufflen; - host->ecb[ecbno].dataptr = isa_virt_to_bus(buff); - } - host->ecb[ecbno].lun = SCpnt->device->lun; - host->ecb[ecbno].ses = 1; /* Suppress underrun errors */ - host->ecb[ecbno].dir = direction; - host->ecb[ecbno].ars = 1; /* Yes, get the sense on an error */ - host->ecb[ecbno].senselen = 12; - host->ecb[ecbno].senseptr = isa_virt_to_bus(host->ecb[ecbno].sense); - host->ecb[ecbno].statusptr = isa_virt_to_bus(host->ecb[ecbno].status); - host->ecb[ecbno].done = done; - host->ecb[ecbno].SCpnt = SCpnt; + } else { + host->ecb[ecbno].datalen = bufflen; + sgptr->buf_dma_addr = dma_map_single (&host->edev->dev, + buff, bufflen, + DMA_BIDIRECTIONAL); + host->ecb[ecbno].dataptr = sgptr->buf_dma_addr; + } + host->ecb[ecbno].lun = SCpnt->device->lun; + host->ecb[ecbno].ses = 1; /* Suppress underrun errors */ + host->ecb[ecbno].dir = direction; + host->ecb[ecbno].ars = 1; /* Yes, get the sense on an error */ + host->ecb[ecbno].senselen = 12; + host->ecb[ecbno].senseptr = ecb_cpu_to_dma (SCpnt->device->host, + host->ecb[ecbno].sense); + host->ecb[ecbno].statusptr = ecb_cpu_to_dma (SCpnt->device->host, + host->ecb[ecbno].status); + host->ecb[ecbno].done = done; + host->ecb[ecbno].SCpnt = SCpnt; #ifdef DEBUG - { - int i; - printk("aha1740_command: sending.. "); - for (i = 0; i < sizeof(host->ecb[ecbno]) - 10; i++) - printk("%02x ", ((unchar *)&host->ecb[ecbno])[i]); - } - printk("\n"); + { + int i; + printk("aha1740_command: sending.. "); + for (i = 0; i < sizeof(host->ecb[ecbno]) - 10; i++) + printk("%02x ", ((unchar *)&host->ecb[ecbno])[i]); + } + printk("\n"); #endif - if (done) - { /* The Adaptec Spec says the card is so fast that the loops will - only be executed once in the code below. Even if this was true - with the fastest processors when the spec was written, it doesn't - seem to be true with todays fast processors. We print a warning - if the code is executed more often than LOOPCNT_WARN. If this - happens, it should be investigated. If the count reaches - LOOPCNT_MAX, we assume something is broken; since there is no - way to return an error (the return value is ignored by the - mid-level scsi layer) we have to panic (and maybe that's the - best thing we can do then anyhow). */ + if (done) { + /* The Adaptec Spec says the card is so fast that the loops + will only be executed once in the code below. Even if this + was true with the fastest processors when the spec was + written, it doesn't seem to be true with todays fast + processors. We print a warning if the code is executed more + often than LOOPCNT_WARN. If this happens, it should be + investigated. If the count reaches LOOPCNT_MAX, we assume + something is broken; since there is no way to return an + error (the return value is ignored by the mid-level scsi + layer) we have to panic (and maybe that's the best thing we + can do then anyhow). */ #define LOOPCNT_WARN 10 /* excessive mbxout wait -> syslog-msg */ #define LOOPCNT_MAX 1000000 /* mbxout deadlock -> panic() after ~ 2 sec. */ - int loopcnt; - unsigned int base = SCpnt->device->host->io_port; - DEB(printk("aha1740[%d] critical section\n",ecbno)); - - spin_lock_irqsave(&aha1740_lock, flags); - for (loopcnt = 0; ; loopcnt++) { - if (inb(G2STAT(base)) & G2STAT_MBXOUT) break; - if (loopcnt == LOOPCNT_WARN) { - printk("aha1740[%d]_mbxout wait!\n",ecbno); - } - if (loopcnt == LOOPCNT_MAX) - panic("aha1740.c: mbxout busy!\n"); - } - outl(isa_virt_to_bus(host->ecb + ecbno), MBOXOUT0(base)); - for (loopcnt = 0; ; loopcnt++) { - if (! (inb(G2STAT(base)) & G2STAT_BUSY)) break; - if (loopcnt == LOOPCNT_WARN) { - printk("aha1740[%d]_attn wait!\n",ecbno); - } - if (loopcnt == LOOPCNT_MAX) - panic("aha1740.c: attn wait failed!\n"); - } - outb(ATTN_START | (target & 7), ATTN(base)); /* Start it up */ - spin_unlock_irqrestore(&aha1740_lock, flags); - DEB(printk("aha1740[%d] request queued.\n",ecbno)); - } - else - printk(KERN_ALERT "aha1740_queuecommand: done can't be NULL\n"); - return 0; + int loopcnt; + unsigned int base = SCpnt->device->host->io_port; + DEB(printk("aha1740[%d] critical section\n",ecbno)); + + spin_lock_irqsave(&SCpnt->device->host->host_lock, flags); + for (loopcnt = 0; ; loopcnt++) { + if (inb(G2STAT(base)) & G2STAT_MBXOUT) break; + if (loopcnt == LOOPCNT_WARN) { + printk("aha1740[%d]_mbxout wait!\n",ecbno); + } + if (loopcnt == LOOPCNT_MAX) + panic("aha1740.c: mbxout busy!\n"); + } + outl (ecb_cpu_to_dma (SCpnt->device->host, host->ecb + ecbno), + MBOXOUT0(base)); + for (loopcnt = 0; ; loopcnt++) { + if (! (inb(G2STAT(base)) & G2STAT_BUSY)) break; + if (loopcnt == LOOPCNT_WARN) { + printk("aha1740[%d]_attn wait!\n",ecbno); + } + if (loopcnt == LOOPCNT_MAX) + panic("aha1740.c: attn wait failed!\n"); + } + outb(ATTN_START | (target & 7), ATTN(base)); /* Start it up */ + spin_unlock_irqrestore(&SCpnt->device->host->host_lock, flags); + DEB(printk("aha1740[%d] request queued.\n",ecbno)); + } else + printk(KERN_ALERT "aha1740_queuecommand: done can't be NULL\n"); + return 0; } /* Query the board for its irq_level. Nothing else matters in enhanced mode on an EISA bus. */ static void aha1740_getconfig(unsigned int base, unsigned int *irq_level, - unsigned int *translation) + unsigned int *translation) { - static int intab[] = { 9, 10, 11, 12, 0, 14, 15, 0 }; + static int intab[] = { 9, 10, 11, 12, 0, 14, 15, 0 }; - *irq_level = intab[inb(INTDEF(base)) & 0x7]; - *translation = inb(RESV1(base)) & 0x1; - outb(inb(INTDEF(base)) | 0x10, INTDEF(base)); + *irq_level = intab[inb(INTDEF(base)) & 0x7]; + *translation = inb(RESV1(base)) & 0x1; + outb(inb(INTDEF(base)) | 0x10, INTDEF(base)); } -static int aha1740_detect(Scsi_Host_Template * tpnt) +static int aha1740_biosparam(struct scsi_device *sdev, + struct block_device *dev, + sector_t capacity, int* ip) { - int count = 0, slot; + int size = capacity; + int extended = HOSTDATA(sdev->host)->translation; - DEB(printk("aha1740_detect: \n")); + DEB(printk("aha1740_biosparam\n")); + if (extended && (ip[2] > 1024)) { + ip[0] = 255; + ip[1] = 63; + ip[2] = size / (255 * 63); + } else { + ip[0] = 64; + ip[1] = 32; + ip[2] = size >> 11; + } + return 0; +} + +static int aha1740_eh_abort_handler (Scsi_Cmnd *dummy) +{ +/* + * From Alan Cox : + * The AHA1740 has firmware handled abort/reset handling. The "head in + * sand" kernel code is correct for once 8) + * + * So we define a dummy handler just to keep the kernel SCSI code as + * quiet as possible... + */ - for ( slot=MINEISA; slot <= MAXEISA; slot++ ) - { + return 0; +} + +static Scsi_Host_Template aha1740_template = { + .module = THIS_MODULE, + .proc_name = "aha1740", + .proc_info = aha1740_proc_info, + .name = "Adaptec 174x (EISA)", + .queuecommand = aha1740_queuecommand, + .bios_param = aha1740_biosparam, + .can_queue = AHA1740_ECBS, + .this_id = 7, + .sg_tablesize = AHA1740_SCATTER, + .cmd_per_lun = AHA1740_CMDLUN, + .use_clustering = ENABLE_CLUSTERING, + .eh_abort_handler = aha1740_eh_abort_handler, +}; + +static int aha1740_probe (struct device *dev) +{ int slotbase; unsigned int irq_level, translation; struct Scsi_Host *shpnt; struct aha1740_hostdata *host; - slotbase = SLOTBASE(slot); - /* - * The ioports for eisa boards are generally beyond that used in the - * check/allocate region code, but this may change at some point, - * so we go through the motions. - */ - if (!request_region(slotbase, SLOTSIZE, "aha1740")) /* See if in use */ - continue; + struct eisa_device *edev = to_eisa_device (dev); + + DEB(printk("aha1740_probe: \n")); + + slotbase = edev->base_addr + EISA_VENDOR_ID_OFFSET; + if (!request_region(slotbase, SLOTSIZE, "aha1740")) /* See if in use */ + return -EBUSY; if (!aha1740_test_port(slotbase)) - goto err_release; + goto err_release; aha1740_getconfig(slotbase,&irq_level,&translation); if ((inb(G2STAT(slotbase)) & - (G2STAT_MBXOUT|G2STAT_BUSY)) != G2STAT_MBXOUT) - { /* If the card isn't ready, hard reset it */ - outb(G2CNTRL_HRST, G2CNTRL(slotbase)); - outb(0, G2CNTRL(slotbase)); + (G2STAT_MBXOUT|G2STAT_BUSY)) != G2STAT_MBXOUT) { + /* If the card isn't ready, hard reset it */ + outb(G2CNTRL_HRST, G2CNTRL(slotbase)); + outb(0, G2CNTRL(slotbase)); } - printk(KERN_INFO "Configuring aha174x at IO:%x, IRQ %d\n", slotbase, irq_level); + printk(KERN_INFO "Configuring %s at IO:%x, IRQ %d\n", + dev->name, slotbase, irq_level); printk(KERN_INFO "aha174x: Extended translation %sabled.\n", translation ? "en" : "dis"); - DEB(printk("aha1740_detect: enable interrupt channel %d\n",irq_level)); - if (request_irq(irq_level,aha1740_intr_handle,0,"aha1740",NULL)) { - printk("Unable to allocate IRQ for adaptec controller.\n"); - goto err_release; - } - shpnt = scsi_register(tpnt, sizeof(struct aha1740_hostdata)); + shpnt = scsi_host_alloc(&aha1740_template, + sizeof(struct aha1740_hostdata)); if(shpnt == NULL) - goto err_free_irq; + goto err_release; shpnt->base = 0; shpnt->io_port = slotbase; @@ -537,70 +617,80 @@ shpnt->irq = irq_level; shpnt->dma_channel = 0xff; host = HOSTDATA(shpnt); - host->slot = slot; + host->edev = edev; host->translation = translation; - aha_host[irq_level - 9] = shpnt; - count++; - continue; - - err_free_irq: - free_irq(irq_level, aha1740_intr_handle); - err_release: + host->ecb_dma_addr = dma_map_single (&edev->dev, host->ecb, + sizeof (host->ecb), + DMA_BIDIRECTIONAL); + if (!host->ecb_dma_addr) { + printk (KERN_ERR "aha1740_probe: Couldn't map ECB, giving up\n"); + scsi_unregister (shpnt); + goto err_release; + } + + DEB(printk("aha1740_probe: enable interrupt channel %d\n",irq_level)); + if (request_irq(irq_level,aha1740_intr_handle,0,"aha1740",shpnt)) { + printk(KERN_ERR "aha1740_probe: Unable to allocate IRQ %d.\n", + irq_level); + goto err_release; + } + + eisa_set_drvdata (edev, shpnt); + scsi_add_host (shpnt, dev); + return 0; + + err_release: release_region(slotbase, SLOTSIZE); - } - return count; + + return -ENODEV; } -static int aha1740_release(struct Scsi_Host *shost) +static __devexit int aha1740_remove (struct device *dev) { - if (shost->irq) - free_irq(shost->irq, NULL); - if (shost->io_port && shost->n_io_port) - release_region(shost->io_port, shost->n_io_port); - scsi_unregister(shost); + struct Scsi_Host *shpnt = dev->driver_data; + struct aha1740_hostdata *host = HOSTDATA (shpnt); + + if (scsi_remove_host (shpnt)) + return -EBUSY; + + free_irq (shpnt->irq, shpnt); + dma_unmap_single (dev, host->ecb_dma_addr, + sizeof (host->ecb), DMA_BIDIRECTIONAL); + release_region (shpnt->io_port, SLOTSIZE); + + scsi_host_put (shpnt); + return 0; } -static int aha1740_biosparam(struct scsi_device *sdev, struct block_device *dev, - sector_t capacity, int* ip) -{ - int size = capacity; - int extended = HOSTDATA(sdev->host)->translation; +static struct eisa_device_id aha1740_ids[] = { + { "ADP0000" }, /* 1740 */ + { "ADP0001" }, /* 1740A */ + { "ADP0002" }, /* 1742A */ + { "ADP0400" }, /* 1744 */ + { "" } +}; + +static struct eisa_driver aha1740_driver = { + .id_table = aha1740_ids, + .driver = { + .name = "aha1740", + .probe = aha1740_probe, + .remove = __devexit_p (aha1740_remove), + }, +}; - DEB(printk("aha1740_biosparam\n")); - if (extended && (ip[2] > 1024)) - { - ip[0] = 255; - ip[1] = 63; - ip[2] = size / (255 * 63); - } - else - { - ip[0] = 64; - ip[1] = 32; - ip[2] = size >> 11; - } - return 0; +static __init int aha1740_init (void) +{ + return eisa_driver_register (&aha1740_driver); } -MODULE_LICENSE("GPL"); +static __exit void aha1740_exit (void) +{ + eisa_driver_unregister (&aha1740_driver); +} -static Scsi_Host_Template driver_template = { - .proc_name = "aha1740", - .proc_info = aha1740_proc_info, - .name = "Adaptec 174x (EISA)", - .detect = aha1740_detect, - .release = aha1740_release, - .queuecommand = aha1740_queuecommand, - .bios_param = aha1740_biosparam, - .can_queue = AHA1740_ECBS, - .this_id = 7, - .sg_tablesize = AHA1740_SCATTER, - .cmd_per_lun = AHA1740_CMDLUN, - .use_clustering = ENABLE_CLUSTERING, -}; -#include "scsi_module.c" +module_init (aha1740_init); +module_exit (aha1740_exit); -/* Okay, you made it all the way through. As of this writing, 3/31/93, I'm -brad@saturn.gaylord.com or brad@bradpc.gaylord.com. I'll try to help as time -permits if you have any trouble with this driver. Happy Linuxing! */ +MODULE_LICENSE("GPL"); diff -Nru a/drivers/scsi/aha1740.h b/drivers/scsi/aha1740.h --- a/drivers/scsi/aha1740.h Tue Jul 1 18:44:35 2003 +++ b/drivers/scsi/aha1740.h Tue Jul 1 18:44:35 2003 @@ -12,11 +12,6 @@ #include -/* Eisa Enhanced mode operation - slot locating and addressing */ -#define MINEISA 1 /* I don't have an EISA Spec to know these ranges, so I */ -#define MAXEISA 8 /* Just took my machine's specifications. Adjust to fit. */ - /* I just saw an ad, and bumped this from 6 to 8 */ -#define SLOTBASE(x) ((x << 12) + 0xc80) #define SLOTSIZE 0x5c /* EISA configuration registers & values */ @@ -151,11 +146,6 @@ #define AHA1740CMD_DOWN 0x09 /* Download Firmware (yeah, I bet!) */ #define AHA1740CMD_RINQ 0x0a /* Read Host Adapter Inquiry Data */ #define AHA1740CMD_TARG 0x10 /* Target SCSI Command */ - -static int aha1740_detect(Scsi_Host_Template *); -static int aha1740_command(Scsi_Cmnd *); -static int aha1740_queuecommand(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); -static int aha1740_biosparam(struct scsi_device *, struct block_device *, sector_t, int *); #define AHA1740_ECBS 32 #define AHA1740_SCATTER 16 diff -Nru a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c --- a/drivers/scsi/dc395x.c Tue Jul 1 18:44:32 2003 +++ b/drivers/scsi/dc395x.c Tue Jul 1 18:44:32 2003 @@ -59,6 +59,7 @@ #include #include #include +#include /*--------------------------------------------------------------------------- Features diff -Nru a/drivers/scsi/fd_mcs.c b/drivers/scsi/fd_mcs.c --- a/drivers/scsi/fd_mcs.c Tue Jul 1 18:44:34 2003 +++ b/drivers/scsi/fd_mcs.c Tue Jul 1 18:44:34 2003 @@ -589,7 +589,6 @@ static int fd_mcs_proc_info(struct Scsi_Host *shpnt, char *buffer, char **start, off_t offset, int length, int inout) { int len = 0; - int i; if (inout) return (-ENOSYS); diff -Nru a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c --- a/drivers/scsi/gdth.c Tue Jul 1 18:44:36 2003 +++ b/drivers/scsi/gdth.c Tue Jul 1 18:44:36 2003 @@ -3662,7 +3662,7 @@ pci_unmap_single(ha->pdev,scp->SCp.dma_handle, scp->request_bufflen,scp->SCp.Message); if (scp->SCp.buffer) - pci_unmap_single(ha->pdev,(dma_addr_t)(u32)scp->SCp.buffer, + pci_unmap_single(ha->pdev,(dma_addr_t)scp->SCp.buffer, 16,PCI_DMA_FROMDEVICE); #endif if (ha->status == S_OK) { diff -Nru a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c --- a/drivers/scsi/hosts.c Tue Jul 1 18:44:31 2003 +++ b/drivers/scsi/hosts.c Tue Jul 1 18:44:31 2003 @@ -82,6 +82,13 @@ sht->info ? sht->info(shost) : sht->name); error = scsi_sysfs_add_host(shost, dev); + + if (!shost->can_queue) { + printk(KERN_ERR "%s: can_queue = 0 no longer supported\n", + sht->name); + error = -EINVAL; + } + if (!error) { scsi_proc_host_add(shost); scsi_scan_host(shost); @@ -187,7 +194,7 @@ shost->use_blk_tcq = sht->use_blk_tcq; shost->highmem_io = sht->highmem_io; - if (!sht->max_host_blocked) + if (sht->max_host_blocked) shost->max_host_blocked = sht->max_host_blocked; else shost->max_host_blocked = SCSI_DEFAULT_HOST_BLOCKED; diff -Nru a/drivers/scsi/hosts.h b/drivers/scsi/hosts.h --- a/drivers/scsi/hosts.h Tue Jul 1 18:44:34 2003 +++ b/drivers/scsi/hosts.h Tue Jul 1 18:44:34 2003 @@ -26,28 +26,8 @@ #include #include -#include #include - -struct scsi_driver { - struct module *owner; - struct device_driver gendrv; - - int (*init_command)(struct scsi_cmnd *); - void (*rescan)(struct device *); -}; -#define to_scsi_driver(drv) \ - container_of((drv), struct scsi_driver, gendrv) - -extern int scsi_register_driver(struct device_driver *); -#define scsi_unregister_driver(drv) \ - driver_unregister(drv); - -extern int scsi_register_interface(struct class_interface *); -#define scsi_unregister_interface(intf) \ - class_interface_unregister(intf) - /** * scsi_find_device - find a device given the host diff -Nru a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c --- a/drivers/scsi/ibmmca.c Tue Jul 1 18:44:32 2003 +++ b/drivers/scsi/ibmmca.c Tue Jul 1 18:44:32 2003 @@ -2379,7 +2379,6 @@ { int len = 0; int i, id, lun, host_index; - struct Scsi_Host *shpnt; unsigned long flags; int max_pun; @@ -2450,11 +2449,6 @@ len = length; spin_unlock_irqrestore(shpnt->host_lock, flags); return len; -} - -static void ibmmca_scsi_setup(char *str, int *ints) -{ - internal_ibmmca_scsi_setup(str, ints); } static int option_setup(char *str) diff -Nru a/drivers/scsi/ibmmca.h b/drivers/scsi/ibmmca.h --- a/drivers/scsi/ibmmca.h Tue Jul 1 18:44:36 2003 +++ b/drivers/scsi/ibmmca.h Tue Jul 1 18:44:36 2003 @@ -13,7 +13,6 @@ /* Interfaces to the midlevel Linux SCSI driver */ static int ibmmca_detect (Scsi_Host_Template *); static int ibmmca_release (struct Scsi_Host *); -static int ibmmca_command (Scsi_Cmnd *); static int ibmmca_queuecommand (Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); static int ibmmca_abort (Scsi_Cmnd *); static int ibmmca_host_reset (Scsi_Cmnd *); diff -Nru a/drivers/scsi/ips.c b/drivers/scsi/ips.c --- a/drivers/scsi/ips.c Tue Jul 1 18:44:31 2003 +++ b/drivers/scsi/ips.c Tue Jul 1 18:44:31 2003 @@ -7009,10 +7009,10 @@ * are guaranteed to be < 4G. */ if ( IPS_ENABLE_DMA64 && IPS_HAS_ENH_SGLIST(ha) && - !pci_set_dma_mask(ha->pcidev, (u64)0xffffffffffffffff)) { + !pci_set_dma_mask(ha->pcidev, 0xffffffffffffffffULL)) { (ha)->flags |= IPS_HA_ENH_SG; } else { - if ( pci_set_dma_mask(ha->pcidev, (u64)0xffffffff) != 0 ) { + if ( pci_set_dma_mask(ha->pcidev, 0xffffffffULL) != 0 ) { printk(KERN_WARNING "Unable to set DMA Mask\n"); return ips_abort_init(ha, index); } diff -Nru a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c --- a/drivers/scsi/lasi700.c Tue Jul 1 18:44:32 2003 +++ b/drivers/scsi/lasi700.c Tue Jul 1 18:44:32 2003 @@ -76,6 +76,7 @@ .name = "Lasi SCSI", .id_table = lasi700_scsi_tbl, .probe = lasi700_driver_callback, + .remove = __devexit_p(lasi700_driver_remove), }; static int __init @@ -97,12 +98,6 @@ } memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters)); - if (!request_mem_region(base, 64, dev->dev.name)) { - printk(KERN_ERR "%s: Failed to claim memory region\n", - dev->dev.name); - goto out_kfree; - } - hostdata->dev = &dev->dev; dma_set_mask(&dev->dev, 0xffffffffUL); hostdata->base = base; @@ -122,7 +117,7 @@ host = NCR_700_detect(&lasi700_template, hostdata); if (!host) - goto out_release_mem_region; + goto out_kfree; host->irq = dev->irq; if (request_irq(dev->irq, NCR_700_intr, SA_SHIRQ, @@ -132,33 +127,33 @@ goto out_put_host; } + dev_set_drvdata(&dev->dev, host); scsi_add_host(host, &dev->dev); + return 0; out_put_host: scsi_host_put(host); - out_release_mem_region: - release_mem_region(base, 64); + out_kfree: kfree(hostdata); - return 1; + return -ENODEV; } -#if 0 -static int -lasi700_release(struct Scsi_Host *host) +static int __exit +lasi700_driver_remove(struct parisc_device *dev) { - struct D700_Host_Parameters *hostdata = - (struct D700_Host_Parameters *)host->hostdata[0]; + struct Scsi_Host *host = dev_get_drvdata(&dev->dev); + struct NCR_700_Host_Parameters *hostdata = + (struct NCR_700_Host_Parameters *)host->hostdata[0]; + scsi_remove_host(host); NCR_700_release(host); - kfree(hostdata); free_irq(host->irq, host); - release_mem_region(host->base, 64); - unregister_parisc_driver(&lasi700_driver); - return 1; + kfree(hostdata); + + return 0; } -#endif static int __init lasi700_init(void) @@ -166,4 +161,12 @@ return register_parisc_driver(&lasi700_driver); } +static void __exit +lasi700_exit(void) +{ + unregister_parisc_driver(&lasi700_driver); + scsi_sysfs_release_attributes(&lasi700_template); +} + module_init(lasi700_init); +module_exit(lasi700_exit); diff -Nru a/drivers/scsi/lasi700.h b/drivers/scsi/lasi700.h --- a/drivers/scsi/lasi700.h Tue Jul 1 18:44:32 2003 +++ b/drivers/scsi/lasi700.h Tue Jul 1 18:44:32 2003 @@ -25,9 +25,8 @@ #ifndef _LASI700_H #define _LASI700_H -static int lasi700_detect(Scsi_Host_Template *); static int lasi700_driver_callback(struct parisc_device *dev); -static int lasi700_release(struct Scsi_Host *host); +static int lasi700_driver_remove(struct parisc_device *dev); #define LASI_710_SVERSION 0x082 #define LASI_700_SVERSION 0x071 diff -Nru a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c --- a/drivers/scsi/megaraid.c Tue Jul 1 18:44:31 2003 +++ b/drivers/scsi/megaraid.c Tue Jul 1 18:44:31 2003 @@ -40,6 +40,7 @@ #include #include #include +#include #include #include "scsi.h" diff -Nru a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c --- a/drivers/scsi/ncr53c8xx.c Tue Jul 1 18:44:34 2003 +++ b/drivers/scsi/ncr53c8xx.c Tue Jul 1 18:44:34 2003 @@ -82,7 +82,7 @@ ** Etc... ** ** Supported NCR/SYMBIOS chips: -** 53C720 (Wide, Fast SCSI-2, HP Zalon) +** 53C720 (Wide, Fast SCSI-2, intfly problems) ** 53C810 (8 bits, Fast SCSI-2, no rom BIOS) ** 53C815 (8 bits, Fast SCSI-2, on board rom BIOS) ** 53C820 (Wide, Fast SCSI-2, no rom BIOS) @@ -173,31 +173,6 @@ #endif #endif -/* -** Define the BSD style u_int32 and u_int64 type. -** Are in fact u_int32_t and u_int64_t :-) -*/ -typedef u32 u_int32; -typedef u64 u_int64; -typedef u_long vm_offset_t; - -#ifdef __hppa__ -/* - * Yuck. Current plan is to use ncr58c8xx.c for non-pci big endian - * chips, and sym53c8xx.c for pci little endian chips. Define this - * here so it gets seen by sym53c8xx_defs.h, pulled in via ncr53c8xx.h. - */ -#define SCSI_NCR_BIG_ENDIAN -/* INTFLY interrupts don't always seem to get serviced atm..... */ -#define SIMULATED_INTFLY -#endif - -#if defined(CONFIG_SCSI_ZALON) || defined(CONFIG_SCSI_ZALON_MODULE) -#define ENABLE_SCSI_ZALON -#include -#include "zalon.h" -#endif - #include "ncr53c8xx.h" /* @@ -215,6 +190,12 @@ #include "sym53c8xx_comm.h" +int ncr53c8xx_slave_configure(Scsi_Device *device); +int ncr53c8xx_bus_reset(Scsi_Cmnd *cmd); +int ncr53c8xx_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)); +const char *ncr53c8xx_info (struct Scsi_Host *host); + + /*========================================================== ** ** The CCB done queue uses an array of CCB virtual @@ -397,7 +378,6 @@ #define ScsiResult(host_code, scsi_code) (((host_code) << 16) + ((scsi_code) & 0x7f)) -static irqreturn_t ncr53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs); static void ncr53c8xx_timeout(unsigned long np); static int ncr53c8xx_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int func); @@ -1245,7 +1225,7 @@ ** return from the subroutine. */ -#ifdef ENABLE_SCSI_ZALON +#ifdef CONFIG_NCR53C8XX_PREFETCH #define PREFETCH_FLUSH_CNT 2 #define PREFETCH_FLUSH SCR_CALL, PADDRH (wait_dma), #else @@ -1419,8 +1399,6 @@ static void ncr_usercmd (ncb_p np); #endif -static int ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device); - static void insert_into_waiting_list(ncb_p np, Scsi_Cmnd *cmd); static Scsi_Cmnd *retrieve_from_waiting_list(int to_remove, ncb_p np, Scsi_Cmnd *cmd); static void process_waiting_list(ncb_p np, int sts); @@ -3236,7 +3214,7 @@ * ctest4 for others. */ #define burst_code(dmode, ctest0, ctest4, ctest5) \ - (np->device_id == PSEUDO_ZALON_720_ID) ? \ + (np->device_id == PSEUDO_720_ID) ? \ (ctest0) & 0x80? 0 : (((dmode) & 0xc0) >> 6) + 1 : \ (ctest4) & 0x80? 0 : (((dmode) & 0xc0) >> 6) + ((ctest5) & 0x04) + 1 @@ -3245,7 +3223,7 @@ */ static inline void ncr_init_burst(ncb_p np, u_char bc) { - u_char *be = (np->device_id == PSEUDO_ZALON_720_ID) ? + u_char *be = (np->device_id == PSEUDO_720_ID) ? &np->rv_ctest0 : &np->rv_ctest4; *be &= ~0x80; np->rv_dmode &= ~(0x3 << 6); @@ -3646,7 +3624,7 @@ ** start the timer daemon. */ -static int __init +struct Scsi_Host * __init ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device) { struct host_data *host_data; @@ -3656,7 +3634,22 @@ ncr_nvram *nvram = device->nvram; int i; -#ifndef ENABLE_SCSI_ZALON +#ifdef SCSI_NCR_PROC_INFO_SUPPORT + tpnt->proc_info = ncr53c8xx_proc_info, +#endif + tpnt->info = ncr53c8xx_info; + tpnt->queuecommand = ncr53c8xx_queue_command; + tpnt->slave_configure = ncr53c8xx_slave_configure; + tpnt->eh_bus_reset_handler = ncr53c8xx_bus_reset; + tpnt->can_queue = SCSI_NCR_CAN_QUEUE; + tpnt->this_id = 7; + tpnt->sg_tablesize = SCSI_NCR_SG_TABLESIZE; + tpnt->cmd_per_lun = SCSI_NCR_CMD_PER_LUN; + tpnt->use_clustering = DISABLE_CLUSTERING; + + if(device->differential) + driver_setup.diff_support = device->differential; + printk(KERN_INFO "ncr53c%s-%d: rev 0x%x on pci bus %d device %d function %d " #ifdef __sparc__ "irq %s\n", @@ -3671,12 +3664,11 @@ #else device->slot.irq); #endif -#endif /* ** Allocate host_data structure */ - if (!(instance = scsi_register(tpnt, sizeof(*host_data)))) + if (!(instance = scsi_host_alloc(tpnt, sizeof(*host_data)))) goto attach_error; host_data = (struct host_data *) instance->hostdata; @@ -3744,7 +3736,11 @@ np->paddr2 = (np->features & FE_RAM)? device->slot.base_2 : 0; #ifndef SCSI_NCR_IOMAPPED - np->vaddr = remap_pci_mem(device->slot.base_c, (u_long) 128); + if(device->slot.base_v) + np->vaddr = device->slot.base_v; + else + np->vaddr = remap_pci_mem(device->slot.base_c, (u_long) 128); + if (!np->vaddr) { printk(KERN_ERR "%s: can't map memory mapped IO region\n",ncr_name(np)); @@ -3763,16 +3759,14 @@ np->reg = (struct ncr_reg*) np->vaddr; -#endif /* !defined SCSI_NCR_IOMAPPED */ +#else /* ** Try to map the controller chip into iospace. */ -#ifndef ENABLE_SCSI_ZALON - request_region(device->slot.io_port, 128, "ncr53c8xx"); -#endif np->base_io = device->slot.io_port; +#endif /* !defined SCSI_NCR_IOMAPPED */ #ifdef SCSI_NCR_NVRAM_SUPPORT if (nvram) { @@ -3898,24 +3892,6 @@ ** Install the interrupt handler. */ - if (request_irq(device->slot.irq, ncr53c8xx_intr, - ((driver_setup.irqm & 0x10) ? 0 : SA_SHIRQ) | -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,0) - ((driver_setup.irqm & 0x20) ? 0 : SA_INTERRUPT), -#else - 0, -#endif - "ncr53c8xx", np)) { -#ifdef __sparc__ - printk(KERN_ERR "%s: request irq %s failure\n", - ncr_name(np), __irq_itoa(device->slot.irq)); -#else - printk(KERN_ERR "%s: request irq %d failure\n", - ncr_name(np), device->slot.irq); -#endif - goto attach_error; - } - np->irq = device->slot.irq; /* @@ -3981,40 +3957,13 @@ NCR_UNLOCK_NCB(np, flags); - return 0; + return instance; attach_error: - if (!instance) return -1; + if (!instance) return NULL; printk(KERN_INFO "%s: detaching...\n", ncr_name(np)); if (!np) goto unregister; -#ifndef SCSI_NCR_IOMAPPED - if (np->vaddr) { -#ifdef DEBUG_NCR53C8XX - printk(KERN_DEBUG "%s: releasing memory mapped IO region %lx[%d]\n", ncr_name(np), (u_long) np->vaddr, 128); -#endif - unmap_pci_mem((vm_offset_t) np->vaddr, (u_long) 128); - } -#endif /* !SCSI_NCR_IOMAPPED */ - if (np->base_io) { -#ifdef DEBUG_NCR53C8XX - printk(KERN_DEBUG "%s: releasing IO region %x[%d]\n", ncr_name(np), np->base_io, 128); -#endif -#ifndef ENABLE_SCSI_ZALON - release_region(np->base_io, 128); -#endif - } - if (np->irq) { -#ifdef DEBUG_NCR53C8XX -#ifdef __sparc__ - printk(KERN_INFO "%s: freeing irq %s\n", ncr_name(np), - __irq_itoa(np->irq)); -#else - printk(KERN_INFO "%s: freeing irq %d\n", ncr_name(np), np->irq); -#endif -#endif - free_irq(np->irq, np); - } if (np->scripth0) m_free_dma(np->scripth0, sizeof(struct scripth), "SCRIPTH"); if (np->script0) @@ -4024,9 +3973,9 @@ m_free_dma(np, sizeof(struct ncb), "NCB"); unregister: - scsi_unregister(instance); + scsi_host_put(instance); - return -1; + return NULL; } @@ -4823,7 +4772,7 @@ ** properly set IRQ mode, prior to resetting the bus. */ OUTB (nc_stest3, TE); - if (np->device_id != PSEUDO_ZALON_720_ID) + if (np->device_id != PSEUDO_720_ID) OUTB (nc_dcntl, (np->rv_dcntl & IRQM)); OUTB (nc_scntl1, CRST); UDELAY (200); @@ -5061,19 +5010,6 @@ OUTW (nc_sien , 0); OUTB (nc_dien , 0); -/* -** Free irq -*/ - -#ifdef DEBUG_NCR53C8XX -#ifdef __sparc__ - printk("%s: freeing irq %s\n", ncr_name(np), __irq_itoa(np->irq)); -#else - printk("%s: freeing irq %d\n", ncr_name(np), np->irq); -#endif -#endif - free_irq(np->irq, np); - /* ** Reset NCR chip ** Restore bios setting for automatic clock detection. @@ -5094,24 +5030,6 @@ ncr_selectclock(np, np->sv_scntl3); /* - ** Release Memory mapped IO region and IO mapped region - */ - -#ifndef SCSI_NCR_IOMAPPED -#ifdef DEBUG_NCR53C8XX - printk("%s: releasing memory mapped IO region %lx[%d]\n", ncr_name(np), (u_long) np->vaddr, 128); -#endif - unmap_pci_mem((vm_offset_t) np->vaddr, (u_long) 128); -#endif /* !SCSI_NCR_IOMAPPED */ - -#ifdef DEBUG_NCR53C8XX - printk("%s: releasing IO region %x[%d]\n", ncr_name(np), np->base_io, 128); -#endif -#ifndef ENABLE_SCSI_ZALON - release_region(np->base_io, 128); -#endif - - /* ** Free allocated ccb(s) */ @@ -8634,7 +8552,7 @@ f1 = ncrgetfreq (np, 11); f2 = ncrgetfreq (np, 11); - if (bootverbose) + if(bootverbose) printk ("%s: NCR clock is %uKHz, %uKHz\n", ncr_name(np), f1, f2); if (f1 > f2) f1 = f2; /* trust lower result */ @@ -8774,10 +8692,12 @@ ** routine for each host that uses this IRQ. */ -static irqreturn_t ncr53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs) +irqreturn_t ncr53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs) { unsigned long flags; - ncb_p np = (ncb_p) dev_id; + struct Scsi_Host *shost = (struct Scsi_Host *)dev_id; + struct host_data *host_data = (struct host_data *)shost->hostdata; + ncb_p np = host_data->ncb; Scsi_Cmnd *done_list; #ifdef DEBUG_NCR53C8XX @@ -9188,7 +9108,7 @@ if (len) return -EINVAL; else { - long flags; + unsigned long flags; NCR_LOCK_NCB(np, flags); ncr_usercmd (np); @@ -9335,7 +9255,7 @@ */ static u_short ncr_chip_ids[] __initdata = { - PSEUDO_ZALON_720_ID, + PSEUDO_720_ID, PCI_DEVICE_ID_NCR_53C810, PCI_DEVICE_ID_NCR_53C815, PCI_DEVICE_ID_NCR_53C820, @@ -9350,73 +9270,6 @@ PCI_DEVICE_ID_NCR_53C1510D }; -#ifdef ENABLE_SCSI_ZALON -/* Attach a 53c720 interfaced via Zalon chip on HP boxes. */ -int zalon_attach(Scsi_Host_Template *tpnt, unsigned long io_port, - struct parisc_device *dev, int irq, int unit) -{ - u_short device_id; - u_char revision; - int i; - ncr_chip *chip; - ncr_device device; - - tpnt->proc_name = NAME53C8XX; - tpnt->proc_info = ncr53c8xx_proc_info; - -#if defined(SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT) && defined(MODULE) - if (ncr53c8xx) - ncr53c8xx_setup(ncr53c8xx); -#endif - -#ifdef SCSI_NCR_DEBUG_INFO_SUPPORT - ncr_debug = driver_setup.debug; -#endif - if (initverbose >= 2) - ncr_print_driver_setup(); - - memset(&device, 0, sizeof(ncr_device)); - chip = 0; - device_id = PSEUDO_ZALON_720_ID; - revision = 0; - for (i = 0; i < sizeof(ncr_chip_table)/sizeof(ncr_chip_table[0]); i++) { if (device_id != ncr_chip_table[i].device_id) - continue; - chip = &device.chip; - memcpy(chip, &ncr_chip_table[i], sizeof(*chip)); - chip->revision_id = revision; - break; - } - - if (!chip) { - printk(NAME53C8XX ": not initializing, device not supported\n"); return -1; - } - - /* Fix some features according to driver setup. */ - driver_setup.diff_support = 2; - - /* The following three are needed before any other access. */ - writeb(0x20, io_port + 0x38); /* DCNTL_REG, EA */ - writeb(0x04, io_port + 0x1b); /* CTEST0_REG, EHP */ - writeb(0x80, io_port + 0x22); /* CTEST4_REG, MUX */ - - /* Initialise ncr_device structure with items required by ncr_attach. */ - device.host_id = driver_setup.host_id; - device.dev = &dev->dev; - device.slot.bus = 0; - device.slot.device_fn = 0; - device.slot.base = (u_long)io_port; - device.slot.base_c = (u_long)io_port; - device.slot.base_2 = 0; - device.slot.base_2_c = 0; - device.slot.io_port = io_port; - device.slot.irq = irq; - device.attach_done = 0; - - printk(KERN_INFO NAME53C8XX ": 53c%s detected\n", device.chip.name); - - return ncr_attach(tpnt, unit, &device); -} -#endif /*========================================================== ** @@ -9445,33 +9298,3 @@ { return SCSI_NCR_DRIVER_NAME; } - -/* -** Module stuff -*/ -MODULE_LICENSE("GPL"); - -static Scsi_Host_Template driver_template = { -#ifdef ENABLE_SCSI_ZALON - .proc_name = "zalon720", - .detect = zalon7xx_detect, - .release = zalon7xx_release, -#else - .proc_name = NAME53C8XX, - .detect = ncr53c8xx_detect, - .release = ncr53c8xx_release, -#endif -#ifdef SCSI_NCR_PROC_INFO_SUPPORT - .proc_info = ncr53c8xx_proc_info, -#endif - .info = ncr53c8xx_info, - .queuecommand = ncr53c8xx_queue_command, - .slave_configure = ncr53c8xx_slave_configure, - .eh_bus_reset_handler = ncr53c8xx_bus_reset, - .can_queue = SCSI_NCR_CAN_QUEUE, - .this_id = 7, - .sg_tablesize = SCSI_NCR_SG_TABLESIZE, - .cmd_per_lun = SCSI_NCR_CMD_PER_LUN, - .use_clustering = DISABLE_CLUSTERING, -}; -#include "scsi_module.c" diff -Nru a/drivers/scsi/ncr53c8xx.h b/drivers/scsi/ncr53c8xx.h --- a/drivers/scsi/ncr53c8xx.h Tue Jul 1 18:44:34 2003 +++ b/drivers/scsi/ncr53c8xx.h Tue Jul 1 18:44:34 2003 @@ -42,6 +42,79 @@ #ifndef NCR53C8XX_H #define NCR53C8XX_H +/* +** Define the BSD style u_int32 and u_int64 type. +** Are in fact u_int32_t and u_int64_t :-) +*/ +typedef u32 u_int32; +typedef u64 u_int64; +typedef u_long vm_offset_t; + #include "sym53c8xx_defs.h" + +/*========================================================== +** +** Structures used by the detection routine to transmit +** device configuration to the attach function. +** +**========================================================== +*/ +typedef struct { + int bus; + u_char device_fn; + u_long base; + u_long base_2; + u_long io_port; + u_long base_c; + u_long base_2_c; + u_long base_v; + u_long base_2_v; + int irq; +/* port and reg fields to use INB, OUTB macros */ + u_long base_io; + volatile struct ncr_reg *reg; +} ncr_slot; + +/*========================================================== +** +** Structure used to store the NVRAM content. +** +**========================================================== +*/ +typedef struct { + int type; +#define SCSI_NCR_SYMBIOS_NVRAM (1) +#define SCSI_NCR_TEKRAM_NVRAM (2) +#ifdef SCSI_NCR_NVRAM_SUPPORT + union { + Symbios_nvram Symbios; + Tekram_nvram Tekram; + } data; +#endif +} ncr_nvram; + +/*========================================================== +** +** Structure used by detection routine to save data on +** each detected board for attach. +** +**========================================================== +*/ +typedef struct { + struct device *dev; + ncr_slot slot; + ncr_chip chip; + ncr_nvram *nvram; + u_char host_id; +#ifdef SCSI_NCR_PQS_PDS_SUPPORT + u_char pqs_pds; +#endif + __u8 differential; + int attach_done; +} ncr_device; + +extern struct Scsi_Host *ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device); +extern int ncr53c8xx_release(struct Scsi_Host *host); +irqreturn_t ncr53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs); #endif /* NCR53C8XX_H */ diff -Nru a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c --- a/drivers/scsi/nsp32.c Tue Jul 1 18:44:34 2003 +++ b/drivers/scsi/nsp32.c Tue Jul 1 18:44:34 2003 @@ -283,7 +283,6 @@ static int nsp32_eh_abort(Scsi_Cmnd *); static int nsp32_eh_bus_reset(Scsi_Cmnd *); static int nsp32_eh_host_reset(Scsi_Cmnd *); -static int nsp32_reset(Scsi_Cmnd *, unsigned int); static int nsp32_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int); static int __devinit nsp32_probe(struct pci_dev *, const struct pci_device_id *); static void __devexit nsp32_remove(struct pci_dev *); @@ -1853,18 +1852,6 @@ return data->info_str; } - -/* - * error handler - */ -static int nsp32_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags) -{ - nsp32_dbg(NSP32_DEBUG_BUSRESET, "SCpnt=0x%p why=%d\n", SCpnt, reset_flags); - - nsp32_eh_bus_reset(SCpnt); - - return SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET; -} static int nsp32_eh_abort(Scsi_Cmnd *SCpnt) { diff -Nru a/drivers/scsi/osst.c b/drivers/scsi/osst.c --- a/drivers/scsi/osst.c Tue Jul 1 18:44:35 2003 +++ b/drivers/scsi/osst.c Tue Jul 1 18:44:35 2003 @@ -63,6 +63,7 @@ #include "scsi.h" #include "hosts.h" +#include #include #define ST_KILOBYTE 1024 diff -Nru a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c --- a/drivers/scsi/scsi.c Tue Jul 1 18:44:35 2003 +++ b/drivers/scsi/scsi.c Tue Jul 1 18:44:35 2003 @@ -139,7 +139,7 @@ sreq->sr_device = sdev; sreq->sr_host = sdev->host; sreq->sr_magic = SCSI_REQ_MAGIC; - sreq->sr_data_direction = SCSI_DATA_UNKNOWN; + sreq->sr_data_direction = DMA_BIDIRECTIONAL; } return sreq; diff -Nru a/drivers/scsi/scsi.h b/drivers/scsi/scsi.h --- a/drivers/scsi/scsi.h Tue Jul 1 18:44:33 2003 +++ b/drivers/scsi/scsi.h Tue Jul 1 18:44:33 2003 @@ -25,54 +25,6 @@ #include /* - * These are the values that the SCpnt->sc_data_direction and - * SRpnt->sr_data_direction can take. These need to be set - * The SCSI_DATA_UNKNOWN value is essentially the default. - * In the event that the command creator didn't bother to - * set a value, you will see SCSI_DATA_UNKNOWN. - */ -#define SCSI_DATA_UNKNOWN 0 -#define SCSI_DATA_WRITE 1 -#define SCSI_DATA_READ 2 -#define SCSI_DATA_NONE 3 - -#ifdef CONFIG_PCI -#include -#if ((SCSI_DATA_UNKNOWN == PCI_DMA_BIDIRECTIONAL) && (SCSI_DATA_WRITE == PCI_DMA_TODEVICE) && (SCSI_DATA_READ == PCI_DMA_FROMDEVICE) && (SCSI_DATA_NONE == PCI_DMA_NONE)) -#define scsi_to_pci_dma_dir(scsi_dir) ((int)(scsi_dir)) -#else -extern __inline__ int scsi_to_pci_dma_dir(unsigned char scsi_dir) -{ - if (scsi_dir == SCSI_DATA_UNKNOWN) - return PCI_DMA_BIDIRECTIONAL; - if (scsi_dir == SCSI_DATA_WRITE) - return PCI_DMA_TODEVICE; - if (scsi_dir == SCSI_DATA_READ) - return PCI_DMA_FROMDEVICE; - return PCI_DMA_NONE; -} -#endif -#endif - -#if defined(CONFIG_SBUS) && !defined(CONFIG_SUN3) && !defined(CONFIG_SUN3X) -#include -#if ((SCSI_DATA_UNKNOWN == SBUS_DMA_BIDIRECTIONAL) && (SCSI_DATA_WRITE == SBUS_DMA_TODEVICE) && (SCSI_DATA_READ == SBUS_DMA_FROMDEVICE) && (SCSI_DATA_NONE == SBUS_DMA_NONE)) -#define scsi_to_sbus_dma_dir(scsi_dir) ((int)(scsi_dir)) -#else -extern __inline__ int scsi_to_sbus_dma_dir(unsigned char scsi_dir) -{ - if (scsi_dir == SCSI_DATA_UNKNOWN) - return SBUS_DMA_BIDIRECTIONAL; - if (scsi_dir == SCSI_DATA_WRITE) - return SBUS_DMA_TODEVICE; - if (scsi_dir == SCSI_DATA_READ) - return SBUS_DMA_FROMDEVICE; - return SBUS_DMA_NONE; -} -#endif -#endif - -/* * Some defs, in case these are not defined elsewhere. */ #ifndef TRUE @@ -226,6 +178,21 @@ struct device_attribute *attr); extern int scsi_sysfs_modify_shost_attribute(struct class_device_attribute ***class_attrs, struct class_device_attribute *attr); + +/* + * Legacy dma direction interfaces. + * + * This assumes the pci/sbus dma mapping flags have the same numercial + * values as the generic dma-mapping ones. Currently they have but there's + * no way to check. Better don't use these interfaces! + */ +#define SCSI_DATA_UNKNOWN (DMA_BIDIRECTIONAL) +#define SCSI_DATA_WRITE (DMA_TO_DEVICE) +#define SCSI_DATA_READ (DMA_FROM_DEVICE) +#define SCSI_DATA_NONE (DMA_NONE) + +#define scsi_to_pci_dma_dir(scsi_dir) ((int)(scsi_dir)) +#define scsi_to_sbus_dma_dir(scsi_dir) ((int)(scsi_dir)) /* * This is the crap from the old error handling code. We have it in a special diff -Nru a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c --- a/drivers/scsi/scsi_error.c Tue Jul 1 18:44:31 2003 +++ b/drivers/scsi/scsi_error.c Tue Jul 1 18:44:31 2003 @@ -532,14 +532,14 @@ static int scsi_request_sense(struct scsi_cmnd *scmd) { static unsigned char generic_sense[6] = - {REQUEST_SENSE, 0, 0, 0, 254, 0}; + {REQUEST_SENSE, 0, 0, 0, 252, 0}; unsigned char *scsi_result; int saved_result; int rtn; memcpy(scmd->cmnd, generic_sense, sizeof(generic_sense)); - scsi_result = kmalloc(254, GFP_ATOMIC | (scmd->device->host->hostt->unchecked_isa_dma) ? __GFP_DMA : 0); + scsi_result = kmalloc(252, GFP_ATOMIC | (scmd->device->host->hostt->unchecked_isa_dma) ? __GFP_DMA : 0); if (unlikely(!scsi_result)) { @@ -555,14 +555,14 @@ * address (db). 0 is not a valid sense code. */ memset(scmd->sense_buffer, 0, sizeof(scmd->sense_buffer)); - memset(scsi_result, 0, 254); + memset(scsi_result, 0, 252); saved_result = scmd->result; scmd->request_buffer = scsi_result; - scmd->request_bufflen = 254; + scmd->request_bufflen = 252; scmd->use_sg = 0; scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]); - scmd->sc_data_direction = SCSI_DATA_READ; + scmd->sc_data_direction = DMA_FROM_DEVICE; scmd->underflow = 0; rtn = scsi_send_eh_cmnd(scmd, SENSE_TIMEOUT); @@ -742,7 +742,7 @@ scmd->use_sg = 0; scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]); scmd->underflow = 0; - scmd->sc_data_direction = SCSI_DATA_NONE; + scmd->sc_data_direction = DMA_NONE; rtn = scsi_send_eh_cmnd(scmd, SENSE_TIMEOUT); @@ -1338,7 +1338,7 @@ if (unlikely(!sreq)) { printk(KERN_ERR "%s: request allocate failed," - "prevent media removal cmd not sent", __FUNCTION__); + "prevent media removal cmd not sent\n", __FUNCTION__); return; } @@ -1348,7 +1348,7 @@ sreq->sr_cmnd[3] = 0; sreq->sr_cmnd[4] = SCSI_REMOVAL_PREVENT; sreq->sr_cmnd[5] = 0; - sreq->sr_data_direction = SCSI_DATA_NONE; + sreq->sr_data_direction = DMA_NONE; sreq->sr_bufflen = 0; sreq->sr_buffer = NULL; sreq->sr_allowed = 5; @@ -1723,7 +1723,7 @@ scmd->cmd_len = 0; - scmd->sc_data_direction = SCSI_DATA_UNKNOWN; + scmd->sc_data_direction = DMA_BIDIRECTIONAL; scmd->sc_request = NULL; scmd->sc_magic = SCSI_CMND_MAGIC; diff -Nru a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c --- a/drivers/scsi/scsi_ioctl.c Tue Jul 1 18:44:38 2003 +++ b/drivers/scsi/scsi_ioctl.c Tue Jul 1 18:44:38 2003 @@ -104,7 +104,7 @@ return -ENOMEM; } - sreq->sr_data_direction = SCSI_DATA_NONE; + sreq->sr_data_direction = DMA_NONE; scsi_wait_req(sreq, cmd, NULL, 0, timeout, retries); SCSI_LOG_IOCTL(2, printk("Ioctl returned 0x%x\n", sreq->sr_result)); @@ -258,19 +258,19 @@ return -ENOMEM; memset(buf, 0, buf_needed); if (inlen == 0) { - data_direction = SCSI_DATA_READ; + data_direction = DMA_FROM_DEVICE; } else if (outlen == 0 ) { - data_direction = SCSI_DATA_WRITE; + data_direction = DMA_TO_DEVICE; } else { /* * Can this ever happen? */ - data_direction = SCSI_DATA_UNKNOWN; + data_direction = DMA_BIDIRECTIONAL; } } else { buf = NULL; - data_direction = SCSI_DATA_NONE; + data_direction = DMA_NONE; } /* @@ -322,7 +322,7 @@ } sreq = scsi_allocate_request(sdev); - if (sreq) { + if (!sreq) { result = -EINTR; goto error; } diff -Nru a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c --- a/drivers/scsi/scsi_lib.c Tue Jul 1 18:44:35 2003 +++ b/drivers/scsi/scsi_lib.c Tue Jul 1 18:44:35 2003 @@ -18,6 +18,7 @@ #include "scsi.h" #include "hosts.h" +#include #include "scsi_priv.h" #include "scsi_logging.h" @@ -1094,14 +1095,17 @@ return 0; } } - if (!list_empty(&sdev->starved_entry)) - return 0; if ((shost->can_queue > 0 && shost->host_busy >= shost->can_queue) || shost->host_blocked || shost->host_self_blocked) { - list_add_tail(&sdev->starved_entry, &shost->starved_list); + if (list_empty(&sdev->starved_entry)) + list_add_tail(&sdev->starved_entry, &shost->starved_list); return 0; } + /* We're OK to process the command, so we can't be starved */ + if (!list_empty(&sdev->starved_entry)) + list_del_init(&sdev->starved_entry); + return 1; } @@ -1128,6 +1132,7 @@ * the host is no longer able to accept any more requests. */ while (!blk_queue_plugged(q)) { + int rtn; /* * get next queueable request. We do this early to make sure * that the request is fully prepared even if we cannot @@ -1181,8 +1186,17 @@ /* * Dispatch the command to the low-level driver. */ - scsi_dispatch_cmd(cmd); + rtn = scsi_dispatch_cmd(cmd); spin_lock_irq(q->queue_lock); + if(rtn) { + /* we're refusing the command; because of + * the way locks get dropped, we need to + * check here if plugging is required */ + if(sdev->device_busy == 0) + blk_plug_device(q); + + break; + } } return; @@ -1203,6 +1217,8 @@ blk_queue_end_tag(q, req); __elv_add_request(q, req, 0, 0); sdev->device_busy--; + if(sdev->device_busy == 0) + blk_plug_device(q); } u64 scsi_calculate_bounce_limit(struct Scsi_Host *shost) @@ -1335,4 +1351,128 @@ mempool_destroy(sgp->pool); kmem_cache_destroy(sgp->slab); } +} +/** + * __scsi_mode_sense - issue a mode sense, falling back from 10 to + * six bytes if necessary. + * @sreq: SCSI request to fill in with the MODE_SENSE + * @dbd: set if mode sense will allow block descriptors to be returned + * @modepage: mode page being requested + * @buffer: request buffer (may not be smaller than eight bytes) + * @len: length of request buffer. + * @timeout: command timeout + * @retries: number of retries before failing + * @data: returns a structure abstracting the mode header data + * + * Returns zero if unsuccessful, or the header offset (either 4 + * or 8 depending on whether a six or ten byte command was + * issued) if successful. + **/ +int +__scsi_mode_sense(struct scsi_request *sreq, int dbd, int modepage, + unsigned char *buffer, int len, int timeout, int retries, + struct scsi_mode_data *data) { + unsigned char cmd[12]; + int use_10_for_ms; + int header_length; + + memset(data, 0, sizeof(*data)); + memset(&cmd[0], 0, 12); + cmd[1] = dbd & 0x18; /* allows DBD and LLBA bits */ + cmd[2] = modepage; + + retry: + use_10_for_ms = sreq->sr_device->use_10_for_ms; + + if (use_10_for_ms) { + if (len < 8) + len = 8; + + cmd[0] = MODE_SENSE_10; + cmd[8] = len; + header_length = 8; + } else { + if (len < 4) + len = 4; + + cmd[0] = MODE_SENSE; + cmd[4] = len; + header_length = 4; + } + + sreq->sr_cmd_len = 0; + sreq->sr_sense_buffer[0] = 0; + sreq->sr_sense_buffer[2] = 0; + sreq->sr_data_direction = DMA_FROM_DEVICE; + + memset(buffer, 0, len); + + scsi_wait_req(sreq, cmd, buffer, len, timeout, retries); + + /* This code looks awful: what it's doing is making sure an + * ILLEGAL REQUEST sense return identifies the actual command + * byte as the problem. MODE_SENSE commands can return + * ILLEGAL REQUEST if the code page isn't supported */ + if (use_10_for_ms && ! scsi_status_is_good(sreq->sr_result) && + (driver_byte(sreq->sr_result) & DRIVER_SENSE) && + sreq->sr_sense_buffer[2] == ILLEGAL_REQUEST && + (sreq->sr_sense_buffer[4] & 0x40) == 0x40 && + sreq->sr_sense_buffer[5] == 0 && + sreq->sr_sense_buffer[6] == 0 ) { + sreq->sr_device->use_10_for_ms = 0; + goto retry; + } + + if(scsi_status_is_good(sreq->sr_result)) { + data->header_length = header_length; + if(use_10_for_ms) { + data->length = buffer[0]*256 + buffer[1]; + data->medium_type = buffer[2]; + data->device_specific = buffer[3]; + data->longlba = buffer[4] & 0x01; + data->block_descriptor_length = buffer[6]*256 + + buffer[7]; + } else { + data->length = buffer[0]; + data->medium_type = buffer[1]; + data->device_specific = buffer[3]; + data->block_descriptor_length = buffer[4]; + } + } + + return sreq->sr_result; +} + +/** + * scsi_mode_sense - issue a mode sense, falling back from 10 to + * six bytes if necessary. + * @sdev: scsi device to send command to. + * @dbd: set if mode sense will disable block descriptors in the return + * @modepage: mode page being requested + * @buffer: request buffer (may not be smaller than eight bytes) + * @len: length of request buffer. + * @timeout: command timeout + * @retries: number of retries before failing + * + * Returns zero if unsuccessful, or the header offset (either 4 + * or 8 depending on whether a six or ten byte command was + * issued) if successful. + **/ +int +scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, + unsigned char *buffer, int len, int timeout, int retries, + struct scsi_mode_data *data) +{ + struct scsi_request *sreq = scsi_allocate_request(sdev); + int ret; + + if (!sreq) + return -1; + + ret = __scsi_mode_sense(sreq, dbd, modepage, buffer, len, + timeout, retries, data); + + scsi_release_request(sreq); + + return ret; } diff -Nru a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c --- a/drivers/scsi/scsi_scan.c Tue Jul 1 18:44:37 2003 +++ b/drivers/scsi/scsi_scan.c Tue Jul 1 18:44:37 2003 @@ -33,6 +33,7 @@ #include "scsi.h" #include "hosts.h" +#include #include "scsi_priv.h" #include "scsi_logging.h" @@ -116,7 +117,7 @@ scsi_cmd[4] = 0x2a; /* size */ scsi_cmd[5] = 0; sreq->sr_cmd_len = 0; - sreq->sr_data_direction = SCSI_DATA_READ; + sreq->sr_data_direction = DMA_FROM_DEVICE; scsi_wait_req(sreq, scsi_cmd, result, 0x2a /* size */, SCSI_TIMEOUT, 3); } @@ -333,7 +334,7 @@ scsi_cmd[0] = INQUIRY; scsi_cmd[4] = 36; /* issue conservative alloc_length */ sreq->sr_cmd_len = 0; - sreq->sr_data_direction = SCSI_DATA_READ; + sreq->sr_data_direction = DMA_FROM_DEVICE; memset(inq_result, 0, 36); scsi_wait_req(sreq, (void *) scsi_cmd, (void *) inq_result, 36, @@ -379,7 +380,7 @@ scsi_cmd[0] = INQUIRY; scsi_cmd[4] = (unsigned char) possible_inq_resp_len; sreq->sr_cmd_len = 0; - sreq->sr_data_direction = SCSI_DATA_READ; + sreq->sr_data_direction = DMA_FROM_DEVICE; /* * re-zero inq_result just to be safe. */ @@ -940,7 +941,7 @@ scsi_cmd[10] = 0; /* reserved */ scsi_cmd[11] = 0; /* control */ sreq->sr_cmd_len = 0; - sreq->sr_data_direction = SCSI_DATA_READ; + sreq->sr_data_direction = DMA_FROM_DEVICE; /* * We can get a UNIT ATTENTION, for example a power on/reset, so diff -Nru a/drivers/scsi/scsi_syms.c b/drivers/scsi/scsi_syms.c --- a/drivers/scsi/scsi_syms.c Tue Jul 1 18:44:35 2003 +++ b/drivers/scsi/scsi_syms.c Tue Jul 1 18:44:35 2003 @@ -19,6 +19,7 @@ #include #include "scsi.h" +#include #include #include "hosts.h" #include "scsi_logging.h" @@ -85,6 +86,9 @@ EXPORT_SYMBOL(scsi_add_device); EXPORT_SYMBOL(scsi_remove_device); EXPORT_SYMBOL(scsi_set_device_offline); + +EXPORT_SYMBOL(__scsi_mode_sense); +EXPORT_SYMBOL(scsi_mode_sense); /* * This symbol is for the highlevel drivers (e.g. sg) only. diff -Nru a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c --- a/drivers/scsi/scsi_sysfs.c Tue Jul 1 18:44:33 2003 +++ b/drivers/scsi/scsi_sysfs.c Tue Jul 1 18:44:33 2003 @@ -195,19 +195,13 @@ sdev_rw_attr_bit (online); static ssize_t -show_rescan_field (struct device *dev, char *buf) -{ - return 0; -} - -static ssize_t store_rescan_field (struct device *dev, const char *buf, size_t count) { scsi_rescan_device(dev); - return 0; + return count; } -static DEVICE_ATTR(rescan, S_IRUGO | S_IWUSR, show_rescan_field, store_rescan_field) +static DEVICE_ATTR(rescan, S_IWUSR, NULL, store_rescan_field) /* Default template for device attributes. May NOT be modified */ struct device_attribute *scsi_sysfs_sdev_attrs[] = { @@ -388,30 +382,36 @@ * * returns zero if successful or error if not **/ -int scsi_sysfs_modify_shost_attribute(struct class_device_attribute ***class_attrs, - struct class_device_attribute *attr) +int scsi_sysfs_modify_shost_attribute( + struct class_device_attribute ***class_attrs, + struct class_device_attribute *attr) { - int modify = 0; + int modify = -1; int num_attrs; if(*class_attrs == NULL) *class_attrs = scsi_sysfs_shost_attrs; for(num_attrs=0; (*class_attrs)[num_attrs] != NULL; num_attrs++) - if(strcmp((*class_attrs)[num_attrs]->attr.name, attr->attr.name) == 0) + if(strcmp((*class_attrs)[num_attrs]->attr.name, + attr->attr.name) == 0) modify = num_attrs; - if(*class_attrs == scsi_sysfs_shost_attrs || !modify) { + if(*class_attrs == scsi_sysfs_shost_attrs || modify < 0) { /* note: need space for null at the end as well */ - struct class_device_attribute **tmp_attrs = kmalloc(sizeof(struct class_device_attribute)*(num_attrs + (modify ? 1 : 2)), GFP_KERNEL); + struct class_device_attribute **tmp_attrs = + kmalloc(sizeof(*tmp_attrs) * + (num_attrs + (modify >= 0 ? 1 : 2)), + GFP_KERNEL); if(tmp_attrs == NULL) return -ENOMEM; - memcpy(tmp_attrs, *class_attrs, sizeof(struct class_device_attribute)*num_attrs); + memcpy(tmp_attrs, *class_attrs, sizeof(*tmp_attrs) * + (num_attrs + 1)); if(*class_attrs != scsi_sysfs_shost_attrs) kfree(*class_attrs); *class_attrs = tmp_attrs; } - if(modify) { + if(modify >= 0) { /* spare the caller from having to copy things it's * not interested in */ struct class_device_attribute *old_attr = @@ -444,27 +444,32 @@ int scsi_sysfs_modify_sdev_attribute(struct device_attribute ***dev_attrs, struct device_attribute *attr) { - int modify = 0; + int modify = -1; int num_attrs; if(*dev_attrs == NULL) *dev_attrs = scsi_sysfs_sdev_attrs; for(num_attrs=0; (*dev_attrs)[num_attrs] != NULL; num_attrs++) - if(strcmp((*dev_attrs)[num_attrs]->attr.name, attr->attr.name) == 0) + if(strcmp((*dev_attrs)[num_attrs]->attr.name, + attr->attr.name) == 0) modify = num_attrs; - if(*dev_attrs == scsi_sysfs_sdev_attrs || !modify) { + if(*dev_attrs == scsi_sysfs_sdev_attrs || modify < 0) { /* note: need space for null at the end as well */ - struct device_attribute **tmp_attrs = kmalloc(sizeof(struct device_attribute)*(num_attrs + (modify ? 1 : 2)), GFP_KERNEL); + struct device_attribute **tmp_attrs = + kmalloc(sizeof(*tmp_attrs) * + (num_attrs + (modify >= 0 ? 1 : 2)), + GFP_KERNEL); if(tmp_attrs == NULL) return -ENOMEM; - memcpy(tmp_attrs, *dev_attrs, sizeof(struct device_attribute)*num_attrs); + memcpy(tmp_attrs, *dev_attrs, sizeof(*tmp_attrs) * + (num_attrs + 1)); if(*dev_attrs != scsi_sysfs_sdev_attrs) kfree(*dev_attrs); *dev_attrs = tmp_attrs; } - if(modify) { + if(modify >= 0) { /* spare the caller from having to copy things it's * not interested in */ struct device_attribute *old_attr = diff -Nru a/drivers/scsi/sd.c b/drivers/scsi/sd.c --- a/drivers/scsi/sd.c Tue Jul 1 18:44:36 2003 +++ b/drivers/scsi/sd.c Tue Jul 1 18:44:36 2003 @@ -49,6 +49,8 @@ #include "scsi.h" #include "hosts.h" + +#include #include #include @@ -161,11 +163,11 @@ memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd)); if (rq_data_dir(rq) == WRITE) - SCpnt->sc_data_direction = SCSI_DATA_WRITE; + SCpnt->sc_data_direction = DMA_TO_DEVICE; else if (rq->data_len) - SCpnt->sc_data_direction = SCSI_DATA_READ; + SCpnt->sc_data_direction = DMA_FROM_DEVICE; else - SCpnt->sc_data_direction = SCSI_DATA_NONE; + SCpnt->sc_data_direction = DMA_NONE; this_count = rq->data_len; if (rq->timeout) @@ -251,10 +253,10 @@ return 0; } SCpnt->cmnd[0] = WRITE_6; - SCpnt->sc_data_direction = SCSI_DATA_WRITE; + SCpnt->sc_data_direction = DMA_TO_DEVICE; } else if (rq_data_dir(SCpnt->request) == READ) { SCpnt->cmnd[0] = READ_6; - SCpnt->sc_data_direction = SCSI_DATA_READ; + SCpnt->sc_data_direction = DMA_FROM_DEVICE; } else { printk(KERN_ERR "sd: Unknown command %lx\n", SCpnt->request->flags); @@ -790,7 +792,7 @@ SRpnt->sr_cmd_len = 0; SRpnt->sr_sense_buffer[0] = 0; SRpnt->sr_sense_buffer[2] = 0; - SRpnt->sr_data_direction = SCSI_DATA_NONE; + SRpnt->sr_data_direction = DMA_NONE; scsi_wait_req (SRpnt, (void *) cmd, (void *) buffer, 0/*512*/, SD_TIMEOUT, SD_MAX_RETRIES); @@ -850,7 +852,7 @@ SRpnt->sr_sense_buffer[0] = 0; SRpnt->sr_sense_buffer[2] = 0; - SRpnt->sr_data_direction = SCSI_DATA_NONE; + SRpnt->sr_data_direction = DMA_NONE; scsi_wait_req(SRpnt, (void *)cmd, (void *) buffer, 0/*512*/, SD_TIMEOUT, SD_MAX_RETRIES); @@ -915,7 +917,7 @@ SRpnt->sr_cmd_len = 0; SRpnt->sr_sense_buffer[0] = 0; SRpnt->sr_sense_buffer[2] = 0; - SRpnt->sr_data_direction = SCSI_DATA_READ; + SRpnt->sr_data_direction = DMA_FROM_DEVICE; scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer, longrc ? 12 : 8, SD_TIMEOUT, SD_MAX_RETRIES); @@ -1062,40 +1064,12 @@ } /* called with buffer of length 512 */ -static int +static inline int sd_do_mode_sense(struct scsi_request *SRpnt, int dbd, int modepage, - unsigned char *buffer, int len) { - unsigned char cmd[12]; - - memset((void *) &cmd[0], 0, 12); - cmd[1] = dbd; - cmd[2] = modepage; - - if (SRpnt->sr_device->use_10_for_ms) { - if (len < 8) - len = 8; - - cmd[0] = MODE_SENSE_10; - cmd[8] = len; - } else { - if (len < 4) - len = 4; - - cmd[0] = MODE_SENSE; - cmd[4] = len; - } - - SRpnt->sr_cmd_len = 0; - SRpnt->sr_sense_buffer[0] = 0; - SRpnt->sr_sense_buffer[2] = 0; - SRpnt->sr_data_direction = SCSI_DATA_READ; - - memset((void *) buffer, 0, len); - - scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer, - len, SD_TIMEOUT, SD_MAX_RETRIES); - - return SRpnt->sr_result; + unsigned char *buffer, int len, struct scsi_mode_data *data) +{ + return __scsi_mode_sense(SRpnt, dbd, modepage, buffer, len, + SD_TIMEOUT, SD_MAX_RETRIES, data); } /* @@ -1106,33 +1080,34 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname, struct scsi_request *SRpnt, unsigned char *buffer) { int res; + struct scsi_mode_data data; /* * First attempt: ask for all pages (0x3F), but only 4 bytes. * We have to start carefully: some devices hang if we ask * for more than is available. */ - res = sd_do_mode_sense(SRpnt, 0, 0x3F, buffer, 4); + res = sd_do_mode_sense(SRpnt, 0, 0x3F, buffer, 4, &data); /* * Second attempt: ask for page 0 * When only page 0 is implemented, a request for page 3F may return * Sense Key 5: Illegal Request, Sense Code 24: Invalid field in CDB. */ - if (res) - res = sd_do_mode_sense(SRpnt, 0, 0, buffer, 4); + if (!scsi_status_is_good(res)) + res = sd_do_mode_sense(SRpnt, 0, 0, buffer, 4, &data); /* * Third attempt: ask 255 bytes, as we did earlier. */ - if (res) - res = sd_do_mode_sense(SRpnt, 0, 0x3F, buffer, 255); + if (!scsi_status_is_good(res)) + res = sd_do_mode_sense(SRpnt, 0, 0x3F, buffer, 255, &data); - if (res) { + if (!scsi_status_is_good(res)) { printk(KERN_WARNING "%s: test WP failed, assume Write Enabled\n", diskname); } else { - sdkp->write_prot = ((buffer[2] & 0x80) != 0); + sdkp->write_prot = ((data.device_specific & 0x80) != 0); printk(KERN_NOTICE "%s: Write Protect is %s\n", diskname, sdkp->write_prot ? "on" : "off"); printk(KERN_DEBUG "%s: Mode Sense: %02x %02x %02x %02x\n", @@ -1149,43 +1124,45 @@ struct scsi_request *SRpnt, unsigned char *buffer) { int len = 0, res; - const int dbd = 0x08; /* DBD */ + const int dbd = 0; /* DBD */ const int modepage = 0x08; /* current values, cache page */ + struct scsi_mode_data data; + /* cautiously ask */ - res = sd_do_mode_sense(SRpnt, dbd, modepage, buffer, 4); + res = sd_do_mode_sense(SRpnt, dbd, modepage, buffer, 4, &data); - if (res == 0) { + if (scsi_status_is_good(res)) { /* that went OK, now ask for the proper length */ - len = buffer[0] + 1; + len = data.length; if (len > 128) len = 128; - res = sd_do_mode_sense(SRpnt, dbd, modepage, buffer, len); + res = sd_do_mode_sense(SRpnt, dbd, modepage, buffer, + len, &data); } - if (res == 0 && buffer[3] + 6 < len) { + if (scsi_status_is_good(res)) { const char *types[] = { "write through", "none", "write back", "write back, no read (daft)" }; int ct = 0; - int offset = buffer[3] + 4; /* start of mode page */ + int offset = data.header_length + + data.block_descriptor_length + 2; - sdkp->WCE = ((buffer[offset + 2] & 0x04) != 0); - sdkp->RCD = ((buffer[offset + 2] & 0x01) != 0); + sdkp->WCE = ((buffer[offset] & 0x04) != 0); + sdkp->RCD = ((buffer[offset] & 0x01) != 0); ct = sdkp->RCD + 2*sdkp->WCE; printk(KERN_NOTICE "SCSI device %s: drive cache: %s\n", diskname, types[ct]); } else { - if (res == 0 || - (status_byte(res) == CHECK_CONDITION - && (SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 + if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 && (SRpnt->sr_sense_buffer[2] & 0x0f) == ILLEGAL_REQUEST /* ASC 0x24 ASCQ 0x00: Invalid field in CDB */ && SRpnt->sr_sense_buffer[12] == 0x24 - && SRpnt->sr_sense_buffer[13] == 0x00)) { + && SRpnt->sr_sense_buffer[13] == 0x00) { printk(KERN_NOTICE "%s: cache data unavailable\n", diskname); } else { @@ -1417,7 +1394,7 @@ return; } - sreq->sr_data_direction = SCSI_DATA_NONE; + sreq->sr_data_direction = DMA_NONE; for (retries = 3; retries > 0; --retries) { unsigned char cmd[10] = { 0 }; diff -Nru a/drivers/scsi/seagate.c b/drivers/scsi/seagate.c --- a/drivers/scsi/seagate.c Tue Jul 1 18:44:34 2003 +++ b/drivers/scsi/seagate.c Tue Jul 1 18:44:34 2003 @@ -266,20 +266,6 @@ #define WRITE_CONTROL(d) { isa_writeb((d), st0x_cr_sr); } #define WRITE_DATA(d) { isa_writeb((d), st0x_dr); } -static void st0x_setup (char *str, int *ints) -{ - controller_type = SEAGATE; - base_address = ints[1]; - irq = ints[2]; -} - -static void tmc8xx_setup (char *str, int *ints) -{ - controller_type = FD; - base_address = ints[1]; - irq = ints[2]; -} - #ifndef OVERRIDE static unsigned int seagate_bases[] = { 0xc8000, 0xca000, 0xcc000, diff -Nru a/drivers/scsi/seagate.h b/drivers/scsi/seagate.h --- a/drivers/scsi/seagate.h Tue Jul 1 18:44:37 2003 +++ b/drivers/scsi/seagate.h Tue Jul 1 18:44:37 2003 @@ -10,7 +10,6 @@ #define SEAGATE_H static int seagate_st0x_detect(Scsi_Host_Template *); -static int seagate_st0x_command(Scsi_Cmnd *); static int seagate_st0x_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); static int seagate_st0x_abort(Scsi_Cmnd *); diff -Nru a/drivers/scsi/sg.c b/drivers/scsi/sg.c --- a/drivers/scsi/sg.c Tue Jul 1 18:44:34 2003 +++ b/drivers/scsi/sg.c Tue Jul 1 18:44:34 2003 @@ -64,6 +64,7 @@ #include #include "scsi.h" #include "hosts.h" +#include #include #include diff -Nru a/drivers/scsi/sr.c b/drivers/scsi/sr.c --- a/drivers/scsi/sr.c Tue Jul 1 18:44:33 2003 +++ b/drivers/scsi/sr.c Tue Jul 1 18:44:33 2003 @@ -48,6 +48,8 @@ #include "scsi.h" #include "hosts.h" + +#include #include /* For the door lock/unlock commands */ #include "scsi_logging.h" @@ -65,7 +67,7 @@ (CDC_CLOSE_TRAY|CDC_OPEN_TRAY|CDC_LOCK|CDC_SELECT_SPEED| \ CDC_SELECT_DISC|CDC_MULTI_SESSION|CDC_MCN|CDC_MEDIA_CHANGED| \ CDC_PLAY_AUDIO|CDC_RESET|CDC_IOCTLS|CDC_DRIVE_STATUS| \ - CDC_CD_R|CDC_CD_RW|CDC_DVD|CDC_DVD_R|CDC_GENERIC_PACKET) + CDC_CD_R|CDC_CD_RW|CDC_DVD|CDC_DVD_R|CDC_DVD_RAM|CDC_GENERIC_PACKET) static int sr_probe(struct device *); static int sr_remove(struct device *); @@ -660,9 +662,9 @@ static void get_capabilities(struct scsi_cd *cd) { - struct cdrom_generic_command cgc; unsigned char *buffer; int rc, n; + struct scsi_mode_data data; static char *loadmech[] = { @@ -681,18 +683,10 @@ printk(KERN_ERR "sr: out of memory.\n"); return; } - memset(&cgc, 0, sizeof(struct cdrom_generic_command)); - cgc.cmd[0] = MODE_SENSE; - cgc.cmd[2] = 0x2a; - cgc.cmd[4] = 128; - cgc.buffer = buffer; - cgc.buflen = 128; - cgc.quiet = 1; - cgc.data_direction = SCSI_DATA_READ; - cgc.timeout = SR_TIMEOUT; - rc = sr_do_ioctl(cd, &cgc); + rc = scsi_mode_sense(cd->device, 0, 0x2a, buffer, 128, + SR_TIMEOUT, 3, &data); - if (rc) { + if (!scsi_status_is_good(rc)) { /* failed, drive doesn't have capabilities mode page */ cd->cdi.speed = 1; cd->cdi.mask |= (CDC_CD_R | CDC_CD_RW | CDC_DVD_R | @@ -702,7 +696,7 @@ printk("%s: scsi-1 drive\n", cd->cdi.name); return; } - n = buffer[3] + 4; + n = data.header_length + data.block_descriptor_length; cd->cdi.speed = ((buffer[n + 8] << 8) + buffer[n + 9]) / 176; cd->readcd_known = 1; cd->readcd_cdda = buffer[n + 5] & 0x01; diff -Nru a/drivers/scsi/st.c b/drivers/scsi/st.c --- a/drivers/scsi/st.c Tue Jul 1 18:44:36 2003 +++ b/drivers/scsi/st.c Tue Jul 1 18:44:36 2003 @@ -58,6 +58,8 @@ #include "scsi.h" #include "hosts.h" + +#include #include #define ST_KILOBYTE 1024 diff -Nru a/drivers/scsi/sym53c416.h b/drivers/scsi/sym53c416.h --- a/drivers/scsi/sym53c416.h Tue Jul 1 18:44:36 2003 +++ b/drivers/scsi/sym53c416.h Tue Jul 1 18:44:36 2003 @@ -25,7 +25,6 @@ static int sym53c416_detect(Scsi_Host_Template *); static const char *sym53c416_info(struct Scsi_Host *); static int sym53c416_release(struct Scsi_Host *); -static int sym53c416_command(Scsi_Cmnd *); static int sym53c416_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); static int sym53c416_abort(Scsi_Cmnd *); static int sym53c416_host_reset(Scsi_Cmnd *); diff -Nru a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c --- a/drivers/scsi/sym53c8xx_2/sym_glue.c Tue Jul 1 18:44:39 2003 +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c Tue Jul 1 18:44:39 2003 @@ -295,12 +295,8 @@ #ifndef SYM_LINUX_DYNAMIC_DMA_MAPPING typedef u_long bus_addr_t; #else -#if SYM_CONF_DMA_ADDRESSING_MODE > 0 -typedef dma64_addr_t bus_addr_t; -#else typedef dma_addr_t bus_addr_t; #endif -#endif /* * Used by the eh thread to wait for command completion. @@ -1863,7 +1859,7 @@ #if SYM_CONF_DMA_ADDRESSING_MODE == 1 #define PciDmaMask 0xffffffffff #elif SYM_CONF_DMA_ADDRESSING_MODE == 2 -#define PciDmaMask 0xffffffffffffffff +#define PciDmaMask 0xffffffffffffffffULL #endif if (np->features & FE_DAC) { if (!pci_set_dma_mask(np->s.device, PciDmaMask)) { @@ -2752,14 +2748,6 @@ } /* This one is guaranteed by AC to do nothing :-) */ if (pci_enable_device(pcidev)) - continue; - /* Some HW as the HP LH4 may report twice PCI devices */ - for (i = 0; i < count ; i++) { - if (devtbl[i].s.bus == PciBusNumber(pcidev) && - devtbl[i].s.device_fn == PciDeviceFn(pcidev)) - break; - } - if (i != count) /* Ignore this device if we already have it */ continue; devp = &devtbl[count]; devp->host_id = SYM_SETUP_HOST_ID; diff -Nru a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c Tue Jul 1 18:44:31 2003 +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c Tue Jul 1 18:44:31 2003 @@ -4641,7 +4641,10 @@ case M_IGN_RESIDUE: if (DEBUG_FLAGS & DEBUG_POINTER) sym_print_msg(cp,"ign wide residue", np->msgin); - sym_modify_dp(np, tp, cp, -1); + if (cp->host_flags & HF_SENSE) + OUTL_DSP (SCRIPTA_BA (np, clrack)); + else + sym_modify_dp(np, tp, cp, -1); return; case M_REJECT: if (INB (HS_PRT) == HS_NEGOTIATE) diff -Nru a/drivers/scsi/sym53c8xx_comm.h b/drivers/scsi/sym53c8xx_comm.h --- a/drivers/scsi/sym53c8xx_comm.h Tue Jul 1 18:44:35 2003 +++ b/drivers/scsi/sym53c8xx_comm.h Tue Jul 1 18:44:35 2003 @@ -795,7 +795,7 @@ dma_addr_t daddr; vp = (m_addr_t) dma_alloc_coherent(mp->bush, PAGE_SIZE<vaddr = vp; @@ -1097,66 +1097,6 @@ #define initverbose (driver_setup.verbose) #define bootverbose (np->verbose) - -/*========================================================== -** -** Structures used by the detection routine to transmit -** device configuration to the attach function. -** -**========================================================== -*/ -typedef struct { - int bus; - u_char device_fn; - u_long base; - u_long base_2; - u_long io_port; - u_long base_c; - u_long base_2_c; - int irq; -/* port and reg fields to use INB, OUTB macros */ - u_long base_io; - volatile struct ncr_reg *reg; -} ncr_slot; - -/*========================================================== -** -** Structure used to store the NVRAM content. -** -**========================================================== -*/ -typedef struct { - int type; -#define SCSI_NCR_SYMBIOS_NVRAM (1) -#define SCSI_NCR_TEKRAM_NVRAM (2) -#ifdef SCSI_NCR_NVRAM_SUPPORT - union { - Symbios_nvram Symbios; - Tekram_nvram Tekram; - } data; -#endif -} ncr_nvram; - -/*========================================================== -** -** Structure used by detection routine to save data on -** each detected board for attach. -** -**========================================================== -*/ -typedef struct { - device_t dev; - ncr_slot slot; - ncr_chip chip; - ncr_nvram *nvram; - u_char host_id; -#ifdef SCSI_NCR_PQS_PDS_SUPPORT - u_char pqs_pds; -#endif - int attach_done; -} ncr_device; - -static int ncr_attach (Scsi_Host_Template *tpnt, int unit, ncr_device *device); /*========================================================== ** diff -Nru a/drivers/scsi/sym53c8xx_defs.h b/drivers/scsi/sym53c8xx_defs.h --- a/drivers/scsi/sym53c8xx_defs.h Tue Jul 1 18:44:37 2003 +++ b/drivers/scsi/sym53c8xx_defs.h Tue Jul 1 18:44:37 2003 @@ -85,7 +85,7 @@ /* * No more an option, enabled by default. */ -#ifndef ENABLE_SCSI_ZALON +#ifndef CONFIG_SCSI_NCR53C8XX_NO_NVRAM # ifndef CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT # define CONFIG_SCSI_NCR53C8XX_NVRAM_DETECT # endif @@ -188,10 +188,6 @@ #define SCSI_NCR_IOMAPPED #define SCSI_NCR_PCI_MEM_NOT_SUPPORTED #endif -#elif defined(__sparc__) -#undef SCSI_NCR_IOMAPPED -#elif defined(__hppa__) && defined(ENABLE_SCSI_ZALON) -#undef SCSI_NCR_IOMAPPED #endif /* @@ -532,7 +528,6 @@ */ #if defined(SCSI_NCR_IOMAPPED) - /* * IO mapped only input / ouput */ @@ -593,7 +588,7 @@ #else -#ifdef ENABLE_SCSI_ZALON +#ifdef CONFIG_SCSI_NCR53C8XX_NO_WORD_TRANSFERS /* Only 8 or 32 bit transfers allowed */ #define INW_OFF(o) (readb((char *)np->reg + ncr_offw(o)) << 8 | readb((char *)np->reg + ncr_offw(o) + 1)) #else @@ -601,7 +596,7 @@ #endif #define INL_OFF(o) readl_raw((char *)np->reg + (o)) -#ifdef ENABLE_SCSI_ZALON +#ifdef CONFIG_SCSI_NCR53C8XX_NO_WORD_TRANSFERS /* Only 8 or 32 bit transfers allowed */ #define OUTW_OFF(o, val) do { writeb((char)((val) >> 8), (char *)np->reg + ncr_offw(o)); writeb((char)(val), (char *)np->reg + ncr_offw(o) + 1); } while (0) #else @@ -654,8 +649,8 @@ ** NCR53C8XX Device Ids */ -#ifndef PSEUDO_ZALON_720_ID -#define PSEUDO_ZALON_720_ID 0x5a00 +#ifndef PSEUDO_720_ID +#define PSEUDO_720_ID 0x5a00 #endif #ifndef PCI_DEVICE_ID_NCR_53C810 @@ -785,7 +780,7 @@ #define SCSI_NCR_CHIP_TABLE \ { \ - {PSEUDO_ZALON_720_ID, 0x0f, "720", 3, 8, 4, \ + {PSEUDO_720_ID, 0x0f, "720", 3, 8, 4, \ FE_WIDE|FE_DIFF|FE_EHP|FE_MUX|FE_EA} \ , \ {PCI_DEVICE_ID_NCR_53C810, 0x0f, "810", 4, 8, 4, \ @@ -860,7 +855,7 @@ */ #define SCSI_NCR_CHIP_IDS \ { \ - PSEUDO_ZALON_720_ID, \ + PSEUDO_720_ID, \ PCI_DEVICE_ID_NCR_53C810, \ PCI_DEVICE_ID_NCR_53C815, \ PCI_DEVICE_ID_NCR_53C820, \ diff -Nru a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c --- a/drivers/scsi/zalon.c Tue Jul 1 18:44:36 2003 +++ b/drivers/scsi/zalon.c Tue Jul 1 18:44:36 2003 @@ -24,30 +24,24 @@ #include "scsi.h" #include "hosts.h" -/* - * ** Define the BSD style u_int32 and u_int64 type. - * ** Are in fact u_int32_t and u_int64_t :-) - * */ -typedef u32 u_int32; -typedef u64 u_int64; -typedef u_long vm_offset_t; +#include "ncr53c8xx.h" #include "zalon.h" +MODULE_AUTHOR("Richard Hirst"); +MODULE_DESCRIPTION("Bluefish/Zalon 720 SCSI Driver"); +MODULE_LICENSE("GPL"); + +static ncr_chip zalon720_chip __initdata = { + .device_id = PSEUDO_720_ID, + .revision_id = 0x0f, + .name = "720", + .burst_max = 3, + .offset_max = 8, + .nr_divisor = 4, + .features = FE_WIDE | FE_DIFF | FE_EHP| FE_MUX | FE_EA, +}; -/* hosts_* are kluges to pass info between the zalon7xx_detected() -** and the register_parisc_driver() callbacks. -*/ -static Scsi_Host_Template *hosts_tptr; -static int hosts_used=0; -static int zalon_id = 0; - -extern int zalon_attach(Scsi_Host_Template *tpnt, - unsigned long base_addr, - struct parisc_device *dev, - int irq_vector, - int unit - ); #if 0 @@ -81,6 +75,11 @@ } #endif +static Scsi_Host_Template zalon7xx_template = { + .module = THIS_MODULE, + .proc_name = "zalon7xx", +}; + static int __init zalon_scsi_callback(struct parisc_device *dev) { @@ -88,6 +87,10 @@ u32 zalon_vers; int irq; unsigned long zalon = dev->hpa; + unsigned long io_port = zalon + GSC_SCSI_ZALON_OFFSET; + static int unit = 0; + struct Scsi_Host *host; + ncr_device device; __raw_writel(CMD_RESET, zalon + IO_MODULE_IO_COMMAND); while (!(__raw_readl(zalon + IO_MODULE_IO_STATUS) & IOSTATUS_RY)) @@ -112,17 +115,43 @@ if ( zalon_vers == 0) printk(KERN_WARNING "%s: Zalon 1.1 or earlier\n", __FUNCTION__); - /* - ** zalon_attach: returns -1 on failure, 0 on success - */ - hosts_used = zalon_attach(hosts_tptr, dev->hpa + GSC_SCSI_ZALON_OFFSET, - dev, irq, zalon_id); + memset(&device, 0, sizeof(ncr_device)); + + /* The following three are needed before any other access. */ + writeb(0x20, io_port + 0x38); /* DCNTL_REG, EA */ + writeb(0x04, io_port + 0x1b); /* CTEST0_REG, EHP */ + writeb(0x80, io_port + 0x22); /* CTEST4_REG, MUX */ + + /* Initialise ncr_device structure with items required by ncr_attach. */ + device.chip = zalon720_chip; + device.host_id = 7; + device.dev = &dev->dev; + device.slot.base = (u_long)io_port; + device.slot.base_c = (u_long)io_port; + device.slot.irq = irq; + device.differential = 2; + + host = ncr_attach(&zalon7xx_template, unit, &device); + if(!host) + goto fail; + + strlcpy(dev->dev.name, "zalon7xx", sizeof(dev->dev.name)); + + if(request_irq(irq, ncr53c8xx_intr, SA_SHIRQ, dev->dev.name, host)) { + printk(KERN_ERR "%s: irq problem with %d, detaching\n ", + dev->dev.name, irq); + goto fail; + } + + unit++; + + dev_set_drvdata(&dev->dev, host); - if (hosts_used == 0) - zalon_id++; + scsi_add_host(host, &dev->dev); - hosts_used = (hosts_used == 0); - return (hosts_used == 0); + return 0; + fail: + return -ENODEV; } static struct parisc_device_id zalon_tbl[] = { @@ -132,30 +161,35 @@ MODULE_DEVICE_TABLE(parisc, zalon_tbl); +static int __exit zalon_remove(struct parisc_device *dev) +{ + struct Scsi_Host *host = dev_get_drvdata(&dev->dev); + int irq = host->irq; + + scsi_remove_host(host); + ncr53c8xx_release(host); + free_irq(irq, host); + + return 0; +} + + static struct parisc_driver zalon_driver = { .name = "GSC SCSI (Zalon)", .id_table = zalon_tbl, .probe = zalon_scsi_callback, + .remove = __devexit_p(zalon_remove), }; -int zalon7xx_detect(Scsi_Host_Template *tpnt) +static int __init zalon7xx_init(void) { - /* "pass" the parameter to the callback functions */ - hosts_tptr = tpnt; - hosts_used = 0; - - /* claim all zalon cards. */ - register_parisc_driver(&zalon_driver); - - /* Check if any callbacks actually found/claimed anything. */ - return (hosts_used != 0); + return register_parisc_driver(&zalon_driver); } -extern int ncr53c8xx_release(struct Scsi_Host *host); - -int zalon7xx_release(struct Scsi_Host *host) +static void __exit zalon7xx_exit(void) { - ncr53c8xx_release(host); unregister_parisc_driver(&zalon_driver); - return 1; } + +module_init(zalon7xx_init); +module_exit(zalon7xx_exit); diff -Nru a/drivers/scsi/zalon.h b/drivers/scsi/zalon.h --- a/drivers/scsi/zalon.h Tue Jul 1 18:44:35 2003 +++ b/drivers/scsi/zalon.h Tue Jul 1 18:44:35 2003 @@ -2,20 +2,7 @@ #define ZALON7XX_H #include - -#include "sym53c8xx_defs.h" - -extern int zalon7xx_detect(Scsi_Host_Template *); - #include - -extern struct proc_dir_entry proc_scsi_zalon7xx; - -/* borrowed from drivers/scsi/ncr53c8xx.h */ -int zalon7xx_detect(Scsi_Host_Template *tpnt); -const char *ncr53c8xx_info(struct Scsi_Host *host); -int ncr53c8xx_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); -int zalon7xx_release(struct Scsi_Host *); #define GSC_SCSI_ZALON_OFFSET 0x800 diff -Nru a/drivers/serial/8250.c b/drivers/serial/8250.c --- a/drivers/serial/8250.c Tue Jul 1 18:44:31 2003 +++ b/drivers/serial/8250.c Tue Jul 1 18:44:31 2003 @@ -122,13 +122,13 @@ struct uart_port port; struct timer_list timer; /* "no irq" timer */ struct list_head list; /* ports on this IRQ */ + unsigned short rev; unsigned char acr; unsigned char ier; - unsigned char rev; unsigned char lcr; unsigned char mcr_mask; /* mask of user bits */ unsigned char mcr_force; /* mask of forced bits */ - unsigned int lsr_break_flag; + unsigned char lsr_break_flag; /* * We provide a per-port pm hook. diff -Nru a/drivers/serial/8250_cs.c b/drivers/serial/8250_cs.c --- a/drivers/serial/8250_cs.c Tue Jul 1 18:44:35 2003 +++ b/drivers/serial/8250_cs.c Tue Jul 1 18:44:35 2003 @@ -2,7 +2,7 @@ A driver for PCMCIA serial devices - serial_cs.c 1.123 2000/08/24 18:46:38 + serial_cs.c 1.134 2002/05/04 05:48:53 The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file @@ -43,7 +43,6 @@ #include #include #include -#include #include #include @@ -59,7 +58,7 @@ static int pc_debug = PCMCIA_DEBUG; MODULE_PARM(pc_debug, "i"); #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) -static char *version = "serial_cs.c 1.123 2000/08/24 18:46:38 (David Hinds)"; +static char *version = "serial_cs.c 1.134 2002/05/04 05:48:53 (David Hinds)"; #else #define DEBUG(n, args...) #endif @@ -74,10 +73,13 @@ /* Enable the speaker? */ static int do_sound = 1; +/* Skip strict UART tests? */ +static int buggy_uart; MODULE_PARM(irq_mask, "i"); MODULE_PARM(irq_list, "1-4i"); MODULE_PARM(do_sound, "i"); +MODULE_PARM(buggy_uart, "i"); /*====================================================================*/ @@ -100,7 +102,7 @@ }; #define MULTI_COUNT (sizeof(multi_id)/sizeof(struct multi_id)) -typedef struct serial_info { +struct serial_info { dev_link_t link; int ndev; int multi; @@ -108,8 +110,7 @@ int manfid; dev_node_t node[4]; int line[4]; - struct work_struct remove; -} serial_info_t; +}; static void serial_config(dev_link_t * link); static int serial_event(event_t event, int priority, @@ -124,20 +125,19 @@ /*====================================================================== - After a card is removed, do_serial_release() will unregister + After a card is removed, serial_remove() will unregister the serial device(s), and release the PCMCIA configuration. ======================================================================*/ -/* - * This always runs in process context. - */ -static void do_serial_release(void *arg) +static void serial_remove(dev_link_t *link) { - struct serial_info *info = arg; - int i; + struct serial_info *info = link->priv; + int i, ret; - DEBUG(0, "serial_release(0x%p)\n", &info->link); + link->state &= ~DEV_PRESENT; + + DEBUG(0, "serial_release(0x%p)\n", link); /* * Recheck to see if the device is still configured. @@ -158,25 +158,6 @@ } } -/* - * This may be called from IRQ context. - */ -static void serial_remove(dev_link_t *link) -{ - struct serial_info *info = link->priv; - - link->state &= ~DEV_PRESENT; - - /* - * FIXME: Since the card has probably been removed, - * we should call into the serial layer and hang up - * the ports on the card immediately. - */ - - if (link->state & DEV_CONFIG) - schedule_work(&info->remove); -} - /*====================================================================== serial_attach() creates an "instance" of the driver, allocating @@ -187,7 +168,7 @@ static dev_link_t *serial_attach(void) { - serial_info_t *info; + struct serial_info *info; client_reg_t client_reg; dev_link_t *link; int i, ret; @@ -202,8 +183,6 @@ link = &info->link; link->priv = info; - INIT_WORK(&info->remove, do_serial_release, info); - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; link->io.NumPorts1 = 8; link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; @@ -214,7 +193,6 @@ for (i = 0; i < 4; i++) link->irq.IRQInfo2 |= 1 << irq_list[i]; link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.Vcc = 50; if (do_sound) { link->conf.Attributes |= CONF_ENABLE_SPKR; link->conf.Status = CCSR_AUDIO_ENA; @@ -254,7 +232,7 @@ static void serial_detach(dev_link_t * link) { - serial_info_t *info = link->priv; + struct serial_info *info = link->priv; dev_link_t **linkp; int ret; @@ -275,7 +253,7 @@ /* * Ensure that the ports have been released. */ - do_serial_release(info); + serial_remove(link); if (link->handle) { ret = CardServices(DeregisterClient, link->handle); @@ -290,7 +268,7 @@ /*====================================================================*/ -static int setup_serial(serial_info_t * info, ioaddr_t port, int irq) +static int setup_serial(struct serial_info * info, ioaddr_t port, int irq) { struct serial_struct serial; int line; @@ -299,11 +277,13 @@ serial.port = port; serial.irq = irq; serial.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ; + if (buggy_uart) + serial.flags |= UPF_BUGGY_UART; line = register_serial(&serial); if (line < 0) { printk(KERN_NOTICE "serial_cs: register_serial() at 0x%04lx," " irq %d failed\n", (u_long) serial.port, serial.irq); - return -1; + return -EINVAL; } info->line[info->ndev] = line; @@ -341,7 +321,7 @@ { static ioaddr_t base[5] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8, 0x0 }; client_handle_t handle = link->handle; - serial_info_t *info = link->priv; + struct serial_info *info = link->priv; tuple_t tuple; u_char buf[256]; cisparse_t parse; @@ -445,13 +425,21 @@ static int multi_config(dev_link_t * link) { client_handle_t handle = link->handle; - serial_info_t *info = link->priv; + struct serial_info *info = link->priv; tuple_t tuple; u_char buf[256]; cisparse_t parse; cistpl_cftable_entry_t *cf = &parse.cftable_entry; + config_info_t config; int i, base2 = 0; + i = CardServices(GetConfigurationInfo, handle, &config); + if (i != CS_SUCCESS) { + cs_error(handle, GetConfigurationInfo, i); + return -1; + } + link->conf.Vcc = config.Vcc; + tuple.TupleData = (cisdata_t *) buf; tuple.TupleOffset = 0; tuple.TupleDataMax = 255; @@ -524,6 +512,19 @@ return -1; } + /* The Oxford Semiconductor OXCF950 cards are in fact single-port: + 8 registers are for the UART, the others are extra registers */ + if (info->manfid == MANFID_OXSEMI) { + if (cf->index == 1 || cf->index == 3) { + setup_serial(info, base2, link->irq.AssignedIRQ); + outb(12, link->io.BasePort1 + 1); + } else { + setup_serial(info, link->io.BasePort1, link->irq.AssignedIRQ); + outb(12, base2 + 1); + } + return 0; + } + setup_serial(info, link->io.BasePort1, link->irq.AssignedIRQ); /* The Nokia cards are not really multiport cards */ if (info->manfid == MANFID_NOKIA) @@ -548,7 +549,7 @@ void serial_config(dev_link_t * link) { client_handle_t handle = link->handle; - serial_info_t *info = link->priv; + struct serial_info *info = link->priv; tuple_t tuple; u_short buf[128]; cisparse_t parse; @@ -631,7 +632,8 @@ cs_failed: cs_error(link->handle, last_fn, last_ret); failed: - do_serial_release(info); + serial_remove(link); + link->state &= ~DEV_CONFIG_PENDING; } /*====================================================================== @@ -647,7 +649,7 @@ serial_event(event_t event, int priority, event_callback_args_t * args) { dev_link_t *link = args->client_data; - serial_info_t *info = link->priv; + struct serial_info *info = link->priv; DEBUG(1, "serial_event(0x%06x)\n", event); diff -Nru a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c --- a/drivers/serial/8250_pci.c Tue Jul 1 18:44:36 2003 +++ b/drivers/serial/8250_pci.c Tue Jul 1 18:44:36 2003 @@ -322,7 +322,7 @@ * hope) because it doesn't touch EEPROM settings to prevent conflicts * with other OSes (like M$ DOS). * - * SIIG support added by Andrey Panin , 10/1999 + * SIIG support added by Andrey Panin , 10/1999 * * There is two family of SIIG serial cards with different PCI * interface chip and different configuration methods: diff -Nru a/drivers/serial/Kconfig b/drivers/serial/Kconfig --- a/drivers/serial/Kconfig Tue Jul 1 18:44:38 2003 +++ b/drivers/serial/Kconfig Tue Jul 1 18:44:38 2003 @@ -80,14 +80,14 @@ config SERIAL_8250_ACPI bool "8250/16550 device discovery via ACPI namespace" default y if IA64 - depends on ACPI_BUS + depends on ACPI_BUS && SERIAL_8250 ---help--- If you wish to enable serial port discovery via the ACPI namespace, say Y here. If unsure, say N. config SERIAL_8250_HCDP bool "8250/16550 device discovery support via EFI HCDP table" - depends on IA64 + depends on IA64 && SERIAL_8250 ---help--- If you wish to make the serial console port described by the EFI HCDP table available for use as serial console or general @@ -326,6 +326,14 @@ This driver supports the Zilog8530 serial ports found on many Sparc systems. Say Y or M if you want to be able to these serial ports. +config SERIAL_SUNZILOG_CONSOLE + bool "Console on Sun Zilog8530 serial port" + depends on SERIAL_SUNZILOG=y + help + If you would like to be able to use the Zilog8530 serial port + on your Sparc system as the console, you can do so by answering + Y to this option. + config SERIAL_SUNSU tristate "Sun SU serial support" depends on (SPARC32 || SPARC64) && PCI @@ -334,6 +342,14 @@ mouse on (PCI) UltraSPARC systems. Say Y or M if you want to be able to these serial ports. +config SERIAL_SUNSU_CONSOLE + bool "Console on Sun SU serial port" + depends on SERIAL_SUNSU=y + help + If you would like to be able to use the SU serial port + on your Sparc system as the console, you can do so by answering + Y to this option. + config SERIAL_MUX tristate "Serial MUX support" depends on PARISC @@ -380,6 +396,14 @@ (PCI) UltraSPARC systems. Say Y or M if you want to be able to these serial ports. +config SERIAL_SUNSAB_CONSOLE + bool "Console on Sun Siemens SAB82532 serial port" + depends on SERIAL_SUNSAB=y + help + If you would like to be able to use the SAB82532 serial port + on your Sparc system as the console, you can do so by answering + Y to this option. + config V850E_NB85E_UART bool "NEC V850E on-chip UART support" depends on V850E_NB85E || V850E2_ANNA || V850E_AS85EP1 @@ -407,7 +431,7 @@ config SERIAL_CORE_CONSOLE bool - depends on SERIAL_AMBA_CONSOLE || SERIAL_CLPS711X_CONSOLE || SERIAL_21285_CONSOLE || SERIAL_SA1100_CONSOLE || SERIAL_ANAKIN_CONSOLE || SERIAL_UART00_CONSOLE || SERIAL_8250_CONSOLE || SERIAL_MUX_CONSOLE || SERIAL_SUNCORE || V850E_NB85E_UART_CONSOLE || SERIAL98_CONSOLE + depends on SERIAL_AMBA_CONSOLE || SERIAL_CLPS711X_CONSOLE || SERIAL_21285_CONSOLE || SERIAL_SA1100_CONSOLE || SERIAL_ANAKIN_CONSOLE || SERIAL_UART00_CONSOLE || SERIAL_8250_CONSOLE || SERIAL_MUX_CONSOLE || SERIAL_SUNZILOG_CONSOLE || SERIAL_SUNSU_CONSOLE || SERIAL_SUNSAB_CONSOLE || V850E_NB85E_UART_CONSOLE || SERIAL98_CONSOLE default y config SERIAL_68328 diff -Nru a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c --- a/drivers/serial/sunsab.c Tue Jul 1 18:44:34 2003 +++ b/drivers/serial/sunsab.c Tue Jul 1 18:44:34 2003 @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -38,6 +39,10 @@ #include #include +#if defined(CONFIG_SERIAL_SUNZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + #include #include "suncore.h" @@ -838,6 +843,8 @@ static struct uart_sunsab_port *sunsab_ports; static int num_channels; +#ifdef CONFIG_SERIAL_SUNSAB_CONSOLE + static __inline__ void sunsab_console_putchar(struct uart_sunsab_port *up, char c) { unsigned long flags; @@ -929,6 +936,7 @@ .index = -1, .data = &sunsab_reg, }; +#define SUNSAB_CONSOLE (&sunsab_console) static void __init sunsab_console_init(void) { @@ -949,6 +957,10 @@ sunsab_console.index = i; register_console(&sunsab_console); } +#else +#define SUNSAB_CONSOLE (NULL) +#define sunsab_console_init() do { } while (0) +#endif static void __init for_each_sab_edev(void (*callback)(struct linux_ebus_device *, void *), void *arg) { @@ -1091,7 +1103,7 @@ sunsab_reg.minor = sunserial_current_minor; sunsab_reg.nr = num_channels; - sunsab_reg.cons = &sunsab_console; + sunsab_reg.cons = SUNSAB_CONSOLE; ret = uart_register_driver(&sunsab_reg); if (ret < 0) { diff -Nru a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c --- a/drivers/serial/sunsu.c Tue Jul 1 18:44:33 2003 +++ b/drivers/serial/sunsu.c Tue Jul 1 18:44:33 2003 @@ -46,8 +46,7 @@ #include #endif -/* #if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) */ -#if defined(CONFIG_MAGIC_SYSRQ) +#if defined(CONFIG_SERIAL_SUNSU_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) #define SUPPORT_SYSRQ #endif @@ -1347,6 +1346,8 @@ * ------------------------------------------------------------ */ +#ifdef CONFIG_SERIAL_SUNSU_CONSOLE + #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) /* @@ -1465,6 +1466,7 @@ .index = -1, .data = &sunsu_reg, }; +#define SUNSU_CONSOLE (&sunsu_cons) /* * Register console. @@ -1492,6 +1494,10 @@ register_console(&sunsu_cons); return 0; } +#else +#define SUNSU_CONSOLE (NULL) +#define sunsu_serial_console_init() do { } while (0) +#endif static int __init sunsu_serial_init(void) { @@ -1522,7 +1528,7 @@ sunserial_current_minor += instance; sunsu_reg.nr = instance; - sunsu_reg.cons = &sunsu_cons; + sunsu_reg.cons = SUNSU_CONSOLE; ret = uart_register_driver(&sunsu_reg); if (ret < 0) diff -Nru a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c --- a/drivers/serial/sunzilog.c Tue Jul 1 18:44:39 2003 +++ b/drivers/serial/sunzilog.c Tue Jul 1 18:44:39 2003 @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #ifdef CONFIG_SERIO @@ -42,6 +43,10 @@ #endif #include +#if defined(CONFIG_SERIAL_SUNZILOG_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + #include #include "suncore.h" @@ -1331,6 +1336,7 @@ #endif /* CONFIG_SERIO */ +#ifdef CONFIG_SERIAL_SUNZILOG_CONSOLE static void sunzilog_console_write(struct console *con, const char *s, unsigned int count) { @@ -1400,6 +1406,7 @@ .index = -1, .data = &sunzilog_reg, }; +#define SUNZILOG_CONSOLE (&sunzilog_console) static int __init sunzilog_console_init(void) { @@ -1422,6 +1429,10 @@ register_console(&sunzilog_console); return 0; } +#else +#define SUNZILOG_CONSOLE (NULL) +#define sunzilog_console_init() do { } while (0) +#endif /* * We scan the PROM tree recursively. This is the most reliable way @@ -1639,7 +1650,7 @@ * in the system. */ sunzilog_reg.nr = NUM_CHANNELS; - sunzilog_reg.cons = &sunzilog_console; + sunzilog_reg.cons = SUNZILOG_CONSOLE; sunzilog_reg.minor = sunserial_current_minor; sunserial_current_minor += NUM_CHANNELS; diff -Nru a/drivers/sgi/Kconfig b/drivers/sgi/Kconfig --- a/drivers/sgi/Kconfig Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,57 +0,0 @@ -# -# Character device configuration -# - -menu "SGI devices" - depends on SGI_IP22 - -config SGI_SERIAL - bool "SGI Zilog85C30 serial support" - help - If you want to use your SGI's built-in serial ports under Linux, - answer Y. - -config SERIAL_CONSOLE - bool "Support for console on serial port" - depends on SGI_SERIAL - ---help--- - If you say Y here, it will be possible to use a serial port as the - system console (the system console is the device which receives all - kernel messages and warnings and which allows logins in single user - mode). This could be useful if some terminal or printer is connected - to that serial port. - - Even if you say Y here, the currently visible virtual console - (/dev/tty0) will still be used as the system console by default, but - you can alter that using a kernel command line option such as - "console=ttyS1". (Try "man bootparam" or see the documentation of - your boot loader (lilo or loadlin) about how to pass options to the - kernel at boot time.) - - If you don't have a VGA card installed and you say Y here, the - kernel will automatically use the first serial line, /dev/ttyS0, as - system console. - - If unsure, say N. - -config SGI_DS1286 - bool "SGI DS1286 RTC support" - help - If you say Y here and create a character special file /dev/rtc with - major number 10 and minor number 135 using mknod ("man mknod"), you - will get access to the real time clock built into your computer. - Every SGI has such a clock built in. It reports status information - via the file /proc/rtc and its behaviour is set by various ioctls on - /dev/rtc. - -config SGI_NEWPORT_GFX - tristate "SGI Newport Graphics support (EXPERIMENTAL)" - depends on EXPERIMENTAL - help - If you have an SGI machine and you want to compile the graphics - drivers, say Y here. This will include the code for the - /dev/graphics and /dev/gfx drivers into the kernel for supporting - virtualized access to your graphics hardware. - -endmenu - diff -Nru a/drivers/sgi/Makefile b/drivers/sgi/Makefile --- a/drivers/sgi/Makefile Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,10 +0,0 @@ -# -# Makefile for the linux kernel. -# - -# -# Character and Audio devices for SGI machines. -# -subdir-m += char - -obj-y += char/ diff -Nru a/drivers/sgi/char/Makefile b/drivers/sgi/char/Makefile --- a/drivers/sgi/char/Makefile Tue Jul 1 18:44:31 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,9 +0,0 @@ -# -# Makefile for the linux kernel. -# - -obj-y := newport.o shmiq.o sgicons.o usema.o streamable.o - -obj-$(CONFIG_SGI_SERIAL) += sgiserial.o -obj-$(CONFIG_SGI_DS1286) += ds1286.o -obj-$(CONFIG_SGI_NEWPORT_GFX) += graphics.o rrm.o diff -Nru a/drivers/sgi/char/ds1286.c b/drivers/sgi/char/ds1286.c --- a/drivers/sgi/char/ds1286.c Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,521 +0,0 @@ -/* - * DS1286 Real Time Clock interface for Linux - * - * Copyright (C) 1998, 1999, 2000 Ralf Baechle - * - * Based on code written by Paul Gortmaker. - * - * This driver allows use of the real time clock (built into nearly all - * computers) from user space. It exports the /dev/rtc interface supporting - * various ioctl() and also the /proc/rtc pseudo-file for status - * information. - * - * The ioctls can be used to set the interrupt behaviour and generation rate - * from the RTC via IRQ 8. Then the /dev/rtc interface can be used to make - * use of these timer interrupts, be they interval or alarm based. - * - * The /dev/rtc interface will block on reads until an interrupt has been - * received. If a RTC interrupt has already happened, it will output an - * unsigned long and then block. The output value contains the interrupt - * status in the low byte and the number of interrupts since the last read - * in the remaining high bytes. The /dev/rtc interface can also be used with - * the select(2) call. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#define DS1286_VERSION "1.0" - -/* - * We sponge a minor off of the misc major. No need slurping - * up another valuable major dev number for this. If you add - * an ioctl, make sure you don't conflict with SPARC's RTC - * ioctls. - */ - -static DECLARE_WAIT_QUEUE_HEAD(ds1286_wait); - -static ssize_t ds1286_read(struct file *file, char *buf, - size_t count, loff_t *ppos); - -static int ds1286_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg); - -static unsigned int ds1286_poll(struct file *file, poll_table *wait); - -void get_rtc_time (struct rtc_time *rtc_tm); -void get_rtc_alm_time (struct rtc_time *alm_tm); - -void set_rtc_irq_bit(unsigned char bit); -void clear_rtc_irq_bit(unsigned char bit); - -static inline unsigned char ds1286_is_updating(void); - -static spinlock_t ds1286_lock = SPIN_LOCK_UNLOCKED; - -/* - * Bits in rtc_status. (7 bits of room for future expansion) - */ - -#define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */ -#define RTC_TIMER_ON 0x02 /* missed irq timer active */ - -unsigned char ds1286_status; /* bitmapped status byte. */ -unsigned long ds1286_freq; /* Current periodic IRQ rate */ - -unsigned char days_in_mo[] = -{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; - -/* - * Now all the various file operations that we export. - */ - -static ssize_t ds1286_read(struct file *file, char *buf, - size_t count, loff_t *ppos) -{ - return -EIO; -} - -static int ds1286_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - - struct rtc_time wtime; - - switch (cmd) { - case RTC_AIE_OFF: /* Mask alarm int. enab. bit */ - { - unsigned int flags; - unsigned char val; - - if (!capable(CAP_SYS_TIME)) - return -EACCES; - - spin_lock_irqsave(&ds1286_lock, flags); - val = CMOS_READ(RTC_CMD); - val |= RTC_TDM; - CMOS_WRITE(val, RTC_CMD); - spin_unlock_irqrestore(&ds1286_lock, flags); - - return 0; - } - case RTC_AIE_ON: /* Allow alarm interrupts. */ - { - unsigned int flags; - unsigned char val; - - if (!capable(CAP_SYS_TIME)) - return -EACCES; - - spin_lock_irqsave(&ds1286_lock, flags); - val = CMOS_READ(RTC_CMD); - val &= ~RTC_TDM; - CMOS_WRITE(val, RTC_CMD); - spin_unlock_irqrestore(&ds1286_lock, flags); - - return 0; - } - case RTC_WIE_OFF: /* Mask watchdog int. enab. bit */ - { - unsigned int flags; - unsigned char val; - - if (!capable(CAP_SYS_TIME)) - return -EACCES; - - spin_lock_irqsave(&ds1286_lock, flags); - val = CMOS_READ(RTC_CMD); - val |= RTC_WAM; - CMOS_WRITE(val, RTC_CMD); - spin_unlock_irqrestore(&ds1286_lock, flags); - - return 0; - } - case RTC_WIE_ON: /* Allow watchdog interrupts. */ - { - unsigned int flags; - unsigned char val; - - if (!capable(CAP_SYS_TIME)) - return -EACCES; - - spin_lock_irqsave(&ds1286_lock, flags); - val = CMOS_READ(RTC_CMD); - val &= ~RTC_WAM; - CMOS_WRITE(val, RTC_CMD); - spin_unlock_irqrestore(&ds1286_lock, flags); - - return 0; - } - case RTC_ALM_READ: /* Read the present alarm time */ - { - /* - * This returns a struct rtc_time. Reading >= 0xc0 - * means "don't care" or "match all". Only the tm_hour, - * tm_min, and tm_sec values are filled in. - */ - - get_rtc_alm_time(&wtime); - break; - } - case RTC_ALM_SET: /* Store a time into the alarm */ - { - /* - * This expects a struct rtc_time. Writing 0xff means - * "don't care" or "match all". Only the tm_hour, - * tm_min and tm_sec are used. - */ - unsigned char hrs, min, sec; - struct rtc_time alm_tm; - - if (!capable(CAP_SYS_TIME)) - return -EACCES; - - if (copy_from_user(&alm_tm, (struct rtc_time*)arg, - sizeof(struct rtc_time))) - return -EFAULT; - - hrs = alm_tm.tm_hour; - min = alm_tm.tm_min; - - if (hrs >= 24) - hrs = 0xff; - - if (min >= 60) - min = 0xff; - - BIN_TO_BCD(sec); - BIN_TO_BCD(min); - BIN_TO_BCD(hrs); - - spin_lock(&ds1286_lock); - CMOS_WRITE(hrs, RTC_HOURS_ALARM); - CMOS_WRITE(min, RTC_MINUTES_ALARM); - spin_unlock(&ds1286_lock); - - return 0; - } - case RTC_RD_TIME: /* Read the time/date from RTC */ - { - get_rtc_time(&wtime); - break; - } - case RTC_SET_TIME: /* Set the RTC */ - { - struct rtc_time rtc_tm; - unsigned char mon, day, hrs, min, sec, leap_yr; - unsigned char save_control; - unsigned int yrs, flags; - - if (!capable(CAP_SYS_TIME)) - return -EACCES; - - if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, - sizeof(struct rtc_time))) - return -EFAULT; - - yrs = rtc_tm.tm_year + 1900; - mon = rtc_tm.tm_mon + 1; /* tm_mon starts at zero */ - day = rtc_tm.tm_mday; - hrs = rtc_tm.tm_hour; - min = rtc_tm.tm_min; - sec = rtc_tm.tm_sec; - - if (yrs < 1970) - return -EINVAL; - - leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400)); - - if ((mon > 12) || (day == 0)) - return -EINVAL; - - if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr))) - return -EINVAL; - - if ((hrs >= 24) || (min >= 60) || (sec >= 60)) - return -EINVAL; - - if ((yrs -= 1940) > 255) /* They are unsigned */ - return -EINVAL; - - if (yrs >= 100) - yrs -= 100; - - BIN_TO_BCD(sec); - BIN_TO_BCD(min); - BIN_TO_BCD(hrs); - BIN_TO_BCD(day); - BIN_TO_BCD(mon); - BIN_TO_BCD(yrs); - - spin_lock_irqsave(&ds1286_lock, flags); - save_control = CMOS_READ(RTC_CMD); - CMOS_WRITE((save_control|RTC_TE), RTC_CMD); - - CMOS_WRITE(yrs, RTC_YEAR); - CMOS_WRITE(mon, RTC_MONTH); - CMOS_WRITE(day, RTC_DATE); - CMOS_WRITE(hrs, RTC_HOURS); - CMOS_WRITE(min, RTC_MINUTES); - CMOS_WRITE(sec, RTC_SECONDS); - CMOS_WRITE(0, RTC_HUNDREDTH_SECOND); - - CMOS_WRITE(save_control, RTC_CMD); - spin_unlock_irqrestore(&ds1286_lock, flags); - - return 0; - } - default: - return -EINVAL; - } - return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0; -} - -/* - * We enforce only one user at a time here with the open/close. - * Also clear the previous interrupt data on an open, and clean - * up things on a close. - */ - -static int ds1286_open(struct inode *inode, struct file *file) -{ - spin_lock_irq(&ds1286_lock); - - if (ds1286_status & RTC_IS_OPEN) - goto out_busy; - - ds1286_status |= RTC_IS_OPEN; - - spin_lock_irq(&ds1286_lock); - return 0; - -out_busy: - spin_lock_irq(&ds1286_lock); - return -EBUSY; -} - -static int ds1286_release(struct inode *inode, struct file *file) -{ - ds1286_status &= ~RTC_IS_OPEN; - - return 0; -} - -static unsigned int ds1286_poll(struct file *file, poll_table *wait) -{ - poll_wait(file, &ds1286_wait, wait); - - return 0; -} - -/* - * The various file operations we support. - */ - -static struct file_operations ds1286_fops = { - .llseek = no_llseek, - .read = ds1286_read, - .poll = ds1286_poll, - .ioctl = ds1286_ioctl, - .open = ds1286_open, - .release = ds1286_release, -}; - -static struct miscdevice ds1286_dev= -{ - RTC_MINOR, - "rtc", - &ds1286_fops -}; - -int __init ds1286_init(void) -{ - printk(KERN_INFO "DS1286 Real Time Clock Driver v%s\n", DS1286_VERSION); - return misc_register(&ds1286_dev); -} - -static char *days[] = { - "***", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" -}; - -/* - * Info exported via "/proc/rtc". - */ -int get_ds1286_status(char *buf) -{ - char *p, *s; - struct rtc_time tm; - unsigned char hundredth, month, cmd, amode; - - p = buf; - - get_rtc_time(&tm); - hundredth = CMOS_READ(RTC_HUNDREDTH_SECOND); - BCD_TO_BIN(hundredth); - - p += sprintf(p, - "rtc_time\t: %02d:%02d:%02d.%02d\n" - "rtc_date\t: %04d-%02d-%02d\n", - tm.tm_hour, tm.tm_min, tm.tm_sec, hundredth, - tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); - - /* - * We implicitly assume 24hr mode here. Alarm values >= 0xc0 will - * match any value for that particular field. Values that are - * greater than a valid time, but less than 0xc0 shouldn't appear. - */ - get_rtc_alm_time(&tm); - p += sprintf(p, "alarm\t\t: %s ", days[tm.tm_wday]); - if (tm.tm_hour <= 24) - p += sprintf(p, "%02d:", tm.tm_hour); - else - p += sprintf(p, "**:"); - - if (tm.tm_min <= 59) - p += sprintf(p, "%02d\n", tm.tm_min); - else - p += sprintf(p, "**\n"); - - month = CMOS_READ(RTC_MONTH); - p += sprintf(p, - "oscillator\t: %s\n" - "square_wave\t: %s\n", - (month & RTC_EOSC) ? "disabled" : "enabled", - (month & RTC_ESQW) ? "disabled" : "enabled"); - - amode = ((CMOS_READ(RTC_MINUTES_ALARM) & 0x80) >> 5) | - ((CMOS_READ(RTC_HOURS_ALARM) & 0x80) >> 6) | - ((CMOS_READ(RTC_DAY_ALARM) & 0x80) >> 7); - if (amode == 7) s = "each minute"; - else if (amode == 3) s = "minutes match"; - else if (amode == 1) s = "hours and minutes match"; - else if (amode == 0) s = "days, hours and minutes match"; - else s = "invalid"; - p += sprintf(p, "alarm_mode\t: %s\n", s); - - cmd = CMOS_READ(RTC_CMD); - p += sprintf(p, - "alarm_enable\t: %s\n" - "wdog_alarm\t: %s\n" - "alarm_mask\t: %s\n" - "wdog_alarm_mask\t: %s\n" - "interrupt_mode\t: %s\n" - "INTB_mode\t: %s_active\n" - "interrupt_pins\t: %s\n", - (cmd & RTC_TDF) ? "yes" : "no", - (cmd & RTC_WAF) ? "yes" : "no", - (cmd & RTC_TDM) ? "disabled" : "enabled", - (cmd & RTC_WAM) ? "disabled" : "enabled", - (cmd & RTC_PU_LVL) ? "pulse" : "level", - (cmd & RTC_IBH_LO) ? "low" : "high", - (cmd & RTC_IPSW) ? "unswapped" : "swapped"); - - return p - buf; -} - -/* - * Returns true if a clock update is in progress - */ -static inline unsigned char ds1286_is_updating(void) -{ - return CMOS_READ(RTC_CMD) & RTC_TE; -} - -void get_rtc_time(struct rtc_time *rtc_tm) -{ - unsigned long uip_watchdog = jiffies; - unsigned char save_control; - unsigned int flags; - - /* - * read RTC once any update in progress is done. The update - * can take just over 2ms. We wait 10 to 20ms. There is no need to - * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP. - * If you need to know *exactly* when a second has started, enable - * periodic update complete interrupts, (via ioctl) and then - * immediately read /dev/rtc which will block until you get the IRQ. - * Once the read clears, read the RTC time (again via ioctl). Easy. - */ - - if (ds1286_is_updating() != 0) - while (jiffies - uip_watchdog < 2*HZ/100) - barrier(); - - /* - * Only the values that we read from the RTC are set. We leave - * tm_wday, tm_yday and tm_isdst untouched. Even though the - * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated - * by the RTC when initially set to a non-zero value. - */ - spin_lock_irqsave(&ds1286_lock, flags); - save_control = CMOS_READ(RTC_CMD); - CMOS_WRITE((save_control|RTC_TE), RTC_CMD); - - rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS); - rtc_tm->tm_min = CMOS_READ(RTC_MINUTES); - rtc_tm->tm_hour = CMOS_READ(RTC_HOURS) & 0x1f; - rtc_tm->tm_mday = CMOS_READ(RTC_DATE); - rtc_tm->tm_mon = CMOS_READ(RTC_MONTH) & 0x1f; - rtc_tm->tm_year = CMOS_READ(RTC_YEAR); - - CMOS_WRITE(save_control, RTC_CMD); - spin_unlock_irqrestore(&ds1286_lock, flags); - - BCD_TO_BIN(rtc_tm->tm_sec); - BCD_TO_BIN(rtc_tm->tm_min); - BCD_TO_BIN(rtc_tm->tm_hour); - BCD_TO_BIN(rtc_tm->tm_mday); - BCD_TO_BIN(rtc_tm->tm_mon); - BCD_TO_BIN(rtc_tm->tm_year); - - /* - * Account for differences between how the RTC uses the values - * and how they are defined in a struct rtc_time; - */ - if (rtc_tm->tm_year < 45) - rtc_tm->tm_year += 30; - if ((rtc_tm->tm_year += 40) < 70) - rtc_tm->tm_year += 100; - - rtc_tm->tm_mon--; -} - -void get_rtc_alm_time(struct rtc_time *alm_tm) -{ - unsigned char cmd; - unsigned int flags; - - /* - * Only the values that we read from the RTC are set. That - * means only tm_wday, tm_hour, tm_min. - */ - spin_lock_irqsave(&ds1286_lock, flags); - alm_tm->tm_min = CMOS_READ(RTC_MINUTES_ALARM) & 0x7f; - alm_tm->tm_hour = CMOS_READ(RTC_HOURS_ALARM) & 0x1f; - alm_tm->tm_wday = CMOS_READ(RTC_DAY_ALARM) & 0x07; - cmd = CMOS_READ(RTC_CMD); - spin_unlock_irqrestore(&ds1286_lock, flags); - - BCD_TO_BIN(alm_tm->tm_min); - BCD_TO_BIN(alm_tm->tm_hour); - alm_tm->tm_sec = 0; -} diff -Nru a/drivers/sgi/char/gconsole.h b/drivers/sgi/char/gconsole.h --- a/drivers/sgi/char/gconsole.h Tue Jul 1 18:44:34 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,33 +0,0 @@ -/* - * This is a temporary measure, we should eventually migrate to - * Gert's generic graphic console code. - */ - -#define cmapsz 8192 -#define CHAR_HEIGHT 16 - -struct console_ops { - void (*set_origin)(unsigned short offset); - void (*hide_cursor)(void); - void (*set_cursor)(int currcons); - void (*get_scrmem)(int currcons); - void (*set_scrmem)(int currcons, long offset); - int (*set_get_cmap)(unsigned char *arg, int set); - void (*blitc)(unsigned short charattr, unsigned long addr); - void (*memsetw)(void *s, unsigned short c, unsigned int count); - void (*memcpyw)(unsigned short *to, unsigned short *from, unsigned int count); -}; - -void register_gconsole (struct console_ops *); - -/* This points to the system console */ -extern struct console_ops *gconsole; - -extern void gfx_init (const char **name); - -extern void __set_origin (unsigned short offset); -extern void hide_cursor (void); -extern unsigned char vga_font[]; - -extern void disable_gconsole (void); -extern void enable_gconsole (void); diff -Nru a/drivers/sgi/char/graphics.c b/drivers/sgi/char/graphics.c --- a/drivers/sgi/char/graphics.c Tue Jul 1 18:44:35 2003 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,377 +0,0 @@ -/* - * gfx.c: support for SGI's /dev/graphics, /dev/opengl - * - * Author: Miguel de Icaza (miguel@nuclecu.unam.mx) - * Ralf Baechle (ralf@gnu.org) - * Ulf Carlsson (ulfc@bun.falkenberg.se) - * - * On IRIX, /dev/graphics is [10, 146] - * /dev/opengl is [10, 147] - * - * From a mail with Mark J. Kilgard, /dev/opengl and /dev/graphics are - * the same thing, the use of /dev/graphics seems deprecated though. - * - * The reason that the original SGI programmer had to use only one - * device for all the graphic cards on the system will remain a - * mistery for the rest of our lives. Why some ioctls take a board - * number and some others not? Mistery. Why do they map the hardware - * registers into the user address space with an ioctl instead of - * mmap? Mistery too. Why they did not use the standard way of - * making ioctl constants and instead sticked a random constant? - * Mistery too. - * - * We implement those misterious things, and tried not to think about - * the reasons behind them. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "gconsole.h" -#include "graphics.h" -#include "usema.h" -#include -#include -#include -#include -#include